Commit Graph
155 Commits
Author SHA1 Message Date
cognitive 0eb8d0fdcd feat(coding-agent/plan-mode): add "Approve and compact context" approval choice
A fifth ExitPlanMode approval choice — sits between the existing
"Approve and execute" (purge session) and "Approve and keep context"
(full transcript). Runs `handleCompactCommand` against the plan-mode
transcript with a planning-specific custom instruction rendered from
`plan-mode-compact-instructions.md`, then dispatches the plan-approved
synthetic prompt so it lands as the first entry in the freshly-
summarized transcript — giving execution a fresh cache anchor with
the rationale carried over.

Cancel/fail contract:
- ok       → bookkeeping runs, plan-approved synthetic prompt dispatched.
- cancelled → bookkeeping runs (tools restored, plan reference path
              recorded), warning surfaced, dispatch skipped.
              `markPlanReferenceSent` is intentionally deferred past
              the cancel guard so `AgentSession.#buildPlanReferenceMessage`
              re-injects the plan on the operator's next prompt() call.
              If we marked it sent on cancel, the executor's first turn
              would have no plan context.
- failed   → bookkeeping runs, error already surfaced by executeCompaction,
             dispatch proceeds best-effort. Approval intent stands.

Cancel vs. fail is discriminated via `instanceof CompactionCancelledError`
at the session/compaction error boundary (introduced in the previous
commit), so any abort source — operator Esc, extension hook, programmatic
abort — classifies uniformly without input-modality or message-string
coupling.

Op: extend
2026-05-12 23:01:06 +00:00
cognitive bad4c133e7 feat(coding-agent/session): typed CompactionCancelledError sentinel and CompactionOutcome
Introduce `CompactionCancelledError` and `CompactionOutcome` ("ok" |
"cancelled" | "failed") so callers can discriminate user-driven aborts
from generic failures via `instanceof`, instead of inspecting error
messages or `AbortError`-name strings.

`AgentSession.compact()`'s two abort-rejection sites now throw the
typed sentinel; the model-call wrapper normalizes AbortError-shaped
rejections to the sentinel only when the compaction's abort signal
is actually set, preserving every other exception unchanged so real
compaction bugs are not silently relabeled as cancellations.

`CommandController.executeCompaction` and `handleCompactCommand`
return `Promise<CompactionOutcome>`; the catch classifies via
`instanceof CompactionCancelledError`. Existing callers (`/compact`,
loop runner, auto-compact) ignore the return value — non-breaking.

Op: extend
2026-05-12 22:58:27 +00:00
can1357 6d513c606f feat(coding-agent/modes): added timed expiry and cleanup for IRC chat messages
- Updated addMessageToChat in UI helpers and InteractiveModeContext to return rendered components instead of void.
- EventController now tracks IRC message components and removes them after a 10-second TTL, avoiding duplicate expiry scheduling per message signature.
- EventController dispose now clears all pending IRC expiry timers and tests were added for immediate render, TTL removal, duplicate suppression, and timer cleanup.
2026-05-12 03:11:49 +02:00
can1357 f10349a2f9 tweak(welcome): slim logo, diagonal gradient
- Trim logo from 14w to 12w (2-wide legs).
- Diagonal BL→TR gradient instead of per-line LTR.
- Truecolor: 3-stop magenta→violet→cyan path that skips the deep-blue valley.
- 256-color: same 6-stop ramp as fallback.
- Compute the colored logo once at module load instead of per render.
2026-05-10 04:53:53 +02:00
Can BölükandGitHub c0990c9180 Merge pull request #979 from bjin/fix/plan-review-resubmit-rendering
fix(coding-agent): append plan review previews on resubmit
2026-05-10 04:45:51 +02:00
can1357 e4b801590d refactor(coding-agent): tightened custom editor factory typing in interactive mode
- Updated ExtensionUIContext, InteractiveModeContext, and InteractiveMode to require editor factories to return CustomEditor instances.
- Removed the runtime compatibility guard and warning for non-CustomEditor implementations in setEditorComponent.
- Removed the test that verified rejection of non-CustomEditor factories in interactive-mode editor-component tests.
2026-05-09 07:03:37 +02:00
Can BölükandGitHub f9cc082ef2 Merge pull request #909 from quickserve-ai/fix/pi-vim-editor-component-hook
Fix ExtensionUIContext.setEditorComponent in interactive mode
2026-05-09 06:58:14 +02:00
Bin Jin 6218032820 fix(coding-agent): append plan review previews on resubmit
- Render each exit_plan_mode submission as a fresh plan review entry so refined plans are emitted into terminal scrollback.
- Keep external-editor edits replacing the current preview instead of adding duplicate review entries.
- Updated the plan review regression test to preserve the first preview and append the second one after intervening chat content.
2026-05-09 12:47:07 +08:00
can1357 9943a280db feat(coding-agent): added /loop count/duration arg parsing and budgeting
- Added optional `/loop` `count|duration` command arguments and wired `command.args` into loop handling.
- Implemented `loop-limit` parsing and runtime types/helpers for iteration and duration budget limits with validation.
- Updated interactive mode to enforce loop limits per iteration, check duration expiry, and clear budget state on disable.
- Added loop-limit parse/runtime tests and fixed `/loop` arg errors plus macOS `MallocStackLogging` environment leakage.
2026-05-07 15:40:45 +02:00
can1357 f4732522cd fix(interactive-mode): cleared spinner when extension command skips model turn
- Stopped the loading animation and cleared optimistic state in `finishPendingSubmission` when no streaming session was started. Fixes #927.
2026-05-06 20:32:07 +02:00
can1357 f2684b7a18 fix: harden plan enabled toggle 2026-05-06 18:16:01 +02:00
phanthhandcan1357 1b5e1bc129 fix: address PR review comments for plan.enabled setting
- Move planModeEnabled check before plan.enabled guard so /plan can
  still exit an active session even if setting toggled off mid-session
- Clear stale plan/plan_paused mode_change entries when plan.enabled
  is off during session restore, preventing unexpected re-entry when
  the setting is later re-enabled
2026-05-06 18:08:49 +02:00
phanthhandcan1357 bd6113a01d feat 2026-05-06 18:08:49 +02:00
can1357 4e3ff73d89 feat(coding-agent): add approve and keep context plan option
Fixes #948
2026-05-06 17:13:11 +02:00
can1357 c2a0253028 feat(coding-agent): added unsent editor draft persistence for resumed sessions
- Added session-draft persistence methods in SessionManager to write unsent editor text to an artifacts-sidecar draft file and delete it after single-shot consumption.
- Persisted editor text during interactive shutdown and restored that draft on resume when the editor was empty, enabling Ctrl+D draft recovery.
- Updated Ctrl+D handling in the editor/controller path and added tests covering draft round-trip, artifact cleanup, stale-draft eviction, and in-memory no-op behavior.
2026-05-04 02:20:29 +02:00
can1357 39f299ad40 refactor(coding-agent): extracted local-submission tracking into reusable helpers
- Added `recordLocalSubmission` and `withLocalSubmission` to replace inline signature set mutations across input and compaction flush paths.
- Signatures are now cleaned up automatically on delivery failure, preventing stale entries from suppressing editor-draft protection on retries.
- Extended test fixtures and added cases covering signature lifecycle for idle, streaming, and fire-and-forget submission paths.
2026-05-04 00:19:06 +02:00
can1357 ee8b4ec252 fix(coding-agent): adjusted status-line session accent handling for border gaps
- Status-line rendering now treats `statusLine.sessionAccent` as disabled only when explicitly set to false.
- Updated status-line overflow tests to assert gap colors use session accent when enabled and theme border when disabled.
- Test teardown now restores `WSL_INTEROP` and `WSL_DISTRO_NAME` environment variables after mutation.
2026-05-03 04:59:43 +02:00
can1357 581148452c fix(coding-agent/modes): prevented status-line accent lookup before settings initialization
- Added an isSettingsInitialized helper to expose whether global settings were created.
- Updated interactive mode to use the session name when settings are not yet initialized.
- Guarded the status-line accent lookup behind settings initialization to avoid premature access.
2026-05-03 04:58:12 +02:00
can1357 a1a2331d5a fix(tui): avoided OSC 11 polling on Windows Subsystem for Linux
- Added WSL detection in terminal initialization and skipped periodic OSC 11 polling when running under Windows Subsystem for Linux.
- Removed mode 2031 activity tracking and stopped OSC 11 polling immediately when DA1/Mode 2031 reports were received.
- Extended OSC 11 appearance tests to restore platform/env state and verify no polling is started under WSL.

