When an uncaught exception fires in interactive mode, the process dies with
stdin still in raw mode and the cursor hidden, leaving the user with a
"borked" terminal that needs `stty sane && reset` to recover. The most
common trigger is an extension's async ChildProcess `exit` callback that
throws (e.g. from accessing a stale ctx after session replacement), but
this affects any uncaught throw from anywhere in pi.
Add an uncaughtException handler in registerSignalHandlers that calls
ui.stop() before exiting, mirroring the existing emergencyTerminalExit
pattern. The handler is registered with prependListener and tracked in
signalCleanupHandlers, so it is removed on graceful shutdown the same way
the other handlers are.
Unlike emergencyTerminalExit (used for SIGHUP / dead-terminal EIO), the
terminal is still alive on uncaughtException, so we run the normal
ui.stop() to restore cooked mode, the cursor, bracketed paste mode, and
Kitty / modifyOtherKeys sequences.
Skill slash commands store a structural <skill>...</skill> wrapper in raw
user messages. The TUI uses parseSkillBlock() to split this into separate
SkillInvocationMessageComponent and UserMessageComponent siblings, but the
HTML export renderer passed the full raw text through markdown, causing
broken/dangling XML tags to appear in exported HTML.
Add parseSkillBlock() to the export template and render skill-invocation
and user-message as separate sibling blocks:
- Sidebar tree shows skill name + user prompt separately
- Content area shows a clickable skill-invocation block (collapsed by
default, markdown content on expand) followed by the user message
- Copy-link button preserved on the wrapper element
- Toggle tools (O key) expands/collapses skill invocations alongside
compaction and tool output blocks
The @mariozechner/clipboard native addon uses clipboard-rs, which is
X11-only and does not retain selection ownership after set_text resolves.
On Wayland-only compositors (Hyprland, Niri, ...) /copy reported success
without populating the clipboard. Skip the native addon on Linux and let
wl-copy/xclip/xsel handle text writes; they properly daemonize.
closes#4177
* feat(coding-agent): allow comments and trailing commas in models.json
Run user-supplied models.json through a small `stripJsonComments` helper
before JSON.parse so users can annotate their config and leave trailing
commas without breaking the loader.
Co-Authored-By: julien-agent <Agents+cyolo@huggingface.co>
* fix(coding-agent): strip comments before trailing commas in models.json
The single-pass regex couldn't see a trailing comma when a `//` comment sat
between the comma and its closer. Split into two passes: strip comments
first, then strip trailing commas on the cleaned input.
Co-Authored-By: julien-agent <Agents+cyolo@huggingface.co>
---------
Co-authored-by: julien-agent <Agents+cyolo@huggingface.co>