Commit Graph

8535 Commits

Author SHA1 Message Date
roboomp ed715eda7b fix(mnemopi): stripped retention markers from embeddings
Added an embedText projection for remember() so stored transcripts can remain readable while embeddings, FTS indexing, and embedding-model rebuilds use marker-free text. Updated coding-agent retention to pass the marker-free projection and strip retained protocol markers from recall display.

Fixes #4395
2026-07-03 04:59:02 +00:00
can1357 d0c1890a6c chore: bump version to 16.3.4 2026-07-03 06:37:14 +02:00
can1357 eacaf65ea3 release(cli): documented usage cli reporting fixes
- Documented a fix for the usage CLI where sibling-only limits were incorrectly hidden when omitted from the usage report.
- Added a note regarding the new explicit not reported row for missing usage buckets.
2026-07-03 04:53:28 +02:00
can1357 469333d749 test(cli): verified reporting logic for sibling provider limits
- Added test case to verify that missing provider limits in sibling accounts are correctly marked as not reported.
- Verified that the usage breakdown correctly distinguishes between reported and unreported sibling provider limits.
2026-07-03 04:53:28 +02:00
can1357 8c648e4d02 fix(cli): enabled consistent reporting for sibling provider limits
- Added collectProviderLimitTemplates to aggregate limit IDs across all reports.
- Updated formatUsageBreakdown to render placeholders for limits missing from specific providers.
- Standardized label widths across sibling providers to align status bars.
2026-07-03 04:53:28 +02:00
can1357 afc79e4cda chore: bump version to 16.3.3 2026-07-03 00:57:22 +02:00
can1357 79f499e092 feat(coding-agent/modes): requested UI render during loading state
- Triggered a UI render update when transitioning to the loading animation state to ensure the interface reflects the status change immediately.
2026-07-03 00:55:57 +02:00
can1357 5c171b2860 chore: refactored failure reporting and update quiet mode output
- Extracted failure formatting logic into a reusable `formatChunkFailure` function.
- Updated quiet mode to display detailed failure output immediately when a test chunk fails.
- Adjusted final failure summary to improve output readability and conditional flow.
2026-07-03 00:47:56 +02:00
can1357 16267f4e6a Merge remote-tracking branch 'origin/farm/51e9b851/tui-render-cpu-overhead' 2026-07-03 00:47:33 +02:00
can1357 83176e159f chore: implemented watchdog and stabilize GC for test execution
- Added a per-chunk watchdog that terminates wedged test processes with SIGKILL after a configurable timeout.
- Implemented incremental stream draining to capture test output even when a process is forcibly killed.
- Stabilized test execution by forcing single-threaded GC markers (`BUN_JSC_numberOfGCMarkers=1`) to prevent segmentation faults during heap-heavy operations.
2026-07-03 00:46:46 +02:00
can1357 80eccf99e4 fix(coding-agent/modes): improved rpc client startup error handling
- Prevent premature failure during process startup by waiting for stderr to drain before throwing exit errors.
- Resolve race conditions between stdout closure, process exit, and readiness timeouts by using a local child process reference.
- Ensure proper cleanup of abandoned processes during startup failures to prevent leaks.
2026-07-03 00:46:46 +02:00
can1357 f577f4cb22 ux(coding-agent): visualized advisor notes to distinguish from output
- Introduced a dedicated advisor rail symbol to differentiate note cards from thinking output.
- Applied bold custom header tags and severity-tinted rails to distinguish advisor notes from surrounding text.
- Shifted note body text to the default content color to prevent blending with dimmed thinking-output styles.
2026-07-03 00:46:46 +02:00
roboomp 30527aee0c fix(tui): cut TUI CPU overhead during interactive sessions
Four tightly-scoped hot-path fixes covering the highest-impact items in the
reporter's CPU profile (13.1 s profiled / 30 s window):

