- Replaced puppeteer-based WebRTC with native LiveWebRtcPeer for cross-platform live audio delivery.
- Added cross-platform microphone capture via miniaudio and Opus codec integration for live encoding/decoding.
- Added Apple DeviceCheck attestation token generation via raw Objective-C FFI for macOS.
- Updated live session model to "gpt-live-1-codex" and default voice to "sol" across protocol and controller.
- Added LiveWebRtcPeer and deviceCheckGenerateToken to the public native bindings API.
- Extracted #formatToolExecution into a standalone formatDefaultToolExecution module.
- Updated xdev renderXdevCall and renderXdevResult to use the default card when no mounted renderer exists.
- Added fallback rendering that shows tool label, args, and output with appropriate theming.
- Added integration test verifying generic card renders for mounted tools without bespoke renderers.
- Added cmp builtin with full POSIX-compatible flag support including `-b`, `-i`, `-l`, `-s`, `-x`, `-h`, `-z`.
- Integrated into shell builtin registry and coreutils module.
- Added comprehensive tests using tempfile for temporary directories.
- Catch execution errors in XdevRegistry and render them using the mounted tool's error handling.
- Preserve xdev dispatch context when device execution fails.
- Add `pinSessionOAuthAccount` storage method and active account flag to the auth storage API.
- Introduce session account selector component, controller logic, and interactive mode delegation.
- Implement the `/session pin` builtin slash command with text listing and account pinning capabilities.
- Add unit tests covering session account selection, component navigation, and command handling.
- Replaced resolveHangulCompatibilityJamoWidthFromTerminalIdentity with a
static hangulJamoWidth field on TerminalInfo (ghostty 2, warp 1,
platform otherwise); startup now reads TERMINAL.hangulJamoWidth.
requestRender(true) only queues the paint via setImmediate; calling
prewarm() synchronously afterwards put the worker spawn syscall ahead
of the render callback in the same loop turn. Schedule the prewarm
with its own setImmediate (FIFO after the render callback) so the
first startup frame paints before the subprocess spawns.
- Fixed a macOS clipboard bug where copied URL text like `https://i.can.ac/x.png` was coerced into a bogus HFS path (`/https/::i.can.ac:x.png`) and dead-ended with "Image not found" instead of falling through to text paste.
- The AppleScript now checks `clipboard info for "class furl"` before coercing so plain text/URL clipboards paste as text rather than file paths.
- Extracted the script to its own `.applescript` file and added TypeScript declarations for `.applescript` imports.
- Updated the OpenAI Codex provider to unroll native computer calls and tool outputs into standard function calls.
- Added support for the `PI_CODEX_RESPONSES_LITE` environment variable override via the request transformer.
- Updated documentation and tests to cover lite response resolution and native computer response unrolling.
- Added the upstream keyText helper to the legacy package-root shim.
- Covered active keybinding formatting and documented the compatibility fix.
Fixes#6470
#finalizeFile marked the sink finalized then ran the capped-artifact tail
replay before closing. A write error during that replay threw before
sink.end(), and because #finalized was already set the executor finally
paths calling dispose() could not retry the close, leaking the descriptor
and masking the original tool error.
Moved sink.end() into a finally around the tail replay and swallowed both
the replay and close errors so the descriptor is always released and
dispose() never throws.
The first interactive submit fired session.generateTitle() before
startPendingSubmission() painted the optimistic user row, and
tinyTitleClient.generate() spawned the local tiny-title subprocess
synchronously in #ensureWorker() before its first await. With a local
providers.tinyModel configured, subprocess-spawn latency therefore landed
ahead of the first frame, stalling the first prompt.
Paint the pending row before starting titling, and prewarm an idle,
unref'd worker at TUI startup via a no-op ping (no model load) so the
first submit reuses a live subprocess.
Fixes#6462
OutputSink.dump() was the only path that closed the spill Bun.FileSink.
The bash and Python executors re-throw on failure and their finally
blocks never closed the sink, so any large-output command that errored
leaked the artifact descriptor until an unrelated read (e.g. a SKILL.md
load) hit EMFILE.
Added an idempotent OutputSink.dispose() that closes the sink exactly
once (awaiting any in-flight sink creation, guarding post-finalize
resurrection) and wired it into every executor's finally block.
Fixes#6463
- Reused terminal identity detection to select Warp narrow and Ghostty wide profiles.
- Covered Warp resolution while preserving platform defaults for other terminals.
Fixes#6461
- Replaced the separate GUI-linked pi_natives.desktop.linux-x64 addon with
a pure-Rust X11 backend (x11rb RustConnection capture via RandR/GetImage,
XTest input with keysym mapping) compiled into the core addon on every
published target; Linux arm64 and musl are now supported and headless
hosts load the addon unaffected.
- Removed the native-desktop-linux cargo feature, desktop_unsupported.rs,
lazy desktop loader, second napi build, desktop packaging/CI steps, GUI
build dependencies, and the now-unreferenced vendored libspa crate;
reverted setup-system-deps to main.
- Preserved the desktop input hardening semantics on the unified backend:
XTest layouts reject negative origins and coordinates beyond 0..=32767,
batch coordinates stay bound to the frame last returned to JS with
intermediate screenshots deferred, coordinate input requires a
previously returned frame, and failed chord releases still release
every held key.
- Enforced a 60s worker-side execute deadline (DESKTOP_DEADLINE_EXCEEDED):
no input is emitted after expiry and wait-heavy batches are rejected
upfront.
- Added int32 fail-closed validation for coordinates, drag points, and
scroll deltas at the JS ingress and gateway schema.
- Exposed computer to models without native OpenAI computer-use support as
a regular function tool with a typed GA action schema across OpenAI,
Azure, and Codex Responses providers, including named forced choice.
- Added the /computer slash command (on/off/status/toggle) for
session-only enablement via runtime tool registration in SessionTools.
- Updated docs, changelogs, and contract tests accordingly.
- Shimmed writable select.value in export-html harness; linkedom's getter-only HTMLSelectElement.value made template.js theme assignment throw under strict mode.
- Bound the oauth-flow port blocker to 127.0.0.1 explicitly; macOS lets a specific-address bind coexist with a wildcard one, so the flow bound the blocked port and never fell back.
- Re-anchored atomic-rewrite race tests on rewriteEntries() after the compaction-supersede rewrite trigger was removed in cb63ebd.
- Superseded compaction summaries render as elided placeholders in the forward transcript since cb63ebd; only the active compaction keeps its text and frames.
fetchProviderModelsFromCatalog returning succeeded=true for an empty
discovery made every dynamicModelsAuthoritative provider drop its
models.dev and previous-snapshot rows after a flaky empty-but-200
response. Restored the fetched-models requirement for other providers;
only alibaba-token-plan treats an empty success as authoritative so the
subscribed-edition allowlist is not widened by the curated seed. Also
dropped the stray trailing newline in models.json that the generator
does not emit.
The alibaba-token-plan branch in resolveOpenAIRequestSetup accepted the
generic $env.OPENAI_API_KEY fallback as bearer material because generic
OpenAI keys match the broad sk-* token grammar. Throw MissingApiKeyError
when no provider-resolved credential is supplied.