summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorDanny Milosavljevic <dannym@friendly-machines.com>2026-03-14 20:05:44 +0100
committerDanny Milosavljevic <dannym@friendly-machines.com>2026-03-14 21:51:16 +0100
commitafa8b9ae47a43b6e696328b99bfc0e8a970cde00 (patch)
tree1e67076b9225818ccc89c9f050fb74a6a9875343 /gnu
parented9e7345183c30b811bb3d2788495aab17d00b33 (diff)
gnu: Fix module cycle.
Fixes: guix/guix#7159 * gnu/packages/rust-sources.scm (codex, codex-acp): Move to... * gnu/packages/codex.scm (codex, codex-acp): ...here. * gnu/local.mk (GNU_SYSTEM_MODULES): Add file. Change-Id: Ic158d97cb9f97655a72ea58d16adb102dbe4d5ea
Diffstat (limited to 'gnu')
-rw-r--r--gnu/local.mk1
-rw-r--r--gnu/packages/codex.scm411
-rw-r--r--gnu/packages/rust-apps.scm365
3 files changed, 412 insertions, 365 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 52324514d50..56791554e34 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -213,6 +213,7 @@ GNU_SYSTEM_MODULES = \
213 %D%/packages/connman.scm \ 213 %D%/packages/connman.scm \
214 %D%/packages/containers.scm \ 214 %D%/packages/containers.scm \
215 %D%/packages/convmv.scm \ 215 %D%/packages/convmv.scm \
216 %D%/packages/codex.scm \
216 %D%/packages/coq.scm \ 217 %D%/packages/coq.scm \
217 %D%/packages/cpio.scm \ 218 %D%/packages/cpio.scm \
218 %D%/packages/cpp.scm \ 219 %D%/packages/cpp.scm \
diff --git a/gnu/packages/codex.scm b/gnu/packages/codex.scm
new file mode 100644
index 00000000000..70f8bafd7d8
--- /dev/null
+++ b/gnu/packages/codex.scm
@@ -0,0 +1,411 @@
1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2026 Danny Milosavljevic <dannym@friendly-machines.com>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19;;; This module is separate from (gnu packages rust-apps) to avoid a
20;;; circular module dependency: (gnu packages rust-sources), which
21;;; defines rust-codex-0.98.0, transitively loads (gnu packages
22;;; rust-apps) through its #:use-module chain. If the codex package
23;;; lived in rust-apps.scm, loading rust-sources would trigger loading
24;;; rust-apps before rust-codex-0.98.0 is defined, causing an unbound
25;;; variable error.
26
27(define-module (gnu packages codex)
28 #:use-module ((guix licenses) #:prefix license:)
29 #:use-module (guix gexp)
30 #:use-module (guix packages)
31 #:use-module (guix download)
32 #:use-module (guix git-download)
33 #:use-module (guix build-system cargo)
34 #:use-module (gnu packages)
35 #:use-module (gnu packages bash)
36 #:use-module (gnu packages base)
37 #:use-module (gnu packages cmake)
38 #:use-module (gnu packages compression)
39 #:use-module (gnu packages libunwind)
40 #:use-module (gnu packages llvm)
41 #:use-module (gnu packages perl)
42 #:use-module (gnu packages pkg-config)
43 #:use-module (gnu packages python)
44 #:use-module (gnu packages rust-sources)
45 #:use-module (gnu packages sqlite)
46 #:use-module (gnu packages tls)
47 #:use-module (gnu packages version-control))
48
49(define-public codex
50 (package
51 (name "codex")
52 (version (package-version rust-codex-0.98.0))
53 (source
54 (origin
55 (inherit (package-source rust-codex-0.98.0))
56 (patches (search-patches
57 "codex-0.98.0-remove-patch-sections.patch"
58 "rust-codex-0.98.0-test-shebangs.patch"
59 "rust-codex-0.98.0-test-timeout.patch"))))
60 (build-system cargo-build-system)
61 (arguments
62 (list
63 #:install-source? #f
64 #:cargo-install-paths '(list "cli" "exec" "exec-server"
65 "linux-sandbox" "mcp-server" "network-proxy"
66 "app-server" "tui")
67 ;; schema_fixtures_match_generated (upstream fixture is stale:
68 ;; FileChange::Update in codex-protocol gained old_content,
69 ;; new_content, move_path fields but the committed JSON schema
70 ;; fixture was not regenerated).
71 #:cargo-test-flags '(list "--workspace"
72 "--exclude" "codex-app-server-protocol"
73 "--"
74 ;; These tests exercise sandbox denial and
75 ;; escalation, which requires Landlock to
76 ;; cleanly deny filesystem access. Inside the
77 ;; build container Landlock returns NotEnforced
78 ;; and the sandbox binary panics instead.
79 ;; Disabling Landlock would not help either,
80 ;; since these tests need a working sandbox to
81 ;; have anything to deny and escalate.
82 "--skip" "sandbox_denied_shell_returns_original_output"
83 "--skip" "shell_escalated_permissions_rejected_then_ok"
84 "--skip" "unified_exec_runs_under_sandbox"
85 ;; These tests (in codex-exec) directly call
86 ;; spawn_command_under_linux_sandbox to verify
87 ;; that python and bash work correctly inside
88 ;; the Landlock sandbox. The sandbox binary
89 ;; (codex-exec) panics with LandlockRestrict
90 ;; (exit code 101) before the inner command
91 ;; even starts.
92 "--skip" "python_getpwuid_works_under_sandbox"
93 "--skip" "python_multiprocessing_lock_works_under_sandbox"
94 "--skip" "sandbox_distinguishes_command_and_policy_cwds"
95 ;; These linux-sandbox tests directly invoke
96 ;; the Landlock sandbox via
97 ;; process_exec_tool_call; same root cause.
98 "--skip" "test_writable_root"
99 "--skip" "test_timeout"
100 "--skip" "test_root_read"
101 "--skip" "test_dev_null_write"
102 "--skip" "test_no_new_privs_is_enabled"
103 ;; This test iterates many approval scenarios;
104 ;; one of them
105 ;; (danger_full_access_on_request_allows_network)
106 ;; runs a command through the Landlock sandbox
107 ;; binary, which panics with LandlockRestrict
108 ;; inside the build container. Cargo --skip
109 ;; cannot target individual scenarios, so we
110 ;; skip the entire matrix.
111 "--skip" "approval_matrix_covers_all_modes"
112 ;; This test verifies session-level patch
113 ;; approval caching: approve once, skip
114 ;; future prompts for the same file. When
115 ;; Landlock is unavailable (as in the Guix
116 ;; build container) the sandbox binary panics,
117 ;; triggering the escalation-retry path, which
118 ;; interferes with the approval cache and
119 ;; causes a spurious re-prompt on the second
120 ;; patch.
121 "--skip" "approving_apply_patch_for_session_skips_future_prompts_for_same_file"
122 ;; These tests expect to interrupt a
123 ;; long-running 'sleep 60' and receive
124 ;; TurnAborted. Default test config is
125 ;; OnRequest + ReadOnly. What happens:
126 ;;
127 ;; 1. ReadOnly wraps the command with
128 ;; codex-linux-sandbox (Landlock-based).
129 ;; 2. Landlock is unavailable in the Guix
130 ;; build container, so the sandbox
131 ;; binary exits instantly (~1 ms).
132 ;; 3. Orchestrator gets SandboxErr::Denied.
133 ;; wants_no_sandbox_approval(OnRequest)
134 ;; returns false (sandboxing.rs:222),
135 ;; so no escalation -- denial returned
136 ;; directly.
137 ;; 4. ToolEmitter::finish sends the error
138 ;; to the mock model as
139 ;; function_call_output.
140 ;; 5. Second mock SSE response fires,
141 ;; turn finishes with TurnComplete.
142 ;; 6. Op::Interrupt arrives 100 ms later,
143 ;; but the turn is already done --
144 ;; TurnAborted is never emitted,
145 ;; test times out.
146 ;;
147 ;; The similar interrupt_long_running_tool_
148 ;; emits_turn_aborted passes because it
149 ;; sends the interrupt with no delay and
150 ;; has only one mock response (so the turn
151 ;; cannot complete first).
152 "--skip" "interrupt_persists_turn_aborted_marker_in_next_request"
153 "--skip" "interrupt_tool_records_history_entries"
154 ;; Upstream bug: test hardcodes "0.0.0" in the
155 ;; expected user-agent string but the workspace
156 ;; version is "0.98.0".
157 "--skip" "get_user_agent_returns_current_codex_user_agent"
158 ;; Same upstream bug: mcp-server tests
159 ;; check the initialize response which
160 ;; includes "version": "0.0.0" but the
161 ;; server returns "0.98.0".
162 "--skip" "test_codex_tool_passes_base_instructions"
163 "--skip" "test_shell_command_approval_triggers_elicitation"
164 "--skip" "test_patch_approval_triggers_elicitation"
165 ;; These codex-exec-server tests need
166 ;; "dotslash", a Meta tool that lazily
167 ;; downloads pre-built binaries from a
168 ;; JSON manifest. The test helper
169 ;; create_transport runs
170 ;; `dotslash -- fetch <path>` to obtain a
171 ;; custom bash binary described in
172 ;; exec-server/tests/suite/bash.
173 ;; dotslash is not available in the build
174 ;; container.
175 "--skip" "list_tools"
176 "--skip" "accept_elicitation_for_prompt_rule"
177 ;;; Test isolation bug: each test in
178 ;;; state/src/runtime.rs calls
179 ;;; unique_temp_dir() to get its own
180 ;;; temporary directory (and thus its
181 ;;; own SQLite database). That function
182 ;;; names directories using the current
183 ;;; nanosecond timestamp, so when tests
184 ;;; run in parallel several can receive
185 ;;; the same name and open the same
186 ;;; database. The initial SQLite
187 ;;; migration runs CREATE TABLE threads
188 ;;; (without IF NOT EXISTS), so any init
189 ;;; after the first panics with "table
190 ;;; threads already exists". Any of
191 ;;; these tests
192 ;;; can be the victim.
193 "--skip" "init_removes_legacy_state_db_files"
194 "--skip" "upsert_and_get_thread_memory"
195 "--skip" "get_last_n_thread_memories_for_cwd_matches_exactly"
196 "--skip" "upsert_thread_memory_errors_for_unknown_thread"
197 "--skip" "get_last_n_thread_memories_for_cwd_zero_returns_empty"
198 "--skip" "get_last_n_thread_memories_for_cwd_does_not_prefix_match"
199 "--skip" "deleting_thread_cascades_thread_memory")
200 #:cargo-package-crates
201 ''(;;; Tier 0: No internal deps.
202 "codex-async-utils"
203 "codex-client"
204 "codex-execpolicy"
205 "codex-file-search"
206 "codex-git"
207 "codex-keyring-store"
208 "codex-utils-absolute-path"
209 "codex-utils-cache"
210 "codex-utils-cargo-bin"
211 "codex-utils-home-dir"
212 "codex-utils-json-to-toml"
213 "codex-utils-pty"
214 "codex-utils-readiness"
215 "codex-utils-string"
216 "codex-backend-openapi-models"
217 "codex-process-hardening"
218 "codex-ansi-escape"
219 ;;; Tier 1: Depends on tier 0.
220 "codex-utils-image"
221 "codex-apply-patch"
222 "codex-protocol"
223 "codex-windows-sandbox"
224 "codex-api"
225 "codex-experimental-api-macros"
226 "codex-secrets"
227 "codex-execpolicy-legacy"
228 "codex-debug-client"
229 ;;; Tier 2.
230 "codex-app-server-protocol"
231 "codex-rmcp-client"
232 "codex-otel"
233 "codex-state"
234 "codex-core"
235 "codex-linux-sandbox"
236 "codex-feedback"
237 ;;; Tier 3.
238 "codex-arg0"
239 "codex-lmstudio"
240 "codex-login"
241 "codex-ollama"
242 "codex-common"
243 "codex-mcp-server"
244 "codex-backend-client"
245 "codex-responses-api-proxy"
246 ;;; Tier 4.
247 "codex-cloud-requirements"
248 "codex-exec"
249 "codex-exec-server"
250 "codex-stdio-to-uds"
251 "codex-network-proxy"
252 "codex-chatgpt"
253 "codex-cloud-tasks-client"
254 ;;; Tier 5.
255 "codex-app-server"
256 "codex-app-server-test-client"
257 "codex-tui"
258 ;;; Tier 6.
259 "codex-cloud-tasks"
260 ;; The main executable.
261 "codex-cli")
262 #:phases
263 #~(modify-phases %standard-phases
264 (add-after 'unpack 'chdir-to-workspace
265 (lambda _
266 (chdir "codex-rs")))
267 (add-after 'chdir-to-workspace 'update-version-in-snapshots
268 (lambda _
269 ;; Snapshot test files contain hardcoded v0.0.0 version strings.
270 ;; Update them to match the actual package version.
271 (let ((snap-files (find-files "." "\\.snap$")))
272 (substitute* snap-files
273 (("\\(v0\\.0\\.0\\) ") "(v0.98.0)")))))
274 (add-after 'chdir-to-workspace 'patch-git-deps-to-vendor
275 (lambda _
276 ;; Replace git dependencies with version references so cargo
277 ;; resolves them from the vendored sources.
278 (substitute* "Cargo.toml"
279 (("nucleo = \\{ git = [^}]+\\}")
280 "nucleo = \"0.5.0\"")
281 (("runfiles = \\{ git = [^}]+\\}")
282 "runfiles = \"0.1.0\""))))
283 (add-after 'chdir-to-workspace 'add-version-to-workspace-deps
284 (lambda _
285 ;; cargo package requires all dependencies to have versions.
286 ;; cargo package requires all dependencies to have versions.
287 ;; Add version = "0.98.0" to internal path dependencies.
288 (let ((cargo-files (find-files "." "^Cargo\\.toml$")))
289 (substitute* cargo-files
290 ;; Handle inline deps: name = { path = "..." }
291 (("(codex-[a-z0-9-]+) = \\{ path = " all name)
292 (string-append name " = { version = \"0.98.0\", path = "))
293 ;; Handle inline deps with package: name = { package = "...", path = "..." }
294 (("(codex-[a-z0-9-]+) = \\{ package = " all name)
295 (string-append name " = { version = \"0.98.0\", package = "))
296 ;; Handle section deps: [dependencies.X] with path = "..."
297 (("^(path = \"\\.\\./[^\"]*\")" all path-line)
298 (string-append path-line "\nversion = \"0.98.0\""))))))
299 (add-after 'chdir-to-workspace 'patch-hardcoded-paths
300 (lambda* (#:key inputs #:allow-other-keys)
301 (let ((bash-bin (string-append
302 (assoc-ref inputs "bash-minimal") "/bin"))
303 (coreutils-bin (string-append
304 (assoc-ref inputs "coreutils") "/bin"))
305 (git-bin (string-append
306 (assoc-ref inputs "git-minimal") "/bin"))
307 (sed-bin (string-append
308 (assoc-ref inputs "sed") "/bin"))
309 ;; Include .policy files: the execpolicy-legacy
310 ;; crate embeds default.policy via include_str!
311 ;; at compile time, so its paths must also be
312 ;; patched.
313 (rs-files (find-files "." "\\.(rs|policy)$")))
314 (substitute* rs-files
315 (("\"/bin/bash\"")
316 (string-append "\"" bash-bin "/bash\""))
317 (("\"/bin/sh\"")
318 (string-append "\"" bash-bin "/sh\""))
319 (("\"/usr/bin/bash\"")
320 (string-append "\"" bash-bin "/bash\""))
321 (("\"/usr/bin/sh\"")
322 (string-append "\"" bash-bin "/sh\""))
323 ;;; bash/sh with inline arguments, e.g. "/bin/bash -i".
324 (("\"/bin/bash ")
325 (string-append "\"" bash-bin "/bash "))
326 (("\"/bin/sh ")
327 (string-append "\"" bash-bin "/sh "))
328 ;; coreutils.
329 (("\"/bin/(cat|cp|date|echo|head|ls|rm|sleep|true|touch)\"" all cmd)
330 (string-append "\"" coreutils-bin "/" cmd "\""))
331 ;; coreutils.
332 (("\"/usr/bin/(cat|cp|head|ls|touch|true)\"" all cmd)
333 (string-append "\"" coreutils-bin "/" cmd "\""))
334 ;; coreutils with inline arguments
335 ;; like "/bin/echo END-EVENT".
336 (("\"/bin/(cat|cp|date|echo|head|ls|rm|sleep|true|touch) " all cmd)
337 (string-append "\"" coreutils-bin "/" cmd " "))
338 (("\"/usr/bin/git\"")
339 (string-append "\"" git-bin "/git\""))
340 (("\"/usr/bin/sed\"")
341 (string-append "\"" sed-bin "/sed\"")))
342 ;; @SHELL@ placeholder from test-shebangs patch
343 (substitute*
344 (list "rmcp-client/src/program_resolver.rs"
345 "tui/src/external_editor.rs")
346 (("@SHELL@")
347 (string-append bash-bin "/sh")))
348 ;; shebang in test-only file
349 (substitute*
350 "core/tests/suite/user_notification.rs"
351 (("#!/bin/bash")
352 (string-append "#!" bash-bin "/bash"))))))
353 (add-before 'check 'set-home
354 (lambda _
355 (setenv "HOME" "/tmp")
356 (setenv "USER" "nixbld"))))))
357 (native-inputs (list clang ;bindgen uses libclang to parse BoringSSL's C headers
358 cmake-minimal ;BoringSSL is compiled from C source
359 libunwind ;BoringSSL tests verify stack unwinding in assembly
360 perl python-minimal ;for tests
361 pkg-config))
362 (inputs (cons* bash-minimal coreutils git-minimal sed
363 openssl sqlite `(,zstd "lib")
364 (cargo-inputs 'codex)))
365 (home-page "https://github.com/openai/codex")
366 (synopsis "AI-assisted coding CLI and TUI")
367 (description
368 "Codex is an AI-powered coding assistant that runs in the terminal.
369It provides an interactive TUI for conversations with AI models, with
370support for shell command execution, file editing, and code generation.
371Configure providers via @file{~/.codex/config.toml}.")
372 (license license:asl2.0)))
373
374(define-public codex-acp
375 (package
376 (name "codex-acp")
377 (version "0.9.2")
378 (source
379 (origin
380 (method git-fetch)
381 (uri (git-reference
382 (url "https://github.com/zed-industries/codex-acp")
383 (commit (string-append "v" version))))
384 (file-name (git-file-name name version))
385 (sha256
386 (base32 "190sq6s6jfz8dkj1y8305r7x6ln86qqr2j1bnfjci7f1x2wyzmsj"))
387 (patches (search-patches "codex-acp-0.9.2-remove-patch-sections.patch"
388 "codex-acp-0.9.2-replace-result-flatten.patch"))))
389 (build-system cargo-build-system)
390 (arguments
391 (list
392 #:install-source? #f
393 #:phases
394 #~(modify-phases %standard-phases
395 (add-after 'unpack 'patch-codex-deps
396 (lambda _
397 ;; Rewrite git dependencies to use vendored sources from rust-codex
398 (substitute* "Cargo.toml"
399 (("git = \"https://github.com/zed-industries/codex\", branch = \"acp\"")
400 "version = \"0.0.0\"")))))))
401 (native-inputs (list pkg-config))
402 (inputs (cons* openssl sqlite `(,zstd "lib") (cargo-inputs 'codex-acp)))
403 (home-page "https://github.com/zed-industries/codex-acp")
404 (synopsis "ACP-compatible agent bridging Zed Codex with ACP clients")
405 (description
406 "This package provides an Agent Client Protocol (ACP) compatible agent
407that bridges the Zed Codex runtime with ACP clients over stdio. It
408supports multiple LLM providers through configuration in
409@file{~/.codex/config.toml} and integrates with MCP servers for filesystem
410operations.")
411 (license license:asl2.0)))
diff --git a/gnu/packages/rust-apps.scm b/gnu/packages/rust-apps.scm
index 8c05d01ffab..b165539848c 100644
--- a/gnu/packages/rust-apps.scm
+++ b/gnu/packages/rust-apps.scm
@@ -125,7 +125,6 @@
125 #:use-module (gnu packages python-xyz) 125 #:use-module (gnu packages python-xyz)
126 #:use-module (gnu packages ruby-xyz) 126 #:use-module (gnu packages ruby-xyz)
127 #:use-module (gnu packages rust) 127 #:use-module (gnu packages rust)
128 #:use-module (gnu packages rust-sources)
129 #:use-module (gnu packages security-token) 128 #:use-module (gnu packages security-token)
130 #:use-module (gnu packages sqlite) 129 #:use-module (gnu packages sqlite)
131 #:use-module (gnu packages terminals) 130 #:use-module (gnu packages terminals)
@@ -837,370 +836,6 @@ Commit and SemVer specifications.")
837 "This package provides CLI Tool for codeberg similar to gh and glab.") 836 "This package provides CLI Tool for codeberg similar to gh and glab.")
838 (license license:agpl3+))) 837 (license license:agpl3+)))
839 838
840(define-public codex
841 (package
842 (name "codex")
843 (version (package-version rust-codex-0.98.0))
844 (source
845 (origin
846 (inherit (package-source rust-codex-0.98.0))
847 (patches (search-patches
848 "codex-0.98.0-remove-patch-sections.patch"
849 "rust-codex-0.98.0-test-shebangs.patch"
850 "rust-codex-0.98.0-test-timeout.patch"))))
851 (build-system cargo-build-system)
852 (arguments
853 (list
854 #:install-source? #f
855 #:cargo-install-paths '(list "cli" "exec" "exec-server"
856 "linux-sandbox" "mcp-server" "network-proxy"
857 "app-server" "tui")
858 ;; schema_fixtures_match_generated (upstream fixture is stale:
859 ;; FileChange::Update in codex-protocol gained old_content,
860 ;; new_content, move_path fields but the committed JSON schema
861 ;; fixture was not regenerated).
862 #:cargo-test-flags '(list "--workspace"
863 "--exclude" "codex-app-server-protocol"
864 "--"
865 ;; These tests exercise sandbox denial and
866 ;; escalation, which requires Landlock to
867 ;; cleanly deny filesystem access. Inside the
868 ;; build container Landlock returns NotEnforced
869 ;; and the sandbox binary panics instead.
870 ;; Disabling Landlock would not help either,
871 ;; since these tests need a working sandbox to
872 ;; have anything to deny and escalate.
873 "--skip" "sandbox_denied_shell_returns_original_output"
874 "--skip" "shell_escalated_permissions_rejected_then_ok"
875 "--skip" "unified_exec_runs_under_sandbox"
876 ;; These tests (in codex-exec) directly call
877 ;; spawn_command_under_linux_sandbox to verify
878 ;; that python and bash work correctly inside
879 ;; the Landlock sandbox. The sandbox binary
880 ;; (codex-exec) panics with LandlockRestrict
881 ;; (exit code 101) before the inner command
882 ;; even starts.
883 "--skip" "python_getpwuid_works_under_sandbox"
884 "--skip" "python_multiprocessing_lock_works_under_sandbox"
885 "--skip" "sandbox_distinguishes_command_and_policy_cwds"
886 ;; These linux-sandbox tests directly invoke
887 ;; the Landlock sandbox via
888 ;; process_exec_tool_call; same root cause.
889 "--skip" "test_writable_root"
890 "--skip" "test_timeout"
891 "--skip" "test_root_read"
892 "--skip" "test_dev_null_write"
893 "--skip" "test_no_new_privs_is_enabled"
894 ;; This test iterates many approval scenarios;
895 ;; one of them
896 ;; (danger_full_access_on_request_allows_network)
897 ;; runs a command through the Landlock sandbox
898 ;; binary, which panics with LandlockRestrict
899 ;; inside the build container. Cargo --skip
900 ;; cannot target individual scenarios, so we
901 ;; skip the entire matrix.
902 "--skip" "approval_matrix_covers_all_modes"
903 ;; This test verifies session-level patch
904 ;; approval caching: approve once, skip
905 ;; future prompts for the same file. When
906 ;; Landlock is unavailable (as in the Guix
907 ;; build container) the sandbox binary panics,
908 ;; triggering the escalation-retry path, which
909 ;; interferes with the approval cache and
910 ;; causes a spurious re-prompt on the second
911 ;; patch.
912 "--skip" "approving_apply_patch_for_session_skips_future_prompts_for_same_file"
913 ;; These tests expect to interrupt a
914 ;; long-running 'sleep 60' and receive
915 ;; TurnAborted. Default test config is
916 ;; OnRequest + ReadOnly. What happens:
917 ;;
918 ;; 1. ReadOnly wraps the command with
919 ;; codex-linux-sandbox (Landlock-based).
920 ;; 2. Landlock is unavailable in the Guix
921 ;; build container, so the sandbox
922 ;; binary exits instantly (~1 ms).
923 ;; 3. Orchestrator gets SandboxErr::Denied.
924 ;; wants_no_sandbox_approval(OnRequest)
925 ;; returns false (sandboxing.rs:222),
926 ;; so no escalation -- denial returned
927 ;; directly.
928 ;; 4. ToolEmitter::finish sends the error
929 ;; to the mock model as
930 ;; function_call_output.
931 ;; 5. Second mock SSE response fires,
932 ;; turn finishes with TurnComplete.
933 ;; 6. Op::Interrupt arrives 100 ms later,
934 ;; but the turn is already done --
935 ;; TurnAborted is never emitted,
936 ;; test times out.
937 ;;
938 ;; The similar interrupt_long_running_tool_
939 ;; emits_turn_aborted passes because it
940 ;; sends the interrupt with no delay and
941 ;; has only one mock response (so the turn
942 ;; cannot complete first).
943 "--skip" "interrupt_persists_turn_aborted_marker_in_next_request"
944 "--skip" "interrupt_tool_records_history_entries"
945 ;; Upstream bug: test hardcodes "0.0.0" in the
946 ;; expected user-agent string but the workspace
947 ;; version is "0.98.0".
948 "--skip" "get_user_agent_returns_current_codex_user_agent"
949 ;; Same upstream bug: mcp-server tests
950 ;; check the initialize response which
951 ;; includes "version": "0.0.0" but the
952 ;; server returns "0.98.0".
953 "--skip" "test_codex_tool_passes_base_instructions"
954 "--skip" "test_shell_command_approval_triggers_elicitation"
955 "--skip" "test_patch_approval_triggers_elicitation"
956 ;; These codex-exec-server tests need
957 ;; "dotslash", a Meta tool that lazily
958 ;; downloads pre-built binaries from a
959 ;; JSON manifest. The test helper
960 ;; create_transport runs
961 ;; `dotslash -- fetch <path>` to obtain a
962 ;; custom bash binary described in
963 ;; exec-server/tests/suite/bash.
964 ;; dotslash is not available in the build
965 ;; container.
966 "--skip" "list_tools"
967 "--skip" "accept_elicitation_for_prompt_rule"
968 ;;; Test isolation bug: each test in
969 ;;; state/src/runtime.rs calls
970 ;;; unique_temp_dir() to get its own
971 ;;; temporary directory (and thus its
972 ;;; own SQLite database). That function
973 ;;; names directories using the current
974 ;;; nanosecond timestamp, so when tests
975 ;;; run in parallel several can receive
976 ;;; the same name and open the same
977 ;;; database. The initial SQLite
978 ;;; migration runs CREATE TABLE threads
979 ;;; (without IF NOT EXISTS), so any init
980 ;;; after the first panics with "table
981 ;;; threads already exists". Any of
982 ;;; these tests
983 ;;; can be the victim.
984 "--skip" "init_removes_legacy_state_db_files"
985 "--skip" "upsert_and_get_thread_memory"
986 "--skip" "get_last_n_thread_memories_for_cwd_matches_exactly"
987 "--skip" "upsert_thread_memory_errors_for_unknown_thread"
988 "--skip" "get_last_n_thread_memories_for_cwd_zero_returns_empty"
989 "--skip" "get_last_n_thread_memories_for_cwd_does_not_prefix_match"
990 "--skip" "deleting_thread_cascades_thread_memory")
991 #:cargo-package-crates
992 ''(;;; Tier 0: No internal deps.
993 "codex-async-utils"
994 "codex-client"
995 "codex-execpolicy"
996 "codex-file-search"
997 "codex-git"
998 "codex-keyring-store"
999 "codex-utils-absolute-path"
1000 "codex-utils-cache"
1001 "codex-utils-cargo-bin"
1002 "codex-utils-home-dir"
1003 "codex-utils-json-to-toml"
1004 "codex-utils-pty"
1005 "codex-utils-readiness"
1006 "codex-utils-string"
1007 "codex-backend-openapi-models"
1008 "codex-process-hardening"
1009 "codex-ansi-escape"
1010 ;;; Tier 1: Depends on tier 0.
1011 "codex-utils-image"
1012 "codex-apply-patch"
1013 "codex-protocol"
1014 "codex-windows-sandbox"
1015 "codex-api"
1016 "codex-experimental-api-macros"
1017 "codex-secrets"
1018 "codex-execpolicy-legacy"
1019 "codex-debug-client"
1020 ;;; Tier 2.
1021 "codex-app-server-protocol"
1022 "codex-rmcp-client"
1023 "codex-otel"
1024 "codex-state"
1025 "codex-core"
1026 "codex-linux-sandbox"
1027 "codex-feedback"
1028 ;;; Tier 3.
1029 "codex-arg0"
1030 "codex-lmstudio"
1031 "codex-login"
1032 "codex-ollama"
1033 "codex-common"
1034 "codex-mcp-server"
1035 "codex-backend-client"
1036 "codex-responses-api-proxy"
1037 ;;; Tier 4.
1038 "codex-cloud-requirements"
1039 "codex-exec"
1040 "codex-exec-server"
1041 "codex-stdio-to-uds"
1042 "codex-network-proxy"
1043 "codex-chatgpt"
1044 "codex-cloud-tasks-client"
1045 ;;; Tier 5.
1046 "codex-app-server"
1047 "codex-app-server-test-client"
1048 "codex-tui"
1049 ;;; Tier 6.
1050 "codex-cloud-tasks"
1051 ;; The main executable.
1052 "codex-cli")
1053 #:phases
1054 #~(modify-phases %standard-phases
1055 (add-after 'unpack 'chdir-to-workspace
1056 (lambda _
1057 (chdir "codex-rs")))
1058 (add-after 'chdir-to-workspace 'update-version-in-snapshots
1059 (lambda _
1060 ;; Snapshot test files contain hardcoded v0.0.0 version strings.
1061 ;; Update them to match the actual package version.
1062 (let ((snap-files (find-files "." "\\.snap$")))
1063 (substitute* snap-files
1064 (("\\(v0\\.0\\.0\\) ") "(v0.98.0)")))))
1065 (add-after 'chdir-to-workspace 'patch-git-deps-to-vendor
1066 (lambda _
1067 ;; Replace git dependencies with version references so cargo
1068 ;; resolves them from the vendored sources.
1069 (substitute* "Cargo.toml"
1070 (("nucleo = \\{ git = [^}]+\\}")
1071 "nucleo = \"0.5.0\"")
1072 (("runfiles = \\{ git = [^}]+\\}")
1073 "runfiles = \"0.1.0\""))))
1074 (add-after 'chdir-to-workspace 'add-version-to-workspace-deps
1075 (lambda _
1076 ;; cargo package requires all dependencies to have versions.
1077 ;; cargo package requires all dependencies to have versions.
1078 ;; Add version = "0.98.0" to internal path dependencies.
1079 (let ((cargo-files (find-files "." "^Cargo\\.toml$")))
1080 (substitute* cargo-files
1081 ;; Handle inline deps: name = { path = "..." }
1082 (("(codex-[a-z0-9-]+) = \\{ path = " all name)
1083 (string-append name " = { version = \"0.98.0\", path = "))
1084 ;; Handle inline deps with package: name = { package = "...", path = "..." }
1085 (("(codex-[a-z0-9-]+) = \\{ package = " all name)
1086 (string-append name " = { version = \"0.98.0\", package = "))
1087 ;; Handle section deps: [dependencies.X] with path = "..."
1088 (("^(path = \"\\.\\./[^\"]*\")" all path-line)
1089 (string-append path-line "\nversion = \"0.98.0\""))))))
1090 (add-after 'chdir-to-workspace 'patch-hardcoded-paths
1091 (lambda* (#:key inputs #:allow-other-keys)
1092 (let ((bash-bin (string-append
1093 (assoc-ref inputs "bash-minimal") "/bin"))
1094 (coreutils-bin (string-append
1095 (assoc-ref inputs "coreutils") "/bin"))
1096 (git-bin (string-append
1097 (assoc-ref inputs "git-minimal") "/bin"))
1098 (sed-bin (string-append
1099 (assoc-ref inputs "sed") "/bin"))
1100 ;; Include .policy files: the execpolicy-legacy
1101 ;; crate embeds default.policy via include_str!
1102 ;; at compile time, so its paths must also be
1103 ;; patched.
1104 (rs-files (find-files "." "\\.(rs|policy)$")))
1105 (substitute* rs-files
1106 (("\"/bin/bash\"")
1107 (string-append "\"" bash-bin "/bash\""))
1108 (("\"/bin/sh\"")
1109 (string-append "\"" bash-bin "/sh\""))
1110 (("\"/usr/bin/bash\"")
1111 (string-append "\"" bash-bin "/bash\""))
1112 (("\"/usr/bin/sh\"")
1113 (string-append "\"" bash-bin "/sh\""))
1114 ;;; bash/sh with inline arguments, e.g. "/bin/bash -i".
1115 (("\"/bin/bash ")
1116 (string-append "\"" bash-bin "/bash "))
1117 (("\"/bin/sh ")
1118 (string-append "\"" bash-bin "/sh "))
1119 ;; coreutils.
1120 (("\"/bin/(cat|cp|date|echo|head|ls|rm|sleep|true|touch)\"" all cmd)
1121 (string-append "\"" coreutils-bin "/" cmd "\""))
1122 ;; coreutils.
1123 (("\"/usr/bin/(cat|cp|head|ls|touch|true)\"" all cmd)
1124 (string-append "\"" coreutils-bin "/" cmd "\""))
1125 ;; coreutils with inline arguments
1126 ;; like "/bin/echo END-EVENT".
1127 (("\"/bin/(cat|cp|date|echo|head|ls|rm|sleep|true|touch) " all cmd)
1128 (string-append "\"" coreutils-bin "/" cmd " "))
1129 (("\"/usr/bin/git\"")
1130 (string-append "\"" git-bin "/git\""))
1131 (("\"/usr/bin/sed\"")
1132 (string-append "\"" sed-bin "/sed\"")))
1133 ;; @SHELL@ placeholder from test-shebangs patch
1134 (substitute*
1135 (list "rmcp-client/src/program_resolver.rs"
1136 "tui/src/external_editor.rs")
1137 (("@SHELL@")
1138 (string-append bash-bin "/sh")))
1139 ;; shebang in test-only file
1140 (substitute*
1141 "core/tests/suite/user_notification.rs"
1142 (("#!/bin/bash")
1143 (string-append "#!" bash-bin "/bash"))))))
1144 (add-before 'check 'set-home
1145 (lambda _
1146 (setenv "HOME" "/tmp")
1147 (setenv "USER" "nixbld"))))))
1148 (native-inputs (list clang ;bindgen uses libclang to parse BoringSSL's C headers
1149 cmake-minimal ;BoringSSL is compiled from C source
1150 libunwind ;BoringSSL tests verify stack unwinding in assembly
1151 perl python-minimal ;for tests
1152 pkg-config))
1153 (inputs (cons* bash-minimal coreutils git-minimal sed
1154 openssl sqlite `(,zstd "lib")
1155 (cargo-inputs 'codex)))
1156 (home-page "https://github.com/openai/codex")
1157 (synopsis "AI-assisted coding CLI and TUI")
1158 (description
1159 "Codex is an AI-powered coding assistant that runs in the terminal.
1160It provides an interactive TUI for conversations with AI models, with
1161support for shell command execution, file editing, and code generation.
1162Configure providers via @file{~/.codex/config.toml}.")
1163 (license license:asl2.0)))
1164
1165(define-public codex-acp
1166 (package
1167 (name "codex-acp")
1168 (version "0.9.2")
1169 (source
1170 (origin
1171 (method git-fetch)
1172 (uri (git-reference
1173 (url "https://github.com/zed-industries/codex-acp")
1174 (commit (string-append "v" version))))
1175 (file-name (git-file-name name version))
1176 (sha256
1177 (base32 "190sq6s6jfz8dkj1y8305r7x6ln86qqr2j1bnfjci7f1x2wyzmsj"))
1178 (patches (search-patches "codex-acp-0.9.2-remove-patch-sections.patch"
1179 "codex-acp-0.9.2-replace-result-flatten.patch"))))
1180 (build-system cargo-build-system)
1181 (arguments
1182 (list
1183 #:install-source? #f
1184 #:phases
1185 #~(modify-phases %standard-phases
1186 (add-after 'unpack 'patch-codex-deps
1187 (lambda _
1188 ;; Rewrite git dependencies to use vendored sources from rust-codex
1189 (substitute* "Cargo.toml"
1190 (("git = \"https://github.com/zed-industries/codex\", branch = \"acp\"")
1191 "version = \"0.0.0\"")))))))
1192 (native-inputs (list pkg-config))
1193 (inputs (cons* openssl sqlite `(,zstd "lib") (cargo-inputs 'codex-acp)))
1194 (home-page "https://github.com/zed-industries/codex-acp")
1195 (synopsis "ACP-compatible agent bridging Zed Codex with ACP clients")
1196 (description
1197 "This package provides an Agent Client Protocol (ACP) compatible agent
1198that bridges the Zed Codex runtime with ACP clients over stdio. It
1199supports multiple LLM providers through configuration in
1200@file{~/.codex/config.toml} and integrates with MCP servers for filesystem
1201operations.")
1202 (license license:asl2.0)))
1203
1204(define-public complgen 839(define-public complgen
1205 (package 840 (package
1206 (name "complgen") 841 (name "complgen")