Commit Graph

790 Commits

Author SHA1 Message Date
Teknium b154046e4e chore: map contributor email for zhuermu 2026-08-19 01:19:37 -07:00
marketing2981 ed47d41dc9 fix(desktop): bot navigation no longer forces the all-profiles sidebar on
Every host.openSession call in the Bot Mode plugin omitted
keepAllProfilesScope, so the SDK applied its default and flipped
$showAllProfiles back on whenever the target session belonged to a
different profile than the live gateway (sdk/index.ts:
options.keepAllProfilesScope !== false => setShowAllProfiles(true)).

For anyone running more than one profile this silently undid the sidebar
profile filter: narrow Sessions to one profile, click any other bot, and
the unified all-profiles list came back.

Bot navigation is an explicit context switch into that bot's profile, so
pass keepAllProfilesScope: false at every openSession call site (4 on
current main after the plugin.js refactor consolidated the original 7).

Salvaged from PR #89031 onto current main; includes contributor mapping.
2026-08-18 21:52:41 -07:00
Jay 104ec97595 fix(bot-mode): group room preview shows the bot handle, not @default
`botHandle()` exists so that, per its own comment, "the word 'default'
never surfaces in the UI" — it presents the primary profile as `hermes`.
The roster rows, mention resolution and the group-chat prompt all route
through it. Two preview paths did not, and rendered the raw profile name:

- `GroupRow`'s room preview line built `@${last.from?.name}`, so a group
  room read `@default: …` while the bot answers to `@hermes`.
- `previewKind()` returned the raw captured name from the bot-to-bot
  delivery prefix, so the `🤖 @<name>` badge and its tooltip could show
  `@default` too.

The mismatch is presentation-only, but it reads as a routing bug: the
room says the message came from `@default` while `@default` is not a
handle the mention resolver accepts, so users reasonably conclude
bot-to-bot addressing is broken when it is working correctly.

Both paths now map through `botHandle()`. `GroupRow` passes the matching
member so a bot with a custom handle keeps it; `previewKind` maps the
lowercased sender name, which leaves every non-primary profile unchanged.

Tests: the primary profile resolves to `hermes` and a named profile keeps
its own handle (behavioural, in the existing previewKind suite), plus a
source-shape assertion for the render path matching that file's
convention. Both new assertions fail against the pre-fix source.

