feat: publish xianyu hunter hermes skill package
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
# Xianyu-hunter Hermes send_message notifications (2026-05)
|
||||
|
||||
Session learning: BOSS wanted xianyu-hunter notification settings changed from a Hermes webhook URL to a Web-visible platform selector that sends through Hermes `send_message` directly.
|
||||
|
||||
## Implementation pattern
|
||||
|
||||
- Backend file: `/Users/chick/.Hermes/workspace/research/xianyu-hunter/lib/notifier.mjs`.
|
||||
- Keep `GET/PUT /api/notify-config`, but add `targetOptions` to the returned config for UI dropdowns.
|
||||
- Use channel type `hermes-send-message` instead of `hermes-webhook`.
|
||||
- Migrate existing `hermes-webhook` channels to `hermes-send-message` and map bare `feishu` to the current Feishu DM when appropriate.
|
||||
- Server-side send implementation can spawn Hermes Agent's Python venv and call the tool handler:
|
||||
|
||||
```js
|
||||
const script = `import json\nfrom tools.send_message_tool import send_message_tool\nprint(send_message_tool({"action":"send","target":${JSON.stringify(target)},"message":${JSON.stringify(message)}}))\n`;
|
||||
const child = spawn(
|
||||
process.env.HERMES_PYTHON || '/Users/chick/.hermes/hermes-agent/venv/bin/python3',
|
||||
['-c', script],
|
||||
{ cwd: process.env.HERMES_AGENT_DIR || '/Users/chick/.hermes/hermes-agent' }
|
||||
);
|
||||
```
|
||||
|
||||
## UI pattern
|
||||
|
||||
- Frontend files: `public/app.js`, `public/index.html`.
|
||||
- In notification modal, label Hermes channel as **Hermes 平台消息**.
|
||||
- Provide a dropdown populated from `notifyConfig.targetOptions` and a separate optional custom target input.
|
||||
- Target examples:
|
||||
- `feishu:oc_3e963a150d98f254d8f38881bcfa1812`
|
||||
- `weixin:o9cq809DWSYDlvbA9pj1akncjrhY@im.wechat`
|
||||
- `weixin:o9cq808qCd1W-cIDo0iWjteE5lHY@im.wechat`
|
||||
- `qqbot` if configured
|
||||
- Bump static cache query strings (`app.js?v=...`, `style.css?v=...`) after UI edits.
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
cd /Users/chick/.Hermes/workspace/research/xianyu-hunter
|
||||
node --check server.mjs
|
||||
node --check lib/notifier.mjs
|
||||
node --check public/app.js
|
||||
node tools/xianyu_ops.mjs stop || true
|
||||
node tools/xianyu_ops.mjs start --port 3000
|
||||
curl -sS http://127.0.0.1:3000/api/notify-config | python3 -m json.tool | head -90
|
||||
```
|
||||
|
||||
Smoke-test notifier without running a real task:
|
||||
|
||||
```bash
|
||||
node --input-type=module <<'JS'
|
||||
import { sendNotifications } from './lib/notifier.mjs';
|
||||
const task = { id: 'smoke-test', name: '通知配置 smoke test' };
|
||||
const summary = {
|
||||
minScore: 75, total: 1, recommendedCount: 1, cautionCount: 0, rejectedCount: 0,
|
||||
reportPath: 'smoke-test',
|
||||
topItems: [{ title: 'xianyu-hunter 通知测试', score: 99, verdict: 'recommend', price: '测试', location: '本机', reason: '验证服务端可直接调用 Hermes send_message', href: '' }]
|
||||
};
|
||||
const config = { enabled: true, notifyOnlyGood: false, minScore: 75, channels: [{ id:'smoke-feishu', type:'hermes-send-message', name:'飞书 smoke', enabled:true, target:'feishu:oc_3e963a150d98f254d8f38881bcfa1812' }] };
|
||||
const r = await sendNotifications(task, summary, { force: true, config });
|
||||
console.log(JSON.stringify(r, null, 2));
|
||||
if (!r.ok) process.exit(1);
|
||||
JS
|
||||
```
|
||||
|
||||
## Test notification channel
|
||||
|
||||
When BOSS asks to add/test notification channels, add a Web-visible test path rather than relying on real task analysis:
|
||||
|
||||
- Backend route in `server.mjs`:
|
||||
- `POST /api/notify-test`
|
||||
- Accepts `{ config, title }` where `config` has the same shape as `/api/notify-config`.
|
||||
- Builds a fake task `{ id: 'notify-test', name: '通知渠道测试' }` plus a one-item `summary`.
|
||||
- Calls `sendNotifications(task, summary, { force: true, config: { ...config, enabled: true, notifyOnlyGood: false } })` so the test bypasses score/good-only gating.
|
||||
- Return HTTP 200 if `result.ok`, otherwise 500 with per-channel errors.
|
||||
- Frontend in `public/app.js`:
|
||||
- Add `testNotifyConfigFromForm()` beside `saveNotifyConfigFromForm()`.
|
||||
- It calls `collectNotifyConfig()`, requires at least one enabled channel, posts to `/api/notify-test`, and writes ✅/❌ per-channel results into `#notify-log`.
|
||||
- It should not require saving first; this lets BOSS test temporary target edits directly from the modal.
|
||||
- UI in `public/index.html`:
|
||||
- Add a modal footer button: `发送测试通知` wired to `testNotifyConfigFromForm()`.
|
||||
- Bump static cache query strings (`app.js?v=...`, `style.css?v=...`).
|
||||
|
||||
Verification command:
|
||||
|
||||
```bash
|
||||
curl -sS -X POST http://127.0.0.1:3000/api/notify-test \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"config":{"enabled":true,"notifyOnlyGood":false,"minScore":75,"channels":[{"id":"api-test-feishu","type":"hermes-send-message","name":"API测试飞书","enabled":true,"target":"feishu:oc_3e963a150d98f254d8f38881bcfa1812"}]},"title":"xianyu-hunter API 测试通知"}' \
|
||||
| python3 -m json.tool
|
||||
```
|
||||
|
||||
A known-good result has `ok: true` and `results[0].ok: true`; in the 2026-05 run this sent a real Feishu test message successfully.
|
||||
|
||||
|
||||
Do **not** spawn Homebrew Python such as `/Users/chick/homebrew/opt/python@3.11/bin/python3.11` for Hermes `send_message`. It may lack Hermes dependencies (`yaml`, gateway modules) and fail with:
|
||||
|
||||
```text
|
||||
Failed to load gateway config: No module named 'yaml'
|
||||
```
|
||||
|
||||
Use Hermes' own venv interpreter:
|
||||
|
||||
```text
|
||||
/Users/chick/.hermes/hermes-agent/venv/bin/python3
|
||||
```
|
||||
|
||||
You can verify it with:
|
||||
|
||||
```bash
|
||||
/Users/chick/.hermes/hermes-agent/venv/bin/python3 - <<'PY'
|
||||
import yaml
|
||||
import gateway.config
|
||||
from tools.send_message_tool import send_message_tool
|
||||
print(send_message_tool({'action':'list'}))
|
||||
PY
|
||||
```
|
||||
Reference in New Issue
Block a user