Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2ca541e
security(desktop): bump tauri-plugin-updater to 2.14.1 for zip CVE-20…
devin-ai-integration[bot] Oct 29, 2026
9ccd9b3
Merge dev and align desktop MSRV with pinned Tauri crates
luvs01 Oct 31, 2026
bed14bf
fix(cli): attest Codex listener before token injection (#8007)
luvs01 Nov 3, 2026
83f7667
fix(kimi): report monthly Coding Plan quota (#8077)
zarv1k Nov 3, 2026
14692ab
fix(codex): keep profile keys OpenCodex does not manage (#8074)
codewith-aditya Nov 3, 2026
086f0ab
fix(kiro): report content-filter stops as non-retryable refusals (#8072)
mushikingh Nov 3, 2026
491beb6
fix(command-code): avoid double charging live NDJSON buffers (#8047)
0disoft Nov 3, 2026
665cc48
fix(link): restore owned integrations before native signal exit (#8036)
luvs01 Nov 3, 2026
a143604
perf(devin): batch consumed stream chunk removal (#8049)
0disoft Nov 3, 2026
8c822dc
fix(codex): hold selection ownership through dashboard feature toggle…
luvs01 Nov 3, 2026
fde2e4c
fix(responses): keep untyped assistant messages inside their tool-cal…
fec123 Nov 3, 2026
3dc4022
fix(responses): unwrap one extra executable freeform body wrapper (#8…
nickdavis Nov 3, 2026
c0221fe
fix(kiro): resubmit a finished answer on the completion retry (#8070)
mushikingh Nov 3, 2026
7b3bb7a
Fix non-ASCII Codex turn metadata headers (#8040)
visualbridge7188 Nov 3, 2026
345c428
chore(release): open dev at 2.98.0 before releasing 2.97.0 (#8135)
github-actions[bot] Nov 3, 2026
a98a6bf
test(diagnostics): use executable catalog fixture on macOS (#8136)
lidge-jun Nov 3, 2026
40c83b6
Merge remote-tracking branch 'origin/dev' into lane/8039
lidge-jun Nov 3, 2026
acea1f4
ci: run the full Ubuntu shards on this head
lidge-jun Nov 3, 2026
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
1,214 changes: 668 additions & 546 deletions desktop/src-tauri/Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
[package]
name = "opencodex-desktop"
version = "2.97.0"
version = "2.98.0"
description = "OpenCodex desktop shell"
authors = ["OpenCodex contributors"]
license = "MIT"
edition = "2021"
rust-version = "1.88"
rust-version = "1.90"

[lib]
name = "opencodex_desktop_lib"
crate-type = ["staticlib", "cdylib", "rlib"]

[build-dependencies]
tauri-build = { version = "=2.6.3", features = [] }
tauri-build = { version = "=2.7.4", features = [] }
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

[dependencies]
base64 = "=0.22.1"
Expand All @@ -22,14 +22,14 @@ serde = { version = "=1.0.229", features = ["derive"] }
serde_json = "=1.0.151"
sha2 = "=0.10.9"
uuid = { version = "=1.18.1", features = ["v4"] }
tauri = { version = "=2.11.6", features = ["tray-icon", "image-png", "macos-private-api"] }
tauri-utils = "=2.9.3"
tauri = { version = "=2.12.5", features = ["tray-icon", "image-png", "macos-private-api"] }
tauri-utils = "=2.10.2"
tauri-plugin-autostart = "=2.5.0"
tauri-plugin-opener = "=2.5.3"
tauri-plugin-process = "=2.3.0"
tauri-plugin-shell = "=2.2.1"
tauri-plugin-single-instance = "=2.4.0"
tauri-plugin-updater = "=2.9.0"
tauri-plugin-updater = "=2.14.1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 Windows update path is outside pull-request CI

Pull-request desktop CI runs only on Ubuntu, so it cannot exercise a Windows update with the new updater. Consider a manual Windows run on this head before release.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Windows-native evidence for 9ccd9b3: exact Rust 1.90.0 cargo check --locked with the real prepared sidecar/GUI, 33 distinct native unit tests (including the registry recovery and ACL cases under BasicUser), and the official unsigned local release build for both MSI and NSIS. Both bundle digests and the elevated-owner/controlled-runner-cleanup limitations are now recorded in Verification. The committed updater key, endpoint and release-signing configuration are unchanged.

This narrows the gap but does not replace the requested end-to-end updater check: no installed app was replaced or launched, and no signed updater archive was produced. Signed update discovery/extraction/installation/restart remains an explicit pre-release requirement using an approved signed test artifact/feed and an isolated Windows user or VM. I have left that acceptance unchecked rather than marking it passed from a successful bundle build.

tokio = { version = "=1.45.1", features = ["sync", "time"] }

# Linux only, and already in this graph: `tao` enables its own `dbus` feature by default, so
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "OpenCodex",
"version": "2.97.0",
"version": "2.98.0",
"identifier": "com.opencodex.desktop",
"build": {
"frontendDist": "../ui",
Expand Down
10 changes: 10 additions & 0 deletions docs-site/src/content/docs/fr/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ configuration de référence et de repli. Sur l'interface de bouclage, ce fichie
vous pouvez fusionner manuellement si l'injection automatique a été supprimée ; hors bouclage, il contient la
forme avec fournisseur dédié. Le mode de fournisseur externe laisse ce profil intact.

Quand ce fichier est régénéré, les clés racine simples qu'OpenCodex ne gère pas sont conservées : un réglage
que vous ajoutez, comme `stream_idle_timeout_ms` ou `stream_max_retries`, survit à l'injection suivante.
Chaque affectation conservée est copiée telle quelle, y compris les valeurs sur plusieurs lignes et les entiers
64 bits, et placée avant la première table. Les clés à l'intérieur des tables et les clés racine pointées comme
`a.b = 1` ne sont pas conservées. En cas de conflit, OpenCodex l'emporte toujours : les clés racine qu'il gère
(`model_provider`, `model_catalog_json`, `openai_base_url`) sont réécrites pour le mode de routage actif, et
une clé racine portant le nom d'une table écrite par le profil, par exemple un `features = { ... }` en ligne
quand le profil écrit `[features]`, est supprimée. Si le fichier change pendant qu'une injection attend le
verrou d'écriture, l'injection s'arrête avec une erreur réessayable et laisse votre modification en place.

:::caution
Les clés racine telles que `openai_base_url`, `model_provider` et `model_catalog_json` **doivent** précéder le
premier en-tête `[table]`. L'injecteur garantit ce placement, supprime ses propres copies obsolètes ou en double
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/fr/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ ocx start --socks5-off

### `ocx stop`

Un Link Child non supervisé restaure Codex natif et Grok avant de libérer son listener lors d’un signal, en revérifiant la connexion à chaque écriture. Service/Desktop, sibling, transfert de redémarrage et reçu stop du parent préservent les intégrations. L’arrêt refuse le redémarrage avec `409 runtime_stopping`. Une terminaison forcée peut éviter le signal ; la restauration par `ocx stop` reste nécessaire.

Arrête le proxy actif à partir de son PID, supprime le fichier de PID et rétablit le fonctionnement natif de Codex. Si un service d’arrière-plan géré est installé, `ocx stop` l’arrête d’abord afin qu’il ne puisse pas relancer le proxy. Le bouton **Stop** du tableau de bord Web exécute la même opération (`POST /api/stop`) sur tous les backends, sauf le Planificateur de tâches Windows : le wrapper peut y relancer le proxy après la fin de la tâche, donc le tableau de bord refuse avec `respawnable_service`, ne modifie rien et vous demande d'exécuter `ocx stop`.

Sur un client hub connecté, `ocx stop`, y compris via l’API, conserve le routage Codex, le catalogue et la configuration Grok appartenant à la connexion ; `ocx start` les dessert de nouveau. L’arrêt explicite d’un Remote Link Child rétablit au contraire, si la restauration partagée réussit, le routage natif de Codex, le catalogue et les métadonnées de reprise sauvegardées, et supprime la configuration Grok gérée. La connexion Home enregistrée reste conservée ; `ocx disconnect` la supprime.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ L’API de gestion expose `GET`/`PUT /api/v2`, `/api/injection-model`, `/api/eff

La page Codex Auth permet également de modifier l’indicateur natif `default_mode_request_user_input` de Codex (`GET`/`PUT /api/codex-auth/features/default-mode-request-user-input`). Son activation ajoute `[features] default_mode_request_user_input = true` au fichier `$CODEX_HOME/config.toml` de Codex au moyen de la commande officielle `codex features enable|disable`. Cette modification préserve le format du fichier et est retirée lorsque l’option est désactivée. Codex peut ainsi suspendre une session en mode Default et vous poser des questions avec l’outil `request_user_input`. Cet indicateur est encore en développement en amont et ne s’applique qu’aux nouvelles sessions ; l’activation échoue explicitement si la version installée de Codex ne le reconnaît pas encore.

Pendant qu’une mise à jour de Codex CLI détient l’installation, cette commande renvoie HTTP 503 avec `codex_cli_selection_busy` et `retryable: true` avant toute exécution. Réessayez après la mise à jour ; les erreurs d’écriture de la configuration restent des réponses 502.

## Liste des modèles et consignes

La liste v2 effective comprend, parmi les modèles configurés, les cinq premiers qui sont visibles dans le sélecteur, classés par priorité, compatibles avec v2 et présents dans le catalogue injecté. Un modèle est admissible en v2 si son choix imposé en amont vaut explicitement `"v2"`, vaut `null` ou est absent. Un véritable choix `"v1"` l’exclut. Les entrées exclues restent dans la configuration afin de pouvoir redevenir admissibles ultérieurement.
Expand Down
16 changes: 16 additions & 0 deletions docs-site/src/content/docs/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,16 @@ reference/fallback config. On loopback it contains the root keys you can merge m
injection was removed; on non-loopback it contains the dedicated provider form. External-provider
mode leaves this profile untouched.

Rebuilding that file keeps the plain root keys OpenCodex does not manage, so a setting you add such as
`stream_idle_timeout_ms` or `stream_max_retries` survives the next injection. Each kept assignment is
copied exactly as written, including values that span several lines and 64-bit integers, and is placed
above the first table. Keys inside tables and dotted root keys such as `a.b = 1` are not kept.
OpenCodex wins every collision: the root keys it owns (`model_provider`, `model_catalog_json`,
`openai_base_url`) are rewritten for the routing mode in use, and a root key named like a table the
profile writes, such as an inline `features = { ... }` when the profile writes `[features]`, is
dropped. If the file changes while an injection waits for the write lock, the injection stops with a
retryable error and leaves your edit in place.

:::caution
Root keys such as `openai_base_url`, `model_provider`, and `model_catalog_json` **must** sit before the
first `[table]` header. The injector guarantees that placement, removes its own stale/duplicate
Expand Down Expand Up @@ -760,6 +770,12 @@ Codex. Native custom calls and converted function calls use the same completion
patch previews are held while their executable form is unresolved. JavaScript that merely
contains patch text and unrelated native custom payloads stay unchanged.

When a routed model double-wraps an executable freeform body, opencodex removes one extra
JSON object containing only an input string. This repair applies to local exec and apply_patch
bodies, leaves other tool grammars and ambiguous objects unchanged, and does not decode recursively.
A body holds its streamed preview only while it can still turn out to be such a wrapper;
JavaScript that merely starts with an object or block keeps streaming as it arrives.

A routed model can also mistakenly send a shell-argument object such as
`{"cmd":"git status --short"}` to code-mode `exec`. For a verified code-mode catalog,
opencodex converts an unambiguous shell object into `tools.exec_command(...)` JavaScript
Expand Down
12 changes: 12 additions & 0 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,8 @@ If Kiro ends with plain text instead of its private final-answer tool, one bound
still runs, and only the resulting final answer is displayed. Progress accompanying a real
tool call remains visible. A normal private final answer needs no completion retry.

When Kiro's safety filter stops a turn (`CONTENT_FILTERED`, for example the Claude `BIO` classifier), the request ends as a refusal that clients do not retry: Claude clients see `stop_reason: "refusal"` and Codex sees a failed response carrying Kiro's category and explanation. If the filter stops the bounded retry, no final answer is displayed; the progress held from the first attempt and any partial text from the retry are shown as commentary before the refusal.

When Kiro emits credit metering, request logs preserve the reported spend as
`usage.providerCredits`, including in the persisted usage ledger. These are Kiro credits;
token counts may still be estimated, and the credit value does not replace USD cost estimates.
Expand Down Expand Up @@ -1837,6 +1839,16 @@ Google Antigravity, OpenCode Go, OpenRouter, DeepSeek, ClinePass, Z.AI, MiniMax,
Moonshot, Venice, Synthetic, DeepInfra, Neuralwatt, Command Code, and any a6api-backed
or Abliteration custom provider.

**Kimi Coding Plan quota.** Account login and API-key providers on the canonical
`https://api.kimi.com/coding/v1` endpoint read `/usages`. Plans that report
`usages.limit_month_total` (or `monthTotal`) show a monthly utilization bar, with
`limit_month_code` (or `monthCode`) as the fallback when total usage is unavailable.
The `used_ratio` / `usedRatio` fraction must be in `[0, 1]` before conversion to a consumed
percentage; invalid ratios are ignored. Empty or unusable `usages` containers do not hide
usable monthly data in another supported envelope. Any reported reset time is retained.
Existing 5-hour, weekly, and total subscription-credit
windows remain separate, and an absent monthly window is not shown as 0%.

**Abliteration credits.** A provider of any name whose `baseUrl` is
`https://api.abliteration.ai` or `https://api.abliteration.ai/v1` reads
`GET https://api.abliteration.ai/v1/credits` with its active key as a Bearer token and does not
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/ja/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ env_key = "OPENCODEX_API_AUTH_TOKEN"

OpenCodex がルーティングを所有している場合、どちらのモードも参照/フォールバック設定として `$CODEX_HOME/opencodex.config.toml` を書き込みます。ループバックでは、自動挿入が削除された場合に手動でマージできるルート キーが含まれています。非ループバックでは、専用のプロバイダー フォームが含まれます。外部プロバイダー モードでは、このプロファイルは変更されません。

このファイルを再生成しても、OpenCodex が管理しない単純なルート キーは保持されます。そのため、`stream_idle_timeout_ms` や `stream_max_retries` のように追加した設定は次の挿入後も残ります。保持される代入は、複数行にわたる値や 64 ビット整数も含めて書かれたとおりにコピーされ、最初のテーブルより前に置かれます。テーブル内のキーと、`a.b = 1` のようなドット付きルート キーは保持されません。衝突した場合は常に OpenCodex が優先されます。OpenCodex が所有するルート キー(`model_provider`、`model_catalog_json`、`openai_base_url`)は使用中のルーティング モードに合わせて書き直され、プロファイルが書き込むテーブルと同じ名前のルート キー(プロファイルが `[features]` を書き込むときのインライン `features = { ... }` など)は削除されます。挿入が書き込みロックを待っている間にファイルが変更された場合、挿入は再試行可能なエラーで停止し、編集内容はそのまま残ります。

:::caution
`openai_base_url`、`model_provider`、`model_catalog_json` などのルート キーは、最初の `[table]` ヘッダーの前に**なければなりません**。インジェクターはその配置を保証し、それ自身の古い/重複したコピーを削除し、ユーザー所有のルート `openai_base_url` を決して上書きしません。存在する場合、sync はカタログを更新しますが、ルーティングが挿入されなかったことを報告します。
:::
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/ja/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ocx start --socks5-off

### `ocx stop`

監督プロセスのない Link Child は終了シグナル時、各書き込みで接続を再確認し、リスナーを閉じる前に Codex と管理対象 Grok を復元します。サービス・Desktop、sibling、再起動の引き継ぎ、親 stop 記録がある場合は設定を保持します。終了中の再起動は `409 runtime_stopping` です。強制終了はシグナル処理を省略する場合があり、親 `ocx stop` の復元も必要です。

実行中のプロキシを (PID によって) 停止し、PID ファイルを削除します。スタンドアロンの所有者ではネイティブ Codex を復元します。マネージド バックグラウンド サービスがインストールされている場合、`ocx stop` はそれを最初に停止するため、プロキシを再起動できません。Web ダッシュボードの **停止** ボタンは同じ処理 (`POST /api/stop`) を実行しますが、Windows タスク スケジューラだけは例外です。タスク終了後もラッパーがプロキシを再起動しうるため、ダッシュボードは `respawnable_service` で拒否し、何も変更せずに `ocx stop` の実行を促します。

接続済みの hub クライアントでは、`ocx stop`(成功した API 停止を含む)は接続が所有する Codex のルーティング、モデルカタログ、Grok 設定を保持します。`ocx start` はルーティングを再注入せず、その設定で再び処理します。Codex を自身のアカウントへ戻すには `ocx disconnect`、既にネイティブルーティングへ戻した後の再適用には `ocx sync --restart-codex` を使います。
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/ko/guides/codex-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ env_key = "OPENCODEX_API_AUTH_TOKEN"

OpenCodex가 라우팅을 소유할 때는 두 모드 모두 `$CODEX_HOME/opencodex.config.toml`을 참고용/폴백 설정으로 작성합니다. loopback에서는 자동 주입이 사라졌을 때 수동으로 합칠 수 있는 root key가 들어가고, non-loopback에서는 전용 provider 형식이 들어갑니다. 외부 provider 모드는 이 프로필을 건드리지 않습니다.

이 파일을 다시 만들 때 OpenCodex가 관리하지 않는 일반 root key는 그대로 남습니다. 그래서 `stream_idle_timeout_ms`나 `stream_max_retries`처럼 직접 추가한 설정은 다음 주입 뒤에도 유지됩니다. 남는 대입문은 여러 줄에 걸친 값과 64비트 정수까지 작성한 그대로 복사되고, 첫 번째 테이블보다 앞에 놓입니다. 테이블 안의 키와 `a.b = 1` 같은 점 표기 root key는 남지 않습니다. 충돌하면 항상 OpenCodex 쪽이 이깁니다. OpenCodex가 소유한 root key(`model_provider`, `model_catalog_json`, `openai_base_url`)는 현재 라우팅 모드에 맞게 다시 쓰이고, 프로필이 쓰는 테이블과 이름이 같은 root key(프로필이 `[features]`를 쓸 때의 인라인 `features = { ... }` 등)는 버려집니다. 주입이 쓰기 잠금을 기다리는 동안 파일이 바뀌면 주입은 재시도 가능한 오류로 멈추고 수정한 내용은 그대로 둡니다.

:::caution
`openai_base_url`, `model_provider`, `model_catalog_json` 같은 root key는 첫 번째 `[table]` 헤더보다 **반드시** 앞에 있어야 합니다. 인젝터는 그 위치를 보장하고, 자신이 남긴 오래되었거나 중복된 복사본은 지웁니다. 사용자가 소유한 root `openai_base_url`은 덮어쓰지 않습니다. 그런 값이 있으면 sync는 카탈로그만 갱신하고 라우팅은 주입하지 않았다고 알립니다.
:::
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/ko/reference/cli/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ ocx start --socks5-off

### `ocx stop`

감독 프로세스 없이 실행되는 Link Child는 종료 신호 처리 시 각 쓰기 직전에 연결을 재확인하고 리스너를 닫기 전에 Codex 기본 설정과 관리 Grok 설정을 복원합니다. 서비스·Desktop 감독, sibling, 재시작·재활용 인계, 부모 stop 영수증이 있으면 설정을 보존합니다. 종료 중 재시작 요청은 `409 runtime_stopping`입니다. 강제 종료는 신호 처리를 건너뛸 수 있어 부모 `ocx stop`의 복원도 필요합니다.

실행 중인 프록시를 PID 기준으로 중지하고 PID 파일을 삭제합니다. 독립 실행 소유자라면 기본 Codex를 복원합니다. 관리형
백그라운드 서비스가 설치되어 있으면 `ocx stop`이 먼저 그 서비스를 중지하므로 프록시가 다시
올라올 수 없습니다. 웹 대시보드의 **Stop** 버튼도 같은 동작(`POST /api/stop`)을 하지만, Windows 작업 스케줄러는 예외입니다. 작업이 끝나도 래퍼가 프록시를 다시 띄울 수 있어서, 대시보드는 `respawnable_service`로 거절하고 아무것도 바꾸지 않은 채 `ocx stop` 실행을 안내합니다.
Expand Down
2 changes: 2 additions & 0 deletions docs-site/src/content/docs/reference/adapters.md
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,8 @@ real client tool call keeps the turn open. A completion-tool answer is always em
`final_answer`, even when it exactly repeats prior commentary, because phase correctness is more
important than cosmetic de-duplication. Tool-free requests retain normal text completion behavior.

The continuation's instruction tells the model that its ordinary text has not reached the user, and asks it to call `codex_kiro_final_answer` with the complete final answer if the task is complete, submitting its previous reply unchanged when that reply already was the answer. A model that answered a trivial request in plain text therefore keeps its answer, instead of being told to continue a task it had already finished.

### Reasoning effort

The GPT-5.6 family uses `additionalModelRequestFields.reasoning.effort`; `claude-opus-5`
Expand Down
Loading
Loading