Commit Graph

25 Commits

Author SHA1 Message Date
teknium1
76fe8f7f5f fix: plugin catalog ranks by stars only and drops the review-claim badges
The catalog hero showed three trust chips ("Reviewed by the Hermes team",
"Installs exactly the version we reviewed", "One click from Hermes Desktop")
and the hero copy repeated the review claim. Teknium asked for the review
claim to go; the row goes with it since the remaining two chips only made
sense as a set.

Ranking pinned the official tier above every community entry, so a 5-star
official plugin sat above a 215-star community one and the page looked
unsorted. Tier no longer ranks; stars desc, unknown stars last, name as the
tiebreak. The Official/Community filter pills still exist for anyone who
wants the tier view.
2026-09-19 22:45:39 -07:00
teknium1
3eb9712180 Revert "feat(catalog): restore website install links to Desktop"
This reverts commit cf59980e2c.
2026-09-19 00:11:36 -07:00
teknium1
36fb2be926 fix(website): cross-page doc links resolve on GitHub as well as on the site
Docs under website/docs were linked with Docusaurus site routes
(`](/getting-started/installation)`, `](/docs/user-guide/x)`), which GitHub's
file viewer resolves as repository paths and 404s (#114428). Relative Markdown
file links (`](../user-guide/x.md#anchor)`) are followed by both GitHub and
Docusaurus, so that becomes the authoring convention:

- website/scripts/check_doc_links.py lints hand-authored EN + zh-Hans pages
  for route-style links (`--fix` rewrites them, refusing any route that maps
  to no doc file); wired into the Docs Site Checks workflow and
  tests/website/test_check_doc_links.py.
- generate-skill-docs.py emits the same relative form for related-skill and
  catalog links instead of `/docs/user-guide/skills/...`.
- src/remark/relativeDocLinks.js rewrites `./x.md`/`../x.md` to
  content-root-absolute `/x.md` before Docusaurus resolves links, so a
  relative link still resolves in the zh-Hans build when source and target
  sit on different sides of the translation fallback (Docusaurus resolves
  `./`/`../` only against the source file's own directory).
- website/README.md states the convention and points at the checker.
2026-09-18 14:27:04 -07:00
teknium1
668a778606 test(i18n): make the zh-Hans Bot Mode parity checks invariants, not change-detectors
The heading-sequence and code-block-count tests pinned the English page's exact shape, so any English-only edit of bot-mode.md (e.g. #113411 adds a heading) turned main red until the translation was re-synced. Replace them with two invariants of the translation itself: the page exists and routes like the English page (front matter id/slug agree), and every zh-Hans code block is a byte-accurate copy of a block that still exists in the English page, so only a genuinely stale command/config in the translation fails.
2026-09-16 17:13:00 -07:00
teknium1
6b753202aa docs(i18n): refresh the zh-Hans Bot Mode guide to the current English source; trim to 2 parity tests
The salvaged translation (#94377) mirrored the English guide as of its
base commit; the English page has since gained 147 lines. Translate the
drift so zh-Hans readers see the same guide:

- Bots pane: row-click/tab-caption behaviour, the rewritten "Active now"
  filter, and the archive-retires-a-Bot-Chat paragraph
  (`sessions.auto_archive`).
- New section "Organize bots into sections" (`ui_meta`).
- Avatars: the geometric-face live-turn pose wording.
- Groups: queued-message lead paragraph, editable room identity
  (picture + Group settings), room ordering (Move up/down), and the new
  room bullets (one visible conversation, `@hermes` handoff, needs-you
  prompts, rooms keep running via `groups.capabilities`, plugin hook
  `on_room_member_activity`); member sessions no longer named
  `Group: <name>`.
- Bot-to-bot messaging: live delivery ownership paragraph
  (`runtime/bot_live_delivery/`), the "Staying silent" bullet, the
  `SESSION_NOT_OWNED`/`target_busy` and quiet-CLI-turn paragraphs, the
  side-by-side delivery sentence (`bot_mode.envelope_ttl_seconds`).
- `hermes peer run/status/stop` commands and paragraph, the NAT note.
- New sections "Transferring hosted room authority" (JSON-RPC payloads
  kept byte-identical) and "Warm Bot Backends".
- Turning it off: Capabilities → Plugins → Bots Desktop switch.

Tests: drop the file-exists and internal-link checks (the Docusaurus
build already fails on broken links); keep heading parity and
code-block parity as the two invariants.
2026-09-16 17:13:00 -07:00
chelsealong
9476d4ee05 docs(i18n): add Simplified Chinese translation of the Bot Mode guide
website/docs/user-guide/bot-mode.md had no zh-Hans mirror, so readers on
that locale silently fell back to the English page after #89250 wired up
Bot Mode's docs entry points. Translate the guide in full, preserving
heading order, commands, config keys, paths, and internal links, and add
a structural-parity test so the two stay in sync.

Fixes #94366
2026-09-16 17:13:00 -07:00
teknium1
034313e7cd feat: plugin catalog entries carry an optional version label and card image
The 40-hex sha stays the release, but nobody reads one. Entries may now add
`version: "1.4.0"` (free-form, <=32 chars, never parsed) and `image:` (an https
URL on raw.githubusercontent.com / github.com / *.githubusercontent.com).

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

Readers updated together: PluginCatalogEntry + entry_from_mapping (drop with a
warning, entry survives), validate_plugin_catalog.py (admission error), the
site extractor (drop, never fatal), the /docs/plugins card (banner + version
pill + "1.4.0 @ abcd1234" pin), the CLI table/info (pin_label), the TUI-gateway
plugin row (catalog_version -> Desktop "Update to 1.4.0"), and the Desktop
catalog detail header (image).
2026-09-16 14:18:39 -07:00
brooklyn!
cf59980e2c feat(catalog): restore website install links to Desktop 2026-09-16 13:55:13 -05:00
teknium1
9796235822 Revert "feat(catalog): open website installs in Hermes Desktop"
This reverts commit b0e78e60fb.
2026-09-16 09:25:14 -07:00
brooklyn!
b0e78e60fb feat(catalog): open website installs in Hermes Desktop 2026-09-16 04:33:07 -05:00
teknium1
471d8a427a ci(plugin-catalog): probe stars only from the scheduled skills-index run, in one GraphQL request
Aligns the star ranking with the rule the skills index already follows:
GitHub is consulted only by the twice-daily skills-index.yml schedule, whose
artifact every docs deploy reuses. deploy-site.yml now runs
fetch-plugin-stars.py without --probe (reuse-only: artifact → live site copy →
disk → empty) and cannot call the API at all, so a same-day merge train adds
zero requests regardless of cache age.

The probe itself collapses from one REST call per repo (~26 today, growing
with the catalog) to a single GraphQL query with aliased repository fields,
so the scheduled run costs one request no matter how big the catalog gets. A
failed probe (rate limit, renamed repo, bad token) keeps the previous counts.
2026-09-15 04:39:38 -07:00
teknium1
3e2e2c50eb feat(plugin-catalog): rank entries by GitHub stars, probed at most once a day
Catalog entries sort official → stars desc → name, both in browse shelves and
filtered grids, with a ★ pill on each card linking to the repo's stargazers.

Rate-limit discipline is the design constraint: the docs site deploys many
times a day and shares one GitHub App API budget with every other workflow
(tonight's merge train got rate-limited on unrelated uploads). So
website/scripts/fetch-plugin-stars.py first fetches the live site's own
plugin-stars.json (a CDN GET, not the API); if that cache is under 24h old it
is reused verbatim and GitHub is never called. Only a stale cache triggers one
GET /repos/{owner}/{repo} per unique catalog repo, and a 403/429 mid-run keeps
the previous counts instead of zeroing them. extract-plugins.py merges the
cache into plugins.json (`stars`) and plugins-meta.json (`starsFetchedAt`), and
the page footnote says when the ranking was last refreshed.
2026-09-14 21:24:33 -07:00
teknium1
2de17e5d40 feat(plugin-catalog): default shelf is Desktop, catch-all is General; categorise today's six entries
Teknium's call: most community submissions are Desktop panes, so an entry
without a category lands on the Desktop shelf; "other" becomes "general" for
plugins that genuinely span areas. Shelf order puts Desktop first. The six
entries merged today (pets-all, newswire, auto-titler, live-voice,
metamask-wallet, web-octen) get explicit categories.
2026-09-14 21:00:29 -07:00
teknium1
55dbd7f6e1 feat(plugin-catalog): shelve the catalog by category (Memory, Desktop, Platforms, …)
The catalog page was one undifferentiated grid filtered only by tier, so a
memory provider sat between two Desktop panes. Entries now carry an optional
``category`` (memory | desktop | platform | web | tools | voice | automation |
models | other, default other) that the loader, the admission validator and
the site extractor all understand.

/docs/plugins renders one shelf per category in browse mode, a category pill
row under the tier pills, a clickable category chip on every card, and a
results bar (active category, count, clear) when a filter or search flattens
the view. ``hermes plugins catalog`` gains a Category column and groups by it.
All 18 shipped entries are categorised. Unknown categories fail admission
(same contract as tier) so a typo cannot create a phantom shelf.
2026-09-14 21:00:29 -07:00
teknium1
d1c7f29d75 chore: drop the vendor reference from the parity test docstring 2026-09-13 20:40:45 -07:00
teknium1
f250c15647 test: match documented command forms as whole tokens
A bare substring check let a short alias (/q, /v, /bg, /hb) count as
documented whenever a longer command that starts with the same letters
appears anywhere in the doc, so direction 1 of the contract could pass
while the alias's own command had no row.
2026-09-13 20:40:45 -07:00
Teknium
48bd70b586 Port from nearai/ironclaw#7378: doc-fact contract test keeps slash-commands.md in sync with the command registry
Two-direction contract test (tests/website/test_slash_commands_doc_parity.py):
every CommandDef must be documented under its name or an alias, and every
doc table row must resolve to a registered command. Ported from IronClaw's
doc-fact contract tests (nearai/ironclaw#7378), adapted from their clap
--help parser to our COMMAND_REGISTRY single source of truth.

Real drift it caught, fixed here: /loop (alias /proactive) shipped with a
full feature page (user-guide/features/loops.md) and CLI+gateway handlers
but never got a row in the slash-commands reference. Added to both the CLI
Session table and the messaging table, plus the both-surfaces note.
2026-09-13 20:40:45 -07:00
Teknium
f4af457679 test(plugins): trim catalog tests to invariants against the new shapes
538+570+296+216 lines of change-detectors → 4 files of contract tests:
seed catalog valid, bad entries skipped, kill list name-or-repo, live
fallback+union; real-git pinned install + sidecar + re-pin; kill list
blocks CLI/dashboard/TUI with only the CLI bypass; dashboard merge via
sidecar; probe get_config default; extractor live document.
2026-09-09 04:38:01 -07:00
Teknium
7e17ff0ab3 Merge origin/main into feat/plugin-catalog — reconcile with landed index/manifest-v2 tracks 2026-08-27 21:29:42 -07:00
Brooklyn Nicholson
a45d854d7d fix(docs): index every docs page in llms.txt, not a hand-picked 98
The section list decided membership as well as order, so it drifted as the
docs grew: 109 of 204 pages were absent from the index every LLM reads to
learn what Hermes does — Bot Mode, the desktop app, computer use, web search,
skins, Mixture of Agents, and 22 messaging platforms among them.

Enumerate the docs tree instead. SECTIONS now curates only which pages lead a
section; anything it does not name is absorbed under its path, and a page
matching no section lands in "More" rather than falling out. This also picks
up the three .mdx pages the .md-only glob never saw, points section landing
pages at the directory URL Docusaurus actually serves, and drops a curated row
still aimed at a guide moved to developer-guide/plugins in #59613.

Tests hold both directions against the filesystem rather than the enumerator,
so a page cannot go missing and a link cannot point at a page that moved.
2026-08-19 12:41:45 -05:00
dongjiang
de6a672168 fix(skills-hub): include owner in ClawHub source URLs and add retry on 429 (#51236)
Two fixes for the Skills Hub "View source" links on ClawHub skills:

1. Source URL generation was missing the required {owner} segment —
   https://clawhub.ai/skills/{slug} → 404. Correct format is
   https://clawhub.ai/{owner}/skills/{slug}. When the owner handle is
   unavailable, source_url is now "" (card omits the button) instead of
   emitting a broken link.

2. _fetch_owner_handle() previously delegated to _get_json() which
   returned None on any non-200 response with no retry. Under HTTP 429
   rate-limiting the "50 consecutive failures" safety rail in
   enrich_owners() fired immediately — the documented claim "Respects
   HTTP 429 rate-limit responses with exponential backoff" was not
   actually implemented. Now has its own retry loop: 3 attempts, honours
   Retry-After on 429, exponential backoff on 5xx/transport errors, no
   retry on 4xx.

Changes:
- tools/skills_hub.py: _coerce_skill_payload carries owner from top-level
  response; inspect() captures owner from detail API; _fetch_owner_handle()
  added with bounded retry/backoff; enrich_owners() batch method with
  safety rails (30 workers, early termination at 50 consecutive failures).
- website/scripts/extract-skills.py: _source_url() reads extra["owner"]
  for ClawHub.
- scripts/build_skills_index.py: batch enrichment step after crawling.
- tests: 35 URL/enrichment tests + 7 retry tests (42 total).

Signed-off-by: dongjiang <dongjiang1989@126.com>
2026-07-31 22:33:11 -07:00
Teknium
fb40a768fc feat(docs): add /docs/plugins catalog page fed by plugin-catalog/ extractor
- website/scripts/extract-plugins.py: reads plugin-catalog/*.yaml (+removed.yaml),
  emits static/api/plugins.json + plugins-meta.json; degrades to an empty
  catalog with exit 0 when plugin-catalog/ does not exist yet
- website/src/pages/plugins/: catalog page with search, tier tabs
  (All/Official/Community), capability chips, pinned-SHA repo links,
  copyable install commands, and an empty-state submission CTA
- cross-nav between Skills Hub and Plugin Catalog pages + navbar item
- user docs: user-guide/features/plugin-catalog.md (trust model, install,
  submission checklist, custom git-URL contrast), registered in sidebars.ts
- wired into deploy-site.yml and prebuild.mjs; artifacts gitignored
- tests: tests/website/test_extract_plugins.py
2026-07-22 07:28:53 -07:00
Teknium
59510d7b44 feat(skills): fix browse cap, add source links + copy buttons + category cleanup (#37143)
Skills discovery surfaced ~136 of 88k skills in the CLI and gave community
skills no clickable source on the docs page. Three coupled fixes:

CLI browse:
- hermes skills browse capped at 50 because the per-source limit dict had no
  'hermes-index' key — when the centralized index is available the router
  skips external APIs and serves only the index, so the default-50 fallthrough
  silently truncated the whole hub. Add hermes-index: 5000. Browse now loads
  5367 (269 pages) instead of 136.
- Add an Identifier column + install/inspect hint to the browse table so users
  can act on what they see without a second 'search'.
- Route the TUI browse_skills() helper through parallel_search_sources so it
  inherits the same index-aware source-skip (was double-counting); expose
  identifier in its output.

Docs Skills Hub page:
- Synthesize a sourceUrl for every community skill (github tree URL, clawhub /
  skills.sh / lobehub / browse.sh detail pages), preferring the adapter's
  explicit extra.detail_url/source_url/repo_url. Expanded cards now show
  'View source' for community skills (was nothing) and keep 'View full
  documentation' for built-in/optional. 99% coverage.
- Add a Copy button on the install command.
- Add a loading state instead of flashing '0 skills / No skills found' while
  the 45MB catalog fetches.

Category cleanup:
- _guess_category fell back to tags[0] verbatim, producing ~430 junk one-off
  categories (version strings, brand names: '0.10.7 Dev', 'Doramagic Crystal').
  Now only curated buckets are accepted; unknowns fold into 'Other'. Widen the
  tag->category map so common community tags route to real buckets. 430 -> 173
  categories, top 20 all meaningful.

Tests: tests/website/test_extract_skills.py covers _source_url synthesis +
precedence and _guess_category curation (13 tests). All 27 skills-hub CLI
tests still pass. Docusaurus build verified; expanded cards confirmed in
browser for both community (View source) and built-in (View full docs).
2026-06-01 19:52:28 -07:00
LeonSGP43
80c579a9dd docs(skills): explain restoring bundled skills 2026-05-05 13:46:20 -07:00
Teknium
65f648ee84 fix(website): auto-wrap ASCII-art code blocks in generated skill pages (#16497)
Defensive: when the generator encounters a fenced code block containing
Unicode box-drawing characters, wrap it in `<!-- ascii-guard-ignore -->`
markers so the docs-site-checks lint (which scans inside code fences)
can't reject the page for a skill's own diagram.

Plain bash/python code blocks stay uncluttered — only blocks with box
chars get wrapped. Skill authors no longer have to remember to add the
ignore markers in every SKILL.md with ASCII art.

Fixes #15305.
2026-04-27 03:38:39 -07:00