@ours.network/hermes 0.17.0-nightly.9 → 0.18.0-nightly.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/bin/hermes-config-install.mjs +3 -3
- package/config/ours.mcp.example.yaml +1 -1
- package/install.sh +10 -10
- package/package.json +1 -1
- package/skills/ours/SKILL.md +12 -19
- package/skills/ours/references/configuration.md +26 -82
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ It mirrors the Claude Code plugin (`packages/claude-code`), adapted to Hermes:
|
|
|
11
11
|
invites, contacts, send/read, files, control plane), in Hermes `SKILL.md`
|
|
12
12
|
format, plus `writing-agent-bios`.
|
|
13
13
|
3. **Reactivity** — in-session wake-on-mail: the agent tails
|
|
14
|
-
`ours-mcp watch
|
|
14
|
+
`ours-mcp watch <identity>` via its `terminal` tool (backgrounded) and drains
|
|
15
15
|
each new-mail line with `mcp_ours_get_messages`. No connector, no webhook, no
|
|
16
16
|
secret — same stream Claude Code's native Monitor tails.
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ It mirrors the Claude Code plugin (`packages/claude-code`), adapted to Hermes:
|
|
|
20
20
|
Wake-on-mail is **in-session**, driven by the agent itself — there is no webhook
|
|
21
21
|
route, no HMAC secret, and no connector process. Once an identity is bound:
|
|
22
22
|
|
|
23
|
-
- **WATCH**: the agent runs `ours-mcp watch
|
|
23
|
+
- **WATCH**: the agent runs `ours-mcp watch <identity>` in the background via
|
|
24
24
|
Hermes's `terminal` tool. This tails the same new-mail stream Claude Code's
|
|
25
25
|
native Monitor tails; each new message emits a line.
|
|
26
26
|
- **DRAIN**: on each new-mail line the agent reacts, draining the inbox with
|
|
@@ -65,7 +65,7 @@ Wake-on-mail is enabled **in-session**, not by the installer. Once ours is insta
|
|
|
65
65
|
|
|
66
66
|
1. In your Hermes agent, **bind (or create) an identity** via the `ours` skill.
|
|
67
67
|
2. Ask the `ours` skill to **"wake me on new mail"**. The agent starts tailing
|
|
68
|
-
`ours-mcp watch
|
|
68
|
+
`ours-mcp watch <identity>` in the background via its `terminal` tool and reacts
|
|
69
69
|
to each new-mail line by draining with `mcp_ours_get_messages` (or, as a fallback,
|
|
70
70
|
polls `get_messages` every ~5s while it's live). No route, no secret, no connector.
|
|
71
71
|
|
|
@@ -116,11 +116,11 @@ Then run **`/reload-mcp`** in Hermes so it loads the `mcp_ours_*` tools.
|
|
|
116
116
|
3. `/reload-mcp` in Hermes.
|
|
117
117
|
|
|
118
118
|
To get woken on new mail, ask the `ours` skill in-session to wake you: it tails
|
|
119
|
-
`ours-mcp watch
|
|
119
|
+
`ours-mcp watch <identity>` via the `terminal` tool and drains with `get_messages`.
|
|
120
120
|
|
|
121
121
|
## Verify
|
|
122
122
|
|
|
123
|
-
- `ours
|
|
123
|
+
- `ours daemon status` — shared daemon up.
|
|
124
124
|
- In Hermes: *"which mcp_ours tools are available?"* — should list ours tools.
|
|
125
125
|
- Ask the agent to wake you on new mail (bind an identity first), then send yourself a
|
|
126
126
|
message from a peer identity and confirm the in-session watch reacts.
|
|
@@ -25,9 +25,9 @@ export function planConfigInstall(text) {
|
|
|
25
25
|
const t = text ?? '';
|
|
26
26
|
if (t.includes(SENTINEL)) {
|
|
27
27
|
if (!t.includes(SENTINEL_END)) return { action: 'manual', reason: 'ours managed block is incomplete' };
|
|
28
|
-
return t.includes('
|
|
28
|
+
return t.includes('ours-mcp') && t.includes('proxy') && !t.includes('--application')
|
|
29
29
|
? { action: 'noop', reason: 'ours block already present' }
|
|
30
|
-
: { action: 'replace', reason: 'migrate the managed block to
|
|
30
|
+
: { action: 'replace', reason: 'migrate the managed block to shared-daemon selection' };
|
|
31
31
|
}
|
|
32
32
|
if (!t.trim()) return { action: 'write', reason: 'no existing config' };
|
|
33
33
|
if (/^mcp_servers:/m.test(t)) {
|
|
@@ -47,7 +47,7 @@ export function renderConfigBlock() {
|
|
|
47
47
|
mcp_servers:
|
|
48
48
|
ours:
|
|
49
49
|
command: "ours-mcp"
|
|
50
|
-
args: ["proxy"
|
|
50
|
+
args: ["proxy"]
|
|
51
51
|
enabled: true
|
|
52
52
|
${SENTINEL_END}
|
|
53
53
|
`;
|
package/install.sh
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Install the ours.network plugin into Hermes:
|
|
3
|
-
# 1. ensure the ours
|
|
3
|
+
# 1. ensure the ours operator CLI and MCP adapter are installed; start the shared daemon
|
|
4
4
|
# 2. install the ours + writing-agent-bios skills into ~/.hermes/skills/
|
|
5
5
|
# 3. write the `ours` MCP server into ~/.hermes/config.yaml (idempotent, never corrupts
|
|
6
6
|
# existing YAML)
|
|
@@ -31,18 +31,18 @@ say(){ printf 'ours-install: %s\n' "$1"; }
|
|
|
31
31
|
ensure_daemon_latest(){
|
|
32
32
|
if [ "${OURS_INSTALL_SKIP_DAEMON:-}" = "1" ]; then say "skipping daemon step (OURS_INSTALL_SKIP_DAEMON=1)"; return 0; fi
|
|
33
33
|
local before after
|
|
34
|
-
before="$(ours
|
|
35
|
-
say "ensuring @ours.network/mcp@latest…"
|
|
36
|
-
npm i -g @ours.network/mcp@latest
|
|
37
|
-
after="$(ours
|
|
38
|
-
if ! ours
|
|
39
|
-
say "starting the ours daemon…"; ours
|
|
34
|
+
before="$(ours version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)"
|
|
35
|
+
say "ensuring @ours.network/cli@latest and @ours.network/mcp@latest…"
|
|
36
|
+
npm i -g @ours.network/cli@latest @ours.network/mcp@latest
|
|
37
|
+
after="$(ours version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)"
|
|
38
|
+
if ! ours daemon status >/dev/null 2>&1; then
|
|
39
|
+
say "starting the ours daemon…"; ours daemon start || say "could not start; run 'ours daemon start' if the tools error."
|
|
40
40
|
elif [ -n "$before" ] && [ "$before" != "$after" ]; then
|
|
41
|
-
say "
|
|
41
|
+
say "operator CLI upgraded (v${before} → v${after}) — restarting its daemon…"; ours daemon restart || ours daemon start || true
|
|
42
42
|
else
|
|
43
43
|
say "daemon already current (v${after:-unknown})."
|
|
44
44
|
fi
|
|
45
|
-
say "
|
|
45
|
+
say "operator CLI: $(command -v ours) (v${after:-unknown}); MCP adapter: $(command -v ours-mcp)"
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
# Idempotent, GUARDED cleanup of legacy connector-era artifacts earlier (0.2.0/0.3.0) installers
|
|
@@ -93,7 +93,7 @@ say "done. Run /reload-mcp in Hermes to load the mcp_ours_* tools."
|
|
|
93
93
|
# --- version echo: show the user they are on latest ---
|
|
94
94
|
if [ "${OURS_INSTALL_SKIP_DAEMON:-}" != "1" ]; then
|
|
95
95
|
say "versions:"
|
|
96
|
-
say "
|
|
96
|
+
say " MCP adapter: $(ours-mcp --version 2>/dev/null | head -1 || echo 'unknown')"
|
|
97
97
|
say " plugin: $(npm ls -g @ours.network/hermes 2>/dev/null | grep -oE '@ours\.network/hermes@[0-9][0-9.]*' | head -1 || echo '@ours.network/hermes (not a global install)')"
|
|
98
98
|
fi
|
|
99
99
|
say "next: in your agent, bind (or create) an identity and ask the ours skill to \"wake me on new"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/hermes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0-nightly.1",
|
|
4
4
|
"description": "Hermes (Nous Research) plugin for ours — secure agent-to-agent messaging over ADAPT. Registers the ours MCP server, bundles the ours skill, and wires in-session wake-on-mail via `ours-mcp watch` (no webhook, no external watcher).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
package/skills/ours/SKILL.md
CHANGED
|
@@ -77,19 +77,12 @@ allows it for legacy reasons; this skill does not.
|
|
|
77
77
|
|
|
78
78
|
Walk the user through these, checking each. Stop and help at the first one that isn't done.
|
|
79
79
|
|
|
80
|
-
1. **Daemon running.** The MCP tools
|
|
81
|
-
`ours
|
|
82
|
-
@ours.network/mcp`, then `ours
|
|
83
|
-
`ours
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
type `! ours-mcp status` etc.
|
|
87
|
-
Then check optional voice support with `ours-mcp voice-status --json`. If it is
|
|
88
|
-
not ready and the user wants voice transcription, ask them to run `ours-install`
|
|
89
|
-
in a terminal: it re-detects incomplete setup and reads the provider key with
|
|
90
|
-
hidden input. **Never ask for, paste, echo, or put the key in chat/tool arguments.**
|
|
91
|
-
Environment-only operators may set `OURS_STT_*` themselves. Troubleshooting and
|
|
92
|
-
the exact Telegram OGG/Opus fallback contract are in `references/configuration.md`.
|
|
80
|
+
1. **Daemon running.** The MCP tools attach to the shared daemon. Check it with
|
|
81
|
+
`ours daemon status`. If the commands are missing, install
|
|
82
|
+
`@ours.network/cli@1.0.1` and `@ours.network/mcp`, then run `ours config setup`
|
|
83
|
+
and `ours daemon start`. For boot persistence offer
|
|
84
|
+
`ours daemon install-service`. These are operator commands; explain the shared
|
|
85
|
+
blast radius and obtain consent before changing configuration or lifecycle.
|
|
93
86
|
2. **Plugin installed.** Run this package's `install.sh` (from `@ours.network/hermes`).
|
|
94
87
|
It ensures the daemon, writes the `ours` MCP server into `~/.hermes/config.yaml`, and
|
|
95
88
|
installs this skill into `~/.hermes/skills/`. That's all — no identities, no webhook route,
|
|
@@ -100,7 +93,7 @@ Walk the user through these, checking each. Stop and help at the first one that
|
|
|
100
93
|
4. **Connect.** Generate an invite to share, or paste one to add a contact. Same-host
|
|
101
94
|
identities skip invites via the local contact book.
|
|
102
95
|
5. **(Optional) Wake on mail.** Wake is enabled **in-session by you**, after an identity is
|
|
103
|
-
bound: offer to enter **autonomous watch mode** — hold a blocking `ours-mcp watch
|
|
96
|
+
bound: offer to enter **autonomous watch mode** — hold a blocking `ours-mcp watch <identity>`
|
|
104
97
|
via the `terminal` tool and react to each new message from that loop (see *Getting woken on new mail*
|
|
105
98
|
below). **Be honest that this BLOCKS the session** (unlike Claude Code's background Monitor) —
|
|
106
99
|
don't sell it as "just works". The installer never sets this up.
|
|
@@ -190,7 +183,7 @@ the bio, so a persona prompt is only needed if they want to role-play it).
|
|
|
190
183
|
2. **Wake check.** The `choose_identity` / `create_identity` response may prompt you to "arm a
|
|
191
184
|
message monitor" — that is the Claude-Code seam, and the intent is the same in Hermes: **you**
|
|
192
185
|
enable wake in-session, right after binding, by entering **autonomous watch mode** (hold a
|
|
193
|
-
blocking `ours-mcp watch
|
|
186
|
+
blocking `ours-mcp watch <identity>` and handle each message from that loop — see *Wake on new
|
|
194
187
|
mail*). If the user wants live reactivity for the just-bound identity, offer to enter watch
|
|
195
188
|
mode now.
|
|
196
189
|
|
|
@@ -233,8 +226,8 @@ random public-safe `tmp-…` name), binds it to this session, and marks it **tem
|
|
|
233
226
|
If a notice says your plugin and the running daemon are different
|
|
234
227
|
versions, it is **advisory** — everything still works. Relay it to the user and,
|
|
235
228
|
if they want matching versions, tell them: the daemon is shared and is not
|
|
236
|
-
restarted automatically, so run `ours
|
|
237
|
-
mid-task
|
|
229
|
+
restarted automatically, so run `ours daemon restart` only when no other session
|
|
230
|
+
is mid-task, or update the lagging side.
|
|
238
231
|
Do **not** stop work, refuse, or restart anything on your own over this.
|
|
239
232
|
|
|
240
233
|
### Workspace identity pin (`.ours-identity`)
|
|
@@ -364,7 +357,7 @@ When you bind an identity, offer the user, in plain language:
|
|
|
364
357
|
|
|
365
358
|
> "Want this session to **auto-wake** when a new message arrives, or **check manually**?"
|
|
366
359
|
|
|
367
|
-
- **Auto-wake** → arm the monitor: you hold a live `ours-mcp watch
|
|
360
|
+
- **Auto-wake** → arm the monitor: you hold a live `ours-mcp watch <id>` and react to each message as it arrives. **Be upfront:** while watching, this session is **busy** — you can't send it new prompts. To do something else: press **ESCAPE** to interrupt the watch, type your prompt, then ask it to **resume** watching. *(On Claude Code this same monitor runs non-blocking in the background — a Claude Code advantage.)*
|
|
368
361
|
- **Manual** → don't arm it; ask it to check `get_messages` whenever you want. No blocking.
|
|
369
362
|
|
|
370
363
|
## Control plane — human oversight of a fleet
|
|
@@ -394,7 +387,7 @@ feature and still works; it is described above.
|
|
|
394
387
|
event (sender + id + date) to `$OURS_STATE_DIR/<identity>/notifications.log` (the wake
|
|
395
388
|
signal `ours-mcp watch` reads) and refreshes a body-free `unread.json`. Text lives in the
|
|
396
389
|
packet and leaves it solely via `get_messages`.
|
|
397
|
-
- **The wake signal is uniform.** `ours-mcp watch
|
|
390
|
+
- **The wake signal is uniform.** `ours-mcp watch <identity>` is the explicitly named stream; each harness
|
|
398
391
|
drives it in-session. Claude Code uses its native `Monitor` tool; **Hermes uses autonomous watch
|
|
399
392
|
mode** — the agent holds a blocking `ours-mcp watch` via the `terminal` tool and reacts from that
|
|
400
393
|
loop (see *Getting woken on new mail*). The ours daemon, identities, and tools are identical across
|
|
@@ -1,82 +1,26 @@
|
|
|
1
|
-
# ours configuration
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
Both methods edit the same `~/.ours/config.json` file — the interactive survey is just guided editing.
|
|
28
|
-
|
|
29
|
-
**Blast radius — explain this before any change:**
|
|
30
|
-
- **Any config change restarts the daemon — every active session loses its binding and must `choose_identity` again.** Only change config when no other session is mid-task.
|
|
31
|
-
- **Changing `stateDir` orphans existing identities** — they live under the old
|
|
32
|
-
directory and won't be found under the new one.
|
|
33
|
-
|
|
34
|
-
If a tool can't reach the daemon, first check `ours-mcp status` (is it running,
|
|
35
|
-
on which port). With `autoStart` off (the default) the most common cause is
|
|
36
|
-
simply a daemon that was never started — the fix is `ours-mcp start`. A port
|
|
37
|
-
collision is the other usual cause; resolving it is a config change — surface
|
|
38
|
-
it to the user with the blast radius above and act only on an explicit yes.
|
|
39
|
-
|
|
40
|
-
## Voice-message transcription
|
|
41
|
-
|
|
42
|
-
Run `ours-mcp voice-status --json` first. It reports only readiness, provider,
|
|
43
|
-
key presence/source, and a missing-field reason; it never returns the key. A
|
|
44
|
-
ready result is idempotent: keep it and do not ask for setup again. A not-ready
|
|
45
|
-
result should be offered again on every interactive `ours-install` rerun.
|
|
46
|
-
Headless/`OURS_ASSUME_YES` runs never prompt and never invent credentials.
|
|
47
|
-
|
|
48
|
-
Safest guided setup: ask the user to run `ours-install` in their own terminal.
|
|
49
|
-
Its API-key prompt is hidden, it writes `config.json` atomically with mode
|
|
50
|
-
`0600`, and it restores the prior file if the daemon cannot reload the change.
|
|
51
|
-
Never request a provider key in chat, pass one through an agent tool/command
|
|
52
|
-
argument, print the `stt` config block, or test with a real key. Environment-only
|
|
53
|
-
operators can set `OURS_STT_PROVIDER`, `OURS_STT_API_KEY`, `OURS_STT_MODEL`,
|
|
54
|
-
`OURS_STT_BASE_URL`, and `OURS_STT_LANGUAGE`; environment values override the
|
|
55
|
-
file field-by-field.
|
|
56
|
-
|
|
57
|
-
Provider requirements:
|
|
58
|
-
|
|
59
|
-
- `openai-compatible`: key + explicit `/v1` base URL + model.
|
|
60
|
-
- `elevenlabs`: key + model; base URL is optional.
|
|
61
|
-
- `deepgram`: key; model/base URL are optional provider defaults.
|
|
62
|
-
- `custom`: key + `stt.custom.url`; model is required when the custom template
|
|
63
|
-
references it.
|
|
64
|
-
|
|
65
|
-
Troubleshooting:
|
|
66
|
-
|
|
67
|
-
- “not ready” names the missing field. Do not ask the user to reveal its value.
|
|
68
|
-
- If a file edit appears ineffective, check the reported key source and
|
|
69
|
-
`OURS_STT_*`; an environment override may shadow the file.
|
|
70
|
-
- Config changes require a daemon restart and active sessions may need to bind
|
|
71
|
-
their identity again.
|
|
72
|
-
- Incoming voice is recognized strictly as an `audio/*` MIME carrying
|
|
73
|
-
`x-ours-kind=voice-message`, or the legacy `voice-message-…` audio filename.
|
|
74
|
-
Generic audio and connector-specific filename guesses remain ordinary files.
|
|
75
|
-
- Telegram fallback preserves the original OGG/Opus bytes and `.ogg` filename.
|
|
76
|
-
Its `send_file` MIME and correlated v2 envelope `attachment.mime` must both be
|
|
77
|
-
`audio/ogg; x-ours-kind=voice-message`; `attachment.wire_id` identifies the
|
|
78
|
-
separately delivered file. Connector-local STT success may remain text-only.
|
|
79
|
-
- Oversized audio is saved but not uploaded (daemon default: 5 MiB). Provider
|
|
80
|
-
HTTP, timeout, malformed-response, and network failures degrade to a precise
|
|
81
|
-
“transcription failed” line with the saved audio path; provider responses are
|
|
82
|
-
scrubbed if they echo the configured key.
|
|
1
|
+
# ours daemon configuration
|
|
2
|
+
|
|
3
|
+
ours-mcp is a client of one already-running shared daemon. The operator CLI owns
|
|
4
|
+
configuration and lifecycle:
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
ours config show --json
|
|
8
|
+
ours config setup --port 3050 --state-dir "$HOME/.ours"
|
|
9
|
+
ours daemon start
|
|
10
|
+
ours daemon status --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The MCP adapter uses the published SDK's coherent selection. The wholly default
|
|
14
|
+
selection is port 3050 with state directory `~/.ours`. For another daemon, set
|
|
15
|
+
`OURS_CONFIG`, or set matching `OURS_PORT` and `OURS_STATE_DIR`. A token or
|
|
16
|
+
endpoint selection must be paired with its state directory. The daemon's
|
|
17
|
+
`/state-dir` response is verified before credentials are sent.
|
|
18
|
+
|
|
19
|
+
The adapter never starts a daemon and never falls back to an embedded one.
|
|
20
|
+
`OURS_INSTANCE`, `--application`, and old ours-mcp daemon variables are errors.
|
|
21
|
+
Do not add a duplicate MCP registration; the managed command is simply
|
|
22
|
+
`ours-mcp proxy`.
|
|
23
|
+
|
|
24
|
+
Changing daemon configuration or restarting the shared daemon affects every
|
|
25
|
+
connected application. Explain that blast radius and obtain the user's consent
|
|
26
|
+
before making operator-level changes.
|