Commit Graph

635 Commits

Author SHA1 Message Date
Brian Le
32a59f3bf7 feat: refresh one pooled OAuth grant from the CLI 2026-09-07 08:06:48 -07:00
Brian Le
1a4bb74a40 feat: choose pooled credential priority from the CLI 2026-09-07 08:06:48 -07:00
Brian Le
53221df05f feat: reset one pooled credential without clearing sibling cooldowns 2026-09-07 08:06:48 -07:00
Teknium
34e512ae58 fix(sessions): remove remaining timer migration and guidance 2026-09-07 06:10:54 -07:00
Teknium
1481a0de96 docs(gateway): describe persistent sessions without reset timers 2026-09-07 06:10:54 -07:00
Teknium
245e48008f fix: listing surfaces show the merged view for MCP servers named like built-in toolsets
get_all_toolsets() copied static TOOLSETS entries verbatim, so /toolsets and the
dashboard showed only the built-in tools for a colliding name even though
get_toolset() now unions the MCP alias in. Route those names through
get_toolset() and document the alias/collision behaviour.
2026-09-05 17:00:18 -07:00
Teknium
4dc9988f78 feat(skills): reddit-reading and rss-feeds bundled skills, multi-platform sweep guidance
Two zero-install research skills plus routing guidance, ported as ideas
(not code) from the Agent Reach skill's per-platform backend routing.

reddit-reading (skills/social-media): subreddit listings, site/subreddit
search, threads with comments, user pages. Live-verified from a datacentre
IP: www .json, api.reddit.com, old.reddit, r.jina.ai and the browser tool
all return 403 / an empty shell / a humanity check; the Atom .rss endpoints
are the only anonymous path and are throttled to ~1 request/min/IP. The
script waits out the x-ratelimit-reset window once and retries, and
switches to the OAuth API (scores, nested comments, ~100 req/min) when
REDDIT_CLIENT_ID/SECRET are present. `doctor` reports the active backend.

rss-feeds (skills/research): RSS 2.0 / RSS 1.0 / Atom / JSON Feed parsing
with UTC-normalised dates, --since/--limit, and feed discovery behind a
page URL (<link rel=alternate>, then well-known paths). Stdlib only; the
optional blogwatcher skill remains the stateful many-feed reader and now
points at this one for one-off reads.

grounded-citations gains a "Multi-Platform Sweeps" section routing
"what are people saying about X" tasks across web, Reddit, feeds, video,
code and X with per-platform attribution and coverage-gap reporting;
competitor-news-monitor references the new sources.

Tests: two invariant tests per skill (format normalisation + discovery;
anonymous 429 handling + OAuth routing/flattening), no network. The
reddit test caught a real bug: the feed footer's "/u/author" leaked into
post bodies.
2026-09-05 14:01:34 -07:00
Teknium
f1ccf436a2 feat(web): Perplexity Search API as a web_search + web_extract backend
Adds plugins/web/perplexity — a keyed-only WebSearchProvider over httpx:

- search: POST https://api.perplexity.ai/search (documented Search API),
  search_context_size=low so `snippet` stays description-sized;
  results[].snippet -> description, max_results capped at the API's 20.
- extract: POST /sdk/content/snippets — the query-relevant page-excerpt
  route behind `pplx content snippets` (the CLI's `content fetch` is
  deprecated upstream). web_extract has no query, so the URLs' path words
  serve as the relevance query; per-URL `error` entries survive a 200.
- Wired into the same touchpoints as the other keyed vendors: legacy
  backend set + credential ladder + availability probe (web_tools),
  registry preference walk, OPTIONAL_ENV_VARS, `hermes config`/status/
  dump key lists, nous_subscription direct-credential detection, setup
  summary, test conftests, docs.

Not a keyless-ring member (Perplexity has no anonymous tier). Related
closed PRs #9192 / #23981 / #45225 predate the plugin ABC.
2026-09-04 07:17:00 -07:00
joaomarcos
d47fe28fc5 fix(backup): import SQLite databases without replacing the live inode
`hermes import` published every zip member, including `state.db`, with
`_extract_member_atomically` — a rename that swaps the file's inode. Any
gateway, dashboard, or WebUI process holding the database open keeps its
descriptor on the now-unlinked inode: it goes on serving pre-import pages
and writing sessions no other process can see, while the sidecar WAL left
beside the new file describes the database that was just unlinked. Nothing
raises, so the import prints "Import complete" and the sessions are simply
absent from the database everyone opens next.