1. `event-controller.ts:handleEvent` no longer fires a blanket
   `statusLine.invalidate() + ui.requestRender()` before every session event.
   The pre-render was a leftover from #4145 when `updateEditorTopBorder()`
   still eagerly rebuilt the border; the lazy provider added in #4145 made
   it redundant. It fired on every `message_update`/`tool_execution_update`
   during streaming — the pre-render's frame ran while the handler was
   awaiting, then the handler's own `requestRender` scheduled a second
   identical frame. Every handler that mutates visible state already calls
   `requestRender()`.

2. `shimmer.ts:shimmerSegments` iterates the segment string in place instead
   of building a code-point array with `Array.from(seg.text)` every animation
   frame. Runs of same-tier chars are emitted via a single `slice` per run
   rather than accumulating into `runBuf`. Surrogate pairs stay atomic — the
   code-point index still advances by 1 per emoji. Microbench over 30k
   frames: 45 ms → 18 ms (2.53x), allocation rate down from ~N-per-frame to
   a handful per frame. New tests cover mixed BMP+surrogate and all-emoji
   inputs. `Array.from` was the #1 self-time hotspot in the reporter's
   profile at 10.2%.

3. `Markdown.setText` gains an equality guard mirroring `Text.setText`
   (returns `false` when `text === #text`). Providers re-emit identical text
   on ticks with no delta (throttled frames, reconciled tool-execution
   updates); each of those now short-circuits instead of dropping
   `#cachedLines` and forcing a full lex + wrap on the accumulated paragraph
   (the reporter's #3 hotspot at 8.4%). New test asserts render-reference
   stability + return-value semantics.

4. `SPINNER_RENDER_INTERVAL_MS` aligned with `SPINNER_GLYPH_ADVANCE_MS`
   (both 80 ms). The previous 33 ms cadence emitted ~2.4 paints per glyph
   step; the differential-output dedup only skips the write, not the
   compose walk. Visually identical (glyph advance was already 12.5fps),
   halves paints during tool execution.

Skipped (out of scope for a bug fix, deserve dedicated PRs):
- Freezing streaming prefix on single `\n` boundaries — correctness-bound
  to `\n\n` block separators (CommonMark loose-list continuation).
- Compose-phase idle gate + adaptive-backpressure moving-average — need a
  component-level dirty flag; the 200 ms cap in `#scheduleRender` was set
  for a reason (#4145 tail-latency guard).

Tests updated: two IRC-expiry tests in event-controller-message-start.test.ts
that were asserting the pre-render's second `requestRender` call now expect
one.

Fixes #4353
2026-07-02 22:11:26 +00:00
can1357 2632aace00 test(coding-agent): updated merged regression assertions 2026-07-02 23:51:19 +02:00
can1357 3315ef0007 fix(network): bounded smithery and startup fetches 2026-07-02 23:51:18 +02:00
can1357 d0fa896c19 fix(dap): removed per-write exit handlers 2026-07-02 23:51:18 +02:00
can1357 c983918c30 chore: update changelogs 2026-07-02 23:49:32 +02:00
can1357 eff714c750 Merge remote-tracking branch 'origin/farm/16f7ef23/ssh-helper-timeouts' 2026-07-02 23:43:11 +02:00
can1357 eb47ce1063 Merge remote-tracking branch 'origin/farm/a23a6b23/drain-plugin-install-pipes' 2026-07-02 23:43:11 +02:00
can1357 8b3d0a7190 Merge remote-tracking branch 'origin/farm/1f41837c/timeout-bare-fetches' 2026-07-02 23:43:11 +02:00
can1357 8172708b10 Merge remote-tracking branch 'origin/farm/df17c0e9/async-clipboard-reads' 2026-07-02 23:43:10 +02:00
can1357 a721e56bf8 Merge remote-tracking branch 'origin/farm/7a7807b2/fix-status-line-gh-pr-lookup-hang' 2026-07-02 23:43:10 +02:00
can1357 f44a6cef81 Merge remote-tracking branch 'origin/farm/70e09bb6/fix-dap-client-flush-and-socket-spawn-leaks' 2026-07-02 23:43:10 +02:00
can1357 1301d5b07a Merge remote-tracking branch 'origin/farm/f5b6b32e/fix-edit-anchor-fresh-read' 2026-07-02 23:43:10 +02:00
can1357 e64f15eb63 Merge remote-tracking branch 'origin/farm/20bff231/zhipu-glm-coding-plan-auth' 2026-07-02 23:43:10 +02:00
can1357 43856f70d9 Merge remote-tracking branch 'origin/farm/8994bf65/rebind-advisor-model-role' 2026-07-02 23:43:09 +02:00
can1357 41f06129b3 Merge remote-tracking branch 'origin/farm/2b21222d/fix-update-plugin-list-flag' 2026-07-02 23:43:09 +02:00
can1357 245cf45bd9 Merge remote-tracking branch 'origin/farm/a6b47aec/mcp-oauth-client-id' 2026-07-02 23:43:09 +02:00
can1357 dedb08f72b Merge remote-tracking branch 'origin/farm/90f245d0/surface-models-yml-validation' 2026-07-02 23:43:09 +02:00
can1357 1c0e35f73e Merge remote-tracking branch 'origin/farm/813601d2/install-npm-pi-packages' 2026-07-02 23:43:08 +02:00
can1357 98338d0c55 Merge remote-tracking branch 'origin/farm/6f458e03/configurable-gemini-search-model' 2026-07-02 23:43:08 +02:00
can1357 b9ce7ef103 Merge remote-tracking branch 'origin/farm/b15f12c7/ssh-repaint-topology'
# Conflicts:
#	packages/coding-agent/src/tools/renderers.ts
2026-07-02 23:42:59 +02:00
can1357 1ee11c05b5 Merge remote-tracking branch 'origin/farm/b3ffd580/sshfs-macos-mountpoint-fallback' 2026-07-02 23:42:39 +02:00
can1357 ae89b3ff08 fix(tui): merged scrollback offer boundary repair
Merged PR #4330 and fixed the remaining offered-boundary regression by stopping offer promotion at intervening live blocks.

Verified with targeted transcript/native scrollback regressions: 40 pass.
2026-07-02 23:41:53 +02:00
can1357 5de45fa975 Merge remote-tracking branch 'origin/farm/61175132/fix-windows-session-tail-loss' 2026-07-02 23:33:20 +02:00
can1357 2c8daf0578 feat: implemented dynamic coercion for legacy tool argument aliases
- Added `normalizeSingleStringField` to dynamically map misplaced string inputs to required schema fields for single-argument tools.
- Integrated argument normalization into `validateToolArguments` to handle model-specific variations in JSON payloads during validation passes.
- Updated `coding-agent` streaming and rendering components to recognize `_input` as a legacy alias for `input` across various UI paths and logic flows.
- Refactored `hashlineEditParamsSchema` to strictly enforce the `input` field while maintaining support for legacy aliases via runtime coercion rather than schema definition.
- Corrected unit tests to reflect that `_input` is rejected by the strict schema but handled gracefully by the validation layer.
2026-07-02 23:32:35 +02:00
can1357 ae2da8b8bc Merge remote-tracking branch 'origin/farm/1ca78b3d/capture-tts-worker-stderr' 2026-07-02 23:28:45 +02:00
can1357 718eefcdf5 Merge remote-tracking branch 'origin/farm/fd1e45ae/fix-acp-terminal-shell-wrap' 2026-07-02 23:28:06 +02:00
can1357 03821843a5 Merge remote-tracking branch 'origin/farm/c1eb4f67/cursor-persist-tool-calls' 2026-07-02 23:27:22 +02:00
roboomp 01ab7e26d7 fix(session): kept newer fence owner on stale rewrite unwind
SessionManager.#runFencedAtomicRewrite's finally now only clears #atomicRewriteFenceEpoch when it still matches the unwinding task's epoch. When flushSync supersedes an in-flight rewrite (bumping #diskEpoch and resetting #diskTail), a fresh atomic task scheduled at the new epoch can take ownership of the fence before the stale rewrite finally settles; the previous unconditional clear stranded the newer rewrite's bookkeeping so subsequent sync appends took the hot writer path and were then detached by the newer publish.

Regression: SequencedRewriteStorage pauses the first N writeTextAtomic calls on per-call gates. Test schedules a stale rewrite, forces flushSync to bump the epoch via a fenced append, schedules a newer rewrite that parks at pauses[1], releases the stale gate (stale unwinds and guard-rejects), then appends a custom entry — asserts writerOpens does not grow (fence preserved) and the fenced entry lands in the newer publish's body. Without the fix, writerOpens grows from 1 to 2.

Fixes #4338
2026-07-02 21:20:53 +00:00
can1357 234a46fa3f feat(session): delayed session termination for pending async background jobs
- Added `#hasPendingAsyncWake` to detect running or pending background jobs owned by the agent.
- Deferred todo reminders and `session_stop` hook passes until all agent-owned background async jobs complete.
- Ensured scheduling pauses caused by async jobs do not trigger terminal session stops or premature todo nags.
2026-07-02 23:14:22 +02:00
roboomp f26006737e style: bun run fix 2026-07-02 21:02:46 +00:00
roboomp cfedc0efd0 fix(cursor): synthesize toolCall blocks for exec-channel native tools
Cursor's provider only pushed toolCall content blocks for MCP and todo
in processInteractionUpdate.toolCallStarted. Native tools (bash, read,
write, grep, ls, delete, lsp) execute via the exec channel and produced
no toolCall blocks, so persisted assistant messages contained only text.

On replay, renderSessionContext could not pair the subsequent toolResult
messages with any toolCall block and fell through to addMessageToChat
(a no-op for toolResult), causing header-less \`\\u23ce\` output beneath the
last assistant text.

- packages/ai/src/providers/cursor.ts: add synthesizeCursorExecToolCall
  and inject it at the top of each native exec case in
  handleExecServerMessage, using the coding-agent bridge's mapped tool
  name and args so live event and rebuild render identically. Normalize
  args.toolCallId before invoking the handler so provider block id and
  bridge result id always match.
- packages/agent/src/agent.ts: drop the text-length split in
  #emitCursorSplitAssistantMessage. With toolCall blocks now at their
  correct positions in content, emit the assistant message as-is
  followed by buffered toolResults; the split's preambleText-per-text
  copy also silently duplicated text on multi-block turns.
- packages/ai/test/cursor-streaming-args.test.ts + new
  packages/coding-agent/test/issue-4348-repro.test.ts: guard block
  ordering, event sequence, and rebuild pairing behavior.

Fixes #4348
2026-07-02 21:02:33 +00:00
roboomp 549b4c13a8 fix(session): relaxed fence once flushSync superseded the atomic
Replaced the boolean #atomicRewriteActive flag with #atomicRewriteFenceEpoch: number | null. The fence branch in #appendToSessionFile now applies only while the pending atomic rewrite's epoch still matches #diskEpoch. Once flushSync -> #rewriteSynchronously bumps the epoch, the in-flight writeTextAtomic is guaranteed to abandon via its commitGuard, so subsequent sync appends can (and must) take the hot path against the freshly-published body instead of being stranded in memory when close() returns without another rewrite.

New regression: pauses writeTextAtomic mid-flight, appends a fenced custom entry, calls flushSync (which captures it into the durable body), then appends a message + custom entry after the epoch bump. Reads the current JSONL BEFORE releasing the paused atomic and asserts both post-flushSync entries are already on disk; then releases the atomic (commitGuard rejects) and closes the session and asserts nothing is lost.

Fixes #4338
2026-07-02 20:54:24 +00:00
can1357 0059aed4f0 feat(hashline): enabled content hash matching to resolve tag collisions
- Simplified match logic to rely exclusively on content hash equality.
- Removed strict validation that rejected colliding snapshot tags.
- Updated recovery behavior to resolve collisions to the most-recently recorded snapshot.
- Refactored tests to expect successful preview and patching despite tag ambiguity.
2026-07-02 22:45:29 +02:00
can1357 d82b9bdc5f feat(agent): allowed dynamic model resolution per LLM call
- Added `getModel` to `AgentLoopConfig` to allow runtime model resolution.
- Updated `streamAssistantResponse` to resolve the model dynamically per provider call instead of using the stale configuration snapshot.
- Enabled mid-run model switches to take effect immediately for context promotion and retry fallbacks.
2026-07-02 22:43:11 +02:00
roboomp babb731cf5 fix(session): looped title fallback + drained backend on close
SessionManager.#persistTitleChangeEntry's catch fallback previously did a single-shot atomic rewrite: any prompt/tool appended while it awaited was fenced with #atomicRewriteDirty=true but never re-serialized. Extracted the fenced-rewrite do-while loop into #runFencedAtomicRewrite and used it from both #rewriteAtomically and #persistTitleChangeEntry, so fenced entries during either path are captured before the task resolves.

Added SessionStorage.drain(): for FileSessionStorage and MemorySessionStorage it is a no-op; IndexedSessionStorage already had one and now conforms to the interface. SessionManager.flush() and close() await it so a graceful shutdown does not exit while a fire-and-forget writeTextSync publish (queued by flushSync on an indexed backend) is still on the wire — reducing the residual publish-window race for Redis/SQL where the backend cannot be aborted mid-flight.

Regression covers the title fallback loop: TitleFallbackPausingStorage forces updateSessionTitle to throw, pauses the fallback's writeTextAtomic, appends a message and a custom entry during the pause, and asserts (a) both fenced entries land on the current JSONL, (b) the final title is applied, and (c) writeTextAtomicCalls >= 2 proving the loop iterated.

Fixes #4338
2026-07-02 20:32:27 +00:00
roboomp f614ec1537 fix(session): honored commitGuard at indexed publish time
IndexedSessionStorage.writeTextAtomic no longer delegates directly to writeText, which yielded on #awaitPath between the guard check and the backend publish. The new impl consults the guard three times — up front, again after #awaitPath resolves, and finally inside the enqueued task immediately before #backend.writeFull — so a flushSync that bumps #diskEpoch while the atomic rewrite is suspended cannot land stale content on Redis/SQL backends. When the enqueue-time guard rejects, the optimistic index update is restored only when nothing has advanced it past our mtime, so a concurrent writer's state is preserved.

Added a PausableWriteFullBackend regression: the first writeTextAtomic parks inside backend.writeFull holding the per-path tail; the second queues with a guard that flips after the first is released. The backend records only the first content, confirming the guard is honored at publish time.

Fixes #4338
2026-07-02 19:17:45 +00:00
roboomp 23d9f7c898 fix(session): discarded temp on EPERM guard-reject branches
FileSessionStorage.#replaceSessionFileAfterEpermSync now unlinks the staged temp file when commitGuard returns false in both fallback branches: the ENOENT-vanished-target path and the post-move-aside path (where the moved-aside backup is also restored). Honors the writeTextAtomic contract that a guard-rejected stage is discarded.

Regressions cover all three guard-reject exits: the direct rename pre-check, the ENOENT branch inside the EPERM fallback, and the move-aside branch that also restores the backup. Each asserts no orphan .tmp remains in the session dir.

Fixes #4338
2026-07-02 19:11:25 +00:00
roboomp 24c6b3a9f9 fix(session): fenced writer close-yield inside atomic rewrite
SessionManager.#rewriteAtomically now enables #atomicRewriteActive before #closeWriterHandle() and keeps it set until the rewrite task exits, so a sync append landing in the close-yield window is fenced and cannot open a fresh writer that the pending writeTextAtomic would then detach from the current JSONL path. Same pattern applied to the #persistTitleChangeEntry atomic fallback.

Added a regression that pauses the fake storage's writer.close() gate, appends a message and a custom entry during the pause, and asserts (1) no new writer opens (writerOpens counter unchanged) and (2) the fenced entries land on the current JSONL path after the rewrite completes.

Fixes #4338
2026-07-02 19:07:36 +00:00