Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ enum ProviderImplementationManifest {
FutureAGIProviderImplementation(),
PluginAPIKeyProviderImplementation(spec: DevPassProviderDescriptor.spec),
PluginAPIKeyProviderImplementation(spec: AtlasCloudProviderDescriptor.spec),
PluginAPIKeyProviderImplementation(spec: VercelProviderDescriptor.spec),
VercelProviderImplementation(),
PluginAPIKeyProviderImplementation(spec: LLMManProviderDescriptor.spec),
PluginAPIKeyProviderImplementation(spec: XKiroProviderDescriptor.spec),
PluginCookieProviderImplementation(spec: MuseAIProviderDescriptor.spec),
Expand Down
110 changes: 110 additions & 0 deletions Sources/CodexBar/Providers/Vercel/VercelProviderImplementation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import CodexBarCore
import Foundation
import SwiftUI

struct VercelProviderImplementation: ProviderImplementation {
let id: UsageProvider = .vercel
var loadTeams: @Sendable ([String: String]) async throws -> [VercelCLITeam] = {
try await VercelCLIUsageFetcher().teams(environment: $0)
}

@MainActor
func observeSettings(_ settings: SettingsStore) {
PluginAPIKeyProviderImplementation(spec: VercelProviderDescriptor.spec).observeSettings(settings)
_ = settings.providerConfig(for: .vercel)?.source
}

@MainActor
func sourceMode(context: ProviderSourceModeContext) -> ProviderSourceMode {
context.settings.providerConfig(for: .vercel)?.source ?? .auto
}

@MainActor
func settingsFields(context: ProviderSettingsContext) -> [ProviderSettingsFieldDescriptor] {
PluginAPIKeyProviderImplementation(spec: VercelProviderDescriptor.spec).settingsFields(context: context)
.filter { $0.id != "vercel-team-id" }
}

@MainActor
func settingsPickers(context: ProviderSettingsContext) -> [ProviderSettingsPickerDescriptor] {
let refresh: (String) async -> Void = { _ in
await context.store.refreshProvider(.vercel, allowDisabled: true)
}
let source = Binding(
get: { (context.settings.providerConfig(for: .vercel)?.source ?? .auto).rawValue },
set: { value in
guard let mode = ProviderSourceMode(rawValue: value), [.auto, .api, .cli].contains(mode) else { return }
guard (context.settings.providerConfig(for: .vercel)?.source ?? .auto) != mode else { return }
context.settings.updateProviderConfig(provider: .vercel) { $0.source = mode == .auto ? nil : mode }
context.store.clearProviderState(.vercel)
})
let team = Binding(
get: { context.settings[providerConfig: .vercel, field: .workspace] },
set: { value in
guard context.settings[providerConfig: .vercel, field: .workspace] != value else { return }
context.settings[providerConfig: .vercel, field: .workspace] = value
context.store.clearProviderState(.vercel)
})
var options = [ProviderSettingsPickerOption(id: "", title: "Auto")]
+ context.store.vercelTeams.map {
ProviderSettingsPickerOption(id: $0.id, title: "\($0.name) (\($0.slug))")
}
if !team.wrappedValue.isEmpty, !options.contains(where: { $0.id == team.wrappedValue }) {
options.append(ProviderSettingsPickerOption(id: team.wrappedValue, title: team.wrappedValue))
}
return [
ProviderSettingsPickerDescriptor(
id: "vercel-source",
title: "Usage source",
subtitle: "",
binding: source,
options: [
.init(id: "auto", title: "Auto"),
.init(id: "cli", title: "Vercel CLI"),
.init(id: "api", title: "API key"),
],
isVisible: nil,
onChange: refresh),
ProviderSettingsPickerDescriptor(
id: "vercel-team",
title: "Team",
subtitle: "Uses the CLI's current team by default. Refresh to choose another team.",
binding: team,
options: options,
isVisible: { source.wrappedValue != "api" },
isEnabled: { !context.store.vercelTeamsRefreshing },
onChange: refresh,
trailingText: { context.statusText("vercel-teams") },
trailingActions: [.init(
id: "vercel-refresh-teams",
title: "Refresh",
style: .bordered,
isVisible: nil,
perform: { await self.refreshTeams(context: context) })]),
]
}

@MainActor
private func refreshTeams(context: ProviderSettingsContext) async {
guard !context.store.vercelTeamsRefreshing else { return }
context.store.vercelTeamsRefreshing = true
defer { context.store.vercelTeamsRefreshing = false }
context.setStatusText("vercel-teams", L("Refreshing"))
let revision = context.settings.providerConfigRevision(for: .vercel)
do {
let teams = try await self.loadTeams(context.store.environmentBase)
guard !Task.isCancelled, context.settings.providerConfigRevision(for: .vercel) == revision else {
context.setStatusText("vercel-teams", nil)
return
}
context.store.vercelTeams = teams
context.setStatusText("vercel-teams", nil)
} catch {
context.setStatusText(
"vercel-teams",
Task.isCancelled ||
context.settings.providerConfigRevision(for: .vercel) != revision ? nil : error
.localizedDescription)
}
}
}
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/ar.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "مخزنة في ~/.codexbar/config.json. أنشئ واحدًا على console.x.ai ضمن الإعدادات > مفاتيح الإدارة؛ لا يتم قبول مفاتيح الاستدلال API.";
"xai-..." = "xai-...";
"Team ID" = "فريق ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "يستخدم فريق CLI الحالي افتراضيًا. حدّث القائمة لاختيار فريق آخر.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "مطلوب. يظهر في وحدة التحكم xAI URL وإعدادات الفريق.";
"Sakana AI cost summary is not supported." = "ملخص تكلفة Sakana AI غير مدعوم.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "مخزنة في ~/.codexbar/config.json. انسخ رأس طلب وحدة التحكم Sakana AI Cookie.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/ca.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Emmagatzemat a ~/.codexbar/config.json. Creeu-ne un a console.x.ai a Configuració > Claus de gestió; Les claus d'inferència API no s'accepten.";
"xai-..." = "xai-...";
"Team ID" = "Equip ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Per defecte fa servir l'equip actual del CLI. Actualitza la llista per triar-ne un altre.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Obligatori. Es mostra a la consola xAI URL i a la configuració de l'equip.";
"Sakana AI cost summary is not supported." = "El resum de costos Sakana AI no s'admet.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Emmagatzemat a ~/.codexbar/config.json. Copieu la capçalera de sol·licitud de la consola Sakana AI Cookie.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/de.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2203,6 +2203,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Gespeichert in ~/.codexbar/config.json. Erstellen Sie einen unter console.x.ai unter Einstellungen > Verwaltungsschlüssel. Inferenzschlüssel API werden nicht akzeptiert.";
"xai-..." = "xai-...";
"Team ID" = "Team ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Verwendet standardmäßig das aktuelle CLI-Team. Aktualisiere die Liste, um ein anderes Team auszuwählen.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Erforderlich. Wird in der xAI-Konsole URL und in den Teameinstellungen angezeigt.";
"Sakana AI cost summary is not supported." = "Die Kostenübersicht Sakana AI wird nicht unterstützt.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Gespeichert in ~/.codexbar/config.json. Kopieren Sie den Anforderungsheader der Sakana AI-Konsole Cookie.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted.";
"xai-..." = "xai-...";
"Team ID" = "Team ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Uses the CLI's current team by default. Refresh to choose another team.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Required. Shown in the xAI Console URL and team settings.";
"Sakana AI cost summary is not supported." = "Sakana AI cost summary is not supported.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/es.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2199,6 +2199,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Almacenado en ~/.codexbar/config.json. Cree uno en console.x.ai en Configuración > Claves de administración; No se aceptan claves de inferencia API.";
"xai-..." = "xai-...";
"Team ID" = "Equipo ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Usa el equipo actual de la CLI de forma predeterminada. Actualiza la lista para elegir otro equipo.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Requerido. Se muestra en la consola xAI URL y en la configuración del equipo.";
"Sakana AI cost summary is not supported." = "No se admite el resumen de costos Sakana AI.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Almacenado en ~/.codexbar/config.json. Copie el encabezado de solicitud Cookie de la consola Sakana AI.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/fa.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "ذخیره شده در ~/.codexbar/config.json. یکی را در console.x.ai در زیر تنظیمات > کلیدهای مدیریت ایجاد کنید. کلیدهای استنتاج API پذیرفته نمی شوند.";
"xai-..." = "xai-...";
"Team ID" = "تیم ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "به‌طور پیش‌فرض از تیم فعلی CLI استفاده می‌کند. برای انتخاب تیم دیگر، فهرست را تازه‌سازی کنید.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "مورد نیاز. در کنسول xAI URL و تنظیمات تیم نشان داده شده است.";
"Sakana AI cost summary is not supported." = "خلاصه هزینه Sakana AI پشتیبانی نمی شود.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "ذخیره شده در ~/.codexbar/config.json. هدر درخواست کنسول Sakana AI Cookie را کپی کنید.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/fr.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Stocké dans ~/.codexbar/config.json. Créez-en un sur console.x.ai sous Paramètres > Clés de gestion ; Les clés d'inférence API ne sont pas acceptées.";
"xai-..." = "xai-...";
"Team ID" = "Équipe ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Utilise par défaut l'équipe actuelle du CLI. Actualisez la liste pour choisir une autre équipe.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Obligatoire. Affiché dans la console xAI URL et les paramètres d'équipe.";
"Sakana AI cost summary is not supported." = "Le récapitulatif des coûts Sakana AI n’est pas pris en charge.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Stocké dans ~/.codexbar/config.json. Copiez l'en-tête de requête Cookie de la console Sakana AI.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/gl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Almacenado en ~/.codexbar/config.json. Crea un en console.x.ai en Configuración > Teclas de xestión; As chaves de inferencia API non se aceptan.";
"xai-..." = "xai-...";
"Team ID" = "Equipo ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Usa o equipo actual da CLI por defecto. Actualiza a lista para escoller outro equipo.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Obrigatorio. Móstrase na consola xAI URL e na configuración do equipo.";
"Sakana AI cost summary is not supported." = "O resumo de custos Sakana AI non é compatible.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Almacenado en ~/.codexbar/config.json. Copie a cabeceira da solicitude da consola Sakana AI Cookie.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/id.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Disimpan di ~/.codexbar/config.json. Buat satu di console.x.ai di bawah Pengaturan > Kunci Manajemen; kesimpulan kunci API tidak diterima.";
"xai-..." = "xai-...";
"Team ID" = "Tim ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Secara default menggunakan tim CLI saat ini. Segarkan daftar untuk memilih tim lain.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Diperlukan. Ditampilkan di Konsol xAI URL dan pengaturan tim.";
"Sakana AI cost summary is not supported." = "Ringkasan biaya Sakana AI tidak didukung.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Disimpan di ~/.codexbar/config.json. Salin header permintaan Sakana AI konsol Cookie.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/it.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Memorizzato in ~/.codexbar/config.json. Creane uno su console.x.ai in Impostazioni > Chiavi di gestione; le chiavi di inferenza API non sono accettate.";
"xai-..." = "xai-...";
"Team ID" = "Squadra ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Usa il team attuale della CLI per impostazione predefinita. Aggiorna l'elenco per scegliere un altro team.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Obbligatorio. Visualizzato nella console xAI URL e nelle impostazioni del team.";
"Sakana AI cost summary is not supported." = "Il riepilogo dei costi Sakana AI non è supportato.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Memorizzato in ~/.codexbar/config.json. Copia l'intestazione della richiesta Cookie della console Sakana AI.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/ja.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2201,6 +2201,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "~/.codexbar/config.json に保存されます。 [設定] > [管理キー] の console.x.ai で作成します。推論 API キーは受け入れられません。";
"xai-..." = "xai-...";
"Team ID" = "チームID";
"Uses the CLI's current team by default. Refresh to choose another team." = "既定では CLI の現在のチームを使用します。別のチームを選ぶには一覧を更新してください。";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "必須。 xAI コンソール URL およびチーム設定に表示されます。";
"Sakana AI cost summary is not supported." = "Sakana AI コスト概要はサポートされていません。";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "~/.codexbar/config.json に保存されます。 Sakana AI コンソールの Cookie リクエスト ヘッダーをコピーします。";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/ko.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "~/.codexbar/config.json에 저장됩니다. 설정 > 관리 키 아래 console.x.ai에서 하나를 생성합니다. 추론 API 키는 허용되지 않습니다.";
"xai-..." = "xai-...";
"Team ID" = "팀 ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "기본적으로 CLI의 현재 팀을 사용합니다. 다른 팀을 선택하려면 새로고침하세요.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "필수입니다. xAI 콘솔 URL 및 팀 설정에 표시됩니다.";
"Sakana AI cost summary is not supported." = "Sakana AI 비용 요약은 지원되지 않습니다.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "~/.codexbar/config.json에 저장됩니다. Sakana AI 콘솔 Cookie 요청 헤더를 복사합니다.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/nl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Opgeslagen in ~/.codexbar/config.json. Maak er een aan op console.x.ai onder Instellingen > Beheersleutels; gevolgtrekking API-sleutels worden niet geaccepteerd.";
"xai-..." = "xai-...";
"Team ID" = "Team ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Gebruikt standaard het huidige CLI-team. Vernieuw de lijst om een ander team te kiezen.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Vereist. Weergegeven in de xAI-console URL en teaminstellingen.";
"Sakana AI cost summary is not supported." = "Sakana AI-kostenoverzicht wordt niet ondersteund.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Opgeslagen in ~/.codexbar/config.json. Kopieer de Sakana AI-console Cookie-verzoekheader.";
Expand Down
2 changes: 2 additions & 0 deletions Sources/CodexBar/Resources/pl.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -2204,6 +2204,8 @@
"Stored in ~/.codexbar/config.json. Create one at console.x.ai under Settings > Management Keys; inference API keys are not accepted." = "Przechowywane w ~/.codexbar/config.json. Utwórz go pod adresem console.x.ai w obszarze Ustawienia > Klucze zarządzania; wnioskowanie Klucze API nie są akceptowane.";
"xai-..." = "xai-...";
"Team ID" = "Zespół ID";
"Uses the CLI's current team by default. Refresh to choose another team." = "Domyślnie używa bieżącego zespołu CLI. Odśwież listę, aby wybrać inny zespół.";
"Vercel CLI" = "Vercel CLI";
"Required. Shown in the xAI Console URL and team settings." = "Wymagane. Wyświetlane w konsoli xAI URL i ustawieniach zespołu.";
"Sakana AI cost summary is not supported." = "Podsumowanie kosztów Sakana AI nie jest obsługiwane.";
"Stored in ~/.codexbar/config.json. Copy the Sakana AI console Cookie request header." = "Przechowywane w ~/.codexbar/config.json. Skopiuj nagłówek żądania Cookie konsoli Sakana AI.";
Expand Down
Loading
Loading