Fixes #89484
2026-08-18 21:50:31 -07:00
Axl Ibiza, MBA 693c0e1c62 chore: remove case-colliding agent@Agents-Mac-mini.local contributor entries
The tracked contributors/emails/agent@Agents-Mac-mini.local and
agent@agents-Mac-mini.local differ only by case, which cannot materialize on
case-insensitive filesystems and surfaces one of them as perpetually modified
in git status, breaking clean checkouts. These entries are stale agent
identifiers, not real contributors; remove both.
2026-08-18 16:27:32 -07:00
Axl Ibiza, MBA 0ee9bc8d1e fix(agent): give interrupted-turn hidden placeholder a neutral provider-replay sidecar
Bot-mode interrupted member turns with no visible assistant text persisted an
empty assistant row (content="" + display_kind="hidden"). The pre-call
sanitizer repair_empty_non_final_messages() re-healed that row on every later
call (wire copy only), so the loop never converged (#88955).

Stamp api_content="[response interrupted]" (the canonical
_INTERRUPTED_PLACEHOLDER) on the hidden placeholder instead. display_kind is
stripped before sanitization, but api_content is projected back into content
for historical assistant rows, so the provider sees a non-empty neutral turn
and the sanitizer stops touching the row — while the durable transcript stays
hidden and empty. Uses the neutral interruption text, never the
_INTERRUPTED_SCAFFOLD_MARKER, which replaying as assistant text caused #81841.

Adds regression coverage proving (A) the placeholder carries the replay
sidecar, (B) two consecutive projections converge without sanitizer healing,
(C) the sanitizer still repairs genuinely-empty unmarked assistants.

Refs #88955
2026-08-18 16:27:32 -07:00
Teknium c7d0f6c35f fix(providers): honor a custom base_url over models_url in fetch_models
Follow-up to the salvaged CommandCode signature fix: accepting base_url
but ignoring it left custom endpoints (user-configured model.base_url /
COMMANDCODE_BASE_URL proxies) fetching the public catalog instead of the
configured one. Reviewer dansigma flagged this on PR #88851.

Class-wide fix, not a CommandCode patch:

- providers/base.py: a caller base_url that DIFFERS from the profile's
  default now wins over models_url. Equality with the default means "not
  customised" (callers pass base_url unconditionally, defaulting to the
  profile's own URL) and keeps models_url as the endpoint, preserving the
  OpenRouter-style split-catalog behavior.
- commandcode: _fetch_commandcode_models() takes the endpoint override;
  both profile overrides forward base_url.
- Tests: base-class precedence (custom beats models_url, default does
  not), CommandCode redirect via live local HTTP server incl. claude-*
  filter, and default-echo hitting the canonical endpoint. All verified
  to fail against the pre-fix implementation (sabotage run).
2026-08-18 14:27:36 -07:00
Teknium 38b7a40382 chore: map whisky0809 contributor email 2026-08-18 14:19:39 -07:00
Peter 6a3ef22346 fix(desktop): render math and missing markdown elements in .md file preview
The preview renderer for .md files was missing the math plugin, table/image/link components, and the markdown preprocessing pipeline that the chat transcript renderer has. Add KaTeX math rendering (inline $...$ and block $$...$$), table, image, and link support so file previews match the chat rendering.
2026-08-18 13:18:41 -07:00
Teknium de213b5210 chore: add contributor email mappings for vadelma-agent and tmielika
Maps vadelma@agenttiklubi.org and the bare noreply address to
vadelma-agent, and taneli.mielikainen@iki.fi to tmielika, so the
check-attribution gate passes on their open PRs (#70667, #72671,
#67934, #86255, #89194).
2026-08-18 12:38:10 -07:00
Teknium 9d8ae051dc chore: map lazy-idler contributor email 2026-08-18 12:37:38 -07:00
Teknium ef5bec0e14 chore: map contributor citizendev9c 2026-08-18 12:22:44 -07:00
Teknium e624e9fde5 chore: map contributor email for #88864 salvage 2026-08-18 00:26:31 -07:00
Teknium d4a72b7d7e chore: map contributor email for #88807 salvage 2026-08-18 00:03:16 -07:00
imMxts 7e156c6d2e fix(desktop): preserve primary remote connection identity 2026-08-17 23:52:54 -07:00
Teknium 9aa1413781 feat(desktop): extend kanban native notifications to blocker/failure events
Builds on @nductien's completion-notify module (PR #87705):

- Notify on the gateway watcher's full terminal set — blocked, gave_up,
  crashed, timed_out, block_loop_detected — not just completed. A worker
  hitting a blocker while the user is away was the original community ask.
- Route all notification copy through the kanban plugin i18n bundles
  (en/ja/zh/zh-hant), with an English-bundle fallback when the translator
  isn't bound yet.
- Wire the ctx.os.notify door so events also fire a NATIVE OS notification
  while the user is away from the Hermes window (host.notify toast covers
  the foreground). OS-door failures are isolated from the toast path.
- Docs: Desktop notifications section in kanban.md, including the
  app-running coverage window.
2026-08-17 17:00:00 -07:00
Teknium 54b0a5bc46 chore: map contributor emails for @loafoe and @k0rnacki 2026-08-17 16:54:01 -07:00
Teknium 10134bd846 chore: map contributor email 2026-08-17 16:34:02 -07:00
adybag14-cyber 9e81a102df chore: map contributor email 2026-08-17 15:47:17 -07:00
Teknium e3c954447c chore: map contributor email for @AL-ZiLLA 2026-08-17 14:32:52 -07:00
Teknium 9ed4a7c025 chore: map contributor email for laviesony 2026-08-17 12:58:51 -07:00
Teknium 5de09f7b0c chore: map contributor email for intellectronica 2026-08-17 12:57:09 -07:00
Teknium b919dc7db8 chore: map contributor email for @negroni334 2026-08-17 11:29:47 -07:00
Teknium 0ea430ab84 chore: map contributor email for @29206394 2026-08-17 10:02:32 -07:00
kshitij 0c3452bf75 Merge pull request #88327 from kshitijk4poor/chore/author-map-kstawiski
chore: add kstawiski to AUTHOR_MAP
2026-08-17 17:18:38 +05:30
kshitij 458f3bfac5 chore: add kstawiski to AUTHOR_MAP
Salvage of PR #73877 (cron: warn agent when scheduler is unavailable)
maps contributor email konrad.stawiski@umed.lodz.pl to GitHub login kstawiski.
2026-08-17 15:41:29 +05:30
Teknium 780ede4d17 chore: map contributor email for PYTHONHOME/junction salvage (Starfie1d1272) 2026-08-17 02:10:32 -07:00
Teknium 7a2ad9ae55 chore: map contributor emails for PYTHONPATH salvage (Yiipu, mmchuangyt-ai) 2026-08-16 23:26:04 -07:00
Teknium de29f46bab chore: map contributor emails for salvage of #85421 2026-08-16 22:20:35 -07:00
Teknium bbe9175577 chore: normalize contributors/emails/razsoc.01@gmail.com to LF line endings 2026-08-16 21:56:30 -07:00
Aleksei Razsadin 89bf7f182e chore: map razsoc.01@gmail.com contributor email to Cossackx
Fixes the check-attribution CI failure on PR #88051.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 21:56:30 -07:00
Teknium 55db6187e5 chore(contributors): map skip-agent's commit email for attribution 2026-08-16 21:17:47 -07:00
Teknium 2bef9e8f51 chore: map contributor email for tigercraft4 (PR #74468 salvage) 2026-08-16 19:58:49 -07:00
Teknium b82b94811a chore: map contributor email for attribution audit 2026-08-16 19:28:56 -07:00
Teknium d0d605ad0a chore: add contributor email mapping for addelh 2026-08-16 16:26:50 -07:00
Teknium 2c51abe8e1 chore: map contributor email for xkam7ar 2026-08-16 10:59:19 -07:00
Teknium ddc51ec109 fix(update): reload process-scan modules at the dashboard-cleanup entry point
Widen PR #87757 to cover the ZIP path: _update_via_zip() also calls
_finish_dashboard_update_cleanup() but never runs _reload_config_modules,
so the Windows git-broken fallback would still crash with the same
ImportError (cannot import name 'bounded_probe_run' from the stale cached
hermes_cli._subprocess_compat).

- new _reload_process_scan_modules() called inside
  _finish_dashboard_update_cleanup itself, so every current and future
  call site is covered; reloads dependency-first
  (_subprocess_compat, then dashboard_procs)
- reload failures log at warning (a miss surfaces seconds later as an
  ImportError in the same process)
- regression tests: reload-before-kill ordering, node-failure skip,
  stale-module symbol restoration (the exact #87134 boundary state),
  nonfatal reload failure, and the #87757 reload-list contract
2026-08-16 10:31:24 -07:00
Teknium de254c48fb chore: map contributor email for @yflmq001 2026-08-16 06:31:26 -07:00
Teknium 6ce7922af1 chore: map contributor email for focused-session atoms salvage 2026-08-16 03:15:27 -07:00
Cary Palmer be38224b49 fix(desktop): lint and map contributor email for running-is-not-busy
Drop the redundant Boolean() on selected in $primaryBusy and add the
professorpalmer9@gmail.com mapping so attribution CI can resolve the PR.
2026-08-16 03:01:45 -07:00
Teknium f325008ebf chore(contributors): map emails for P2-sweep salvage wave 2026-08-16 02:13:05 -07:00
kshitij 2cd5393af7 chore: map justin@bowes.org to @justinbowes
Attribution mapping for the PR #84982 salvage. The commit email is not
linked to a public GitHub account, so contributor_audit --strict fails
without it; login confirmed from the PR author field.
2026-08-16 13:10:40 +05:30
Teknium 128fb74d98 chore: map contributor email for 5Hyeons 2026-08-15 23:37:15 -07:00
Teknium 411903b6fa chore: contributor mapping for NikolaRHristov 2026-08-15 23:03:52 -07:00
Teknium 951ae62ffc test(computer-use): pin 0.17+ split refs/content_refs merge behavior
Regression test for the _ref_map merge (salvaged from #79515): the live
0.19.3 driver splits action refs into refs[] while content_refs re-lists
every node with empty actions; the empty entries must not clobber the
action-bearing ones. Caught live: every typed click refused with
browser_ref_stale until the merge fix.
2026-08-15 15:36:19 -07:00
Teknium 9859e8852f chore: map 807847218@qq.com -> Tommy00748 for attribution audit 2026-08-15 13:31:35 -07:00
Teknium 07161e1da4 chore: map contributor email for @RGerrish 2026-08-15 04:33:47 -07:00
LordMelkor 6efab28726 feat(auth): add key_cmd credential source for custom providers
Custom providers could only authenticate from a static credential (inline
api_key or a key_env env var). Enterprise gateways -- SSO/OIDC brokers, cloud
IAM, internal auth proxies -- issue short-lived bearers instead, so a value
copied into .env is stale within the hour: long sessions start returning 401s
and the user has to restart or run an external cron that rewrites .env.

The existing `secrets.command` source does not cover this: it runs once per
process at startup (subsequent calls are no-ops by design), so it cannot
re-mint a credential mid-session.

Add providers.<name>.key_cmd: a command that prints a token, wrapped at
resolution in a zero-argument callable. Both wire clients already accept a
callable api_key and invoke it per request (the Entra ID path established
this), so chat_completions, codex_responses and anthropic_messages all work
unchanged and always send a fresh credential. The callable also routes the
Anthropic client through its per-request Authorization hook, which is what
OAuth-gated gateway routes require -- so no per-vendor auth wiring is needed
anywhere in core.

- cached until shortly before the advertised expiry (60s leeway), so the
  helper runs about once per token lifetime rather than once per request
- expiry is read from the OAuth 2.0 relative `expires_in` when present, and
  otherwise from an absolute ISO 8601 deadline (`expiry`, `expiresOn`), which
  is what CLI token helpers commonly print. Reading only `expires_in` treated
  those helpers as advertising no TTL at all, cached their token for the life
  of the process, and returned 401 on every request once the real deadline
  passed. ISO parsing reuses hermes_cli.auth._parse_iso_timestamp rather than
  adding another datetime parser.
- no synthetic expiry: when no TTL is advertised, or the advertised one is
  unparseable or already past, the token is used and refreshed on 401 instead
  of re-minted on an invented schedule
- stdout contract matches OAuth 2.0 token endpoints and existing agent
  helpers (bare token or JSON access_token/expires_in); multi-line output is
  rejected rather than guessed at, so a misconfigured helper surfaces as a
  clear error instead of a corrupt-credential 401
- precedence: explicit --api-key still wins; otherwise key_cmd beats a
  static api_key/key_env on the same entry
- failures never include the helper's output (may hold a partial token) or
  the command string (may embed a client secret)

Resolution happens on two paths. agent/auxiliary_client.py resolves named
custom providers itself rather than calling _resolve_named_custom_runtime, so
key_cmd is honoured in both: wiring only the runtime resolver leaves the main
agent turn working while every auxiliary call (title generation, compression,
vision, embedding) falls back to the no-key-required placeholder and 401s.
Precedence is identical on both paths, so one config entry cannot yield two
different credentials depending on which resolver the caller reached.

Closes #84162

Signed-off-by: LordMelkor <kray@block.xyz>
2026-08-15 03:16:21 -07:00
Teknium 26aa12337a feat: /save exports the current session as json, md, or html on all platforms
Rework of salvaged PR #6372 (@ag9920) onto current main:

- /save promoted from CLI-only JSON snapshot to a cross-platform session
  export: `/save [json|md|html] [filename] [redact]` on CLI and every
  gateway platform (sent as a document via adapter.send_document).
- Rendering routes through the existing shared renderers
  (hermes_cli/session_export.py + session_export_html.py) instead of the
  PR's new hermes_state formatter — new helpers normalize_save_format /
  render_session_for_save / default_save_filename are shared by both
  surfaces.
- `redact` arg runs the export through the force-mode secret redaction
  pass (session_export_md.redact_session_data) before writing.
- Gateway handler awaits AsyncSessionDB correctly, sanitizes user-supplied
  filenames with basename, and lands in gateway/slash_commands.py (the
  handlers moved out of gateway/run.py since the PR was authored).
- /export stays profile export (name collision resolved: session export
  lives on /save).
- Slack 50-slash cap curation: /platform moves to the /hermes-only set to
  free a native slot for /save (parity test updated rationale comment).
- Folds in PR #62268 (@briandevans): None title/model coalescing in the
  single-session HTML export.

Closes #4249. Closes #51200.
2026-08-15 02:04:49 -07:00
Teknium 467ec9208a chore: map content@tyfpro.com -> tyfcontent for #85181 salvage 2026-08-15 02:04:10 -07:00
Teknium e1dd43bf7b chore: map contributor emails 2026-08-15 01:21:40 -07:00