# Xianyu Per-Item Notifications + Feishu Clickable Links — 2026-05 ## Context BOSS reported two UX issues after initial link normalization: 1. Feishu still did not show reliable clickable product links. 2. Notifications should behave like the original project: each product should be pushed as its own message, not bundled into one long report-style message. A key pitfall was that the running `server.mjs` process still used the old notifier module until the service was restarted. Always restart the Node service after patching notification rendering. ## Implemented pattern `lib/notifier.mjs` now defaults to: ```json { "perItem": true, "maxNotifyItems": 10 } ``` Notification rendering now: - Selects candidates by `verdict === 'recommend' || score >= minScore`. - Sends up to `maxNotifyItems` items. - Sends one message per item when `perItem !== false`. - Uses explicit Feishu-compatible Markdown link syntax: ```md [🔗 打开闲鱼商品](https://h5.m.goofish.com/item?id=) 备用链接:https://h5.m.goofish.com/item?id= ``` The backup plain h5 URL is kept because Feishu/clients sometimes vary in Markdown rendering. ## Verification After patching, run: ```bash cd /Users/chick/.Hermes/workspace/research/xianyu-hunter node --check lib/notifier.mjs && node --check server.mjs ``` Dry-run without sending: ```bash node --input-type=module - <<'NODE' import fs from 'fs'; import { buildAnalysis } from './lib/analyzer.mjs'; import { sendNotifications } from './lib/notifier.mjs'; const data = JSON.parse(fs.readFileSync('data/tasks.json','utf8')); const task = data.at(-1); const analysis = buildAnalysis(task, { limit: 3 }); const res = await sendNotifications(task, { ...analysis.summary, maxNotifyItems: 3 }, { force: true, config: { enabled: true, notifyOnlyGood: false, minScore: 0, perItem: true, maxNotifyItems: 3, channels: [] } }); console.log(res.messages.join('\n\n---\n\n')); NODE ``` Restart exact Node server process, then test through API: ```bash # kill old node server.mjs PID, then start tracked/background process PORT=3000 node server.mjs curl -sS -X POST http://127.0.0.1:3000/api/notify-test \ -H 'Content-Type: application/json' \ -d '{"title":"xianyu-hunter 单商品链接测试"}' | python3 -m json.tool ``` Expected API response includes: - `perItem: true` - `messages: [ ... ]` - message text contains `[🔗 打开闲鱼商品](https://h5.m.goofish.com/item?id=...)` - `results[].itemIndex` for each individual pushed item ## Notes - `cfg.perItem === false` can still be used to send a bundled message for webhook channels if needed. - `chatUrl` should remain a desktop IM URL; only user-facing product links use h5 mobile URLs.