Fixes #914
2026-05-03 04:53:38 +02:00
can1357 24b150cf8e feat(coding-agent): added session accent toggle for status line and border colors
- Added a new boolean statusLine.sessionAccent setting to settings schema and propagated it through status-line preview, controller, and component setting updates.
- Updated status line rendering and interactive border coloring to disable session-based accent colors when the setting is false.
- Added a regression test verifying the status-line gap uses theme border color instead of session accent when session accents are disabled.

Fixes #918
2026-05-03 04:52:10 +02:00
conway fd946a649e fix(coding-agent): wire extension editor component replacement 2026-05-01 18:30:33 -07:00
can1357 7467add484 refactor(coding-agent): unified session title and accent handling around session names
- Removed title-source aware branching from session terminal-title and accent helpers, and updated callers to use session name plus cwd only.
- Dropped UUID-based recent-session naming by preferring explicit header titles or first user prompts and generating an "Untitled · <time>" fallback.
- Adjusted welcome session-row rendering for width-aware name truncation and disabled reasoning in title generation requests to keep terminal titles concise.
2026-05-02 01:42:06 +02:00
can1357 cf60e6df51 feat(coding-agent): implemented eval framework and replaced python tool
- Added a unified eval framework with parser grammar, backend interfaces, and JS/Python execution result types.
- Added eval tool docs and updated prompts for fenced cells, `eval.py`/`eval.js`, and fallback behavior.
- Replaced the built-in `python` tool with `eval` across registry, rendering, interactive modes, and tool settings.
- Migrated Python execution runtime from `src/ipy` to `src/eval/py`, renamed state fields, and removed legacy introspection.
- Refactored browser tooling from in-process VM helpers to worker-managed tab supervisors and protocol transport.
- Added eval parser fallback and JS tool-bridge tests, updated imports, and removed obsolete python-mode suites.
2026-04-30 18:08:37 +02:00
can1357 c7008cc416 perf: optimized startup by parallelizing plugin preload and AGENTS scan
- Parallelized startup by deferring plugin preload and running AGENTS.md scan plus context/template/command discovery in parallel.
- Added AgentsMdSearch exports and options so prebuilt search results were passed into system-prompt construction.
- Reworked logger timing to use AsyncLocalStorage-backed nested spans, initialize a root span, and emit hierarchical summaries.
- Added PI_TIMING-gated TS/TSX module-load timing via side-effect module-timer registration and wrapped key init/request paths with logger.time.
2026-04-30 14:53:38 +02:00
can1357 5003996a01 feat(coding-agent): added content-based todo matching for write/commands
- Removed `id` fields from todo models/fixtures and switched session clones to content-based task identity.
- Replaced `/todo_write` `replace` with `init`, updated setup schemas to `list`/`phase`, and append content-only items.
- Updated `/todo` command flows to match phases and tasks by names/content (exact/prefix/substr, case-insensitive), with no ID targeting.
- Updated rendering/output labels to `# Todos`, `formatPhaseDisplayName`, and Roman-numeral phase headings across todo views.
- Aligned prompts, changelog, and todo tests/fixtures with the new init and content-based todo-write contract.
2026-04-30 06:40:53 +02:00
can1357 895ff6f3a7 fix(coding-agent): clear pending plan-role model switch on plan-mode exit
When entering plan mode while the session is streaming, #applyPlanModeModel
defers the switch into #pendingModelSwitch and snapshots the previous model.
On exit, the snapshot was restored but the deferred switch was left queued,
so the next agent_end flush landed the session on the plan-role model after
the user had already left plan mode.

Drop the pending switch in #exitPlanMode when its target matches the
plan-role resolution; leave any other queued switch alone.

