@qoniai/qoni 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -4
- package/README.md +28 -14
- package/README.zh-CN.md +21 -14
- package/dist/index.cjs +208 -110
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -4
- package/dist/index.d.ts +9 -4
- package/dist/index.js +208 -109
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/qoni-sdk/SKILL.md +6 -6
- package/skills/qoni-sdk/agents/openai.yaml +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,65 @@ This project follows semantic versioning. Before `1.0.0`, minor versions may
|
|
|
6
6
|
include SDK API changes, while patch versions are reserved for backward
|
|
7
7
|
compatible fixes.
|
|
8
8
|
|
|
9
|
+
## 0.4.2 - 2026-09-09
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Require authoritative run details when settling `wait()`: preserve detail
|
|
14
|
+
errors and reject unconfirmed terminal states instead of inventing success.
|
|
15
|
+
- Reuse terminal details read after a clean stream close and resume from every
|
|
16
|
+
wire event cursor, including frames filtered from semantic events.
|
|
17
|
+
- Propagate wait cancellation to detail and artifact-list GETs. Bound complete
|
|
18
|
+
JSON, NDJSON, binary, and HTTP error body reads by the request timeout, cancel
|
|
19
|
+
stalled readers, and discard late responses without starting replacement runs.
|
|
20
|
+
- Clean up wait timers and SSE abort listeners. Cancel idle SSE readers directly
|
|
21
|
+
and release their locks without waiting indefinitely for source cancellation.
|
|
22
|
+
- Retry HTTP 408 stream failures within the configured reconnect budget and stop
|
|
23
|
+
delivering buffered events after cancellation.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Optional abort signals on product run-detail and artifact-list wire reads;
|
|
28
|
+
existing calls without a signal remain compatible.
|
|
29
|
+
|
|
9
30
|
## Unreleased
|
|
10
31
|
|
|
32
|
+
### Breaking
|
|
33
|
+
|
|
34
|
+
- Rename the public SDK constructor from its previous longer name to `Qoni`.
|
|
35
|
+
The previous constructor export has been removed.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- The default Qoni host is now `https://dashboard.qoni.ai` (was
|
|
40
|
+
`https://anima.eazo.ai/dashboard`). Callers that never passed an explicit `host`
|
|
41
|
+
reach a different control plane after upgrading. Note that the new default has
|
|
42
|
+
no `/dashboard` path segment — pass `host` explicitly for private or local
|
|
43
|
+
deployments.
|
|
44
|
+
- Service resolution no longer fetches the runtime-config document to answer a
|
|
45
|
+
Qoni base URL. It never read the result for that service, but it did require
|
|
46
|
+
the fetch to succeed, so an unavailable discovery endpoint failed every Qoni
|
|
47
|
+
call. Discovery is still fetched lazily for `genauth` / `gumem` / `webagent`,
|
|
48
|
+
which do read it.
|
|
49
|
+
- Signed Qoni requests always stay on the configured control-plane host. Service
|
|
50
|
+
resolution no longer follows `eakBaseUrl` from the runtime config for the
|
|
51
|
+
Qoni service, because AK/SK signatures are scoped to that endpoint and a
|
|
52
|
+
cross-origin runtime URL can strip `Authorization` on redirect or disclose
|
|
53
|
+
credentials to an unintended origin.
|
|
54
|
+
- `unstableRequest()` without a `token` now signs the call with AK/SK instead of
|
|
55
|
+
sending it unauthenticated. Caller-supplied `authorization`, `content-type`,
|
|
56
|
+
`date` and `x-authing-*` headers are dropped so they cannot corrupt the
|
|
57
|
+
signature.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- The previous default host was unreachable for SDK API calls. A client created
|
|
62
|
+
as `new Qoni({ accessKey, secretKey })` now reaches the live control plane.
|
|
63
|
+
- Abandoning an event iterator no longer leaks its connection. Leaving
|
|
64
|
+
`for await (const event of run.events())` through a `break` now cancels the
|
|
65
|
+
response body before releasing the reader lock, returning the socket to the
|
|
66
|
+
connection pool.
|
|
67
|
+
|
|
11
68
|
### Added
|
|
12
69
|
|
|
13
70
|
- `RunHandle.events()` and `wait()` accept `onWireEvent` and `onReconnect`
|
|
@@ -23,8 +80,8 @@ compatible fixes.
|
|
|
23
80
|
### Breaking
|
|
24
81
|
|
|
25
82
|
- Rename the package from its previous product name to `@qoniai/qoni`.
|
|
26
|
-
- Rename the primary constructor and all branded exports to `
|
|
27
|
-
|
|
83
|
+
- Rename the primary constructor and all branded exports to `Qoni` and the
|
|
84
|
+
corresponding `Qoni*` types, constants, and error classes.
|
|
28
85
|
- Rename the product namespace to `client.qoni` and environment variables to
|
|
29
86
|
`QONI_*`. The current server wire contract remains unchanged: SDK gateway
|
|
30
87
|
routes stay under `/api/v3/eak/*`, delegation tokens retain
|
|
@@ -207,7 +264,7 @@ Initial public release of `@qoniai/qoni`.
|
|
|
207
264
|
|
|
208
265
|
### What ships
|
|
209
266
|
|
|
210
|
-
- Server-side `
|
|
267
|
+
- Server-side `Qoni` constructor for Qoni Agent delegation and product
|
|
211
268
|
runtime calls.
|
|
212
269
|
- Runtime service discovery from the Qoni Console gateway through
|
|
213
270
|
`GET /api/v3/eak/runtime-config`.
|
|
@@ -226,7 +283,7 @@ Initial public release of `@qoniai/qoni`.
|
|
|
226
283
|
|
|
227
284
|
### Compatibility
|
|
228
285
|
|
|
229
|
-
- `Qoni`
|
|
286
|
+
- `Qoni` is the public SDK constructor.
|
|
230
287
|
- `delegateAgent` and `completeDelegateAgent` remain available as deprecated
|
|
231
288
|
aliases for older integrations, but new integrations should use
|
|
232
289
|
`delegateToken`.
|
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Agents that perform real work need more than a backend API key. They need a user
|
|
|
19
19
|
|
|
20
20
|
Qoni keeps that model small:
|
|
21
21
|
|
|
22
|
-
- One SDK entry: `new
|
|
22
|
+
- One SDK entry: `new Qoni({ accessKey, secretKey })`.
|
|
23
23
|
- One discovery path: `host` can override the Qoni Console/SDK gateway for private or local deployments, and the SDK reads downstream runtime URLs from `/api/v3/eak/runtime-config`.
|
|
24
24
|
- One delegation entry: call `delegateToken`; silent mode returns `data.token`, while interactive mode returns an authorization URL and later completes on your server.
|
|
25
25
|
- One management path: call `genauth.users.*`, and the SDK exchanges AK/SK for a GenAuth management token before calling GenAuth v3 users APIs.
|
|
@@ -59,8 +59,8 @@ The package ships both ESM and CommonJS builds with TypeScript types, so either
|
|
|
59
59
|
import style works:
|
|
60
60
|
|
|
61
61
|
```ts
|
|
62
|
-
import {
|
|
63
|
-
const {
|
|
62
|
+
import { Qoni } from "@qoniai/qoni"; // ESM / TypeScript
|
|
63
|
+
const { Qoni } = require("@qoniai/qoni"); // CommonJS
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
## AI Skill
|
|
@@ -87,9 +87,9 @@ Start with a server-side SDK instance. AK/SK stays on your trusted server for bo
|
|
|
87
87
|
|
|
88
88
|
```ts
|
|
89
89
|
import fs from "node:fs";
|
|
90
|
-
import {
|
|
90
|
+
import { Qoni } from "@qoniai/qoni";
|
|
91
91
|
|
|
92
|
-
const qoni = new
|
|
92
|
+
const qoni = new Qoni({
|
|
93
93
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
94
94
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
95
95
|
});
|
|
@@ -472,7 +472,7 @@ const sameMonitor = await qoni.track.attach(monitor.id, { token });
|
|
|
472
472
|
### GenAuth User Context and Management
|
|
473
473
|
|
|
474
474
|
```ts
|
|
475
|
-
const client = new
|
|
475
|
+
const client = new Qoni({
|
|
476
476
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
477
477
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
478
478
|
});
|
|
@@ -499,7 +499,7 @@ const created = await client.genauth.users.create({
|
|
|
499
499
|
### Client
|
|
500
500
|
|
|
501
501
|
```ts
|
|
502
|
-
const qoni = new
|
|
502
|
+
const qoni = new Qoni({
|
|
503
503
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
504
504
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
505
505
|
timeoutMs: 30_000,
|
|
@@ -512,7 +512,7 @@ const qoni = new QoniAgentKit({
|
|
|
512
512
|
| `secretKey` | `string` | Yes | Qoni secret key from Qoni Console. |
|
|
513
513
|
| `host` | `string` | No | Optional Qoni Console/SDK gateway override for private or local deployments. |
|
|
514
514
|
| `fetch` | `typeof fetch` | No | Custom transport implementation. |
|
|
515
|
-
| `timeoutMs` | `number` | No | Per-request timeout (connect +
|
|
515
|
+
| `timeoutMs` | `number` | No | Per-request timeout (connect + headers + body for one-shot requests; headers only for successful SSE connections). Defaults to `30000`. |
|
|
516
516
|
|
|
517
517
|
> **`timeoutMs` does not bound a long-running run.** It applies to individual
|
|
518
518
|
> one-shot HTTP requests (delegation, `status()`, a single POST). The live
|
|
@@ -524,12 +524,6 @@ const qoni = new QoniAgentKit({
|
|
|
524
524
|
> `wait()` timeout does not stop the run; it keeps executing server-side and
|
|
525
525
|
> you can `attach()` to it again.
|
|
526
526
|
|
|
527
|
-
`Qoni` is also exported as a short alias:
|
|
528
|
-
|
|
529
|
-
```ts
|
|
530
|
-
import { Qoni, QoniAgentKit } from "@qoniai/qoni";
|
|
531
|
-
```
|
|
532
|
-
|
|
533
527
|
### Namespaces
|
|
534
528
|
|
|
535
529
|
| Namespace | Methods |
|
|
@@ -556,6 +550,26 @@ await run.cancel(reason?) // idempotent
|
|
|
556
550
|
|
|
557
551
|
`await run.wait(...)` settles to a `RunResult`:
|
|
558
552
|
|
|
553
|
+
The run-detail response must confirm a terminal state. Detail read errors propagate
|
|
554
|
+
unchanged; `wait()` never substitutes an SSE completion payload for the authoritative
|
|
555
|
+
result. A nonterminal or incomplete detail rejects with a retryable `upstream.failed`
|
|
556
|
+
error; use `status()` or re-attach to recover.
|
|
557
|
+
|
|
558
|
+
`timeoutMs` and `signal` stop waiting for detail/artifact reads and promises returned
|
|
559
|
+
by `onEvent`, `onWireEvent`, `onInteraction`, and `onScreenshot`. They cannot preempt
|
|
560
|
+
synchronous JavaScript or stop work already started inside a callback. `onReconnect`
|
|
561
|
+
is synchronous telemetry: its return value is not awaited and returned promise
|
|
562
|
+
rejections are not handled. Do not pass an async callback there; synchronous throws
|
|
563
|
+
propagate. Reconnect backoff remains abortable and subject to the wait deadline.
|
|
564
|
+
|
|
565
|
+
Detail/artifact-list GETs receive the wait signal: aborting or timing out a wait aborts
|
|
566
|
+
the request and cancels its body reader. The client's per-request timer also covers
|
|
567
|
+
complete JSON/NDJSON and binary body reads, including HTTP error bodies. A late response
|
|
568
|
+
from a custom fetch that ignores abort has its body canceled and cannot resume settlement
|
|
569
|
+
or start subsequent run requests. Custom transports must honor `RequestInit.signal` to
|
|
570
|
+
stop their own in-flight network work. Stopping a wait neither cancels the server-side
|
|
571
|
+
run nor creates a replacement task; use `cancel()` explicitly to stop the existing run.
|
|
572
|
+
|
|
559
573
|
```ts
|
|
560
574
|
interface RunResult {
|
|
561
575
|
runId: string;
|
package/README.zh-CN.md
CHANGED
|
@@ -14,7 +14,7 @@ AK/SK 必须只保存在可信服务端,不能下发到浏览器、移动端
|
|
|
14
14
|
|
|
15
15
|
Qoni 把 Agent 授权模型收敛成几个稳定边界:
|
|
16
16
|
|
|
17
|
-
- 一个 SDK 入口:`new
|
|
17
|
+
- 一个 SDK 入口:`new Qoni({ accessKey, secretKey })`。
|
|
18
18
|
- 一条发现路径:`host` 可在私有化或本地部署中覆盖 Qoni Console/SDK 网关,SDK 通过 `/api/v3/eak/runtime-config` 获取 GenAuth、GUMem、WebAgent 等运行时地址。
|
|
19
19
|
- 一个授权入口:调用 `delegateToken`;silent 模式直接返回 `data.token`,interactive 模式返回授权 URL,之后由业务服务端完成兑换。
|
|
20
20
|
- 一条管理面路径:调用 `genauth.users.*`,SDK 会先用 AK/SK 换取 GenAuth management token,再调用 GenAuth v3 users API。
|
|
@@ -52,8 +52,8 @@ yarn add @qoniai/qoni
|
|
|
52
52
|
包同时发布 ESM 和 CommonJS 两套构建(都带 TypeScript 类型),两种引入方式都可用:
|
|
53
53
|
|
|
54
54
|
```ts
|
|
55
|
-
import {
|
|
56
|
-
const {
|
|
55
|
+
import { Qoni } from "@qoniai/qoni"; // ESM / TypeScript
|
|
56
|
+
const { Qoni } = require("@qoniai/qoni"); // CommonJS
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
## AI Skill
|
|
@@ -80,9 +80,9 @@ npm 包中包含 `skills/` 目录,但推荐仍使用上面的 GitHub 仓库安
|
|
|
80
80
|
|
|
81
81
|
```ts
|
|
82
82
|
import fs from "node:fs";
|
|
83
|
-
import {
|
|
83
|
+
import { Qoni } from "@qoniai/qoni";
|
|
84
84
|
|
|
85
|
-
const qoni = new
|
|
85
|
+
const qoni = new Qoni({
|
|
86
86
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
87
87
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
88
88
|
});
|
|
@@ -442,7 +442,7 @@ const sameMonitor = await qoni.track.attach(monitor.id, { token });
|
|
|
442
442
|
### GenAuth 用户上下文与用户管理
|
|
443
443
|
|
|
444
444
|
```ts
|
|
445
|
-
const client = new
|
|
445
|
+
const client = new Qoni({
|
|
446
446
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
447
447
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
448
448
|
});
|
|
@@ -469,7 +469,7 @@ const created = await client.genauth.users.create({
|
|
|
469
469
|
### Client
|
|
470
470
|
|
|
471
471
|
```ts
|
|
472
|
-
const qoni = new
|
|
472
|
+
const qoni = new Qoni({
|
|
473
473
|
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
474
474
|
secretKey: process.env.QONI_SECRET_KEY!,
|
|
475
475
|
timeoutMs: 30_000,
|
|
@@ -482,16 +482,10 @@ const qoni = new QoniAgentKit({
|
|
|
482
482
|
| `secretKey` | `string` | 是 | Qoni Console 创建的 secret key。 |
|
|
483
483
|
| `host` | `string` | 否 | 私有化或本地部署时可选的 Qoni Console/SDK 网关覆盖地址。 |
|
|
484
484
|
| `fetch` | `typeof fetch` | 否 | 自定义传输实现。 |
|
|
485
|
-
| `timeoutMs` | `number` | 否 |
|
|
485
|
+
| `timeoutMs` | `number` | 否 | 单次请求超时(一次性请求覆盖连接、响应头及响应体;成功建立的 SSE 仅覆盖到响应头),默认 `30000`。 |
|
|
486
486
|
|
|
487
487
|
> **`timeoutMs` 不会限制长任务。** 它只作用于单次一次性 HTTP 请求(委托、`status()`、单个 POST)。事件流(`events()` / `wait()`)**不受它约束**——流的响应头一到,这个单次计时器就被清掉了,所以一个跑一小时的 Deep Research 在默认 30s 客户端超时下也能正常流式。要限制等待时长用 `wait({ timeoutMs })`;不传则 `wait()` 一直等到终态。`wait()` 超时**不会停止 run**——它在服务端继续跑,可以再 `attach()` 回去。
|
|
488
488
|
|
|
489
|
-
兼容导出:
|
|
490
|
-
|
|
491
|
-
```ts
|
|
492
|
-
import { Qoni, QoniAgentKit } from "@qoniai/qoni";
|
|
493
|
-
```
|
|
494
|
-
|
|
495
489
|
### 命名空间
|
|
496
490
|
|
|
497
491
|
| 命名空间 | 方法 |
|
|
@@ -518,6 +512,19 @@ await run.cancel(reason?) // 幂等
|
|
|
518
512
|
|
|
519
513
|
`await run.wait(...)` 结算成一个 `RunResult`:
|
|
520
514
|
|
|
515
|
+
必须由 run-detail 响应确认终态。详情读取错误原样抛出,`wait()` 不会用 SSE 完成事件替代权威结果。
|
|
516
|
+
详情仍为非终态或缺少终态信息时,抛出可重试的 `upstream.failed`;可通过 `status()` 或重新 `attach()` 恢复。
|
|
517
|
+
|
|
518
|
+
`timeoutMs` 与 `signal` 会结束详情、交付物读取及 `onEvent`、`onWireEvent`、`onInteraction`、
|
|
519
|
+
`onScreenshot` 返回的 Promise 的等待,但不能抢占同步 JavaScript,也不能停止回调内部已启动的工作。
|
|
520
|
+
`onReconnect` 是同步遥测通知:返回值不被等待,返回的 Promise 的 rejection 也不被处理,因此不要传 async
|
|
521
|
+
回调;同步抛错会向上传播。重连退避等待仍可被 signal 或 wait 超时中断。
|
|
522
|
+
|
|
523
|
+
详情/交付物列表 GET 会接收 wait signal:wait 中止或超时时会中止请求、取消并释放响应体 reader。
|
|
524
|
+
客户端单次请求计时器也覆盖完整 JSON/NDJSON、二进制响应体及 HTTP 错误体读取。即使自定义 fetch 忽略
|
|
525
|
+
abort,SDK 也会取消其迟到响应体,不恢复结算或启动后续 run 请求;自定义传输须遵守 `RequestInit.signal`
|
|
526
|
+
才能停止其内部网络工作。停止 wait 既不会取消服务端 run,也不会创建替代任务;需要停止原 run 时须显式调用 `cancel()`。
|
|
527
|
+
|
|
521
528
|
```ts
|
|
522
529
|
interface RunResult {
|
|
523
530
|
runId: string;
|