- Handled local resumes with missing source CWD by prompting to move and reopening sessions.
- Shared missing-CWD relocation logic between local and global resumes for consistency.
- Added regression test for local explicit-session-dir resumes and session-header cwd updates.
- Tracked kitty-dot payload listings to emit BEL-terminated OSC5522 responses.
- Updated non-kitty-dot writes to include mime in metadata and drop ST terminator.
- Adjusted enhanced-paste tests to assert BEL terminator and metadata formatting.
- Updated startup handling so `applyStartupCwd` now re-syncs `parsed.cwd` to the resolved absolute project directory after `setProjectDir` runs.
- Adjusted the CLI cwd tests to verify a relative `--cwd` argument is normalized to an absolute path and does not double-resolve against the new process cwd.
- Added an interrupt state in EventController to switch the working label to `Interrupting...` and suspend intent-driven updates until the turn resets.
- Called `notifyInterrupting()` from streaming-interrupt paths in InputController and exposed it on InteractiveModeContext so Esc acknowledgement shows immediately while tools tear down.
- Added tests to verify loader acknowledgement, freeze of late intent updates during interruption, and label updates resuming on the next agent start.
- Changed the `github-copilot` service provider to resolve credentials only from `COPILOT_GITHUB_TOKEN`.
- Updated CLI extra help text to document `COPILOT_GITHUB_TOKEN` as the GitHub Copilot environment variable.
- Reworded environment variable docs to reflect the revised Copilot/GitHub token usage and order.
When a session's working directory is moved or renamed (e.g. `git worktree
move`), the session file stays under the old cwd-encoded bucket while the new
directory is empty. Resuming was lossy:
- `--continue` rejected the terminal breadcrumb purely on cwd mismatch and then
found nothing in the new bucket, silently starting a fresh empty session.
- cross-project `--resume <id>` only offered to *fork* (duplicate) the session
into the new directory, forcing manual id selection and leaving a stale copy.
Detect relocation via the strong, low-false-positive signal "recorded cwd no
longer exists on disk" and re-root in place with the existing `moveTo()`:
- `continueRecent` re-roots the terminal's last session into the current
directory when its recorded cwd is gone and the new location has no sessions
of its own (otherwise behavior is unchanged). `readTerminalBreadcrumb` is
refactored into `readTerminalBreadcrumbEntry` returning the raw cwd +
session file so callers can interpret a cwd mismatch.
- cross-project `--resume <id>` offers "Move (re-root)" instead of fork when the
source directory is gone; a still-existing different project still forks.
Tests: continue-relocation (re-root on move, no-hijack on plain cd, prefer
local recent) and cross-project move-vs-fork routing.
`finalizeSubprocessOutput` always spliced collected `report_finding`
entries onto a top-level `findings` array regardless of the active output
schema. A caller-supplied schema with `additionalProperties: false` and
no `findings` property would accept the raw payload in-tool (via the
`yield` validator, which only sees the pre-injection data) but then fail
post-mortem validation — emitting `schema_violation: findings: must not
be present` and propagating as a fatal `RuntimeError` through
`agent-bridge.ts` and the eval Python/JS preludes, collapsing the entire
workflow cell along with any prior successful subagent work.
`normalizeCompleteData` now takes the resolved validator and only
performs the injection when the augmented candidate validates. When the
schema rejects it, the raw payload is returned instead — which the in-
tool yield validator already accepted, so the lockstep guarantee
documented at the top of `output-schema-validator.ts` is honored.
Findings remain visible via the agent progress stream and JSONL
artifact, so no information is dropped when injection is suppressed.
Both finalize call paths (yield-success and no-yield fallback) now share
the single validator build instead of constructing it twice, and the
yield-path schema_violation branch is now reached only via the
explicit malformed-schema check, never via spurious findings rejection.
Fixes#2070
MCPTool and DeferredMCPTool now declare approval = 'write' instead of
implicitly defaulting to 'exec'. Without this, the approval system
requires user confirmation for every MCP tool call in non-yolo modes,
but the confirmation prompt never renders in the TUI while streaming,
causing the agent to hang indefinitely.
Also propagate the approval property through customToolToDefinition()
in sdk.ts, which was silently dropping it during CustomTool ->
ToolDefinition conversion.
Kitty implements OSC 5522 paste-event listings by sending one DATA
packet whose mime field decodes to the literal dot sentinel and whose
payload carries the available types as a whitespace-separated list. The
TUI previously only honored the ancillary per-type DATA-packet form, so
plain-text Kitty pastes were rejected as unsupported.
Decode the dot-listing payload during the listing phase and keep the
per-type packet path as a fallback. Also emit the follow-up OSC 5522 read
request using the Kitty protocol shape: the selected MIME list belongs in
the request payload, not in mime metadata. Sending it as metadata makes
Kitty parse an empty requested MIME list and returns no clipboard bytes,
which surfaces as an empty paste.
Add regression coverage for Kitty's text-only and multi-type listings,
and assert the payload-form read requests for default and primary
selection paste events.
Fixes#2051
Kitty implements the OSC 5522 "list available MIME types" reply by
sending one DATA packet whose `mime` field decodes to the literal `.`
and whose payload carries the available types as a whitespace-separated
list (see `fulfill_read_request` in kovidgoyal/kitty:kitty/clipboard.py
when the requested MIME is `TARGETS_MIME = '.'`). The 5522-mode
ancillary spec (rockorager.dev/misc/bracketed-paste-mime) instead
encodes each available type as its own DATA packet with an empty
payload.
The TUI's EnhancedPasteController only honored the ancillary form. When
Kitty delivered the dot-listing form for a plain-text paste, the parser
pushed `.` into the candidate list, `choosePasteMime(["."])` matched
nothing, and the editor surfaced "Clipboard paste has no supported text
or image data" instead of inserting the text.
Decode the payload as a UTF-8 whitespace-separated MIME list when the
DATA packet's mime is the dot sentinel, then fall through to the
existing per-type behavior. Add two regression tests covering the
single-type and multi-type Kitty payload shapes.
Fixes#2051
Route follow-up shortcut submissions through the builtin slash-command dispatcher before queueing them as deferred prompts.
Added regression coverage for /goal set submitted through InputController.handleFollowUp while a stream is active.
Fixes#2038
handleCtrlZ called process.kill(0, "SIGTSTP") unconditionally; on
Windows the runtime rejects the signal name with TypeError, which
propagated out of the TUI input dispatcher and crashed the agent
with an [Uncaught Exception]. Even on POSIX the call could fail
(sandboxes that block sending to pid=0, runtime-reserved signals),
and a thrown error after we already stopped the TUI and registered
a one-shot SIGCONT listener left the UI stranded with a leaked
handler that would fire on the next unrelated continue and try to
re-start() an already-running TUI.
Branch on process.platform first so Windows shows a status notice
and never calls process.kill, and wrap the POSIX kill in try/catch
that removes the SIGCONT listener and re-starts the TUI on failure.
Fixes#2036
- Added a `showHeader` option to shell rendering and suppressed the bash frame title bar by default.
- Parsed trailing raw-output artifact notices and folded their IDs into status footer metadata instead of command output.
- Updated read-group rendering to use the enabled success mark and omitted duplicate success marks on child files in grouped reads.
- Adjusted find and search renderers to apply tool-title coloring, search icons, and padded layout via createCachedComponent.
- Added tests covering read-group success marking and padded find/search renderer output.
- Added `display.smoothStreaming` to settings schema.
- Updated streaming-reveal behavior to produce smooth 30 FPS reveals.
- Updated event-controller flow to support smooth streaming reveal mode.
- Expanded streaming-reveal tests for the new smooth streaming behavior.
- Added regression coverage for EventController to collapse single-read completions into one read group.
- Added assertions that visible reasoning breaks grouping and finalizes the prior read block.
- Added nested-live task rendering test for static task header while the task body shimmers.
- Added task-progress rendering tests for shimmered task-name rows and spinner-disabled fallback.
- Added a ToolExecutionComponent timing test validating bash spinnerFrame increments on 30fps cadence.
- Reduced shimmer-driven UI animations and borders to a 30fps cadence.
- Collapsed consecutive read tool calls into one finalized transcript block.
- Tracked visible assistant content to finalize and reset read groups correctly.
- Updated running task rows to static bullet markers with shimmer-only subagent labels.
- Updated task call and result rendering to process shared context with the Markdown renderer, so context sections are now displayed with proper Markdown formatting.
- Stopped shimmer animation on pending bash/eval/task blocks once async state is `running`, preventing the committed frame from freezing a transient dark border segment.
- Adjusted rule path display to fall back to a root-relative path when cwd-relative resolution is unavailable.
- Updated the initial render intent to carry a `clearScrollback` flag.
- Adjusted first-frame rendering logic to preserve existing scrollback by default and clear only when requested.
- Added `resolver` stubs to coding-agent and web-search test registries for interface compatibility.
- Added a clear-initial-terminal-history flag to interactive mode initialization and passed it from cold-launch startup.
- Extended TUI.start to accept clearScrollback and clear native scrollback on initial full paint for non-multiplexer sessions.
- Preserved ED3 streaming scrollback accounting during capped streaming frames and added tests to prevent committed prefix duplication across terminal history rewrites.
- Marked Markdown cached lines as readonly snapshots and returned copied arrays from `render()`.
- Stored fresh snapshot arrays in both L1 and L2 caches so callers appending rows cannot mutate shared cached Markdown output.
- Added an AskTool test that renders calls and results twice to verify repeated renders remain stable and do not duplicate option labels.
- Updated InputController streaming submit handling to interrupt and resume when queued steering exists, refreshing the pending-message UI and render.
- Added AgentSession.interruptAndFlushQueuedMessages to abort active work and continue processing queued messages immediately.
- Added tests for queued steering interruption in both agent-session concurrency and input-controller keybinding flows.
- Replaced approved-plan renaming with `resolveApprovedPlan` resolution and state/slug lookup.
- Updated ACP and interactive apply flows to propagate canonical `planFilePath` instead of renamed paths.
- Added local plan fallback lookup by mtime for unresolved slugs after plan approval.
- Restricted plan-mode writes to `local://` plan artifacts and simplified path handling.
- Extended `OutputBlock` section metadata with an optional `separator` flag and included it in cache hashing.
- Updated output block rendering to emit an unlabeled section divider when the separator flag is enabled.
- Marked task and result render paths to request separators for non-context content sections to improve output clarity.
- Added a configurable `contentPaddingLeft` option to `renderOutputBlock` with normalized defaults.
- Updated edit renderer output blocks to disable inherited left padding and align inner-width wrapping.
- Added coverage for completed edit gutter rendering to confirm no leading space and correct frame width.
- Passed a formatted TTSR match message into the agent abort call when streaming is interrupted by TTSR rules.
- Added a `#formatTtsrAbortReason` helper to include matched rule names in the abort reason.
- Added a concurrent-session test confirming aborted tool results mention the matched TTSR rule instead of `Request was aborted`.