Commit Graph

4296 Commits

Author SHA1 Message Date
Teknium
3dcf0deb29 test(desktop): adapt status-card regression to current router 2026-09-08 03:39:32 -07:00
Lester Liang
dec10c9177 fix(desktop): keep task status card opaque on scroll 2026-09-08 03:39:32 -07:00
Teknium
c2a0a188c1 fix(desktop): align subagent hydration with owned roster contract 2026-09-08 03:06:30 -07:00
Teknium
975699714d feat(desktop): hydrate scoped subagents and read extended live transcripts 2026-09-08 03:06:30 -07:00
Teknium
fd3932c416 fix(desktop): preserve scoped steering drafts and worker timer origins 2026-09-08 03:06:30 -07:00
Teknium
98aa270978 feat(desktop): steer and stop subagents through their parent owner 2026-09-08 03:06:30 -07:00
Teknium
092ed67532 feat(desktop): surface live subagent work above each composer 2026-09-08 03:06:30 -07:00
Teknium
9516ac130e fix: refresh retained bot tiles without losing their live turn 2026-09-07 23:16:13 -07:00
Gille
9a017b9691 fix(desktop): refresh busy bot chat on explicit open 2026-09-07 23:16:13 -07:00
hermes-seaeye[bot]
9fd44b4dfc fmt(js): npm run fix on merge (#105601)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-08 05:35:50 +00:00
hermes-seaeye[bot]
b1cf905786 fmt(js): npm run fix on merge (#105600)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-08 05:30:17 +00:00
Teknium
cae1c0c4a9 fix: reschedule bounded Desktop foreground queue retries 2026-09-07 22:25:12 -07:00
Teknium
3a7bf7455f fix: keep Bot Mode group replies visible in arrival order 2026-09-07 22:03:12 -07:00
hermes-seaeye[bot]
966637323e fmt(js): npm run fix on merge (#105451)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-08 00:13:36 +00:00
Teknium
aa1a546a22 test: make desktop orphan-reap deadline checks deterministic 2026-09-07 17:08:51 -07:00
kshitijk4poor
25761bb221 fix(desktop): scrape the remote >> log 2>&1 READY sentinel with the merged-buffer regex
The splice hazard the tail seed guards against is live in remote-lifecycle's
scrapeReadyPort: the remote spawn log merges stdout and stderr, yet it was
matched with the `^`-anchored READY_RE. Export one READY_IN_MERGED_OUTPUT_RE
(lookbehind token boundary — the hand-rolled `[^0-9A-Z_]` class admitted
lowercase-glued tokens) from backend-ready.ts and use it for both merged
buffers. Comments trimmed to the WHY; 6 new tests collapsed to the two
invariants (splice recovers, prose does not match) plus one remote-log case.
2026-09-08 02:30:34 +05:30
joaomarcos
d6c7148507 docs(desktop): record that the merged-tail seed is dormant under the current call ordering
Both callers build the wait in the same synchronous block as
`outputTail.attach(child)`, and stream 'data' is asynchronous, so
`bufferedOutput()` is always empty at the seed and this block recovers
nothing today. Say so at the code, so nobody reads the seed as the live
recovery path for a lost READY sentinel — and so the condition that makes it
load-bearing again (any await reintroduced between attach and this call, the
pre-#100442 ordering) is written down next to the code that depends on it.
2026-09-08 02:30:34 +05:30
joaomarcos
4bbfdaf0b7 fix(desktop): recover a READY sentinel spliced into the merged output tail (#103792)
The spawn-time output tail feeds stdout AND stderr into ONE buffer, so its
contents are not line-accurate. uvicorn logs to stderr in raw chunks, and a
chunk that ends without a newline is concatenated directly onto the stdout
sentinel that follows it:

    INFO  Started server process [4711]HERMES_BACKEND_READY port=65238

The late-attach seed scan added for #60323 matched that buffer with the
line-anchored `_READY_RE`, so `^` never lined up and the seed silently
recovered nothing. The live stdout listener cannot cover the gap either: the
sentinel was already consumed by the tail, and flowing-mode streams never
replay chunks to late listeners. The wait then runs out its full 90s deadline
and a healthy, listening backend is SIGTERMed — while desktop.log, which reads
both streams, plainly shows the READY line. That contradiction (READY logged,
boot timed out anyway) is the reported macOS regression.

Scan the tail with a boundary-guarded pattern instead of a line-anchored one.
`port=<digits>` keeps the token unambiguous, so prose naming the sentinel and
longer identifiers ending in it still do not match. The live per-line scanner
keeps `^`: individual stream chunks ARE line-accurate there, and loosening it
would let unrelated child output settle the boot on a bogus port.

Scope: the seed only. Watching stderr on the live path is #97086's change and
is deliberately untouched here — the two compose.
2026-09-08 02:30:34 +05:30
Teknium
610c869ac6 fix(desktop): task panel follows the todo_list wire name
The core-tool rename shipped `todo_list` on the wire (legacy alias `todo`
kept for old transcripts), but the Desktop renderer still matched the tool
by the literal `todo` in seven places: the live tool.start/tool.complete
mirror into the composer status stack, the todo-stream router, args
carry-over, the transcript hoist, the silent-tool class, the count noun,
and stored-history hydration. Every live task update therefore went into
the transcript as an ordinary tool row while the task panel stayed empty,
and reopening a chat never restored a finished list.

One predicate (`isTodoToolName`) now owns the wire/legacy name pair and
every site reads it.
2026-09-07 11:25:20 -07:00
Teknium
a460b44c93 docs(desktop): document directive action hover grace 2026-09-07 08:21:57 -07:00
Teknium
04767e7aaa fix(display): distinguish estimated context from provider usage 2026-09-07 08:13:01 -07:00
Teknium
478d772f2c fix(desktop): resolve artifact downloads in their originating session 2026-09-07 07:11:36 -07:00
Teknium
f9d05081d8 fix(desktop): route relative remote artifacts to gateway download
Salvage the focused renderer hunk from #104131. Preserve raw gateway tilde and relative paths at the authenticated file bridge; do not reinterpret remote paths on the client or widen external protocol handling.

Co-authored-by: Halldrix <12357213+Halldrix@users.noreply.github.com>
2026-09-07 07:11:36 -07:00
Teknium
6504f33f49 fix(desktop): honor explicit worktree sidebar dismissal
Slim salvage of #103992: preserve dismissal provenance as removed ids rather than a second metadata schema; discovery only overrides successful git removals. Explicit hide is durable even before a discovery scan finishes.

Co-authored-by: Tranquil-Flow <66773372+Tranquil-Flow@users.noreply.github.com>
2026-09-07 07:07:49 -07:00
Teknium
d70fb4e6bd fix(desktop): keep directive hover timers on owned boundaries 2026-09-07 06:58:20 -07:00
Konstantin Khlopkov
45c7388213 fix(desktop): give the composer action pill a transit-safe hide delay 2026-09-07 06:58:20 -07:00
hermes-seaeye[bot]
1f92ab1ddf fmt(js): npm run fix on merge (#105106)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-07 13:53:40 +00:00
Jerry Gooch
26ed08c23e fix(desktop): isolate hidden composer selection 2026-09-07 06:46:56 -07:00
Teknium
0b3391322c fix: keep desktop provider setup within its selected profile
Remount scope-owned credential state on Applies-to changes and bind onboarding requests to their initiating route. Cancel polling and invalidate late results when setup closes or reopens, without undoing writes already sent.

Co-authored-by: By JTT <29462570+jordan-thirkle@users.noreply.github.com>
2026-09-07 06:44:04 -07:00
Teknium
75fbefacce test(desktop): keep cold module transforms outside UI assertion deadlines 2026-09-07 06:34:02 -07:00
anhtahaylove
49fc4911a9 test(desktop): stop the unread-tile test timing out on loaded CI
`session-unread-tile.test.ts` intermittently fails CI with
`Test timed out in 15000ms` at the first case. It has hit at least three
independent branches, `main` included, so it is not tied to any one change.

The cost is module reconstruction. `beforeEach`/`afterEach` both call
`vi.resetModules()`, so each of the three cases re-imports six modules,
including `@/lib/chat-runtime` and the pane-tree store. Locally that is
~3.3s on median but the tail reaches 11.8s (3.6x the median) on a warm
machine; a loaded CI runner pushes that past the 15s budget. One observed
CI run passed at 14614ms, 386ms under the limit, which is the same test
sitting on the wrong side of the same boundary.

Drop `resetModules` and undo the per-test state explicitly instead:

- collect the `registry.register` disposers and run them in `afterEach`,
  matching what `session-states.test.ts` already does;
- reset `$layoutTree` and `$activeTreeGroup` at the top of `setup()`.
  `declareDefaultTree` only seeds the layout when it is empty, so without
  this the second case would adopt the first case's tree.

The test keeps its teeth: reverting the `$focusedStoredSessionId` change
from a5b5043 still fails exactly the same two cases as before this patch.

Slowest of 30 consecutive local runs goes from 11.84s to 3.70s, with the
median roughly unchanged.
2026-09-07 06:34:02 -07:00
Teknium
50d7a756d8 fix(desktop): scope separator highlighting to model searches
Keep command-palette literal filter semantics unchanged; opt model surfaces into the shared fold. Preserve original highlighter contracts and trim new regressions to two invariants. Native Electron catalog before/after and visibility dialog verified; campaign suites remain queued.
2026-09-07 06:21:44 -07:00
DavidMetcalfe
b292e2d91d fix(desktop): fold the model-picker downloads filter too
Review-response sweep found one straggler: model-picker.tsx's
visibleDownloads filter still used raw toLowerCase().includes(), so a
hyphen-style query wouldn't match a space-separated download target —
the same bug class this PR fixes, in the same picker. The catalog
menu's equivalent filter was already converted.
2026-09-07 06:21:44 -07:00
DavidMetcalfe
afcd5ea86a fix(desktop): fold separators in model search so filters and highlights agree
Model ids use hyphens/underscores, display names use spaces, versions use
dots. The pickers' filter haystacks contained both the raw id and the
display name, but the highlight only ever saw the display label — so
'qwen3.8-flash' revealed the row (via the id segment) while lighting up
nothing, and model-picker.tsx had the inverse polarity (spaces matched,
hyphens didn't highlight). This violated HighlightMatches' own documented
contract: the query must mirror the filter's semantics or the emphasis
lies.

One length-preserving searchFold ([-_.] -> space, 1 char in / 1 char out)
now runs on both sides of every model-search filter AND inside
HighlightMatches' range finder. Length preservation keeps mark ranges
valid against the original text, so <mark> rendering is untouched. The
fold is a per-character substitution applied to both sides, so any query
that matched before still matches — only coverage grows.

- lib/text.ts: searchFold + foldIncludes, the one matcher for all pickers
- highlight-matches.tsx: ranges computed on folded text, marks slice original
- model-catalog-menu.tsx: family, MoA, and download haystacks use foldIncludes
- model-visibility-dialog.tsx, model-picker.tsx: same (fixes inverse polarity)
- dropdown-menu.tsx: DropdownMenuSearch sets spellCheck={false} — squiggles
  under model ids are noise; composer/settings inputs already disable it

Tests: fold primitives (equivalence, 1:1 length, superset), highlighter
fold behavior + index fidelity, end-to-end menu behavior (hyphen query
marks the spaced label; space query finds the hyphenated id without
over-matching), and an updated hidden-model-search test whose id-style
query now legitimately highlights.
2026-09-07 06:21:44 -07:00
Teknium
fd3565deec fix: remove dedicated user-facing output cap controls 2026-09-07 06:15:43 -07:00
Teknium
f4f691c6cc fix(desktop): retain restored offsets through deferred layout
Observe post-settle transcript resizes until reader input or a live run takes ownership. Keep parked upward-wheel cancellation and namespace capture intact. Extend the maintained Chromium restoration probe with long reload and streaming controls; retain the two existing component invariants.
2026-09-07 06:14:35 -07:00
Teknium
3329b38bf3 fix(desktop): retain scroll ownership and honor hydration wheel intent 2026-09-07 06:14:35 -07:00
Teknium
9a78d5ac2b test(desktop): document and probe reading-position restoration 2026-09-07 06:14:35 -07:00
Victor Nogueira
52ce7b23d2 fix(desktop): scope saved scroll by gateway 2026-09-07 06:14:35 -07:00
Victor Nogueira
0237fcc295 fix(desktop): defer parked scroll restore until ready 2026-09-07 06:14:35 -07:00
David Metcalfe
c06caad8f7 fix(desktop): preserve per-session chat scroll position
Rework per hermes-sweeper review (keep_open, salvageability=medium):

- Capture moves out of the render body into the session-switch layout-effect
  cleanup, so only committed switches persist state (no uncommitted render
  can write localStorage).
- Live state is fed by both scroll events and a ResizeObserver on the
  content element, so distance-from-bottom stays fresh under async
  relayout that changes height without a scroll event (the staleness gap
  #70478's own review threads flagged).
- State is distance-from-bottom (or sticky-bottom), not raw scrollTop:
  the render-budget backfill prepends older turns and main anchors by
  distance-from-bottom, so an absolute offset no longer identifies the
  same reading location after the height change.
- Restore integrates with main's hasGroups/settle/anchor lifecycle: the
  settle loop re-applies the remembered target, defers on a clamped offset
  (content still arriving), hands back locked only for sticky-bottom, and
  leaves mid-read sessions escaped at their offset.
- anchorBeforePrepend no longer records 0 mid-load, which would clobber a
  restored offset once the backfill lands; the settle loop owns the target
  every frame until settled.
- Storage is scoped per profile with the session.ts .profile.<encoded>
  key pattern (no cross-profile bleed, #67709 pattern) and LRU-capped at
  120 sessions per profile.
- Regression tests: state classification, target math, profile isolation,
  LRU eviction, corrupt/invalid payload handling.

Related to #45562 (partial; no automatic closure)

(cherry picked from commit 1d79bef93f63d7b190b471bf652b5109b4288a8e)
2026-09-07 06:14:35 -07:00
Teknium
a275adefe2 fix(desktop): retain manual recovery scope through retries 2026-09-07 06:12:00 -07:00
Teknium
5f02693fe0 fix(desktop): reconnect only the active gateway route 2026-09-07 06:12:00 -07:00
Teknium
2bd6fe0dde fix(desktop): keep gateway reconnect available on open transports 2026-09-07 06:12:00 -07:00
Teknium
6c0750e7b7 fix(desktop): cancel MCP auth when scoped Skills tabs leave their owner 2026-09-07 06:10:28 -07:00
Teknium
09229312aa test(desktop): trim MCP relay coverage to ownership and cleanup invariants 2026-09-07 06:10:28 -07:00
Filipe Bezerra
5cf8d7451e fix(desktop): preserve explicit local MCP OAuth without callback bridge 2026-09-07 06:10:28 -07:00
Filipe Bezerra
e3ba651b6d fix(desktop): relay MCP OAuth through client-local callbacks 2026-09-07 06:10:28 -07:00
Teknium
f83ff89780 fix(desktop): reveal complete slash help across the window
Preserve producer descriptions without identity wrappers and size the existing themed tooltip to the viewport. Replace skipped and structural tests with two behavioral invariants. Native Electron before/after hover, click and keyboard verification passed; campaign suite validation remains queued.
2026-09-07 06:10:15 -07:00
Konstantin Khlopkov
00bb169d1b feat(desktop): full command description hover on slash autocomplete rows (#104729) 2026-09-07 06:10:15 -07:00