Commit Graph

6353 Commits

Author SHA1 Message Date
ethernet
427d0883be Merge remote-tracking branch 'origin/main' into ethie/pm-clean 2026-09-24 09:33:58 -04:00
ethernet
e8a5e0978c chore(desktop): require prepared build Python and refresh release comment 2026-09-24 09:20:50 -04:00
ethernet
edcb3346a7 fix(desktop): constrain baked environment and validate registered feeds 2026-09-24 09:20:50 -04:00
brooklyn!
30565b2db2 fix(desktop): ship a Windows voice chord that is not the sidebar toggle
Off macOS, ctrl folds to mod, so a Ctrl+B voice default is the sidebar
chord. Ship Ctrl+Alt+V instead, and let a binding be cleared to an empty
combo so sidebar mod+b can be unbound. Point the Voice settings hint at
the voice conversation action, not dictation.
2026-09-24 08:19:33 -05:00
brooklyn!
482349c5e5 fix(desktop): take keyboard focus when the terminal pane is revealed
Revealing the terminal restored the layout but left the composer holding
the keyboard. Terminals stay mounted while hidden, so the activation
focus effect never re-runs. Ctrl+backtick, the palette row, and the
statusbar pill now claim focus on the reveal direction and re-assert if
the composer steals it. Hiding does not. No second focus chord.
2026-09-24 08:18:14 -05:00
teknium1
deb4bd2c08 test(desktop): packaged boot fails fast (60s) with main log tail; README lists the new specs and KNOWN policy 2026-09-24 06:06:00 -07:00
teknium1
e0615053dc test(desktop): #120730 Bot-Mode shape (local primary + remote secondary) and a backend that really cannot see client paths
remote-secondary: a bot on a remote secondary connection (connections.json)
with the local backend as primary; a client-only image must reach the remote
as image.attach_bytes. startRemoteBackend({hide}) covers client folders with
an empty tmpfs in a private mount namespace (unprivileged userns; annotated
'fidelity' when unavailable), used by both remote specs. remote-topology:
the post-restart state.db poll (which passed before the new backend opened
the DB) is replaced by a new-pid check + the restarted backend serving the
title after reload.
2026-09-24 06:06:00 -07:00
teknium1
552704e26d test(desktop): real compaction lineages — rotated rows (#121148) and in-turn compaction handoff (#121088) as merge-order-safe KNOWN cells
lineage-sidebar's #121148/#121088 steps never compacted (/compress was
refused as would_grow on a tiny transcript), so they could not fail.
lineage-rotation drives real auto-compaction with compression.in_place:
false (state.db-verified sealed parent + continuation) and asserts one
sidebar row per lineage after rotation, reload and cold relaunch; the live
nested-branch shape is KNOWN #121148. lineage-compaction-prompt compacts
inside an acknowledged redirect turn so the refresh passes through
preserveLocalPendingTurnMessages; the duplicate prompt is KNOWN #121088.
known.ts: expectNoSymptom marks a test expected-failing at run time only on
the bug's own assertion (a fix merging first stays green). lineage-sidebar
keeps the branch/switch scenario, drops the #121096 claim and now checks the
in-page duplicate sampler.
2026-09-24 06:06:00 -07:00
teknium1
6157155c62 test(desktop): format + drop empty KNOWN scaffolding in lineage spec 2026-09-24 06:06:00 -07:00
teknium1
4e489e9ee6 test(desktop): lineage/sidebar integrity after compaction and branching (#121148 #121088 #121062 #121096) 2026-09-24 06:06:00 -07:00
teknium1
7f401ed5e0 test(desktop): remote-backend topology — image bytes not client paths (#120730), rename across backend restart (#121192) 2026-09-24 06:06:00 -07:00
teknium1
65b24e9600 test(desktop): packaged-app smoke — asarUnpack contract + packaged binary boots to a first chat (#121097) 2026-09-24 06:06:00 -07:00
ethernet
8eb20a50ae Merge remote-tracking branch 'origin/main' into ethie/pm-clean
# Conflicts:
#	agent/learning_graph.py
#	hermes_cli/backup.py
#	tests/hermes_cli/test_backup.py
#	tests/hermes_cli/test_doctor_journal_modes.py
#	tests/hermes_cli/test_sessions_set_journal_mode.py
2026-09-24 08:51:52 -04:00
brooklyn!
e755211327 fix(desktop): refocus find bar input on repeated Cmd-F
A second open while the bar is already visible rewrote EMPTY, which
cleared the query, and the focus effect only watched active, so it
never ran again. Bump focusRequest instead, keep the typed query and
the captured scope, and select the existing text on refocus.

Co-authored-by: David Metcalfe <80915+DavidMetcalfe@users.noreply.github.com>
2026-09-24 07:50:18 -05:00
denis.dresvyanskiy
5f50e5fbaa fix(desktop): announce a deferred /compress completion
A manual /compress whose session.compress reply is `status: 'pending'`
(#97948 — the gateway's compute-host wait expired while the host kept
compressing) shows one 8s "still running in the background" toast and
returns. The summary and the success toast are rendered only in the
synchronous result branch that `return` skips, so when the host finishes
the `compacted`/`ready` edge merely clears the spinner: no transcript
line, no completion toast, and hydrateFromStoredSession swaps the
transcript underneath the user with no acknowledgement it ever ran.

Claim the session on the pending reply and announce the completion on the
terminal edge, reusing the notice id the handler already notified under so
the pending toast is replaced in place rather than stacked. The transcript
line is appended only after the hydrate resolves — it replaces the
transcript wholesale and would otherwise drop the line. The claim is
consumed once, so a later auto-compaction cannot replay the notice and an
auto-compaction the user never asked for stays silent.
2026-09-24 07:47:08 -05:00
brooklyn!
20b76aac49 test(desktop): cover the live empty slash query
detectTrigger('/') passes query '', not '/'. An arrowed highlight still
accepts that row, and an unhighlighted bare slash still returns null.
2026-09-24 07:43:41 -05:00
salch-cred
9b0eb7f518 fix(desktop): honour arrowed slash-picker highlight on bare '/' query
implicitSlashAcceptIndex() returned null immediately when no command name
had been typed yet (!typed), so the activeExplicit branch was never
reached.  Pressing Enter after arrow-key selection on a bare '/' sent a
bare '/' instead of the highlighted command (#98535).

Fix: move the activeExplicit guard above the !typed early-return.  A
deliberately arrowed highlight always wins regardless of query content —
'Enter means I want this one' should hold even before any characters are
typed.

Regression tests added:
- bare '/' + arrow-key → returns the highlighted index
- bare '/' + no arrow-key → still returns null (auto-accept not engaged)
2026-09-24 07:43:41 -05:00
rodricksz4h5
c633cd87c5 fix(memory): key the journey card lookups to the fingerprinted node id
Two places map a node id back to its memory card by rebuilding the bare
`memory:<source>:<index>` string: the timeline chart rows and the desktop
starmap's tooltip/body map. With the fingerprint in the id both missed
every card, so a memory row rendered an empty body.

Both now key the card under whichever shapes apply, so an imported or
pre-fingerprint graph keeps working. The CLI help and the memory doc now
describe the id as `journey list` prints it.

(cherry picked from commit fa0c984c5d7d7ad0820fa2f2bde088e532f4e897)
2026-09-24 18:01:46 +05:30
ethernet
b50e343778 Merge remote-tracking branch 'origin/main' into ethie/pm-clean 2026-09-24 08:25:07 -04:00
ethernet
947224dd5d fix(desktop): justify short private SSH socket path to lint 2026-09-24 08:13:10 -04:00
OcuClaw
035171c7c9 fix(desktop): never clone a unified package's desktop half standalone on a local backend
The install dialog gated the package path on the agent install succeeding in
the same click (`agentInstalled && desktopHalfFromPackage`). A package already
on disk answers "Plugin '<name>' already exists. Use force reinstall" without
Force, so the retry fell through to installDesktopPlugin and cloned
desktop-plugins/<git-name>/ beside the package copy the app had already
materialised as desktop-plugins/<manifest-name>/. Two folders, one plugin id:
the on-disk duplicate from #100412 (since e1a6679399 an error row instead of
a competing live instance, but still created by the install flow).

The package path now applies whenever the repo is a unified package, the
backend is local and the Agent box is ticked, whatever the agent install
returned. reconcileDesktopPlugins() is idempotent, so a retry touches
nothing; the desktop success toast is raised only when the agent half landed
or a copy was actually materialised, so a refused install shows the agent
error alone. A failed fresh install no longer leaves a standalone desktop
clone behind for the next successful install to duplicate.

Remote backends keep the separate clone (their plugins/ folder is not
readable from this machine); the Desktop-UI-only tick is unchanged.

Fixes #100412 (install-time half; runtime half landed in #118902).

Tests: two invariants in plugin-install-modal.test.tsx, the first red on
main (installDesktopPlugin called on the refused retry), the second guarding
the remote-backend clone.

(cherry picked from commit 9fbd3a9d8328ea452a4149252a35a0e6f43982e6)
2026-09-24 06:59:49 -05:00
ethernet
a252718284 fix: keep desktop SSH control sockets short under deep homes
Use a checked private per-user directory in /tmp only when the home-based socket and OpenSSH temporary suffix exceed sun_path. Validate the directory before probing or reusing a master, and prove a real Unix listener binds with a deep HOME.
2026-09-24 07:49:37 -04:00
ethernet
43c105d5ba Merge remote-tracking branch 'origin/main' into ethie/pm-clean 2026-09-24 07:39:33 -04:00
brooklyn!
09f4adc705 fix(desktop): do not classify a signal-killed ssh child as unreachable
runSsh dropped Node's close signal, so a null exit code looked like a
plain failure. Every close consumer now keeps that signal. An empty
stderr signal death is not an unreachable host.
2026-09-24 06:23:43 -05:00
djohonson
b3ee10187e fix(desktop): fail loudly when a built renderer chunk is not valid ESM
- assert-dist-built now parses every emitted dist/assets/*.js chunk as an
  ES module (node --input-type=module --check via spawnSync) before the
  build reports success
- a silent bundler output loss (observed twice: a 10-byte identifier token
  missing from the main chunk) previously shipped a syntactically invalid
  bundle that white-screens Electron with Uncaught SyntaxError
- the loud failure feeds the existing update-path honest-retry and
  stage-and-swap, so a corrupted build retries instead of shipping
- vitest coverage: invalid chunk fails with the chunk name in the error,
  valid chunks (incl. import.meta / template literals) still pass

Fixes #105184
2026-09-24 06:23:28 -05:00
ethernet
5739bd22f6 Merge remote-tracking branch 'origin/main' into ethie/pm-clean 2026-09-24 06:55:33 -04:00
brooklyn!
d909c697f0 fix(desktop): collect artifacts referenced with #media: hrefs
Chat emits file refs as `[label](#media:<encoded path>)`, but the
Artifacts collector classified the raw href and dropped it. Decode
those hrefs before looksLikeArtifact so Windows and POSIX paths,
image markdown, and explicit tool artifact keys are collected.
Legacy MEDIA: tags and plain URLs are unchanged.

Same decode as pull 88158; that patch did not apply cleanly.

Fixes #88084

Co-authored-by: SayHell0W0rld <18085695+SayHell0W0rld@users.noreply.github.com>
2026-09-24 05:54:10 -05:00
brooklyn!
850931b4ca fix(desktop): gate Close Tab, Reload, and Zoom on keyDown
before-input-event fires for keyup as well as keydown. A Ctrl+W that
started in another app delivers its keyup when Windows focuses Hermes,
and the shortcut handlers treated that as Close Tab.

Refs #105498
2026-09-24 05:54:02 -05:00
brooklyn!
9647f3505b fix(desktop): keep inline-code MEDIA closers out of the path (#105212)
The bare-word fallback still used \S+, so relative paths and unknown
extensions swallowed a trailing backtick. Stop that alternative before
backtick and double-quote, and keep the anchored extension branch.
2026-09-24 05:53:37 -05:00
brooklyn!
fbff2b8a7a fix(auth): audit API 401s and name stale app-token mint failures
A bearer 401 from the dashboard gate was returned to the client but
never written to dashboard-auth.log. Record session_rejected with the
client-facing reason, path, and IP, and never the bearer.

When that rejection is the app's saved bearer, the desktop mint error
says the app token is invalid instead of telling the user to
re-authenticate the server OAuth session.

Fixes #103117
2026-09-24 05:33:01 -05:00
Ayush Nangia
2fabc78292 test(projects): adapt NFC regression to the current session fixture
(cherry picked from commit 380030f6f8f61dac4d181577f0ae7d9d78dfd62b)
2026-09-24 05:31:58 -05:00
Ayush Nangia
284765d3d9 fix(projects): NFC-normalize path identity so accented folders keep their sessions (#65014)
(cherry picked from commit 762e7bd49bbb0b82de41d574ad74ed39fe947507)
2026-09-24 05:31:58 -05:00
ethernet
ebc69c5faf style(desktop): keep PM source-check bridge lint clean 2026-09-24 06:30:30 -04:00
ethernet
1695fab334 fix: run Windows Desktop source checks through PM launcher 2026-09-24 06:29:22 -04:00
ethernet
2120e8728d test(e2e): route managed Desktop checks to staged Git main 2026-09-24 06:19:09 -04:00
ethernet
099addd628 fix: run Desktop source checks through PM installation launcher 2026-09-24 06:16:55 -04:00
ethernet
25b859a3ad Merge remote-tracking branch 'origin/main' into ethie/pm-clean
# Conflicts:
#	apps/desktop/electron/main.ts
#	hermes_cli/_early_recovery.py
#	hermes_cli/main_install_repair.py
#	hermes_cli/update_cmd.py
#	hermes_cli/update_cmd_deps.py
#	tests/hermes_cli/test_early_recovery.py
#	tests/hermes_cli/test_update_interrupted_recovery.py
#	tests/hermes_cli/test_update_self_lock.py
2026-09-24 05:49:00 -04:00
hermes-seaeye[bot]
76c5bdcc9d fmt(js): npm run fix on merge (#121304)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-24 09:43:10 +00:00
brooklyn!
0397efef87 fix(desktop): every project session is reachable from the sidebar
An entered lane stopped at 5 chats behind a hover-only "…" that added 5
at a time, and an expanded overview project or entered Home mounted every
loaded row at once. Lanes, expanded projects and Home now page with a
labeled "Show N more in <lane>" row (50 per step), reusing the overview's
show-all row. The collapsed preview and tree request are unchanged.

Co-authored-by: cherrish333013 <139594807+cherrish333013@users.noreply.github.com>
Co-authored-by: George Shalhoub <george@georgeshalhoub.com>
2026-09-24 04:32:58 -05:00
brooklyn!
03add1fe7a fix(desktop): keep root-only project chats out of Home
A session row with an empty cwd but a persisted git_repo_root fell to Home:
_project_for_session bailed on the empty cwd before matching the repo root,
and _place_session refused to place it, so the backend owner map made Home
the chat's single owner while the renderer (root-aware) still labeled it with
its project. Match and place on cwd, else git_repo_root; a row is homeless
only when it has neither, matching the renderer's isDetachedSession.

Entered Home's live overlay also upserted every briefly-detached live row
without consulting the authoritative owner map, so a named-project chat whose
session.info landed with an empty cwd listed in Home as well. overlayHomeLane
now takes the owner map from overlayLiveLanes and skips rows (by id or
lineage root) owned by a named project.

Refs #77591 (symptom D, entered-project refetch lag, is not addressed).

Co-authored-by: networthexplained <300128320+networthexplained@users.noreply.github.com>
2026-09-24 04:31:47 -05:00
brooklyn!
94dcb170fe fix(desktop): isolate primary and pooled backend spawns from launch-profile secrets
Both local `hermes serve` spawn sites spread process.env into the child.
Route them through profileBackendParentEnv so a pooled profile backend, and
a primary pinned to (or sticky on) a non-launch profile, only get the
credentials their own profile scope provides (#68367).

Co-authored-by: Yash Jain <23dec512@lnmiit.ac.in>
2026-09-24 04:29:19 -05:00
brooklyn!
d17f5191cc fix(desktop): profile backend env drops the launch profile's dotenv names
`hermes desktop` loads its launch profile's .env/.op.env into os.environ
before exec'ing Electron, so every Desktop-spawned backend inherited that
profile's credentials. A named profile with no TLON_* (or its own .op.env)
still came up with the default profile's values ahead of its own dotenv.

profileBackendParentEnv() returns the parent env for a `hermes serve`
child of a given profile: unchanged when the child is the launch profile,
otherwise minus every name the launch profile's .env/.op.env declares
(OS names like PATH/HOME excepted). Mirrors _profile_action_environment on
the dashboard side. Windows folds env names and home paths.

Co-authored-by: Yash Jain <23dec512@lnmiit.ac.in>
2026-09-24 04:29:19 -05:00
brooklyn!
7ba3a71611 fix(desktop): closing a tool tab in the chat's zone fronts the chat 2026-09-24 04:27:38 -05:00
ethernet
c70129205f Merge remote-tracking branch 'origin/main' into ethie/pm-clean 2026-09-24 05:10:12 -04:00
ethernet
7dd4d7556c test(installer): drop retired Windows venv path assertions 2026-09-24 05:10:06 -04:00
ethernet
ca06a8dec9 Merge remote-tracking branch 'origin/main' into ethie/pm-clean
# Conflicts:
#	apps/bootstrap-installer/src-tauri/src/update.rs
2026-09-24 05:03:23 -04:00
brooklyn!
ecacf3d0c9 fix(desktop): declare the branch methods in the typed gateway contract
Rebased onto main, where params are validated against tui_gateway/contracts
and unknown keys are rejected: the copy_parent_history / omit_messages flags
on session.create and session.branch now answered 4000. Keep both methods'
wire shape unchanged and give the two new methods their own contracts
(session.branch_stored, session.branch_whole) with messages_omitted results;
the handlers take the behaviour as keyword arguments, not wire flags.
2026-09-24 03:57:08 -05:00
Benjamin Brumbaugh
d95a6bc910 fix(desktop): preserve message-level branch responses 2026-09-24 03:57:08 -05:00
Benjamin Brumbaugh
1c7ec93aea fix(desktop): preserve branch compatibility with older gateways 2026-09-24 03:57:08 -05:00
Benjamin Brumbaugh
44812b5e90 fix(desktop): branch long sessions without renderer transcript load 2026-09-24 03:57:08 -05:00