The live-safe path already exists: `/snapshot restore` has routed `.db`
files through `_safe_restore_db()` since #65942, writing snapshot pages
into the existing file so every open connection converges. `hermes import`
— the disaster-recovery path, reached by users who already lost something
once — never got that treatment.

Route `.db` members through it. A target that does not exist yet has no
holders and no inode worth preserving, so it keeps the ordinary atomic
publish. A refused or failed live-safe restore now raises, so the import
reports a skipped file instead of counting a silent success, and the
existing database is left untouched.

Importing an older backup over newer work stays allowed but no longer
silent: the summary reports the session/message counts the import replaced,
the same before/after evidence `restore_cron_jobs_if_emptied` uses for
`cron/jobs.json`.

Closes #100960

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ShTVU941HYygvypY9JMYE
(cherry picked from commit 8ff260a312341cb85bdf7cdd570de5ff888c6013)
2026-09-03 11:30:30 +05:30
Teknium
8e4366d358 fix(tools): freeze tools[] across agent-cache eviction; make /reload-mcp the re-probe hatch
Policy: availability-gated tools (check_fn probes — Docker, HASS_TOKEN,
OAuth…) are frozen for the life of a session. tools[] only changes on
/new, /reload-mcp, or compaction. Two doors remained after #100638:

* Gateway agent-cache eviction (LRU/idle sweep/cross-process invalidation)
  rebuilds a fresh AIAgent for the SAME session and agent_init re-derives
  agent.tools from live probes with no predecessor to preserve. Persist
  the session's resolved tool-name order in a new `sessions.tool_names`
  JSON column (declarative reconciliation, SCHEMA_VERSION 28), written
  alongside the system prompt and re-pinned on every published refresh
  (so /reload-mcp and compaction naturally reset it; /new mints a new
  row). On restore-for-existing-session the fresh definitions are folded
  onto the saved order via the SAME `_merge_preserving_prefix` helper —
  a probe-flipped tool is carried forward from the registry schema, a
  deregistered one dropped, new tools appended at the tail.

* /reload-mcp (CLI, gateway, TUI RPC) now also calls
  `reprobe_tool_availability()` — drops the check_fn verdict cache and the
  get_tool_definitions memo — so a user can consciously pick up a
  credential/daemon that appeared mid-session. Docs updated.
2026-09-02 07:22:59 -07:00
Teknium
c2954c8934 feat(model-catalog): picker catalogs refresh every 20 minutes, gateway keeps them warm
The /model picker's remote catalogs (curated manifest, OpenRouter live
filter, Nous Portal recommendations) only refreshed when someone opened
the picker on a stale cache, with a 1h TTL. A delisted model (tencent/hy3:free
after the free promo ended) or a newly published one could sit stale for
an hour after the manifest deploy, and indefinitely in a gateway nobody
opened /model in.

- model_catalog.ttl_minutes: 20 replaces ttl_hours: 1 as the default;
  an explicitly set legacy ttl_hours is still honoured.
- model_catalog.refresh_catalogs() force-refreshes all three sources to
  disk; refresh_interval_seconds() exposes the cadence.
- Gateway spawns a supervised _model_catalog_refresh_watcher that calls
  it off-thread every TTL window, so every surface on the machine reads
  a cache no older than 20 minutes.
- Config migration v39→v40 drops the old ttl_hours: 1 default only.
- Docs: reference/model-catalog.md updated.
2026-09-02 06:16: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
c7e2e0b779 feat(fast): bounded /fast auto|cold windows behind one route-aware gate
Adds two bounded fast modes on top of the static /fast toggle, default OFF:

- `auto`: every user turn opens a `agent.fast_auto_seconds` (default 60s)
  window; requests inside it carry the provider fast param, later tool-loop
  requests fall back to standard pricing.
- `cold`: the same window, but only on the first turn of a session (no prior
  user/assistant/tool history).

agent/fast_mode.py holds the whole policy: `begin_turn()` at the
run_conversation ingress arms `agent._fast_until`; `effective_request_overrides()`
is consumed in the ONE place request_overrides feed the transports
(build_api_kwargs), so the fast param is a per-request kwarg only. System
prompt, tools and messages are untouched — the prompt cache is preserved.

