Commit Graph

85 Commits

Author SHA1 Message Date
Teknium 23fa4ae748 docs: explain live subagent monitoring across chat surfaces 2026-09-08 03:06:30 -07:00
Teknium 478d772f2c fix(desktop): resolve artifact downloads in their originating session 2026-09-07 07:11:36 -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
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 9a78d5ac2b test(desktop): document and probe reading-position restoration 2026-09-07 06:14:35 -07:00
Teknium 5f02693fe0 fix(desktop): reconnect only the active gateway route 2026-09-07 06:12:00 -07:00
Teknium c0c6b31543 fix(update): stream build progress without concealing silent stalls
Retain partial-line output, UTF-8 decoding, failure output and cancellation cleanup. Based on streaming investigations by Artemonim (#101850) and lEWFkRAD (#104843); gateway tee adapted from fangliquanflq (#97402). Live Linux child/tee probe: withheld or dropped on base, visible in 0.02 seconds after. Campaign-locked tests and native Windows proof are pending.
2026-09-07 05:56:50 -07:00
Teknium 513c0b2e3c fix: follow focused session panes in desktop sidebar
Reuse the focused pane derivation for visible sidebar activity rather than trusting a stale workspace route. Live Electron reproduction: Kanban stayed highlighted while a resumed session tab was visible; the highlight now clears without changing the retained route. Adapted the rendered sidebar invariant and focus derivation from MarcoFernstaedt's PR #88691 for #88517. Directory suite queued under the campaign test lock.
2026-09-07 05:56:02 -07:00
Teknium 8c10ffba55 fix: preserve Desktop async report bodies during hydration
Keep compact completion labels while rendering only result and job output bodies, including legacy and batch deliveries. Credit Gyarados4157's #101083 investigation; avoid rendering its full model instruction envelope.
2026-09-07 05:06:39 -07:00
Teknium 55ad5afa12 fix(desktop): retain Markdown boundary and code-copy whitespace 2026-09-07 04:57:11 -07:00
Teknium 3e1b7af21b fix(desktop): preserve Markdown whitespace through media extraction
Remove whole-document whitespace cleanup that erased hard breaks and fenced-code spacing across all five ingestion paths. Limit generated-image gap joining to the removed image itself. Keep soft newlines as soft breaks.

Investigated #97117 and the approaches in #97431 (@wooyongbin3-cpu) and #97175 (@Jackal991); both leave fenced-code whitespace and sibling ingestion paths exposed, so remove the destructive normalization instead.
2026-09-07 04:57:11 -07:00
Teknium 80e585fad3 test: verify desktop task tails remain reachable in Chromium 2026-09-07 04:56:05 -07:00
HoneyTyagii 381d6064d7 fix(desktop): preserve custom Linux launcher entries when opted out
Salvage #101453 (03a3f466d38134ba416764185884b3d655197a1d). Preserve its opt-out and first-run behavior; replace predicate-mocked tests with one native config/filesystem invariant and clarify XDG docs. Real venv/XDG probe: base clobbers custom entry, fix preserves it; targeted suite 94 passed.
2026-09-07 04:55:17 -07:00
Brooklyn Nicholson 06a4f4ab31 feat(desktop): group a comment batch by page region so it lands as a few tasks
Twenty-three comments arrived as twenty-three flat blocks, so the agent made
twenty-three todos and ground through them one at a time. They now arrive
grouped by where they sit in the page, with a line telling the agent to work
the groups rather than the comments.

The renderer groups on structure, not meaning. Whether a comment is a UI nit
or a functional bug is a judgment only the model can make, and prose-matching
it here would be wrong constantly; which pins share a DOM subtree is something
the selector already answers. That split is also the one that makes parallel
work safe — grouping by theme instead ("all the spacing ones") cuts across the
same components and puts several workers in the same files, so the guidance
says to hand out whole groups and never to regroup by theme.

Grouping compares ancestor paths, so a heading and a paragraph in one card
stay together instead of becoming two singletons. Depth is derived rather than
tuned: descend the shared prefix until it stops being shared, then sub-split
any group still holding more than a third of the batch — without that pass a
normal page buries every section under `main`. Batches under four comments,
and batches that all land in one region, stay flat.

Grouping is advice in the prompt, never an action: the renderer does not spawn
or delegate anything. That stays the agent's call.
2026-09-02 12:29:25 -05:00
Brooklyn Nicholson e4bda3ff77 feat(desktop): browser comments carry the element's selector, markup, and styles
Comment mode shipped the crop and the note, so an agent got a picture of the
problem and had to grep for the element it showed. Each element comment now
also names its CSS selector, its markup, and the computed styles that decide
layout, which is what the agent needs to land in the right file.

The target line stays prose — it is what the user pointed at — and the DOM
detail rides labelled lines beneath it. Area pins have no element, so they
still get only the crop and the note.

Markup is redacted in the guest before it crosses to the host: password and
hidden input values, and any attribute reading as a key/token/secret, are
replaced with [redacted] on a clone, so a page's secrets never reach the
composer or the model. It is clipped to a 600-char budget so one comment
cannot paste a whole section.

AnnotateIdentity was a hand-copy of CompactIdentity that had already drifted;
it is now an alias, so the guest, the pin, and the packer cannot disagree
about the shape again.
2026-09-02 12:29:25 -05:00
Teknium 648c664eb3 feat(desktop): gate cold-start restore on display.resume_last_session
- use-desktop-integrations: hold the restore latch until the config
  record answers; when false, stay on the fresh chat (route and session
  restore alike) while still remembering the open chat for next launch.
- wiring: read the shared config-record query; undefined while pending,
  fetch failure falls back to the historical behavior (resume).
- appearance-settings: ToggleRow writing through the shared config
  cache with rollback + notifyError on a failed save.
- ar/ru strings, docs line in user-guide/desktop.md, two hook tests.
2026-09-02 05:56:54 -07:00
Teknium aaa34b0e08 fix(desktop): model picker no longer hardcodes --global; one persist policy for every surface (#90235)
Symptom: picking a model in the Desktop composer for the primary chat
silently rewrote config.yaml (model.default + model.provider) as the
profile default, ignoring model.persist_switch_by_default. A throwaway
pick that resolved to e.g. openai-api (no key) left the profile with an
unusable default on the next launch (#90235).

Root cause: 7d96537bc8 (#86414) made use-model-controls.ts send --global
for every primary-tile pick so a fresh profile would get a persisted
provider instead of falling through to a leftover OPENAI_API_KEY env var.
That put a persistence policy in the client, contradicting the
server-side rule /model uses (resolve_persist_behavior).

Fix:
- resolve_persist_behavior gains one rule, ahead of the --provider
  session-only rule: when neither model.default nor model.provider is
  configured yet, persist. This preserves #86414's first-pick motivation
  for CLI, gateway and Desktop alike. With a default configured, a plain
  pick is session-only unless --global / persist_switch_by_default.
- Desktop primary-tile picks send no scope flag and let the gateway decide.
  Secondary tiles and MoA presets still send --session.
- /model help text in cli.py said "(persists)"; it now matches reality and
  lists --global.
- Docs: desktop.md picker note + slash-commands /model row.

Tests: test_first_pick_persists_then_session_only (fails on main), and the
existing use-model-controls vitest updated to assert the flag-less request.
2026-09-02 05:33:33 -07:00
Teknium 3e63367175 feat(desktop): status bar can show live cache-hit rate and tokens/sec (off by default)
Two new right-click-toggleable status bar items, mirroring the CLI/TUI
Pantheon status bar upgrades: prompt-cache hit rate ("87%") and rolling
output throughput ("42 t/s"). Both are hidden by default and enabled from
the bar's existing 'Show in status bar' context menu, like the context meter.

Renderer-only: the tui_gateway already emits cache_hit_pct and avg_tps in
every session.usage tick and message.complete payload, so the items ride
the same UsageStats the context meter reads — no new RPC, no polling.
Labels show a placeholder until the backend has data, never self-hide.
2026-09-02 03:06:20 -07:00
emozilla 43e67d872f feat: local models — managed llama.cpp runtime with one-click desktop setup
Run models locally as a first-class provider. The CLI grows a managed
llama.cpp runtime (engine install, model download, server supervision);
the desktop app grows the full setup and management story on top of it.
GUI surfaces ship behind the desktop --local launch flag (hermes desktop
--local, or the flag on the packaged app); backend routes and the CLI
are always live.

Runtime (hermes_cli/local_runtime/):
- curated GGUF catalog with per-machine variant selection: hardware
  probe (VRAM/RAM/UMA), fit planning with spill accounting, quant choice
  by context window
- derived recommendation: quality-ranked picks gated by a predicted
  decode-speed floor, bandwidth-aware on unified memory; the decision
  table is pinned as a test (pick AND reason per memory class), and the
  Recommended badge explains its pick in a tooltip fed by the resolver's
  actual branch
- engine install + model download with resumable split parts, cumulative
  plan-level progress, and staged-model integrity (a split GGUF counts
  only when every part is present)
- server supervision: spawn/adopt/stop, router mode with per-model load
  progress relayed over SSE, abandoned-request cleanup

Desktop:
- Settings -> Providers -> Local models: one-click quickstart (install
  engine, download the recommended model, boot) plus per-model download/
  activate/eject, fit-ranked catalog with context pills
- model pickers (composer dropdown + Cmd+K) show staged local models,
  in-flight downloads as live progress rows, and load-into-memory bars
- local-setup campaign tip for eligible hardware; System resources
  statusbar widget (GPU/VRAM/RAM); in-chat load progress during sends
- friendly dead-server errors, and failed agent builds retry on the next
  send instead of wedging the session

Co-developed with NVIDIA field feedback on RTX 5090 and DGX Spark.
2026-09-01 16:01:53 -04:00
Teknium 269e5bde33 fix(desktop,i18n): polish Russian catalog and register ru in locale tests/docs
- Translate leftover English 'toolset(s)' strings in ru.ts
- Cover ru aliases/config value in languages.test.ts (parity with ar)
- List Russian among desktop UI languages in website/docs/user-guide/desktop.md
2026-09-01 08:31:03 -07:00
Teknium a1c25d393a feat(desktop): built-in optional-skills catalog in Capabilities → Skills with one-click install
The Skills tab now lists the entire official optional-skills catalog
(optional-skills/ shipped with the repo) below the installed skills.
Each catalog row has an Install button that routes through the standard
hub action pipeline; once the install finishes the row flips into the
installed list with the normal enabled/disabled toggle.

- backend: GET /api/skills/hub/official — OptionalSkillSource.list_local()
  scan (no network) + per-profile installed flags from the hub lock
- desktop: catalog section in SkillsView with search/scope integration,
  install-state spinners off $hubActions, and an OfficialSkillDetail pane
  (hub preview: frontmatter + full SKILL.md + Install)
- CapRow gains an optional action slot (button instead of the Switch)
- electron: route the new endpoint with the skills family (primary backend)
- i18n: officialCatalog/officialPill keys across en/ja/zh/zh-hant
2026-09-01 01:39:59 -07:00
Teknium 66e258b4b9 docs(desktop): document the in-app browser comment mode
Covers the Annotate toggle, numbered pins, save-never-sends, and
Add N comments -> composer flow shipped in #100083.
2026-09-01 01:17:33 -07:00
Teknium be85903234 feat(macos): one-switch Full Disk Access guidance in doctor and setup
The last piece of the macOS permissions campaign (#52010 follow-up): macOS
prompts per-folder (Desktop, then Downloads, then Documents, ...) as the
agent touches each one — a drip-feed of dialogs on first use. ONE Full Disk
Access grant covers all of them permanently, and with the stable signing
identities merged this week it survives every update. Nothing in Hermes
taught users that.

- hermes doctor: check_macos_full_disk_access() — prompt-free probe (the
  FDA-gated TCC db dir returns EPERM without a dialog; TCC only prompts on
  protected-CATEGORY paths), reports granted state or prints the one-switch
  setup with the Privacy_AllFiles deep link.
- hermes setup: same probe at the end of onboarding — the moment users are
  primed to do system setup — silent when already granted, indeterminate,
  or non-macOS.
- docs: desktop.md TCC section now leads with the one-switch guidance.
- 7 tests (granted / denied / indeterminate / non-macOS, both surfaces).
2026-08-26 06:26:07 -07:00
David Metcalfe 36c1755065 fix(macos): detect stale TCC grants and guide one-time re-grant
TCC keys permission grants to the app's code-signing requirement. Grants
made to pre-#73681 builds carry a cdhash-pinned requirement that no
longer matches the rebuilt bundle, so macOS re-prompts on every capture
even though the System Settings toggle shows ON — and the modern prompt
has no Allow button, so users cannot complete the one-time re-grant.

- hermes doctor: new check_macos_tcc_grants() reports the desktop
  bundle's DR class (cdhash-pinned → grants reset on every update;
  identifier-pinned → stable) and prints the exact stale-grant repair
  (tccutil reset, toggle ON, fully quit & relaunch).
- hermes update: after a successful update on macOS with a desktop app
  installed, print the one-line stale-grant guidance.
- docs: desktop.md no longer claims grants persist 'out of the box';
  documents the one-time re-grant for pre-fix grants.

Closes #86385
2026-08-25 21:59:36 -07:00
Teknium 28f2ea86e2 fix(desktop): make --setup-tcc-identity produce a VALID signing identity on modern macOS
Fixes the two live E2E blockers @ctaylor86 found on PR #77189 (macOS 26.3.1,
OpenSSL 3.6.3):
- retry the PKCS#12 export with -legacy when security import rejects the
  OpenSSL 3 default format ('MAC verification failed during PKCS12 import')
- trust the self-signed root for the codeSign policy (security
  add-trusted-cert -r trustRoot -p codeSign) — an imported-but-untrusted cert
  is invisible to find-identity -v and unusable by codesign
- gate success on find-identity -v -p codesigning (postcondition), and use
  the same -v probe for idempotency so an untrusted leftover cert is repaired
  instead of reported as done

Tests rewritten as stateful fakes (valid only after import+trust), plus new
coverage for the -legacy retry, trust failure, postcondition gate, and the
untrusted-cert repair path; sabotage-verified (reverting to the name-in-output
probe fails 4 tests). Docs: manual fallback now includes the Trust step.
2026-08-25 16:24:19 -07:00
CriptoGus eeb391d0b1 feat(desktop): add --setup-tcc-identity to keep macOS TCC grants across rebuilds
Adds a one-shot `hermes desktop --setup-tcc-identity` command that creates a
self-signed code-signing certificate in the login keychain (openssl +
security import), grants codesign access to it, writes
desktop.macos_signing_identity to config.yaml, and re-signs the packaged app
with a certificate-anchored Designated Requirement.

macOS persists permission grants (Full Disk Access, Accessibility, Files and
Folders, microphone) against the app's code-signing identity, not its path.
The default identifier-pinned ad-hoc signature is stable across rebuilds, but
a certificate-anchored identity is the strongest guarantee — the same
mechanism yabai/skhd rely on. Previously users had to create the certificate
manually in Keychain Access; this command automates the whole flow and is
idempotent (re-run after updates).

Docs: desktop.md TCC section now leads with the command, keeps manual steps.
Tests: 4 new — fresh cert creation path, idempotent reuse, non-macOS no-op,
cmd_gui early-exit before build.
2026-08-25 16:24:19 -07:00
SHL0MS e2e8d7e59a fix(web): keyword-align titles of six high-impression docs pages
GSC page-level data shows configuration (171K impr, pos 5.3), quickstart
(135K, 5.3), providers (123K, 5.3), web-dashboard (68K, 6.5), docker
(37K, 6.3) and the desktop app page (98K, 3.9) all losing ranking
headroom because their title/H1 are bare nouns instead of the terms
people search.

- Frontmatter title + H1 now carry the query terms on all six pages
- Desktop docs page links back to the new marketing /desktop product
  page, joining the two official properties Google sees for the query

Done by Hermes Agent (deepseek-v4-pro via nous), Nous Research.
2026-08-24 17:40:59 -04:00
Brooklyn Nicholson 7e500d2ead fix(desktop): float and pin the HUD on Hyprland
Omarchy tiles the HUD like any other toplevel, so always-on-top and
xdg_toplevel.move never apply. Ask Hyprland to float+pin after map,
trying classic dispatch then Lua for 0.55+ configs.
2026-08-24 11:57:38 -05:00
howdeploy 81baae6bc3 fix(desktop): polish HUD movement and resizing on X11 2026-08-24 06:48:10 -05:00
Brooklyn Nicholson 4fee6f31a0 docs(desktop): document Linux and Wayland HUD behavior
Spell out native-compositor drag, the ozone_platform_hint escape hatch
for COSMIC always-on-top, and the snap-to-pointer no-op on Wayland.
2026-08-24 06:48:10 -05:00
Teknium 8f30e9c77a feat(desktop): Send Diagnostics — one-click redacted debug-bundle upload from the error card
New diagnostics.share_nous RPC reuses the CLI --nous pipeline
(collect_share_bundle → build_nous_bundle → share_to_nous) with redaction
forced on; accepts redacted error context + client-side extra files
(local desktop.log on remote connections) with sanitized labels and size
caps. Desktop: Send Diagnostics action on the failed-turn error card →
consent modal (privacy notice, explicit Upload) → private view link +
GitHub Issues / Nous Portal Support / Discord handoff. CLI --nous success
output gets the same three-destination pointer. i18n en/ja/zh/zh-hant/ar;
docs updated.
2026-08-21 23:01:30 -07:00
Teknium 334bcbac93 fix(desktop): error card honors the classifier's retry verdict + failing-session identity (review feedback)
Addresses @helix4u's review on #91493:
- conversation_loop now stamps failure_retryable (the real ClassifiedError
  verdict) next to failure_reason; error_surface prefers it and only falls
  back to the reason set for older results. Fallback set corrected to match
  classify_api_error (auth, format_error, billing_unverified now
  non-retryable).
- The descriptor carries the failing session's provider/model captured at
  classification time; Copy error details prefers them over the foreground
  composer atoms.
- Open logs is labeled 'Open Desktop logs' on remote/cloud connections —
  the local folder holds transport logs, not the remote runtime's.
- API-exception module allowlist widened to botocore/boto3/google/grpc/
  requests/aiohttp so other adapter SDKs don't misclassify as gateway.
2026-08-21 15:24:03 -07:00
Teknium 50f1e414bc polish(desktop): rename error-card action to 'Copy error details'
'Copy diagnostics' was dev-speak; match the familiar OS-error phrasing.
All five locales + docs updated.
2026-08-21 15:24:03 -07:00
Teknium 3903428a72 Revert "feat(desktop): error card offers Nous support link on Portal-auth sessions"
This reverts commit 31872bfcf555cedb2501122a75e29328c0e90e80.
2026-08-21 15:24:03 -07:00
Teknium e3d46bb5fb feat(desktop): error card offers Nous support link on Portal-auth sessions
Sessions running on provider 'nous' get a 'Nous support' action on the
failed-turn card, opening the portal help hub
(https://portal.nousresearch.com/help — docs, Discord, GitHub) in the
external browser. All five locales + docs updated.
2026-08-21 15:24:03 -07:00
Teknium 98f6fc549a feat(desktop): failed turns name the failing layer with recovery actions
Turn errors now carry a structured {layer, code, retryable} descriptor
(agent/error_surface.py) built from the same classifier the retry loop
uses. The tui_gateway stamps it on terminal error frames, retained
failed-turn snapshots, and resume replay; the Desktop error card renders
the layer title (provider / endpoint / streaming / auth / billing /
gateway / runtime / disk) plus matched actions: Retry, Switch provider,
Open logs, Copy diagnostics.

Older backends that omit the descriptor keep today's behavior (generic
title, string-sniff fallbacks) — the field is advisory on both sides.
2026-08-21 15:24:03 -07:00
Teknium fa2601c2f5 docs(desktop): troubleshooting entry for SSH host-key-changed latch 2026-08-20 02:07:10 -07:00
Teknium bd5b221a61 feat(desktop): updating now updates every target — remote backends, other gateways, and the app itself
Remote-mode installs had every update affordance (About panel Update now,
⌘K Update Hermes, the update-ready toast) pointed at the BACKEND only, so
users updated their VPS forever while the desktop app itself sat weeks
stale — with no signal it was behind (the skew warning only fired the
other way). Reported by Santiago Sarceda: mac app on v0.20.0 kept
repro'ing UI bugs fixed on main because 'update' never touched the app.

- store/updates.ts: applyEverythingUpdate() orchestrates all targets —
  active backend first (detailed progress), every other eligible
  registered gateway via the existing Electron fan-out (cloud rows skip),
  the client LAST (its apply relaunches the app). startActiveUpdate/
  requestActiveUpdate route through it whenever more than one update
  target exists; single-machine installs keep the one-button flow.
- After ANY successful backend update, the client version is re-checked
  and a one-click 'Update desktop app' warning fires if the GUI is still
  behind — the reverse-skew signal that didn't exist.
- electron: hermes:connections:update-all accepts optional excludeIds so
  the flow doesn't double-dispatch the active backend / local runtime.
- i18n: 7 new updates.* keys across en/zh/zh-hant/ja/ar.
- docs: desktop.md Updating section + multi-connection guide.
- tests: 10 new cases (gating, ordering, exclusions, failure isolation,
  memoization, nudge on/off).
2026-08-20 01:48:05 -07:00
David Dudok de Wit 72fc5ab7ca fix(desktop): use gateway terminology in connection UI 2026-08-18 22:03:25 -07:00
David Dudok de Wit 2228bc7d88 feat(desktop): remember the last used source 2026-08-18 22:03:25 -07:00
David Dudok de Wit ccd30f955c feat(desktop): distinguish sources from profiles 2026-08-18 22:03:25 -07:00
David Dudok de Wit 4ea516b8d4 docs(desktop): explain multi-source session scoping 2026-08-18 22:03:25 -07:00
Teknium 6170f844c4 fix(desktop): remove profile scoping from the Gateways settings page
The unified Gateways settings page (from the recent settings merge) still
carried the legacy per-profile gateway-override machinery: an "Applies to"
profile-chip scope switcher, a scope state machine threaded through load/
save/test/sign-in paths, inherit-mode ModeCard variants, and an SSH
remote-profile mapping row.

The page is machine-level gateway management: it decides which gateway
backends this desktop can connect to, and profiles are discovered FROM the
connected gateways. It must not be profile-scoped.

- Delete the scope chips section, ScopeChip component, and the scope/setScope
  state; every scope-conditional collapses to its global (scope === null)
  branch. getConnectionConfig/save/apply/test/sign-in are all unscoped now.
- ModeCard local card always renders the local title/desc (inherit variants
  gone); SSH remote-profile mapping row removed.
- i18n: drop now-unused gateway keys (appliesTo, allProfiles,
  defaultConnection, profileConnection, inheritTitle, inheritDesc,
  sshRemoteProfileTitle, sshRemoteProfileDesc) from types.ts and en/zh/
  zh-hant/ja/ar in sync; rewrite the gateway intro in each locale to say
  connections are machine-level and profiles come from gateways.
- Tests: replace the scope-switching component tests with a machine-level
  assertion (loads getConnectionConfig(null), never a profile scope, no
  scope UI rendered).
- Docs: update desktop.md and multi-connection-desktop.md wording — gateway
  connections are machine-level; per-profile backend routing continues via
  the profile rail / session source surfaces, not the settings page.

The electron main-process per-profile override mechanism
(getConnectionConfig(profileName), route map) and the profile-rail connect
flows are intentionally untouched; only the settings page loses the
affordance.
2026-08-17 20:39:02 -07:00
Teknium d127b27303 docs(desktop): document the tabbed SESSIONS|BOTS sidebar, Bots-mode-only Cronjobs pane, per-bot Hide/Unhide, and host.paneVisibility (#88788, #88800) 2026-08-17 19:22:47 -07:00
Teknium 24f7f9a9da docs: reflect the unified Gateways page, settings profile scope, plugins cleanup, Bot Mode group rows, and host.openWorkspace
Update the desktop docs for five just-merged desktop changes:

- Settings → Gateway + Settings → Connections are now one "Gateways" page:
  retitle every reference, describe the Add-connection flow's four kinds
  (Local / Hermes Cloud / Remote gateway / SSH) and the save-time duplicate
  rules (one local; URL-normalized dedupe across remote/cloud; user@host:port
  + remote profile for SSH), and describe the "Per-profile overrides"
  subsection that replaced the page-level Applies to chip row.
- Document the shared "Applies to" profile scope on the config-backed
  settings pages (Model, Workspace, Safety, Memory & Context, Voice, Chat,
  Advanced, Tools & Keys) and the Messaging overlay.
- Agent plugins section: bundled built-ins are hidden (user/git/project/
  pip/portable installs only), Example Plugin is gone, and the section has
  its own Applies to selector backed by plugins.manage's optional profile
  param.
- Bot Mode: group chats are standalone Discord-style roster rows and open
  in the main chat window (older builds fall back to the in-panel view).
- Desktop Plugin SDK: document the new host.openWorkspace(id, { render,
  title, minWidth, onClose }) door, its refresh/re-front semantics, and
  the feature-detection fallback pattern.

Also retitles the Settings → Gateway references in the web-dashboard guide.
No new pages; sidebars.ts unchanged. `npx docusaurus build` passes.
2026-08-17 17:23:25 -07:00
Teknium 66221397a1 fix(bot-mode): always hide Bot Mode sessions from the global Sessions sidebar
Bot Mode's group chats spawned one per-member session per room, and those
"Group: ..." rows (plus canonical Bot Chats when the old eye-toggle pref was
off) flooded the global Sessions sidebar — a 6-bot room dumped six identical
rows into recents (reported with screenshot, Aug 17).

Plugin (apps/desktop/src/plugins/hermes-bots/plugin.js):
- session.create now passes hidden:true UNCONDITIONALLY for both canonical
  Bot Chats and group-room member sessions; the $hideBotChats pref, its eye
  toggle, and its storage hydrate are removed (Bot Mode sessions are plumbing
  or plugin-owned forever-chats, never scratch conversations).
- hideOwnedBotSessions(): idempotent reconciliation sweep over every owned
  session id (bot meta canonical chats + each room's member sessions) via
  session.set_hidden, run on plugin load and on each gateway reconnect, so
  rows born visible under the old pref get cleaned up.
- The Bots session browser and canonical-chat recovery scan pass
  include_hidden:true so they still see the rows they own.

Gateway (tui_gateway/methods_session.py):
- session.list honors an include_hidden param (default off — the resume
  picker and all global callers keep dropping hidden rows).
- session.set_hidden gains a durable fallback: when no LIVE runtime session
  matches, resolve the stored session id in the target profile's state.db
  (via resolve_session_id) and flip the flag there. The sweep holds stored
  ids for chats that aren't live; the old live-only lookup 4001'd them.

Validated E2E with real imports against a temp HERMES_HOME: born-hidden row
(hidden=1), profile-scoped session.list default vs include_hidden (0 vs 1),
and stored-id sweep on a non-live legacy row (hidden=1). Plugin suite
167/167; new RPC regression tests in tests/tui_gateway/test_session_hidden_rpc.py.
2026-08-17 16:02:42 -07:00
Teknium bf53915331 docs: Bot Mode guide — Create-on picker, cross-machine mentions + group chats
Community asks (Discord, Aug 17): unclear what happens across cloud vs
desktop, whether every bot replies in group chats, and how to persist
connections to multiple gateways.

Extends the Bot Mode user-guide page (landed on main today) with the new
cross-connection features:

- "Create on" picker: creating an agent on another registered machine, with
  the remote-target caveats (clone source, staged capability checklists,
  draft discard).
- Group chats: explicit "not every bot replies" explanation of the
  round-robin/pass model, and rooms spanning machines with device badges.
- @mentions across machines via the Connections registry (no gateway switch).
- Bots-across-machines section: persistent SSH inventory, last-known rows,
  and the stay-in-your-chat interaction model; cloud+desktop recipe.
- desktop.md Bot Mode section links to the full guide; multi-connection
  page's Bot Mode reference points at the docs page instead of the old
  standalone repo.
2026-08-17 14:32:52 -07:00
Teknium 78a4693eef fix(agent): scope the Bot Mode protocol section to canonical Bot Chat sessions
Per review: the protocol belongs only in official Bot Mode interactions,
not every session on a managed install. The prompt builder now injects
the section only when the agent's session row is titled "Bot Chat"
(BOT_CHAT_TITLE, matching the desktop's createCanonicalChat pin and the
`hermes -p <bot> chat -c "Bot Chat"` resume target). Regular sessions
never carry it; the desktop composer middleware owns @mention sends.

Title is read once at first prompt build and the rendered prompt is
cached + DB-restored — cache-safe. E2E against the real AIAgent +
SessionDB: absent in an untitled session, present in Bot Chat,
byte-stable across rebuilds, absent after retitle, absent with the
flag off. Overhead unchanged (~916B, Bot Chat sessions only).
2026-08-16 18:30:53 -07:00