Fixes #816
2026-04-30 04:51:23 +02:00
can1357 fd44728d6e fix(coding-agent/session): resolved local:// files for streaming edit cache operations
- Added a shared session path resolver that maps local:// URLs through local-protocol options, skips other internal schemes, and returns an absolute filesystem path for real files.
- Updated streaming-edit pre-cache and post-edit cache invalidation to use the shared resolver, preventing internal-scheme assertions while keeping filesystem-based flow for local plan files.
- Extended streaming-edit tests to confirm local:// plan edits complete without panicking and that auto-generated checks receive resolved absolute paths.
2026-04-30 03:48:36 +02:00
can1357 90fabf6d4f feat(coding-agent): added batch PR handling to pr_view and pr_diff
- Added support for batch PR operations by accepting `pr` as string or array and dropping `worktree` input.
- Updated `pr_view` and `pr_diff` to normalize PR IDs, process multiple PRs in parallel, and emit combined summaries.
- Refactored checkout into `checkoutPullRequest`, added repo-locking, fixed worktree paths, and summary metadata outputs.
- Updated `remote.add` handling with URL-aware idempotency and per-repo queueing for serialized git mutations.
- Added temp-home test scaffolding and expanded tests for batched PR flows and remote add conflict/no-op cases.
2026-04-30 03:48:25 +02:00
Can BölükandGitHub 55aab2815a Merge pull request #821 from metaphorics/perf/sessiontree-dedupe-context-build
perf(coding-agent): dedupe buildSessionContext walk on session-tree navigation
2026-04-30 03:40:20 +02:00
Can BölükandGitHub 57e912e462 Merge pull request #822 from metaphorics/perf/markdown-global-render-cache
perf(tui): module-level LRU for Markdown render cache
2026-04-30 03:39:59 +02:00
can1357 f8be2ceda5 feat(coding-agent): added /context command flow for interactive dispatch
- Added a `/context` slash command flow from registry to interactive-mode command dispatch.
- Added `handleContextCommand()` to the mode context interface and command-controller wiring.
- Added context usage breakdown utilities, cell allocation, and 20x10 usage rendering for token categories.
- Reworked compaction token estimation to use tokenizer counts, role aggregation, image token estimates, and fallback handling.
- Exported `resolveThresholdTokens()` as a public compaction helper.
2026-04-30 02:26:04 +02:00
can1357 0b3c03189b feat(coding-agent/modes): enabled /loop to use the next user prompt for repeating iterations
- Updated loop command handling to toggle `/loop` without a prompt argument and prompt for the next user input to start repeating.
- Stored each user-submitted prompt as the active loop prompt while loop mode is enabled so iterations auto-resubmit that input after each yield.
- Introduced `pauseLoop` behavior to clear the captured loop prompt and cancel pending auto-submit when Escape is pressed, while `handleLoopCommand` now no longer disables mode automatically with arguments.
2026-04-29 21:42:03 +02:00
can1357 65507f343e fix(coding-agent/modes): preserved editor drafts for local message_start deliveries
- Tracked locally submitted user signatures for both optimistic and streamed-queue submissions in interactive-mode context state.
- Updated user message_start handling to avoid re-clearing the editor and re-adding chat for locally originated messages.
- Cleared consumed local signatures on queued-message restore and added tests for queued, external, and optimistic message_start editor behavior.
2026-04-29 19:39:26 +02:00
can1357 2965efac70 feat(coding-agent): added configurable loop mode actions for /loop iterations
- Added a new `loop.mode` enum setting and UI option entries for prompt, compact, and reset behaviors.
- Updated interactive mode's loop auto-submit flow to execute selected compact or reset actions before re-submitting the prompt.
- Registered a new `just.enabled` setting in the tools settings schema.
2026-04-29 18:55:03 +02:00
can1357 4f45cf1fb4 feat(coding-agent/modes): added loop mode command and status-line mode segment support
- Added loop-mode command handling in interactive mode, including enable/disable toggling, repeated auto-submission scheduling, and Escape-based cancellation.
- Propagated loop mode state to the status line via a renamed `mode` segment that now renders plan or loop status, and updated presets/theme assets for the new loop icon.
- Migrated persisted status-line segment usage from `plan_mode` to `mode` in configuration defaults and normalization so legacy settings continue to load.
2026-04-29 16:55:14 +02:00
cognitive e9d70260f4 fix(tui/markdown): invalidate L2 cache on theme change
The L2 render cache used objectId(this.#theme) as part of the key.
After setTheme(), the same Markdown instance still holds the old
theme reference (same objectId) but the closures now read a different
palette — so the cache returned pre-switch styled lines (F3).

Export clearRenderCache() from markdown.ts and call it from the
onThemeChange handler in interactive-mode.ts so all L2 entries are
dropped on every theme switch, forcing a clean re-render.
2026-04-28 11:40:42 +00:00
cognitive 68baba82d2 perf(coding-agent): dedupe buildSessionContext walk on session-tree navigation
Before this change, every navigateTree → renderInitialMessages call path
performed two independent O(N) session-tree walks:

  1. agent-session.ts:6586  buildDisplaySessionContext()   [inside navigateTree]
  2. ui-helpers.ts:402      sessionManager.buildSessionContext()  [inside renderInitialMessages]

Changes:
- agent-session.ts: navigateTree() now calls sessionManager.buildSessionContext()
  once, derives the display (deobfuscated) context from the raw result, and
  returns the raw SessionContext in the result object.
- ui-helpers.ts: renderInitialMessages() accepts an optional prebuiltContext
  parameter; reuses it when provided, falls back to buildSessionContext() otherwise.
- interactive-mode.ts: forwards prebuiltContext through the wrapper.
- modes/types.ts: updates InteractiveModeContext interface to match.
- selector-controller.ts: passes result.sessionContext from navigateTree into
  renderInitialMessages(), closing the deduplication loop.

Bench (100-msg session, 200 iterations):
  two walks [BEFORE]: 0.0702ms/op
  one walk  [AFTER]:  0.0298ms/op
  Saved: 0.0404ms/navigation (57.5% reduction per navigate)

Tests: render-initial-messages-dedupe.test.ts asserts buildSessionContext is
called 0 times when a prebuilt context is passed, 1 time as fallback.
2026-04-27 03:55:14 +00:00
Miroslav Drbal d9d870bab4 feat(coding-agent): add /drop command to delete current session and start fresh
/drop works like /new but permanently deletes the current session file
and artifacts instead of flushing (saving) it. Useful when the session
should not be kept.

- add drop?: boolean to NewSessionOptions
- branch in AgentSession.newSession(): skip flush, delete via
  FileSessionStorage.deleteSessionWithArtifacts when drop=true;
  deletion failure is non-fatal (logged, new session still starts)
- wire handleDropCommand() through InteractiveModeContext interface,
  InteractiveMode delegation, and CommandController implementation
- guard: shows error if session has not been saved yet (no file to drop)
- register /drop in builtin-registry adjacent to /new
2026-04-26 10:00:48 +02:00
can1357 0d75c582dd feat(coding-agent): added todo note operations to coding-agent todo-write
- Added `note` support to todo-write with `op: "note"` and required `text` input.
- Added optional `notes: string[]` to todo models and preserved notes in cloning and session task mapping.
- Implemented `op: "note"` append flow and markdown `>` block serialization/parsing for todo import/export.
- Updated HUD todo rendering to append superscript `+N` note markers and show in-progress note bodies.
- Documented note operation, required text field, and note rendering rules in todo-write docs and changelog.
2026-04-26 09:05:42 +02:00
can1357 9ca2d2e4cf feat(coding-agent): added /todo slash command actions in interactive-mode
- Added `/todo` slash command with edit, copy, start, done, drop, rm, append, and replace actions.
- Added InteractiveMode context/controller wiring to dispatch `/todo` commands through session runtime.
- Added todo controller parsing, editor-assisted edits, and commit syncing for session, UI, and storage updates.
- Changed todo persistence/restoration behavior, restored grep defaults, and removed chunk read mode and `pi-natives` references.
2026-04-26 08:32:20 +02:00
Vu Anh Nguyenandcan1357 81fd90ecc0 Fix Mermaid markdown rendering on non-image terminals 2026-04-24 06:47:56 +02:00
can1357 23c66791bc fix: stabilize merged review follow-ups 2026-04-18 23:24:00 +02:00
djdembeckandcan1357 f353873b75 refactor: extract local:// URL normalization to shared utility
Extract duplicate normalizeLocalScheme regex pattern into a shared function in path-utils.ts. Updated interactive-mode.ts, approved-plan.ts, agent-session.ts, bash-skill-urls.ts, and plan-mode-guard.ts to use the shared utility. Also fixed error message formatting (removed extra backslashes).
2026-04-18 22:40:07 +02:00
djdembeckandcan1357 5da806671e fix: prevent local:// URI from creating local: directory on Linux
On Linux, Node's path.normalize() collapses the double slash in
local://PLAN.md to local:/PLAN.md, creating a directory called local:
in the project root instead of routing through the local:// protocol handler.

Defense-in-depth fixes across 5 layers:

1. resolveToCwd() now throws if a path starts with any internal URL
   scheme prefix (local:, agent:, skill:, etc.), preventing all 59
   call sites from treating URIs as relative filesystem paths.

2. resolvePlanPath() now matches on local: prefix (not just local://)
   and normalizes local:/ to local:// before resolution, catching
   all slash variants.

3. Bash URL expansion regex and early-exit checks now also match
   local:/ (single slash), and normalize before resolution.

4. Edit preview/diff functions now gracefully skip internal URL paths
   instead of crashing via the resolveToCwd guard.

5. All startsWith('local://') checks updated to startsWith('local:')
   with normalization in agent-session, interactive-mode, and
   approved-plan modules.

Also adds local: to .gitignore to prevent accidental commits of the
leaked directory.
2026-04-18 22:40:07 +02:00
can1357 11b7ba7846 fix(coding-agent): respected session title source when formatting terminal titles
- Propagated session title source through terminal-title update calls so auto and user names are handled consistently across controllers.
- Suppressed auto-generated names in status-line segments and completion messages by falling back to cwd-based titles.
- Updated title formatter tests to verify auto-generated and user-specified session titles produce different terminal labels.
2026-04-13 06:22:37 +02:00
can1357 d2caf2770c feat: added /rename command to set session titles for status/header/tab display
- Added `/rename <title>` slash command to set explicit session names and update header/tab titles.
- Added `session_name` status segment with hash-derived accent color for session titles.
- Fixed shell execution failure sanitization to preserve all `execResult` fields after redacting stderr.
- Fixed tool execution completion output to pass original `toolResult` text instead of sanitized `content`.
2026-04-13 01:09:38 +02:00
can1357 d2202d0b0b fix(coding-agent): ignore auto titles for session accent 2026-04-13 00:42:24 +02:00
Christoph Gross 09810120ba feat(coding-agent): add /rename command with session accent coloring
- Add /rename <title> slash command to set an explicit session name,
  updating the session header, terminal tab title, and status line
- Add session_name status segment: displays the session name on the
  right side of the status bar with a stable djb2-hash-derived accent
  color unique to each name; shown in all presets when a name is set
- Add setSessionName source tracking ('user' vs 'auto'): auto-generated
  titles are silently ignored once the user has explicitly set a name,
  preventing the async title generation from overwriting a /rename
- Sanitize session names at storage time: strip C0/C1 control characters
  (including ANSI ESC) via static #sanitizeName before storing, blocking
  escape sequence injection into the TUI, terminal title, and session file
- Extend sanitizeStatusText to cover the full C0/C1 range as
  defense-in-depth (superset of the previous \r\n\t-only strip)
- Use stored (sanitized) name for showStatus message and terminal title
  in handleRenameCommand, not the raw user input
- Guard terminal title update in auto-title path via titleSource === 'auto'
  so a user rename is never overwritten by a late-resolving LLM call
- Reset #titleSource in #newSessionSync so each new session starts fresh
- Thread source parameter through AgentSession.setSessionName wrapper;
  extension API and RPC set_session_name treated as 'user' intent

Closes #658
2026-04-11 13:49:01 +02:00
can1357 16ad914da0 feat(coding-agent): added LSP status updates to welcome banner on warmup completion
- Added real-time LSP server status updates in welcome banner when background warmup completes.
- Changed welcome banner status icon from warning to muted pending symbol for improved visual clarity.
- Extracted LSP server conversion logic into dedicated helper methods for better maintainability.
- Added comprehensive test coverage for interactive mode LSP startup welcome banner updates.
2026-04-08 08:58:39 +02:00
can1357 7f88a0c24c refactor: restructured logger.time() API to accept function references with wall-clock markers
- Refactored logger.time() API to accept function references and arguments separately instead of wrapped callbacks.
- Replaced RingBuffer-based timing with wall-clock markers and async span tracking for improved timing accuracy.
- Updated 20+ call sites across executor, kernel, main, and tools modules to use new logger.time() signature.
- Removed parsePath() helper function and inlined path.split() calls in settings module.
- Added test case verifying model selection without auth validation during startup.
2026-04-08 08:47:32 +02:00