Commit Graph

4791 Commits

Author SHA1 Message Date
teknium1
bd46352705 feat: catalog card image slot is 2:1; version pill reads as a pill
repo social banners are 2:1, so that shape fills the slot without a crop;
the recommended size is in the README/docs. Desktop AgentPluginRow gains
catalog_version to match the generated contract.
2026-09-16 14:18:39 -07:00
teknium1
034313e7cd feat: plugin catalog entries carry an optional version label and card image
The 40-hex sha stays the release, but nobody reads one. Entries may now add
`version: "1.4.0"` (free-form, <=32 chars, never parsed) and `image:` (an https
URL on raw.githubusercontent.com / github.com / *.githubusercontent.com).

Why GitHub-only: the Desktop catalog browser deliberately never fetches from
third-party hosts, and a raw URL pinned to the entry commit is as immutable as
the sha it decorates.

Readers updated together: PluginCatalogEntry + entry_from_mapping (drop with a
warning, entry survives), validate_plugin_catalog.py (admission error), the
site extractor (drop, never fatal), the /docs/plugins card (banner + version
pill + "1.4.0 @ abcd1234" pin), the CLI table/info (pin_label), the TUI-gateway
plugin row (catalog_version -> Desktop "Update to 1.4.0"), and the Desktop
catalog detail header (image).
2026-09-16 14:18:39 -07:00
brooklyn!
74ca4f28ba fix(onboarding): consume future catalog entries without custom metadata 2026-09-16 15:54:47 -05:00
brooklyn!
4716ec0ba4 feat(desktop): suggest varied first tasks from real integrations 2026-09-16 15:16:09 -05:00
brooklyn!
4e9d3c713a feat(desktop): browse catalogs as cards with a saved list option 2026-09-16 13:55:13 -05:00
brooklyn!
2e05fcf524 feat(ui): support icon-only segmented controls 2026-09-16 13:55:13 -05:00
brooklyn!
cbd76e4ea3 feat(desktop): restore native skill and plugin catalogs
Restore the shared browser, protocol handling, and install confirmations from the original catalog work for further UI iteration.
2026-09-16 13:55:13 -05:00
Austin Pickett
a7691f41ec fix(desktop): explicit bot opens and session creates dial the pool at foreground priority (#113269)
* fix(desktop): foreground spawn priority through requestGatewayForAgent/retainGatewayForAgent and the session-create dials

The #102281/#104139 chain tagged every activation-door dial
(openGatewayForAgent/openGatewayForProfile/ensureGatewayForAgent/
sharedPrimaryRoute) as 'foreground' so a user-initiated open takes the
pool's reserved slot instead of queuing behind background roster
hydration. requestGatewayForAgent and retainGatewayForAgent never got a
spawnPriority, so they always dialed 'background', and they are the only
dial path createBackendSessionForSend (first send on a fresh chat) and
openNewSessionTile ("New session" / tab-strip "+") use. On a saturated
3-slot local pool the user's first message or new-tab click could wait
out the background slot timeout.

Add `{ spawnPriority }` options (main's requestGatewayForProfile shape,
5eb0ed4531) to both functions and forward it into every dial they make:
requestGatewayForProfile on the scope===key and primary-registry
branches, isAttachedSharedRemote, openSecondary, and the plain-profile
retain branch's gatewayForProfile(key, true, ...) which neither #105390
nor #110354 covered. The four session-create call sites pass
'foreground'.

Tests: gateway-spawn-priority.test.ts gains both polarities for
request/retain plus the plain-profile retain branch; the
use-session-actions and default-new-session matchers pin the tagged
dial. SpawnPriority is now exported for the SDK.

* fix(desktop): canonical Bot Chat lookup dials foreground through host.requestProfile options

Clicking a bot in the roster runs findExistingCanonicalChat ->
requestForBot(bot, 'session.list') -> host.requestProfile(route, ...)
-> requestGatewayForAgent with no intent, so the first RPC of the
gesture, the one that cold-spawns the bot's backend on a local pool,
dialed 'background'. With three roster backends already hydrating the
click produced no backend activity and the fail-closed lookup surfaced
as a "try again" toast (#105104). The later host.openSession is already
foreground, but it never runs until this lookup returns.

host.requestProfile gains a fifth `options?: { spawnPriority }`
argument; `timeoutMs` stays the fourth positional so no existing caller
changes shape, and the SDK keeps its exact call arity when no options
are given. requestForBot takes the same options and forwards them only
when set, so passive roster warming (profiles.list, ui_meta) still
dials background. The canonical `session.list` and the `session.create`
that follows on a first-ever open both pass 'foreground'.

Tests: profile-routing.test.ts (options form with and without a
timeout), routing.test.ts (tag forwarded, untagged call keeps three
args), canonical-chat-registry.test.ts (session.list and session.create
carry foreground; session.title does not).

---------

Co-authored-by: nftpoetrist <264138787+nftpoetrist@users.noreply.github.com>
Co-authored-by: jxfjosh <282433633+jxfjosh@users.noreply.github.com>
2026-09-16 14:27:54 -04:00
brooklyn!
fdb7b216ec fix(desktop): keep timeline ticks compact outside hover 2026-09-16 13:02:32 -05:00
brooklyn!
09aaa4cc41 feat(desktop): add profile window and default context actions 2026-09-16 12:39:46 -05:00
brooklyn!
63d129bf17 feat(desktop): apply profile defaults to startup and new chats 2026-09-16 12:39:46 -05:00
brooklyn!
8eaf776c3b feat(desktop): persist default profile and route peer windows 2026-09-16 12:39:46 -05:00
teknium1
9796235822 Revert "feat(catalog): open website installs in Hermes Desktop"
This reverts commit b0e78e60fb.
2026-09-16 09:25:14 -07:00
teknium1
4718ba7352 Revert "feat(desktop): browse skills and plugins in a shared native catalog"
This reverts commit 07c9088460.
2026-09-16 09:25:14 -07:00
teknium1
9d67c7c29a Revert "fix(desktop): show skill install progress and completion in the shared dialog"
This reverts commit 25be09822d.
2026-09-16 09:25:14 -07:00
teknium1
9139bb8a4e Revert "fix(catalog): align CI checks with the shared action row"
This reverts commit 0fc2c59a07.
2026-09-16 09:25:14 -07:00
teknium1
6a912eb1cb Revert "refactor(desktop): reuse ActionStatus for catalog installs"
This reverts commit f30e5cbfd8.
2026-09-16 09:25:14 -07:00
Austin Pickett
f57857ade5 fix(desktop): host.navigate fronts the workspace pane on a re-click (#112942)
Plugin entry points (Kanban palette row, statusbar count, ⌘⌥N) route
through the SDK's host.navigate, which only wrote the hash. Re-issuing
the current route fires no router event, so the page stayed behind a
focused session tile. Reveal imperatively via syncWorkspaceRoute, the
same door navigateToWorkspacePage gives the sidebar and keybinds.

Supersedes #111898.

Co-authored-by: xxxigm <tuancanhnguyen706@gmail.com>
2026-09-16 11:58:42 -04:00
Austin Pickett
6bea68a1de fix(desktop): route project writes to the live profile in All profiles (#112943)
* fix(desktop): route project writes to the live profile in All profiles

All profiles is a sidebar filter, not a write target. Appearance, rename,
add-folder, and delete now use the active gateway profile, matching create.

* test(desktop): type the all-profiles write fixture as ProjectInfo

---------

Co-authored-by: Guillaume <guillaume.eynaud@icloud.com>
2026-09-16 11:18:20 -04:00
Austin Pickett
03b0c79472 fix(desktop): send Cloudflare Access headers on OAuth login (#110987)
* test(desktop): cover access-proxy headers on OAuth login URLs

Connections extra headers must apply to /login and OAuth-partition
requests, not only an exact remembered WebSocket URL.

* fix(desktop): send extra gateway headers on OAuth login

Cloudflare Access service tokens never reached the OAuth sign-in
window because they were injected only on defaultSession and v1
remote config. Attach them on OAuth partitions and loadURL too.

* fix(desktop): strip CR/LF from remote gateway header values

The PR this builds on sanitized header values in remote-ws-headers.ts, on
the resolution path only. That left the sibling consumers of
decryptRemoteHeaders untouched: buildRemoteConnection and both
connection-test paths still handed raw values to setHeader.

Sanitize on the canonical normalizer instead, where header NAMES are
already validated against REMOTE_HEADER_NAME_RE, so every consumer
inherits it. normalizeRemoteHeaders only trim()'d, which strips a
trailing newline but leaves an EMBEDDED CR/LF intact — the actual
request-splitting vector.

* refactor(desktop): drop the duplicate header normalizer from remote-ws-headers

Header values now arrive sanitized from decryptRemoteHeaders, so the
second sanitizeRemoteHeaderValue/sanitizeRemoteHeaderMap pair here was a
duplicate of the canonical one in connection-config.

The routing test keeps its original job (Connections headers reach
/login, longest base URL wins); the CR/LF assertions move to
connection-config.test.ts where the stripping now lives.

* perf(desktop): memoize decrypted remote header sources

onBeforeSendHeaders is now attached to every OAuth partition as well as
defaultSession, and headersForRemoteRequest decrypts EVERY registry
connection's headers. A safeStorage-encoded value costs a keychain
round-trip per read, so that was N decryptions per subresource request
where main previously did at most one behind a modeIsRemoteLike gate.

Key the collected sources off the connection config and registry cache
objects, which both readers already refresh on mtime change.

---------

Co-authored-by: xxxigm <tuancanhnguyen706@gmail.com>
2026-09-16 09:46:44 -04:00
brooklyn!
784d5c3f9c test(desktop): cover shared composer focus and draft ownership 2026-09-16 06:59:03 -05:00
brooklyn!
087fbe3847 feat(desktop): share the floating composer across chat panes 2026-09-16 06:59:03 -05:00
brooklyn!
657ee57a99 fix(desktop): align timeline idle checks and skip unsaved history work 2026-09-16 06:39:15 -05:00
brooklyn!
586737c5ce fix(desktop): show scrollbars only in hovered regions without fading 2026-09-16 06:39:15 -05:00
brooklyn!
2efbbef981 perf(desktop): virtualize the timeline and bound history jumps 2026-09-16 06:39:15 -05:00
yoniebans
a63d6af683 R4: pin hidden owner hint scope for hydration and refresh
Use typed transcript fixtures and document the narrow ownership-only row fixtures for the lint ratchet.

Reported-by: kshitijk4poor
2026-09-16 13:29:36 +02:00
yoniebans
22db213917 R5: use the owner route type and colocate resolver tests
Reported-by: kshitijk4poor
2026-09-16 13:29:36 +02:00
yoniebans
6270c86f67 R3: share transcript scope resolution with tile reconciliation
Reported-by: kshitijk4poor
2026-09-16 13:29:36 +02:00
yoniebans
1323acea89 R2: require the captured runtime for transcript owner resolution
Reported-by: kshitijk4poor
2026-09-16 13:29:36 +02:00
yoniebans
45e81c0843 R1: remove unobserved transcript owner profile matching
Reported-by: kshitijk4poor
2026-09-16 13:29:36 +02:00
yoniebans
9397101dd5 test(desktop): cover unverified active transcript owner boundaries 2026-09-16 13:29:36 +02:00
yoniebans
201c7ea883 fix(desktop): require explicit tile ownership before overriding rows (F2) 2026-09-16 13:29:36 +02:00
yoniebans
b78d7f5e30 fix(desktop): reject mismatched runtime owner fallback (F1) 2026-09-16 13:29:36 +02:00
KoNit-K
7a5a9108f8 fix(desktop): keep active Bot Chat profile when refreshing history
A visible default-profile duplicate of the same stored session id was winning
visible-row-first resolution and swapping the main transcript onto the root
database. Prefer the verified tile owner for the active runtime, while still
letting a real visible row override a stale leftover hint.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 13:29:36 +02:00
brooklyn!
b4e4b9a650 test(approval): align CI with transcript hosting and terminal scope 2026-09-16 06:27:23 -05:00
brooklyn!
0d8f494a88 test(desktop): cover queued approval server-request lifecycle 2026-09-16 06:27:23 -05:00
brooklyn!
cb95c278af feat(desktop): keep live approval stacks stable during execution 2026-09-16 06:27:23 -05:00
brooklyn!
56ea9bab92 feat(desktop): stack approvals and advance exact requests with Enter 2026-09-16 06:27:23 -05:00
brooklyn!
ca6bfe2b6c feat(desktop): give queued toasts bounded card depth 2026-09-16 06:27:23 -05:00
brooklyn!
691228447d perf(desktop): observe live workspace frame pacing without synthetic sessions 2026-09-16 06:20:40 -05:00
brooklyn!
fd304509ec perf(desktop): defer closed action menus until their content mounts 2026-09-16 06:20:40 -05:00
brooklyn!
fa148ce1b7 perf(desktop): keep relational style invalidation out of unrelated panes 2026-09-16 06:20:40 -05:00
Konstantin Khlopkov
741fa6acc1 fix(desktop): pause thinking preview pin while the reader is scrolled up (#109510)
(cherry picked from commit 13a70c79db1212b373d5652a34b421c41253f901)
2026-09-16 04:59:02 -05:00
Kenshin
651268b8a7 fix(desktop): drop overscroll-contain on the thinking body (dead zone + broken chaining)
scroller, but the class is unconditional and has two problems:

- Expanded (no max-h): the body grows to its content and never scrolls
  itself, so `contain` has nothing to contain — it eats the wheel entirely,
  leaving a dead zone where neither the body nor the thread viewport scrolls.
- Preview with short content: same dead zone when content is under max-h-40.

`contain` only "works" when the body actually overflows — exactly when a
reader most wants the wheel to keep going. And it makes thinking the only
scroller in the app that doesn't chain to the transcript (settings panels,
code blocks, tool output all chain; chaining is the macOS platform default).

Drop `overscroll-contain` entirely. The body keeps `overflow-auto`: it
consumes the wheel first and, once at top/bottom, chains to the thread
viewport like every other block. Regression test asserts no
`overscroll-contain` in preview or expanded states.

Verified with a real-wheel Playwright repro (dead zone only with the
post-#95783 classes).

(cherry picked from commit 3c5b3bbff836fe8b05a04f2d219ae550f61ceded)
2026-09-16 04:59:02 -05:00
brooklyn!
e82fc060d0 fix(desktop): hand nested transcript scrolling back to the thread 2026-09-16 04:59:02 -05:00
brooklyn!
622e98787b fix(desktop): let readers scroll away from streaming thoughts 2026-09-16 04:59:02 -05:00
brooklyn!
7b6e0d3848 fix(desktop): keep tooltip wrappers from blocking fan controls 2026-09-16 04:49:32 -05:00
brooklyn!
1b7c9f6f9f fix(desktop): place tooltips around rows and controls consistently 2026-09-16 04:49:32 -05:00
brooklyn!
b8b7d7531c fix(desktop): keep tooltips compact and anchored with exit-only motion 2026-09-16 04:49:32 -05:00
brooklyn!
f30e5cbfd8 refactor(desktop): reuse ActionStatus for catalog installs 2026-09-16 04:33:07 -05:00