mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-11 13:41:53 +00:00
tests: pin ink engine in _make_tui_argv npm-bootstrap tests (post-merge semantic fix)
Main's rewritten test_tui_npm_install.py tests call _make_tui_argv expecting the Ink/npm flow unconditionally; with the dual-engine dispatch merged in, _resolve_tui_engine() auto-selects opentui whenever ui-opentui/dist is built in the repo, routing the call away from the path under test (first subprocess became 'node --version' instead of 'npm run build'). Pin the engine to ink via an autouse fixture, mirroring the existing pinning precedent in test_tui_resume_flow.py.
This commit is contained in:
parent
ab37440ce6
commit
e1067dbbe5
756 changed files with 79874 additions and 19585 deletions
|
|
@ -66,6 +66,11 @@ metadata:
|
|||
description: "What this setting controls"
|
||||
default: "sensible-default"
|
||||
prompt: "Display prompt for setup"
|
||||
blueprint: # Optional — marks this skill a runnable automation
|
||||
schedule: "0 9 * * *" # cron expr / "every 2h" / ISO timestamp
|
||||
deliver: origin # optional (default origin)
|
||||
prompt: "Task instruction for each run" # optional
|
||||
no_agent: false # optional
|
||||
required_environment_variables: # Optional — env vars the skill needs
|
||||
- name: MY_API_KEY
|
||||
prompt: "Enter your API key"
|
||||
|
|
@ -334,6 +339,64 @@ If your skill is official and useful but not universally needed (e.g., a paid se
|
|||
|
||||
If your skill is specialized, community-contributed, or niche, it's better suited for a **Skills Hub** — upload it to a registry and share it via `hermes skills install`.
|
||||
|
||||
## Blueprints: skills that are also automations
|
||||
|
||||
A **blueprint** is an ordinary skill that additionally declares a schedule in its frontmatter. Add a `metadata.hermes.blueprint` block and the skill becomes a shareable, runnable automation:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [blueprint, email]
|
||||
blueprint:
|
||||
schedule: "0 8 * * *" # presence of `blueprint:` marks it runnable
|
||||
deliver: telegram # optional (default: origin)
|
||||
prompt: "Summarize my unread email and today's calendar." # optional
|
||||
no_agent: false # optional
|
||||
```
|
||||
|
||||
Because a blueprint **is** a skill, it flows through the entire skills pipeline unchanged — search, inspect, install, security scan, provenance, taps, the centralized index, and `hermes skills publish` for sharing. Nothing new to learn.
|
||||
|
||||
**Installing a blueprint.** When you install a skill that carries a `blueprint:` block, Hermes registers it as a **suggested cron job** rather than scheduling it. Scheduling is **opt-in** — installing never silently creates a recurring job. You review and accept it via `/suggestions`:
|
||||
|
||||
```bash
|
||||
hermes skills install owner/morning-brief
|
||||
# → Blueprint: 'morning-brief' is an automation (schedule 0 8 * * *).
|
||||
# Added to your suggestions — run /suggestions to schedule or dismiss it.
|
||||
|
||||
# then, in a session:
|
||||
/suggestions # lists pending suggestions, numbered
|
||||
/suggestions accept 1 # creates the cron job
|
||||
/suggestions dismiss 1 # never offer it again
|
||||
```
|
||||
|
||||
Blueprints are one **source** of the unified Suggested Cron Jobs surface — the same place curated starter automations and (later) usage-pattern and integration suggestions appear. See [Suggested Cron Jobs](#suggested-cron-jobs) below.
|
||||
|
||||
**Sharing an automation you built.** A blueprint loaded by a cron job (`hermes cron create --skill <name> ...`) can be exported back to a SKILL.md and published like any other skill, so an automation you tuned for yourself becomes a one-command install for someone else.
|
||||
|
||||
The blueprint layer adds no new object type, store, or transport — the blueprint is a skill, the schedule is a cron job, and sharing is the existing publish/tap/index path.
|
||||
|
||||
## Suggested Cron Jobs
|
||||
|
||||
Hermes can *propose* automations and let you accept them with one tap, instead of making you assemble cron jobs by hand. Every proposal flows through one surface — the `/suggestions` command — regardless of where it came from:
|
||||
|
||||
| Source | Trigger |
|
||||
|--------|---------|
|
||||
| `catalog` | Curated starter automations (`/suggestions catalog`) — daily briefing, important-mail monitor, weekly review, workday-start reminder |
|
||||
| `blueprint` | You installed a skill carrying a `blueprint:` block |
|
||||
| `usage` | The background review noticed a recurring ask a schedule would serve |
|
||||
| `integration` | You connected an account (Gmail, GitHub, ...) and the obvious automations are offered |
|
||||
|
||||
```bash
|
||||
/suggestions # list pending
|
||||
/suggestions accept N # schedule suggestion N (creates the cron job)
|
||||
/suggestions dismiss N # dismiss it — latched, never re-offered
|
||||
/suggestions catalog # add the curated starter automations
|
||||
```
|
||||
|
||||
Accepting a suggestion calls the same `cron.jobs.create_job` the `cronjob` tool uses — there is no second job engine. Suggestions **never** auto-create jobs; acceptance is always explicit. Dismissed suggestions latch by a stable key so the same proposal is never re-offered. The pending list is capped so it never becomes a nag wall.
|
||||
|
||||
The **important-mail monitor** catalog entry is the poll→classify→surface pattern: it scores inbox items with a cheap classifier model (`auxiliary.monitor` in `config.yaml`) and delivers only the ones above an urgency threshold, staying silent otherwise.
|
||||
|
||||
## Publishing Skills
|
||||
|
||||
### To the Skills Hub
|
||||
|
|
|
|||
|
|
@ -131,8 +131,9 @@ class AcmeProfile(ProviderProfile):
|
|||
|
||||
def build_api_kwargs_extras(self, *, reasoning_config=None, **context):
|
||||
"""Returns (extra_body_additions, top_level_kwargs). Needed when some
|
||||
fields go top-level (Kimi's reasoning_effort) and some go in extra_body
|
||||
(OpenRouter's reasoning dict). Default: ({}, {})."""
|
||||
fields go top-level (Kimi's reasoning_effort, OpenRouter's verbosity for
|
||||
adaptive Anthropic models) and some go in extra_body (OpenRouter's
|
||||
reasoning dict). Default: ({}, {})."""
|
||||
return {}, {}
|
||||
|
||||
def fetch_models(self, *, api_key=None, timeout=8.0) -> list[str] | None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue