Node.js / TypeScript SDK
当前 SDK 是服务端包 @qoniai/qoni。文档里的 @web-agent/sdk、Client、client.sessions 等旧示例已经不再对应现行 SDK。
安装与初始化
npm install @qoniai/qoniAK/SK 只能放在可信服务端,不能下发到浏览器:
import { Qoni } from "@qoniai/qoni";
const qoni = new Qoni({
accessKey: process.env.QONI_ACCESS_KEY!,
secretKey: process.env.QONI_SECRET_KEY!,
});先取得用户委托 token
WebAgent 是代表终端用户执行的运行时能力。silent 委托需要一个真实的 GenAuth 用户 ID;不要把 API key 直接传给 qoni.doAnything.run()。
const { token } = (
await qoni.delegateToken({
user: { id: process.env.QONI_USER_ID! },
products: ["doAnything"],
})
).data;products 可用 doAnything、deepResearch、webSearch、track。需要交互式授权时使用 mode: "interactive" 和 completeDelegateToken();不要自行调用 /api/v3/eak/token-exchange。
DoAnything
const run = await qoni.doAnything.run({
token,
prompt: "打开 Hacker News,列出首页前五条故事的标题和链接。",
capture: { screenshots: true },
limits: { maxDurationMinutes: 10 },
});
console.log(run.id);
for await (const event of run.events()) {
if (event.type === "progress") console.log(event.data);
if (event.type === "message") console.log(event.data.text);
}
const result = await run.wait();
console.log(result.status, result.output);run() 返回 RunHandle,不是旧版的 JSON envelope。句柄常用方法是 status()、events()、wait()、cancel() 和 interactionHandle()。复用同一个浏览器 session 时,把 run.sessionRef 传给下一次 run();重连用 qoni.doAnything.attach(run.id, { token })。
DeepResearch、WebSearch
const researchToken = (await qoni.delegateToken({
user: { id: process.env.QONI_USER_ID! },
products: ["deepResearch", "webSearch"],
})).data.token;
const research = await qoni.deepResearch.run({
token: researchToken,
prompt: "研究 2026 年浏览器自动化的主要趋势。",
depth: "standard",
limits: { maxDurationMinutes: 120 },
});
const report = await research.wait();
const search = await qoni.webSearch.run({
token: researchToken,
prompt: ["browser automation 2026"],
maxResultsPerQuery: 5,
});
const hits = await search.wait();DoAnything、DeepResearch 和 WebSearch 都用 run.id、run.events()、run.wait()、run.cancel();Track 兼容边界见下节。
WebSearch 的服务端创建接口始终返回异步 run;wait() 只是 SDK 帮你等待终态,不代表 HTTP 创建请求是同步接口。WebSearch 没有 runAsync()、refine() 或 follow-up 方法。
Track
正式 npm 0.9.0 的 Track 旧路由与当前后端不兼容。未发布修复候选改用 /track/tracks,要求显式 interval 或 daily 调度;没有 Track SSE 或问询/干预能力。候选示例、最近 50 次 checks 与任务引用见 Track,不要把它们当作 0.9.0 已发布能力。
事件与人工介入
SDK 将 wire 事件归一成语义事件:progress、message、interaction、screenshot、done,不同产品还会有各自的 phase、sectionReady、resultsReady(当前 Track 无事件流)。遇到 interaction 时,用对应句柄的 interactionHandle(event.data),不要硬编码不存在的 client.messages.intervene()。
for await (const event of run.events()) {
if (event.type !== "interaction") continue;
const interaction = run.interactionHandle(event.data);
if (interaction.can("confirm")) await interaction.confirm();
}低层 API
每个命名空间都暴露 .api 作为 wire-level escape hatch,例如 qoni.deepResearch.api.followUp()、qoni.deepResearch.api.feedback()。这些方法的字段使用后端 OpenAPI 的 snake_case 契约;优先使用上面的高层方法,只有确实需要低层端点时才使用 .api。
不要照抄的旧调用
以下名称不属于当前 @qoniai/qoni 公共高层 API:new Client({ apiKey, projectId })、client.sessions、client.events、runAsync、run_async、webSearch.refine、track.listSnapshots、track.getSnapshot、track.retryDelivery。