You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
infinity-agent-cli: display truncation slices strings by byte index, can panic on non-ASCII #118
Follow-up to string-related review comments on #115. These byte-index slicing sites pre-date that PR (they exist on main both before and after the change), so they are collected here to be fixed in a separate PR.
Rust string slicing like &s[..n] operates on byte indices and panics if n is not a char boundary. All of the sites below truncate display strings this way. Thread IDs are currently ASCII UUIDs, but with remote-prefixed thread refs (remote/uuid, see #115) a remote name — and session titles already today — can contain non-ASCII, making these potential runtime panics.
Locations
crates/infinity-agent-cli/src/session_picker.rs — session name truncation (both the title and id branches):
Use a char-safe (or display-width-aware) truncation instead of byte slicing, e.g.:
s.chars().take(n).collect::<String>(), or
&s[..s.floor_char_boundary(n)] (stable since Rust 1.93), or
width-based truncation via unicode-width for correct terminal column alignment (note: the surrounding layout math in session_picker.rs also mixes str::len() byte lengths with chars().count() when computing label column ranges).
A small shared helper (e.g. fn truncate_display(s: &str, max: usize) -> &str) in infinity-agent-cli would cover all three sites.
Implemented in draft PR #180 (commit 61ae475854b9eaf6f2a6e35ff117aebd590ad24d).
Root cause: Arbitrary byte slices in the session picker and terminal short IDs could split UTF-8; remote label offsets mixed bytes and characters.
Fix boundary: Keep every reported display slice on a UTF-8 boundary and calculate remote label offsets in character units.
Focused checks: CLI library 17 passed; tui_flow_snapshots 15 passed, including 3 new regression tests (the picker test covers 3 cases).
Runtime proof: cargo-run temporary example invoked the public terminal loop against a virtual terminal: status 1234567 | /help, child subscription [1234567] ⚡watch: changed, picker 123456….
Full all-target test run: 358 passed, 7 failed, 0 ignored. The exact same seven TUI snapshots fail on clean base 1abc6fcff1f186124f924b56aa92c3a3684c90c5 (355 passed, 7 failed). No baselines or tolerances were changed.
Doctests: 45 passed, 1 ignored. Rust formatting, workspace Clippy with warnings denied, and all-target compilation passed. Independent read-only review found no blocking issues.
I am maintaining this proposed fix. The PR remains Draft, not ready or merged: full checks are not green, remote CI currently lists no checks, and maintainer review remains outstanding. The repository script skipped docs/UI Prettier because node_modules are absent; optional browser e2e and THIRD-PARTY verification were not reached after the test gate failed. No live model account was used. No merge, Issue closure, or deployment has been performed.
Activity
kaluli123123 commentedon Nov 3, 2026
Implemented in draft PR #180 (commit
61ae475854b9eaf6f2a6e35ff117aebd590ad24d).1234567 | /help, child subscription[1234567] ⚡watch: changed, picker123456….1abc6fcff1f186124f924b56aa92c3a3684c90c5(355 passed, 7 failed). No baselines or tolerances were changed.I am maintaining this proposed fix. The PR remains Draft, not ready or merged: full checks are not green, remote CI currently lists no checks, and maintainer review remains outstanding. The repository script skipped docs/UI Prettier because node_modules are absent; optional browser e2e and THIRD-PARTY verification were not reached after the test gate failed. No live model account was used. No merge, Issue closure, or deployment has been performed.