Files
xianyu-hunter-hermes-skill/skill/xianyu-hunter-monitor/references/web-task-editing-scheduling-ai-optimize-2026-05.md
T

134 lines
5.2 KiB
Markdown

# Web Task Editing, Scheduling, and AI-Optimize UI (2026-05)
Session learning from extending BOSS's local `xianyu-hunter` fork at:
```text
/Users/chick/.Hermes/workspace/research/xianyu-hunter
```
## Feature shape implemented
When BOSS asks for Web后台 task management instead of Hermes-only CLI control, keep the product shape focused on monitoring/analysis-only:
- Web task modal supports both create and edit.
- Existing tasks can be edited only when not running.
- Task form supports:
- search keywords (`queries`)
- price min/max
- region
- personal seller toggle
- max pages
- `maxItems` / 单次最大商品寻找量
- custom requirements
- coarse/fine prompts
- schedule enabled + interval minutes
- AI optimize/current-form generation
- Save modes:
- `autoStart:false` = 手动新增任务但不立即采集
- save + run = create and start immediately
- edit + reset run = save then rerun with old products cleared
- Keep seller chat disabled. Scheduled/background runs must still stop at collection + local prefilter/detail collection and never auto-contact sellers.
## Backend/API pattern
Good API additions:
```text
PUT /api/tasks/:id edit task config (reject while running)
POST /api/tasks/optimize generate optimized config from current form
POST /api/tasks accepts autoStart:false
POST /api/tasks/:id/start accepts { reset:true }
```
Task config should normalize legacy and new schedule shapes:
```js
const existingSchedule = config.schedule || {};
const scheduleEnabled = config.scheduleEnabled ?? existingSchedule.enabled ?? false;
const scheduleIntervalMinutes = config.scheduleIntervalMinutes ?? existingSchedule.intervalMinutes ?? 0;
```
`maxItems` should be enforced after each query's dedupe and before fine detail fetch:
```js
const remaining = Math.max(0, (task.config.maxItems || 60) - task.products.raw.length);
const accepted = deduped.slice(0, remaining);
task.products.raw.push(...accepted);
if (task.products.raw.length >= (task.config.maxItems || 60)) break;
await fineFilter(task.products.coarseFiltered.slice(0, task.config.maxItems || 60), ...)
```
Scheduler pattern:
- `TaskManager` starts an interval timer in constructor after `_loadFromDisk()`.
- Tick every ~30s.
- For enabled schedule with due `nextRunAt`, non-running task: push a log and call `startTask(id, { reset: true, scheduled: true })`.
- On scheduled run, set `lastRunAt` and normalize next run.
## AI optimize fallback
`POST /api/tasks/optimize` can try `chatCompletion()`, but must tolerate missing AI config. If it fails, return `{ ok:true, source:'local-fallback', task }` so the UI still works.
Local fallback should generate conservative monitoring defaults:
- `maxPages`: 2
- `maxItems`: 40
- `personalSeller`: true
- requirements explicitly include: no seller contact, exclude parts/repair/wanted/rental/recycling/commercial bulk/title spam.
## Frontend/UI notes
- Reuse the create modal for editing by tracking `editingTaskId`.
- Add buttons in pipeline controls: 编辑, 复制, 继续/启动, 重新采集, 删除.
- `重新采集` should confirm because it clears current round products.
- `fillTaskForm(taskOrConfig)` avoids duplicate create/edit/duplicate mapping bugs.
- Add cache-busting version bump for `style.css` and `app.js`; also serve static files with `Cache-Control: no-store` to avoid stale dashboard assets.
## Verification recipe
Before final response:
```bash
cd /Users/chick/.Hermes/workspace/research/xianyu-hunter
node --check server.mjs && node --check lib/task.mjs && node --check public/app.js
```
Restart the exact server on port 3000. If `node tools/xianyu_ops.mjs stop` says `no-recorded-server` but port is in use, kill both the listener and parent npm process:
```bash
lsof -nP -iTCP:3000 -sTCP:LISTEN
ps -p <listener_pid> -o pid,ppid,command
kill -TERM <parent_pid> <listener_pid>
```
Then start in background and verify API:
```bash
PORT=3000 npm start
curl -sS http://127.0.0.1:3000/api/tasks | python3 -m json.tool
```
Smoke-test the new APIs with a temporary task and delete it after:
```bash
python3 - <<'PY'
import json, urllib.request
base='http://127.0.0.1:3000'
def req(method,path,data=None):
body=json.dumps(data).encode() if data is not None else None
r=urllib.request.Request(base+path,data=body,method=method,headers={'Content-Type':'application/json'})
with urllib.request.urlopen(r,timeout=30) as resp:
return json.loads(resp.read().decode())
opt=req('POST','/api/tasks/optimize',{'product':'e3-1245v3 cpu','budget':'150','currentRequirements':'只要CPU本体,排除主板套装'})
created=req('POST','/api/tasks',{**opt['task'],'name':'__api_verify_temp__','autoStart':False,'scheduleEnabled':True,'scheduleIntervalMinutes':120,'maxItems':25})
updated=req('PUT',f"/api/tasks/{created['id']}",{'name':'__api_verify_temp_updated__','queries':['e3 1245 v3 verify'],'maxItems':30,'scheduleEnabled':False,'scheduleIntervalMinutes':0})
req('DELETE',f"/api/tasks/{created['id']}")
print('ok', opt.get('source'), created['id'], updated['config']['maxItems'])
PY
```
## Pitfall
Do not leave a final user response empty after tools. If a tool result shows a port conflict or failed restart, process it immediately, continue with the fix, and give BOSS the final verified state.