diff --git a/desktop/src-tauri/src/provider_icons.rs b/desktop/src-tauri/src/provider_icons.rs index 2799453c795..94b4b4d6010 100644 --- a/desktop/src-tauri/src/provider_icons.rs +++ b/desktop/src-tauri/src/provider_icons.rs @@ -56,6 +56,7 @@ const ALIASES: &[(&str, &str)] = &[ ("meta-model", "meta.svg"), ("meta-muse", "meta.svg"), ("mistral", "mistral-color.svg"), + ("mirasim", "mirasim.svg"), ("minimax", "minimax.svg"), ("minimax-cn", "minimax.svg"), ("moonshot", "moonshot-color.svg"), @@ -182,6 +183,7 @@ fn svg(file: &str) -> Option<&'static str> { "meta.svg" => svg!("meta.svg"), "minimax.svg" => svg!("minimax.svg"), "mistral-color.svg" => svg!("mistral-color.svg"), + "mirasim.svg" => svg!("mirasim.svg"), "moonshot-color.svg" => svg!("moonshot-color.svg"), "nanogpt.svg" => svg!("nanogpt.svg"), "nebius.svg" => svg!("nebius.svg"), diff --git a/devlog/_plan/260921_mirasim_provider/010_provider_design.md b/devlog/_plan/260921_mirasim_provider/010_provider_design.md new file mode 100644 index 00000000000..22dc767da8b --- /dev/null +++ b/devlog/_plan/260921_mirasim_provider/010_provider_design.md @@ -0,0 +1,85 @@ +# Mirasim provider native port + +## Goal + +Port the current `cpa-plugin-mirasim` protocol into OpenCodex as a native provider without embedding CLIProxyAPI or its native plugin ABI. + +Reference implementation pinned for this port: + +- `KIDA-MNESIA/cpa-plugin-mirasim` v1.1.0 / `857a984` +- OpenCodex base after the final pre-port fast-forward: `origin/dev` / `a49974639` + +## Architecture + +```text +Codex / Claude Code + | + v +OpenCodex router + | + v +Mirasim adapter + | | + | +-- GPT -> existing OpenAI Responses serializer/parser + | + +-- Claude -> existing Anthropic serializer/parser + | + v +Mirasim transport + - OAuth access/refresh + - Ed25519 device identity + - device ticket mint/cache + - mrs-sig-v2 request signing + - mrs-seal-v1 inference metadata envelope + - HTTP/1.1 pin through OpenCodex provider transport + | + v +relay.mirasim.ai +``` + +The provider composes existing protocol translators. It does not fork Anthropic Messages or OpenAI Responses translation. + +## Wire invariants + +1. Device/control-plane requests are signed with `mrs-sig-v2`, empty metadata and no sealed envelope. +2. Inference requests add session/agent/call metadata, include it in the v2 signature, then seal all Mirasim metadata except `x-mirasim-client` into `x-mirasim-enc`. +3. Relay metadata uses X25519 + HKDF-SHA256 + ChaCha20-Poly1305 (`mrs-seal-v1`). +4. Device tickets come from `POST /v1/device/session`; 404 falls back to access-token signing for one minute, 501 for fifteen minutes. +5. GPT models use `/v1/responses`; Claude models use `/v1/messages`. +6. Existing OAuth account selection must bind access token and device private key from the same stored credential. +7. Mirasim requests pin OpenCodex upstream transport to HTTP/1.1. Lower-case header spelling should be verified separately at wire level because fetch APIs may canonicalize names. +8. Auxiliary inference routes reuse the same signed/sealed transport: Claude `/v1/messages/count_tokens`, GPT `/v1/alpha/search`, and GPT `/v1/responses/compact`. +9. A Claude `[1m]` selector is local routing syntax only. The relay receives the bare model id plus the deduplicated `context-1m-2025-08-07` beta. +10. Signed account roster fields are authoritative over the static fallback catalog and remain account/device-scoped across access-token rotation. + +## Delivery order + +1. Golden-vector crypto parity. +2. OAuth credential shape, login, refresh and protected device key persistence. +3. Device-ticket and signed/sealed transport. +4. Dual-wire adapter and registry preset. +5. Static fallback catalog. +6. Signed dynamic `/v1/models` + `/v1/model-roster`. **Implemented.** +7. Provider quota via `/v1/limits`. **Implemented.** +8. Native `/v1/responses/compact`. **Implemented.** +9. Claude `count_tokens`, GPT `alpha/search`, and `[1m]` selector parity. **Implemented.** +10. Browser OAuth plus CLI-only email-code login (`--email` / optional `--code`), refresh, and best-effort `/auth/me` identity enrichment. **Implemented.** +11. Wire capture parity and real Claude/Codex acceptance tests. **Synthetic wire tests implemented; real account E2E requires a Mirasim login and is currently blocked because the local auth store has no Mirasim account.** + +## Safety boundaries + +- Device private keys remain only in `~/.opencodex/auth.json`; management/status projections never expose them. +- Caller-supplied `x-mirasim-*`, authorization and proxy authorization headers are stripped before signing. +- `x-mirasim-probe` is the only provider-owned control header allowlisted after signing; callers cannot inject it through the ordinary request surface. +- The request transport reuses OpenCodex's provider-scoped fetch executor so proxy, egress, timeout and HTTP-version policy stay centralized. +- Protocol golden vectors from the Go reference are the compatibility oracle. + +## Intentional host-lifecycle difference + +The CPA plugin asks its host to re-enter refresh every five minutes so it can poll `/auth/me` +for subscription-plan drift. OpenCodex's OAuth resolver has no provider-specific periodic refresh +scheduler; adding one solely for Mirasim would leak CPA host semantics into the shared OAuth +lifecycle. The native port therefore keeps `/auth/me` as best-effort login identity enrichment, +uses normal expiry refresh, and force-refreshes the OAuth snapshot after authenticated relay 401s. +The signed live model/roster cache is account/device-scoped rather than access-token-scoped, so a +normal token rotation does not lose the observed Claude thinking shape. diff --git a/docs-site/src/content/docs/fr/getting-started/quickstart.md b/docs-site/src/content/docs/fr/getting-started/quickstart.md index cad99b993ba..a3eb2f9fea0 100644 --- a/docs-site/src/content/docs/fr/getting-started/quickstart.md +++ b/docs-site/src/content/docs/fr/getting-started/quickstart.md @@ -13,7 +13,7 @@ ocx init `ocx init` vous accompagne dans les étapes suivantes : -1. **Choix d’un fournisseur** — sélectionnez l’un des 103 préréglages intégrés au registre, ou `custom` pour saisir une +1. **Choix d’un fournisseur** — sélectionnez l’un des 104 préréglages intégrés au registre, ou `custom` pour saisir une URL de base et un adaptateur. 2. **Clé API** — collez une clé ou référencez une variable d’environnement telle que `${ANTHROPIC_API_KEY}`. 3. **Modèle par défaut** — pour les fournisseurs clés, locaux et personnalisés, acceptez le préréglage ou saisissez un identifiant de modèle. diff --git a/docs-site/src/content/docs/fr/guides/providers.md b/docs-site/src/content/docs/fr/guides/providers.md index 8a928f1b299..193f37a9ea6 100644 --- a/docs-site/src/content/docs/fr/guides/providers.md +++ b/docs-site/src/content/docs/fr/guides/providers.md @@ -295,7 +295,7 @@ existante n'est pas concernée. ## 3. Catalogue des clés API -opencodex fournit 103 préréglages intégrés : 84 à clé, 15 OAuth, trois locaux et un préréglage par défaut de +opencodex fournit 104 préréglages intégrés : 84 à clé, 16 OAuth, trois locaux et un préréglage par défaut de transfert ChatGPT. Dans le tableau de bord, le sélecteur **Ajouter un fournisseur** ouvre le tableau de bord du fournisseur à clé, valide la clé et l'enregistre ; la validation dépend du fournisseur. Parmi les entrées notables : diff --git a/docs-site/src/content/docs/getting-started/quickstart.md b/docs-site/src/content/docs/getting-started/quickstart.md index 41e4485ce6e..99ff1a1d5d7 100644 --- a/docs-site/src/content/docs/getting-started/quickstart.md +++ b/docs-site/src/content/docs/getting-started/quickstart.md @@ -18,7 +18,7 @@ ocx init `ocx init` walks you through: -1. **Pick a provider** — choose one of the 103 built-in registry presets or `custom` to type a base +1. **Pick a provider** — choose one of the 104 built-in registry presets or `custom` to type a base URL and adapter. 2. **API key** — paste a key, or reference an environment variable like `${ANTHROPIC_API_KEY}`. 3. **Default model** — for key, local, and custom providers, accept the preset or enter a model id. diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index 2bbdeb0ed4f..9929c9a700a 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -185,6 +185,7 @@ that route. ```bash ocx login xai # xAI Grok ocx login anthropic # Anthropic Claude (Pro/Max) +ocx login mirasim # Mirasim browser login; use --email
for email verification ocx login kimi # Moonshot Kimi ocx login nous # Nous Portal (device grant; free + paid models) ocx login kiro # import kiro-cli credentials (or token fallback) @@ -203,6 +204,7 @@ ocx logout | --- | --- | --- | --- | | `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth uses the separate Grok CLI subscription gateway. The API-key override uses `https://api.x.ai/v1` and may inject Priority Processing. Live-first Grok catalog; `grok-4.5` is the fallback default. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude models; live model list fetched from `/v1/models`. | +| `mirasim` | `mirasim` | `https://relay.mirasim.ai` | Native signed Mirasim account provider. GPT-family models and `kimi-k3` use Responses semantics; Claude-family models use Messages semantics. The signed account roster supplies live model availability/context limits, and the Providers page shows Mirasim account quota windows. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi Code Plan coding models. Defaults to the stable `kimi-for-coding` alias (currently K2.8 Preview): 1M-token context window, adjustable `low`/`high`/`max` thinking (default `max`), text + image input. Retired `kimi-k2.x` selections are migrated to the alias on upgrade. | | `kimi-responses` | `openai-responses` | `https://api.kimi.com/coding/v1` | Same Kimi account login (reuses the `kimi` OAuth credential) over the OpenAI Responses wire. Same model roster and capabilities as `kimi`; thinking content stays encrypted server-side, tool calls and results stay visible. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research subscription gateway (same backend Hermes Agent uses). Device-grant login against `portal.nousresearch.com`; the access token is the per-request inference JWT. Mixed paid + `:free` model catalog (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) discovered live from the signed-in account. Refresh tokens are single-use and rotated on every refresh. | @@ -216,6 +218,8 @@ ocx logout Google Antigravity groups a model's complete `low` / `medium` / `high` variants into one entry with an effort selector. This includes Claude Opus and Sonnet 5.5 and future versions discovered during automatic refresh. Partial sets remain separate. Existing enabled/disabled choices carry into the grouped entry; genuinely new models still follow your New model policy. Saved suffix IDs continue to request their original tier. Grouped effort routing survives a proxy restart when model discovery is temporarily unavailable. A running Codex session may need to reload its model list after catalog refresh. Usage groups known Claude Sonnet and Opus 5.5 tier IDs under their base model, including historical tier records. Their displayed costs are derived Anthropic reference estimates, not Antigravity subscription charges. +For Mirasim email login, `ocx login mirasim --email
` prompts for the one-time code locally. For non-interactive use, pass `--code -` and supply the code on standard input rather than placing it in the process arguments. Claude selectors may append `[1m]` when the signed roster advertises the long-context variant; OpenCodex removes that selector before dispatch and applies the corresponding Claude beta. + Google Antigravity account and provider quota probes use fixed Google accounting endpoints, including the models fallback. They support transparent Fake-IP DNS for those destinations while retaining TLS verification, redirect rejection and private-address checks. A custom provider base URL changes model requests, not quota destinations; `NO_PROXY` continues to select the direct-route policy. ### Google tool-schema loss diagnostics @@ -517,7 +521,7 @@ The account list marks Kiro accounts excluded from automatic selection with a re ## 3. API-key catalog -opencodex ships 103 built-in presets: 84 key-based, 15 OAuth, three local, and one default +opencodex ships 104 built-in presets: 84 key-based, 16 OAuth, three local, and one default ChatGPT-forward preset. The dashboard's **Add provider** picker opens a key provider's dashboard, validates the key, and stores it; validation is provider-specific. Notable entries: diff --git a/docs-site/src/content/docs/ja/getting-started/quickstart.md b/docs-site/src/content/docs/ja/getting-started/quickstart.md index 500c89a2f65..2294fc1d541 100644 --- a/docs-site/src/content/docs/ja/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ja/getting-started/quickstart.md @@ -18,7 +18,7 @@ ocx init `ocx init` では次の手順を説明します。 -1. **プロバイダーを選択してください** — 103 個の組み込みレジストリプリセットのいずれか、または `custom` を選択してベース URL とアダプターを入力します。 +1. **プロバイダーを選択してください** — 104 個の組み込みレジストリプリセットのいずれか、または `custom` を選択してベース URL とアダプターを入力します。 2. **API キー** — キーを貼り付けるか、`${ANTHROPIC_API_KEY}` のような環境変数を参照します。 3. **デフォルト モデル** — キー、ローカル、カスタム プロバイダーの場合は、プリセットを受け入れるか、モデル ID を入力します。 4. **プロキシ ポート** — デフォルトは `10100` です。 diff --git a/docs-site/src/content/docs/ja/guides/providers.md b/docs-site/src/content/docs/ja/guides/providers.md index a499d77d404..5ebb8d08d5b 100644 --- a/docs-site/src/content/docs/ja/guides/providers.md +++ b/docs-site/src/content/docs/ja/guides/providers.md @@ -193,7 +193,7 @@ Kiro のログインには Kiro CLI が必要です。Unix では `curl -fsSL ht ## 3. API キーカタログ -opencodex には組み込みプリセットが 103 個含まれています。キー方式 84、OAuth 15、ローカル 3、 +opencodex には組み込みプリセットが 104 個含まれています。キー方式 84、OAuth 16、ローカル 3、 デフォルト ChatGPT 転送プリセット 1 です。ダッシュボードの **Add provider** ピッカーはキー発行ページを開き、 入力したキーを検証した後保存します(検証はプロバイダー固有です)。主な項目は以下のとおりです: diff --git a/docs-site/src/content/docs/ko/getting-started/quickstart.md b/docs-site/src/content/docs/ko/getting-started/quickstart.md index 22653fc9b91..2c06b538f7f 100644 --- a/docs-site/src/content/docs/ko/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ko/getting-started/quickstart.md @@ -18,7 +18,7 @@ ocx init `ocx init`은 다음 과정을 안내합니다: -1. **프로바이더 선택** — 내장 레지스트리 프리셋 103개 중 하나를 고르거나 `custom`을 선택해 base URL과 adapter를 직접 입력합니다. +1. **프로바이더 선택** — 내장 레지스트리 프리셋 104개 중 하나를 고르거나 `custom`을 선택해 base URL과 adapter를 직접 입력합니다. 2. **API 키** — 키를 붙여넣거나 `${ANTHROPIC_API_KEY}` 같은 환경 변수를 참조합니다. 3. **기본 모델** — 키, 로컬, custom 프로바이더에서는 프리셋을 그대로 쓰거나 모델 ID를 직접 입력합니다. 4. **프록시 포트** — 기본값은 `10100`입니다. diff --git a/docs-site/src/content/docs/ko/guides/providers.md b/docs-site/src/content/docs/ko/guides/providers.md index 3fda5134b55..9c1ef41b09c 100644 --- a/docs-site/src/content/docs/ko/guides/providers.md +++ b/docs-site/src/content/docs/ko/guides/providers.md @@ -190,7 +190,7 @@ Kiro 로그인에는 Kiro CLI가 필요합니다. Unix에서는 `curl -fsSL http ## 3. API 키 카탈로그 -opencodex에는 빌트인 프리셋이 103개 들어 있습니다. 키 방식 84개, OAuth 15개, 로컬 3개, +opencodex에는 빌트인 프리셋이 104개 들어 있습니다. 키 방식 84개, OAuth 16개, 로컬 3개, 기본 ChatGPT 포워드 프리셋 1개입니다. 대시보드의 **Add provider** 선택기는 키 발급 페이지를 열고, 입력한 키를 검증한 뒤 저장합니다(검증은 프로바이더별로 다릅니다). 주요 항목은 다음과 같습니다: diff --git a/docs-site/src/content/docs/ru/getting-started/quickstart.md b/docs-site/src/content/docs/ru/getting-started/quickstart.md index 16108d8d67a..67ff8415a92 100644 --- a/docs-site/src/content/docs/ru/getting-started/quickstart.md +++ b/docs-site/src/content/docs/ru/getting-started/quickstart.md @@ -18,7 +18,7 @@ ocx init `ocx init` проведёт вас по следующим шагам: -1. **Выбор провайдера** — выберите один из 103 встроенных пресетов реестра или `custom`, чтобы +1. **Выбор провайдера** — выберите один из 104 встроенных пресетов реестра или `custom`, чтобы ввести базовый URL и адаптер вручную. 2. **API-ключ** — вставьте ключ или сошлитесь на переменную окружения вида `${ANTHROPIC_API_KEY}`. 3. **Модель по умолчанию** — для провайдеров с ключом, локальных и `custom` примите значение из diff --git a/docs-site/src/content/docs/ru/guides/providers.md b/docs-site/src/content/docs/ru/guides/providers.md index 7317ddafbc4..8d0d6e8c981 100644 --- a/docs-site/src/content/docs/ru/guides/providers.md +++ b/docs-site/src/content/docs/ru/guides/providers.md @@ -206,7 +206,7 @@ Inline JSON и лишние позиционные аргументы откло ## 3. Каталог API-ключей -opencodex поставляется с 103 встроенными пресетами: 84 на основе ключей, 15 OAuth, три локальных и +opencodex поставляется с 104 встроенными пресетами: 84 на основе ключей, 16 OAuth, три локальных и один пресет ChatGPT-форварда по умолчанию. Селектор **Add provider** в дашборде открывает страницу выдачи ключей провайдера, проверяет ключ и сохраняет его; проверка зависит от провайдера. Наиболее заметные записи: diff --git a/docs-site/src/content/docs/tr/getting-started/quickstart.md b/docs-site/src/content/docs/tr/getting-started/quickstart.md index 0d707f5e0ee..baa5172c95b 100644 --- a/docs-site/src/content/docs/tr/getting-started/quickstart.md +++ b/docs-site/src/content/docs/tr/getting-started/quickstart.md @@ -14,7 +14,7 @@ ocx init `ocx init` adım adım size rehberlik eder: -1. **Bir sağlayıcı seçin** — yerleşik kayıt defterindeki 103 önayardan birini +1. **Bir sağlayıcı seçin** — yerleşik kayıt defterindeki 104 önayardan birini veya bir temel URL ile adaptör yazmak için `custom` seçeneğini belirleyin. 2. **API anahtarı** — bir anahtar yapıştırın veya `${ANTHROPIC_API_KEY}` gibi bir ortam değişkenine başvurun. diff --git a/docs-site/src/content/docs/tr/guides/providers.md b/docs-site/src/content/docs/tr/guides/providers.md index 75bb1318860..370d42f33f8 100644 --- a/docs-site/src/content/docs/tr/guides/providers.md +++ b/docs-site/src/content/docs/tr/guides/providers.md @@ -327,7 +327,7 @@ olmayan bir makineden oturum açmak bundan etkilenmez. ## 3. API anahtarı kataloğu -opencodex 103 yerleşik önayar ile birlikte gelir: 84 anahtar tabanlı, 15 +opencodex 104 yerleşik önayar ile birlikte gelir: 84 anahtar tabanlı, 16 OAuth, üç yerel ve bir varsayılan ChatGPT iletme önayarı. Kontrol panelinin **Sağlayıcı ekle** seçicisi bir anahtar sağlayıcısının kontrol panelini açar, anahtarı doğrular ve saklar; doğrulama sağlayıcıya özgüdür. Dikkate değer diff --git a/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md b/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md index c73b77d255f..9d0c51ebf7b 100644 --- a/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md +++ b/docs-site/src/content/docs/zh-cn/getting-started/quickstart.md @@ -18,7 +18,7 @@ ocx init `ocx init` 会引导你完成: -1. **选择 provider** — 从内置 registry 的 103 个预设中选择一个,或选择 `custom` 手动输入 base URL 和 adapter。 +1. **选择 provider** — 从内置 registry 的 104 个预设中选择一个,或选择 `custom` 手动输入 base URL 和 adapter。 2. **API key** — 粘贴一个 key,或引用一个环境变量,例如 `${ANTHROPIC_API_KEY}`。 3. **默认模型** — 对于 key、本地和 custom provider,接受预设值或输入模型 id。 4. **代理端口** — 默认为 `10100`。 diff --git a/docs-site/src/content/docs/zh-cn/guides/providers.md b/docs-site/src/content/docs/zh-cn/guides/providers.md index e4d90fa4495..d56c5b9ea96 100644 --- a/docs-site/src/content/docs/zh-cn/guides/providers.md +++ b/docs-site/src/content/docs/zh-cn/guides/providers.md @@ -186,7 +186,7 @@ Kiro 登录需要 Kiro CLI:Unix 使用 `curl -fsSL https://cli.kiro.dev/instal ## 3. API 密钥目录 -opencodex 内置 103 个预设:84 个密钥预设、15 个 OAuth 预设、3 个本地预设,以及 1 个默认的 +opencodex 内置 104 个预设:84 个密钥预设、16 个 OAuth 预设、3 个本地预设,以及 1 个默认的 ChatGPT 转发预设。仪表盘的 **Add provider** 选择器会打开密钥提供商的控制台,验证并保存密钥。 验证因提供商而异。主要条目包括: diff --git a/docs-site/src/content/docs/zh-tw/getting-started/quickstart.md b/docs-site/src/content/docs/zh-tw/getting-started/quickstart.md index 0583cbe4473..8a28107b8bc 100644 --- a/docs-site/src/content/docs/zh-tw/getting-started/quickstart.md +++ b/docs-site/src/content/docs/zh-tw/getting-started/quickstart.md @@ -13,7 +13,7 @@ ocx init `ocx init` 會引導你完成: -1. **選擇 provider** —— 從內建 registry 的 103 個預設中選擇一個,或選擇 `custom` 手動輸入 +1. **選擇 provider** —— 從內建 registry 的 104 個預設中選擇一個,或選擇 `custom` 手動輸入 base URL 和 adapter。 2. **API key** —— 貼上一個 key,或引用一個環境變數,例如 `${ANTHROPIC_API_KEY}`。 3. **預設模型** —— 對於 API key、本機和 custom provider,可接受預設值或輸入模型 id。 diff --git a/docs-site/src/content/docs/zh-tw/guides/providers.md b/docs-site/src/content/docs/zh-tw/guides/providers.md index 2deea9cb86d..b565cc88553 100644 --- a/docs-site/src/content/docs/zh-tw/guides/providers.md +++ b/docs-site/src/content/docs/zh-tw/guides/providers.md @@ -249,7 +249,7 @@ database 並移除目前的 WAL、SHM 與 journal sidecar,再發布先前的 s ## 3. API 金鑰目錄 -opencodex 內建 103 個 preset:84 個 key-based、15 個 OAuth、3 個 local,以及 1 個預設 ChatGPT-forward +opencodex 內建 104 個 preset:84 個 key-based、16 個 OAuth、3 個 local,以及 1 個預設 ChatGPT-forward preset。儀表板的 **Add provider** picker 會開啟 key provider 的 dashboard、驗證金鑰並儲存;驗證方式 依 provider 而異。主要條目如下。 diff --git a/gui/public/provider-icons/README.md b/gui/public/provider-icons/README.md index 0e595d7b4f7..91f20b39c86 100644 --- a/gui/public/provider-icons/README.md +++ b/gui/public/provider-icons/README.md @@ -205,6 +205,11 @@ Sourced for the providers that were rendering a coloured initial tile. Every entry below was fetched from the vendor's own domain, taken from the registry's `baseUrl`/`dashboardUrl` rather than guessed. +- `mirasim.svg` — supplied by the operator on 2026-09-21 as a 793x698 RGBA + logo image. The committed SVG is a geometric vector reconstruction of that + exact black plate / eight white rounded bars so the small provider tile stays + sharp; no external brand asset was substituted. + Published as SVG and committed with only comments, ``/`<desc>` and `data-name` attributes stripped: diff --git a/gui/public/provider-icons/mirasim.svg b/gui/public/provider-icons/mirasim.svg new file mode 100644 index 00000000000..aaab565396a --- /dev/null +++ b/gui/public/provider-icons/mirasim.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 793 698" role="img" aria-labelledby="title"> + <title id="title">Mirasim + + + + + + + + + + + + diff --git a/gui/src/components/QuotaBars.tsx b/gui/src/components/QuotaBars.tsx index fc72b0bb5f3..750ea11bcde 100644 --- a/gui/src/components/QuotaBars.tsx +++ b/gui/src/components/QuotaBars.tsx @@ -23,8 +23,11 @@ export type QuotaBarRow = { * shorter windows first — 5h, weekly, cursor first-party, cursor API, monthly, * then subscription credits before other custom windows. */ +const MIRASIM_MODEL_WEEKLY = /^Model\s*·\s*7d[-_]([a-z0-9][a-z0-9.-]{0,63})$/i; + function rawCustomWindowRank(rawLabel: string): number { if (rawLabel === "5h") return 0; + if (MIRASIM_MODEL_WEEKLY.test(rawLabel)) return 1.5; if (rawLabel === "First-party models") return 2; if (rawLabel === "API usage") return 3; if (rawLabel === "Total subscription credits") return 4.5; @@ -53,6 +56,23 @@ export function isCustomQuotaWindowIncomplete( } function localizeCustomQuotaLabel(rawLabel: string, t: TFn): string { + const mirasimWeekly = rawLabel.match(MIRASIM_MODEL_WEEKLY); + if (mirasimWeekly?.[1]) { + const familyId = mirasimWeekly[1].toLowerCase(); + const knownFamilyKey = ({ + claude: "quota.modelFamily.claude", + fable: "quota.modelFamily.fable", + sonnet: "quota.modelFamily.sonnet", + opus: "quota.modelFamily.opus", + haiku: "quota.modelFamily.haiku", + } as const)[familyId as "claude" | "fable" | "sonnet" | "opus" | "haiku"]; + const family = knownFamilyKey + ? t(knownFamilyKey) + : familyId.split(/[.-]/).filter(Boolean) + .map(part => part.charAt(0).toUpperCase() + part.slice(1)) + .join(" "); + return `${family} · ${t("quota.weeklyLimit")}`; + } switch (rawLabel) { case "First-party models": return t("quota.cursorFirstParty"); diff --git a/gui/src/components/provider-workspace/ProviderAuthPanel.tsx b/gui/src/components/provider-workspace/ProviderAuthPanel.tsx index da5419c975c..7f1daf32538 100644 --- a/gui/src/components/provider-workspace/ProviderAuthPanel.tsx +++ b/gui/src/components/provider-workspace/ProviderAuthPanel.tsx @@ -8,7 +8,11 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useT } from "../../i18n/shared"; import { IconLock, IconRefresh, IconTrash } from "../../icons"; import type { WorkspaceItem } from "../../provider-workspace/catalog"; -import { oauthAccountDisplayLabel, providerAuthSurface } from "../../provider-workspace/auth"; +import { + oauthAccountDisplayLabel, + oauthAccountSecondaryIdentity, + providerAuthSurface, +} from "../../provider-workspace/auth"; import { displayAccountId } from "../../lib/privacy"; import AccountAutoSwitchControl from "../AccountAutoSwitchControl"; import { @@ -561,6 +565,7 @@ export default function ProviderAuthPanel({ const maskedId = displayAccountId(account.id); const healthLabel = formatOAuthHealthLabel(t, account.health); const healthSummary = formatOAuthHealthSummary(t, item.name, account.id, account.health); + const secondaryIdentity = oauthAccountSecondaryIdentity(account, maskedId, t); return (
  • @@ -572,7 +577,7 @@ export default function ProviderAuthPanel({