@qoniai/qoni 0.5.1 → 0.5.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 +8 -0
- package/README.md +2 -1
- package/README.zh-CN.md +2 -1
- package/dist/index.cjs +79 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +79 -82
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.2 - 2026-09-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Keep permission errors concise instead of appending every known scope.
|
|
8
|
+
- Explain how to enable a permission policy when an AccessKey has no allowed
|
|
9
|
+
scopes. Preserve the backend error code and request ID for diagnosis.
|
|
10
|
+
|
|
3
11
|
## 0.5.1 - 2026-09-23
|
|
4
12
|
|
|
5
13
|
### Fixed
|
package/README.md
CHANGED
|
@@ -727,7 +727,7 @@ All error classes are exported and can be matched with `instanceof`:
|
|
|
727
727
|
| --- | --- | --- |
|
|
728
728
|
| `QoniValidationError` | Local input check failed before any request (bad scope string, silent delegation missing a user). | Fix the call — the message states the correct form. |
|
|
729
729
|
| `QoniAuthError` | AK/SK signing rejected by Qoni (bad/rotated credentials). | Check `accessKey` / `secretKey`. |
|
|
730
|
-
| `QoniPermissionDeniedError` | The delegation token lacks a required scope (403). |
|
|
730
|
+
| `QoniPermissionDeniedError` | The AccessKey or delegation token lacks a required scope (403). | Check the AccessKey permission policy and request the missing scope with `delegateToken`. |
|
|
731
731
|
| `QoniTokenExpiredError` | The delegation / product token expired. | Mint a fresh token and retry. |
|
|
732
732
|
| `QoniDelegationRequiredError` | A product call was made without `token`, or with a raw token the gateway won't accept directly. | Pass `delegation.data.token` to the product call. |
|
|
733
733
|
| `QoniRateLimitError` | Rate limited (429). | Back off and retry (`retryable === true`). |
|
|
@@ -777,6 +777,7 @@ Common first-run errors:
|
|
|
777
777
|
| --- | --- | --- |
|
|
778
778
|
| `agent must be a string` | The online delegation API currently expects `agent` to be a string id. | Pass `agent: "memory-agent"` rather than an object. |
|
|
779
779
|
| `eak.delegation.user_not_bound` | The `userId` is not in the GenAuth userpool bound to this Qoni credential. | Use a real user id from `currentUser` or from the same bound userpool. |
|
|
780
|
+
| `eak.delegation.no_allowed_scopes` | The AccessKey has no permission scopes enabled. | In Qoni Console, open its Permission scope settings and enable the policy required by this call. |
|
|
780
781
|
| `eak.genauth.userpool_binding_missing` | The AK/SK is not bound to a GenAuth userpool, so `genauth.users.*` cannot obtain a management token. | Bind the Qoni credential to the target GenAuth userpool before calling user management APIs. |
|
|
781
782
|
| `eak.genauth.userpool_owner_missing` | The bound GenAuth userpool has no resolvable owner user for management-token signing. | Fix the GenAuth userpool owner data or binding. |
|
|
782
783
|
| `eak.token_exchange.upstream_failed` with `unauthorized_client` or `grant_type is not enabled` | Delegation succeeded, but the managed delegation app is missing token-exchange grant support or has drifted from the tenant binding. | Repair the managed delegation app binding before calling GUMem or WebAgent product capabilities. |
|
package/README.zh-CN.md
CHANGED
|
@@ -657,7 +657,7 @@ type QoniEvent<T = unknown> = {
|
|
|
657
657
|
| --- | --- | --- |
|
|
658
658
|
| `QoniValidationError` | 请求发出前的本地校验失败(scope 字符串格式错、silent 委托缺 user)。 | 按消息修正调用——消息里给出正确写法。 |
|
|
659
659
|
| `QoniAuthError` | AK/SK 签名被 Qoni 拒绝(凭据错误/已轮换)。 | 检查 `accessKey` / `secretKey`。 |
|
|
660
|
-
| `QoniPermissionDeniedError` | delegation token
|
|
660
|
+
| `QoniPermissionDeniedError` | AccessKey 或 delegation token 缺少所需 scope(403)。 | 检查 AccessKey 权限策略,并在 `delegateToken` 中申请所需 scope。 |
|
|
661
661
|
| `QoniTokenExpiredError` | delegation / 产品 token 过期。 | 重新 mint token 再试。 |
|
|
662
662
|
| `QoniDelegationRequiredError` | 产品调用没带 `token`,或带的是网关不接受的裸 token。 | 把 `delegation.data.token` 传给产品调用。 |
|
|
663
663
|
| `QoniRateLimitError` | 被限流(429)。 | 退避后重试(`retryable === true`)。 |
|
|
@@ -706,6 +706,7 @@ try {
|
|
|
706
706
|
| --- | --- | --- |
|
|
707
707
|
| `agent must be a string` | 当前线上 delegation API 期望 `agent` 是字符串 ID。 | 使用 `agent: "memory-agent"`,不要传对象。 |
|
|
708
708
|
| `eak.delegation.user_not_bound` | `userId` 不属于该 Qoni credential 绑定的 GenAuth userpool。 | 使用 `currentUser` 返回的真实用户 ID,或确认用户来自同一个绑定 userpool。 |
|
|
709
|
+
| `eak.delegation.no_allowed_scopes` | AccessKey 没有启用任何权限 scope。 | 在 Qoni Console 的 Permission scope 设置中启用本次调用所需的策略。 |
|
|
709
710
|
| `eak.genauth.userpool_binding_missing` | AK/SK 没有绑定 GenAuth userpool,`genauth.users.*` 无法换取 management token。 | 先把 Qoni credential 绑定到目标 GenAuth userpool。 |
|
|
710
711
|
| `eak.genauth.userpool_owner_missing` | 绑定的 GenAuth userpool 找不到可用于签发 management token 的 owner 用户。 | 修复 GenAuth userpool owner 数据或绑定。 |
|
|
711
712
|
| `eak.token_exchange.upstream_failed` 且包含 `unauthorized_client` 或 `grant_type is not enabled` | Delegation 已成功,但 managed delegation app 缺少 token-exchange grant,或租户绑定发生漂移。 | 先修复 managed delegation app 绑定,再调用 GUMem 或 WebAgent 产品能力。 |
|
package/dist/index.cjs
CHANGED
|
@@ -104,81 +104,6 @@ function buildSignedHeaders(credentials, method, pathname, payload) {
|
|
|
104
104
|
return headers;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
// src/scopes.ts
|
|
108
|
-
var QoniScopes = {
|
|
109
|
-
GUMEM_SESSION_CREATE: "gumem.session:create",
|
|
110
|
-
GUMEM_MESSAGE_WRITE: "gumem.message:write",
|
|
111
|
-
GUMEM_MEMORY_READ: "gumem.memory:read",
|
|
112
|
-
GUMEM_MEMORY_WRITE: "gumem.memory:write",
|
|
113
|
-
GUMEM_MEMORY_DELETE: "gumem.memory:delete",
|
|
114
|
-
GUMEM_SEARCH_RUN: "gumem.search:run",
|
|
115
|
-
GUMEM_ADMIN_MANAGE: "gumem.admin:manage",
|
|
116
|
-
GUMEM_RESOURCE_WRITE: "gumem.resource:write",
|
|
117
|
-
GUMEM_ACTION_WRITE: "gumem.action:write",
|
|
118
|
-
GUMEM_ACTION_READ: "gumem.action:read",
|
|
119
|
-
GUMEM_PROFILE_READ: "gumem.profile:read",
|
|
120
|
-
// WebAgent products: exactly two verbs per product — `read` (observe) and
|
|
121
|
-
// `manage` (anything that changes execution state). See
|
|
122
|
-
// wa/docs/qoni-sdk-public-surface.md §3.
|
|
123
|
-
DO_ANYTHING_READ: "webagent.do_anything:read",
|
|
124
|
-
DO_ANYTHING_MANAGE: "webagent.do_anything:manage",
|
|
125
|
-
WEB_SEARCH_READ: "webagent.web_search:read",
|
|
126
|
-
WEB_SEARCH_MANAGE: "webagent.web_search:manage",
|
|
127
|
-
DEEP_RESEARCH_READ: "webagent.deep_research:read",
|
|
128
|
-
DEEP_RESEARCH_MANAGE: "webagent.deep_research:manage",
|
|
129
|
-
TRACK_READ: "webagent.track:read",
|
|
130
|
-
TRACK_MANAGE: "webagent.track:manage"
|
|
131
|
-
};
|
|
132
|
-
var QoniProductScopes = {
|
|
133
|
-
doAnything: [
|
|
134
|
-
QoniScopes.DO_ANYTHING_READ,
|
|
135
|
-
QoniScopes.DO_ANYTHING_MANAGE
|
|
136
|
-
],
|
|
137
|
-
webSearch: [
|
|
138
|
-
QoniScopes.WEB_SEARCH_READ,
|
|
139
|
-
QoniScopes.WEB_SEARCH_MANAGE
|
|
140
|
-
],
|
|
141
|
-
deepResearch: [
|
|
142
|
-
QoniScopes.DEEP_RESEARCH_READ,
|
|
143
|
-
QoniScopes.DEEP_RESEARCH_MANAGE
|
|
144
|
-
],
|
|
145
|
-
track: [
|
|
146
|
-
QoniScopes.TRACK_READ,
|
|
147
|
-
QoniScopes.TRACK_MANAGE
|
|
148
|
-
]
|
|
149
|
-
};
|
|
150
|
-
var KNOWN_SCOPES = Object.values(QoniScopes);
|
|
151
|
-
var QoniScopeBundles = {
|
|
152
|
-
GUMEM_READONLY: [QoniScopes.GUMEM_MEMORY_READ, QoniScopes.GUMEM_PROFILE_READ],
|
|
153
|
-
GUMEM_SESSION_RECALL: [
|
|
154
|
-
QoniScopes.GUMEM_MEMORY_READ,
|
|
155
|
-
QoniScopes.GUMEM_MEMORY_WRITE,
|
|
156
|
-
QoniScopes.GUMEM_MESSAGE_WRITE
|
|
157
|
-
],
|
|
158
|
-
GUMEM_WRITE: [
|
|
159
|
-
QoniScopes.GUMEM_SESSION_CREATE,
|
|
160
|
-
QoniScopes.GUMEM_MESSAGE_WRITE,
|
|
161
|
-
QoniScopes.GUMEM_ACTION_WRITE
|
|
162
|
-
],
|
|
163
|
-
// One bundle per WebAgent product = [read, manage].
|
|
164
|
-
DO_ANYTHING: [
|
|
165
|
-
QoniScopes.DO_ANYTHING_READ,
|
|
166
|
-
QoniScopes.DO_ANYTHING_MANAGE
|
|
167
|
-
],
|
|
168
|
-
WEB_SEARCH: [
|
|
169
|
-
QoniScopes.WEB_SEARCH_READ,
|
|
170
|
-
QoniScopes.WEB_SEARCH_MANAGE
|
|
171
|
-
],
|
|
172
|
-
DEEP_RESEARCH: [
|
|
173
|
-
QoniScopes.DEEP_RESEARCH_READ,
|
|
174
|
-
QoniScopes.DEEP_RESEARCH_MANAGE
|
|
175
|
-
],
|
|
176
|
-
TRACK: [
|
|
177
|
-
QoniScopes.TRACK_READ,
|
|
178
|
-
QoniScopes.TRACK_MANAGE
|
|
179
|
-
]
|
|
180
|
-
};
|
|
181
|
-
|
|
182
107
|
// src/types.ts
|
|
183
108
|
function isJsonObject(value) {
|
|
184
109
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -262,7 +187,7 @@ function errorFromPayload(status, payload, fallbackMessage) {
|
|
|
262
187
|
const source = detailObject || (isJsonObject(payload) ? payload : {});
|
|
263
188
|
const code = stringField(source, "code") || stringField(source, "apiCode") || statusCodeToCode(status);
|
|
264
189
|
const rawMessage = stringField(source, "message") || stringField(source, "detail") || fallbackMessage;
|
|
265
|
-
const message = appendOnboardingHint(
|
|
190
|
+
const message = code === "eak.delegation.no_allowed_scopes" ? "This AccessKey has no permission scopes. In Qoni Console, open its Permission scope settings, enable the policy needed for this call, then retry." : appendOnboardingHint(
|
|
266
191
|
appendDeniedScopes(appendUpstreamDescription(rawMessage, source), source),
|
|
267
192
|
code
|
|
268
193
|
);
|
|
@@ -279,7 +204,7 @@ function errorFromPayload(status, payload, fallbackMessage) {
|
|
|
279
204
|
if (isDelegationRequired(code)) return new QoniDelegationRequiredError(message, options);
|
|
280
205
|
if (status === 401) return new QoniAuthError(message, options);
|
|
281
206
|
if (status === 403 || isPermissionDenied(code)) {
|
|
282
|
-
return new QoniPermissionDeniedError(
|
|
207
|
+
return new QoniPermissionDeniedError(message, options);
|
|
283
208
|
}
|
|
284
209
|
if (status === 400 || status === 422) return new QoniValidationError(message, options);
|
|
285
210
|
if (status === 429) return new QoniRateLimitError(message, options);
|
|
@@ -314,17 +239,14 @@ function appendUpstreamDescription(message, source) {
|
|
|
314
239
|
}
|
|
315
240
|
var ONBOARDING_HINTS = {
|
|
316
241
|
"eak.delegation.user_not_bound": "Hint: the userId is not in the GenAuth userpool bound to this credential. Resolve a real user with qoni.resolveAnyBoundUser() (demo/smoke) or qoni.currentUser({ accessToken }).",
|
|
317
|
-
"eak.genauth.userpool_binding_missing": "Hint: bind the Qoni credential to a GenAuth userpool before calling genauth.users.*."
|
|
242
|
+
"eak.genauth.userpool_binding_missing": "Hint: bind the Qoni credential to a GenAuth userpool before calling genauth.users.*.",
|
|
243
|
+
"eak.delegation.scope_not_allowed": "Hint: enable the denied scopes in this AccessKey's Permission scope settings in Qoni Console."
|
|
318
244
|
};
|
|
319
245
|
function appendOnboardingHint(message, code) {
|
|
320
246
|
const hint = ONBOARDING_HINTS[code];
|
|
321
247
|
if (!hint || message.includes(hint)) return message;
|
|
322
248
|
return `${message} ${hint}`;
|
|
323
249
|
}
|
|
324
|
-
function appendKnownScopes(message) {
|
|
325
|
-
if (message.includes("Known scopes:")) return message;
|
|
326
|
-
return `${message} (Known scopes: ${KNOWN_SCOPES.join(", ")})`;
|
|
327
|
-
}
|
|
328
250
|
function statusCodeToCode(status) {
|
|
329
251
|
if (status === 401) return "auth.failed";
|
|
330
252
|
if (status === 403) return "permission_denied";
|
|
@@ -1488,6 +1410,81 @@ function createQoniNamespace(_transport, delegateToken, completeDelegateToken) {
|
|
|
1488
1410
|
};
|
|
1489
1411
|
}
|
|
1490
1412
|
|
|
1413
|
+
// src/scopes.ts
|
|
1414
|
+
var QoniScopes = {
|
|
1415
|
+
GUMEM_SESSION_CREATE: "gumem.session:create",
|
|
1416
|
+
GUMEM_MESSAGE_WRITE: "gumem.message:write",
|
|
1417
|
+
GUMEM_MEMORY_READ: "gumem.memory:read",
|
|
1418
|
+
GUMEM_MEMORY_WRITE: "gumem.memory:write",
|
|
1419
|
+
GUMEM_MEMORY_DELETE: "gumem.memory:delete",
|
|
1420
|
+
GUMEM_SEARCH_RUN: "gumem.search:run",
|
|
1421
|
+
GUMEM_ADMIN_MANAGE: "gumem.admin:manage",
|
|
1422
|
+
GUMEM_RESOURCE_WRITE: "gumem.resource:write",
|
|
1423
|
+
GUMEM_ACTION_WRITE: "gumem.action:write",
|
|
1424
|
+
GUMEM_ACTION_READ: "gumem.action:read",
|
|
1425
|
+
GUMEM_PROFILE_READ: "gumem.profile:read",
|
|
1426
|
+
// WebAgent products: exactly two verbs per product — `read` (observe) and
|
|
1427
|
+
// `manage` (anything that changes execution state). See
|
|
1428
|
+
// wa/docs/qoni-sdk-public-surface.md §3.
|
|
1429
|
+
DO_ANYTHING_READ: "webagent.do_anything:read",
|
|
1430
|
+
DO_ANYTHING_MANAGE: "webagent.do_anything:manage",
|
|
1431
|
+
WEB_SEARCH_READ: "webagent.web_search:read",
|
|
1432
|
+
WEB_SEARCH_MANAGE: "webagent.web_search:manage",
|
|
1433
|
+
DEEP_RESEARCH_READ: "webagent.deep_research:read",
|
|
1434
|
+
DEEP_RESEARCH_MANAGE: "webagent.deep_research:manage",
|
|
1435
|
+
TRACK_READ: "webagent.track:read",
|
|
1436
|
+
TRACK_MANAGE: "webagent.track:manage"
|
|
1437
|
+
};
|
|
1438
|
+
var QoniProductScopes = {
|
|
1439
|
+
doAnything: [
|
|
1440
|
+
QoniScopes.DO_ANYTHING_READ,
|
|
1441
|
+
QoniScopes.DO_ANYTHING_MANAGE
|
|
1442
|
+
],
|
|
1443
|
+
webSearch: [
|
|
1444
|
+
QoniScopes.WEB_SEARCH_READ,
|
|
1445
|
+
QoniScopes.WEB_SEARCH_MANAGE
|
|
1446
|
+
],
|
|
1447
|
+
deepResearch: [
|
|
1448
|
+
QoniScopes.DEEP_RESEARCH_READ,
|
|
1449
|
+
QoniScopes.DEEP_RESEARCH_MANAGE
|
|
1450
|
+
],
|
|
1451
|
+
track: [
|
|
1452
|
+
QoniScopes.TRACK_READ,
|
|
1453
|
+
QoniScopes.TRACK_MANAGE
|
|
1454
|
+
]
|
|
1455
|
+
};
|
|
1456
|
+
var KNOWN_SCOPES = Object.values(QoniScopes);
|
|
1457
|
+
var QoniScopeBundles = {
|
|
1458
|
+
GUMEM_READONLY: [QoniScopes.GUMEM_MEMORY_READ, QoniScopes.GUMEM_PROFILE_READ],
|
|
1459
|
+
GUMEM_SESSION_RECALL: [
|
|
1460
|
+
QoniScopes.GUMEM_MEMORY_READ,
|
|
1461
|
+
QoniScopes.GUMEM_MEMORY_WRITE,
|
|
1462
|
+
QoniScopes.GUMEM_MESSAGE_WRITE
|
|
1463
|
+
],
|
|
1464
|
+
GUMEM_WRITE: [
|
|
1465
|
+
QoniScopes.GUMEM_SESSION_CREATE,
|
|
1466
|
+
QoniScopes.GUMEM_MESSAGE_WRITE,
|
|
1467
|
+
QoniScopes.GUMEM_ACTION_WRITE
|
|
1468
|
+
],
|
|
1469
|
+
// One bundle per WebAgent product = [read, manage].
|
|
1470
|
+
DO_ANYTHING: [
|
|
1471
|
+
QoniScopes.DO_ANYTHING_READ,
|
|
1472
|
+
QoniScopes.DO_ANYTHING_MANAGE
|
|
1473
|
+
],
|
|
1474
|
+
WEB_SEARCH: [
|
|
1475
|
+
QoniScopes.WEB_SEARCH_READ,
|
|
1476
|
+
QoniScopes.WEB_SEARCH_MANAGE
|
|
1477
|
+
],
|
|
1478
|
+
DEEP_RESEARCH: [
|
|
1479
|
+
QoniScopes.DEEP_RESEARCH_READ,
|
|
1480
|
+
QoniScopes.DEEP_RESEARCH_MANAGE
|
|
1481
|
+
],
|
|
1482
|
+
TRACK: [
|
|
1483
|
+
QoniScopes.TRACK_READ,
|
|
1484
|
+
QoniScopes.TRACK_MANAGE
|
|
1485
|
+
]
|
|
1486
|
+
};
|
|
1487
|
+
|
|
1491
1488
|
// src/genauth.ts
|
|
1492
1489
|
function createGenAuthNamespace(transport, options = {}) {
|
|
1493
1490
|
return {
|