@zoowork-ai/sdk 0.4.1 → 0.5.0
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 +46 -0
- package/dist/client.d.ts +135 -59
- package/dist/client.js +18 -11
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,52 @@
|
|
|
3
3
|
All notable changes to `@zoowork-ai/sdk` (formerly `@zooclaw-agents/sdk`). Dates are the
|
|
4
4
|
day the behaviour was verified, not the day it was written.
|
|
5
5
|
|
|
6
|
+
## 0.5.0 — 2026-08-28
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **The QR flow now covers WeCom and WeChat, not just Feishu** — gateway PR #3512 shipped
|
|
11
|
+
`/channels/{wecom,weixin}/{setup,poll,setup-cancel}`, and 0.4.x had no way to call them.
|
|
12
|
+
Four platform-taking methods replace the four Feishu-only ones:
|
|
13
|
+
`startChannelSetup(agentId, platform, input?)`, `pollChannelSetup`, `cancelChannelSetup`,
|
|
14
|
+
`waitForChannelSetup`. New types `ChannelSetupInput`, `ChannelSetupSession`,
|
|
15
|
+
`ChannelPollResult`, `GuidedSetupPlatform` (`'feishu' | 'wecom' | 'weixin'`) and
|
|
16
|
+
`AddChannelPlatform`.
|
|
17
|
+
- **`startFeishuSetup` / `pollFeishuSetup` / `cancelFeishuSetup` / `waitForFeishuSetup` still
|
|
18
|
+
work** — they now delegate to the platform-taking versions. `FeishuSetupInput` and
|
|
19
|
+
`FeishuPollResult` are aliases of the new names; `FeishuSetupSession` narrows
|
|
20
|
+
`ChannelSetupSession` to the one platform that always answers `verification_uri_complete`.
|
|
21
|
+
Only the message text of a thrown timeout/abort changed (it names `waitForChannelSetup` and
|
|
22
|
+
the platform); `status` and `type` are unchanged.
|
|
23
|
+
|
|
24
|
+
### Documentation
|
|
25
|
+
|
|
26
|
+
- **`ChannelPlatform` gains `'weixin'`, and WeChat is no longer described as unbindable.**
|
|
27
|
+
0.3.2–0.4.2 said WeChat "answers `400 channel.weixin_setup_required`, naming a QR flow this
|
|
28
|
+
API does not expose". The flow exists now; that error is a signpost to it, not a dead end.
|
|
29
|
+
`addChannel` still refuses WeChat, so `AddChannelPlatform` is the type that lists what it
|
|
30
|
+
takes.
|
|
31
|
+
- **Per-platform shapes, staging-verified 2026-08-28** (`notes/probes/channels-guided-probe.mts`):
|
|
32
|
+
Feishu answers `verification_uri_complete` + `poll_interval: 5`, `expires_in: 600`; WeCom and
|
|
33
|
+
WeChat answer `qrcode_url` with no `poll_interval` and `expires_in: 300`; WeChat's
|
|
34
|
+
`qrcode_url` may be an inline `data:image/…` payload rather than a URL. WeChat reads only
|
|
35
|
+
`dm_policy` and only `'open'`/`'disabled'` — `'allowlist'` is
|
|
36
|
+
`400 channel.allowlist_unsupported` — pins the account to `'default'`, and ignores anything
|
|
37
|
+
else in the body. Cancelled sessions 404 per platform:
|
|
38
|
+
`channel.{feishu,wecom,weixin}_session_not_found`.
|
|
39
|
+
|
|
40
|
+
## 0.4.2 — 2026-08-25
|
|
41
|
+
|
|
42
|
+
### Documentation
|
|
43
|
+
|
|
44
|
+
- **`addChannel` is idempotent, not an upsert — 0.3.4 said the opposite.** Re-posting an
|
|
45
|
+
identical body for the same `platform` + `account` replays the binding you already have and
|
|
46
|
+
answers `201` again; that same pair with a **different** `config` answers
|
|
47
|
+
`409 channel.conflict`. Rotating credentials therefore means `removeChannel` and then a
|
|
48
|
+
fresh `addChannel` — a plain re-add fails. The earlier note came from re-posting the same
|
|
49
|
+
body, where a replay cannot be told apart from an overwrite; the conflict path was measured
|
|
50
|
+
on staging 2026-08-25. No signature or behaviour change.
|
|
51
|
+
|
|
6
52
|
## 0.4.1 — 2026-08-25
|
|
7
53
|
|
|
8
54
|
### Internal
|
package/dist/client.d.ts
CHANGED
|
@@ -259,22 +259,47 @@ export interface AgentChannel {
|
|
|
259
259
|
[k: string]: unknown;
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
262
|
-
* The chat platforms you can bind, staging-verified 2026-08-
|
|
262
|
+
* The chat platforms you can bind, staging-verified 2026-08-28.
|
|
263
263
|
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* this API yet, so today it also binds through `addChannel`.
|
|
264
|
+
* Three of them have a server-driven QR flow ({@link GuidedSetupPlatform}); Slack does not,
|
|
265
|
+
* and structurally cannot — a Slack app is created by a person and its tokens only ever exist
|
|
266
|
+
* in that person's browser, so {@link AddChannelInput} with `botToken` + `appToken` is its
|
|
267
|
+
* permanent path.
|
|
269
268
|
*
|
|
270
|
-
* WeChat
|
|
271
|
-
* `400 channel.weixin_setup_required`,
|
|
272
|
-
* name
|
|
269
|
+
* WeChat is the one platform that goes the other way: `'weixin'`/`'wechat'` on
|
|
270
|
+
* {@link ZooworkClient.addChannel} answers `400 channel.weixin_setup_required`, so the QR flow
|
|
271
|
+
* is its ONLY path. See {@link AddChannelPlatform}. Any name outside this type answers
|
|
272
|
+
* `400 channel.invalid_request`.
|
|
273
273
|
*/
|
|
274
|
-
export type ChannelPlatform = 'feishu' | 'slack' | 'wecom';
|
|
274
|
+
export type ChannelPlatform = 'feishu' | 'slack' | 'wecom' | 'weixin';
|
|
275
|
+
/**
|
|
276
|
+
* The platforms {@link ZooworkClient.addChannel} accepts — every {@link ChannelPlatform}
|
|
277
|
+
* except WeChat, which refuses explicit config and takes the QR flow only.
|
|
278
|
+
*/
|
|
279
|
+
export type AddChannelPlatform = 'feishu' | 'slack' | 'wecom';
|
|
280
|
+
/**
|
|
281
|
+
* The platforms with a server-driven QR flow: {@link ZooworkClient.startChannelSetup} →
|
|
282
|
+
* render the URI → poll. Slack is absent by design, not by omission.
|
|
283
|
+
*
|
|
284
|
+
* The three differ in what the setup answer carries and in what the body may say
|
|
285
|
+
* (staging-verified 2026-08-28):
|
|
286
|
+
*
|
|
287
|
+
* - `feishu` — answers `verification_uri_complete` and a `poll_interval`; takes `brand`,
|
|
288
|
+
* `account`, `dm_policy`, `group_policy`; `expires_in: 600`.
|
|
289
|
+
* - `wecom` — answers `qrcode_url` and NO `poll_interval` (you pick the cadence); takes
|
|
290
|
+
* `account`, `dm_policy`, `group_policy`; `expires_in: 300`.
|
|
291
|
+
* - `weixin` — answers `qrcode_url`, which may be a URL *or* an inline `data:image/…` payload;
|
|
292
|
+
* takes `dm_policy` only, `'open'` or `'disabled'` (the account is pinned to `'default'` and
|
|
293
|
+
* the group policy to `'disabled'` server-side); `expires_in: 300`.
|
|
294
|
+
*/
|
|
295
|
+
export type GuidedSetupPlatform = 'feishu' | 'wecom' | 'weixin';
|
|
275
296
|
export interface AddChannelInput {
|
|
276
|
-
/**
|
|
277
|
-
|
|
297
|
+
/**
|
|
298
|
+
* See {@link AddChannelPlatform}. Typed loosely so a newly supported platform needs no SDK
|
|
299
|
+
* release. `'weixin'`/`'wechat'` is refused here with `400 channel.weixin_setup_required` —
|
|
300
|
+
* use {@link ZooworkClient.startChannelSetup} instead.
|
|
301
|
+
*/
|
|
302
|
+
platform: AddChannelPlatform | (string & {});
|
|
278
303
|
/**
|
|
279
304
|
* Names this binding. It is part of the record's identity, not a setting: `updateChannel`
|
|
280
305
|
* and `removeChannel` find a binding by `platform` + `account`, and nothing renames one
|
|
@@ -324,8 +349,14 @@ export interface UpdateChannelInput {
|
|
|
324
349
|
group_policy?: string;
|
|
325
350
|
enabled?: boolean;
|
|
326
351
|
}
|
|
327
|
-
|
|
328
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Body for {@link ZooworkClient.startChannelSetup}. Every field is optional, and each platform
|
|
354
|
+
* reads a different subset — see {@link GuidedSetupPlatform}. A field a platform does not read
|
|
355
|
+
* is ignored rather than rejected: `weixin` accepts an `account` in the body and still binds
|
|
356
|
+
* `'default'` (staging-verified 2026-08-28).
|
|
357
|
+
*/
|
|
358
|
+
export interface ChannelSetupInput {
|
|
359
|
+
/** Feishu only: `'feishu'` (default) or `'lark'` — the international brand of the same platform. */
|
|
329
360
|
brand?: 'feishu' | 'lark';
|
|
330
361
|
/**
|
|
331
362
|
* Names this binding. It is part of the record's identity, not a setting: `updateChannel`
|
|
@@ -351,37 +382,60 @@ export interface FeishuSetupInput {
|
|
|
351
382
|
* works as-is: it matches the pattern and is unique per agent by construction.
|
|
352
383
|
*/
|
|
353
384
|
account?: string;
|
|
354
|
-
/**
|
|
385
|
+
/**
|
|
386
|
+
* Server default: `'open'`. WeChat takes only `'open'` or `'disabled'` — `'allowlist'` is
|
|
387
|
+
* `400 channel.allowlist_unsupported` there, and `'pairing'` is
|
|
388
|
+
* `400 channel.pairing_unsupported` on every platform.
|
|
389
|
+
*/
|
|
355
390
|
dm_policy?: string;
|
|
356
|
-
/** Server default: `'open'`. */
|
|
391
|
+
/** Server default: `'open'`. Ignored by WeChat, which forces `'disabled'`. */
|
|
357
392
|
group_policy?: string;
|
|
358
393
|
}
|
|
394
|
+
/** @deprecated Use {@link ChannelSetupInput}; this is the same shape under the old name. */
|
|
395
|
+
export type FeishuSetupInput = ChannelSetupInput;
|
|
359
396
|
/**
|
|
360
|
-
* A running
|
|
361
|
-
*
|
|
362
|
-
* `
|
|
363
|
-
*
|
|
397
|
+
* A running QR registration. Show the person doing the binding whichever URI the platform
|
|
398
|
+
* answered — `verification_uri_complete` for Feishu, `qrcode_url` for WeCom and WeChat, so
|
|
399
|
+
* `session.verification_uri_complete ?? session.qrcode_url` is the value to render — then poll
|
|
400
|
+
* with {@link ZooworkClient.pollChannelSetup} / {@link ZooworkClient.waitForChannelSetup} until
|
|
401
|
+
* it leaves `pending`. The session expires after `expires_in` seconds.
|
|
402
|
+
*
|
|
403
|
+
* Two of the three are QR-only: WeCom's `qrcode_url` is a URL you encode yourself, and WeChat's
|
|
404
|
+
* may be a URL *or* an inline `data:image/…` payload you render directly, so check the prefix
|
|
405
|
+
* before you feed it to a QR encoder.
|
|
364
406
|
*/
|
|
365
|
-
export interface
|
|
407
|
+
export interface ChannelSetupSession {
|
|
366
408
|
session_id: string;
|
|
367
|
-
|
|
409
|
+
/** Feishu only — the URI to encode into a QR code. */
|
|
410
|
+
verification_uri_complete?: string;
|
|
411
|
+
/** WeCom and WeChat — a URL to encode, or (WeChat) an inline `data:image/…` image. */
|
|
412
|
+
qrcode_url?: string;
|
|
368
413
|
expires_in: number;
|
|
369
|
-
/** Suggested seconds between polls;
|
|
414
|
+
/** Suggested seconds between polls. Feishu sends it; WeCom and WeChat never do. */
|
|
370
415
|
poll_interval?: number | null;
|
|
371
416
|
[k: string]: unknown;
|
|
372
417
|
}
|
|
373
418
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
|
|
419
|
+
* A running Feishu QR registration — {@link ChannelSetupSession} narrowed to the one platform
|
|
420
|
+
* that always answers `verification_uri_complete`.
|
|
421
|
+
*/
|
|
422
|
+
export interface FeishuSetupSession extends ChannelSetupSession {
|
|
423
|
+
verification_uri_complete: string;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* One poll of a setup session. The gateway's own vocabulary for `status` is
|
|
427
|
+
* `pending | success | expired | denied | error` (`denied` is Feishu-only); treat anything
|
|
428
|
+
* unknown as still-in-flight rather than throwing.
|
|
377
429
|
*/
|
|
378
|
-
export interface
|
|
430
|
+
export interface ChannelPollResult {
|
|
379
431
|
status: string;
|
|
380
432
|
channel_configured?: boolean;
|
|
381
433
|
message?: string | null;
|
|
382
434
|
poll_interval?: number | null;
|
|
383
435
|
[k: string]: unknown;
|
|
384
436
|
}
|
|
437
|
+
/** @deprecated Use {@link ChannelPollResult}; this is the same shape under the old name. */
|
|
438
|
+
export type FeishuPollResult = ChannelPollResult;
|
|
385
439
|
export interface AgentRecord {
|
|
386
440
|
agent_id: string;
|
|
387
441
|
computer_id?: string;
|
|
@@ -1053,11 +1107,15 @@ export interface ZooworkClient {
|
|
|
1053
1107
|
/**
|
|
1054
1108
|
* Bind a channel from explicit platform config (the non-QR path) — `config` carries the
|
|
1055
1109
|
* platform's own credential keys. Answers the created channel (HTTP 201). This is the ONLY
|
|
1056
|
-
* path for Slack
|
|
1057
|
-
*
|
|
1110
|
+
* path for Slack, an alternative to the QR flow for Feishu and WeCom, and refused outright
|
|
1111
|
+
* for WeChat (`400 channel.weixin_setup_required`). See {@link AddChannelPlatform}.
|
|
1058
1112
|
*
|
|
1059
|
-
* **It is
|
|
1060
|
-
* `201` again and
|
|
1113
|
+
* **It is idempotent, not an upsert.** Re-posting an identical body for the same
|
|
1114
|
+
* `platform` + `account` answers `201` again and replays the binding you already have — it
|
|
1115
|
+
* neither creates a second channel nor overwrites the first. That same pair with a DIFFERENT
|
|
1116
|
+
* `config` answers `409 channel.conflict`, so rotating credentials means
|
|
1117
|
+
* {@link removeChannel} and then a fresh `addChannel`; a plain re-add fails
|
|
1118
|
+
* (staging-verified 2026-08-25).
|
|
1061
1119
|
*
|
|
1062
1120
|
* ⚠️ **201 means STORED, not WORKING.** Credentials are not validated at bind time: a channel
|
|
1063
1121
|
* created from deliberately bogus credentials still answered 201 with `health: 'unknown'`,
|
|
@@ -1086,52 +1144,70 @@ export interface ZooworkClient {
|
|
|
1086
1144
|
account?: string;
|
|
1087
1145
|
}): Promise<void>;
|
|
1088
1146
|
/**
|
|
1089
|
-
* Start the
|
|
1090
|
-
* `verification_uri_complete`
|
|
1091
|
-
*
|
|
1147
|
+
* Start a QR registration on one of the three guided platforms. YOU own the UI: render the
|
|
1148
|
+
* URI the session answers (`verification_uri_complete` for Feishu, `qrcode_url` for WeCom and
|
|
1149
|
+
* WeChat) and drive the poll loop — {@link waitForChannelSetup} does the loop part for you.
|
|
1150
|
+
*
|
|
1151
|
+
* What each platform reads from `input`, and what it answers, is in
|
|
1152
|
+
* {@link GuidedSetupPlatform}; the short version is that only Feishu takes `brand`, only
|
|
1153
|
+
* Feishu and WeCom take `account`, and only Feishu sends back a `poll_interval`.
|
|
1092
1154
|
*
|
|
1093
|
-
*
|
|
1094
|
-
* `'
|
|
1095
|
-
*
|
|
1155
|
+
* For Feishu, `brand` picks the real host — `'feishu'` answers an `open.feishu.cn` URI,
|
|
1156
|
+
* `'lark'` an `open.larksuite.com` one — so it has to match the workspace the person will
|
|
1157
|
+
* approve it in.
|
|
1096
1158
|
*
|
|
1097
|
-
* Pick `account` before you show the QR.
|
|
1098
|
-
*
|
|
1159
|
+
* Pick `account` before you show the QR. On Feishu, approving the scan registers a NEW app in
|
|
1160
|
+
* that workspace, and only then does the binding get written — so a name clash surfaces as
|
|
1099
1161
|
* `409 channel.conflict` AFTER someone has scanned, with the freshly registered app left
|
|
1100
1162
|
* behind in their workspace. Retrying under the same name repeats both. See
|
|
1101
1163
|
* {@link AddChannelInput.account} for how names are scoped.
|
|
1102
1164
|
*/
|
|
1103
|
-
|
|
1165
|
+
startChannelSetup(agentId: string, platform: GuidedSetupPlatform, input?: ChannelSetupInput): Promise<ChannelSetupSession>;
|
|
1104
1166
|
/**
|
|
1105
|
-
* One poll of a setup session. `status: 'pending'` means keep going; a cancelled
|
|
1106
|
-
*
|
|
1107
|
-
*
|
|
1167
|
+
* One poll of a setup session. `status: 'pending'` means keep going; a cancelled session
|
|
1168
|
+
* answers `404 channel.{platform}_session_not_found` rather than a terminal status, so a
|
|
1169
|
+
* hand-rolled loop must treat that 404 as an end condition, not as a transport error.
|
|
1108
1170
|
*/
|
|
1109
|
-
|
|
1110
|
-
/** Abandon a setup session. Afterwards polling it answers `404 channel.
|
|
1111
|
-
|
|
1171
|
+
pollChannelSetup(agentId: string, platform: GuidedSetupPlatform, sessionId: string): Promise<ChannelPollResult>;
|
|
1172
|
+
/** Abandon a setup session. Afterwards polling it answers `404 channel.{platform}_session_not_found`. */
|
|
1173
|
+
cancelChannelSetup(agentId: string, platform: GuidedSetupPlatform, sessionId: string): Promise<void>;
|
|
1112
1174
|
/**
|
|
1113
|
-
* Poll a
|
|
1175
|
+
* Poll a setup session until it leaves `pending`, then hand back that terminal poll.
|
|
1114
1176
|
* A status the server reports in the body — `success` / `expired` / `denied` / `error` — is
|
|
1115
1177
|
* RETURNED, not thrown: "the person rejected it" is an outcome, not an exception.
|
|
1116
1178
|
*
|
|
1117
1179
|
* But a session can also stop existing, and then polling answers
|
|
1118
|
-
* `404 channel.
|
|
1119
|
-
* {@link ZooworkError} carrying that `type`. Confirmed for a cancelled session
|
|
1120
|
-
* (staging 2026-08-
|
|
1121
|
-
* `status: 'expired'` in a 200 or disappears into this 404 was NOT observed — handle
|
|
1180
|
+
* `404 channel.{platform}_session_not_found`, which surfaces here as a thrown
|
|
1181
|
+
* {@link ZooworkError} carrying that `type`. Confirmed for a cancelled session on all three
|
|
1182
|
+
* platforms (staging 2026-08-28); whether a session that simply runs past `expires_in`
|
|
1183
|
+
* reports `status: 'expired'` in a 200 or disappears into this 404 was NOT observed — handle
|
|
1184
|
+
* both.
|
|
1122
1185
|
*
|
|
1123
|
-
* Pacing follows the server's `poll_interval` when present (
|
|
1124
|
-
*
|
|
1125
|
-
* pass the session's own value when you
|
|
1126
|
-
*
|
|
1127
|
-
* and every in-flight poll is bounded the way
|
|
1128
|
-
* `onPoll` fires after every poll, terminal one
|
|
1186
|
+
* Pacing follows the server's `poll_interval` when present (Feishu sends 5s; WeCom and WeChat
|
|
1187
|
+
* send none and fall back to the same 5s). The default budget is 600s, which matches Feishu's
|
|
1188
|
+
* `expires_in` but is twice WeCom's and WeChat's 300s — pass the session's own value when you
|
|
1189
|
+
* have it. On timeout it throws `status: 408` / `type: 'timeout'`; on abort, `status: 0` /
|
|
1190
|
+
* `type: 'aborted'` — both synthesized locally, and every in-flight poll is bounded the way
|
|
1191
|
+
* {@link waitUntilRunning} bounds its polls. `onPoll` fires after every poll, terminal one
|
|
1192
|
+
* included, for progress UI.
|
|
1129
1193
|
*/
|
|
1194
|
+
waitForChannelSetup(agentId: string, platform: GuidedSetupPlatform, sessionId: string, opts?: {
|
|
1195
|
+
timeoutMs?: number;
|
|
1196
|
+
signal?: AbortSignal;
|
|
1197
|
+
onPoll?: (poll: ChannelPollResult) => void;
|
|
1198
|
+
}): Promise<ChannelPollResult>;
|
|
1199
|
+
/** Feishu-only spelling of {@link startChannelSetup}, kept for callers written against 0.3.x–0.4.x. */
|
|
1200
|
+
startFeishuSetup(agentId: string, input?: ChannelSetupInput): Promise<FeishuSetupSession>;
|
|
1201
|
+
/** Feishu-only spelling of {@link pollChannelSetup}. */
|
|
1202
|
+
pollFeishuSetup(agentId: string, sessionId: string): Promise<ChannelPollResult>;
|
|
1203
|
+
/** Feishu-only spelling of {@link cancelChannelSetup}. */
|
|
1204
|
+
cancelFeishuSetup(agentId: string, sessionId: string): Promise<void>;
|
|
1205
|
+
/** Feishu-only spelling of {@link waitForChannelSetup}. */
|
|
1130
1206
|
waitForFeishuSetup(agentId: string, sessionId: string, opts?: {
|
|
1131
1207
|
timeoutMs?: number;
|
|
1132
1208
|
signal?: AbortSignal;
|
|
1133
|
-
onPoll?: (poll:
|
|
1134
|
-
}): Promise<
|
|
1209
|
+
onPoll?: (poll: ChannelPollResult) => void;
|
|
1210
|
+
}): Promise<ChannelPollResult>;
|
|
1135
1211
|
/**
|
|
1136
1212
|
* The agent's system-prompt pin and the rendered template in effect. Staging-verified
|
|
1137
1213
|
* 2026-08-14 — a fresh agent answers a real `declaration` (`{source:'platform',version:1}`),
|
package/dist/client.js
CHANGED
|
@@ -336,19 +336,20 @@ export function createZooworkClient(cfg = {}) {
|
|
|
336
336
|
body: JSON.stringify({ account: opts.account ?? 'default' }),
|
|
337
337
|
});
|
|
338
338
|
},
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
339
|
+
startChannelSetup: (agentId, platform, input = {}) => json(`${agents(agentId)}/channels/${encodeURIComponent(platform)}/setup`, {
|
|
340
|
+
method: 'POST',
|
|
341
|
+
body: JSON.stringify(input),
|
|
342
|
+
}),
|
|
343
|
+
pollChannelSetup: (agentId, platform, sessionId) => json(`${agents(agentId)}/channels/${encodeURIComponent(platform)}/poll${query({ session_id: sessionId })}`),
|
|
344
|
+
cancelChannelSetup: async (agentId, platform, sessionId) => {
|
|
345
|
+
await json(`${agents(agentId)}/channels/${encodeURIComponent(platform)}/setup/cancel${query({ session_id: sessionId })}`, { method: 'POST' });
|
|
345
346
|
},
|
|
346
|
-
|
|
347
|
+
waitForChannelSetup: async (agentId, platform, sessionId, opts = {}) => {
|
|
347
348
|
const timeoutMs = opts.timeoutMs ?? 600_000;
|
|
348
349
|
const deadline = Date.now() + timeoutMs;
|
|
349
350
|
let lastStatus = 'unknown';
|
|
350
|
-
const abortedError = () => new ZooworkError(0, `
|
|
351
|
-
const timeoutError = () => new ZooworkError(408,
|
|
351
|
+
const abortedError = () => new ZooworkError(0, `waitForChannelSetup(${agentId}, ${platform}, ${sessionId}) aborted`, 'aborted');
|
|
352
|
+
const timeoutError = () => new ZooworkError(408, `${platform} setup session ${sessionId} still '${lastStatus}' after ${timeoutMs}ms — ` +
|
|
352
353
|
'the QR may simply not have been scanned yet; the session itself expires server-side', 'timeout');
|
|
353
354
|
for (;;) {
|
|
354
355
|
if (opts.signal?.aborted)
|
|
@@ -364,7 +365,7 @@ export function createZooworkClient(cfg = {}) {
|
|
|
364
365
|
const budget = setTimeout(cancelPoll, remaining);
|
|
365
366
|
let result;
|
|
366
367
|
try {
|
|
367
|
-
result = await json(`${agents(agentId)}/channels/
|
|
368
|
+
result = await json(`${agents(agentId)}/channels/${encodeURIComponent(platform)}/poll${query({ session_id: sessionId })}`, { signal: poll.signal });
|
|
368
369
|
}
|
|
369
370
|
catch (e) {
|
|
370
371
|
if (poll.signal.aborted)
|
|
@@ -378,7 +379,7 @@ export function createZooworkClient(cfg = {}) {
|
|
|
378
379
|
opts.onPoll?.(result);
|
|
379
380
|
lastStatus = result.status ?? 'unknown';
|
|
380
381
|
// Only a literal 'pending' keeps the loop alive… except that an UNKNOWN status is
|
|
381
|
-
// treated as still-in-flight too (see
|
|
382
|
+
// treated as still-in-flight too (see ChannelPollResult): a new intermediate state on
|
|
382
383
|
// the server should stretch the wait, not end it with a fake terminal result.
|
|
383
384
|
const terminal = ['success', 'expired', 'denied', 'error'].includes(lastStatus);
|
|
384
385
|
if (terminal)
|
|
@@ -391,6 +392,12 @@ export function createZooworkClient(cfg = {}) {
|
|
|
391
392
|
await sleep(intervalMs, opts.signal);
|
|
392
393
|
}
|
|
393
394
|
},
|
|
395
|
+
// The Feishu-only spellings, kept for callers written against 0.3.x–0.4.x. `startFeishuSetup`
|
|
396
|
+
// narrows the return type only — Feishu always answers `verification_uri_complete`.
|
|
397
|
+
startFeishuSetup: (agentId, input = {}) => client.startChannelSetup(agentId, 'feishu', input),
|
|
398
|
+
pollFeishuSetup: (agentId, sessionId) => client.pollChannelSetup(agentId, 'feishu', sessionId),
|
|
399
|
+
cancelFeishuSetup: (agentId, sessionId) => client.cancelChannelSetup(agentId, 'feishu', sessionId),
|
|
400
|
+
waitForFeishuSetup: (agentId, sessionId, opts = {}) => client.waitForChannelSetup(agentId, 'feishu', sessionId, opts),
|
|
394
401
|
uploadSkill: (zip, opts) => {
|
|
395
402
|
const form = skillForm(zip, opts);
|
|
396
403
|
form.append('scope', opts.scope);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient, type ZooworkConfig, type ZooworkAuth, type Ownership, type ModelInfo, type AgentResource, type AgentRecord, type AgentStatus, type AgentSkill, type AgentChannel, type ChannelPlatform, type AddChannelInput, type UpdateChannelInput, type FeishuSetupInput, type FeishuSetupSession, type FeishuPollResult, type McpServerDeclaration, type SkillRecord, type SessionRecord, type SessionHistoryEntry, type SessionEvent, type SessionEventPage, type OutboundEvent, type PostEventReceipt, type ApprovalDecision, type ApprovalRecord, type ArtifactPage, type ArtifactRecord, type ArtifactStatus, type OutcomeConfig, type OutcomeEvaluator, type SystemPromptDeclaration, type SystemPromptInfo, type SystemPromptPreview, type SystemPromptPreviewInput, type SystemPromptUpgrade, type ScheduleSpec, type SchedulePayload, type ScheduleInput, type ScheduleUpdate, type ScheduleRecord, type ScheduleRun, type WakeResult, type ExecResult, type EnvironmentConfig, type EnvironmentResource, type EnvironmentRecord, type EnvironmentVersionRecord, } from './client.js';
|
|
1
|
+
export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient, type ZooworkConfig, type ZooworkAuth, type Ownership, type ModelInfo, type AgentResource, type AgentRecord, type AgentStatus, type AgentSkill, type AgentChannel, type ChannelPlatform, type AddChannelPlatform, type GuidedSetupPlatform, type AddChannelInput, type UpdateChannelInput, type ChannelSetupInput, type ChannelSetupSession, type ChannelPollResult, type FeishuSetupInput, type FeishuSetupSession, type FeishuPollResult, type McpServerDeclaration, type SkillRecord, type SessionRecord, type SessionHistoryEntry, type SessionEvent, type SessionEventPage, type OutboundEvent, type PostEventReceipt, type ApprovalDecision, type ApprovalRecord, type ArtifactPage, type ArtifactRecord, type ArtifactStatus, type OutcomeConfig, type OutcomeEvaluator, type SystemPromptDeclaration, type SystemPromptInfo, type SystemPromptPreview, type SystemPromptPreviewInput, type SystemPromptUpgrade, type ScheduleSpec, type SchedulePayload, type ScheduleInput, type ScheduleUpdate, type ScheduleRecord, type ScheduleRun, type WakeResult, type ExecResult, type EnvironmentConfig, type EnvironmentResource, type EnvironmentRecord, type EnvironmentVersionRecord, } from './client.js';
|
|
2
2
|
export { SESSION_EVENT_TYPES, type SessionEventType, PUBLIC_INPUT_EVENT_TYPES, type PublicInputEventType, normalizeEvent, isRunFinished, runOutcome, messageText, assistantText, thinkingText, toolCall, type ToolCall, } from './events.js';
|
|
3
3
|
export { parseSSE, type SSEMessage } from './sse.js';
|