feat: publish xianyu hunter hermes skill package

This commit is contained in:
2026-05-06 19:26:45 +08:00
commit 6384156097
59 changed files with 9627 additions and 0 deletions
@@ -0,0 +1,68 @@
#!/usr/bin/env node
import fs from 'fs';
const baseUrl = process.env.XIANHU_BASE_URL || 'http://127.0.0.1:3000';
const args = process.argv.slice(2);
console.error('提示:Hermes 主控模式优先使用 tools/xianyu_ops.mjs create/run;本脚本保留为兼容入口。');
function usage() {
console.log(`Usage:
node tools/create_monitor_task.mjs --name <name> --queries <q1,q2> [--price-min N] [--price-max N] [--region 地区] [--pages N] --requirements <需求>
Environment:
XIANHU_BASE_URL=http://127.0.0.1:3000
Example:
node tools/create_monitor_task.mjs --name 'Mac mini M4 监测' --queries 'Mac mini M4,macmini m4' --price-max 3300 --region 成都 --pages 2 --requirements '自用,国行,成色好,无拆修,预算3300以内,只做筛选分析,不联系卖家,交给 Hermes 分析'
`);
}
function take(flag) {
const i = args.indexOf(flag);
if (i === -1) return undefined;
return args[i + 1];
}
if (args.includes('-h') || args.includes('--help')) {
usage();
process.exit(0);
}
const name = take('--name') || `闲鱼监测-${new Date().toISOString().slice(0, 10)}`;
const queriesRaw = take('--queries');
const requirements = take('--requirements') || take('--req');
if (!queriesRaw || !requirements) {
usage();
process.exit(2);
}
const payload = {
name,
queries: queriesRaw.split(/[,]/).map(s => s.trim()).filter(Boolean),
priceMin: take('--price-min') ? Number(take('--price-min')) : null,
priceMax: take('--price-max') ? Number(take('--price-max')) : null,
region: take('--region') || '',
personalSeller: args.includes('--personal-seller'),
maxPages: take('--pages') ? Number(take('--pages')) : 3,
customRequirements: requirements,
coarsePrompt: `你是闲鱼商品监测助手。只做标题相关性初筛,目标是帮用户发现值得进一步分析的候选商品。只有标题与需求明确矛盾、明显是配件/维修/求购/租赁/广告时才排除;拿不准必须保留。返回纯JSON数组。`,
finePrompt: `你是闲鱼商品风险分析助手。根据商品详情判断是否值得用户人工查看。只做采集后的分析准备,实际深度分析由 Hermes 完成。优先标记:型号/规格不符、价格异常、疑似商家批量、维修/配件/求购、描述矛盾、成色/保修/拆修风险。拿不准可以保留,但理由必须提示待人工确认。`,
};
const res = await fetch(`${baseUrl}/api/tasks`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
const text = await res.text();
if (!res.ok) {
console.error(`HTTP ${res.status}: ${text}`);
process.exit(1);
}
try {
const data = JSON.parse(text);
console.log(JSON.stringify({ ok: true, task: { id: data.id, name: data.name, stage: data.stage }, url: `${baseUrl}/` }, null, 2));
} catch {
console.log(text);
}