134 lines
5.2 KiB
Markdown
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.
|