diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs index 1aa62294d56..255954ed767 100644 --- a/desktop/src-tauri/src/lib.rs +++ b/desktop/src-tauri/src/lib.rs @@ -374,6 +374,9 @@ pub fn run() { .inner_size(1100.0, 720.0) .visible(false) .user_agent(&window::webview_user_agent()) + // Keep dashboard HTML drag/drop (including chat panes) in the webview; + // Tauri's native drop handler intercepts it on Windows. + .disable_drag_drop_handler() // Cmd on macOS, Ctrl elsewhere, with + / - / 0. WebView2 zooms natively; on // macOS and Linux Tauri injects a keydown polyfill whose one IPC call is granted // to the loopback dashboard by `capabilities/dashboard-zoom.json`. diff --git a/docs-site/src/content/docs/fr/guides/claude-code.md b/docs-site/src/content/docs/fr/guides/claude-code.md index 49cd7d6113e..0405b2807d9 100644 --- a/docs-site/src/content/docs/fr/guides/claude-code.md +++ b/docs-site/src/content/docs/fr/guides/claude-code.md @@ -169,24 +169,24 @@ unknown signifie qu’opencodex ne peut pas déterminer si les réglages pointen ### Mode picker : modèles opencodex dans le sélecteur Code first-party -Le mode picker fait partie du mode first-party. Sur macOS, il est activé par défaut lorsque first-party +Le mode picker fait partie du mode first-party. Sur macOS et Windows, il est activé par défaut lorsque first-party est sélectionné, sauf si `claudeCode.intercept.picker: false` est défini. Il modifie le sélecteur de modèles de l'onglet Code de Desktop first-party pour y afficher les modèles opencodex disponibles par leur nom. Lors de la première activation, macOS peut demander l'autorisation d'une autorité de certification -locale dans le trousseau de connexion. Cette autorité est limitée à `claude.ai` et à ses sous-domaines. +locale dans le trousseau de connexion, et Windows dans le magasin racine de l'utilisateur actuel. Cette autorité est limitée à `claude.ai` et à ses sous-domaines. Son identité de signature exportable est protégée par le magasin d'identifiants du système et réutilisée lors des redémarrages ordinaires. Aucune clé de signature picker en clair n'est enregistrée dans le répertoire de configuration OpenCodex. La validation complète de l'autorité contrainte et la vérification -de la confiance du système restent obligatoires. Avec la même identité approuvée et un magasin accessible, -un redémarrage n'ajoute ni ne supprime de réglages de confiance des certificats. La restauration au démarrage -n'installe jamais la confiance : si elle manque, est révoquée ou inconnue, le picker reste en attente. -Exécutez explicitement `ocx claude desktop picker on` ou `ocx claude desktop picker trust` pour l'accorder. +de la confiance du système restent obligatoires, avec sur Windows la correspondance exacte de l'empreinte et une feuille vérifiée. Avec la même identité approuvée et un magasin accessible, +un redémarrage n'ajoute ni ne supprime de réglages de confiance des certificats macOS. La restauration au démarrage +ou la vérification d'état n'installe jamais la confiance : si elle manque, est révoquée ou inconnue, le picker reste en attente. +Exécutez explicitement `ocx claude desktop picker on` ou `ocx claude desktop picker trust` pour l'accorder, y compris la confirmation Windows si nécessaire. Une migration unique depuis une ancienne identité peut demander votre consentement pour supprimer sa confiance. Si ce nettoyage échoue, le picker reste indisponible et le profil appliqué utilise un relais sans déchiffrement jusqu'à sa réussite. macOS peut aussi demander de déverrouiller le trousseau ou -d'autoriser l'accès d'une application aux identifiants, y compris après un redémarrage ou une mise à jour. -Le picker reste non pris en charge sous Windows et Linux : aucun travail de CA, de magasin d'identifiants +d'autoriser l'accès d'une application aux identifiants, y compris après un redémarrage ou une mise à jour. Sur Windows, `on` ou `trust` explicite peut afficher une confirmation d'ajout de la racine. +Le picker reste non pris en charge sous Linux : aucun travail de CA, de magasin d'identifiants ou de proxy picker n'y démarre. L'interception Claude principale reste disponible ; ses fichiers CA locaux sont protégés par des vérifications du propriétaire, des liens symboliques, des permissions et des ACL Windows. diff --git a/docs-site/src/content/docs/fr/guides/combos.md b/docs-site/src/content/docs/fr/guides/combos.md index c35725b8c34..7076e7df862 100644 --- a/docs-site/src/content/docs/fr/guides/combos.md +++ b/docs-site/src/content/docs/fr/guides/combos.md @@ -277,7 +277,7 @@ flux de travail des tâches. ### Tableau de bord Ouvrez le tableau de bord local et choisissez **Modèles → Combos**. L'espace de travail crée, modifie, renomme et supprime -combos, et son sélecteur de cible exclut les modèles désactivés et les combos imbriqués. +les combos. Les sélecteurs de modèles incluent les modèles masqués : la visibilité ne concerne que les listes externes, pas la sélection interne des combos. Sélectionner un modèle masqué ne le rend pas visible. Le sélecteur de cible exclut toujours les fournisseurs désactivés, les combos imbriqués et les fournisseurs JEV réservés au service de décision. Chaque cible affiche aussi un badge de quota en direct : **Disponible**, **Quota épuisé** ou **Quota inconnu**. L’éditeur bloque Enregistrer et Créer pour une raison de quota uniquement lorsque chaque cible utilisable dispose d’une confirmation serveur encore valide indiquant que la limite d’inférence liée à ses identifiants configurés est épuisée. Les quotas de compte, de modèle, de recherche et de MCP fournis uniquement à titre d’affichage, ainsi que les informations de routage absentes ou expirées, ne déclenchent pas ce blocage. Le blocage expire à la réinitialisation applicable ou à l’expiration de la validité des données et fait l’objet d’une nouvelle vérification lorsque la page devient active ou visible ; Actualiser recharge à la fois les données des combos et les quotas. diff --git a/docs-site/src/content/docs/guides/claude-code.md b/docs-site/src/content/docs/guides/claude-code.md index 0c44d43adb2..c6d1eb5abc5 100644 --- a/docs-site/src/content/docs/guides/claude-code.md +++ b/docs-site/src/content/docs/guides/claude-code.md @@ -315,10 +315,13 @@ entries, is kept. Claude Desktop first-party routes its Code tab and subagents through OpenCodex. The standalone Claude Code CLI has a separate first-party switch. Both clients read the same `~/.claude/settings.json` proxy and CA settings: if only one switch is on, the other client still transits the local proxy, where TLS terminates, but its Messages requests relay to Anthropic unchanged. Other Anthropic paths relay unchanged and unrelated hosts remain blind tunnels. With the CLI switch on, the standalone `claude` also lists routed models in `/model`; see [Model picker in the CLI](#model-picker-in-the-cli). :::note[Windows system proxy (Clash, v2rayN, corporate proxies)] -When a Windows system proxy is on, Claude Desktop hands it to the Code tab as `HTTPS_PROXY`, and +For picker-off installs or pending installs with no applied picker profile, a Windows system proxy +is handed to the Code tab as `HTTPS_PROXY`, and that value takes precedence over the OpenCodex proxy in `~/.claude/settings.json`. The Code tab then goes around OpenCodex and routed models fail there, while the standalone CLI keeps working. -Add `api.anthropic.com` to your proxy client's system-proxy bypass list (in Clash Verge, +An applied selected picker profile uses Desktop's fixed egress proxy while it is available, even when +missing trust leaves the picker pending and `claude.ai` relays blindly. System-proxy bypass advice +applies when there is no selected available picker profile. Add `api.anthropic.com` to your proxy client's system-proxy bypass list (in Clash Verge, `system_proxy_bypass`), then fully quit and reopen Claude Desktop. `ocx doctor` reports this under "Claude Desktop first-party vs Windows system proxy". It cannot evaluate a PAC script or automatic proxy detection (WPAD, "Automatically detect settings"), so it reports those as unknown; @@ -349,17 +352,17 @@ hub, so `ocx claude desktop apply` there uses the gateway profile. ### Picker mode: opencodex models in the first-party Code-tab picker -Picker mode is part of first-party mode. On macOS it is on by default when first-party is selected, +Picker mode is part of first-party mode. On macOS and Windows it is on by default when first-party is selected, unless `claudeCode.intercept.picker: false` is set. It changes the first-party Desktop Code-tab picker so it lists available opencodex models by name. The first time it is enabled, macOS may ask you to -trust a local certificate authority in the login keychain. That authority is constrained to `claude.ai` +trust a local certificate authority in the login keychain, and Windows may ask you to trust it in the current-user Root store. That authority is constrained to `claude.ai` and its subdomains. OpenCodex protects its exportable signing identity in the OS credential store and reuses the same validated certificate and key across normal restarts. No plaintext picker signing key is stored in the OpenCodex config directory. The full constrained CA validation and OS trust -verification still apply. With the same approved identity and an available credential store, restarting -OpenCodex does not add or remove Certificate Trust Settings. Startup restore never installs trust: +verification still apply, including the exact fingerprint with a verified leaf on Windows. With the same approved identity and an available credential store, restarting +OpenCodex does not add or remove macOS Certificate Trust Settings. Restart and status never install trust: if trust is missing, revoked or unknown, the picker stays pending. Run `ocx claude desktop picker on` -or `ocx claude desktop picker trust` explicitly to grant trust. +or `ocx claude desktop picker trust` explicitly to grant trust, including the Windows confirmation when needed. Startup also attempts to remove a legacy on-disk picker signing key before checking whether interception is enabled. Cleanup is best-effort and does not enable interception or block startup. @@ -367,9 +370,9 @@ One-time migration from an older picker identity may require consent to remove i If cleanup cannot finish, the picker stays unavailable and the applied profile uses a blind relay until cleanup succeeds; `ocx claude desktop picker status` reports that state. macOS may separately ask you to unlock the keychain or approve an application's access to stored credentials. These native -access prompts can still occur on restart or upgrade. +access prompts can still occur on restart or upgrade. On Windows, explicit `on` or `trust` may show a confirmation to add the root. -Picker mode remains unsupported on Windows and Linux: OpenCodex starts no picker CA, credential-store +Picker mode remains unsupported on Linux: OpenCodex starts no picker CA, credential-store or proxy work there. The main Claude intercept remains available with ownership, symlink, file-permission and Windows ACL checks protecting its local CA files. diff --git a/docs-site/src/content/docs/guides/combos.md b/docs-site/src/content/docs/guides/combos.md index 7673c56b727..4fa8724c5c6 100644 --- a/docs-site/src/content/docs/guides/combos.md +++ b/docs-site/src/content/docs/guides/combos.md @@ -769,8 +769,9 @@ task workflow. ### Dashboard Open the local dashboard and choose **Models → Combos**. The workspace creates, edits, renames, and removes -combos, and its target picker excludes disabled models, nested combos, and the credential-only JEV -provider. **Create JEV Auto** opens the same Combo editor with an editable decision target template; +combos. Its model selectors include hidden models: catalog visibility only controls external model +lists, not internal Combo selection, and selecting a hidden model does not make it visible externally. +The target picker still excludes disabled providers, nested combos, and the credential-only JEV provider. **Create JEV Auto** opens the same Combo editor with an editable decision target template; an existing `jev-auto` id or alias is reported instead of creating a duplicate. A JEV Combo also shows **Decision service** (TypeSafe JEV or a configured `jev-decision` provider) and **Decision timeout (ms)**, and the Combos overview lists each JEV Combo's decision service, endpoint, and timeout. diff --git a/docs-site/src/content/docs/guides/integrations.md b/docs-site/src/content/docs/guides/integrations.md index 5bd17d8072e..78e83640a67 100644 --- a/docs-site/src/content/docs/guides/integrations.md +++ b/docs-site/src/content/docs/guides/integrations.md @@ -1,15 +1,16 @@ --- title: Integrations -description: Connect opencodex to OpenCode, Pi, OMP, Hermes, OpenClaw, Kimi Code, gjc, DeepSeek Harness, MiniMax Code, ZCode, Prime Agent, Aside, Raycast, omo, Cline CLI, Kilo, Command Code and Factory Droid from the dashboard — one switch per client, with a backup taken before every write. +description: Connect opencodex to OpenCode, Pi, Gentle Shell, OMP, Hermes, OpenClaw, Kimi Code, gjc, DeepSeek Harness, MiniMax Code, ZCode, Prime Agent, Aside, Raycast, omo, Cline CLI, Kilo, Command Code and Factory Droid from the dashboard — one switch per client, with a backup taken before every write. --- The **Connect** page writes opencodex's provider block into a client's own config -file, and removes it again. Nineteen clients work this way, each with a switch: +file, and removes it again. Twenty clients work this way, each with a switch: | Client | Config file | Format | When the change takes effect | Credential | |---|---|---|---|---| | OpenCode | `~/.config/opencode/opencode.json` | JSON | next direct launch | `OPENCODEX_OPENCODE_API_KEY` | | Pi | `~/.pi/agent/models.json` | JSON | new sessions | loopback placeholder | +| Gentle Shell | `~/.gentle-shell/agent/models.json` (persistent selected home) | JSON | after restarting Gentle Shell | loopback placeholder | | OMP | `~/.omp/agent/models.yml` | YAML | after restarting OMP | `opencodex-loopback` placeholder | | Hermes | `~/.hermes/config.yaml` | YAML | new sessions | `OPENCODEX_HERMES_API_KEY` | | OpenClaw | `~/.openclaw/openclaw.json` | JSON5 | immediately, on a running gateway | `OPENCODEX_OPENCLAW_API_KEY` | @@ -28,6 +29,36 @@ file, and removes it again. Nineteen clients work this way, each with a switch: | Command Code | `~/.commandcode/providers.json` (on Windows with the default home: use `HOME ?? USERPROFILE` only if nonblank and Windows-absolute, otherwise `homedir()`; a separately supplied home is preserved; append `.commandcode\providers.json`) | JSON | next launch of Command Code | none — keyless loopback (`apiKey: false`) | | Factory Droid | `~/.factory/settings.json` (`%USERPROFILE%\.factory\settings.json` on Windows) | JSON | immediately via file watching | none — keyless loopback | +## Gentle Shell + +Choose **Connect → Gentle Shell**, or use the same managed-integration commands: + +```bash +ocx export --client gentle-shell --json +ocx integration client enable --client gentle-shell +ocx integration client disable --client gentle-shell +``` + +Gentle Shell has a separate destination and rollback history from Pi. Only +`providers.opencodex` is managed; other providers and preferences stay intact. +Catalog changes refresh an already connected, unchanged block. An existing manually +copied block is a conflict, not permission to overwrite it: inspect the preview and +use the explicit overwrite confirmation only if you intend to replace it. + +The saved `home` in `~/.gentle-shell/config.json` selects the destination. A saved +custom path wins; isolated/default mode uses `GENTLE_SHELL_HOME` or +`~/.gentle-shell/agent`. `GENTLE_SHELL_CONFIG` selects an alternate launcher config. +These environment variables must be set on the **OpenCodex process**, not just in a +later shell. Selectors must be absolute paths; literal `~` and relative paths refuse. +One-off `gentle-shell --home` flags cannot be discovered by a background proxy. + +Link mode or a home aliasing Pi refuses with a Pi-integration remedy; use **Connect → Pi** +for that shared file instead. OpenCodex does not change launcher preferences. An +unreadable/unsafe launcher config refuses; malformed JSON falls back to isolated, +matching the launcher. If you move a connected home, disable it using its original +selectors before reconnecting the new one. Restart Gentle Shell after a catalog update. +This integration retains Pi’s loopback-only export policy and stores no real API key. + "omo" names three products that share the `~/.omo` folder. The **omo** tab manages Pi-based omo (the senpi engine) through `~/.omo/agent/models.json`, as in the table above. Codex-based omo (LazyCodex) gets its own section on the same tab, shown only when LazyCodex is detected, described in diff --git a/docs-site/src/content/docs/guides/remote-workspace.md b/docs-site/src/content/docs/guides/remote-workspace.md index 939ea624de9..1ebc0f725a8 100644 --- a/docs-site/src/content/docs/guides/remote-workspace.md +++ b/docs-site/src/content/docs/guides/remote-workspace.md @@ -171,6 +171,29 @@ Prompt submission acknowledges acceptance immediately; the dashboard polls the s cancels an active Executor command, and prevents a late response from reopening the stopped session. +## Work with sessions side by side + +The session list on the left opens a session in the focused pane. Drag a session to the left, +right, top, or bottom edge of another pane to split the conversation area. You can show up to +four different sessions at once. An already visible session moves between panes instead of +opening a duplicate composer. + +Use **Split right** or **Split below** next to a session for the keyboard-accessible alternative. +Drag a divider to resize the panes, or focus the divider and use its arrow keys. **Home** and +**End** set the divider to its minimum and maximum size. Each session +keeps its own draft, submission state, and Stop action, so a pending turn in one pane does not +block a different session. **Close pane** changes the layout only; it does not stop the session. + +The pane layout is restored for this Hub in the same browser. Only session identifiers and pane +positions and divider sizes are saved; draft text and model output are not written to browser storage. Reloading +the page clears unsent drafts. On screens up to 760px wide, panes stack vertically without +resize dividers; the saved split positions and sizes return when the screen is wider. + +This view is shared by the browser dashboard and the OpenCodex desktop dashboard. CLI users +can open the dashboard with `ocx gui` and select **Remote Workspace** after its normal Hub setup. +It does not change the terminal interface of `codex` or the conversation layout inside the +separate official ChatGPT/Codex desktop app. + ## Restart and reconnect behavior The Hub persists bounded session metadata and a small recent event snapshot. After a Hub restart, diff --git a/docs-site/src/content/docs/ja/guides/claude-code.md b/docs-site/src/content/docs/ja/guides/claude-code.md index 4d1cd5938b4..27618ac397d 100644 --- a/docs-site/src/content/docs/ja/guides/claude-code.md +++ b/docs-site/src/content/docs/ja/guides/claude-code.md @@ -166,21 +166,21 @@ unknown は設定がまだ opencodex のプロキシを指すか判断できな ### Picker モード: 1P の Code タブで opencodex モデルを表示する -Picker モードは 1P モードの一部です。macOS で 1P を選ぶとデフォルトで有効になりますが、 +Picker モードは 1P モードの一部です。macOS と Windows で 1P を選ぶとデフォルトで有効になりますが、 `claudeCode.intercept.picker: false` を設定した場合は無効です。1P の Desktop の Code タブにある モデルピッカーを書き換え、利用できる opencodex モデルを名前付きで表示します。初回の有効化時は、 -macOS がログインキーチェーン内のローカル証明書認証局を信頼するよう求めることがあります。この認証局の +macOS がログインキーチェーン内、Windows が現在のユーザーのルートストアでローカル証明書認証局を信頼するよう求めることがあります。この認証局の 制約は `claude.ai` とそのサブドメインに限られます。エクスポート可能な署名用 ID は OS の資格情報ストアで 保護され、通常の再起動でも同じ証明書と鍵を再利用します。OpenCodex の設定ディレクトリには Picker の -署名鍵を平文で保存しません。制約付き CA の完全な検証と OS の信頼確認は引き続き必要です。 -承認済みの同じ ID と利用可能な資格情報ストアがあれば、再起動で証明書の信頼設定を追加・削除しません。 -起動時の復元は信頼をインストールしません。信頼が未設定、取り消し済み、不明の場合は保留となり、 -`ocx claude desktop picker on` または `ocx claude desktop picker trust` を明示的に実行して信頼を付与します。 +署名鍵を平文で保存しません。制約付き CA の完全な検証と OS の信頼確認は引き続き必要です(Windows では正確なフィンガープリントと検証済みリーフで確認します)。 +承認済みの同じ ID と利用可能な資格情報ストアがあれば、再起動で macOS の証明書の信頼設定を追加・削除しません。 +起動時の復元や状態確認は信頼をインストールしません。信頼が未設定、取り消し済み、不明の場合は保留となり、 +`ocx claude desktop picker on` または `ocx claude desktop picker trust` を明示的に実行して信頼を付与します(Windows では確認が表示されることがあります)。 旧 ID からの一度限りの移行では、以前の信頼を削除するために同意が必要になる場合があります。 削除が完了するまでは Picker は利用できず、適用済みプロファイルは復号しない中継を使います。 キーチェーンのロック解除やアプリの資格情報へのアクセス許可は macOS 独自の動作で、再起動や更新時にも -表示される場合があります。Windows と Linux は Picker 非対応で、Picker の CA、資格情報ストア、 +表示される場合があります。Windows では `on` や `trust` の明示的な実行時にルート追加の確認が表示されることがあります。Linux は Picker 非対応で、Picker の CA、資格情報ストア、 プロキシの処理を開始しません。通常の Claude インターセプトは利用でき、ローカル CA ファイルには 所有者、シンボリックリンク、ファイル権限、Windows ACL の検査が適用されます。 diff --git a/docs-site/src/content/docs/ja/guides/combos.md b/docs-site/src/content/docs/ja/guides/combos.md index 33f2b628fd0..7ed25d4cb27 100644 --- a/docs-site/src/content/docs/ja/guides/combos.md +++ b/docs-site/src/content/docs/ja/guides/combos.md @@ -184,7 +184,7 @@ v1/base/v2 モードと完全な暗号化タスクのワークフローについ ### ダッシュボード -ローカル ダッシュボードを開き、**Models → コンボ**を選択します。ワークスペースはコンボを作成、編集、名前変更、削除し、そのターゲット ピッカーは無効なモデルとネストされたコンボを除外します。 +ローカル ダッシュボードを開き、**Models → コンボ**を選択します。ワークスペースではコンボの作成、編集、名前変更、削除ができます。モデル選択には非表示モデルも含まれます。表示設定は外部のモデル一覧にのみ適用され、コンボ内部の選択には影響しません。非表示モデルを選択しても外部には表示されません。ターゲット選択では、無効なプロバイダー、ネストされたコンボ、決定サービス専用の JEV プロバイダーは引き続き除外されます。 各ターゲットには **利用可能**、**クォータを使い切りました**、**クォータ不明** のライブバッジも表示されます。 エディターがクォータを理由に保存と作成をブロックするのは、使用可能なすべてのターゲットについて、設定された認証情報の推論上限に達したことを示す、サーバーによる確認が現在も有効な場合だけです。表示専用のアカウント・モデル・検索・MCP クォータや、ルーティングの根拠情報の欠落・期限切れによって、このブロックが発生することはありません。ブロックは該当するリセット時刻またはデータの有効期限に解除され、ページがアクティブになるか表示状態になると再確認されます。「更新」はコンボデータとクォータの両方を再読み込みします。ダッシュボードのエディターではまだ `cooldownMs` と `waitForCooldownMs` を設定できません。後続の UI 作業が完了するまでは、構成ファイルまたは管理 API を使用してください。 diff --git a/docs-site/src/content/docs/ko/guides/claude-code.md b/docs-site/src/content/docs/ko/guides/claude-code.md index f4a6f3354ec..eb05333120d 100644 --- a/docs-site/src/content/docs/ko/guides/claude-code.md +++ b/docs-site/src/content/docs/ko/guides/claude-code.md @@ -192,21 +192,21 @@ unknown은 설정이 아직 opencodex 프록시를 가리키는지 판단할 수 ### Picker 모드: 1P Code 탭에 opencodex 모델 표시하기 -Picker 모드는 1P 모드의 일부예요. macOS에서 1P를 선택하면 기본으로 켜지지만, +Picker 모드는 1P 모드의 일부예요. macOS와 Windows에서 1P를 선택하면 기본으로 켜지지만, `claudeCode.intercept.picker: false`를 설정하면 꺼져요. 1P Desktop의 Code 탭 모델 선택기를 바꿔서 -사용 가능한 opencodex 모델을 이름으로 보여줘요. 처음 켤 때 macOS 로그인 키체인에서 로컬 인증 기관을 +사용 가능한 opencodex 모델을 이름으로 보여줘요. 처음 켤 때 macOS 로그인 키체인이나 Windows 현재 사용자 Root 저장소에서 로컬 인증 기관을 신뢰하라는 메시지가 표시될 수 있어요. 이 인증 기관은 `claude.ai`와 그 하위 도메인으로 제한돼요. 내보낼 수 있는 서명용 인증서와 키는 OS 자격 증명 저장소로 보호하며, 일반적인 재시작에서는 같은 것을 재사용해요. OpenCodex 설정 디렉터리에 Picker 서명 키를 평문으로 저장하지 않아요. 제한된 CA의 전체 검증과 OS 신뢰 확인은 -계속 적용돼요. 승인한 인증서와 키가 같고 자격 증명 저장소를 사용할 수 있다면 재시작 시 인증서 신뢰 설정을 -추가하거나 삭제하지 않아요. 시작 시 복원은 신뢰를 설치하지 않아요. 신뢰가 없거나 철회됐거나 확인할 수 없다면 +계속 적용돼요(Windows에서는 정확한 지문과 확인된 리프로 검증해요). 승인한 인증서와 키가 같고 자격 증명 저장소를 사용할 수 있다면 재시작 시 macOS 인증서 신뢰 설정을 +추가하거나 삭제하지 않아요. 시작 시 복원이나 상태 확인은 신뢰를 설치하지 않아요. 신뢰가 없거나 철회됐거나 확인할 수 없다면 Picker는 대기 상태로 남아요. `ocx claude desktop picker on` 또는 `ocx claude desktop picker trust`를 직접 실행해 -신뢰를 부여하면 돼요. +신뢰를 부여하면 돼요(Windows에서는 확인 창이 나올 수 있어요). 이전 인증서에서 한 번 마이그레이션할 때는 기존 신뢰를 제거하기 위한 동의가 필요할 수 있어요. 정리가 끝나지 않으면 Picker는 사용할 수 없고 적용된 프로필은 복호화하지 않는 중계로 동작해요. 키체인 잠금 해제나 앱의 -자격 증명 접근 허용은 별도의 macOS 동작이며, 재시작이나 업데이트 때도 메시지가 나올 수 있어요. -Windows와 Linux에서는 Picker를 지원하지 않으며 Picker CA, 자격 증명 저장소, 프록시 작업을 시작하지 않아요. +자격 증명 접근 허용은 별도의 macOS 동작이며, 재시작이나 업데이트 때도 메시지가 나올 수 있어요. Windows에서는 `on`이나 `trust`를 직접 실행할 때 루트 추가 확인이 나올 수 있어요. +Linux에서는 Picker를 지원하지 않으며 Picker CA, 자격 증명 저장소, 프록시 작업을 시작하지 않아요. 기본 Claude 인터셉트는 계속 사용할 수 있고, 로컬 CA 파일에 소유자, 심볼릭 링크, 파일 권한, Windows ACL 검사를 적용해요. Picker 모드가 켜져 있는 동안 Claude Desktop의 네트워크는 OpenCodex를 거쳐요. OpenCodex가 중단되면 diff --git a/docs-site/src/content/docs/ko/guides/combos.md b/docs-site/src/content/docs/ko/guides/combos.md index 92be44fa008..a9a69b76b5a 100644 --- a/docs-site/src/content/docs/ko/guides/combos.md +++ b/docs-site/src/content/docs/ko/guides/combos.md @@ -194,7 +194,7 @@ v1/base/v2 모드와 암호화된 작업의 전체 흐름은 [Sub-agent Surface] ### 대시보드 -로컬 대시보드를 열고 **Models → Combos**를 선택합니다. 워크스페이스는 콤보를 만들고, 편집하고, 이름을 바꾸고, 제거할 수 있으며, 대상 선택기에서는 비활성 모델과 중첩 콤보를 제외합니다. +로컬 대시보드를 열고 **Models → Combos**를 선택합니다. 워크스페이스에서 콤보를 만들고, 편집하고, 이름을 바꾸고, 제거할 수 있습니다. 모델 선택기에는 숨겨진 모델도 포함됩니다. 표시 설정은 외부 모델 목록에만 적용되며 콤보 내부 선택에는 영향을 주지 않습니다. 숨겨진 모델을 선택해도 외부에 표시되지 않습니다. 대상 선택기에서는 비활성 공급자, 중첩 콤보, 결정 서비스 전용 JEV 공급자를 계속 제외합니다. 각 대상에는 **사용 가능**, **할당량 소진**, **할당량 알 수 없음** 실시간 배지도 표시됩니다. 편집기는 사용 가능한 모든 대상에 대해 설정된 인증 정보의 추론 한도가 소진되었다는 서버 확인이 현재 유효할 때만 할당량을 이유로 저장과 만들기를 차단합니다. 표시 전용 계정·모델·검색·MCP 할당량이나 누락되거나 만료된 라우팅 근거 정보는 이 차단을 일으키지 않습니다. 차단은 해당 한도의 초기화 시점이나 데이터 유효기간이 끝나면 해제되며 페이지가 활성화되거나 표시될 때 다시 확인됩니다. 새로 고침은 콤보 데이터와 할당량을 모두 다시 불러옵니다. 대시보드 편집기에서는 아직 `cooldownMs`나 `waitForCooldownMs`를 설정할 수 없습니다. 후속 UI 작업이 완료될 때까지 구성 파일이나 관리 API를 사용하세요. diff --git a/docs-site/src/content/docs/ko/guides/remote-workspace.md b/docs-site/src/content/docs/ko/guides/remote-workspace.md index ef5b6490aec..338234f4da3 100644 --- a/docs-site/src/content/docs/ko/guides/remote-workspace.md +++ b/docs-site/src/content/docs/ko/guides/remote-workspace.md @@ -95,6 +95,28 @@ ocx remote-workspace status 프롬프트 실행 중에도 **Stop**을 사용할 수 있습니다. Hub 코딩 에이전트의 현재 턴을 중단하고 활성 Executor 명령을 취소하며, 늦게 온 응답이 중지된 세션을 다시 열지 못하게 합니다. +## 여러 세션을 분할해서 보기 + +왼쪽 세션 목록에서 세션을 클릭하면 현재 선택한 창에서 열립니다. 세션을 다른 창의 +왼쪽·오른쪽·위·아래 가장자리로 끌어다 놓으면 화면이 분할됩니다. 최대 네 개의 서로 다른 +세션을 동시에 표시할 수 있고, 이미 표시 중인 세션은 중복 창을 만드는 대신 이동합니다. + +세션 옆 **오른쪽으로 분할** 또는 **아래로 분할** 버튼도 사용할 수 있습니다. 경계선을 +드래그하거나 경계선에 키보드 초점을 놓고 방향키를 눌러 크기를 조절하세요. **Home**과 +**End** 키는 최소·최대 크기로 조절합니다. 각 세션의 +입력 중인 글, 전송 상태, 중지 동작은 독립적입니다. **창 닫기**는 배치만 변경하며 세션을 +중지하지 않습니다. + +같은 브라우저에서 이 Hub를 다시 열면 창 배치가 복원됩니다. 브라우저 저장소에는 세션 +식별자, 분할 배치와 경계선 크기만 저장하며, 작성 중인 글이나 모델 응답은 저장하지 않습니다. +새로고침하면 아직 보내지 않은 글은 지워집니다. 화면 너비가 760px 이하이면 경계선 없이 +창을 세로로 쌓아 표시하고, 화면이 넓어지면 저장된 분할 배치와 크기로 돌아갑니다. + +이 화면은 OpenCodex 브라우저 대시보드와 데스크톱 앱에서 공통으로 사용합니다. CLI에서는 +`ocx gui`로 대시보드를 열고 정상적인 Hub 설정 후 **원격 워크스페이스**를 선택하세요. +이 기능은 `codex` 터미널 화면이나 별도 공식 ChatGPT/Codex 앱 내부의 대화 배치를 변경하지 +않습니다. + ## 재시작과 재연결 동작 Hub는 제한된 세션 메타데이터와 최근 이벤트의 작은 스냅샷을 저장합니다. Hub 재시작 뒤 완료되지 않은 세션은 원래 Executor를 기다립니다. 해당 기기가 다시 연결되면 다음 프롬프트가 원래 Codex 작업, Claude Code 세션 또는 Pi 세션 ID를 이어갑니다. diff --git a/docs-site/src/content/docs/ru/guides/claude-code.md b/docs-site/src/content/docs/ru/guides/claude-code.md index 13c5632fb0f..c520548e72b 100644 --- a/docs-site/src/content/docs/ru/guides/claude-code.md +++ b/docs-site/src/content/docs/ru/guides/claude-code.md @@ -180,22 +180,22 @@ unknown означает, что opencodex не может определить, ### Режим picker: модели opencodex в селекторе Code first-party -Режим picker входит в режим first-party. В macOS он включён по умолчанию при выборе first-party, +Режим picker входит в режим first-party. В macOS и Windows он включён по умолчанию при выборе first-party, если не задано `claudeCode.intercept.picker: false`. Он изменяет селектор моделей во вкладке Code first-party Desktop и показывает доступные модели opencodex по именам. При первом включении macOS может -попросить доверить локальному центру сертификации в связке ключей для входа. Этот центр ограничен +попросить доверить локальному центру сертификации в связке ключей для входа, а Windows — в хранилище корней текущего пользователя. Этот центр ограничен `claude.ai` и его поддоменами. Экспортируемая идентичность подписи защищена хранилищем учётных данных ОС и повторно используется при обычных перезапусках. Ключ подписи picker не хранится открытым текстом в -каталоге конфигурации OpenCodex. Полная проверка ограниченного CA и доверия ОС сохраняется. Если одобренная +каталоге конфигурации OpenCodex. Полная проверка ограниченного CA и доверия ОС сохраняется, в Windows — по точному отпечатку с проверенным листом. Если одобренная идентичность не изменилась и хранилище доступно, перезапуск не добавляет и не удаляет настройки доверия -сертификатам. Восстановление при запуске никогда не устанавливает доверие: если оно отсутствует, отозвано +сертификатам macOS. Восстановление при запуске и проверка состояния никогда не устанавливают доверие: если оно отсутствует, отозвано или неизвестно, picker остаётся в ожидании. Для предоставления доверия явно выполните -`ocx claude desktop picker on` или `ocx claude desktop picker trust`. +`ocx claude desktop picker on` или `ocx claude desktop picker trust`, включая подтверждение Windows при необходимости. При однократной миграции со старой идентичности может потребоваться согласие на удаление прежнего доверия. Пока очистка не завершена, picker недоступен, а применённый профиль использует туннель без расшифровки. macOS отдельно может попросить разблокировать связку ключей или разрешить приложению доступ к учётным -данным, в том числе после перезапуска или обновления. Windows и Linux по-прежнему не поддерживают picker: +данным, в том числе после перезапуска или обновления. В Windows явные `on` или `trust` могут запросить подтверждение добавления корня. Linux по-прежнему не поддерживает picker: работа с его CA, хранилищем и прокси не запускается. Основной перехват Claude остаётся доступен; для его локальных файлов CA проверяются владелец, символические ссылки, права доступа и ACL Windows. diff --git a/docs-site/src/content/docs/ru/guides/combos.md b/docs-site/src/content/docs/ru/guides/combos.md index b6f139674c7..29c59a402b4 100644 --- a/docs-site/src/content/docs/ru/guides/combos.md +++ b/docs-site/src/content/docs/ru/guides/combos.md @@ -234,7 +234,7 @@ Failover намеренно ограничен. Он помогает при п ### Дашборд Откройте локальный дашборд и выберите **Models → Combos**. Рабочая область умеет создавать, редактировать, -переименовывать и удалять combo, а селектор целей исключает отключённые модели и вложенные combo. +переименовывать и удалять combo. Селекторы моделей включают скрытые модели: видимость влияет только на внешние списки, а не на внутренний выбор в combo. Выбор скрытой модели не делает её видимой снаружи. Селектор целей по-прежнему исключает отключённых провайдеров, вложенные combo и провайдеров JEV, предназначенных только для сервиса принятия решений. У каждой цели также отображается актуальный значок квоты: **Доступно**, **Квота исчерпана** или **Квота неизвестна**. Редактор блокирует сохранение и создание из-за квоты только тогда, когда для каждой пригодной к использованию цели есть действующее подтверждение сервера об исчерпании лимита инференса для настроенных учётных данных. Квоты аккаунта, модели, поиска и MCP, предназначенные только для отображения, а также отсутствующие или просроченные данные для принятия решения о маршрутизации не вызывают эту блокировку. Блокировка истекает при соответствующем сбросе квоты или окончании срока актуальности данных и проверяется повторно, когда страница становится активной или видимой; «Обновить» повторно загружает и данные combo, и квоты. Редактор дашборда пока не предоставляет `cooldownMs` и `waitForCooldownMs`; до появления соответствующего UI используйте файл конфигурации или Management API. diff --git a/docs-site/src/content/docs/tr/guides/claude-code.md b/docs-site/src/content/docs/tr/guides/claude-code.md index 82340db7c25..3b6b953d344 100644 --- a/docs-site/src/content/docs/tr/guides/claude-code.md +++ b/docs-site/src/content/docs/tr/guides/claude-code.md @@ -191,22 +191,22 @@ unknown, ayarların hâlâ opencodex vekiline işaret edip etmediğinin belirlen ### Picker modu: first-party Code sekmesinde opencodex modelleri -Picker modu first-party modunun bir parçasıdır. macOS'ta first-party seçildiğinde varsayılan olarak +Picker modu first-party modunun bir parçasıdır. macOS ve Windows'ta first-party seçildiğinde varsayılan olarak açıktır; `claudeCode.intercept.picker: false` ayarlanırsa kapalı kalır. First-party Desktop'ın Code sekmesindeki model seçiciyi değiştirerek kullanılabilir opencodex modellerini adlarıyla listeler. -İlk etkinleştirmede macOS, giriş anahtar zincirinde yerel bir sertifika yetkilisine güvenmenizi isteyebilir. +İlk etkinleştirmede macOS, giriş anahtar zincirinde, Windows ise geçerli kullanıcının kök deposunda yerel bir sertifika yetkilisine güvenmenizi isteyebilir. Bu yetkili `claude.ai` ve alt alan adlarıyla sınırlıdır. Dışa aktarılabilir imzalama kimliği işletim sisteminin kimlik bilgisi deposunda korunur ve normal yeniden başlatmalarda aynı sertifika ve anahtar yeniden kullanılır. OpenCodex yapılandırma dizininde düz metin picker imza anahtarı saklanmaz. Kısıtlı CA'nın tam doğrulaması ve -sistemdeki güven denetimi devam eder. Onaylanmış kimlik aynıysa ve depo erişilebilirse yeniden başlatma, -sertifika güven ayarlarını eklemez veya kaldırmaz. Başlangıçta geri yükleme hiçbir zaman güven yüklemez: +sistemdeki güven denetimi devam eder (Windows'ta tam parmak izi ve doğrulanmış yaprak ile). Onaylanmış kimlik aynıysa ve depo erişilebilirse yeniden başlatma, +macOS sertifika güven ayarlarını eklemez veya kaldırmaz. Başlangıçta geri yükleme ve durum denetimi hiçbir zaman güven yüklemez: güven eksik, iptal edilmiş veya bilinmiyorsa picker beklemede kalır. Güven vermek için açıkça -`ocx claude desktop picker on` veya `ocx claude desktop picker trust` komutunu çalıştırın. +`ocx claude desktop picker on` veya `ocx claude desktop picker trust` komutunu çalıştırın, gerekiyorsa Windows onayıyla birlikte. Eski bir kimlikten bir defalık geçişte önceki güveni kaldırmak için onay gerekebilir. Temizlik tamamlanana kadar picker kullanılamaz ve uygulanmış profil şifre çözmeyen bir aktarma kullanır. macOS ayrıca anahtar zincirinin kilidini açmanızı veya uygulamanın kimlik bilgilerine erişimini onaylamanızı isteyebilir; -bu istemler yeniden başlatma veya güncelleme sonrasında da çıkabilir. Windows ve Linux'ta picker desteklenmez: +bu istemler yeniden başlatma veya güncelleme sonrasında da çıkabilir. Windows'ta açık `on` veya `trust` kök ekleme onayını gösterebilir. Linux'ta picker desteklenmez: picker CA, kimlik bilgisi deposu veya proxy işlemleri başlatılmaz. Ana Claude yakalama işlevi kullanılabilir; yerel CA dosyaları için sahiplik, sembolik bağlantı, dosya izinleri ve Windows ACL denetimleri uygulanır. diff --git a/docs-site/src/content/docs/tr/guides/combos.md b/docs-site/src/content/docs/tr/guides/combos.md index fe7381e0341..6e8b5444780 100644 --- a/docs-site/src/content/docs/tr/guides/combos.md +++ b/docs-site/src/content/docs/tr/guides/combos.md @@ -305,8 +305,9 @@ Arayüzü](/tr/guides/sub-agent-surface/) sayfasına bakın. Yerel kontrol panelini açın ve **Modeller → Kombolar** seçeneğini belirleyin. Çalışma alanı komboları oluşturur, düzenler, yeniden adlandırır ve kaldırır; -hedef seçicisi ise devre dışı bırakılmış modelleri ve iç içe geçmiş komboları -hariç tutar. +model seçicileri gizli modelleri de içerir. Görünürlük yalnızca dış model listelerini etkiler, +kombo içindeki seçimi etkilemez; gizli bir modeli seçmek onu dışarıda görünür yapmaz. +Hedef seçicisi devre dışı sağlayıcıları, iç içe komboları ve yalnızca karar hizmeti sunan JEV sağlayıcılarını hariç tutar. Her hedef ayrıca canlı bir kota rozeti gösterir: **Kullanılabilir**, **Kota tükendi** veya **Kota bilinmiyor**. Düzenleyici, kota nedeniyle Kaydet ve Oluştur işlemlerini yalnızca kullanılabilir hedeflerin tümü için yapılandırılmış kimlik bilgisine ait çıkarım sınırının tükendiğini doğrulayan geçerli sunucu bilgisi varsa engeller. Yalnızca görüntüleme amaçlı hesap, model, arama ve MCP kotaları ya da eksik veya süresi dolmuş yönlendirme kanıtları bu engellemeye neden olmaz. Engelleme, ilgili sıfırlama zamanında veya verinin güncellik süresi dolduğunda sona erer ve sayfa etkin ya da görünür olduğunda yeniden kontrol edilir; Yenile, hem kombo verilerini hem de kotaları yeniden yükler. diff --git a/docs-site/src/content/docs/zh-cn/guides/claude-code.md b/docs-site/src/content/docs/zh-cn/guides/claude-code.md index 5a28a1ac65b..8652c595cd7 100644 --- a/docs-site/src/content/docs/zh-cn/guides/claude-code.md +++ b/docs-site/src/content/docs/zh-cn/guides/claude-code.md @@ -158,18 +158,18 @@ unknown 表示 opencodex 无法确定设置是否仍指向自己的代理。外 ### Picker 模式:在第一方 Code 标签页中显示 opencodex 模型 -Picker 模式是第一方模式的一部分。在 macOS 上选择第一方时默认开启;设置 +Picker 模式是第一方模式的一部分。在 macOS 和 Windows 上选择第一方时默认开启;设置 `claudeCode.intercept.picker: false` 后会保持关闭。它会修改第一方 Desktop 的 Code 标签页模型选择器, -按名称列出可用的 opencodex 模型。首次开启时,macOS 可能会要求你在登录钥匙串中信任本地证书颁发机构。 +按名称列出可用的 opencodex 模型。首次开启时,macOS 可能会要求你在登录钥匙串中、Windows 可能会要求你在当前用户根存储中信任本地证书颁发机构。 该颁发机构限制为 `claude.ai` 及其子域名。可导出的签名身份由 OS 凭据存储保护,普通重启会复用同一证书和密钥。 -OpenCodex 配置目录中不保存明文 Picker 签名密钥。受限 CA 的完整验证和 OS 信任检查仍然适用。 -已批准的身份不变且凭据存储可用时,重启不会添加或删除证书信任设置。启动恢复绝不会安装信任: +OpenCodex 配置目录中不保存明文 Picker 签名密钥。受限 CA 的完整验证和 OS 信任检查仍然适用(Windows 按精确指纹与已验证叶子验证)。 +已批准的身份不变且凭据存储可用时,重启不会添加或删除 macOS 证书信任设置。启动恢复与状态检查绝不会安装信任: 若信任缺失、被撤销或无法确认,Picker 会保持待处理状态。请明确运行 `ocx claude desktop picker on` -或 `ocx claude desktop picker trust` 来授予信任。 +或 `ocx claude desktop picker trust` 来授予信任(Windows 需要时含确认)。 从旧身份进行一次性迁移时,清除原有信任可能需要同意。清理未完成时,Picker 不可用,已应用的配置档案 -会使用不解密的中继。macOS 还可能单独要求解锁钥匙串或批准应用访问凭据,重启或升级时也可能出现这些提示。 -Windows 和 Linux 仍不支持 Picker,不会启动 Picker CA、凭据存储或代理工作。主要 Claude 拦截功能仍可用, +会使用不解密的中继。macOS 还可能单独要求解锁钥匙串或批准应用访问凭据,重启或升级时也可能出现这些提示。Windows 上显式 `on` 或 `trust` 可能显示添加根的确认。 +Linux 仍不支持 Picker,不会启动 Picker CA、凭据存储或代理工作。主要 Claude 拦截功能仍可用, 其本地 CA 文件受到所有者、符号链接、文件权限及 Windows ACL 检查保护。 Picker 模式开启期间,Claude Desktop 通过 OpenCodex 访问网络。如果 OpenCodex 停止,Desktop 会处于离线状态, diff --git a/docs-site/src/content/docs/zh-cn/guides/combos.md b/docs-site/src/content/docs/zh-cn/guides/combos.md index 35dc0d4dc82..53e918bd56e 100644 --- a/docs-site/src/content/docs/zh-cn/guides/combos.md +++ b/docs-site/src/content/docs/zh-cn/guides/combos.md @@ -214,7 +214,7 @@ combo 失败分为 **跳转** 失败和 **终止** 失败。 ### Dashboard -打开本地 dashboard 并选择 **Models → Combos**。该工作区可以创建、编辑、重命名和删除 combo,其目标选择器会排除已禁用的模型和嵌套 combo。 +打开本地 dashboard 并选择 **Models → Combos**。该工作区可以创建、编辑、重命名和删除 combo。模型选择器使用包含隐藏模型的完整目录:显示/隐藏设置只影响对外模型列表,不影响 Combo 内部选择,选中隐藏模型也不会将其对外显示。目标选择器仍排除已禁用的提供方、嵌套 combo 和仅用于决策服务的 JEV 提供方。 每个目标还会显示实时额度徽章:**可用**、**额度已用尽**或**额度未知**。只有当每个可用目标均有当前有效的服务器确认,表明其所配置凭据的推理限额已耗尽时,编辑器才会因额度而禁止保存和创建。仅供显示的账户、模型、搜索和 MCP 额度,以及缺失或已过期的路由依据,都不会触发此限制。此限制会在适用的重置时间或数据有效期结束时解除,并在页面变为活动或可见状态时重新检查;刷新会同时重新加载 Combo 数据和额度。dashboard 编辑器目前还不能设置 `cooldownMs` 或 `waitForCooldownMs`;在后续 UI 完成前,请使用配置文件或管理 API。 diff --git a/docs-site/src/content/docs/zh-tw/guides/claude-code.md b/docs-site/src/content/docs/zh-tw/guides/claude-code.md index c91637c60ae..dee9b6374a1 100644 --- a/docs-site/src/content/docs/zh-tw/guides/claude-code.md +++ b/docs-site/src/content/docs/zh-tw/guides/claude-code.md @@ -146,18 +146,18 @@ unknown 表示 opencodex 無法確定設定是否仍指向自己的代理。外 ### Picker 模式:在第一方 Code 分頁顯示 opencodex 模型 -Picker 模式是第一方模式的一部分。在 macOS 上選擇第一方時預設開啟;設定 +Picker 模式是第一方模式的一部分。在 macOS 和 Windows 上選擇第一方時預設開啟;設定 `claudeCode.intercept.picker: false` 後會保持關閉。它會修改第一方 Desktop 的 Code 分頁模型選擇器, -依名稱列出可用的 opencodex 模型。首次開啟時,macOS 可能會要求你在登入鑰匙圈中信任本機憑證授權單位。 +依名稱列出可用的 opencodex 模型。首次開啟時,macOS 可能會要求你在登入鑰匙圈中、Windows 可能會要求你在目前使用者根存放區中信任本機憑證授權單位。 該授權單位限制為 `claude.ai` 及其子網域。可匯出的簽章身分由 OS 認證資料儲存區保護,一般重新啟動會重用相同的憑證與金鑰。 -OpenCodex 設定目錄不會儲存明文 Picker 簽章金鑰。受限 CA 的完整驗證與 OS 信任檢查仍然適用。 -已核准的身分不變且認證資料儲存區可用時,重新啟動不會新增或移除憑證信任設定。啟動復原絕不會安裝信任: +OpenCodex 設定目錄不會儲存明文 Picker 簽章金鑰。受限 CA 的完整驗證與 OS 信任檢查仍然適用(Windows 按精確指紋與已驗證葉片驗證)。 +已核准的身分不變且認證資料儲存區可用時,重新啟動不會新增或移除 macOS 憑證信任設定。啟動復原與狀態檢查絕不會安裝信任: 若信任缺失、遭撤銷或無法確認,Picker 會維持待處理狀態。請明確執行 `ocx claude desktop picker on` -或 `ocx claude desktop picker trust` 來授予信任。 +或 `ocx claude desktop picker trust` 來授予信任(Windows 需要時含確認)。 從舊身分進行一次性移轉時,清除原有信任可能需要同意。清理未完成時,Picker 無法使用,已套用的設定檔 -會使用不解密的中繼。macOS 也可能另外要求解鎖鑰匙圈或核准應用程式存取憑證,重新啟動或升級時也可能出現這些提示。 -Windows 與 Linux 仍不支援 Picker,不會啟動 Picker CA、認證資料儲存區或代理作業。主要 Claude 攔截功能仍可用, +會使用不解密的中繼。macOS 也可能另外要求解鎖鑰匙圈或核准應用程式存取憑證,重新啟動或升級時也可能出現這些提示。Windows 上明確執行 `on` 或 `trust` 可能顯示新增根的確認。 +Linux 仍不支援 Picker,不會啟動 Picker CA、認證資料儲存區或代理作業。主要 Claude 攔截功能仍可用, 其本機 CA 檔案受到擁有者、符號連結、檔案權限及 Windows ACL 檢查保護。 Picker 模式開啟期間,Claude Desktop 會透過 OpenCodex 存取網路。如果 OpenCodex 停止,Desktop 會離線, diff --git a/docs-site/src/content/docs/zh-tw/guides/combos.md b/docs-site/src/content/docs/zh-tw/guides/combos.md index 7073a5baf6d..d95c8409370 100644 --- a/docs-site/src/content/docs/zh-tw/guides/combos.md +++ b/docs-site/src/content/docs/zh-tw/guides/combos.md @@ -221,7 +221,7 @@ Codex v2 子代理有一個重要限制([issue #92](https://github.com/lidge-j ### 儀表板 -開啟本機儀表板並選擇 **Combos**。該工作區可建立、編輯、重新命名與移除 combo,且其目標 picker 會排除已停用的模型與巢狀 combo。 +開啟本機儀表板並選擇 **Combos**。該工作區可建立、編輯、重新命名與移除 combo。模型選擇器包含隱藏模型;顯示/隱藏設定僅影響對外模型清單,不影響 Combo 內部選擇,選取隱藏模型也不會將其對外顯示。目標選擇器仍排除已停用的供應商、巢狀 combo 與僅提供決策服務的 JEV 供應商。 每個目標也會顯示即時額度徽章:**可用**、**額度已用盡**或**額度未知**。只有當每個可用目標均有目前有效的伺服器確認,顯示其所設定憑證的推論限額已耗盡時,編輯器才會因配額而停用儲存與建立。僅供顯示的帳戶、模型、搜尋與 MCP 配額,以及缺失或已過期的路由依據,都不會觸發此限制。此限制會在適用的重設時間或資料有效期限結束時解除,並在頁面變為作用中或可見狀態時重新檢查;重新整理會同時重新載入 Combo 資料與配額。 diff --git a/gui/src/app-routing.ts b/gui/src/app-routing.ts index 195504dd223..51ec534ee3c 100644 --- a/gui/src/app-routing.ts +++ b/gui/src/app-routing.ts @@ -131,6 +131,7 @@ export const INTEGRATION_TAB_HASHES = [ "integrations/cursor", "integrations/opencode", "integrations/pi", + "integrations/gentle-shell", "integrations/omp", "integrations/hermes", "integrations/openclaw", diff --git a/gui/src/components/apikeys-workspace/client-config-clients.ts b/gui/src/components/apikeys-workspace/client-config-clients.ts index 11b0d35b26e..f33555f7b23 100644 --- a/gui/src/components/apikeys-workspace/client-config-clients.ts +++ b/gui/src/components/apikeys-workspace/client-config-clients.ts @@ -8,13 +8,14 @@ * with EXPORT_CLIENT_IDS by hand; adding a client server-side renders no row * until this tuple changes. */ -export const CLIENTS = ["qoder", "opencode", "pi", "omp", "hermes", "openclaw", "kimi", "gajae", "dsh", "mcode", "zcode", "commandcode", "prime", "aside", "raycast", "omo", "cline", "kilo", "droid"] as const; +export const CLIENTS = ["qoder", "opencode", "pi", "omp", "hermes", "openclaw", "kimi", "gajae", "dsh", "mcode", "zcode", "commandcode", "prime", "aside", "raycast", "omo", "cline", "kilo", "droid", "gentle-shell"] as const; export type ExportClientId = (typeof CLIENTS)[number]; export const CLIENT_LABEL_KEYS = { qoder: "api.clientConfig.clientQoder", opencode: "api.clientConfig.clientOpencode", pi: "api.clientConfig.clientPi", + "gentle-shell": "integrations.tab.gentleShell", omp: "api.clientConfig.clientOmp", hermes: "api.clientConfig.clientHermes", openclaw: "api.clientConfig.clientOpenclaw", diff --git a/gui/src/components/integration-marks.ts b/gui/src/components/integration-marks.ts index 40e7e277f5e..73af7a8ddd5 100644 --- a/gui/src/components/integration-marks.ts +++ b/gui/src/components/integration-marks.ts @@ -41,12 +41,14 @@ const NATIVE_MARKS: Record, string> = * * A value may still be null: that is the honest answer for a client whose * vendor publishes nothing usable, and `ClientMark` renders a monogram for it. - * Today none are, which `integration-marks.test.ts` pins. + * Gentle Shell uses that fallback, which `integration-marks.test.ts` pins. */ export const INTEGRATION_MARKS: Record = { ...NATIVE_MARKS, opencode: CLIENT_MARKS.opencode ?? null, pi: CLIENT_MARKS.pi ?? null, + // No verified square Gentle Shell asset: use its own monogram, not Pi's mark. + "gentle-shell": null, omp: CLIENT_MARKS.omp ?? null, hermes: CLIENT_MARKS.hermes ?? null, openclaw: CLIENT_MARKS.openclaw ?? null, diff --git a/gui/src/components/remote-workspace/RemoteWorkspaceChats.tsx b/gui/src/components/remote-workspace/RemoteWorkspaceChats.tsx new file mode 100644 index 00000000000..61f28ad2cf8 --- /dev/null +++ b/gui/src/components/remote-workspace/RemoteWorkspaceChats.tsx @@ -0,0 +1,157 @@ +import { useEffect, useRef, useState, type CSSProperties, type DragEvent, type ReactNode } from "react"; +import { IconArrowDown, IconChevron, IconGrip, IconX } from "../../icons"; +import { useT } from "../../i18n/shared"; +import { Notice } from "../../ui"; +import { EVENT_TKEY, PROFILE_LABEL, STATUS_TKEY, type RemoteDevice, type RemoteSession } from "./types"; +import { MAX_PANES, minLayoutWidth, openPane, paneIds, parseLayout, reconcileLayout, removePane, resizeSplit, splitPane, type PaneLayout, type SplitEdge } from "./split-layout"; +import { useSessionActions } from "./use-session-actions"; + +const DRAG_TYPE = "application/x-opencodex-session"; +const EDGES: SplitEdge[] = ["left", "right", "up", "down"]; + +// Only a nested split reserves its width; a leaf pane stays free to follow the ratio. +const trackMin = (child: PaneLayout) => child.type === "split" ? minLayoutWidth(child) : 0; + +function SplitBranch({ node, renderPane, resize }: { + node: PaneLayout; renderPane: (id: string) => ReactNode; resize: (id: string, ratio: number) => void; +}) { + const t = useT(); + const container = useRef(null); + const dragging = useRef(false); + if (node.type === "pane") return renderPane(node.sessionId); + const style = { "--split-ratio": node.ratio, "--split-min-width": minLayoutWidth(node), + "--split-first-min": trackMin(node.first), "--split-second-min": trackMin(node.second) } as CSSProperties; + return
+
+
{ if (event.button !== 0) return; event.preventDefault(); event.currentTarget.focus(); dragging.current = true; event.currentTarget.setPointerCapture(event.pointerId); }} + onPointerMove={event => { + if (!dragging.current || !container.current) return; + const rect = container.current.getBoundingClientRect(); + const size = node.axis === "row" ? rect.width : rect.height; + if (size > 0) resize(node.id, (node.axis === "row" ? event.clientX - rect.left : event.clientY - rect.top) / size); + }} + onPointerUp={event => { dragging.current = false; if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId); }} + onPointerCancel={() => { dragging.current = false; }} onLostPointerCapture={() => { dragging.current = false; }} + onKeyDown={event => { + const backward = node.axis === "row" ? "ArrowLeft" : "ArrowUp", forward = node.axis === "row" ? "ArrowRight" : "ArrowDown"; + if (![backward, forward, "Home", "End"].includes(event.key)) return; + event.preventDefault(); + resize(node.id, event.key === "Home" ? 0.2 : event.key === "End" ? 0.8 : node.ratio + (event.key === backward ? -0.05 : 0.05)); + }} /> +
+
; +} + +export function RemoteWorkspaceChats({ apiBase, sessions, devices, selectedSessionId, stale, refresh }: { + apiBase: string; sessions: RemoteSession[]; devices: RemoteDevice[]; selectedSessionId: string; stale: boolean; refresh: () => unknown; +}) { + const t = useT(); + const storageKey = `ocx-remote-workspace-layout:${apiBase}`; + const [layout, setLayout] = useState(() => { + try { return parseLayout(localStorage.getItem(storageKey)); } catch { return null; } + }); + const [active, setActive] = useState(""); + const [dragged, setDragged] = useState(null); + const [dropTarget, setDropTarget] = useState<{ id: string; edge: SplitEdge } | null>(null); + const [focusRequest, setFocusRequest] = useState<{ id: string } | null>(null); + const [lastSelection, setLastSelection] = useState(selectedSessionId); + const host = useRef(null); + const actions = useSessionActions(apiBase, sessions, devices, stale, refresh); + const ids = actions.sessions.map(session => session.id); + const fallback = [...actions.sessions].reverse().find(session => session.status !== "stopped")?.id ?? ids.at(-1); + const effectiveLayout = reconcileLayout(layout, ids, fallback); + const visible = paneIds(effectiveLayout); + const activeId = visible.includes(active) ? active : visible[0] ?? ""; + + if (lastSelection !== selectedSessionId) { + setLastSelection(selectedSessionId); + if (selectedSessionId && ids.includes(selectedSessionId)) { + setLayout(openPane(effectiveLayout, selectedSessionId, activeId)); + setActive(selectedSessionId); + } + } else if (layout !== effectiveLayout) setLayout(effectiveLayout); + + useEffect(() => { + try { localStorage.setItem(storageKey, JSON.stringify(effectiveLayout)); } catch { /* The workspace remains usable without storage. */ } + }, [effectiveLayout, storageKey]); + useEffect(() => { + if (!focusRequest) return; + const heading = [...(host.current?.querySelectorAll("[data-pane-heading]") ?? [])].find(element => element.dataset.paneHeading === focusRequest.id); + heading?.focus(); + }, [focusRequest]); + + const open = (id: string) => { setLayout(openPane(effectiveLayout, id, activeId)); setActive(id); }; + const split = (id: string, target: string, edge: SplitEdge) => { + if (!ids.includes(id)) return; + const next = splitPane(effectiveLayout, id, target, edge); + setLayout(next); + if (paneIds(next).includes(id)) setActive(id); + setDragged(null); setDropTarget(null); + }; + const close = (id: string) => { + const next = removePane(effectiveLayout, id); + const nextId = paneIds(next)[0] ?? ""; + setLayout(next); setActive(nextId); setFocusRequest({ id: nextId }); + }; + const startDrag = (event: DragEvent, id: string) => { event.dataTransfer.setData(DRAG_TYPE, id); event.dataTransfer.effectAllowed = "move"; setDragged(id); }; + const endDrag = () => { setDragged(null); setDropTarget(null); }; + const canSplit = (id: string, target: string) => id !== target && (visible.includes(id) || visible.length < MAX_PANES); + + const renderPane = (id: string) => { + const session = actions.sessions.find(value => value.id === id); + if (!session) return null; + const disabled = session.status === "stopped" || (session.status === "failed" && session.resumable === false); + return
setActive(id)} onPointerDown={() => setActive(id)}> +
+
startDrag(event, id)} onDragEnd={endDrag}> +
{PROFILE_LABEL[session.profile]}{session.deviceName}/{session.rootLabel}
+
+ {t(STATUS_TKEY[session.status])} + +
+ {session.accessMode === "read-only" ? t("remote.access.readOnly") : session.capabilities.includes("workspace.exec") ? t("remote.access.workspace") : t("remote.access.workspaceFilesOnly")} +
+ {session.events.length === 0 ?

{t("remote.noEvents")}

: session.events.map(event =>
+ {event.type === "assistant" ? PROFILE_LABEL[session.profile] : t(EVENT_TKEY[event.type])}

{event.text}

+
)} +
+ {session.status === "failed" && session.resumable === false ? {t("remote.notResumable")} : null} + {actions.errors[id] ? {actions.errors[id]} : null} +