Commit Graph

576 Commits

Author SHA1 Message Date
can1357 c7ecc3ef66 Merge PR #8598: fix(session): repair torn JSONL appends (@roboomp)
# Conflicts:
#	packages/coding-agent/src/session/session-loader.ts
#	packages/coding-agent/src/session/session-manager.ts
#	packages/coding-agent/test/session-loader-stream.test.ts
2026-08-16 02:48:12 +02:00
can1357 8a921148e8 Merge PR #8652: fix(tui): bound shimmer animation CPU (@roboomp) 2026-08-16 02:43:31 +02:00
can1357 db056bd8cb chore(repo): applied biome formatting 2026-08-16 02:15:26 +02:00
can1357 a7e810c6cc Merge PR #8444: fix(tui): keep btw panels out of scrollback (@Ant39140) 2026-08-16 02:13:38 +02:00
can1357 7e4fd9a686 Merge PR #8428: fix(tui): welcome banner shows stale model name after model changes (@jacobleft) 2026-08-16 02:03:17 +02:00
Ant39140 9f8eb090cb Merge remote-tracking branch 'upstream/main' into fix/btw-scrollback 2026-08-15 22:31:03 +08:00
roboomp 62eb6d40b8 fix(tui): bounded magic-keyword shimmer cpu
- Routed focused editor animation through cursor-aware direct row writes.

- Preserved cursor marker bookkeeping and native scrollback across marker changes.

- Added fixed-geometry, fallback, and editor integration regressions.

Fixes #8646
2026-08-15 13:17:49 +00:00
roboomp 9ae089d71b fix(session): repaired torn JSONL appends
Rolled partial file appends back to their pre-write size and marked malformed resumed sessions for an atomic rewrite.

Retried transient persistence failures from in-memory state and surfaced the first failure in the interactive TUI.