resolve_fast_mode_overrides() is now the single gate for static and bounded
modes and accepts provider/base_url: OpenRouter, Nous, Copilot, Azure,
Bedrock and custom base_urls never receive service_tier/speed (#34308's
route gating). Both existing callers (CLI turn route, gateway turn route)
and the TUI config.set path pass the route.

Surfaces: config `agent.service_tier: auto|cold` + `agent.fast_auto_seconds`,
`/fast auto|cold` in CLI, gateway (picker gains both entries), TUI/desktop
config.set; status shows the mode; web dashboard select lists the real
values. Docs: configuration.md Fast Mode section with mode table + cost note,
slash-commands, cli-config.yaml.example, locale strings for the two picker
entries.

Salvages #89991 (bounded fast modes) and #34308 (route gating).
Fixes #64785, #74730.

Co-authored-by: Eva <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: kbaicai <kbaicai@qq.com>
2026-09-02 05:33:13 -07:00
Teknium
44a57921c5 fix(providers): hide phantom -cn picker rows lit only by shared intl keys; give alibaba-token-plan-cn its own key var
- alibaba-coding-plan-cn / alibaba-token-plan-cn keep the shared intl key vars
  as ordered fallbacks after their dedicated *_CN_API_KEY, so users who set
  ALIBABA_CODING_PLAN_API_KEY / ALIBABA_TOKEN_PLAN_API_KEY for the CN endpoint
  keep working (the PR as filed dropped them).
- list_authenticated_providers hides a '-cn' row whose only lit key vars are
  ones it shares with its non-CN sibling, unless that CN provider is the
  configured model.provider. With only the shared key: one row, not two;
  DASHSCOPE_API_KEY alone: 3 alibaba rows, not 4.
- Docs: environment-variables.md, providers.md.
2026-09-02 05:32:20 -07:00
Teknium
5fae0d243f docs(faq): explain fail-closed overflow recovery on silently-truncating local servers 2026-09-01 21:36:09 -07:00
joaomarcos
4c870951e2 fix(cli): resolve startup model routes before provider defaults
Resolve configured aliases and provider/model inputs before HermesCLI attaches the configured default provider. Keep aggregator namespaces intact, cover oneshot startup, and document the supported CLI forms.
2026-09-01 12:07:35 -07:00
Lakshya Agarwal
428e084dcd feat(web): add Tavily web search and extract provider
This commit re-introduces the Tavily provider, which supports both search and content extraction capabilities, which was removed in #99199.
2026-09-01 10:56:49 -07:00
Brooklyn Nicholson
b293157f7d feat(tools): withdraw tip and tour when the user switches them off
Off should mean the model is never told the tool exists. A switch that
only made the call fail leaves Hermes offering walkthroughs it cannot
give and promising to point at things it cannot point at, which reads as
a broken agent rather than a respected preference.

Both gate on the switch through a shared desktop_ui.user_enabled helper,
which is the reactions check_fn generalized — same config read, same
reason it has to be config rather than an env var: the switch belongs to
the session's client, and the client may be on another machine.
2026-08-31 21:11:11 -05:00
Teknium
d95682cd04 fix(gateway): announce declined 'all' scope in /sessions and /resume listings
A non-admin '/sessions all' or '/resume --all' silently downgraded to
chat-scoped listing with zero feedback, which reads as 'my session
vanished' (community Telegram report). Both surfaces now append a notice
that cross-chat listing requires a configured admin. Follows up the
salvaged current-session '(current)' marker (PR #68556, fixes #68547):
sibling tests updated to pin the new contract, new i18n key
gateway.resume.all_requires_admin added to all 17 locales, docs updated.
2026-08-31 14:40:09 -07:00
Teknium
a42aee9585 fix(config): greedy literal-key matching + loud phantom-sibling refusal for dotted key names
Builds on webtecnica's escape-aware _split_key_path (#84152, cherry-picked
with authorship preserved; earliest fix in the family was RelaxJonh's #80253
greedy-match approach — both behaviors now ship together):

- _greedy_literal_match: when navigating an EXISTING mapping, prefer an
  existing literal key equal to the dot-join of the next N path segments
  (longest match wins). Dotted model IDs are the norm, so the common
  unescaped command (config set providers.p.models.grok-4.6.supports_vision
  true) now hits the real key across set/get/unset instead of creating a
  phantom sibling. Plain dotted paths with no dotted-key collision split
  exactly as before.
