feat(settings): add third-party integrations dashboard

Add a Settings → Integrations page for installing and managing the three
supported OpenCode provider plugins (Claude Code, Command Code, Cursor),
with search, i18n, and plugin-registry status wiring.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
This commit is contained in:
Serhii Dziupin
2026-08-14 15:19:25 +00:00
committed by Cursor Agent
co-authored by Serhii Dziupin
parent 3f266232f9
commit af380081c2
33 changed files with 1562 additions and 7 deletions
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go Nutzungsverfolgung',
'settings.providers.page.openCodeGo.description': 'Verbinden Sie das OpenCode Go Dashboard, um rollierenden, wöchentlichen und monatlichen Verbrauch anzuzeigen.',
@@ -2124,4 +2125,5 @@ export const settingsDict = {
'settings.openchamber.visual.option.themeMode.light.description': 'Immer helles Erscheinungsbild verwenden',
'settings.openchamber.visual.option.themeMode.dark.description': 'Immer dunkles Erscheinungsbild verwenden',
'chat.message.userText.collapseAria': 'Benutzernachricht einklappen',
...thirdPartyIntegrationI18n.de,
};
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go usage tracking',
'settings.providers.page.openCodeGo.description': 'Connect the OpenCode Go dashboard to show rolling, weekly, and monthly quota.',
@@ -2123,4 +2124,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n.en,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Seguimiento de uso de OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Conecta el panel de OpenCode Go para ver las cuotas móvil, semanal y mensual.',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
"settings.openchamber.visual.field.followUpBehaviorDescription": "Choose what happens when you press Enter on a follow-up message while the agent is still responding.",
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...thirdPartyIntegrationI18n.es,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Suivi de l’utilisation d’OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Connectez le tableau de bord OpenCode Go pour afficher les quotas glissant, hebdomadaire et mensuel.',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n.fr,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 使用量追跡',
'settings.providers.page.openCodeGo.description': 'OpenCode Go ダッシュボードを接続して、ローリング、週間、月間のクォータを表示します。',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'エージェントが応答している間にフォローアップメッセージで Enter を押したときの動作を選択します。',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'ステア',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'キュー',
...thirdPartyIntegrationI18n.ja,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 사용량 추적',
'settings.providers.page.openCodeGo.description': 'OpenCode Go 대시보드를 연결하여 롤링, 주간 및 월간 할당량을 표시합니다.',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n.ko,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Śledzenie użycia OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Połącz panel OpenCode Go, aby wyświetlać limity kroczące, tygodniowe i miesięczne.',
@@ -2125,4 +2126,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n.pl,
};
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Monitoramento de uso do OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Conecte o painel do OpenCode Go para exibir as cotas móvel, semanal e mensal.',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
"settings.openchamber.visual.field.followUpBehaviorDescription": "Choose what happens when you press Enter on a follow-up message while the agent is still responding.",
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...thirdPartyIntegrationI18n['pt-BR'],
} as const;
@@ -0,0 +1,28 @@
import { describe, expect, test } from 'bun:test';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
const locales = ['en', 'de', 'fr', 'es', 'ja', 'pt-BR', 'uk', 'ko', 'pl', 'zh-CN', 'zh-TW'] as const;
const requiredKeys = [
'settings.page.integrations.title',
'settings.page.integrations.description',
'settings.integrations.thirdParty.title',
'settings.integrations.thirdParty.actions.install',
'settings.integrations.thirdParty.actions.update',
'settings.integrations.thirdParty.actions.setup',
'settings.integrations.thirdParty.actions.remove',
'settings.integrations.thirdParty.status.notInstalled',
'settings.integrations.thirdParty.opencodeClaude.description',
'settings.integrations.thirdParty.opencodeCommandcode.description',
'settings.integrations.thirdParty.opencodeCursorOauth.description',
] as const;
describe('third-party integration translations', () => {
test('provides every required key in every supported locale', () => {
for (const locale of locales) {
for (const key of requiredKeys) {
expect(thirdPartyIntegrationI18n[locale][key]).toBeTruthy();
}
}
});
});
@@ -0,0 +1,399 @@
/** Third-party integration settings strings — merged into each locale's settings dictionary. */
export const thirdPartyIntegrationI18n = {
en: {
'settings.page.integrations.title': 'Integrations',
'settings.page.integrations.description': 'Connect third-party providers to OpenCode.',
'settings.integrations.thirdParty.title': 'Third-party integrations',
'settings.integrations.thirdParty.info': 'Install and manage supported OpenCode provider plugins. Setup opens the provider’s existing authentication settings.',
'settings.integrations.thirdParty.actions.install': 'Install',
'settings.integrations.thirdParty.actions.update': 'Update',
'settings.integrations.thirdParty.actions.setup': 'Set up',
'settings.integrations.thirdParty.actions.remove': 'Remove',
'settings.integrations.thirdParty.actions.refresh': 'Refresh',
'settings.integrations.thirdParty.actions.docs': 'Docs',
'settings.integrations.thirdParty.actions.managePlugins': 'Manage plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Not installed',
'settings.integrations.thirdParty.status.installed': 'Installed',
'settings.integrations.thirdParty.status.installedVersion': 'Installed {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Update available: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Following the latest release',
'settings.integrations.thirdParty.status.projectInstalled': 'Also configured for this project',
'settings.integrations.thirdParty.status.ambiguous': 'Multiple user-wide plugin entries need manual management',
'settings.integrations.thirdParty.status.restartRequired': 'Restart OpenCode before setting up this provider.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Could not check npm right now.',
'settings.integrations.thirdParty.status.providerUnavailable': 'The provider is not available yet. Restart OpenCode and try again.',
'settings.integrations.thirdParty.dialog.remove.title': 'Remove integration',
'settings.integrations.thirdParty.dialog.remove.description': 'Remove {name} from your user-wide OpenCode configuration? The provider will no longer load after OpenCode refreshes.',
'settings.integrations.thirdParty.toast.installed': '{name} installed',
'settings.integrations.thirdParty.toast.updated': '{name} updated',
'settings.integrations.thirdParty.toast.removed': '{name} removed',
'settings.integrations.thirdParty.toast.actionFailed': 'Could not update the integration',
'settings.integrations.thirdParty.toast.providerUnavailable': 'The provider could not be opened yet',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use a Claude Pro or Max subscription through OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Use Command Code’s Laguna S 2.1 model through OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Use your Cursor subscription through OpenCode.',
},
de: {
'settings.page.integrations.title': 'Integrationen',
'settings.page.integrations.description': 'Verbinde Drittanbieter-Provider mit OpenCode.',
'settings.integrations.thirdParty.title': 'Drittanbieter-Integrationen',
'settings.integrations.thirdParty.info': 'Installiere und verwalte unterstützte OpenCode-Provider-Plugins. Die Einrichtung öffnet die bestehenden Authentifizierungseinstellungen des Providers.',
'settings.integrations.thirdParty.actions.install': 'Installieren',
'settings.integrations.thirdParty.actions.update': 'Aktualisieren',
'settings.integrations.thirdParty.actions.setup': 'Einrichten',
'settings.integrations.thirdParty.actions.remove': 'Entfernen',
'settings.integrations.thirdParty.actions.refresh': 'Aktualisieren',
'settings.integrations.thirdParty.actions.docs': 'Dokumentation',
'settings.integrations.thirdParty.actions.managePlugins': 'Plugins verwalten',
'settings.integrations.thirdParty.status.notInstalled': 'Nicht installiert',
'settings.integrations.thirdParty.status.installed': 'Installiert',
'settings.integrations.thirdParty.status.installedVersion': '{version} installiert',
'settings.integrations.thirdParty.status.updateAvailable': 'Aktualisierung verfügbar: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Folgt der neuesten Version',
'settings.integrations.thirdParty.status.projectInstalled': 'Auch für dieses Projekt konfiguriert',
'settings.integrations.thirdParty.status.ambiguous': 'Mehrere benutzerweite Plugin-Einträge müssen manuell verwaltet werden',
'settings.integrations.thirdParty.status.restartRequired': 'Starte OpenCode neu, bevor du diesen Provider einrichtest.',
'settings.integrations.thirdParty.status.registryUnavailable': 'npm konnte gerade nicht geprüft werden.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Der Provider ist noch nicht verfügbar. Starte OpenCode neu und versuche es erneut.',
'settings.integrations.thirdParty.dialog.remove.title': 'Integration entfernen',
'settings.integrations.thirdParty.dialog.remove.description': '{name} aus deiner benutzerweiten OpenCode-Konfiguration entfernen? Der Provider wird nach der Aktualisierung von OpenCode nicht mehr geladen.',
'settings.integrations.thirdParty.toast.installed': '{name} installiert',
'settings.integrations.thirdParty.toast.updated': '{name} aktualisiert',
'settings.integrations.thirdParty.toast.removed': '{name} entfernt',
'settings.integrations.thirdParty.toast.actionFailed': 'Die Integration konnte nicht aktualisiert werden',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Der Provider konnte noch nicht geöffnet werden',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Nutze ein Claude-Pro- oder -Max-Abonnement über OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Nutze das Laguna-S-2.1-Modell von Command Code über OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Nutze dein Cursor-Abonnement über OpenCode.',
},
fr: {
'settings.page.integrations.title': 'Intégrations',
'settings.page.integrations.description': 'Connectez des fournisseurs tiers à OpenCode.',
'settings.integrations.thirdParty.title': 'Intégrations tierces',
'settings.integrations.thirdParty.info': 'Installez et gérez les plugins de fournisseurs OpenCode pris en charge. La configuration ouvre les réglages d’authentification existants du fournisseur.',
'settings.integrations.thirdParty.actions.install': 'Installer',
'settings.integrations.thirdParty.actions.update': 'Mettre à jour',
'settings.integrations.thirdParty.actions.setup': 'Configurer',
'settings.integrations.thirdParty.actions.remove': 'Supprimer',
'settings.integrations.thirdParty.actions.refresh': 'Actualiser',
'settings.integrations.thirdParty.actions.docs': 'Documentation',
'settings.integrations.thirdParty.actions.managePlugins': 'Gérer les plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Non installé',
'settings.integrations.thirdParty.status.installed': 'Installé',
'settings.integrations.thirdParty.status.installedVersion': '{version} installé',
'settings.integrations.thirdParty.status.updateAvailable': 'Mise à jour disponible : {version}',
'settings.integrations.thirdParty.status.unpinned': 'Suit la dernière version',
'settings.integrations.thirdParty.status.projectInstalled': 'Également configuré pour ce projet',
'settings.integrations.thirdParty.status.ambiguous': 'Plusieurs entrées de plugin globales doivent être gérées manuellement',
'settings.integrations.thirdParty.status.restartRequired': 'Redémarrez OpenCode avant de configurer ce fournisseur.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Impossible de vérifier npm pour le moment.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Le fournisseur n’est pas encore disponible. Redémarrez OpenCode et réessayez.',
'settings.integrations.thirdParty.dialog.remove.title': 'Supprimer l’intégration',
'settings.integrations.thirdParty.dialog.remove.description': 'Supprimer {name} de votre configuration OpenCode globale ? Le fournisseur ne sera plus chargé après l’actualisation d’OpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} installé',
'settings.integrations.thirdParty.toast.updated': '{name} mis à jour',
'settings.integrations.thirdParty.toast.removed': '{name} supprimé',
'settings.integrations.thirdParty.toast.actionFailed': 'Impossible de mettre à jour l’intégration',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Le fournisseur n’a pas encore pu être ouvert',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Utilisez un abonnement Claude Pro ou Max via OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Utilisez le modèle Laguna S 2.1 de Command Code via OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Utilisez votre abonnement Cursor via OpenCode.',
},
es: {
'settings.page.integrations.title': 'Integraciones',
'settings.page.integrations.description': 'Conecta proveedores de terceros a OpenCode.',
'settings.integrations.thirdParty.title': 'Integraciones de terceros',
'settings.integrations.thirdParty.info': 'Instala y administra los plugins de proveedores OpenCode compatibles. La configuración abre los ajustes de autenticación existentes del proveedor.',
'settings.integrations.thirdParty.actions.install': 'Instalar',
'settings.integrations.thirdParty.actions.update': 'Actualizar',
'settings.integrations.thirdParty.actions.setup': 'Configurar',
'settings.integrations.thirdParty.actions.remove': 'Quitar',
'settings.integrations.thirdParty.actions.refresh': 'Actualizar',
'settings.integrations.thirdParty.actions.docs': 'Documentación',
'settings.integrations.thirdParty.actions.managePlugins': 'Administrar plugins',
'settings.integrations.thirdParty.status.notInstalled': 'No instalado',
'settings.integrations.thirdParty.status.installed': 'Instalado',
'settings.integrations.thirdParty.status.installedVersion': '{version} instalado',
'settings.integrations.thirdParty.status.updateAvailable': 'Actualización disponible: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Sigue la versión más reciente',
'settings.integrations.thirdParty.status.projectInstalled': 'También configurado para este proyecto',
'settings.integrations.thirdParty.status.ambiguous': 'Hay varias entradas de plugin globales que requieren gestión manual',
'settings.integrations.thirdParty.status.restartRequired': 'Reinicia OpenCode antes de configurar este proveedor.',
'settings.integrations.thirdParty.status.registryUnavailable': 'No se pudo comprobar npm ahora mismo.',
'settings.integrations.thirdParty.status.providerUnavailable': 'El proveedor todavía no está disponible. Reinicia OpenCode e inténtalo de nuevo.',
'settings.integrations.thirdParty.dialog.remove.title': 'Quitar integración',
'settings.integrations.thirdParty.dialog.remove.description': '¿Quitar {name} de tu configuración global de OpenCode? El proveedor dejará de cargarse después de actualizar OpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} instalado',
'settings.integrations.thirdParty.toast.updated': '{name} actualizado',
'settings.integrations.thirdParty.toast.removed': '{name} eliminado',
'settings.integrations.thirdParty.toast.actionFailed': 'No se pudo actualizar la integración',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Todavía no se pudo abrir el proveedor',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Usa una suscripción Claude Pro o Max mediante OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Usa el modelo Laguna S 2.1 de Command Code mediante OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Usa tu suscripción de Cursor mediante OpenCode.',
},
ja: {
'settings.page.integrations.title': '連携',
'settings.page.integrations.description': 'サードパーティープロバイダーを OpenCode に接続します。',
'settings.integrations.thirdParty.title': 'サードパーティー連携',
'settings.integrations.thirdParty.info': '対応する OpenCode プロバイダープラグインをインストールして管理します。設定ではプロバイダーの既存の認証設定を開きます。',
'settings.integrations.thirdParty.actions.install': 'インストール',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '設定',
'settings.integrations.thirdParty.actions.remove': '削除',
'settings.integrations.thirdParty.actions.refresh': '再読み込み',
'settings.integrations.thirdParty.actions.docs': 'ドキュメント',
'settings.integrations.thirdParty.actions.managePlugins': 'プラグインを管理',
'settings.integrations.thirdParty.status.notInstalled': '未インストール',
'settings.integrations.thirdParty.status.installed': 'インストール済み',
'settings.integrations.thirdParty.status.installedVersion': '{version} をインストール済み',
'settings.integrations.thirdParty.status.updateAvailable': '更新があります: {version}',
'settings.integrations.thirdParty.status.unpinned': '最新リリースを追跡中',
'settings.integrations.thirdParty.status.projectInstalled': 'このプロジェクトにも設定済み',
'settings.integrations.thirdParty.status.ambiguous': '複数のユーザー全体プラグインエントリーは手動で管理する必要があります',
'settings.integrations.thirdParty.status.restartRequired': 'このプロバイダーを設定する前に OpenCode を再起動してください。',
'settings.integrations.thirdParty.status.registryUnavailable': '現在 npm を確認できません。',
'settings.integrations.thirdParty.status.providerUnavailable': 'プロバイダーはまだ利用できません。OpenCode を再起動して再試行してください。',
'settings.integrations.thirdParty.dialog.remove.title': '連携を削除',
'settings.integrations.thirdParty.dialog.remove.description': '{name} をユーザー全体の OpenCode 設定から削除しますか?OpenCode の更新後、このプロバイダーは読み込まれなくなります。',
'settings.integrations.thirdParty.toast.installed': '{name} をインストールしました',
'settings.integrations.thirdParty.toast.updated': '{name} を更新しました',
'settings.integrations.thirdParty.toast.removed': '{name} を削除しました',
'settings.integrations.thirdParty.toast.actionFailed': '連携を更新できませんでした',
'settings.integrations.thirdParty.toast.providerUnavailable': 'プロバイダーをまだ開けませんでした',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro または Max のサブスクリプションを OpenCode 経由で利用します。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Command Code の Laguna S 2.1 モデルを OpenCode 経由で利用します。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor のサブスクリプションを OpenCode 経由で利用します。',
},
ko: {
'settings.page.integrations.title': '통합',
'settings.page.integrations.description': '서드파티 프로바이더를 OpenCode에 연결합니다.',
'settings.integrations.thirdParty.title': '서드파티 통합',
'settings.integrations.thirdParty.info': '지원되는 OpenCode 프로바이더 플러그인을 설치하고 관리합니다. 설정을 누르면 프로바이더의 기존 인증 설정이 열립니다.',
'settings.integrations.thirdParty.actions.install': '설치',
'settings.integrations.thirdParty.actions.update': '업데이트',
'settings.integrations.thirdParty.actions.setup': '설정',
'settings.integrations.thirdParty.actions.remove': '제거',
'settings.integrations.thirdParty.actions.refresh': '새로 고침',
'settings.integrations.thirdParty.actions.docs': '문서',
'settings.integrations.thirdParty.actions.managePlugins': '플러그인 관리',
'settings.integrations.thirdParty.status.notInstalled': '설치되지 않음',
'settings.integrations.thirdParty.status.installed': '설치됨',
'settings.integrations.thirdParty.status.installedVersion': '{version} 설치됨',
'settings.integrations.thirdParty.status.updateAvailable': '업데이트 가능: {version}',
'settings.integrations.thirdParty.status.unpinned': '최신 릴리스 추적 중',
'settings.integrations.thirdParty.status.projectInstalled': '이 프로젝트에도 구성됨',
'settings.integrations.thirdParty.status.ambiguous': '여러 사용자 전체 플러그인 항목은 수동으로 관리해야 합니다',
'settings.integrations.thirdParty.status.restartRequired': '이 프로바이더를 설정하기 전에 OpenCode를 다시 시작하세요.',
'settings.integrations.thirdParty.status.registryUnavailable': '지금은 npm을 확인할 수 없습니다.',
'settings.integrations.thirdParty.status.providerUnavailable': '프로바이더를 아직 사용할 수 없습니다. OpenCode를 다시 시작한 후 재시도하세요.',
'settings.integrations.thirdParty.dialog.remove.title': '통합 제거',
'settings.integrations.thirdParty.dialog.remove.description': '사용자 전체 OpenCode 구성에서 {name}을(를) 제거할까요? OpenCode가 새로 고쳐진 후 프로바이더가 더 이상 로드되지 않습니다.',
'settings.integrations.thirdParty.toast.installed': '{name} 설치됨',
'settings.integrations.thirdParty.toast.updated': '{name} 업데이트됨',
'settings.integrations.thirdParty.toast.removed': '{name} 제거됨',
'settings.integrations.thirdParty.toast.actionFailed': '통합을 업데이트하지 못했습니다',
'settings.integrations.thirdParty.toast.providerUnavailable': '프로바이더를 아직 열 수 없습니다',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'OpenCode를 통해 Claude Pro 또는 Max 구독을 사용합니다.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'OpenCode를 통해 Command Code의 Laguna S 2.1 모델을 사용합니다.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'OpenCode를 통해 Cursor 구독을 사용합니다.',
},
pl: {
'settings.page.integrations.title': 'Integracje',
'settings.page.integrations.description': 'Połącz zewnętrznych dostawców z OpenCode.',
'settings.integrations.thirdParty.title': 'Integracje zewnętrzne',
'settings.integrations.thirdParty.info': 'Instaluj i zarządzaj obsługiwanymi wtyczkami dostawców OpenCode. Konfiguracja otwiera istniejące ustawienia uwierzytelniania dostawcy.',
'settings.integrations.thirdParty.actions.install': 'Zainstaluj',
'settings.integrations.thirdParty.actions.update': 'Aktualizuj',
'settings.integrations.thirdParty.actions.setup': 'Skonfiguruj',
'settings.integrations.thirdParty.actions.remove': 'Usuń',
'settings.integrations.thirdParty.actions.refresh': 'Odśwież',
'settings.integrations.thirdParty.actions.docs': 'Dokumentacja',
'settings.integrations.thirdParty.actions.managePlugins': 'Zarządzaj wtyczkami',
'settings.integrations.thirdParty.status.notInstalled': 'Nie zainstalowano',
'settings.integrations.thirdParty.status.installed': 'Zainstalowano',
'settings.integrations.thirdParty.status.installedVersion': 'Zainstalowano {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Dostępna aktualizacja: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Śledzi najnowsze wydanie',
'settings.integrations.thirdParty.status.projectInstalled': 'Skonfigurowano także dla tego projektu',
'settings.integrations.thirdParty.status.ambiguous': 'Wiele globalnych wpisów wtyczki wymaga ręcznego zarządzania',
'settings.integrations.thirdParty.status.restartRequired': 'Uruchom ponownie OpenCode przed konfiguracją tego dostawcy.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Nie można teraz sprawdzić npm.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Dostawca nie jest jeszcze dostępny. Uruchom ponownie OpenCode i spróbuj ponownie.',
'settings.integrations.thirdParty.dialog.remove.title': 'Usuń integrację',
'settings.integrations.thirdParty.dialog.remove.description': 'Usunąć {name} z globalnej konfiguracji OpenCode? Dostawca przestanie być ładowany po odświeżeniu OpenCode.',
'settings.integrations.thirdParty.toast.installed': 'Zainstalowano {name}',
'settings.integrations.thirdParty.toast.updated': 'Zaktualizowano {name}',
'settings.integrations.thirdParty.toast.removed': 'Usunięto {name}',
'settings.integrations.thirdParty.toast.actionFailed': 'Nie udało się zaktualizować integracji',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Nie można jeszcze otworzyć dostawcy',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Korzystaj z subskrypcji Claude Pro lub Max przez OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Korzystaj z modelu Laguna S 2.1 od Command Code przez OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Korzystaj z subskrypcji Cursor przez OpenCode.',
},
'pt-BR': {
'settings.page.integrations.title': 'Integrações',
'settings.page.integrations.description': 'Conecte provedores de terceiros ao OpenCode.',
'settings.integrations.thirdParty.title': 'Integrações de terceiros',
'settings.integrations.thirdParty.info': 'Instale e gerencie plugins compatíveis de provedores do OpenCode. A configuração abre as definições de autenticação existentes do provedor.',
'settings.integrations.thirdParty.actions.install': 'Instalar',
'settings.integrations.thirdParty.actions.update': 'Atualizar',
'settings.integrations.thirdParty.actions.setup': 'Configurar',
'settings.integrations.thirdParty.actions.remove': 'Remover',
'settings.integrations.thirdParty.actions.refresh': 'Atualizar',
'settings.integrations.thirdParty.actions.docs': 'Documentação',
'settings.integrations.thirdParty.actions.managePlugins': 'Gerenciar plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Não instalado',
'settings.integrations.thirdParty.status.installed': 'Instalado',
'settings.integrations.thirdParty.status.installedVersion': '{version} instalado',
'settings.integrations.thirdParty.status.updateAvailable': 'Atualização disponível: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Acompanha a versão mais recente',
'settings.integrations.thirdParty.status.projectInstalled': 'Também configurado para este projeto',
'settings.integrations.thirdParty.status.ambiguous': 'Várias entradas de plugin globais precisam de gerenciamento manual',
'settings.integrations.thirdParty.status.restartRequired': 'Reinicie o OpenCode antes de configurar este provedor.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Não foi possível verificar o npm agora.',
'settings.integrations.thirdParty.status.providerUnavailable': 'O provedor ainda não está disponível. Reinicie o OpenCode e tente novamente.',
'settings.integrations.thirdParty.dialog.remove.title': 'Remover integração',
'settings.integrations.thirdParty.dialog.remove.description': 'Remover {name} da sua configuração global do OpenCode? O provedor deixará de ser carregado após a atualização do OpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} instalado',
'settings.integrations.thirdParty.toast.updated': '{name} atualizado',
'settings.integrations.thirdParty.toast.removed': '{name} removido',
'settings.integrations.thirdParty.toast.actionFailed': 'Não foi possível atualizar a integração',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Ainda não foi possível abrir o provedor',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use uma assinatura Claude Pro ou Max pelo OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Use o modelo Laguna S 2.1 do Command Code pelo OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Use sua assinatura Cursor pelo OpenCode.',
},
uk: {
'settings.page.integrations.title': 'Інтеграції',
'settings.page.integrations.description': 'Підключайте сторонніх провайдерів до OpenCode.',
'settings.integrations.thirdParty.title': 'Сторонні інтеграції',
'settings.integrations.thirdParty.info': 'Встановлюйте й керуйте підтримуваними плагінами провайдерів OpenCode. Налаштування відкриває наявні параметри автентифікації провайдера.',
'settings.integrations.thirdParty.actions.install': 'Встановити',
'settings.integrations.thirdParty.actions.update': 'Оновити',
'settings.integrations.thirdParty.actions.setup': 'Налаштувати',
'settings.integrations.thirdParty.actions.remove': 'Видалити',
'settings.integrations.thirdParty.actions.refresh': 'Оновити',
'settings.integrations.thirdParty.actions.docs': 'Документація',
'settings.integrations.thirdParty.actions.managePlugins': 'Керувати плагінами',
'settings.integrations.thirdParty.status.notInstalled': 'Не встановлено',
'settings.integrations.thirdParty.status.installed': 'Встановлено',
'settings.integrations.thirdParty.status.installedVersion': 'Встановлено {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Доступне оновлення: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Відстежує найновіший випуск',
'settings.integrations.thirdParty.status.projectInstalled': 'Також налаштовано для цього проєкту',
'settings.integrations.thirdParty.status.ambiguous': 'Кілька глобальних записів плагіна потребують ручного керування',
'settings.integrations.thirdParty.status.restartRequired': 'Перезапустіть OpenCode перед налаштуванням цього провайдера.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Зараз не вдалося перевірити npm.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Провайдер ще недоступний. Перезапустіть OpenCode й спробуйте знову.',
'settings.integrations.thirdParty.dialog.remove.title': 'Видалити інтеграцію',
'settings.integrations.thirdParty.dialog.remove.description': 'Видалити {name} з вашої глобальної конфігурації OpenCode? Після оновлення OpenCode провайдер більше не завантажуватиметься.',
'settings.integrations.thirdParty.toast.installed': '{name} встановлено',
'settings.integrations.thirdParty.toast.updated': '{name} оновлено',
'settings.integrations.thirdParty.toast.removed': '{name} видалено',
'settings.integrations.thirdParty.toast.actionFailed': 'Не вдалося оновити інтеграцію',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Провайдера ще не вдалося відкрити',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Використовуйте підписку Claude Pro або Max через OpenCode.',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': 'Використовуйте модель Laguna S 2.1 від Command Code через OpenCode.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Використовуйте свою підписку Cursor через OpenCode.',
},
'zh-CN': {
'settings.page.integrations.title': '集成',
'settings.page.integrations.description': '将第三方提供商连接到 OpenCode。',
'settings.integrations.thirdParty.title': '第三方集成',
'settings.integrations.thirdParty.info': '安装和管理受支持的 OpenCode 提供商插件。设置会打开该提供商已有的身份验证设置。',
'settings.integrations.thirdParty.actions.install': '安装',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '设置',
'settings.integrations.thirdParty.actions.remove': '移除',
'settings.integrations.thirdParty.actions.refresh': '刷新',
'settings.integrations.thirdParty.actions.docs': '文档',
'settings.integrations.thirdParty.actions.managePlugins': '管理插件',
'settings.integrations.thirdParty.status.notInstalled': '未安装',
'settings.integrations.thirdParty.status.installed': '已安装',
'settings.integrations.thirdParty.status.installedVersion': '已安装 {version}',
'settings.integrations.thirdParty.status.updateAvailable': '有可用更新:{version}',
'settings.integrations.thirdParty.status.unpinned': '跟踪最新版本',
'settings.integrations.thirdParty.status.projectInstalled': '也已为此项目配置',
'settings.integrations.thirdParty.status.ambiguous': '多个用户级插件条目需要手动管理',
'settings.integrations.thirdParty.status.restartRequired': '请先重启 OpenCode,再设置此提供商。',
'settings.integrations.thirdParty.status.registryUnavailable': '当前无法检查 npm。',
'settings.integrations.thirdParty.status.providerUnavailable': '该提供商尚不可用。请重启 OpenCode 后重试。',
'settings.integrations.thirdParty.dialog.remove.title': '移除集成',
'settings.integrations.thirdParty.dialog.remove.description': '要从用户级 OpenCode 配置中移除 {name} 吗?OpenCode 刷新后将不再加载该提供商。',
'settings.integrations.thirdParty.toast.installed': '已安装 {name}',
'settings.integrations.thirdParty.toast.updated': '已更新 {name}',
'settings.integrations.thirdParty.toast.removed': '已移除 {name}',
'settings.integrations.thirdParty.toast.actionFailed': '无法更新集成',
'settings.integrations.thirdParty.toast.providerUnavailable': '暂时无法打开该提供商',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '通过 OpenCode 使用 Claude Pro 或 Max 订阅。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '通过 OpenCode 使用 Command Code 的 Laguna S 2.1 模型。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': '通过 OpenCode 使用你的 Cursor 订阅。',
},
'zh-TW': {
'settings.page.integrations.title': '整合',
'settings.page.integrations.description': '將第三方供應商連接到 OpenCode。',
'settings.integrations.thirdParty.title': '第三方整合',
'settings.integrations.thirdParty.info': '安裝並管理支援的 OpenCode 供應商外掛。設定會開啟供應商既有的驗證設定。',
'settings.integrations.thirdParty.actions.install': '安裝',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '設定',
'settings.integrations.thirdParty.actions.remove': '移除',
'settings.integrations.thirdParty.actions.refresh': '重新整理',
'settings.integrations.thirdParty.actions.docs': '文件',
'settings.integrations.thirdParty.actions.managePlugins': '管理外掛',
'settings.integrations.thirdParty.status.notInstalled': '未安裝',
'settings.integrations.thirdParty.status.installed': '已安裝',
'settings.integrations.thirdParty.status.installedVersion': '已安裝 {version}',
'settings.integrations.thirdParty.status.updateAvailable': '有可用更新:{version}',
'settings.integrations.thirdParty.status.unpinned': '追蹤最新版本',
'settings.integrations.thirdParty.status.projectInstalled': '也已為此專案設定',
'settings.integrations.thirdParty.status.ambiguous': '多個使用者層級外掛項目需要手動管理',
'settings.integrations.thirdParty.status.restartRequired': '請先重新啟動 OpenCode,再設定此供應商。',
'settings.integrations.thirdParty.status.registryUnavailable': '目前無法檢查 npm。',
'settings.integrations.thirdParty.status.providerUnavailable': '供應商尚不可用。請重新啟動 OpenCode 後再試一次。',
'settings.integrations.thirdParty.dialog.remove.title': '移除整合',
'settings.integrations.thirdParty.dialog.remove.description': '要從使用者層級 OpenCode 設定中移除 {name} 嗎?OpenCode 重新整理後將不再載入此供應商。',
'settings.integrations.thirdParty.toast.installed': '已安裝 {name}',
'settings.integrations.thirdParty.toast.updated': '已更新 {name}',
'settings.integrations.thirdParty.toast.removed': '已移除 {name}',
'settings.integrations.thirdParty.toast.actionFailed': '無法更新整合',
'settings.integrations.thirdParty.toast.providerUnavailable': '暫時無法開啟供應商',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '透過 OpenCode 使用 Claude Pro 或 Max 訂閱。',
'settings.integrations.thirdParty.opencodeCommandcode.name': 'Command Code',
'settings.integrations.thirdParty.opencodeCommandcode.description': '透過 OpenCode 使用 Command Code 的 Laguna S 2.1 模型。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': '透過 OpenCode 使用你的 Cursor 訂閱。',
},
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Відстеження використання OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Підключіть панель OpenCode Go, щоб бачити ковзну, тижневу та місячну квоту.',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
"settings.openchamber.visual.field.followUpBehaviorDescription": "Choose what happens when you press Enter on a follow-up message while the agent is still responding.",
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...thirdPartyIntegrationI18n.uk,
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 用量跟踪',
'settings.providers.page.openCodeGo.description': '连接 OpenCode Go 控制面板以显示滚动、每周和每月配额。',
@@ -2133,4 +2134,5 @@ export const settingsDict = {
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n['zh-CN'],
} as const;
@@ -1,3 +1,4 @@
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 用量追蹤',
'settings.providers.page.openCodeGo.description': '連接 OpenCode Go 控制面板以顯示滾動、每週和每月配額。',
@@ -2133,4 +2134,5 @@
'settings.openchamber.visual.field.followUpBehaviorDescription': 'Choose what happens when you press Enter on a follow-up message while the agent is still responding.',
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...thirdPartyIntegrationI18n['zh-TW'],
} as const;
+6 -1
View File
@@ -25,7 +25,8 @@ export type SettingsPageSlug =
| 'notifications'
| 'voice'
| 'tunnel'
| 'about';
| 'about'
| 'integrations';
type SettingsPageGroup =
| 'general'
@@ -201,6 +202,7 @@ export const SETTINGS_PAGE_METADATA: readonly SettingsPageMeta[] = [
{ slug: 'voice', title: 'Voice', group: 'general', kind: 'single', keywords: ['tts', 'speech', 'voice'], isAvailable: (ctx) => !ctx.isVSCode },
{ slug: 'tunnel', title: 'External Tunnel', group: 'projects', kind: 'single', keywords: ['tunnel', 'external', 'cloudflare', 'qr', 'remote', 'mobile', 'share'], isAvailable: (ctx) => !ctx.isVSCode },
{ slug: 'about', title: 'About', group: 'general', kind: 'single', keywords: ['about', 'version', 'updates', 'release', 'changelog'], isAvailable: (ctx) => ctx.isMobile && !ctx.isVSCode },
{ slug: 'integrations', title: 'Integrations', group: 'general', kind: 'single', keywords: ['integration', 'plugin', 'provider', 'oauth', 'claude', 'cursor', 'command code', 'connect'] },
] as const;
const LEGACY_SIDEBAR_SECTION_TO_SETTINGS_SLUG: Record<SidebarSection, SettingsPageSlug> = {
@@ -286,6 +288,9 @@ export function getSettingsNavIcon(slug: SettingsPageSlug): IconName | null {
case 'git':
return 'git-branch';
case 'integrations':
return 'plug';
case 'usage':
return 'bar-chart-2';
case 'voice':
@@ -0,0 +1,30 @@
import { describe, expect, test } from 'bun:test';
import type { I18nKey } from '@/lib/i18n/store';
import { buildSettingsSearchResults } from './search';
const t = (key: I18nKey): string => key;
const runtimeCtx = {
isVSCode: false,
isWeb: true,
isDesktop: false,
isMobile: false,
isDesktopLocalOrigin: false,
isMac: false,
isWindows: false,
isLinux: false,
isWindowsArm64: false,
};
describe('settings search', () => {
test('finds the Claude Code third-party integration', () => {
const results = buildSettingsSearchResults({
query: 'claude',
runtimeCtx,
t,
getPageTitle: (page) => page,
});
expect(results.some((result) => result.id === 'integrations.third-party.opencode-claude')).toBe(true);
});
});
+28
View File
@@ -933,6 +933,34 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
keywords: ['background', 'push'],
isAvailable: (ctx) => ctx.isWeb && !ctx.isDesktop && !ctx.isVSCode,
},
{
id: 'integrations.third-party',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.title',
keywords: ['plugin', 'provider', 'oauth', 'install', 'update', 'remove'],
},
{
id: 'integrations.third-party.opencode-claude',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.opencodeClaude.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
keywords: ['claude', 'anthropic', 'claude code', 'pro', 'max', 'agent sdk'],
},
{
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'],
},
{
id: 'integrations.third-party.opencode-cursor-oauth',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.opencodeCursorOauth.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeCursorOauth.description',
keywords: ['cursor', 'oauth', 'subscription', 'openai compatible'],
},
] as const;
interface BuildSettingsSearchResultsOptions {