napcat-cli 2.0.0__tar.gz

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.
Files changed (56) hide show
  1. napcat_cli-2.0.0/.gitignore +74 -0
  2. napcat_cli-2.0.0/.gitmodules +3 -0
  3. napcat_cli-2.0.0/PKG-INFO +219 -0
  4. napcat_cli-2.0.0/README.md +208 -0
  5. napcat_cli-2.0.0/docs/HERMES_WAKE.md +95 -0
  6. napcat_cli-2.0.0/napcat_cli/__init__.py +3 -0
  7. napcat_cli-2.0.0/napcat_cli/cli.py +1834 -0
  8. napcat_cli-2.0.0/napcat_cli/daemon/__init__.py +1 -0
  9. napcat_cli-2.0.0/napcat_cli/daemon/schemas.py +470 -0
  10. napcat_cli-2.0.0/napcat_cli/daemon/watch.py +1994 -0
  11. napcat_cli-2.0.0/napcat_cli/data/SKILL.md +328 -0
  12. napcat_cli-2.0.0/napcat_cli/data/__init__.py +0 -0
  13. napcat_cli-2.0.0/napcat_cli/data/persona.md +155 -0
  14. napcat_cli-2.0.0/napcat_cli/data/references/mounting.md +90 -0
  15. napcat_cli-2.0.0/napcat_cli/data/skills-fs-config.json +12 -0
  16. napcat_cli-2.0.0/napcat_cli/data/skills-fs-fragment.json +473 -0
  17. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-friend-time.md +7 -0
  18. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-friend.md +7 -0
  19. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-friends.md +4 -0
  20. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-group-time.md +7 -0
  21. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-group.md +6 -0
  22. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-groups.md +5 -0
  23. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/agents-napcat.md +9 -0
  24. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/persona.md +155 -0
  25. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/skill-agents.md +42 -0
  26. napcat_cli-2.0.0/napcat_cli/data/skills-fs.d/skill-body.md +102 -0
  27. napcat_cli-2.0.0/napcat_cli/lib/__init__.py +1 -0
  28. napcat_cli-2.0.0/napcat_cli/lib/api.py +258 -0
  29. napcat_cli-2.0.0/napcat_cli/lib/config.py +105 -0
  30. napcat_cli-2.0.0/napcat_cli/lib/events.py +127 -0
  31. napcat_cli-2.0.0/napcat_cli/lib/events_sqlite.py +242 -0
  32. napcat_cli-2.0.0/napcat_cli/lib/message.py +156 -0
  33. napcat_cli-2.0.0/napcat_cli/setup_wizard.py +380 -0
  34. napcat_cli-2.0.0/napcat_cli/tui/__init__.py +1 -0
  35. napcat_cli-2.0.0/napcat_cli/tui/__main__.py +13 -0
  36. napcat_cli-2.0.0/napcat_cli/tui/api.py +158 -0
  37. napcat_cli-2.0.0/napcat_cli/tui/app.py +127 -0
  38. napcat_cli-2.0.0/napcat_cli/tui/chat_list.py +168 -0
  39. napcat_cli-2.0.0/napcat_cli/tui/chat_view.py +456 -0
  40. napcat_cli-2.0.0/napcat_cli/tui/styles.tcss +9 -0
  41. napcat_cli-2.0.0/napcat_cli/wake.py +51 -0
  42. napcat_cli-2.0.0/napcat_cli/wake_backend.py +390 -0
  43. napcat_cli-2.0.0/napcat_cli/wake_orchestrator.py +302 -0
  44. napcat_cli-2.0.0/napcat_cli/wake_presets.py +77 -0
  45. napcat_cli-2.0.0/persona.md +155 -0
  46. napcat_cli-2.0.0/pyproject.toml +40 -0
  47. napcat_cli-2.0.0/skills-fs-config.json +12 -0
  48. napcat_cli-2.0.0/tests/conftest.py +26 -0
  49. napcat_cli-2.0.0/tests/test_config.py +84 -0
  50. napcat_cli-2.0.0/tests/test_fs.py +73 -0
  51. napcat_cli-2.0.0/tests/test_setup.py +59 -0
  52. napcat_cli-2.0.0/tests/test_wake.py +58 -0
  53. napcat_cli-2.0.0/tests/test_wake_backend.py +183 -0
  54. napcat_cli-2.0.0/tests/test_wake_orchestrator.py +108 -0
  55. napcat_cli-2.0.0/tools/agents-md.json +10 -0
  56. napcat_cli-2.0.0/tools/gen_mounts.py +349 -0
