feat: publish xianyu hunter hermes skill package
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
# Web Hermes Analysis + Notifications (2026-05)
|
||||
|
||||
Session learning from extending BOSS's local `xianyu-hunter` fork with Web-visible analysis and notification controls.
|
||||
|
||||
## Product shape BOSS expects
|
||||
|
||||
When adding analysis/notification capability, make it visible in the Web dashboard, not only as backend APIs:
|
||||
|
||||
- Header button: **通知设置**.
|
||||
- Task controls: **执行分析** beside edit/duplicate/start/rerun/delete.
|
||||
- New task tab: **Hermes 分析** with recommendation/caution/reject summary and item cards.
|
||||
- Product list should show analysis verdict badges and concise reasons inline.
|
||||
- Analysis should persist into `data/tasks.json` and generate a Markdown report under `reports/`.
|
||||
|
||||
## Backend API pattern
|
||||
|
||||
Add a lightweight local analysis layer and notifier:
|
||||
|
||||
- `lib/analyzer.mjs`
|
||||
- `buildAnalysis(task, { limit })` returns `{ items, summary }`.
|
||||
- `renderAnalysisMarkdown(task, summary)` writes `reports/<task_id>-analysis.md`.
|
||||
- Include item-level `hermesAnalysis: { score, verdict, reason, flags, positives, analyzedAt }`.
|
||||
- `lib/notifier.mjs`
|
||||
- `GET /api/notify-config` and `PUT /api/notify-config` backed by `data/notify-config.json`.
|
||||
- `sendNotifications(task, summary, { force })` supports:
|
||||
- `hermes-webhook`: POST `{ message, target, source, taskId }`.
|
||||
- `bark`: POST `{ title, body, group }` to `https://api.day.app/<key>` or configured endpoint.
|
||||
- `pushplus`: POST `{ token, title, content, template:'txt' }`.
|
||||
- `webhook`: generic JSON `{ title, message, taskId }`.
|
||||
- `server.mjs`
|
||||
- `POST /api/tasks/:id/analyze` should call `taskManager.analyzeTask`, write report, persist summary, and optionally notify.
|
||||
|
||||
## TaskManager persistence details
|
||||
|
||||
- Add `getTaskFull(id)` for routes that need full in-memory task data.
|
||||
- Add `setTaskAnalysis(id, analysis)` that merges item `hermesAnalysis` into `products.fineFiltered`, stores `task.hermesAnalysis`, persists to disk, and emits `task:updated`.
|
||||
- Include `hermesAnalysis` in `_serialize`, `_serializeFull`, and `_loadFromDisk`.
|
||||
- Clear `task.hermesAnalysis = null` when resetting products/rerunning a task.
|
||||
- New/duplicated tasks should initialize `hermesAnalysis: null`.
|
||||
|
||||
## Frontend implementation details
|
||||
|
||||
- Bump asset query versions in `index.html` after changing CSS/JS to avoid stale browser cache (`style.css?v=11`, `app.js?v=11`, etc.).
|
||||
- `public/app.js` helpers:
|
||||
- `analyzeTaskNow(id)` calls `POST /api/tasks/:id/analyze` with `{ notify: true }`, then refreshes task detail.
|
||||
- `renderAnalysis()` renders empty state, stat cards, report path, and scored item cards.
|
||||
- When rendering raw product rows, map analysis from `products.fineFiltered` by `id`; raw items often do not contain the merged `hermesAnalysis` directly.
|
||||
- Preserve notification channel `id` when saving from the form; otherwise repeated saves create new channel IDs.
|
||||
|
||||
## Verification checklist
|
||||
|
||||
Run syntax checks:
|
||||
|
||||
```bash
|
||||
cd /Users/chick/.Hermes/workspace/research/xianyu-hunter
|
||||
node --check server.mjs
|
||||
node --check lib/task.mjs
|
||||
node --check lib/analyzer.mjs
|
||||
node --check lib/notifier.mjs
|
||||
node --check public/app.js
|
||||
```
|
||||
|
||||
Restart exact stale listener if `xianyu_ops.mjs stop` says `no-recorded-server` but port is still occupied:
|
||||
|
||||
```bash
|
||||
pid=$(lsof -nP -iTCP:3000 -sTCP:LISTEN -t || true)
|
||||
[ -z "$pid" ] || kill "$pid"
|
||||
node tools/xianyu_ops.mjs start --port 3000
|
||||
```
|
||||
|
||||
Smoke test APIs:
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:3000/api/notify-config | python3 -m json.tool
|
||||
curl -fsS http://127.0.0.1:3000/api/tasks -o /tmp/xh_tasks.json
|
||||
TASK=$(python3 - <<'PY'
|
||||
import json
|
||||
j=json.load(open('/tmp/xh_tasks.json'))
|
||||
print(j[0]['id'] if j else '')
|
||||
PY
|
||||
)
|
||||
curl -fsS -X POST "http://127.0.0.1:3000/api/tasks/$TASK/analyze" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"notify":false,"limit":10}' | python3 -m json.tool
|
||||
```
|
||||
|
||||
Important pitfall: piping a large `/api/tasks` response directly into `python3 - <<'PY'` consumes stdin for the script, not JSON. Save curl output to a temp file first.
|
||||
|
||||
## Model-specific scoring pitfall: E3-1245v3
|
||||
|
||||
For CPU searches like `E3-1245v3`, scoring must distinguish true target models from related models used as SEO keywords.
|
||||
|
||||
Rules added in `lib/analyzer.mjs`:
|
||||
|
||||
- If the task query indicates `E3-1245v3`, require an exact-ish match: `e3\s*-?\s*1245\s*[_-]?\s*v3`.
|
||||
- Penalize titles whose main model is another E3 v3, e.g. `E3-1275v3 ... 性能超 E3-1245v3`, because the title may only use 1245v3 as a comparison/keyword.
|
||||
- Flag failure terms beyond obvious `坏/不亮/暗病`, including `不能进系统`.
|
||||
|
||||
This reduced false recommendations in the E3-1245v3 task from related CPUs and broken parts.
|
||||
Reference in New Issue
Block a user