4.5 KiB
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.jsonand generate a Markdown report underreports/.
Backend API pattern
Add a lightweight local analysis layer and notifier:
lib/analyzer.mjsbuildAnalysis(task, { limit })returns{ items, summary }.renderAnalysisMarkdown(task, summary)writesreports/<task_id>-analysis.md.- Include item-level
hermesAnalysis: { score, verdict, reason, flags, positives, analyzedAt }.
lib/notifier.mjsGET /api/notify-configandPUT /api/notify-configbacked bydata/notify-config.json.sendNotifications(task, summary, { force })supports:hermes-webhook: POST{ message, target, source, taskId }.bark: POST{ title, body, group }tohttps://api.day.app/<key>or configured endpoint.pushplus: POST{ token, title, content, template:'txt' }.webhook: generic JSON{ title, message, taskId }.
server.mjsPOST /api/tasks/:id/analyzeshould calltaskManager.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 itemhermesAnalysisintoproducts.fineFiltered, storestask.hermesAnalysis, persists to disk, and emitstask:updated. - Include
hermesAnalysisin_serialize,_serializeFull, and_loadFromDisk. - Clear
task.hermesAnalysis = nullwhen resetting products/rerunning a task. - New/duplicated tasks should initialize
hermesAnalysis: null.
Frontend implementation details
- Bump asset query versions in
index.htmlafter changing CSS/JS to avoid stale browser cache (style.css?v=11,app.js?v=11, etc.). public/app.jshelpers:analyzeTaskNow(id)callsPOST /api/tasks/:id/analyzewith{ 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.fineFilteredbyid; raw items often do not contain the mergedhermesAnalysisdirectly.
- Preserve notification channel
idwhen saving from the form; otherwise repeated saves create new channel IDs.
Verification checklist
Run syntax checks:
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:
pid=$(lsof -nP -iTCP:3000 -sTCP:LISTEN -t || true)
[ -z "$pid" ] || kill "$pid"
node tools/xianyu_ops.mjs start --port 3000
Smoke test APIs:
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.