Compare commits

...

7 Commits

Author SHA1 Message Date
jif-oai
bb71bc2d62 Release 0.105.0-alpha.16 2026-02-23 20:15:11 +00:00
Felipe Coury
48e08a1561 fix(tui): recover on owned wrap mapping mismatch (#12609)
## Summary

- Replace the `panic!` in `map_owned_wrapped_line_to_range` with a
recoverable flow that skips synthetic leading characters, logs a warning
on mid-line mismatch, and returns the mapped prefix range instead of
crashing
- Fixes a crash when `textwrap` produces owned lines with synthetic
indent prefixes (e.g. non-space indents via
`initial_indent`/`subsequent_indent`)

## Test plan

- [x] Added unit test for direct mismatch recovery
(`map_owned_wrapped_line_to_range_recovers_on_non_prefix_mismatch`)
- [x] Added end-to-end `wrap_ranges` test with non-space indents that
forces owned wrapped lines and validates full source reconstruction
- [x] Verify no regressions in existing `wrapping.rs` tests (`cargo test
-p codex-tui`)
2026-02-23 20:14:50 +00:00
sayan-oai
bfe622f495 fix: add ellipsis for truncated status indicator (#12540)
#### What

- Add ellipsis truncation of the status indicator, similar to equivalent
truncation done in the footer.
- Extract truncation helpers into separate file



https://github.com/user-attachments/assets/a2d5f22f-8adc-456e-8059-97359194c25c


#### Tests
Updated relevant snapshot tests
2026-02-23 11:45:46 -08:00
Michael Bolin
7f75e74201 Use Arc-based ToolCtx in tool runtimes (#12583)
## Why
Tool handlers and runtimes needed to pass the same turn/session context
for shell and non-shell workflows without duplicative ownership churn.
Using shared pointers avoids temporary lifetimes and keeps existing
behavior unchanged while simplifying call sites.

## What changed
- Converted `ToolCtx` to store shared context handles (`Arc`-based),
including updates across shell, apply-patch, and unified-exec paths.
- Updated orchestrator/runtime call sites to consume the shared context
consistently and remove brittle move/borrow patterns.
- Kept behavior unchanged while preparing the type surface for the new
shell escalation integration in the next stack commit.

## Verification
- Validated this commit stack point with `just clippy` and confirmed
workspace compiles cleanly in this stack state.

[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/12583).
* #12584
* __->__ #12583
* #12556
2026-02-23 18:29:26 +00:00
dependabot[bot]
fec517cd38 chore(deps): bump syn from 2.0.114 to 2.0.117 in /codex-rs (#12529)
Bumps [syn](https://github.com/dtolnay/syn) from 2.0.114 to 2.0.117.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/dtolnay/syn/releases">syn's
releases</a>.</em></p>
<blockquote>
<h2>2.0.117</h2>
<ul>
<li>Fix parsing of <code>self::</code> pattern in first function
argument (<a
href="https://redirect.github.com/dtolnay/syn/issues/1970">#1970</a>)</li>
</ul>
<h2>2.0.116</h2>
<ul>
<li>Optimize parse_fn_arg_or_variadic for less lookahead on erroneous
receiver (<a
href="https://redirect.github.com/dtolnay/syn/issues/1968">#1968</a>)</li>
</ul>
<h2>2.0.115</h2>
<ul>
<li>Enable GenericArgument::Constraint parsing in non-full mode (<a
href="https://redirect.github.com/dtolnay/syn/issues/1966">#1966</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7bcb37cdb3"><code>7bcb37c</code></a>
Release 2.0.117</li>
<li><a
href="9c6e7d3b8d"><code>9c6e7d3</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/syn/issues/1970">#1970</a>
from dtolnay/receiver</li>
<li><a
href="019a84847e"><code>019a848</code></a>
Fix self:: pattern in first function argument</li>
<li><a
href="23f54f3cf6"><code>23f54f3</code></a>
Update test suite to nightly-2026-02-18</li>
<li><a
href="b99b9a627c"><code>b99b9a6</code></a>
Unpin CI miri toolchain</li>
<li><a
href="a62e54a48b"><code>a62e54a</code></a>
Release 2.0.116</li>
<li><a
href="5a8ed9f32e"><code>5a8ed9f</code></a>
Merge pull request <a
href="https://redirect.github.com/dtolnay/syn/issues/1968">#1968</a>
from dtolnay/receiver</li>
<li><a
href="813afcc773"><code>813afcc</code></a>
Optimize parse_fn_arg_or_variadic for less lookahead on erroneous
receiver</li>
<li><a
href="c172150113"><code>c172150</code></a>
Add regression test for issue 1718</li>
<li><a
href="0071ab367c"><code>0071ab3</code></a>
Ignore type_complexity clippy lint</li>
<li>Additional commits viewable in <a
href="https://github.com/dtolnay/syn/compare/2.0.114...2.0.117">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=syn&package-manager=cargo&previous-version=2.0.114&new-version=2.0.117)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 10:25:05 -08:00
dependabot[bot]
5c52ef8e60 chore(deps): bump libc from 0.2.180 to 0.2.182 in /codex-rs (#12528)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.180 to 0.2.182.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/libc/releases">libc's
releases</a>.</em></p>
<blockquote>
<h2>0.2.182</h2>
<h3>Added</h3>
<ul>
<li>Android, Linux: Add <code>tgkill</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4970">#4970</a>)</li>
<li>Redox: Add <code>RENAME_NOREPLACE</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4968">#4968</a>)</li>
<li>Redox: Add <code>renameat2</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4968">#4968</a>)</li>
</ul>
<h2>0.2.181</h2>
<h3>Added</h3>
<ul>
<li>Apple: Add <code>MADV_ZERO</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4924">#4924</a>)</li>
<li>Redox: Add <code>makedev</code>, <code>major</code>, and
<code>minor</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4928">#4928</a>)</li>
<li>GLibc: Add <code>PTRACE_SET_SYSCALL_INFO</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4933">#4933</a>)</li>
<li>OpenBSD: Add more kqueue related constants for (<a
href="https://redirect.github.com/rust-lang/libc/pull/4945">#4945</a>)</li>
<li>Linux: add CAN error types (<a
href="https://redirect.github.com/rust-lang/libc/pull/4944">#4944</a>)</li>
<li>OpenBSD: Add siginfo_t::si_status (<a
href="https://redirect.github.com/rust-lang/libc/pull/4946">#4946</a>)</li>
<li>QNX NTO: Add <code>max_align_t</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4927">#4927</a>)</li>
<li>Illumos: Add <code>_CS_PATH</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4956">#4956</a>)</li>
<li>OpenBSD: add <code>ppoll</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4957">#4957</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li><strong>Breaking</strong>: Redox: Fix the type of <code>dev_t</code>
(<a
href="https://redirect.github.com/rust-lang/libc/pull/4928">#4928</a>)</li>
<li>AIX: Change 'tv_nsec' of 'struct timespec' to type 'c_long' (<a
href="https://redirect.github.com/rust-lang/libc/pull/4931">#4931</a>)</li>
<li>AIX: Use 'struct st_timespec' in 'struct stat{,64}' (<a
href="https://redirect.github.com/rust-lang/libc/pull/4931">#4931</a>)</li>
<li>Glibc: Link old version of <code>tc{g,s}etattr</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4938">#4938</a>)</li>
<li>Glibc: Link the correct version of <code>cf{g,s}et{i,o}speed</code>
on mips{32,64}r6 (<a
href="https://redirect.github.com/rust-lang/libc/pull/4938">#4938</a>)</li>
<li>OpenBSD: Fix constness of tm.tm_zone (<a
href="https://redirect.github.com/rust-lang/libc/pull/4948">#4948</a>)</li>
<li>OpenBSD: Fix the definition of <code>ptrace_thread_state</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4947">#4947</a>)</li>
<li>QuRT: Fix type visibility and defs (<a
href="https://redirect.github.com/rust-lang/libc/pull/4932">#4932</a>)</li>
<li>Redox: Fix values for <code>PTHREAD_MUTEX_{NORMAL, RECURSIVE}</code>
(<a
href="https://redirect.github.com/rust-lang/libc/pull/4943">#4943</a>)</li>
<li>Various: Mark additional fields as private padding (<a
href="https://redirect.github.com/rust-lang/libc/pull/4922">#4922</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Fuchsia: Update <code>SO_*</code> constants (<a
href="https://redirect.github.com/rust-lang/libc/pull/4937">#4937</a>)</li>
<li>Revert &quot;musl: convert inline timespecs to timespec&quot;
(resolves build issues on targets only supported by Musl 1.2.3+ ) (<a
href="https://redirect.github.com/rust-lang/libc/pull/4958">#4958</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/rust-lang/libc/blob/0.2.182/CHANGELOG.md">libc's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/rust-lang/libc/compare/0.2.181...0.2.182">0.2.182</a>
- 2026-02-13</h2>
<h3>Added</h3>
<ul>
<li>Android, Linux: Add <code>tgkill</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4970">#4970</a>)</li>
<li>Redox: Add <code>RENAME_NOREPLACE</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4968">#4968</a>)</li>
<li>Redox: Add <code>renameat2</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4968">#4968</a>)</li>
</ul>
<h2><a
href="https://github.com/rust-lang/libc/compare/0.2.180...0.2.181">0.2.181</a>
- 2026-02-09</h2>
<h3>Added</h3>
<ul>
<li>Apple: Add <code>MADV_ZERO</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4924">#4924</a>)</li>
<li>Redox: Add <code>makedev</code>, <code>major</code>, and
<code>minor</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4928">#4928</a>)</li>
<li>GLibc: Add <code>PTRACE_SET_SYSCALL_INFO</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4933">#4933</a>)</li>
<li>OpenBSD: Add more kqueue related constants for (<a
href="https://redirect.github.com/rust-lang/libc/pull/4945">#4945</a>)</li>
<li>Linux: add CAN error types (<a
href="https://redirect.github.com/rust-lang/libc/pull/4944">#4944</a>)</li>
<li>OpenBSD: Add siginfo_t::si_status (<a
href="https://redirect.github.com/rust-lang/libc/pull/4946">#4946</a>)</li>
<li>QNX NTO: Add <code>max_align_t</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4927">#4927</a>)</li>
<li>Illumos: Add <code>_CS_PATH</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4956">#4956</a>)</li>
<li>OpenBSD: add <code>ppoll</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4957">#4957</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li><strong>breaking</strong>: Redox: Fix the type of dev_t (<a
href="https://redirect.github.com/rust-lang/libc/pull/4928">#4928</a>)</li>
<li>AIX: Change 'tv_nsec' of 'struct timespec' to type 'c_long' (<a
href="https://redirect.github.com/rust-lang/libc/pull/4931">#4931</a>)</li>
<li>AIX: Use 'struct st_timespec' in 'struct stat{,64}' (<a
href="https://redirect.github.com/rust-lang/libc/pull/4931">#4931</a>)</li>
<li>Glibc: Link old version of <code>tc{g,s}etattr</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4938">#4938</a>)</li>
<li>Glibc: Link the correct version of <code>cf{g,s}et{i,o}speed</code>
on mips{32,64}r6 (<a
href="https://redirect.github.com/rust-lang/libc/pull/4938">#4938</a>)</li>
<li>OpenBSD: Fix constness of tm.tm_zone (<a
href="https://redirect.github.com/rust-lang/libc/pull/4948">#4948</a>)</li>
<li>OpenBSD: Fix the definition of <code>ptrace_thread_state</code> (<a
href="https://redirect.github.com/rust-lang/libc/pull/4947">#4947</a>)</li>
<li>QuRT: Fix type visibility and defs (<a
href="https://redirect.github.com/rust-lang/libc/pull/4932">#4932</a>)</li>
<li>Redox: Fix values for <code>PTHREAD_MUTEX_{NORMAL, RECURSIVE}</code>
(<a
href="https://redirect.github.com/rust-lang/libc/pull/4943">#4943</a>)</li>
<li>Various: Mark additional fields as private padding (<a
href="https://redirect.github.com/rust-lang/libc/pull/4922">#4922</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Fuchsia: Update <code>SO_*</code> constants (<a
href="https://redirect.github.com/rust-lang/libc/pull/4937">#4937</a>)</li>
<li>Revert &quot;musl: convert inline timespecs to timespec&quot;
(resolves build issues on targets only supported by Musl 1.2.3+ ) (<a
href="https://redirect.github.com/rust-lang/libc/pull/4958">#4958</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="e879ee90b6"><code>e879ee9</code></a>
chore: Release libc 0.2.182</li>
<li><a
href="2efe72f4da"><code>2efe72f</code></a>
remove copyright year in LICENSE-MIT</li>
<li><a
href="634bc4e66e"><code>634bc4e</code></a>
ci: Update the list of tested and documented targets</li>
<li><a
href="d7aa109ab5"><code>d7aa109</code></a>
Revert &quot;Disable hexagon-unknown-linux-musl testing for
now&quot;</li>
<li><a
href="14e2f5641e"><code>14e2f56</code></a>
Revert &quot;ci: Skip hexagon-unknown-linux-musl&quot;</li>
<li><a
href="b7807c369b"><code>b7807c3</code></a>
Revert &quot;aix: Temporarily skip checking powerpc64-ibm-aix
builds&quot;</li>
<li><a
href="abe93a0bfe"><code>abe93a0</code></a>
feat(linux): add <code>tgkill</code> for Linux and Android</li>
<li><a
href="25f7dde943"><code>25f7dde</code></a>
feat(redox): add <code>RENAME_NOREPLACE</code></li>
<li><a
href="4b4ce4f220"><code>4b4ce4f</code></a>
feat(redox): add <code>renameat2</code></li>
<li><a
href="ab8c36c493"><code>ab8c36c</code></a>
build(deps): bump vmactions/solaris-vm from 1.2.8 to 1.3.0</li>
<li>Additional commits viewable in <a
href="https://github.com/rust-lang/libc/compare/0.2.180...0.2.182">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=libc&package-manager=cargo&previous-version=0.2.180&new-version=0.2.182)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-23 10:24:35 -08:00
Charley Cunningham
3cea3e665e app-server: box request dispatch future to reduce stack pressure (#12421) 2026-02-23 10:05:41 -08:00
23 changed files with 416 additions and 231 deletions

152
codex-rs/Cargo.lock generated
View File

@@ -282,7 +282,7 @@ checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -482,7 +482,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"synstructure",
]
@@ -494,7 +494,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -632,7 +632,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -672,7 +672,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -689,7 +689,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -1047,7 +1047,7 @@ dependencies = [
"darling 0.20.11",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -1223,7 +1223,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -1845,7 +1845,7 @@ version = "0.0.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -2929,7 +2929,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -2973,7 +2973,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -2987,7 +2987,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3000,7 +3000,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3011,7 +3011,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core 0.20.11",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3022,7 +3022,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
dependencies = [
"darling_core 0.21.3",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3033,7 +3033,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
dependencies = [
"darling_core 0.23.0",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3170,7 +3170,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3200,7 +3200,7 @@ dependencies = [
"convert_case 0.6.0",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"unicode-xid",
]
@@ -3214,7 +3214,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustc_version",
"syn 2.0.114",
"syn 2.0.117",
"unicode-xid",
]
@@ -3327,7 +3327,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3380,7 +3380,7 @@ checksum = "83e195b4945e88836d826124af44fdcb262ec01ef94d44f14f4fb5103f19892a"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3449,7 +3449,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3470,7 +3470,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3631,7 +3631,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -3945,7 +3945,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -4497,7 +4497,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim 0.11.1",
"syn 2.0.114",
"syn 2.0.117",
"unic-langid",
]
@@ -4511,7 +4511,7 @@ dependencies = [
"i18n-config",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -4851,7 +4851,7 @@ dependencies = [
"indoc",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -4993,7 +4993,7 @@ checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -5135,9 +5135,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.180"
version = "0.2.182"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
[[package]]
name = "libdbus-sys"
@@ -6051,7 +6051,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -6386,7 +6386,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -6626,7 +6626,7 @@ dependencies = [
"proc-macro-error-attr2",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -6687,7 +6687,7 @@ dependencies = [
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -7023,7 +7023,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -7336,7 +7336,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -7495,7 +7495,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_json",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -7543,7 +7543,7 @@ dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn 2.0.114",
"syn 2.0.117",
"walkdir",
]
@@ -7838,7 +7838,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -7850,7 +7850,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8124,7 +8124,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8135,7 +8135,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8184,7 +8184,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8236,7 +8236,7 @@ dependencies = [
"darling 0.21.3",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8286,7 +8286,7 @@ checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8545,7 +8545,7 @@ dependencies = [
"quote",
"sqlx-core",
"sqlx-macros-core",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8568,7 +8568,7 @@ dependencies = [
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"syn 2.0.114",
"syn 2.0.117",
"tokio",
"url",
]
@@ -8753,7 +8753,7 @@ dependencies = [
"dupe",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8875,7 +8875,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8887,7 +8887,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -8928,9 +8928,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.114"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -8954,7 +8954,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9081,7 +9081,7 @@ dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9092,7 +9092,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"test-case-core",
]
@@ -9115,7 +9115,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9164,7 +9164,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9175,7 +9175,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9319,7 +9319,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9588,7 +9588,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9687,7 +9687,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568"
dependencies = [
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -9757,7 +9757,7 @@ checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"termcolor",
]
@@ -10167,7 +10167,7 @@ dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"wasm-bindgen-shared",
]
@@ -10481,7 +10481,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -10492,7 +10492,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -10503,7 +10503,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -10514,7 +10514,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -11099,7 +11099,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"synstructure",
]
@@ -11150,7 +11150,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"zvariant_utils",
]
@@ -11182,7 +11182,7 @@ checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -11202,7 +11202,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"synstructure",
]
@@ -11223,7 +11223,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -11257,7 +11257,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]
[[package]]
@@ -11388,7 +11388,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
"zvariant_utils",
]
@@ -11400,5 +11400,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.117",
]

View File

@@ -67,7 +67,7 @@ members = [
resolver = "2"
[workspace.package]
version = "0.0.0"
version = "0.105.0-alpha.16"
# Track the edition for all workspace crates in one place. Individual
# crates can still override this value, but keeping it here means new
# crates created with `cargo new -w ...` automatically inherit the 2024
@@ -190,7 +190,7 @@ itertools = "0.14.0"
keyring = { version = "3.6", default-features = false }
landlock = "0.4.4"
lazy_static = "1"
libc = "0.2.177"
libc = "0.2.182"
log = "0.4"
lru = "0.16.3"
maplit = "1.0.2"

View File

@@ -49,6 +49,7 @@ use codex_core::default_client::set_default_originator;
use codex_feedback::CodexFeedback;
use codex_protocol::ThreadId;
use codex_protocol::protocol::SessionSource;
use futures::FutureExt;
use tokio::sync::broadcast;
use tokio::time::Duration;
use tokio::time::timeout;
@@ -386,8 +387,12 @@ impl MessageProcessor {
.await;
}
other => {
// Box the delegated future so this wrapper's async state machine does not
// inline the full `CodexMessageProcessor::process_request` future, which
// can otherwise push worker-thread stack usage over the edge.
self.codex_message_processor
.process_request(connection_id, other)
.boxed()
.await;
}
}

View File

@@ -31,6 +31,7 @@ use async_trait::async_trait;
use codex_apply_patch::ApplyPatchAction;
use codex_apply_patch::ApplyPatchFileChange;
use codex_utils_absolute_path::AbsolutePathBuf;
use std::sync::Arc;
pub struct ApplyPatchHandler;
@@ -139,8 +140,8 @@ impl ToolHandler for ApplyPatchHandler {
let mut orchestrator = ToolOrchestrator::new();
let mut runtime = ApplyPatchRuntime::new();
let tool_ctx = ToolCtx {
session: session.as_ref(),
turn: turn.as_ref(),
session: session.clone(),
turn: turn.clone(),
call_id: call_id.clone(),
tool_name: tool_name.to_string(),
};
@@ -149,7 +150,7 @@ impl ToolHandler for ApplyPatchHandler {
&mut runtime,
&req,
&tool_ctx,
&turn,
turn.as_ref(),
turn.approval_policy.value(),
)
.await
@@ -193,8 +194,8 @@ pub(crate) async fn intercept_apply_patch(
command: &[String],
cwd: &Path,
timeout_ms: Option<u64>,
session: &Session,
turn: &TurnContext,
session: Arc<Session>,
turn: Arc<TurnContext>,
tracker: Option<&SharedTurnDiffTracker>,
call_id: &str,
tool_name: &str,
@@ -203,11 +204,13 @@ pub(crate) async fn intercept_apply_patch(
codex_apply_patch::MaybeApplyPatchVerified::Body(changes) => {
session
.record_model_warning(
format!("apply_patch was requested via {tool_name}. Use the apply_patch tool instead of exec_command."),
turn,
format!(
"apply_patch was requested via {tool_name}. Use the apply_patch tool instead of exec_command."
),
turn.as_ref(),
)
.await;
match apply_patch::apply_patch(turn, changes).await {
match apply_patch::apply_patch(turn.as_ref(), changes).await {
InternalApplyPatchInvocation::Output(item) => {
let content = item?;
Ok(Some(ToolOutput::Function {
@@ -219,8 +222,12 @@ pub(crate) async fn intercept_apply_patch(
let changes = convert_apply_patch_to_protocol(&apply.action);
let approval_keys = file_paths_for_action(&apply.action);
let emitter = ToolEmitter::apply_patch(changes.clone(), apply.auto_approved);
let event_ctx =
ToolEventCtx::new(session, turn, call_id, tracker.as_ref().copied());
let event_ctx = ToolEventCtx::new(
session.as_ref(),
turn.as_ref(),
call_id,
tracker.as_ref().copied(),
);
emitter.begin(event_ctx).await;
let req = ApplyPatchRequest {
@@ -235,8 +242,8 @@ pub(crate) async fn intercept_apply_patch(
let mut orchestrator = ToolOrchestrator::new();
let mut runtime = ApplyPatchRuntime::new();
let tool_ctx = ToolCtx {
session,
turn,
session: session.clone(),
turn: turn.clone(),
call_id: call_id.to_string(),
tool_name: tool_name.to_string(),
};
@@ -245,13 +252,17 @@ pub(crate) async fn intercept_apply_patch(
&mut runtime,
&req,
&tool_ctx,
turn,
turn.as_ref(),
turn.approval_policy.value(),
)
.await
.map(|result| result.output);
let event_ctx =
ToolEventCtx::new(session, turn, call_id, tracker.as_ref().copied());
let event_ctx = ToolEventCtx::new(
session.as_ref(),
turn.as_ref(),
call_id,
tracker.as_ref().copied(),
);
let content = emitter.finish(event_ctx, out).await?;
Ok(Some(ToolOutput::Function {
body: FunctionCallOutputBody::Text(content),

View File

@@ -296,8 +296,8 @@ impl ShellHandler {
&exec_params.command,
&exec_params.cwd,
exec_params.expiration.timeout_ms(),
session.as_ref(),
turn.as_ref(),
session.clone(),
turn.clone(),
Some(&tracker),
&call_id,
tool_name.as_str(),
@@ -343,8 +343,8 @@ impl ShellHandler {
let mut orchestrator = ToolOrchestrator::new();
let mut runtime = ShellRuntime::new();
let tool_ctx = ToolCtx {
session: session.as_ref(),
turn: turn.as_ref(),
session: session.clone(),
turn: turn.clone(),
call_id: call_id.clone(),
tool_name,
};

View File

@@ -172,8 +172,8 @@ impl ToolHandler for UnifiedExecHandler {
&command,
&cwd,
Some(yield_time_ms),
context.session.as_ref(),
context.turn.as_ref(),
context.session.clone(),
context.turn.clone(),
Some(&tracker),
&context.call_id,
tool_name.as_str(),

View File

@@ -48,7 +48,7 @@ impl ToolOrchestrator {
async fn run_attempt<Rq, Out, T>(
tool: &mut T,
req: &Rq,
tool_ctx: &ToolCtx<'_>,
tool_ctx: &ToolCtx,
attempt: &SandboxAttempt<'_>,
has_managed_network_requirements: bool,
) -> (Result<Out, ToolError>, Option<DeferredNetworkApproval>)
@@ -56,7 +56,7 @@ impl ToolOrchestrator {
T: ToolRuntime<Rq, Out>,
{
let network_approval = begin_network_approval(
tool_ctx.session,
&tool_ctx.session,
&tool_ctx.turn.sub_id,
&tool_ctx.call_id,
has_managed_network_requirements,
@@ -65,8 +65,8 @@ impl ToolOrchestrator {
.await;
let attempt_tool_ctx = ToolCtx {
session: tool_ctx.session,
turn: tool_ctx.turn,
session: tool_ctx.session.clone(),
turn: tool_ctx.turn.clone(),
call_id: tool_ctx.call_id.clone(),
tool_name: tool_ctx.tool_name.clone(),
};
@@ -79,7 +79,7 @@ impl ToolOrchestrator {
match network_approval.mode() {
NetworkApprovalMode::Immediate => {
let finalize_result =
finish_immediate_network_approval(tool_ctx.session, network_approval).await;
finish_immediate_network_approval(&tool_ctx.session, network_approval).await;
if let Err(err) = finalize_result {
return (Err(err), None);
}
@@ -88,7 +88,7 @@ impl ToolOrchestrator {
NetworkApprovalMode::Deferred => {
let deferred = network_approval.into_deferred();
if run_result.is_err() {
finish_deferred_network_approval(tool_ctx.session, deferred).await;
finish_deferred_network_approval(&tool_ctx.session, deferred).await;
return (run_result, None);
}
(run_result, deferred)
@@ -100,7 +100,7 @@ impl ToolOrchestrator {
&mut self,
tool: &mut T,
req: &Rq,
tool_ctx: &ToolCtx<'_>,
tool_ctx: &ToolCtx,
turn_ctx: &crate::codex::TurnContext,
approval_policy: AskForApproval,
) -> Result<OrchestratorRunResult<Out>, ToolError>
@@ -128,7 +128,7 @@ impl ToolOrchestrator {
}
ExecApprovalRequirement::NeedsApproval { reason, .. } => {
let approval_ctx = ApprovalCtx {
session: tool_ctx.session,
session: &tool_ctx.session,
turn: turn_ctx,
call_id: &tool_ctx.call_id,
retry_reason: reason,
@@ -256,7 +256,7 @@ impl ToolOrchestrator {
&& network_approval_context.is_none();
if !bypass_retry_approval {
let approval_ctx = ApprovalCtx {
session: tool_ctx.session,
session: &tool_ctx.session,
turn: turn_ctx,
call_id: &tool_ctx.call_id,
retry_reason: Some(retry_reason),

View File

@@ -70,7 +70,7 @@ impl ApplyPatchRuntime {
})
}
fn stdout_stream(ctx: &ToolCtx<'_>) -> Option<crate::exec::StdoutStream> {
fn stdout_stream(ctx: &ToolCtx) -> Option<crate::exec::StdoutStream> {
Some(crate::exec::StdoutStream {
sub_id: ctx.turn.sub_id.clone(),
call_id: ctx.call_id.clone(),
@@ -156,7 +156,7 @@ impl ToolRuntime<ApplyPatchRequest, ExecToolCallOutput> for ApplyPatchRuntime {
&mut self,
req: &ApplyPatchRequest,
attempt: &SandboxAttempt<'_>,
ctx: &ToolCtx<'_>,
ctx: &ToolCtx,
) -> Result<ExecToolCallOutput, ToolError> {
let spec = Self::build_command_spec(req)?;
let env = attempt

View File

@@ -60,7 +60,7 @@ impl ShellRuntime {
Self
}
fn stdout_stream(ctx: &ToolCtx<'_>) -> Option<crate::exec::StdoutStream> {
fn stdout_stream(ctx: &ToolCtx) -> Option<crate::exec::StdoutStream> {
Some(crate::exec::StdoutStream {
sub_id: ctx.turn.sub_id.clone(),
call_id: ctx.call_id.clone(),
@@ -150,7 +150,7 @@ impl ToolRuntime<ShellRequest, ExecToolCallOutput> for ShellRuntime {
fn network_approval_spec(
&self,
req: &ShellRequest,
_ctx: &ToolCtx<'_>,
_ctx: &ToolCtx,
) -> Option<NetworkApprovalSpec> {
req.network.as_ref()?;
Some(NetworkApprovalSpec {
@@ -163,7 +163,7 @@ impl ToolRuntime<ShellRequest, ExecToolCallOutput> for ShellRuntime {
&mut self,
req: &ShellRequest,
attempt: &SandboxAttempt<'_>,
ctx: &ToolCtx<'_>,
ctx: &ToolCtx,
) -> Result<ExecToolCallOutput, ToolError> {
let base_command = &req.command;
let session_shell = ctx.session.user_shell();
@@ -207,7 +207,7 @@ impl ToolRuntime<ShellRequest, ExecToolCallOutput> for ShellRuntime {
.session
.services
.zsh_exec_bridge
.execute_shell_request(&env, ctx.session, ctx.turn, &ctx.call_id)
.execute_shell_request(&env, &ctx.session, &ctx.turn, &ctx.call_id)
.await;
}

View File

@@ -153,7 +153,7 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
fn network_approval_spec(
&self,
req: &UnifiedExecRequest,
_ctx: &ToolCtx<'_>,
_ctx: &ToolCtx,
) -> Option<NetworkApprovalSpec> {
req.network.as_ref()?;
Some(NetworkApprovalSpec {
@@ -166,7 +166,7 @@ impl<'a> ToolRuntime<UnifiedExecRequest, UnifiedExecProcess> for UnifiedExecRunt
&mut self,
req: &UnifiedExecRequest,
attempt: &SandboxAttempt<'_>,
ctx: &ToolCtx<'_>,
ctx: &ToolCtx,
) -> Result<UnifiedExecProcess, ToolError> {
let base_command = &req.command;
let session_shell = ctx.session.user_shell();

View File

@@ -18,14 +18,14 @@ use codex_protocol::approvals::ExecPolicyAmendment;
use codex_protocol::approvals::NetworkApprovalContext;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::ReviewDecision;
use futures::Future;
use futures::future::BoxFuture;
use serde::Serialize;
use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::path::Path;
use futures::Future;
use futures::future::BoxFuture;
use serde::Serialize;
use std::sync::Arc;
#[derive(Clone, Default, Debug)]
pub(crate) struct ApprovalStore {
@@ -267,9 +267,9 @@ pub(crate) trait Sandboxable {
}
}
pub(crate) struct ToolCtx<'a> {
pub session: &'a Session,
pub turn: &'a TurnContext,
pub(crate) struct ToolCtx {
pub session: Arc<Session>,
pub turn: Arc<TurnContext>,
pub call_id: String,
pub tool_name: String,
}
@@ -281,7 +281,7 @@ pub(crate) enum ToolError {
}
pub(crate) trait ToolRuntime<Req, Out>: Approvable<Req> + Sandboxable {
fn network_approval_spec(&self, _req: &Req, _ctx: &ToolCtx<'_>) -> Option<NetworkApprovalSpec> {
fn network_approval_spec(&self, _req: &Req, _ctx: &ToolCtx) -> Option<NetworkApprovalSpec> {
None
}

View File

@@ -594,8 +594,8 @@ impl UnifiedExecProcessManager {
exec_approval_requirement,
};
let tool_ctx = ToolCtx {
session: context.session.as_ref(),
turn: context.turn.as_ref(),
session: context.session.clone(),
turn: context.turn.clone(),
call_id: context.call_id.clone(),
tool_name: "exec_command".to_string(),
};
@@ -604,7 +604,7 @@ impl UnifiedExecProcessManager {
&mut runtime,
&req,
&tool_ctx,
context.turn.as_ref(),
&context.turn,
context.turn.approval_policy.value(),
)
.await

View File

@@ -110,10 +110,10 @@
//! overall state machine, since it affects which transitions are even possible from a given UI
//! state.
use crate::bottom_pane::footer::mode_indicator_line;
use crate::bottom_pane::selection_popup_common::truncate_line_with_ellipsis_if_overflow;
use crate::key_hint;
use crate::key_hint::KeyBinding;
use crate::key_hint::has_ctrl_or_alt;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::ui_consts::FOOTER_INDENT_COLS;
use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;

View File

@@ -990,7 +990,7 @@ const SHORTCUTS: &[ShortcutDescriptor] = &[
#[cfg(test)]
mod tests {
use super::*;
use crate::bottom_pane::selection_popup_common::truncate_line_with_ellipsis_if_overflow;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::test_backend::VT100Backend;
use insta::assert_snapshot;
use pretty_assertions::assert_eq;

View File

@@ -46,8 +46,8 @@ use crate::bottom_pane::bottom_pane_view::BottomPaneView;
use crate::bottom_pane::popup_consts::MAX_POPUP_ROWS;
use crate::bottom_pane::scroll_state::ScrollState;
use crate::bottom_pane::selection_popup_common::render_rows_single_line;
use crate::bottom_pane::selection_popup_common::truncate_line_with_ellipsis_if_overflow;
use crate::key_hint;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::render::Insets;
use crate::render::RectExt;
use crate::render::renderable::ColumnRenderable;

View File

@@ -14,6 +14,7 @@ use unicode_width::UnicodeWidthChar;
use unicode_width::UnicodeWidthStr;
use crate::key_hint::KeyBinding;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::render::Insets;
use crate::render::RectExt as _;
use crate::style::user_message_style;
@@ -105,12 +106,6 @@ pub(crate) fn wrap_styled_line<'a>(line: &'a Line<'a>, width: u16) -> Vec<Line<'
word_wrap_line(line, opts)
}
fn line_width(line: &Line<'_>) -> usize {
line.iter()
.map(|span| UnicodeWidthStr::width(span.content.as_ref()))
.sum()
}
fn line_to_owned(line: Line<'_>) -> Line<'static> {
Line {
style: line.style,
@@ -126,91 +121,6 @@ fn line_to_owned(line: Line<'_>) -> Line<'static> {
}
}
pub(crate) fn truncate_line_to_width(line: Line<'static>, max_width: usize) -> Line<'static> {
if max_width == 0 {
return Line::from(Vec::<Span<'static>>::new());
}
let Line {
style,
alignment,
spans,
} = line;
let mut used = 0usize;
let mut spans_out: Vec<Span<'static>> = Vec::new();
for span in spans {
let text = span.content.into_owned();
let style = span.style;
let span_width = UnicodeWidthStr::width(text.as_str());
if span_width == 0 {
spans_out.push(Span::styled(text, style));
continue;
}
if used >= max_width {
break;
}
if used + span_width <= max_width {
used += span_width;
spans_out.push(Span::styled(text, style));
continue;
}
let mut truncated = String::new();
for ch in text.chars() {
let ch_width = UnicodeWidthChar::width(ch).unwrap_or(0);
if used + ch_width > max_width {
break;
}
truncated.push(ch);
used += ch_width;
}
if !truncated.is_empty() {
spans_out.push(Span::styled(truncated, style));
}
break;
}
Line {
style,
alignment,
spans: spans_out,
}
}
pub(crate) fn truncate_line_with_ellipsis_if_overflow(
line: Line<'static>,
max_width: usize,
) -> Line<'static> {
if max_width == 0 {
return Line::from(Vec::<Span<'static>>::new());
}
let width = line_width(&line);
if width <= max_width {
return line;
}
let truncated = truncate_line_to_width(line, max_width.saturating_sub(1));
let Line {
style,
alignment,
mut spans,
} = truncated;
let ellipsis_style = spans.last().map(|span| span.style).unwrap_or_default();
spans.push(Span::styled("", ellipsis_style));
Line {
style,
alignment,
spans,
}
}
fn compute_desc_col(
rows_all: &[GenericDisplayRow],
start_idx: usize,

View File

@@ -2,7 +2,7 @@
source: tui/src/bottom_pane/mod.rs
expression: "render_snapshot(&pane, area)"
---
• Working (0s • esc to interru
• Working (0s • esc to interr
Ask Codex to do anything

View File

@@ -3,7 +3,7 @@ source: tui/src/chatwidget/tests.rs
expression: terminal.backend()
---
" "
"• Working (0s • esc to interrupt) · 1 background terminal running · /ps to view "
"• Working (0s • esc to interrupt) · 1 background terminal running · /ps to view"
" "
" "
" Ask Codex to do anything "

View File

@@ -80,6 +80,7 @@ mod get_git_diff;
mod history_cell;
pub mod insert_history;
mod key_hint;
mod line_truncation;
pub mod live_wrap;
mod markdown;
mod markdown_render;

View File

@@ -0,0 +1,100 @@
use ratatui::text::Line;
use ratatui::text::Span;
use unicode_width::UnicodeWidthChar;
use unicode_width::UnicodeWidthStr;
pub(crate) fn line_width(line: &Line<'_>) -> usize {
line.iter()
.map(|span| UnicodeWidthStr::width(span.content.as_ref()))
.sum()
}
pub(crate) fn truncate_line_to_width(line: Line<'static>, max_width: usize) -> Line<'static> {
if max_width == 0 {
return Line::from(Vec::<Span<'static>>::new());
}
let Line {
style,
alignment,
spans,
} = line;
let mut used = 0usize;
let mut spans_out: Vec<Span<'static>> = Vec::with_capacity(spans.len());
for span in spans {
let span_width = UnicodeWidthStr::width(span.content.as_ref());
if span_width == 0 {
spans_out.push(span);
continue;
}
if used >= max_width {
break;
}
if used + span_width <= max_width {
used += span_width;
spans_out.push(span);
continue;
}
let style = span.style;
let text = span.content.as_ref();
let mut end_idx = 0usize;
for (idx, ch) in text.char_indices() {
let ch_width = UnicodeWidthChar::width(ch).unwrap_or(0);
if used + ch_width > max_width {
break;
}
end_idx = idx + ch.len_utf8();
used += ch_width;
}
if end_idx > 0 {
spans_out.push(Span::styled(text[..end_idx].to_string(), style));
}
break;
}
Line {
style,
alignment,
spans: spans_out,
}
}
/// Truncate a styled line to `max_width` and append an ellipsis on overflow.
///
/// Intended for short UI rows. This preserves a fast no-overflow path (width
/// pre-scan + return original line unchanged) and uses `truncate_line_to_width`
/// for the overflow case.
/// Performance should be reevaluated if using this method in loops/over larger content in the future.
pub(crate) fn truncate_line_with_ellipsis_if_overflow(
line: Line<'static>,
max_width: usize,
) -> Line<'static> {
if max_width == 0 {
return Line::from(Vec::<Span<'static>>::new());
}
if line_width(&line) <= max_width {
return line;
}
let truncated = truncate_line_to_width(line, max_width.saturating_sub(1));
let Line {
style,
alignment,
mut spans,
} = truncated;
let ellipsis_style = spans.last().map(|span| span.style).unwrap_or_default();
spans.push(Span::styled("", ellipsis_style));
Line {
style,
alignment,
spans,
}
}

View File

@@ -2,5 +2,5 @@
source: tui/src/status_indicator_widget.rs
expression: terminal.backend()
---
"• Working (0s • esc "
"• Working (0s • esc"
" "

View File

@@ -23,6 +23,7 @@ use crate::app_event::AppEvent;
use crate::app_event_sender::AppEventSender;
use crate::exec_cell::spinner;
use crate::key_hint;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::render::renderable::Renderable;
use crate::shimmer::shimmer_spans;
use crate::text_formatting::capitalize_first;
@@ -253,7 +254,10 @@ impl Renderable for StatusIndicatorWidget {
}
let mut lines = Vec::new();
lines.push(Line::from(spans));
lines.push(truncate_line_with_ellipsis_if_overflow(
Line::from(spans),
usize::from(area.width),
));
if area.height > 1 {
// If there is enough space, add the details lines below the header.
let details = self.wrapped_details_lines(area.width);

View File

@@ -44,7 +44,7 @@ where
let opts = width_or_options.into();
let mut lines: Vec<Range<usize>> = Vec::new();
let mut cursor = 0usize;
for line in textwrap::wrap(text, opts).iter() {
for (line_index, line) in textwrap::wrap(text, &opts).iter().enumerate() {
match line {
std::borrow::Cow::Borrowed(slice) => {
let start = unsafe { slice.as_ptr().offset_from(text.as_ptr()) as usize };
@@ -54,7 +54,12 @@ where
cursor = end + trailing_spaces;
}
std::borrow::Cow::Owned(slice) => {
let mapped = map_owned_wrapped_line_to_range(text, cursor, slice);
let synthetic_prefix = if line_index == 0 {
opts.initial_indent
} else {
opts.subsequent_indent
};
let mapped = map_owned_wrapped_line_to_range(text, cursor, slice, synthetic_prefix);
let trailing_spaces = text[mapped.end..].chars().take_while(|c| *c == ' ').count();
lines.push(mapped.start..mapped.end + trailing_spaces + 1);
cursor = mapped.end + trailing_spaces;
@@ -74,7 +79,7 @@ where
let opts = width_or_options.into();
let mut lines: Vec<Range<usize>> = Vec::new();
let mut cursor = 0usize;
for line in textwrap::wrap(text, opts).iter() {
for (line_index, line) in textwrap::wrap(text, &opts).iter().enumerate() {
match line {
std::borrow::Cow::Borrowed(slice) => {
let start = unsafe { slice.as_ptr().offset_from(text.as_ptr()) as usize };
@@ -83,7 +88,12 @@ where
cursor = end;
}
std::borrow::Cow::Owned(slice) => {
let mapped = map_owned_wrapped_line_to_range(text, cursor, slice);
let synthetic_prefix = if line_index == 0 {
opts.initial_indent
} else {
opts.subsequent_indent
};
let mapped = map_owned_wrapped_line_to_range(text, cursor, slice, synthetic_prefix);
lines.push(mapped.clone());
cursor = mapped.end;
}
@@ -99,7 +109,18 @@ where
/// function walks the owned string character-by-character against the
/// source, skipping trailing penalty chars, and returns the
/// corresponding source byte range starting from `cursor`.
fn map_owned_wrapped_line_to_range(text: &str, cursor: usize, wrapped: &str) -> Range<usize> {
fn map_owned_wrapped_line_to_range(
text: &str,
cursor: usize,
wrapped: &str,
synthetic_prefix: &str,
) -> Range<usize> {
let wrapped = if synthetic_prefix.is_empty() {
wrapped
} else {
wrapped.strip_prefix(synthetic_prefix).unwrap_or(wrapped)
};
let mut start = cursor;
while start < text.len() && !wrapped.starts_with(' ') {
let Some(ch) = text[start..].chars().next() else {
@@ -112,6 +133,7 @@ fn map_owned_wrapped_line_to_range(text: &str, cursor: usize, wrapped: &str) ->
}
let mut end = start;
let mut saw_source_char = false;
let mut chars = wrapped.chars().peekable();
while let Some(ch) = chars.next() {
if end < text.len() {
@@ -120,6 +142,7 @@ fn map_owned_wrapped_line_to_range(text: &str, cursor: usize, wrapped: &str) ->
};
if ch == src {
end += src.len_utf8();
saw_source_char = true;
continue;
}
}
@@ -131,7 +154,20 @@ fn map_owned_wrapped_line_to_range(text: &str, cursor: usize, wrapped: &str) ->
continue;
}
panic!("wrap_ranges: could not map owned line {wrapped:?} to source near byte {cursor}");
// Non-source chars can be synthesized by textwrap in owned output
// (e.g. non-space indent prefixes). Keep going and map the source bytes
// we can confidently match instead of crashing the app.
if !saw_source_char {
continue;
}
tracing::warn!(
wrapped = %wrapped,
cursor,
end,
"wrap_ranges: could not fully map owned line; returning partial source range"
);
break;
}
start..end
@@ -1229,6 +1265,124 @@ them."#
);
}
#[test]
fn map_owned_wrapped_line_to_range_recovers_on_non_prefix_mismatch() {
// Match source chars first, then introduce a non-penalty mismatch.
// The function should recover and return the mapped prefix range.
let range = map_owned_wrapped_line_to_range("hello world", 0, "helloX", "");
assert_eq!(range, 0..5);
}
#[test]
fn map_owned_wrapped_line_to_range_indent_coincides_with_source() {
// When the synthetic indent prefix starts with a character that also
// appears at the current source position, the mapper must not confuse
// the indent char for a source match. Here the indent is "- " and the
// source text also starts with "-", so a naive char-by-char match would
// consume the source "-" for the indent "-", set saw_source_char too
// early, then break on the space — returning 0..1 instead of the full
// first word.
let text = "- item one and some more words";
// Simulate what textwrap would produce for the first continuation line
// when subsequent_indent = "- ": it prepends "- " to the source slice.
let range = map_owned_wrapped_line_to_range(text, 0, "- - item one", "- ");
// The mapper should skip the synthetic "- " prefix and map "- item one"
// back to source bytes 0..10.
assert_eq!(range, 0..10);
}
#[test]
fn wrap_ranges_indent_prefix_coincides_with_source_char() {
// End-to-end: source text starts with the same character as the indent
// prefix. wrap_ranges must still reconstruct the full source.
let text = "- first item is long enough to wrap around";
let opts = || {
textwrap::Options::new(16)
.initial_indent("- ")
.subsequent_indent("- ")
};
let ranges = wrap_ranges(text, opts());
assert!(!ranges.is_empty());
let mut rebuilt = String::new();
let mut cursor = 0usize;
for range in ranges {
let start = range.start.max(cursor).min(text.len());
let end = range.end.min(text.len());
if start < end {
rebuilt.push_str(&text[start..end]);
}
cursor = cursor.max(end);
}
assert_eq!(rebuilt, text);
}
#[test]
fn map_owned_wrapped_line_to_range_repro_overconsumes_repeated_prefix_patterns() {
let text = "- - foo";
let opts = textwrap::Options::new(3)
.initial_indent("- ")
.subsequent_indent("- ")
.word_separator(textwrap::WordSeparator::AsciiSpace)
.break_words(false);
let wrapped = textwrap::wrap(text, opts);
let Some(line) = wrapped.first() else {
panic!("expected at least one wrapped line");
};
let mapped = map_owned_wrapped_line_to_range(text, 0, line.as_ref(), "- ");
let expected_len = line
.as_ref()
.strip_prefix("- ")
.unwrap_or(line.as_ref())
.len();
let mapped_len = mapped.end.saturating_sub(mapped.start);
assert!(
mapped_len <= expected_len,
"overconsumed source: text={text:?} line={line:?} mapped={mapped:?} expected_len={expected_len}"
);
}
#[test]
fn wrap_ranges_recovers_with_non_space_indents() {
let text = "The quick brown fox jumps over the lazy dog";
let wrapped = textwrap::wrap(
text,
textwrap::Options::new(12)
.initial_indent("* ")
.subsequent_indent(" "),
);
assert!(
wrapped
.iter()
.any(|line| matches!(line, std::borrow::Cow::Owned(_))),
"expected textwrap to produce owned lines with synthetic indent prefixes"
);
let ranges = wrap_ranges(
text,
textwrap::Options::new(12)
.initial_indent("* ")
.subsequent_indent(" "),
);
assert!(!ranges.is_empty());
// wrap_ranges returns cursor-oriented ranges that may overlap by one byte;
// rebuild with cursor progression to validate full source coverage.
let mut rebuilt = String::new();
let mut cursor = 0usize;
for range in ranges {
let start = range.start.max(cursor).min(text.len());
let end = range.end.min(text.len());
if start < end {
rebuilt.push_str(&text[start..end]);
}
cursor = cursor.max(end);
}
assert_eq!(rebuilt, text);
}
#[test]
fn wrap_ranges_trim_handles_owned_lines_with_penalty_char() {
fn split_every_char(word: &str) -> Vec<usize> {