Fixes #8596
2026-08-15 00:34:41 +00:00
can1357 b279db1790 test: refactored test suites to eliminate time-based sleeps and polling loops
- Replaced time-based sleeps and polling loops with event-driven promise resolvers and fake timers across agent and tool tests.
- Migrated test suites to share in-memory auth storage and fixtures using lifecycle hooks.
- Updated catalog model definitions, metadata, and configurations.
2026-08-13 19:32:22 +02:00
can1357 28997c0d46 refactor(coding-agent): restructured transcript rendering during initialization
- Stage transcript initialization inside a detached TranscriptContainer to keep existing messages visible during incremental rendering.
- Add fallback state restoration in InteractiveMode.renderInitialMessages when chat rendering is aborted or fails.
- Update render-initial-messages tests to assert that old transcripts remain visible until replacements are fully committed.
2026-08-13 18:55:36 +02:00
Ant39140 45b023cd83 fix(tui): keep btw panels out of scrollback 2026-08-14 00:09:56 +08:00
jacobleft 7b5921abc5 fix(tui): request repaint after catch-up model sync
setModel() invalidates the render cache but doesn't schedule a paint.
The initial forced startup paint (line 1104) may have already rendered
the old model, so the catch-up #updateWelcomeModel() must explicitly
request a render — matching #updateWelcomeLspServers().
2026-08-13 19:34:21 +08:00
jacobleft 272a0e8461 fix(tui): resync welcome banner after init-time model changes
Address review feedback: init-time model switches (#reconcileModeFromSession,
#enterPlanMode for plan.defaultOnStartup) fire model_changed before the
subscription exists, leaving the banner stale for those cases too.

Adds a catch-up #updateWelcomeModel() call right after the subscription is
installed, mirroring how the sessionName listener is registered before
those same init steps (line 1094-1095 comment).

Also adds a regression test for the catch-up path and comments tying the
component test to the wiring gap it covers.
2026-08-13 19:22:05 +08:00
jacobleft 9bb18d3e0e fix(tui): update welcome banner model name on model_changed event
The welcome banner (WelcomeComponent) captures the session's active
model name at init time but never receives updates when the model
changes. Its setModel() method already existed but was never called
after construction.

This wires the model_changed agent session event to a new
#updateWelcomeModel() method in InteractiveMode, mirroring the
existing #updateWelcomeLspServers() pattern. The banner now reflects
the live model after:
- delayed config/modelRoles load (the startup race where an
  alphabetically-first provider is picked before config resolves)
- explicit /model switches
- retry-fallback model swaps
2026-08-13 19:05:36 +08:00
can1357 2481c5c30d fix(coding-agent): consume mode command drafts before skill turns 2026-08-13 01:21:57 +02:00
can1357 e1039f6a34 Merge PR #8138: fix(coding-agent): interpret inline skill directive in mode-command prompts (@roboomp)
# Conflicts:
#	packages/coding-agent/src/modes/interactive-mode.ts
2026-08-13 01:20:47 +02:00
can1357 193894c8d4 Merge PR #8135: fix(tui): keep large transcript rebuilds responsive (@roboomp)
# Conflicts:
#	packages/coding-agent/test/modes/utils/render-initial-messages.test.ts
2026-08-13 01:16:23 +02:00
Jeff Scott Ward 75a233a000 fix(mcp): show config source in startup failures 2026-08-12 01:26:28 -04:00
can1357 20732b5355 Merge PR #8273: fix(tui): hide remaining activity in hidden-tool mode (@dannyboy-ai) 2026-08-12 01:53:53 +02:00
Daniel Anderson-Little e4dc5c9637 refactor(coding-agent): clarify warning activity policy 2026-08-11 17:52:05 -04:00
Daniel Anderson-Little d50e47d2af fix(coding-agent): align activity visibility contract 2026-08-11 17:26:33 -04:00
Daniel Anderson-Little cbd7dc2e70 fix(coding-agent): centralize hidden activity state 2026-08-11 17:07:20 -04:00
Daniel Anderson-Little 3a4ea6a376 fix(coding-agent): hide internal tool activity blocks 2026-08-11 16:59:53 -04:00
roboomp dbc199d2db fix(coding-agent): copy local artifacts across handoff session boundary
/handoff mints a fresh session via newSession(), producing a new
artifactsDir and an empty local/ root. The handoff document routinely
references plans and scratch files under '/data/workspaces/can1357__oh-my-pi__8261/.omp-session/2026-08-11T16-39-09-489Z_019ff1b1-31b1-7000-81f5-c540f4ebf43d/local/,' so every reference
became a dangling pointer in the new session. The plan approve-and-execute
path already copies artifacts across the boundary; handoff did not.

Extracted the plan-approve copy helper into a shared copyLocalArtifacts()
in local-protocol.ts and invoke it across the handoff session switch
(best-effort, since the switch is already committed).

Fixes #8261
2026-08-11 16:45:15 +00:00
can1357 64baa7c1bd chore(format): applied biome formatting and removed dead code from merged prs 2026-08-11 15:14:15 +02:00
Vanko ed820703a7 fix(extension-api): restore overlayOptions/onHandle passthrough in ui.custom
showHookCustom hardcoded the overlay geometry and never read
overlayOptions/onHandle, which regressed the v0.45.6 API (PR
badlogic/pi-mono#667). Forward overlayOptions to showOverlay (keeping the
full-cover defaults as fallback), invoke onHandle with the returned
OverlayHandle, widen the options type via a shared ExtensionCustomOptions,
and re-export OverlayHandle/OverlayOptions from the extension API.
2026-08-11 15:08:39 +02:00
can1357 7896a58406 Merge PR #8050: fix(tui): keep pasted images when a mode command submits the draft (@fatihaziz) 2026-08-11 15:06:13 +02:00
can1357 66a55fb916 Merge PR #7983: fix(vibe): restore the pre-vibe toolset when switching between vibe sessions (@iskWang) 2026-08-11 15:06:12 +02:00
can1357 f6d4f1e38b Merge PR #7965: fix(coding-agent): surface todo progress in the collapsed panel (@z80dev) 2026-08-11 15:06:12 +02:00
Fatih Al-Aziz 8a22872ece fix(tui): preserve mode submissions across async input 2026-08-11 16:46:45 +07:00
Fatih Al-Aziz de9ee6d412 fix(tui): preserve mode attachments across async paths 2026-08-11 16:25:20 +07:00
Fatih Al-Aziz d194f2d76c fix(tui): honor transformed mode attachments 2026-08-11 15:52:58 +07:00
roboomp af31ae4885 fix(coding-agent): interpret inline /skill in mode-command prompts
`/plan <prompt> /skill:name` (and `/vibe`) delivered the skill token to
the agent as literal text. Mode commands strip their slash prefix and
resubmit the remaining prompt through onInputCallback ->
submitInteractiveInput -> session.prompt(), a path with no skill
dispatch, so the invocation was never interpreted.

Route mode-command inline prompts through a shared
#submitModeInitialPrompt helper that dispatches registered skills via
the same custom-message path as the editor submit flow, falling back to
a normal prompt otherwise.

Fixes #8137
2026-08-10 05:49:35 +00:00
roboomp 94c51945d4 fix(tui): chunked large transcript rebuilds
Replayed idle transcripts in bounded message and time chunks, painting cleared scrollback between macrotasks so terminal input remains responsive during restore and tree navigation. Kept streaming rebuilds atomic and migrated every rebuild caller to await completion.

Fixes #8133
2026-08-10 05:30:18 +00:00
Josh Mini bb5bfb2c04 fix(vibe): only override the vibe snapshot when teardown lost the live toolset
The persisted pre-vibe snapshot was applied on every reconciliation that
re-entered vibe mode, including cold resumes and switches in from a non-vibe
session. Those paths build their toolset from the current CLI flags and
settings, so replacing it with a historical snapshot silently drops tools the
session was started with: resuming a session that entered vibe under
--tools read with --tools read,bash restored only read on exit.

Gate the override on the one case the snapshot exists for: the vibe -> vibe
switch, where #clearTransientModeState kept the already-reduced live set.
2026-08-09 11:23:07 +08:00
Fatih Al-Aziz 276f1dd3b2 fix(tui): keep pasted images when a mode command submits the draft
`/goal <objective>`, `/plan <prompt>` and `/vibe <prompt>` promote the
composer draft into the first turn, but built their submission from the
draft *text* only:

    this.onInputCallback(this.startPendingSubmission({ text: objective }));

The editor-submit path in `InputController` passes
`editor.pendingImages`/`pendingImageLinks` alongside the text; these four
call sites did not. A draft holding pasted screenshots therefore reached
the model with its positional `[Image #N, WxH]` markers intact and every
image payload missing, so the agent saw markers pointing at nothing and
`read "Image #1"` resolved against an empty list.

The payload was not only dropped, it also outlived the draft: the mode
commands cleared the composer with `editor.setText("")`, which leaves
`pendingImages` attached. The orphans then rode along with whatever the
user typed next, one index off, which is how a later message can attach a
screenshot the user never re-pasted.

Measured on 259 image-bearing user messages across 10 local session logs
(v17.2.x): 36 of 37 messages submitted as a goal objective lost every
image, against 190 of 198 preserved on the ordinary submit path.

Fix:
- `#takeDraftImages()` detaches the composer's pending images and links,
  and all four mode-command submissions spread it into
  `startPendingSubmission` (`cancelPendingSubmission` already restores
  them when a submission is cancelled).
- `/goal`, `/guided-goal`, `/plan` and `/vibe` clear the draft with
  `editor.clearDraft()` instead of `editor.setText("")`, so images can
  never outlive the text they were pasted into (the streaming branch of
  `/goal` never submits, so its draft must die whole).

Tests: two regression cases in `goal-mode-integration.test.ts` assert the
objective submission carries the image and empties the composer; both
fail on the previous behaviour with `images: undefined`. The `/plan`,
`/goal` and `/guided-goal` slash stubs now model `clearDraft`.
2026-08-09 08:38:09 +07:00
Josh Mini 1e142aace9 fix(vibe): restore the pre-vibe toolset when switching between vibe sessions
Entering /vibe snapshotted the live toolset into an in-memory field only.
When a session already in vibe mode switches into another session that is also
in vibe mode, #clearTransientModeState takes the removeVibeToolsPreservingActive
path, which deliberately keeps the live active set instead of applying the
source snapshot. #reconcileModeFromSession then re-enters vibe mode, and the
live toolset is by then the reduced vibe set, so the new snapshot was that
reduced set and exiting restored it instead of the target's real pre-vibe
toolset. bash, edit, write, grep, glob, task, and hub were silently gone for
the rest of the session.

Neither a cold start nor switching in from a non-vibe session is affected: the
teardown path does not run, so the live toolset is still the full one when the
snapshot is taken.

Record the snapshot on the vibe mode_change entry and read it back from
sessionContext.modeData on the re-entry path, mirroring how plan mode persists
planFilePath. Sessions written by older versions carry no snapshot and fall
back to the previous behaviour.
2026-08-08 13:39:01 +08:00
z80 40b2d534a0 fix(coding-agent): surface todo progress in the collapsed panel
While the agent worked through a plan, every sub-todo rendered unchecked
no matter how far along the run was: the phase header highlighted, the
task rows below it looked untouched. Three separate causes, all on the
collapsed path that is the default view.

`selectCollapsedTodos` dropped every closed row while a phase held open
work, so finishing a task only ever *removed* a line — the panel never
rendered a checked box until the whole phase settled. That also made the
card's completion animation dead code: `details.completedTasks` drives a
14-frame strike reveal at 65ms with a component render per tick, against
a row the viewport had already discarded. The existing animation test
missed it by asserting on `expanded: true`.

The viewport now keeps the newest closed task as a checked lead row,
additive to the open-task cap so it never evicts open work, and the
strike sweep lands where users actually see it.

Second, the card gave a `done/total` count to every collapsed untouched
phase but not to the active one, so the phase being worked in was the
single phase reporting no progress. Extracted `formatPhaseProgress` and
put it on every phase header.

Third, the todo auto-clear (`tasks.todoClearDelay`, default 60s) armed
on any list holding a closed task and physically deleted those tasks
from the HUD's copy. An in-flight phase at `3/4` silently became `0/1`
sixty seconds later, fully-closed phases vanished, and stage roman
numerals renumbered off the filtered index — until the next `todo` call
restored the real snapshot. It now fires only once the whole list is
settled, which is the case the setting exists for; the walking viewport
already hides closed rows while work remains.

Progress counters also count closed tasks rather than only completed
ones. The viewport hides abandoned tasks too, so counting only
completions left a phase reading permanently stuck.
2026-08-07 19:49:31 -04:00
Mantas Vidutis fd3e665310 fix(coding-agent): reset the deferred command queue as a unit
clearTransientSessionUi zeroed the command count and disposed the
preview container but left the queued components and their session id in
place, so a command run after a same-session reset previewed the stale
panel alongside the new one. Clear all three together.
2026-08-07 07:50:27 -07:00
Mantas Vidutis bf55edabb2 fix(coding-agent): render deferred command output above the editor immediately
Follow-up to the queued-count hint: show the panel itself, not just a count.

Since 17.0.1 (d3f4830ce, fixing #4806) panel commands queued their output
until the turn settled, so /usage and /advisor status could not answer while
the agent worked. Issue #4806's reporter explicitly offered two acceptable
fixes - output once, or show it in a separate overlaying window during
streaming - and only the first was built.

The panel now renders in the anchored container above the editor, which is
outside the transcript and therefore cannot duplicate rows in native
scrollback, and the full output still mounts in the transcript at the settle.
Capped at 40% of the viewport (min 6 rows) so a tall report cannot push the
prompt off screen.
2026-08-06 13:11:58 -07:00
Mantas Vidutis f309176564 fix(coding-agent): acknowledge deferred command output above the editor
/usage, /advisor status and every other panel command already queued their
output until the agent settled, but the deferral was silent, so mid-turn the
command was indistinguishable from a dead one.

The acknowledgment reverted in d9d911a58 used showStatus, which mounts into
the transcript; any mid-turn transcript mount re-renders rows below the
growing live block and duplicates them in native scrollback (#4806/#6767).
This uses an anchored container above the editor instead, cleared and rebuilt
in place, which is the same surface the ctrl+p role-cycle track uses for
exactly that reason.
2026-08-06 12:51:23 -07:00
can1357 d9d911a58d fix(coding-agent): kept mid-turn command deferral silent
- Reverted the status-line acknowledgment added for deferred panel
  commands: showStatus mounts a Spacer+Text into the transcript, and any
  mid-turn transcript mount re-renders rows below the growing live block,
  duplicating them in native scrollback (issues #4806/#6767).
- The queue still flushes at every settle, terminal or not.
2026-08-06 14:18:50 +02:00
can1357 0d243ea425 Merge PR #7746: fix(tui): surface deferred command output instead of failing silently (@mvid) 2026-08-05 21:50:01 +02:00
Mantas Vidutis 006933ef06 docs(coding-agent): align presentCommandOutput doc with settle-time flush 2026-08-05 11:13:27 -07:00
can1357 e9888367d1 refactor: migrated packages to internal utility modules and removed external dependencies
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers.
- Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies.
- Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
2026-08-05 13:39:09 +02:00
Mantas Vidutis ced87b907b fix(tui): flush queued command panels at a non-terminal settle
Reaching the `isTerminal === false` branch means the superseded-turn guard
above it already passed, so `session.isStreaming` is false: a command
issued from that point mounts immediately while panels queued earlier in
the turn stay in `#pendingCommandOutput` until some later terminal
agent_end. Newer output rendered ahead of older, and the queued panel
could strand for minutes on an async fan-out that keeps settling
non-terminally.

Flush there too. The transcript is quiescent at a settle, which is the
condition #4806 wanted, and the notice now says "until the agent pauses"
rather than promising the current turn.
2026-08-04 11:47:54 -07:00
Mantas Vidutis f75d597f00 fix(tui): say when command output is deferred by a streaming turn
`presentCommandOutput` queues transcript panels while the agent streams,
so a growing turn cannot bury them, and flushes at turn end. It did that
silently, so `/usage` and `/advisor status` on a long multi-subagent turn
look like dead commands: nothing renders for minutes and the user retries
or assumes a crash. Acknowledge the deferral in the status line.
2026-08-04 11:36:08 -07:00
can1357 a418920ec1 feat: made /reset semantically different
Closes #4447
2026-08-03 15:46:46 +02:00
roboomp a54a2f79cb fix(tui): preserved b before /btw completion
Reserve the plain b shortcut only after /btw has a completed answer or a branch is already pending. Running, empty, aborted, and failed panels now leave the key for the composer, while completed-but-refused branches still consume it with an explanation.

Fixes #7474
2026-08-03 09:33:07 +00:00
roboomp 98f484bd2f fix(session): validated session identity for /btw branch
Branched session files preserve entry ids, so leaf-id equality alone let a stale /btw answer promote into a different loaded session. Capture the originating session id at /btw start and require it to match at both the controller gate and every branchFromBtw checkpoint.

Fixes #7474
2026-08-03 09:22:32 +00:00