@qoniai/qoni 0.9.0 → 0.9.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 +203 -0
- package/README.md +548 -76
- package/README.zh-CN.md +443 -53
- package/dist/index.cjs +15082 -699
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25826 -243
- package/dist/index.d.ts +25826 -243
- package/dist/index.js +15077 -698
- package/dist/index.js.map +1 -1
- package/docs/authing-sdk-LICENSE.txt +21 -0
- package/docs/delivery-examples/README.md +44 -0
- package/docs/delivery-examples/README.zh-CN.md +44 -0
- package/docs/delivery-examples/agents.ts +26 -0
- package/docs/delivery-examples/failure-handling.ts +21 -0
- package/docs/delivery-examples/hosted-login.ts +40 -0
- package/docs/delivery-examples/interactions.ts +30 -0
- package/docs/delivery-examples/local-consumer.mjs +159 -0
- package/docs/delivery-examples/m2-r2/README.md +20 -0
- package/docs/delivery-examples/m2-r2/README.zh-CN.md +20 -0
- package/docs/delivery-examples/m2-r2/local-consumer.mjs +53 -0
- package/docs/delivery-examples/m2-r2/memory-outcome.ts +22 -0
- package/docs/delivery-examples/m2-r2/package.json +1 -0
- package/docs/delivery-examples/m2-r2/tsconfig.json +1 -0
- package/docs/delivery-examples/package.json +5 -0
- package/docs/delivery-examples/profile-memory.ts +30 -0
- package/docs/delivery-examples/tsconfig.json +4 -0
- package/docs/genauth-communication.md +1410 -0
- package/docs/genauth-management-api.md +597 -0
- package/docs/genauth-management.md +285 -0
- package/docs/ordinary-task-profile.md +18 -0
- package/docs/quickstart-v5-contract.md +39 -0
- package/package.json +17 -7
- package/skills/qoni-sdk/SKILL.md +177 -7
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: GenAuth 管理 SDK
|
|
3
|
+
description: 初始化 SDK,管理用户、用户组、组织、角色、权限、应用和自定义字段。
|
|
4
|
+
status: draft
|
|
5
|
+
sdkCandidate: contracts/genauth-management.json
|
|
6
|
+
lastReviewed: 2026-10-12
|
|
7
|
+
pageClass: qoni-sdk-management
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 初始化
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { Qoni } from '@qoniai/qoni'
|
|
14
|
+
|
|
15
|
+
const qoni = new Qoni({
|
|
16
|
+
accessKey: process.env.QONI_ACCESS_KEY!,
|
|
17
|
+
secretKey: process.env.QONI_SECRET_KEY!,
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
使用绑定目标 GenAuth 用户池的 Qoni 访问密钥,在服务端调用。
|
|
22
|
+
|
|
23
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `accessKey` | `string` | 是 | Qoni 访问密钥 |
|
|
26
|
+
| `secretKey` | `string` | 是 | Qoni 访问密钥 Secret |
|
|
27
|
+
| `host` | `string` | 否 | 私有部署的 Qoni 服务地址 |
|
|
28
|
+
| `genauthHost` | `string` | 否 | 指定 GenAuth 服务地址 |
|
|
29
|
+
| `timeoutMs` | `number` | 否 | 请求超时,单位毫秒,默认 `30000` |
|
|
30
|
+
| `fetch` | `typeof fetch` | 否 | 自定义 HTTP transport |
|
|
31
|
+
|
|
32
|
+
## 用户管理
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const { data: user } = await qoni.genauth.users.create({
|
|
36
|
+
username: 'sdk-example-user',
|
|
37
|
+
name: 'Example user',
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const { data: userDetails } = await qoni.genauth.users.get({ userId: user.userId })
|
|
41
|
+
await qoni.genauth.users.update({ userId: user.userId, nickname: 'Alice' })
|
|
42
|
+
const { data: userBatch } = await qoni.genauth.users.getBatch({ userIds: [user.userId] })
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| `users.create` | 创建用户 | username / email / phone;name、password 等可选 | 用户对象 |
|
|
48
|
+
| `users.get` | 读取用户 | userId | 用户对象 |
|
|
49
|
+
| `users.getBatch` | 批量读取用户 | userIds: string[] | 用户数组 |
|
|
50
|
+
| `users.update` | 更新用户 | userId 与需要更新的字段 | 更新后的用户 |
|
|
51
|
+
| `users.createBatch` | 批量创建用户 | list: 用户参数数组 | 用户数组 |
|
|
52
|
+
| `users.deleteBatch` | 批量删除用户 | userIds: string[] | 删除结果 |
|
|
53
|
+
|
|
54
|
+
创建时至少设置用户名、邮箱或手机号。删除在职用户前,先按业务流程通过 `users.resign({ userId })` 设置离职状态。
|
|
55
|
+
|
|
56
|
+
## 用户查询与分页
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const { data: userPage } = await qoni.genauth.users.list({
|
|
60
|
+
page: 1,
|
|
61
|
+
limit: 20,
|
|
62
|
+
keywords: 'alice',
|
|
63
|
+
options: { fuzzySearchOn: ['username', 'email'] },
|
|
64
|
+
})
|
|
65
|
+
console.log(userPage.list, userPage.totalCount)
|
|
66
|
+
|
|
67
|
+
for await (const item of qoni.genauth.users.iterate({ limit: 50 })) {
|
|
68
|
+
console.log(item.userId)
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
73
|
+
| --- | --- | --- | --- |
|
|
74
|
+
| `users.list` | 分页查询用户 | page、limit、keywords、options | { list, totalCount } |
|
|
75
|
+
| `users.iterate` | 逐个遍历用户 | page 默认 1,limit 默认 50、范围 1–50 | `AsyncIterable<User>` |
|
|
76
|
+
|
|
77
|
+
`page` 从 1 开始。`keywords` 用于关键字筛选,`options.fuzzySearchOn` 指定匹配字段。无需筛选时省略这两个参数。`iterate` 中使用 `break` 停止遍历。
|
|
78
|
+
|
|
79
|
+
## 用户组
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const { data: group } = await qoni.genauth.groups.create({
|
|
83
|
+
code: 'engineering',
|
|
84
|
+
name: 'Engineering',
|
|
85
|
+
})
|
|
86
|
+
await qoni.genauth.groups.addMembers({ code: group.code, userIds: [user.userId] })
|
|
87
|
+
const { data: groupPage } = await qoni.genauth.groups.list({ page: 1, limit: 20 })
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
91
|
+
| --- | --- | --- | --- |
|
|
92
|
+
| `groups.create` | 创建用户组 | code、name | 用户组对象 |
|
|
93
|
+
| `groups.get` | 读取用户组 | code | 用户组对象 |
|
|
94
|
+
| `groups.list` | 查询用户组 | page、limit | { list, totalCount } |
|
|
95
|
+
| `groups.update` | 更新用户组 | code 与更新字段 | 用户组对象 |
|
|
96
|
+
| `groups.addMembers` | 添加成员 | code、userIds | 操作结果 |
|
|
97
|
+
|
|
98
|
+
## 组织与部门
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
await qoni.genauth.organizations.create({
|
|
102
|
+
organizationCode: 'company',
|
|
103
|
+
organizationName: 'Example company',
|
|
104
|
+
})
|
|
105
|
+
const { data: department } = await qoni.genauth.departments.create({
|
|
106
|
+
organizationCode: 'company',
|
|
107
|
+
parentDepartmentId: 'root',
|
|
108
|
+
name: 'Engineering',
|
|
109
|
+
code: 'engineering',
|
|
110
|
+
})
|
|
111
|
+
await qoni.genauth.departments.addMembers({
|
|
112
|
+
organizationCode: 'company',
|
|
113
|
+
departmentId: department.departmentId,
|
|
114
|
+
userIds: [user.userId],
|
|
115
|
+
})
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
119
|
+
| --- | --- | --- | --- |
|
|
120
|
+
| `organizations.create` | 创建组织 | organizationCode、organizationName | 组织对象 |
|
|
121
|
+
| `organizations.get` | 读取组织 | organizationCode | 组织对象 |
|
|
122
|
+
| `organizations.list` | 查询组织 | page、limit | 组织列表 |
|
|
123
|
+
| `organizations.update` | 更新组织 | organizationCode 与更新字段 | 组织对象 |
|
|
124
|
+
| `departments.create` | 创建部门 | organizationCode、parentDepartmentId、name | 部门对象 |
|
|
125
|
+
| `departments.get` | 读取部门 | organizationCode、departmentId 或 departmentCode | 部门对象 |
|
|
126
|
+
| `departments.update` | 更新部门 | organizationCode、departmentId 与更新字段 | 部门对象 |
|
|
127
|
+
| `departments.addMembers` | 添加部门成员 | organizationCode、departmentId、userIds | 操作结果 |
|
|
128
|
+
|
|
129
|
+
根部门的 `parentDepartmentId` 使用 `root`;其他部门使用实际父部门 ID。
|
|
130
|
+
|
|
131
|
+
## 角色、资源与授权
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
await qoni.genauth.namespaces.create({ code: 'project', name: 'Project' })
|
|
135
|
+
await qoni.genauth.roles.create({ namespace: 'project', code: 'reader', name: 'Reader' })
|
|
136
|
+
await qoni.genauth.roles.assign({
|
|
137
|
+
namespace: 'project',
|
|
138
|
+
code: 'reader',
|
|
139
|
+
targets: [{ targetType: 'USER', targetIdentifier: user.userId }],
|
|
140
|
+
})
|
|
141
|
+
await qoni.genauth.resources.create({
|
|
142
|
+
namespace: 'project', code: 'documents', type: 'API',
|
|
143
|
+
apiIdentifier: '/documents',
|
|
144
|
+
actions: [{ name: 'documents:read', description: 'Read documents' }],
|
|
145
|
+
})
|
|
146
|
+
await qoni.genauth.permissions.authorize({
|
|
147
|
+
namespace: 'project',
|
|
148
|
+
list: [{
|
|
149
|
+
targetType: 'ROLE', targetIdentifiers: ['reader'],
|
|
150
|
+
resources: [{ code: 'documents:*', resourceType: 'API', actions: ['documents:read'] }],
|
|
151
|
+
}],
|
|
152
|
+
})
|
|
153
|
+
const { data: permission } = await qoni.genauth.permissions.isAllowed({
|
|
154
|
+
namespace: 'project', userId: user.userId,
|
|
155
|
+
resource: 'documents:123', action: 'documents:read',
|
|
156
|
+
})
|
|
157
|
+
console.log(permission.allowed)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
161
|
+
| --- | --- | --- | --- |
|
|
162
|
+
| `namespaces.create` | 创建权限空间 | code、name | 权限空间对象 |
|
|
163
|
+
| `roles.create` | 创建角色 | namespace、code、name | 角色对象 |
|
|
164
|
+
| `roles.list` | 查询角色 | namespace、page、limit | { list, totalCount } |
|
|
165
|
+
| `roles.assign` | 分配角色 | namespace、code、targets | 操作结果 |
|
|
166
|
+
| `resources.create` | 定义资源及动作 | namespace、code、type、actions;API 资源使用 apiIdentifier | 资源对象 |
|
|
167
|
+
| `permissions.authorize` | 授予资源权限 | namespace、list | 操作结果 |
|
|
168
|
+
| `permissions.isAllowed` | 判断用户权限 | namespace、userId、resource、action | { allowed } |
|
|
169
|
+
|
|
170
|
+
角色、资源和授权使用同一 `namespace`。创建资源用 `type`,授权资源项用 `resourceType`。
|
|
171
|
+
|
|
172
|
+
## 应用管理
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const { data: application } = await qoni.genauth.applications.create({
|
|
176
|
+
appName: 'Example app',
|
|
177
|
+
appIdentifier: 'example-app',
|
|
178
|
+
appType: 'web',
|
|
179
|
+
defaultProtocol: 'oidc',
|
|
180
|
+
redirectUris: ['https://app.example.com/callback'],
|
|
181
|
+
})
|
|
182
|
+
const { data: appDetails } = await qoni.genauth.applications.get({ appId: application.appId })
|
|
183
|
+
const { data: appPage } = await qoni.genauth.applications.list({ page: 1, limit: 20 })
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
187
|
+
| --- | --- | --- | --- |
|
|
188
|
+
| `applications.create` | 创建应用 | appName;自建应用传 appIdentifier,可设置 appType、defaultProtocol、redirectUris | 应用创建结果 |
|
|
189
|
+
| `applications.get` | 读取应用配置 | appId | 应用对象 |
|
|
190
|
+
| `applications.list` | 分页查询应用 | page、limit、keywords | 应用列表 |
|
|
191
|
+
| `applications.update` | 更新应用配置 | appId 与更新字段 | 应用对象 |
|
|
192
|
+
| `applications.delete` | 删除应用 | appId | 操作结果 |
|
|
193
|
+
|
|
194
|
+
## 自定义字段
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
await qoni.genauth.customFields.set({
|
|
198
|
+
list: [{ targetType: 'USER', key: 'costCenter', label: 'Cost center', dataType: 'STRING' }],
|
|
199
|
+
})
|
|
200
|
+
await qoni.genauth.customFields.setData({
|
|
201
|
+
targetType: 'USER', targetIdentifier: user.userId,
|
|
202
|
+
list: [{ key: 'costCenter', value: 'engineering' }],
|
|
203
|
+
})
|
|
204
|
+
const { data: fieldValues } = await qoni.genauth.customFields.getData({
|
|
205
|
+
targetType: 'USER', targetIdentifier: user.userId,
|
|
206
|
+
})
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
| 方法 | 功能 | 主要参数 | `data` |
|
|
210
|
+
| --- | --- | --- | --- |
|
|
211
|
+
| `customFields.list` | 查询字段定义 | targetType,默认 USER | 字段定义列表 |
|
|
212
|
+
| `customFields.set` | 创建或更新字段定义 | list: { targetType, key, label, dataType }[] | 操作结果 |
|
|
213
|
+
| `customFields.setData` | 设置对象字段值 | targetType、targetIdentifier、list | 操作结果 |
|
|
214
|
+
| `customFields.getData` | 读取对象字段值 | targetType、targetIdentifier | 字段数据 |
|
|
215
|
+
|
|
216
|
+
先定义字段,再写入字段值。已有字段的 `dataType` 不能修改;角色字段需要传所属 `namespace`。
|
|
217
|
+
|
|
218
|
+
## 其他管理功能
|
|
219
|
+
|
|
220
|
+
| 入口 | 功能 |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| `tenants` | 租户与租户成员 |
|
|
223
|
+
| `identityProviders` | 外部身份源与连接配置 |
|
|
224
|
+
| `dataPermissions / policies` | 数据资源、策略及数据授权 |
|
|
225
|
+
| `auditLogs / sessions` | 管理审计与用户会话 |
|
|
226
|
+
| `security / whitelist / riskLists` | MFA、安全设置及访问名单 |
|
|
227
|
+
| `webhooks / events` | Webhook 配置与事件 |
|
|
228
|
+
| `sync / pipelines` | 账号同步及认证流程 |
|
|
229
|
+
| `accessKeys` | 访问密钥管理 |
|
|
230
|
+
| `positions / dynamicGroups` | 岗位与动态用户组 |
|
|
231
|
+
| `devices / deviceRules` | 设备及设备规则 |
|
|
232
|
+
| `publicAccounts / invitations` | 公共账号及邀请 |
|
|
233
|
+
| `approvals / ldap` | 审批与 LDAP 配置 |
|
|
234
|
+
| `metadata / email / billing` | 元数据、邮件及计费配置 |
|
|
235
|
+
|
|
236
|
+
以上入口均位于 `qoni.genauth` 下。具体方法、参数与返回类型见 [管理方法参考](./genauth-management-api)。
|
|
237
|
+
|
|
238
|
+
## 返回值与请求取消
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
const controller = new AbortController()
|
|
242
|
+
const { data: rolePage, meta } = await qoni.genauth.roles.list(
|
|
243
|
+
{ namespace: 'project', page: 1, limit: 20 },
|
|
244
|
+
{ signal: controller.signal },
|
|
245
|
+
)
|
|
246
|
+
console.log(rolePage.list, meta.requestId)
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
方法返回 `Promise<QoniResponse<T>>`:`data` 为业务结果,`meta.requestId` 为请求标识。第二参数传 `{ signal }`,调用 `controller.abort()` 取消请求。`users.iterate` 返回 `AsyncIterable`。
|
|
250
|
+
|
|
251
|
+
## 使用已有管理 Token
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
const { data: roleList } = await qoni.genauth.roles.list({
|
|
255
|
+
namespace: 'project',
|
|
256
|
+
adminToken: process.env.GENAUTH_MANAGEMENT_TOKEN!,
|
|
257
|
+
userPoolId: process.env.GENAUTH_USER_POOL_ID!,
|
|
258
|
+
})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
`adminToken` 与 `userPoolId` 必须同时传入。显式传入的 Token 过期后由调用方更新。
|
|
262
|
+
|
|
263
|
+
## 错误处理
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
import { QoniError } from '@qoniai/qoni'
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
await qoni.genauth.users.get({ userId: '<user-id>' })
|
|
270
|
+
} catch (error) {
|
|
271
|
+
if (error instanceof QoniError) {
|
|
272
|
+
console.error(error.code, error.message, error.requestId)
|
|
273
|
+
}
|
|
274
|
+
throw error
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
| 错误 | 处理方式 |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| `QoniValidationError` | 检查必填参数与字段类型 |
|
|
281
|
+
| `401` / `403` | 检查凭据、用户池绑定及管理权限 |
|
|
282
|
+
| `404` | 检查对象 ID 与所属用户池 |
|
|
283
|
+
| `409` | 处理对象状态冲突或标识重复 |
|
|
284
|
+
| `QoniTimeoutError` | 重试写操作前先查询原操作结果 |
|
|
285
|
+
| 其他 `QoniError` | 查看 `code`、`message`、`requestId`、`body` |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Ordinary Task Profile / 本轮普通资料
|
|
2
|
+
|
|
3
|
+
Request `user.profile:read` and optionally `user.profile:write` in the original delegation, alongside the WebAgent scopes. They remain in the original GenAuth grant; they are not added to the WebAgent product token. The original Task source and current consent/key/field permissions jointly gate every operation.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
const profile = await qoni.doAnything.profile.read({runId, token, fields: ["name", "address"]});
|
|
7
|
+
// Render profile.data.values only in the current user's authorized UI; do not log it.
|
|
8
|
+
// Only an explicitly authorised original source can save these ordinary fields.
|
|
9
|
+
await qoni.doAnything.profile.update({runId, token, values: {name: "Alice", address: "Road 1"}});
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The main task can use `profile_fill` to reuse existing values and ask for only missing fields through the existing form. Skip/cancel writes nothing. Without save permission, answers are used in the current turn only. An unknown update is never automatically retried; read again to reconcile. A new request token cannot expand the Task's original source. A project admin credential cannot borrow another person's delegation.
|
|
13
|
+
|
|
14
|
+
姓名/地址等资料从原 Task 本人读取。缺失字段使用现有普通表单;跳过不保存。没有保存授权时只供本次使用。读写同时核原 grant 与当前同意、key 和字段权限,新令牌不能扩大旧 Task。提交结果未知时先重新读取,不自动重放。
|
|
15
|
+
|
|
16
|
+
Supported builtins: name, nickname, country, province, city, address, streetAddress, postalCode, company. `customData.<key>` supports visible/editable, nonencrypted primitive STRING/NUMBER/BOOLEAN definitions in the existing UDF store. Custom definitions with validation rules and other UDF types remain unavailable in this ordinary adapter. External custom user databases remain unavailable because they cannot share the GA SQL transaction.
|
|
17
|
+
|
|
18
|
+
Passwords, identity documents, payment fields, credentials, identity tokens and encrypted/desensitised custom fields are excluded. Email/phone changes retain their existing verification flow. Native Console save-only sources have no profile delegation and cannot be upgraded by this API. 本批不包含敏感代填或邮箱业务。
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Quickstart v5 候选合同
|
|
2
|
+
|
|
3
|
+
这些接口从 0.9.2 起随 npm 包发布,需要配套后端;发布不代表完整业务验收,个人 Agent 编排在生产环境尚未开通。
|
|
4
|
+
|
|
5
|
+
## Personal Agent 创建与绑定
|
|
6
|
+
|
|
7
|
+
`genauth.agents.create({displayName, description?, channels: {email}, idempotencyKey?})` 的 `channels.email` 是用户选择的邮箱本地名。返回的 `id`、`email` 仅来自后端已确认的 ready/bound 回执,SDK 不生成地址或补造 ready。旧 `{displayName, idempotencyKey, mailboxLocalPart?}` 方法仍返回 provisioning 回执。
|
|
8
|
+
|
|
9
|
+
新 overload 只发一次 create。后端明确受理、返回合法 provisioningId 且状态为 creating/mail_pending 时,最多进行 20 次只读观察;120 秒总预算从初次 create 前开始,包含该请求及所有等待和观察。每次观察最多 5 秒,受剩余总预算限制,并通过 AbortSignal 取消实际传输。错误或响应未知后不会继续观察或重发 create。
|
|
10
|
+
|
|
11
|
+
失败的 `PersonalAgentCreateError` 保留原错误的 code/status/body/requestId/cause、`retryable: false` 和原 `idempotencyKey`;如果可确认,也保留 provisioningId。调用方可显式执行 `genauth.agents.get(error.recovery)`,按原 key 只读追溯。get 的 provisioningId/agentId/idempotencyKey 三种 selector 恰选一个,原 key 回查要求 `readOnly: true`。
|
|
12
|
+
|
|
13
|
+
自动 key 只保障当前调用能报告其请求身份。App 要跨进程或硬崩溃恢复,须在调用前持久保存显式 key;SDK 不建隐式文件或仅靠内存恢复,也不以 displayName 推测原请求。
|
|
14
|
+
|
|
15
|
+
`genauth.agents.bindUser({agentId, userAccessToken, relation: 'owner'})` 将当前用户 token 发给后端识别本人,验证真实 bound 回执并返回 bindingId/userId。创建、绑定均不授予任务、邮箱或其他业务权限。既有 `agents.bind({provisioningId, accessToken})` 保持兼容。
|
|
16
|
+
|
|
17
|
+
## Formal Agent 委托
|
|
18
|
+
|
|
19
|
+
默认 mode 为 silent,也可显式指定 silent 或 interactive;其他 JavaScript mode 在本地拒绝。formal agentId 必须是 UUID,不能同时使用旧 agent/agentKey 标签。silent 保留明确的目标 userId 要求;interactive 在签名前剔除 user/userId,由真实登录授权决定身份,deprecated 类型兼容不代表采用这些字段。
|
|
20
|
+
|
|
21
|
+
`scopes: ['*']` 仅接受 formal Agent 的默认或显式 silent,不能混入具体 scopes 或 products(包括空数组),不能用于旧标签或 interactive。SDK 原样发送单个星号;后端根据当前 App/凭据、capability、绑定与已有效同意等实际权限有界求交,SDK 不本地展开、缓存授权或扩大权限。要核实实际授予的具体 scopes,应调用 `genauth.introspectDelegationToken({token})`。
|
|
22
|
+
|
|
23
|
+
首次缺少有效授权依据仍可能返回 `needs_authorization`。HTTP 200 内的业务 403 与原 code/body 保持失败;SDK 不自动切换 interactive、续签、重试或替用户同意。显式 interactive 仍需用户完成真实授权,再按正式 complete 接口兑换。
|
|
24
|
+
|
|
25
|
+
## Track 与附件兼容
|
|
26
|
+
|
|
27
|
+
Track 使用实际 `/track/tracks` 合同,保留终态 `done`、409 `task_in_progress` 及真实回执;不自动重跑。未实现的 Track 流式/交互、历史快照及旧 `doAnything.readArtifacts()` 在本地抛出 `QoniUnsupportedError`,不发 HTTP。附件读取沿实际 blob 接口及既有所有者校验。
|
|
28
|
+
|
|
29
|
+
## 本地验证边界
|
|
30
|
+
|
|
31
|
+
`pnpm test` 验证既有 mock、包导出和 Task 回归。Quickstart 新增回归可单独执行:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
pnpm exec vitest run --coverage=false tests/agent-provisioning.test.ts tests/personal-agent-page.test.ts tests/formal-delegation.test.ts tests/formal-agent-silent.test.ts tests/delegation-normalizer-r3.test.ts tests/formal-agent-wildcard.test.ts tests/composed-intersections.test.ts tests/profile.test.ts tests/structured-forms.test.ts tests/structured-forms-r2.test.ts tests/task-mail.test.ts tests/w11-acceptance.test.ts
|
|
35
|
+
pnpm typecheck
|
|
36
|
+
pnpm build
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
这些测试使用 mock 与独立 loopback,不读取真实凭据。它们不证明 GA wildcard 真实签发、邮箱供应商、完整网页业务或 Enterprise namespace/citeSources 记忆接线已通过;这些仍须分别验收。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qoniai/qoni",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Unified Node.js SDK for Qoni Agent delegation, GUMem memory, and WebAgent automation.",
|
|
3
|
+
"version": "0.9.2",
|
|
4
|
+
"description": "Unified Node.js SDK for Qoni Agent delegation, GenAuth management, GUMem memory, and WebAgent automation.",
|
|
5
5
|
"homepage": "https://github.com/QONIAI/qoni-sdk-node#readme",
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/QONIAI/qoni-sdk-node/issues"
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"sdk",
|
|
20
20
|
"delegation",
|
|
21
21
|
"gumem",
|
|
22
|
-
"webagent"
|
|
22
|
+
"webagent",
|
|
23
|
+
"genauth",
|
|
24
|
+
"authing",
|
|
25
|
+
"management"
|
|
23
26
|
],
|
|
24
27
|
"main": "./dist/index.cjs",
|
|
25
28
|
"module": "./dist/index.js",
|
|
@@ -45,20 +48,27 @@
|
|
|
45
48
|
"check:brand": "node scripts/check-brand.mjs",
|
|
46
49
|
"gen:event-types": "node scripts/gen-event-types.mjs",
|
|
47
50
|
"typecheck": "tsc --noEmit",
|
|
48
|
-
"test": "pnpm build && pnpm check:brand && pnpm test:mock && pnpm test:package",
|
|
49
|
-
"test:mock": "vitest run --coverage=false tests/qoni.test.ts tests/semantic-surface.test.ts tests/open-source-readiness.test.ts tests/complete-coverage.test.ts tests/event-catalog.test.ts tests/interactions.test.ts tests/contract-surface.test.ts tests/sse-abort.test.ts tests/do-anything-evidence.test.ts tests/query-matrix.test.ts tests/live-evidence.test.ts tests/site-login-settle-track.test.ts tests/abstract-interactions.test.ts",
|
|
51
|
+
"test": "pnpm build && pnpm check:brand && pnpm test:mock && pnpm test:package && pnpm test:task",
|
|
52
|
+
"test:mock": "vitest run --coverage=false tests/qoni.test.ts tests/semantic-surface.test.ts tests/open-source-readiness.test.ts tests/complete-coverage.test.ts tests/event-catalog.test.ts tests/interactions.test.ts tests/contract-surface.test.ts tests/sse-abort.test.ts tests/do-anything-evidence.test.ts tests/query-matrix.test.ts tests/live-evidence.test.ts tests/site-login-settle-track.test.ts tests/abstract-interactions.test.ts tests/genauth-management.test.ts tests/genauth-communication.test.ts tests/genauth-hosted-login.test.ts tests/personal-agent-page.test.ts tests/agent-provisioning.test.ts tests/formal-agent-silent.test.ts tests/formal-agent-wildcard.test.ts tests/delegation-normalizer-r3.test.ts tests/gray-track-contract.test.ts tests/current-task-login.test.ts tests/memory-context.test.ts tests/memory-submit-outcome.test.ts tests/task-scopes.test.ts",
|
|
50
53
|
"test:e2e": "QONI_LIVE_E2E=1 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=120000 tests/live-e2e/*.test.ts",
|
|
51
54
|
"test:e2e:do-anything": "QONI_LIVE_E2E=1 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=120000 tests/live-e2e/do-anything.test.ts",
|
|
52
55
|
"test:e2e:do-anything:release": "QONI_LIVE_E2E=1 QONI_LIVE_ALLOW_ENV_CONSTRAINTS=0 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=120000 tests/live-e2e/do-anything.test.ts",
|
|
53
56
|
"test:e2e:matrix": "QONI_LIVE_E2E=1 QONI_QUERY_MATRIX=1 QONI_LIVE_ALLOW_ENV_CONSTRAINTS=0 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 tests/live-e2e/query-matrix.test.ts",
|
|
54
57
|
"test:e2e:release": "QONI_LIVE_E2E=1 QONI_LIVE_REQUIRE_ALL=1 QONI_LIVE_ALLOW_ENV_CONSTRAINTS=0 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=120000 tests/live-e2e/*.test.ts",
|
|
55
58
|
"test:package": "vitest run --coverage=false tests/package-surface.test.ts",
|
|
56
|
-
"test:ci": "pnpm test:mock && pnpm test:package",
|
|
59
|
+
"test:ci": "pnpm test:mock && pnpm test:package && pnpm test:task",
|
|
57
60
|
"smoke:auth-gum": "pnpm build && node scripts/qoni-auth-gum-smoke.mjs --mock",
|
|
58
61
|
"smoke:auth-gum:live": "pnpm build && QONI_SMOKE_MODE=live node scripts/qoni-auth-gum-smoke.mjs --live",
|
|
59
62
|
"pack:dry-run": "pnpm build && pnpm pack --dry-run",
|
|
60
63
|
"prepack": "pnpm build",
|
|
61
|
-
"prepare": "tsup"
|
|
64
|
+
"prepare": "tsup",
|
|
65
|
+
"gen:genauth-management": "node scripts/gen-genauth-management.mjs",
|
|
66
|
+
"test:e2e:genauth": "QONI_LIVE_E2E=1 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=30000 tests/live-e2e/genauth-management.test.ts",
|
|
67
|
+
"gen:genauth-communication": "node scripts/gen-genauth-communication.mjs",
|
|
68
|
+
"check:genauth-communication": "node scripts/gen-genauth-communication.mjs --check",
|
|
69
|
+
"test:e2e:communication": "QONI_LIVE_E2E=1 vitest run --coverage=false --fileParallelism=false --maxWorkers=1 --testTimeout=30000 tests/live-e2e/genauth-communication.test.ts",
|
|
70
|
+
"check:genauth-communication-examples": "node scripts/check-genauth-communication-examples.mjs",
|
|
71
|
+
"test:task": "vitest run --coverage=false tests/task-client.test.ts tests/task-client-http.test.ts tests/task-client-types.test.ts"
|
|
62
72
|
},
|
|
63
73
|
"publishConfig": {
|
|
64
74
|
"access": "public"
|