@@ -0,0 +1,74 @@
1
+ # If you prefer the allow list template instead of the deny list, see community template:
2
+ # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3
+ #
4
+ # Binaries for programs and plugins
5
+ *.exe
6
+ *.exe~
7
+ *.dll
8
+ *.so
9
+ *.dylib
10
+
11
+ # Test binary, built with `go test -c`
12
+ *.test
13
+
14
+ # Code coverage profiles and other test artifacts
15
+ *.out
16
+ coverage.*
17
+ *.coverprofile
18
+ profile.cov
19
+
20
+ # Dependency directories (remove the comment below to include it)
21
+ # vendor/
22
+
23
+ # Go workspace file
24
+ go.work
25
+ go.work.sum
26
+
27
+ # Project-specific build artifacts (anchored to root)
28
+ /webdav-server
29
+ /websocket-events
30
+ /websocket-reconnect
31
+ /basic
32
+ /go-bridge
33
+
34
+ # env file
35
+ .env
36
+
37
+ # Editor/IDE
38
+ .idea/
39
+ .vscode/
40
+ *.swp
41
+ *.swo
42
+
43
+ # OS
44
+ .DS_Store
45
+ Thumbs.db
46
+
47
+ # Node.js binding build artifacts
48
+ binding/nodejs/node_modules/
49
+ binding/nodejs/build/
50
+ binding/nodejs/lib/
51
+ binding/nodejs/package-lock.json
52
+
53
+ # Python binding build artifacts
54
+ binding/python/lib/
55
+ binding/python/__pycache__/
56
+ **/__pycache__/
57
+ *.pyc
58
+ *.pyo
59
+
60
+ # Local benchmark baselines (generated on demand)
61
+ bench/baseline.txt
62
+ # Python packaging
63
+ dist/
64
+ *.egg-info
65
+ build/
66
+
67
+ # napcat-cli local cruft (do not commit)
68
+ SKILLS_FS_DEGRADED
69
+ debug
70
+ keys.log
71
+
72
+ # Local virtualenvs (their absolute symlinks break the sdist tar)
73
+ .smoke/
74
+ .test-venv/
@@ -0,0 +1,3 @@
1
+ [submodule "skills-fs"]
2
+ path = skills-fs
3
+ url = https://github.com/yandu-app/skills-fs
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: napcat-cli
3
+ Version: 2.0.0
4
+ Summary: Standalone CLI and daemon for NapCat QQ bot management with skills-fs integration
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: textual>=0.40
8
+ Provides-Extra: dev
9
+ Requires-Dist: pytest>=7; extra == 'dev'
10
+ Description-Content-Type: text/markdown
11
+
12
+ # napcat-cli
13
+
14
+ Standalone CLI and daemon for NapCat QQ bot management with skills-fs integration.
15
+
16
+ > 📝 **介绍博文:** [napcat-cli 群配置与管理速查](https://yvxi.pages.dev/blog/napcat-cli-group-config/) — 从零配置、群消息收发、Agent Wake 的完整链路。
17
+
18
+ ---
19
+
20
+ napcat-cli provides a CLI for all NapCat API operations, a WebSocket daemon
21
+ that bridges to a skills-fs HTTP provider, and an agent wake-up mechanism for
22
+ integrating with Hermes or other AI agents.
23
+
24
+ ```bash
25
+ napcat send group 123456 -m "Hello"
26
+ napcat send private 987654 -m "Hi"
27
+ napcat recall 1001
28
+ napcat events --limit 10
29
+ napcat daemon start
30
+ napcat wake --reason NEW_MESSAGE
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Commands
36
+
37
+ | Command | Description |
38
+ |---------|-------------|
39
+ | `napcat api <endpoint>` | Raw API access (like `gh api`) |
40
+ | `napcat send group <id> -m "msg"` | Send group message |
41
+ | `napcat send private <id> -m "msg"` | Send private message |
42
+ | `napcat reply <id> -m "msg"` | Reply to a message |
43
+ | `napcat recall <msg_id>` | Recall a message |
44
+ | `napcat group <sub>` | Group list, members, settings |
45
+ | `napcat friend <sub>` | Friend list, info |
46
+ | `napcat file <sub>` | File upload, download, list |
47
+ | `napcat events` | Read events from SQLite |
48
+ | `napcat alerts [--clear]` | Pending alerts |
49
+ | `napcat status` | Bot online status |
50
+ | `napcat config get/set` | Configuration management |
51
+ | `napcat daemon start/stop/status/restart` | Watch daemon |
52
+ | `napcat fs tree` | Skills-fs directory tree |
53
+ | `napcat wake [--reason R] [--prompt P] [--transport T] [--dry-run]` | Wake the configured agent (HTTP/CLI, auto-fallback) |
54
+ | `napcat setup` | Interactive setup wizard |
55
+ | `napcat phone` | Textual phone-style TUI |
56
+
57
+ ---
58
+
59
+ ## Setup
60
+
61
+ ```bash
62
+ uv tool install napcat-cli
63
+ napcat setup # interactive — guides token, data dir, skills-fs, wake
64
+ napcat daemon start
65
+ ```
66
+
67
+ The setup wizard writes two config files:
68
+
69
+ - `<data_dir>/config.json` — API URL, token, self_id, ports, triggers
70
+ - `<data_dir>/daemon.json` — All fields consumed by `watch.py` including `skills_fs_*` settings
71
+
72
+ Non-interactive mode uses defaults:
73
+
74
+ ```bash
75
+ napcat setup --non-interactive # no prompts, validates token
76
+ napcat setup --yes # skip token validation
77
+ napcat setup --force # overwrite existing config
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Agent Wake
83
+
84
+ When a notable QQ event arrives, the daemon wakes an external agent (Hermes by
85
+ default) carrying a **contextual prompt** so it can read the inbox and reply.
86
+ The wake mechanism is **generic and pluggable** — Hermes is just the default
87
+ preset; any HTTP endpoint or shell command works.
88
+
89
+ ### Two transports, auto-fallback
90
+
91
+ | Transport | When it's used | Needs |
92
+ |-----------|----------------|-------|
93
+ | **CLI one-shot** (default) | Always available | `hermes` on PATH |
94
+ | **HTTP API server** | Opt-in (best latency, idempotent, in-session) | `wake_http_url` + `wake_http_key` |
95
+
96
+ `wake_primary=auto` tries HTTP first (if configured + reachable), else falls back
97
+ to the CLI one-shot. The Hermes CLI backend runs
98
+ `hermes --continue <session> -z "<prompt>" --yolo --pass-session-id`; the HTTP
99
+ backend POSTs to `POST /api/sessions/{id}/chat` (verified per the Hermes API
100
+ docs), with `Authorization: Bearer <key>` and an `Idempotency-Key` header.
101
+
102
+ ### Event routing
103
+
104
+ | Trigger | Behavior |
105
+ |---------|----------|
106
+ | `AT_ME`, `REPLY_TO_ME` | Near-immediate wake (cooldown bypassed), with who/where/text in the prompt |
107
+ | `GROUP_TRIGGER`, `PRIVATE_TRIGGER` | Debounced wake |
108
+ | `NEW_MESSAGE` (not @) | Tracked, not woken; if unread longer than `wake_new_message_idle_seconds` → a `NEW_MESSAGE_BACKLOG` wake |
109
+ | `NEW_FRIEND`, `NEW_REQUEST`, `BOT_BANNED`, `NEW_POKE`, `GROUP_ADMIN_CHANGE`, `NEW_GROUP_MEMBER`, `BOT_OFFLINE`, … | Debounced + cooldown-bounded wake so the agent perceives them within a reasonable window |
110
+
111
+ Debounce (`wake_debounce_seconds`, default 3) coalesces a burst into one wake;
112
+ cooldown (`wake_cooldown_seconds`, default 30) suppresses repeats. Every wake is
113
+ logged to `daemon.log` as `[WAKE] trigger / queued / deliver / reply` lines
114
+ (including transport, elapsed time, and the agent's reply), and `daemon.log` is
115
+ size-rotated (2 MB × 5) so it can't fill the disk.
116
+
117
+ ### Configure
118
+
119
+ The easiest path is the wizard:
120
+
121
+ ```bash
122
+ napcat setup # choose Hermes preset; CLI one-shot by default, HTTP opt-in
123
+ ```
124
+
125
+ Or set keys directly:
126
+
127
+ ```bash
128
+ napcat config set wake_enabled true
129
+ napcat config set wake_preset hermes # hermes | custom | none
130
+ napcat config set wake_session napcat-qq
131
+ napcat config set wake_primary auto # auto | http | cli
132
+ # HTTP (optional). Key also readable from NAPCAT_WAKE_HTTP_KEY / HERMES_API_KEY:
133
+ napcat config set wake_http_url http://127.0.0.1:8642
134
+ napcat config set wake_http_key <API_SERVER_KEY>
135
+ napcat config set wake_new_message_idle_seconds 600
136
+ ```
137
+
138
+ To enable the Hermes HTTP API server (appends to `~/.hermes/.env` and restarts
139
+ the `hermes-gateway.service` systemd unit), answer "y" during `napcat setup`, or
140
+ set `API_SERVER_ENABLED=true` + `API_SERVER_KEY` in `~/.hermes/.env` yourself and
141
+ `sudo systemctl restart hermes-gateway.service`.
142
+
143
+ ### Manual / debug
144
+
145
+ ```bash
146
+ napcat wake # reason: manual, contextual default prompt
147
+ napcat wake --reason AT_ME --prompt "hello"
148
+ napcat wake --transport cli # force a transport for this wake
149
+ napcat wake --dry-run # render the HTTP request + CLI command without executing
150
+ napcat wake test # per-transport configured + reachable probe
151
+ napcat wake sessions # list Hermes sessions (HTTP backend)
152
+ grep '\[WAKE\]' ~/.napcat-data/daemon.log # see when/why/how wakes fired
153
+ ```
154
+
155
+ The agent replies via `napcat send` / `napcat reply` (or the skills-fs write
156
+ path) — see `napcat_cli/data/SKILL.md`. Legacy `wake_command` shell strings still
157
+ run as a last-resort escape hatch when no backend is configured.
158
+
159
+ ---
160
+
161
+ ## Environment Variables
162
+
163
+ | Variable | Default | Description |
164
+ |----------|---------|-------------|
165
+ | `NAPCAT_API_URL` | `http://127.0.0.1:18801` | NapCat HTTP endpoint |
166
+ | `NAPCAT_TOKEN` | — | API auth token |
167
+ | `NAPCAT_DATA_DIR` | `~/.napcat-data` | Data directory |
168
+
169
+ ---
170
+
171
+ ## skills-fs Integration
172
+
173
+ The daemon runs an HTTP provider server (port 18820/18821) that skills-fs calls
174
+ to read/write NapCat API endpoints through the virtual filesystem.
175
+
176
+ When `skills_fs_enabled` is true in `daemon.json`, the daemon spawns skills-fs
177
+ automatically with the configured mountpoint and config file.
178
+
179
+ Manual start:
180
+
181
+ ```bash
182
+ skills-fs fuse --config ~/.napcat-data/skills-fs.json \
183
+ --mountpoint ~/.napcat-data/skills/napcat-cli --allow-other
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Development
189
+
190
+ ```
191
+ napcat-cli/
192
+ ├── napcat_cli/ # Installable package
193
+ │ ├── cli.py # CLI entry point
194
+ │ ├── wake.py # Wake command-template renderer
195
+ │ ├── wake_backend.py # Generic HTTP/CLI wake transports + Waker (auto-fallback)
196
+ │ ├── wake_presets.py # Hermes/custom/none presets -> Waker
197
+ │ ├── wake_orchestrator.py # Debounce, cooldown, backlog sweep, contextual prompts
198
+ │ ├── setup_wizard.py # Setup wizard
199
+ │ ├── daemon/ # Watch daemon, schemas
200
+ │ ├── lib/ # API, config, events
201
+ │ ├── tui/ # Textual TUI
202
+ │ └── data/ # SKILL.md, persona.md
203
+ ├── pyproject.toml
204
+ ├── tests/
205
+ ├── skills-fs/ # Go submodule
206
+ └── tools/ # Dev utilities
207
+ ```
208
+
209
+ ```bash
210
+ python -m pytest tests/ -v
211
+ python -m build --wheel
212
+ uv build && uv publish
213
+ ```
214
+
215
+ ---
216
+
217
+ ## License
218
+
219
+ MIT
@@ -0,0 +1,208 @@
1
+ # napcat-cli
2
+
3
+ Standalone CLI and daemon for NapCat QQ bot management with skills-fs integration.
4
+
5
+ > 📝 **介绍博文:** [napcat-cli 群配置与管理速查](https://yvxi.pages.dev/blog/napcat-cli-group-config/) — 从零配置、群消息收发、Agent Wake 的完整链路。
6
+
7
+ ---
8
+
9
+ napcat-cli provides a CLI for all NapCat API operations, a WebSocket daemon
10
+ that bridges to a skills-fs HTTP provider, and an agent wake-up mechanism for
11
+ integrating with Hermes or other AI agents.
12
+
13
+ ```bash
14
+ napcat send group 123456 -m "Hello"
15
+ napcat send private 987654 -m "Hi"
16
+ napcat recall 1001
17
+ napcat events --limit 10
18
+ napcat daemon start
19
+ napcat wake --reason NEW_MESSAGE
20
+ ```
21
+
22
+ ---
23
+
24
+ ## Commands
25
+
26
+ | Command | Description |
27
+ |---------|-------------|
28
+ | `napcat api <endpoint>` | Raw API access (like `gh api`) |
29
+ | `napcat send group <id> -m "msg"` | Send group message |
30
+ | `napcat send private <id> -m "msg"` | Send private message |
31
+ | `napcat reply <id> -m "msg"` | Reply to a message |
32
+ | `napcat recall <msg_id>` | Recall a message |
33
+ | `napcat group <sub>` | Group list, members, settings |
34
+ | `napcat friend <sub>` | Friend list, info |
35
+ | `napcat file <sub>` | File upload, download, list |
36
+ | `napcat events` | Read events from SQLite |
37
+ | `napcat alerts [--clear]` | Pending alerts |
38
+ | `napcat status` | Bot online status |
39
+ | `napcat config get/set` | Configuration management |
40
+ | `napcat daemon start/stop/status/restart` | Watch daemon |
41
+ | `napcat fs tree` | Skills-fs directory tree |
42
+ | `napcat wake [--reason R] [--prompt P] [--transport T] [--dry-run]` | Wake the configured agent (HTTP/CLI, auto-fallback) |
43
+ | `napcat setup` | Interactive setup wizard |
44
+ | `napcat phone` | Textual phone-style TUI |
45
+
46
+ ---
47
+
48
+ ## Setup
49
+
50
+ ```bash
51
+ uv tool install napcat-cli
52
+ napcat setup # interactive — guides token, data dir, skills-fs, wake
53
+ napcat daemon start
54
+ ```
55
+
56
+ The setup wizard writes two config files:
57
+
58
+ - `<data_dir>/config.json` — API URL, token, self_id, ports, triggers
59
+ - `<data_dir>/daemon.json` — All fields consumed by `watch.py` including `skills_fs_*` settings
60
+
61
+ Non-interactive mode uses defaults:
62
+
63
+ ```bash
64
+ napcat setup --non-interactive # no prompts, validates token
65
+ napcat setup --yes # skip token validation
66
+ napcat setup --force # overwrite existing config
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Agent Wake
72
+
73
+ When a notable QQ event arrives, the daemon wakes an external agent (Hermes by
74
+ default) carrying a **contextual prompt** so it can read the inbox and reply.
75
+ The wake mechanism is **generic and pluggable** — Hermes is just the default
76
+ preset; any HTTP endpoint or shell command works.
77
+
78
+ ### Two transports, auto-fallback
79
+
80
+ | Transport | When it's used | Needs |
81
+ |-----------|----------------|-------|
82
+ | **CLI one-shot** (default) | Always available | `hermes` on PATH |
83
+ | **HTTP API server** | Opt-in (best latency, idempotent, in-session) | `wake_http_url` + `wake_http_key` |
84
+
85
+ `wake_primary=auto` tries HTTP first (if configured + reachable), else falls back
86
+ to the CLI one-shot. The Hermes CLI backend runs
87
+ `hermes --continue <session> -z "<prompt>" --yolo --pass-session-id`; the HTTP
88
+ backend POSTs to `POST /api/sessions/{id}/chat` (verified per the Hermes API
89
+ docs), with `Authorization: Bearer <key>` and an `Idempotency-Key` header.
90
+
91
+ ### Event routing
92
+
93
+ | Trigger | Behavior |
94
+ |---------|----------|
95
+ | `AT_ME`, `REPLY_TO_ME` | Near-immediate wake (cooldown bypassed), with who/where/text in the prompt |
96
+ | `GROUP_TRIGGER`, `PRIVATE_TRIGGER` | Debounced wake |
97
+ | `NEW_MESSAGE` (not @) | Tracked, not woken; if unread longer than `wake_new_message_idle_seconds` → a `NEW_MESSAGE_BACKLOG` wake |
98
+ | `NEW_FRIEND`, `NEW_REQUEST`, `BOT_BANNED`, `NEW_POKE`, `GROUP_ADMIN_CHANGE`, `NEW_GROUP_MEMBER`, `BOT_OFFLINE`, … | Debounced + cooldown-bounded wake so the agent perceives them within a reasonable window |
99
+
100
+ Debounce (`wake_debounce_seconds`, default 3) coalesces a burst into one wake;
101
+ cooldown (`wake_cooldown_seconds`, default 30) suppresses repeats. Every wake is
102
+ logged to `daemon.log` as `[WAKE] trigger / queued / deliver / reply` lines
103
+ (including transport, elapsed time, and the agent's reply), and `daemon.log` is
104
+ size-rotated (2 MB × 5) so it can't fill the disk.
105
+
106
+ ### Configure
107
+
108
+ The easiest path is the wizard:
109
+
110
+ ```bash
111
+ napcat setup # choose Hermes preset; CLI one-shot by default, HTTP opt-in
112
+ ```
113
+
114
+ Or set keys directly:
115
+
116
+ ```bash
117
+ napcat config set wake_enabled true
118
+ napcat config set wake_preset hermes # hermes | custom | none
119
+ napcat config set wake_session napcat-qq
120
+ napcat config set wake_primary auto # auto | http | cli
121
+ # HTTP (optional). Key also readable from NAPCAT_WAKE_HTTP_KEY / HERMES_API_KEY:
122
+ napcat config set wake_http_url http://127.0.0.1:8642
123
+ napcat config set wake_http_key <API_SERVER_KEY>
124
+ napcat config set wake_new_message_idle_seconds 600
125
+ ```
126
+
127
+ To enable the Hermes HTTP API server (appends to `~/.hermes/.env` and restarts
128
+ the `hermes-gateway.service` systemd unit), answer "y" during `napcat setup`, or
129
+ set `API_SERVER_ENABLED=true` + `API_SERVER_KEY` in `~/.hermes/.env` yourself and
130
+ `sudo systemctl restart hermes-gateway.service`.
131
+
132
+ ### Manual / debug
133
+
134
+ ```bash
135
+ napcat wake # reason: manual, contextual default prompt
136
+ napcat wake --reason AT_ME --prompt "hello"
137
+ napcat wake --transport cli # force a transport for this wake
138
+ napcat wake --dry-run # render the HTTP request + CLI command without executing
139
+ napcat wake test # per-transport configured + reachable probe
140
+ napcat wake sessions # list Hermes sessions (HTTP backend)
141
+ grep '\[WAKE\]' ~/.napcat-data/daemon.log # see when/why/how wakes fired
142
+ ```
143
+
144
+ The agent replies via `napcat send` / `napcat reply` (or the skills-fs write
145
+ path) — see `napcat_cli/data/SKILL.md`. Legacy `wake_command` shell strings still
146
+ run as a last-resort escape hatch when no backend is configured.
147
+
148
+ ---
149
+
150
+ ## Environment Variables
151
+
152
+ | Variable | Default | Description |
153
+ |----------|---------|-------------|
154
+ | `NAPCAT_API_URL` | `http://127.0.0.1:18801` | NapCat HTTP endpoint |
155
+ | `NAPCAT_TOKEN` | — | API auth token |
156
+ | `NAPCAT_DATA_DIR` | `~/.napcat-data` | Data directory |
157
+
158
+ ---
159
+
160
+ ## skills-fs Integration
161
+
162
+ The daemon runs an HTTP provider server (port 18820/18821) that skills-fs calls
163
+ to read/write NapCat API endpoints through the virtual filesystem.
164
+
165
+ When `skills_fs_enabled` is true in `daemon.json`, the daemon spawns skills-fs
166
+ automatically with the configured mountpoint and config file.
167
+
168
+ Manual start:
169
+
170
+ ```bash
171
+ skills-fs fuse --config ~/.napcat-data/skills-fs.json \
172
+ --mountpoint ~/.napcat-data/skills/napcat-cli --allow-other
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Development
178
+
179
+ ```
180
+ napcat-cli/
181
+ ├── napcat_cli/ # Installable package
182
+ │ ├── cli.py # CLI entry point
183
+ │ ├── wake.py # Wake command-template renderer
184
+ │ ├── wake_backend.py # Generic HTTP/CLI wake transports + Waker (auto-fallback)
185
+ │ ├── wake_presets.py # Hermes/custom/none presets -> Waker
186
+ │ ├── wake_orchestrator.py # Debounce, cooldown, backlog sweep, contextual prompts
187
+ │ ├── setup_wizard.py # Setup wizard
188
+ │ ├── daemon/ # Watch daemon, schemas
189
+ │ ├── lib/ # API, config, events
190
+ │ ├── tui/ # Textual TUI
191
+ │ └── data/ # SKILL.md, persona.md
192
+ ├── pyproject.toml
193
+ ├── tests/
194
+ ├── skills-fs/ # Go submodule
195
+ └── tools/ # Dev utilities
196
+ ```
197
+
198
+ ```bash
199
+ python -m pytest tests/ -v
200
+ python -m build --wheel
201
+ uv build && uv publish
202
+ ```
203
+
204
+ ---
205
+
206
+ ## License
207
+
208
+ MIT
@@ -0,0 +1,95 @@
1
+ # Agent Wake — Hermes (and other agents)
2
+
3
+ napcat-cli wakes an external agent when notable QQ events arrive, carrying a
4
+ contextual prompt. **Hermes is the default preset, not a hard dependency** — the
5
+ wake layer is generic (HTTP or shell), so any agent works.
6
+
7
+ ## How a wake flows
8
+
9
+ ```
10
+ QQ event → EventProcessor._wake(reason, event)
11
+ → WakeOrchestrator.submit() [debounce + cooldown + backlog tracking]
12
+ → Waker.wake(prompt) [HTTP first if configured, else CLI]
13
+ → agent turn runs in session `wake_session` (e.g. napcat-qq)
14
+ ```
15
+
16
+ Each step is logged to `daemon.log` with a `[WAKE]` prefix:
17
+
18
+ ```
19
+ [2026-07-22 00:12:03] [WAKE] trigger reason=AT_ME who=Alice(123) where=group456 text='在吗'
20
+ [2026-07-22 00:12:03] [WAKE] queued reason=AT_ME pending=1 debounce=1.0s primary=auto
21
+ [2026-07-22 00:12:05] [WAKE] deliver reason=AT_ME transport=cli ok=True elapsed=2.1s :: exit=0
22
+ [2026-07-22 00:12:05] [WAKE] reply reason=AT_ME transport=cli: 在的,怎么了?
23
+ ```
24
+
25
+ `daemon.log` is size-rotated (2 MB × 5) so it can't fill the disk.
26
+
27
+ ## Transports
28
+
29
+ | Transport | Hermes target | Needs | Notes |
30
+ |-----------|---------------|-------|-------|
31
+ | `http` | `POST /api/sessions/{id}/chat` | `wake_http_url` + `wake_http_key` | Best latency, idempotent, injects into a live session; requires the API server enabled |
32
+ | `cli` | `hermes --continue <session> -z "<prompt>" --yolo --pass-session-id` | `hermes` on PATH | Zero infrastructure; spawns a one-shot process per wake |
33
+
34
+ `wake_primary=auto` (default) tries HTTP first when configured + reachable,
35
+ otherwise falls back to CLI. Force one with `napcat wake --transport http|cli`.
36
+
37
+ ## Enable the Hermes HTTP API server (opt-in)
38
+
39
+ The API server is off by default. To use the HTTP transport:
40
+
41
+ 1. Append to `~/.hermes/.env` (append-only — don't rewrite):
42
+ ```dotenv
43
+ API_SERVER_ENABLED=true
44
+ API_SERVER_KEY=<random 64-hex>
45
+ ```
46
+ 2. Restart the gateway (systemd, passwordless sudo):
47
+ ```bash
48
+ sudo systemctl restart hermes-gateway.service
49
+ ```
50
+ This briefly interrupts the messaging platforms the gateway serves.
51
+ 3. Configure napcat-cli:
52
+ ```bash
53
+ napcat config set wake_http_url http://127.0.0.1:8642
54
+ napcat config set wake_http_key <same API_SERVER_KEY>
55
+ # optional: pin a specific session id instead of resolving by name
56
+ napcat config set wake_http_session_id <session-id>
57
+ ```
58
+ `napcat setup` does all three interactively when you answer "y" to the
59
+ HTTP-enable prompt.
60
+
61
+ ### Verified request shape
62
+
63
+ ```bash
64
+ curl -X POST http://127.0.0.1:8642/api/sessions/$SESSION_ID/chat \
65
+ -H "Authorization: Bearer $API_SERVER_KEY" \
66
+ -H "Idempotency-Key: napcat-AT_ME-1700000000" \
67
+ -H "Content-Type: application/json" \
68
+ -d '{"input":"你在群里被 @ 了…请查看并回复。"}'
69
+ ```
70
+
71
+ If `wake_http_session_id` is unset, the backend resolves it by name via
72
+ `GET /api/sessions`. Docs: <https://hermes-agent.nousresearch.com/docs/user-guide/features/api-server>
73
+
74
+ ## Event routing & timing
75
+
76
+ | Reason | Wake? | Timing |
77
+ |--------|-------|--------|
78
+ | `AT_ME`, `REPLY_TO_ME` | yes | near-immediate (debounce ≤1 s), **cooldown bypassed** |
79
+ | `GROUP_TRIGGER`, `PRIVATE_TRIGGER` | yes | debounced |
80
+ | `NEW_MESSAGE` (not @) | tracked only | a `NEW_MESSAGE_BACKLOG` wake fires if unread > `wake_new_message_idle_seconds` (default 600) |
81
+ | `NEW_FRIEND`, `NEW_REQUEST`, `BOT_BANNED`, `NEW_POKE`, `GROUP_ADMIN_CHANGE`, `NEW_GROUP_MEMBER`, `MY_MESSAGE_RECALLED`, `BOT_KICKED_FROM_GROUP`, `GROUP_DISBANDED`, `BOT_OFFLINE`, `HEALTH_CHECK_OFFLINE` | yes | debounced + cooldown-bounded |
82
+
83
+ Tuning keys: `wake_debounce_seconds` (default 3), `wake_cooldown_seconds`
84
+ (default 30), `wake_new_message_idle_seconds` (default 600).
85
+
86
+ ## Troubleshooting
87
+
88
+ - **`napcat wake test`** — reports per-transport configured/reachable and whether
89
+ `hermes` is on PATH.
90
+ - **No wake fires** — check `wake_enabled` is true and `wake_preset` ≠ `none`;
91
+ grep `[WAKE]` in `daemon.log`. `disabled, skip` means `wake_enabled=false`.
92
+ - **HTTP 401 / unreachable** — `auto` falls back to CLI automatically; to use
93
+ HTTP, confirm `API_SERVER_ENABLED=true` and the gateway was restarted.
94
+ - **Legacy `wake_command`** still runs as a last-resort escape hatch when no
95
+ backend is configured (back-compat for `echo … >> .agent-wake` configs).
@@ -0,0 +1,3 @@
1
+ """napcat-cli — Standalone CLI and daemon for NapCat QQ bot management."""
2
+
3
+ __version__ = "2.0.0"