- _phantom_sibling + ValueError in _set_nested: refuse to CREATE a new
  intermediate mapping that would shadow an existing dotted literal sibling
  (Soju06's fail-loudly suggestion on #84064); set_config_value surfaces it
  as a clean CLI error with the escaped spelling to use.
- utils.py::atomic_roundtrip_yaml_update (the second split site, #91607 —
  /model + TUI persistence) now uses the same escape-aware split + greedy
  literal matching.
- CFG-04 empty-segment guard now splits escape-aware so escaped keys are
  not misclassified.
- Tests for every repro shape in the family: #84064 provider model keys,
  #80006 Matrix room IDs, #91095 dotted models under custom_providers list
  index (incl. escaped creation-when-absent), #91607 model_overrides via
  atomic_roundtrip_yaml_update, #99124 dotted leaf keys; plus
  backward-compat coverage. Also fixed the carrier's one stale assertion
  (structured-value coercion landed on main after #84152 branched) and
  removed its dead _MCP_SECRETS_CONFIG fixture flagged in review.
- Docs: 'Dots inside key names' section in website/docs/reference/cli-commands.md.

Fixes #84064, fixes #80006, fixes #91095, fixes #91607, fixes #99124
2026-08-31 12:18:47 -07:00
RickyYii
3145986c20 fix(cli): honour model_aliases api_key, stop cross-provider key leak (#83612)
Salvaged from PR #84199 by @RickyYii. DirectAlias gains api_key/key_env; the direct-alias override re-resolves credentials against the alias endpoint (host-gated, #28660) and reuses the pre-alias key only on an origin match; oneshot -m <alias> passes the alias key as explicit_api_key; direct-alias branch gains the OLLAMA_API_KEY host gate. Fixes #83612.
2026-08-31 10:59:45 -07:00
Teknium
f2f7a3bf15 feat(cron): doctor flags overdue next_run_at as silent non-firing
Widens the salvaged cron doctor with the highest-value fleet check:
an active job whose next_run_at is parked >15min in the past is not
firing (dead ticker, downed gateway, wedged fire-claim). Also registers
doctor in the docs (cron guide + CLI reference) and resolves the salvage
onto current main alongside runs/incidents/notepad.
2026-08-31 10:00:29 -07:00
Adrià Arrufat
8bdf8836e6 docs(browser): document Lightpanda in Browser Use mode and the engine precedence rules 2026-08-31 21:59:11 +05:30
David Dudok de Wit
e7433910e9 feat(bot-mode): add scoped cross-gateway Group Chat transport 2026-08-31 01:04:11 -07:00
Teknium
d6773cf26f refactor: remove the Tavily web backend; keyless ring is exa/parallel/firecrawl/keenable
- Tavily plugin deleted (plugins/web/tavily), keyless endpoints and
  ring entry removed from keyless_mcp, legacy backend set / credential
  ladder / preference walks / rescue key map scrubbed.
- TAVILY_API_KEY deregistered across config, setup, status, dump, and
  nous_subscription surfaces. The tvly- redaction pattern stays --
  legacy keys in user envs still deserve masking.
- Sibling test pins migrated (keenable/exa stand in where tavily was
  the fixture vendor); tavily test suite deleted.
- Docs updated: web-search, configuration, integrations,
  environment-variables, tools-reference, web-dashboard, provider
  plugin dev guide.

Live-verified from an isolated HERMES_HOME with all web creds blanked:
zero-config resolution lands in the 4-vendor ring, live keyless ring
search succeeds, no tavily anywhere in resolution order.
2026-08-31 00:56:41 -07:00
Teknium
d63f996a75 feat(photon): read-receipt toggle, receipt-type alias, docs
Follow-ups on top of #98964's cherry-pick:
- PHOTON_READ_RECEIPTS env toggle (default true) so users can keep
  messages at Delivered; declared in plugin.yaml optional_env
- adapter drops both 'read' and 'read_receipt' content types (alias
  coverage from #91759 by @mooserini) + regression test
- docs: photon.md feature note + environment-variables.md row
2026-08-30 18:37:50 -07:00
Teknium
c49fa88b80 refactor(skills): shipped-set slim — 15 to optional, github 6-way merge, pdf absorbs OCR, channel-gated teams pipeline (index −26%) (#98539)
* refactor(skills): shipped-set slim — 15 skills to optional, github six-way merge, pdf absorbs OCR+nano-pdf, channel-gated teams pipeline

Maintainer-directed shipped-skills curation (skills index 1,900 -> ~1,400
tok/call on desktop; every session pays the index, so this is a per-call
diet on all installs):

- optional-skills moves (installable via skills hub, history preserved):
  creative comfyui/ascii-art/excalidraw/pretext/sketch/touchdesigner-mcp;
  ALL of mlops (huggingface-hub, llama-cpp, serving-llms-vllm,
  weights-and-biases, evaluating-llms-harness — subcategory structure
  kept); research-paper-writing (55 supporting files, 17.3K-tok load);
  openhue; blogwatcher (first taught the cronjob monitor-field watch
  pattern + web_extract instead of pre-cron manual workflows)
- DELETED session-librarian (Aug-12 'inspired by Perplexity Computer'
  port, never maintainer-intended; session_search covers discovery)
- github: six skills (auth, issues, pr-workflow, issue-to-pr,
  code-review, repo-management) merged into ONE software-development/
  github skill — routing body + complete per-workflow references;
  benbarclay authorship credited; codebase-inspection rides along;
  discipline pins from test_github_issue_to_pr_skill.py preserved
  against the reference body in the new test_github_skill.py
- pdf absorbs ocr-and-documents + nano-pdf as references/ + scripts
  (extract_pymupdf, extract_marker converted to the argparse house
  standard its contract test enforces)
- NEW session_platforms frontmatter gate (metadata.hermes): hides a
  skill from the index on gateway channels it is not for; fail-open on
  unknown platform; teams-meeting-pipeline gated to [teams, cron]
- blocked-page-recovery: research -> new web category; trigger-first
  description ('Use when a fetch fails: 403/429, paywall, WAF, bot
  wall.') so the model actually reaches for it on blocked fetches
- docs regenerated via generate-skill-docs.py (195 pages); related_skills
  swept repo-wide; tests: 1672 passed (2 openclaw failures pre-existing
  on clean main, Windows-local)

* chore: ignore .skills_prompt_snapshot.json (local index cache, accidentally committed)
2026-08-30 04:53:39 -07:00
Teknium
4345cd5b11 fix(skills): impeccable catalog stub meets authoring standards
platforms field added, description under the 60-char hardline, dangling
premium-webapp-ui related_skills ref dropped (user-profile skill, not in
the repo tree). Docs page + catalog row regenerated to match.
2026-08-29 19:15:32 -07:00
Teknium
45d9c33d85 feat(skills-hub): impeccable joins the optional-skills catalog, content pulled live from upstream
hermes skills install impeccable (and the docs-page install button) now
installs the impeccable frontend-design skill as an official optional-skills
entry. The local optional-skills/creative/impeccable/ dir is a catalog STUB:
its frontmatter declares metadata.hermes.upstream (repo + path), and
OptionalSkillSource.fetch() pulls the real 163-file bundle live from
pbakaus/impeccable:.hermes/skills/impeccable — the Hermes-native bundle
upstream maintains and verifies. Nothing vendored, never stale.

New mechanism (generic, not impeccable-specific):
- OptionalSkillSource._upstream_pointer(): parses/validates the upstream
  pointer (owner/name repo, clean relative path, traversal rejected).
- _fetch_from_upstream(): delegates to GitHubSource.fetch(), relabels the
  bundle official/<rel> at trust 'trusted' (curated endorsement, but
  third-party content — dangerous scan verdicts still block).
- The live-repo fallback path redirects stubs the same way, so stale local
  checkouts behave identically.

Three real gaps this surfaced, all fixed:
- GitHubSource.fetch() only downloaded SKILL.md plus paths linked from a
  canonical support dir (references/, scripts/, ...). Impeccable keeps its
  playbooks under reference/ (singular) and links scripts only from
  reference files, so fetch shipped 1 of 163 files. fetch() now downloads
  the full skill directory via the git tree (same approach as the
  optional-skills live fetch), still rejecting symlinks/hidden/unsafe paths
  and still failing on a missing SKILL.md-linked references/ path.
- The five env_exfil_* scanner patterns flagged loopback requests as
  critical exfiltration: impeccable's live mode polls
  http://localhost:PORT/status?token=TOKEN and scored two CRITICALs.
  Scheme-anchored loopback exemption added; evil.com/?u=localhost decoys
  still fire (10-case regex matrix in tests).
- unified_search() truncated to limit before ranking, so official catalog
  entries got crowded out by skills.sh mirrors and bare-name installs
  stalled on an ambiguity table. Results now stable-sort by trust rank
  before the cut, and _resolve_short_name prefers a sole official exact
  match over community mirrors.

Also fixes pre-existing test pollution: TestInstallPathSafety's fixture
monkeypatched the PEP 562 dynamic SKILLS_DIR, permanently shadowing dynamic
resolution and breaking the served_repo E2E tests in any combined run
(reproducible on main).

Validation: live E2E do_install("impeccable") against real GitHub —
resolves to official/creative/impeccable, verdict SAFE, 163 files on disk,
skill loads, /impeccable slash command registers. 128/128 targeted tests;
full-dir fetch test sabotage-verified. Docs: optional-skills catalog row,
generated skill page, sidebar.
2026-08-29 19:15:32 -07:00
Teknium
0f3fcacd3f feat: /plan graduates from bundled skill to built-in command on every surface
The bundled plan skill's auto-generated slash command fell off the capped
Telegram/Discord command menus for most installs (skills are the only tier
trimmed at the platform caps, alphabetically — 'plan' sat past the cutoff at
index 57 of 82 bundled skills). Converting it to a first-class CommandDef
gives it a guaranteed core-tier menu slot on every platform.

- agent/plan_prompt.py: build_plan_prompt() — plan-mode rules + authoring
  craft distilled from the retired skill; prompt-injection pattern like
  /learn and /init (no engine, no model-tool footprint, cache-safe).
- CLI: _handle_plan_command mixin handler (pending-input injection).
- Gateway: /plan branch rewrites event.text and falls through (role
  alternation preserved).
- TUI: command.dispatch branch ('plan' was already in
  _PENDING_INPUT_COMMANDS).
- Removed skills/software-development/plan/ + docs pages (EN + zh-Hans),
  catalog rows, sidebar entry, related_skills references.
- PROTECTED_BUILTIN_SKILLS is now empty (mechanism kept); dependent
  curator/usage tests moved to monkeypatched sentinels.

Salvages #67292 by @webtecnica (credit: first /plan command submission,
issue #67264); reworked from inline planning prompt to the prompt-injection
pattern with workspace-saved plans. Closes #67264, closes #36821 (empty
/plan infers task from conversation context).
2026-08-29 19:14:15 -07:00
Hermes
56a5eb09ef docs(computer-use): drop remaining existing-profile grant references
The grant_existing_profile key was removed in PR #98057; sweep the mode
table, opt-in section, runtime-lifecycle notes, config example, and CLI
reference that still documented it.
2026-08-29 19:13:33 -07:00
Ayush Nangia
94aad6dcd2 fix(providers): surface Alibaba China in desktop parity 2026-08-29 18:01:25 -07:00
Ayush Nangia
695d86f518 fix(providers): fold Token Plan into the alibaba plugin, add runtime-path regressions, document all variants
Sweeper review, all three points:

- Placement: no new plugins/model-providers/ directory. The Token Plan
  profiles register from the existing alibaba plugin module — one module
  per vendor, matching how the kimi module carries both of its endpoint
  variants. Token Plan is the same vendor/service (Model Studio), same
  OpenAI-compatible protocol, its own key + endpoints; splitting to a
  standalone repo remains a 5-minute change if maintainers prefer.
- Runtime coverage: TestRuntimeAlibabaRegionalAndTokenPlan exercises
  resolve_runtime_provider() for all four variants — provider, api_key,
  api_mode, base_url — alongside the existing zai/minimax/kilocode
  runtime regressions.
- Docs: providers.md, environment-variables.md, cli-commands.md updated
  with the bundled variants and their env keys/base-url overrides.
2026-08-29 18:01:25 -07:00
kshitijk4poor
360761c8cf docs: surface Tencent TokenPlan + hy4-preview across provider docs
Follow-up for salvaged PR #96939 (docs completeness audit): setup
table, quick commands (TokenHub example refreshed to hy4-preview),
fallback tables, env-var reference, quickstart, --provider choices,
and .env.example (TokenHub block was missing there too).
2026-08-29 20:51:17 +05:30
kshitijk4poor
a8e11d21c0 docs: surface Nebius Token Factory across user-facing provider docs
Follow-up for salvaged PR #28253 (docs completeness audit): setup
table, quick command, fallback tables, env-var reference, quickstart,
--provider choices, and .env.example.
2026-08-29 20:39:44 +05:30
kshitijk4poor
fbef1ca805 docs: surface Ramp Router across user-facing provider docs
Follow-up for salvaged PR #93548 (docs completeness audit):
- integrations/providers.md: setup table row, quick command example,
  fallback supported-providers list
- reference/environment-variables.md: RAMP_ROUTER_API_KEY / _BASE_URL
- reference/cli-commands.md: --provider choices
- getting-started/quickstart.md: provider table
- user-guide/features/fallback-providers.md: fallback table
- .env.example: commented key block
2026-08-29 20:29:04 +05:30
Samuel Odio
8c23824609 docs: align busy command references 2026-08-29 20:03:48 +05:30
Samuel Odio
597d2230ea refactor(gateway): share plain command dispatch 2026-08-29 20:03:48 +05:30
Teknium
74a95a3ddf feat: /btw now answers side questions with conversation context; /background renamed to /bg
/bg (formerly /background, which is retired) keeps the existing semantics:
spawn a fresh, independent agent session in the background.

/btw is now its own command matching the convention other harnesses use:
ask a quick side question ABOUT the current conversation without
interrupting it. A one-shot auxiliary LLM call (main model by default,
overridable via auxiliary.side_question.* in config.yaml) answers from a
read-only transcript snapshot — the live session's history, role
alternation, and prompt cache are untouched, and the current turn keeps
running.

Surfaces wired: CLI (inline mid-run dispatch), gateway (all messengers,
busy-dispatch table + idle dispatch, i18n across all 17 locales), TUI
(prompt.btw RPC + btw.complete event), Discord native slash, relay
command manifest, desktop exec routing, docs (EN + zh-Hans).
2026-08-29 07:25:17 -07:00
Teknium
b6bd681e89 feat(todo): nested subtasks via optional parent field
The todo tool now supports hierarchical task lists: an item's optional
'parent' field points at another item's id, making it a subtask.

- tools/todo_tool.py: parent validated (self-ref dropped), dangling refs
  and cycles sanitized; merge mode can set/clear parent; post-compression
  injection renders the tree indented and keeps a finished parent visible
  while any descendant is still active; the in-progress reorder pass is
  skipped for nested lists (a flat move would tear subtasks from parents).
- Schema cost: ~45 tokens added to the cached tool schema (one string
  property + one behavior sentence).
- acp_adapter/tools.py: todo result markdown indents by parent depth.
- Desktop: TodoItem carries parent; todoTree() DFS helper; composer
  status stack renders subtask rows indented (depth-capped), stabilizer
  compares depth.
- Docs: tools-reference todo entry mentions nesting.

Hydration/replay paths (gateway fresh-agent, API-server history) work
unchanged: parent rides inside the same todos array.
2026-08-29 07:25:12 -07:00
Teknium
2c232761e4 fix(skills): restore grill-me name, keep frontier-rounds upgrade
Reverts the plan-interrogation rename from #97831 per maintainer decision —
the skill keeps its original grill-me name. The content upgrade (design-tree
frontier-rounds interview mechanic from mattpocock/skills' grilling) stays.
Docs page, catalog row, and sidebar entry renamed back.
2026-08-29 06:30:12 -07:00
Teknium
b1ff8722a5 feat(optional-skills): add decision-questionnaire — turn a blocked decision into an async questionnaire
Ports the MIT-licensed 'to-questionnaire' skill from mattpocock/skills as
decision-questionnaire (optional-skills/productivity). Interviews the user
about the send only (recipient + needed outcomes), then drafts a
most-important-first discovery questionnaire with answer stubs to
decision-questionnaire-<slug>.md. Includes staging tests for frontmatter
standards, template sections, and de-upstreaming.
2026-08-29 05:04:13 -07:00
Teknium
7b17d02a09 feat(optional-skills): add setup-wizard-generator — bash wizard for human-only setup steps
Ports the MIT-licensed 'wizard' skill from mattpocock/skills as
setup-wizard-generator (optional-skills/devops). Generates an interactive
bash wizard that walks a human through manual procedures: opens dashboard
URLs, captures values (hidden entry for secrets), writes .env / GitHub
secrets idempotently, and confirms each stage. Vendors upstream's
template.sh library verbatim (bash -n verified) plus a staging test suite
covering frontmatter, template integrity, and de-upstreaming.
2026-08-29 05:03:52 -07:00
Teknium
bfeeb50257 feat(skills): rename grill-me to plan-interrogation, fold in frontier-rounds interview mechanic
Renames the optional grill-me skill to the more descriptive plan-interrogation
and upgrades it with the design-tree frontier-rounds mechanic from
mattpocock/skills' MIT-licensed 'grilling' skill: batch all currently-askable
questions per round in dependency order, agent finds facts itself, decisions
stay with the user. Docs page, catalog row, and sidebar entry renamed.
2026-08-29 05:03:20 -07:00
teknium1
71c823bbf7 refactor(skills): move grill-me to optional-skills
Per the 'when in doubt, optional' rule — plan-interview is an
on-request capability, not a weekly daily-driver for most users.

Install via: hermes skills install official/software-development/grill-me
2026-08-29 03:12:20 -07:00
teknium1
260adeb075 chore(skills/grill-me): contributor mapping + docs catalog/sidebar regen 2026-08-29 03:12:20 -07:00
Teknium
a5c7eed5f3 feat(cli/tui): -q now seeds a live interactive session; prompts submit literally
On a real TTY, `hermes chat -q "…"` (and `--tui -q`) now starts a normal
interactive session with the prompt submitted literally as the first turn —
no slash-command routing, no '!' shell dispatch, no $(...) interpolation,
no file-drop rewriting — matching how other coding agents handle seeded
launches (Omarchy prompted agent terminals, basecamp/omarchy#8705).

Legacy answer-and-exit is preserved everywhere automation depends on it:
- new `hermes chat --oneshot` flag (distinct dest from top-level -z)
- -Q/--quiet machine-readable contract
- any non-TTY stdio (kanban workers, cron, pipes, A2A)
- top-level `hermes -z` unchanged

CLI: seeded prompt rides a _SeededQueryMessage sentinel through
process_loop, which skips the slash/!/file-drop dispatchers for that one
message. TUI: STARTUP_QUERY submits via a new literal path (submitLiteral)
that bypasses dispatchSubmission and the input.detect_drop rewrite.
2026-08-28 05:15:06 -07:00
brooklyn!
4bd2793367 feat(desktop): default the in-app tip rotation on (#96831)
Made opt-in when it fired a tip 45 seconds into a launch and another
every six minutes, which is a cadence that owes you a choice. The pacing
has since become a settling delay of five to ten minutes per launch and
a six-hour cooldown persisted across them — roughly a tip a day, weeks
to walk the catalog. At that weight the switch has nothing left to
protect anyone from, and a discovery feature nobody meets is one nobody
has. The switch stays for whoever still wants it off.
2026-08-28 03:10:46 +00:00
Brooklyn Nicholson
198a69421c feat(desktop): pace the tip rotation in hours, not minutes
A first tip 45 seconds in and one every six minutes after walks the
whole catalog in an hour, which is the cadence of a notification rather
than a nicety. Games get this right by being almost absent: a tip while
you settle in, then nothing for the rest of the day.

Two clocks now have to agree. A per-launch settling delay of five to ten
minutes means opening the app is never met with a bubble, and a six-hour
cooldown persisted across launches means quitting and reopening isn't a
way to farm them — the old schedule lived in the effect and re-armed on
every mount. Flipping the switch on skips the settling delay and offers
immediately, since that clock guards a launch you came into with a
purpose, not a deliberate opt-in.

An agent tip starts the cooldown too: whoever just pointed at something,
the user has had their one interruption for a while.
2026-08-27 21:50:18 -05:00
Brooklyn Nicholson
0357982696 feat(desktop): make the idle tip rotation opt-in, ungate the tool
The two halves of tips were behind one switch, which meant the app
volunteering commentary at idle shipped on by default. Split them along
the line that matters: the rotation talks unprompted, so it now waits to
be asked for, while an agent tip stays ungated like the tour it mirrors
— Hermes raises one mid-conversation, in answer to something the user
said.

Drops the tool's config gate along with the config key it read. The
renderer mirrored that key with config.set, which has no branch for it
and answered "unknown config key" into a swallowed catch, so the opt-out
never reached the backend in the first place.
2026-08-27 21:50:18 -05:00