跳到正文

Track ​

本页说明 Track 如何按计划重复执行网页任务、查询检查记录,以及当前后端与 Node SDK 的兼容边界。

版本与部署边界

npm @qoniai/qoni@0.9.0 使用旧 /track/monitors,2026-10-08 灰度验收返回 404,不能用于当前 /track/tracks 后端。下文 HTTP 描述该后端契约;Node 示例描述未发布修复候选(Unreleased,目标版本 0.10.0),不是已发布 0.9.0 功能。使用前确认目标部署的 OpenAPI 与 SDK 发布说明。这是破坏性变更,不能作为 npm 0.9.x 的可用功能描述。下载样例仍固定官方 0.9.0,不包含候选实现。

它解决什么问题 ​

Track 为长期任务保存调度定义,通过 DoAnything 会话重复检查网页,适用于供应商价格、政策和合作伙伴门户巡检。页面目标、抽取要求和判断变化的规则写入自然语言 instructions;结果是否符合业务要求仍需应用核验。

核心能力 ​

当前后端支持定时创建、读取定义、暂停/恢复、立即执行、最近检查回查和软删除;调度和任务引用的边界见后文。

典型场景 ​

什么时候用 ​

只执行一次用 DoAnything;公开网页检索用 WebSearch。当前 Track 没有旧版结构化抽取 DSL、触发 DSL、通知渠道或对齐问询能力,不保证每次检查产生通知。

创建 Track ​

http
POST /api/v1/projects/{pid}/track/tracks
Authorization: Bearer wa_...
Content-Type: application/json
HTTP 字段说明
instructions必填,非空任务说明,最长 4000 字符;把目标 URL 与检查要求写在这里
title可选标题,最长 120 字符
schedule必填,不会从 instructions 推断,也没有 SDK 默认值

调度二选一:

  • 间隔:{"every_seconds":3600},整数秒,最短 600 秒,最长 30 天(2592000 秒)。
  • 每日:{"daily_at":"09:00","tz":"Asia/Singapore"},24 小时 HH:MM 与时区;后端会在该时刻前 0–30 分钟开始执行,不保证恰好 09:00。

不支持任意 cron、target_urls、profile_id、extraction_schema、trigger_dsl、stop_condition_dsl、tick_instructions 或 notify_channel。旧字段不能直接移植到新资源。

Node SDK ​

以下示例仅适用于未发布修复候选。

高层 prompt 原样映射为 HTTP instructions;历史句柄名称 MonitorHandle 保留,代表新的 Track 资源。

ts
// 未发布修复候选;npm 0.9.0 不支持此后端契约。
const monitor = await qoni.track.create({
  token,
  prompt: "检查 https://example.com/ 的标题变化,返回标题与来源 URL。",
  title: "示例页面巡检",
  schedule: { kind: "daily", at: "09:00", tz: "Asia/Singapore" },
});

const current = await monitor.get();
const recent = await monitor.runs({ limit: 10, offset: 0 });
console.log(recent);

创建会立即启动首次检查(kind: first_look),上面的示例只读取定义和 checks,不立即 runNow()。checks 的运行状态是 running,成功终态是 done;其他终态是 failed/expired/canceled,不同于统一 RunResult.status 的 succeeded。

手动执行前,先按精确 run ID 等待首次检查终态,并核对当前没有在途检查。检查状态读回与 runNow() 之间仍有竞态:收到 HTTP 409 task_in_progress 时保留原检查、继续查询其状态,稍后由用户明确发起新的手动执行;不要自动重试或把 409 当成成功。

间隔写成 schedule: { kind: "interval", intervalSeconds: 3600 }。候选本地校验调度范围,并以 QoniUnsupportedError 拒绝 cron 和旧 DSL、targetUrls、profileId、通知等不支持字段;不会静默忽略或转换。

方法候选行为与边界
get()读取 Track 定义
pause() / resume()写入 status: paused/active;暂停不取消正在执行的任务
refine(patch)只改 title/schedule,保持原始 instructions;改变监控意图请新建 Track
runNow()返回 trackId/sessionId/runId 真实任务引用;创建的 first_look 或当前检查未结束时返回 409 task_in_progress;HTTP 202 只表示受理,需查询检查终态
runs({ limit?, offset? })读取最近 50 次 checks,按最新优先;参数仅对这个窗口本地分页,不是全历史分页
run(runId)在最近 50 次 checks 内精确查找;未找到会失败,不退回任意 DoAnything 任务读取
delete()软删除 Track 并停止后续调度,不停止当前 run

当前后端没有 Track SSE 或问询/干预接口。候选的 events()(开始迭代时)、interactionHandle()、track.api.events()、track.api.intervene() 都本地抛 QoniUnsupportedError,零 HTTP。Track 权限不能授权 DoAnything 的人工操作;需要独立取得 DoAnything 授权并处理对应任务。

首次 get() 读回时,捕获一次 current.lastTaskId(HTTP last_task_id)作为原首检 ID。checking 表示最新检查是否仍在运行(后端 pending/running/waiting 统一显示为 running);仅 checking: false 不足以判业务成功,仍按原 ID 查 checks 的终态与输出。暂停/恢复或后续读回不能替换已捕获的首检 ID。

检查记录 ​

HTTP checks.items 只含最近 50 条,SDK runs() 对字段名作 camelCase 转换,不改 status/outcome 的值:

HTTP 字段(SDK 字段)输出与边界
run_id(runId)该次检查的精确任务 ID;后续查询保留这个 ID
kindfirst_look、scheduled 或 manual
status在途为 running;终态为 done/failed/expired/canceled
outcomechanged、same、needs_you,尚无报告时可为 null;needs_you 不提供 Track 问询回复 API
headline报告摘要;较旧记录可回退到回答首行,也可能为 null
answer检查回答,可为 null;业务需核验内容及来源
failurefailed/expired 的失败详情,否则为 null;不能用空失败详情推断成功
created_at/ended_at(createdAt/endedAt)创建/结束时间,尚未结束时 ended_at 为 null
step在途检查最近的动作标签,无记录时可为 null

失败与自动暂停 ​

响应/条件处理
创建时 409 track_limit每项目每用户最多保留 20 个 Track,paused 也计入;删除不再需要的 Track 才释放名额
执行时 409 task_in_progress原任务仍在途,按原 ID 读回;不自动重试
422 invalid_track服务层发现无效调度或任务定义;修正输入。请求模型的字段/类型校验也可能返回 422
404 track_not_foundTrack 不存在、已软删除或不在调用者可见范围;不要改用其他资源 ID
连续 3 次检查没有产出 track_report调度器在后续调度检查时自动暂停;读回状态,查看对话与失败记录后再决定是否恢复

成功的报告会清零无报告计数;done 不替代报告与业务输出核验。run(runId) 在最近 50 条窗口找不到记录时,是候选 SDK 的本地 not_found(无 HTTP status),应与后端 track_not_found 区分。

原生 HTTP 生命周期 ​

http
GET    /api/v1/projects/{pid}/track/tracks
GET    /api/v1/projects/{pid}/track/tracks/{track_id}
PATCH  /api/v1/projects/{pid}/track/tracks/{track_id}
DELETE /api/v1/projects/{pid}/track/tracks/{track_id}
POST   /api/v1/projects/{pid}/track/tracks/{track_id}/run_now
GET    /api/v1/projects/{pid}/track/tracks/{track_id}/checks

PATCH 直接传资源字段,例如 {"status":"paused"},不用旧 action/patch 包装。原生接口可更新 instructions/title/schedule/status;SDK 高层 refine() 为保留原意,只开放 title/schedule。checks 返回 items,最多最近 50 次记录;没有旧 /runs/{run_id} 全历史详情接口。

检查结果与下一步 ​

创建后读回定义与调度;runNow() 后用返回的精确 run ID 查检查记录并等待终态,再核验输出与来源。尚未出现检查记录或只有 202 都不算任务成功。删除 Track 后仍需核对当前任务状态。

候选发布前,正式 0.9.0 调用方不能靠换一个 SDK 参数解决旧路由差额。文件产物读取见 Qoni SDK;需要登录态复用时先核对 Profiles 的支持边界。