@qoniai/qoni 0.4.4 → 0.5.1
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 +23 -0
- package/README.md +13 -0
- package/README.zh-CN.md +11 -0
- package/dist/index.cjs +35 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +35 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.1 - 2026-09-23
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Recheck access-key scope policy at token exchange before every SDK product
|
|
8
|
+
operation, including repeated calls with the same delegation token. Removing
|
|
9
|
+
a scope now blocks the next SDK operation instead of leaving a cached product
|
|
10
|
+
token usable until expiry.
|
|
11
|
+
|
|
12
|
+
## 0.5.0 - 2026-09-17
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Let Do Anything callers select a server-managed Browserbase proxy by ID, choose
|
|
17
|
+
`off`, `all`, or `scoped` routing, and select a supported Browserbase compute
|
|
18
|
+
region with `browserProxy`.
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
|
|
22
|
+
- Reject proxy URLs, usernames, passwords, and any unknown proxy option locally.
|
|
23
|
+
Proxy credentials remain in the backend's private registry and never cross the
|
|
24
|
+
public SDK API.
|
|
25
|
+
|
|
3
26
|
## 0.4.4
|
|
4
27
|
|
|
5
28
|
- Populate Do Anything `result.artifacts` from durable run files, including attached runs.
|
package/README.md
CHANGED
|
@@ -391,12 +391,22 @@ const context = await qoni.gumem.recall({
|
|
|
391
391
|
const run = await qoni.doAnything.run({
|
|
392
392
|
token,
|
|
393
393
|
prompt: "Open https://en.wikipedia.org/wiki/Solid-state_battery and summarize its key advantages over lithium-ion.",
|
|
394
|
+
browserProxy: {
|
|
395
|
+
proxyId: "sg-static", // server-side registry id; never pass credentials here
|
|
396
|
+
mode: "scoped", // off | all | scoped
|
|
397
|
+
region: "ap-southeast-1",
|
|
398
|
+
},
|
|
394
399
|
});
|
|
395
400
|
|
|
396
401
|
const status = await run.status(); // refresh the run's current state
|
|
397
402
|
await run.cancel("User stopped the task"); // idempotent
|
|
398
403
|
```
|
|
399
404
|
|
|
405
|
+
`browserProxy` affects only newly created Browserbase sessions. `region` selects
|
|
406
|
+
Browserbase compute, while the registered proxy controls network egress. The SDK
|
|
407
|
+
accepts only a proxy ID, mode, and region; operators manage proxy credentials in
|
|
408
|
+
OpsConsole.
|
|
409
|
+
|
|
400
410
|
### Web Search
|
|
401
411
|
|
|
402
412
|
```ts
|
|
@@ -778,6 +788,9 @@ Common first-run errors:
|
|
|
778
788
|
- Keep Qoni AK/SK on trusted servers only.
|
|
779
789
|
- Do not expose delegation tokens to untrusted clients.
|
|
780
790
|
- Request the smallest useful scope set for each Agent action.
|
|
791
|
+
- Product methods exchange the delegation token on every call, so a change to
|
|
792
|
+
the access key's allowed scopes is checked before the next SDK operation.
|
|
793
|
+
Product tokens already obtained outside the SDK remain valid until expiry.
|
|
781
794
|
- Prefer `interactive` mode for browser control, site login, long-running monitors, and sensitive artifacts.
|
|
782
795
|
- Store `auditId`, `requestId`, and `traceId` with product logs when later investigation matters.
|
|
783
796
|
- Rotate AK/SK through Qoni Console if a credential might have been exposed.
|
package/README.zh-CN.md
CHANGED
|
@@ -362,12 +362,21 @@ const context = await qoni.gumem.recall({
|
|
|
362
362
|
const run = await qoni.doAnything.run({
|
|
363
363
|
token,
|
|
364
364
|
prompt: "打开 https://en.wikipedia.org/wiki/Solid-state_battery ,总结它相对锂离子电池的主要优势。",
|
|
365
|
+
browserProxy: {
|
|
366
|
+
proxyId: "sg-static", // 服务端代理注册表 ID;这里绝不传凭据
|
|
367
|
+
mode: "scoped", // off | all | scoped
|
|
368
|
+
region: "ap-southeast-1",
|
|
369
|
+
},
|
|
365
370
|
});
|
|
366
371
|
|
|
367
372
|
const status = await run.status(); // 刷新并返回当前状态
|
|
368
373
|
await run.cancel("用户停止任务"); // 幂等
|
|
369
374
|
```
|
|
370
375
|
|
|
376
|
+
`browserProxy` 只影响新建的 Browserbase 会话。`region` 选择 Browserbase
|
|
377
|
+
计算区域,注册代理决定网络出口。SDK 只接受代理 ID、模式和区域;代理账号密码由
|
|
378
|
+
运维人员在 OpsConsole 管理。
|
|
379
|
+
|
|
371
380
|
### Web Search
|
|
372
381
|
|
|
373
382
|
```ts
|
|
@@ -708,6 +717,8 @@ try {
|
|
|
708
717
|
- AK/SK 只保存在可信服务端。
|
|
709
718
|
- 不要把 delegation token 暴露给不可信客户端。
|
|
710
719
|
- 每次 Agent 行动只申请必要 scope。
|
|
720
|
+
- SDK 的产品方法每次调用前都会重新兑换 delegation token,因此 AccessKey 的 scope
|
|
721
|
+
变更会在下一次 SDK 调用前重新校验。已经在 SDK 外取得的产品 token 仍会持续有效至过期。
|
|
711
722
|
- 浏览器接管、站点登录、长期监控、敏感产物访问优先使用 `interactive`。
|
|
712
723
|
- 在业务日志中记录 `auditId`、`requestId`、`traceId`,方便后续审计。
|
|
713
724
|
- 如果怀疑 AK/SK 泄露,应在 Qoni Console 中轮换密钥。
|
package/dist/index.cjs
CHANGED
|
@@ -1194,6 +1194,34 @@ var PLATFORM_DECIDED_RUN_OPTIONS = [
|
|
|
1194
1194
|
"outputSchema",
|
|
1195
1195
|
"cacheScript"
|
|
1196
1196
|
];
|
|
1197
|
+
var BROWSERBASE_REGIONS = /* @__PURE__ */ new Set([
|
|
1198
|
+
"us-west-2",
|
|
1199
|
+
"us-east-1",
|
|
1200
|
+
"eu-central-1",
|
|
1201
|
+
"ap-southeast-1"
|
|
1202
|
+
]);
|
|
1203
|
+
function validateBrowserProxyOptions(value) {
|
|
1204
|
+
if (value === void 0) return;
|
|
1205
|
+
if (!isJsonObject(value)) {
|
|
1206
|
+
throw new QoniValidationError("browserProxy must be an object");
|
|
1207
|
+
}
|
|
1208
|
+
const allowed = /* @__PURE__ */ new Set(["proxyId", "mode", "region"]);
|
|
1209
|
+
const extras = Object.keys(value).filter((key) => !allowed.has(key));
|
|
1210
|
+
if (extras.length > 0) {
|
|
1211
|
+
throw new QoniValidationError(
|
|
1212
|
+
`browserProxy does not accept ${extras.join(", ")} \u2014 credentials stay server-side`
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
if (value.proxyId !== void 0 && (typeof value.proxyId !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}$/.test(value.proxyId))) {
|
|
1216
|
+
throw new QoniValidationError("browserProxy.proxyId is invalid");
|
|
1217
|
+
}
|
|
1218
|
+
if (value.mode !== void 0 && !["off", "all", "scoped"].includes(String(value.mode))) {
|
|
1219
|
+
throw new QoniValidationError("browserProxy.mode must be off, all, or scoped");
|
|
1220
|
+
}
|
|
1221
|
+
if (value.region !== void 0 && (typeof value.region !== "string" || !BROWSERBASE_REGIONS.has(value.region))) {
|
|
1222
|
+
throw new QoniValidationError("browserProxy.region is not supported");
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1197
1225
|
function createDoAnythingNamespace(transport) {
|
|
1198
1226
|
const api = {
|
|
1199
1227
|
createSession: (input) => transport.webAgentJson("POST", "/do_anything/sessions", input.token, {
|
|
@@ -1356,6 +1384,7 @@ function createDoAnythingNamespace(transport) {
|
|
|
1356
1384
|
if (!prompt || typeof prompt !== "string") {
|
|
1357
1385
|
throw new QoniValidationError("doAnything.run requires a prompt string");
|
|
1358
1386
|
}
|
|
1387
|
+
validateBrowserProxyOptions(rest.browserProxy);
|
|
1359
1388
|
const unsupported = PLATFORM_DECIDED_RUN_OPTIONS.filter(
|
|
1360
1389
|
(key) => rest[key] !== void 0
|
|
1361
1390
|
);
|
|
@@ -1407,8 +1436,13 @@ function normalizeDoAnythingRunInput(input) {
|
|
|
1407
1436
|
profileId: "profile_id",
|
|
1408
1437
|
keepAlive: "keep_alive",
|
|
1409
1438
|
allowedActions: "allowed_actions",
|
|
1410
|
-
maxDurationMinutes: "max_duration_minutes"
|
|
1439
|
+
maxDurationMinutes: "max_duration_minutes",
|
|
1440
|
+
browserProxy: "browser_proxy"
|
|
1411
1441
|
});
|
|
1442
|
+
const browserProxy = body.browser_proxy;
|
|
1443
|
+
if (isJsonObject(browserProxy)) {
|
|
1444
|
+
body.browser_proxy = renameKeys2(browserProxy, { proxyId: "proxy_id" });
|
|
1445
|
+
}
|
|
1412
1446
|
return body;
|
|
1413
1447
|
}
|
|
1414
1448
|
function normalizeDoAnythingInterveneInput(input) {
|
|
@@ -2080,7 +2114,6 @@ var Qoni = class {
|
|
|
2080
2114
|
secretKey;
|
|
2081
2115
|
host;
|
|
2082
2116
|
runtimeConfigPromise;
|
|
2083
|
-
productTokenCache = /* @__PURE__ */ new Map();
|
|
2084
2117
|
genAuthAdminTokenCache;
|
|
2085
2118
|
gumem;
|
|
2086
2119
|
genauth;
|
|
@@ -2551,9 +2584,6 @@ var Qoni = class {
|
|
|
2551
2584
|
const runtimeToken = requiredRuntimeToken(token);
|
|
2552
2585
|
if (!isQoniDelegationToken(runtimeToken)) return runtimeToken;
|
|
2553
2586
|
const scopes = [...requiredScopes || []].sort();
|
|
2554
|
-
const cacheKey = [service, runtimeToken, scopes.join(" ")].join(":");
|
|
2555
|
-
const cached = this.productTokenCache.get(cacheKey);
|
|
2556
|
-
if (cached && cached.expiresAt > Date.now() + 3e4) return cached.token;
|
|
2557
2587
|
const response = await this.signedPost("/api/v3/eak/token-exchange", {
|
|
2558
2588
|
subjectToken: runtimeToken,
|
|
2559
2589
|
resource: service === "gumem" ? "gumem" : "webagent",
|
|
@@ -2568,10 +2598,6 @@ var Qoni = class {
|
|
|
2568
2598
|
"Qoni product token exchange response did not include an access token"
|
|
2569
2599
|
);
|
|
2570
2600
|
}
|
|
2571
|
-
this.productTokenCache.set(cacheKey, {
|
|
2572
|
-
token: accessToken,
|
|
2573
|
-
expiresAt: Date.now() + Math.max(0, readExpiresIn(payload) ?? 3600) * 1e3
|
|
2574
|
-
});
|
|
2575
2601
|
return accessToken;
|
|
2576
2602
|
}
|
|
2577
2603
|
async genauthAdminTokenFor() {
|