@zoowork-ai/sdk 0.6.0 → 0.8.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 +33 -0
- package/README.md +49 -14
- package/dist/client.d.ts +206 -8
- package/dist/client.js +24 -0
- package/dist/events.d.ts +16 -2
- package/dist/events.js +21 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +10 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,39 @@
|
|
|
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.8.0 — 2026-09-20
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Model catalog lifecycle metadata, including `selectable` and replacement hints.
|
|
11
|
+
- Deleted Session tombstones in filtered cursor pages through `includeDeleted`.
|
|
12
|
+
- Agent declaration fields for global-Skill opt-out and named user timezones.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- Model-selection examples now reject non-selectable catalog rows; selecting one can return
|
|
17
|
+
`409 model_not_selectable`.
|
|
18
|
+
|
|
19
|
+
## 0.7.0 — 2026-09-14
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Application-executed custom tools.** Agent resources can declare `custom_tools`; event
|
|
24
|
+
helpers expose requested calls; and the client can list pending calls, resolve a call, or
|
|
25
|
+
post typed `user.custom_tool_result` content.
|
|
26
|
+
- **Filtered cursor session listing.** `listSessionPage()` adds the channel, surface,
|
|
27
|
+
runtime-mode and archive-filtered cursor lane without changing the existing numeric-page
|
|
28
|
+
behavior of `listSessions()`. Session archive and delete operations are also exposed.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **MCP configuration now covers runtime context and permissions.** Types include metadata
|
|
33
|
+
context, a server permission default, exact per-tool overrides, and trailing-prefix tool
|
|
34
|
+
policy selectors.
|
|
35
|
+
- **Channel contracts include direct DingTalk configuration and Feishu document capability
|
|
36
|
+
state.** Callers can inspect provider, sync, missing-scope and approval-state details from
|
|
37
|
+
returned capabilities.
|
|
38
|
+
|
|
6
39
|
## 0.6.0 — 2026-09-11
|
|
7
40
|
|
|
8
41
|
### Changed
|
package/README.md
CHANGED
|
@@ -29,8 +29,10 @@ The base URL has a working default, so you do not configure an endpoint. Overrid
|
|
|
29
29
|
// send. Select a model returned by this deployment instead of relying on a
|
|
30
30
|
// remembered id or on a server default that can rotate.
|
|
31
31
|
const models = await zc.listModels()
|
|
32
|
-
const primary = models.find(
|
|
33
|
-
|
|
32
|
+
const primary = models.find(
|
|
33
|
+
(model) => model.selectable !== false && model.model === 'litellm/gpt-5.6-terra',
|
|
34
|
+
)?.model
|
|
35
|
+
if (!primary) throw new Error('Choose a selectable model returned by listModels()')
|
|
34
36
|
|
|
35
37
|
const agent = await zc.createAgent({
|
|
36
38
|
resource: { name: 'research-agent', model: { primary } },
|
|
@@ -45,6 +47,15 @@ const session = await zc.createSession(agent.agent_id, {
|
|
|
45
47
|
})
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
`listModels()` can include a model whose retirement has started. Check `selectable !== false`
|
|
51
|
+
before using a catalog row in a new Agent or config. A non-selectable choice returns
|
|
52
|
+
`409 model_not_selectable`; `expired_fallback_to` names the reviewed replacement when present.
|
|
53
|
+
|
|
54
|
+
Agent resources also accept `userTimezone`, a named IANA timezone used for prompt and message
|
|
55
|
+
time context, and `include_global_skills: false` to disable automatic global Skills while keeping
|
|
56
|
+
explicitly listed Skills. An explicit `skills: []` also opts out. Schedule timezones are configured
|
|
57
|
+
separately.
|
|
58
|
+
|
|
48
59
|
## Configuration
|
|
49
60
|
|
|
50
61
|
| Option | Environment variable | Default |
|
|
@@ -115,7 +126,7 @@ instead of silently returning an empty or apparently complete array.
|
|
|
115
126
|
`run.finished` ends a turn; assistant text arrives on `agent.assistant`.
|
|
116
127
|
|
|
117
128
|
```ts
|
|
118
|
-
import { assistantText, isRunFinished, runOutcome, toolCall } from '@zoowork-ai/sdk'
|
|
129
|
+
import { assistantText, customToolUse, isRunFinished, runOutcome, toolCall } from '@zoowork-ai/sdk'
|
|
119
130
|
|
|
120
131
|
for await (const ev of zc.streamEvents(agent.agent_id, session.session_id)) {
|
|
121
132
|
process.stdout.write(assistantText(ev)) // '' for every non-assistant event
|
|
@@ -201,10 +212,33 @@ const { exit_code, stdout } = await zc.exec(agent.agent_id, ['bash', '-lc', 'pwd
|
|
|
201
212
|
|
|
202
213
|
## Sessions, approvals, environments
|
|
203
214
|
|
|
204
|
-
`listSessions
|
|
215
|
+
`listSessions` keeps the legacy numeric-page contract. Use `listSessionPage` for the filtered
|
|
216
|
+
cursor lane: it starts with `sls1:0`, accepts channel/surface/runtime/archive filters, and returns
|
|
217
|
+
`next_cursor` plus a `list_cursor` on each row. Cursors are opaque and bound to the same filters.
|
|
218
|
+
Pass `{ includeDeleted: true }` to include deletion tombstones for reconciliation; returned rows
|
|
219
|
+
then carry `deleted` and the page carries `includes_deleted: true`. This flag is part of the cursor
|
|
220
|
+
scope, so do not reuse a cursor created without it.
|
|
221
|
+
`archiveSession` and `deleteSession` round out the session surface. There is no
|
|
205
222
|
`patchSession`: the gateway does not proxy `PATCH` at all (405), so session `metadata` is fixed at
|
|
206
223
|
creation time.
|
|
207
224
|
|
|
225
|
+
An application-executed tool is declared in `resource.custom_tools`. When
|
|
226
|
+
`customToolUse(ev)?.phase === 'requested'`, execute the named operation and call
|
|
227
|
+
`resolveCustomToolCall`; `listCustomToolCalls` recovers pending work after a restart. You may also
|
|
228
|
+
post a typed `user.custom_tool_result` event to the owning session. The run reports
|
|
229
|
+
`awaiting_approval` while paused, so use `pending_custom_tool_calls` to distinguish this wait from
|
|
230
|
+
a normal approval. These contracts are source-reviewed and need deployment verification.
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
const call = customToolUse(ev)
|
|
234
|
+
if (call?.phase === 'requested') {
|
|
235
|
+
await zc.resolveCustomToolCall(agentId, call.callId, {
|
|
236
|
+
content: [{ type: 'json', value: { price: 42 } }],
|
|
237
|
+
resolvedBy: 'pricing-service',
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
208
242
|
`listApprovals` / `resolveApproval` expose the approvals resource — `decision` is one of
|
|
209
243
|
`allow-once`, `allow-always`, `deny`. End-to-end approval and turn-budget behavior need
|
|
210
244
|
separate verification on the deployment you use.
|
|
@@ -291,18 +325,19 @@ temporary Agent/Session, one potentially billable model turn and cleanup. JSON r
|
|
|
291
325
|
in its printed private directory. The test never publishes. Normal `pnpm test` is offline
|
|
292
326
|
and needs no key. See [E2E and recovery instructions](e2e/README.md) for scope and options.
|
|
293
327
|
|
|
294
|
-
|
|
328
|
+
Publishing runs through [`.github/workflows/release.yml`](.github/workflows/release.yml). Configure
|
|
329
|
+
the npm package's Trusted Publisher once with organization `SerendipityOneInc`, repository
|
|
330
|
+
`zoowork-sdk-typescript`, workflow `release.yml`, and direct publish permission. No npm token or
|
|
331
|
+
repeated `npm login` is needed after that.
|
|
295
332
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
npm
|
|
299
|
-
|
|
333
|
+
For each release, merge the intended version and changelog, then publish a GitHub Release whose
|
|
334
|
+
tag is exactly `v<package version>` — for example, `v0.7.0`. The workflow verifies that match,
|
|
335
|
+
runs the offline test and build gates, and publishes the public package with npm OIDC. A mismatched
|
|
336
|
+
tag fails before publication, and an existing npm version cannot be overwritten.
|
|
300
337
|
|
|
301
|
-
The
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
changelog before publishing; existing npm versions cannot be overwritten. Use
|
|
305
|
-
`npm publish --dry-run` to inspect the package without uploading it.
|
|
338
|
+
The release workflow does not run live E2E or read a staging key. Run `pnpm test:e2e` separately
|
|
339
|
+
before creating the GitHub Release when live verification is required. Use
|
|
340
|
+
`npm publish --dry-run` locally to inspect the package without uploading it.
|
|
306
341
|
|
|
307
342
|
## License
|
|
308
343
|
|
package/dist/client.d.ts
CHANGED
|
@@ -121,8 +121,29 @@ export interface ModelInfo {
|
|
|
121
121
|
display_name?: string;
|
|
122
122
|
family?: string;
|
|
123
123
|
api?: string;
|
|
124
|
+
expired_at?: string | null;
|
|
125
|
+
expired_fallback_to?: string | null;
|
|
126
|
+
retired_at?: string | null;
|
|
127
|
+
revision?: number;
|
|
128
|
+
lifecycle_status?: 'active' | 'scheduled' | 'draining' | 'retired' | string;
|
|
129
|
+
/** `false` means this catalog row cannot be selected for a new Agent or config. */
|
|
130
|
+
selectable?: boolean;
|
|
131
|
+
retire_not_before?: string | null;
|
|
132
|
+
default_for?: string[];
|
|
124
133
|
[k: string]: unknown;
|
|
125
134
|
}
|
|
135
|
+
/** Approval behavior for one MCP server or one of its tools. */
|
|
136
|
+
export type McpToolPermission = 'always_ask' | 'always_allow';
|
|
137
|
+
/** Opt-in runtime coordinates sent only while a tool is executing, never during catalog discovery. */
|
|
138
|
+
export interface McpContextConfig {
|
|
139
|
+
/** Add the coordinates under `params._meta['ai.zooclaw/context']` on `tools/call`. */
|
|
140
|
+
meta?: boolean;
|
|
141
|
+
/** Add the coordinates as `x-zooclaw-*` headers on the tool call's HTTP requests. */
|
|
142
|
+
headers?: boolean;
|
|
143
|
+
}
|
|
144
|
+
export interface McpToolPermissionOverride {
|
|
145
|
+
permission: McpToolPermission;
|
|
146
|
+
}
|
|
126
147
|
/**
|
|
127
148
|
* One remote MCP server, declared as `resource.mcp[]` on create or update.
|
|
128
149
|
*
|
|
@@ -161,8 +182,36 @@ export interface McpServerDeclaration {
|
|
|
161
182
|
* There is no `auto` value.
|
|
162
183
|
*/
|
|
163
184
|
exposure?: 'deferred' | 'direct';
|
|
185
|
+
/**
|
|
186
|
+
* Opt in to runtime coordinates for this server. Both switches default to false. The context
|
|
187
|
+
* can include agent/session/computer ids and, when available, run/turn/config/actor fields.
|
|
188
|
+
* Catalog discovery never receives it. Header delivery may be unavailable through proxies;
|
|
189
|
+
* `_meta` is the portable option.
|
|
190
|
+
*/
|
|
191
|
+
context?: McpContextConfig;
|
|
192
|
+
/** Default approval behavior for every tool on this server. Omit for the existing default-allow behavior. */
|
|
193
|
+
permission?: McpToolPermission;
|
|
194
|
+
/**
|
|
195
|
+
* Per-tool approval overrides keyed by the server's original tool name, not its
|
|
196
|
+
* `mcp__<server>__<tool>` name. Keys are exact and cannot contain `*`; at most 64 entries.
|
|
197
|
+
*/
|
|
198
|
+
tools?: Record<string, McpToolPermissionOverride>;
|
|
164
199
|
[k: string]: unknown;
|
|
165
200
|
}
|
|
201
|
+
/** One application-executed tool declared under {@link AgentResource.custom_tools}. */
|
|
202
|
+
export interface CustomToolDeclaration {
|
|
203
|
+
/** Unique within the Agent; 1–64 ASCII letters, numbers, `_` or `-`. Reserved runtime names are rejected. */
|
|
204
|
+
name: string;
|
|
205
|
+
/** Non-empty tool description, at most 4 KiB UTF-8. */
|
|
206
|
+
description: string;
|
|
207
|
+
/** JSON Schema for the input. Its top-level `type` must be `object`; at most 16 KiB serialized. */
|
|
208
|
+
input_schema: {
|
|
209
|
+
type: 'object';
|
|
210
|
+
[k: string]: unknown;
|
|
211
|
+
};
|
|
212
|
+
/** Result wait budget in milliseconds. Defaults to 600,000; maximum 86,400,000. */
|
|
213
|
+
timeoutMs?: number;
|
|
214
|
+
}
|
|
166
215
|
/**
|
|
167
216
|
* The system-prompt pin (`resource.system_prompt`).
|
|
168
217
|
*
|
|
@@ -229,6 +278,8 @@ export interface OutcomeConfig {
|
|
|
229
278
|
}
|
|
230
279
|
export interface AgentResource {
|
|
231
280
|
name: string;
|
|
281
|
+
/** Named IANA timezone used in prompt context and message timestamps, e.g. `Asia/Shanghai`. */
|
|
282
|
+
userTimezone?: string;
|
|
232
283
|
/**
|
|
233
284
|
* Omit this section to pin the platform's current model defaults at create time. Those
|
|
234
285
|
* defaults can rotate; call `listModels()` and set `primary` explicitly for deterministic
|
|
@@ -251,10 +302,27 @@ export interface AgentResource {
|
|
|
251
302
|
skill_id: string;
|
|
252
303
|
version?: number | 'latest';
|
|
253
304
|
}[];
|
|
305
|
+
/**
|
|
306
|
+
* Defaults to true. False disables automatic global Skills without removing explicitly
|
|
307
|
+
* listed Skills. An explicit empty `skills` array also opts out.
|
|
308
|
+
*/
|
|
309
|
+
include_global_skills?: boolean;
|
|
254
310
|
labels?: Record<string, string>;
|
|
311
|
+
/**
|
|
312
|
+
* Tool-surface and approval policy. Name selectors in `allow`, `deny`, `rules[].match.tool`,
|
|
313
|
+
* `afterRules[].match.tool`, and MCP names in `deferred.pinned` accept an exact name, `*`, or
|
|
314
|
+
* one trailing `prefix*`. Other wildcard forms match nothing. `alsoAllow` and
|
|
315
|
+
* `permissions` keys remain exact. Kept open for forward-compatible policy fields.
|
|
316
|
+
*/
|
|
255
317
|
tool_policy?: Record<string, unknown>;
|
|
256
318
|
/** Remote MCP servers. Only unauthenticated ones work today — see {@link McpServerDeclaration}. */
|
|
257
319
|
mcp?: McpServerDeclaration[];
|
|
320
|
+
/**
|
|
321
|
+
* Tools executed by your application. At most 32. A model call emits
|
|
322
|
+
* `agent.custom_tool_use`; return the result with `resolveCustomToolCall` or a
|
|
323
|
+
* `user.custom_tool_result` event. Source-reviewed; deployment availability is unverified.
|
|
324
|
+
*/
|
|
325
|
+
custom_tools?: CustomToolDeclaration[];
|
|
258
326
|
/**
|
|
259
327
|
* System-prompt pin. Omitted on create means "the platform version active right now", pinned
|
|
260
328
|
* from then on. REPLACE-ON-WRITE on PUT, like `tool_policy` — see {@link SystemPromptDeclaration}.
|
|
@@ -312,6 +380,27 @@ export interface AgentSkill {
|
|
|
312
380
|
}[];
|
|
313
381
|
[k: string]: unknown;
|
|
314
382
|
}
|
|
383
|
+
/** Source-reviewed asynchronous capability-configuration state for one channel feature. */
|
|
384
|
+
export interface AgentChannelCapabilitySync {
|
|
385
|
+
state: 'pending' | 'applied' | 'retry' | 'error';
|
|
386
|
+
[k: string]: unknown;
|
|
387
|
+
}
|
|
388
|
+
export interface FeishuChannelProviderStatus {
|
|
389
|
+
state: 'ready' | 'degraded';
|
|
390
|
+
missing_scopes: string[];
|
|
391
|
+
approval_state?: 'pending_admin' | null;
|
|
392
|
+
[k: string]: unknown;
|
|
393
|
+
}
|
|
394
|
+
export interface FeishuDocumentsCapability {
|
|
395
|
+
permission_admin_enabled: boolean;
|
|
396
|
+
sync: AgentChannelCapabilitySync;
|
|
397
|
+
provider: FeishuChannelProviderStatus;
|
|
398
|
+
[k: string]: unknown;
|
|
399
|
+
}
|
|
400
|
+
export interface AgentChannelCapabilities {
|
|
401
|
+
feishu_documents?: FeishuDocumentsCapability | null;
|
|
402
|
+
[k: string]: unknown;
|
|
403
|
+
}
|
|
315
404
|
/**
|
|
316
405
|
* One platform account bound to an agent, as the channel service reports it.
|
|
317
406
|
* `dm_policy` / `group_policy` are the reachability policies (`'open'` is the
|
|
@@ -328,10 +417,13 @@ export interface AgentChannel {
|
|
|
328
417
|
health?: string;
|
|
329
418
|
status?: string;
|
|
330
419
|
status_code?: string | null;
|
|
420
|
+
/** Source-reviewed capability state. Omitted when the platform reports none. */
|
|
421
|
+
capabilities?: AgentChannelCapabilities | null;
|
|
331
422
|
[k: string]: unknown;
|
|
332
423
|
}
|
|
333
424
|
/**
|
|
334
|
-
* The chat platforms you can bind, staging-verified
|
|
425
|
+
* The chat platforms you can bind. Feishu, Slack, WeCom and WeChat were staging-verified
|
|
426
|
+
* 2026-08-28. Direct DingTalk support is source-reviewed, not deployment-verified here.
|
|
335
427
|
*
|
|
336
428
|
* Three of them have a server-driven QR flow ({@link GuidedSetupPlatform}); Slack does not,
|
|
337
429
|
* and structurally cannot — a Slack app is created by a person and its tokens only ever exist
|
|
@@ -340,15 +432,15 @@ export interface AgentChannel {
|
|
|
340
432
|
*
|
|
341
433
|
* WeChat is the one platform that goes the other way: `'weixin'`/`'wechat'` on
|
|
342
434
|
* {@link ZooworkClient.addChannel} answers `400 channel.weixin_setup_required`, so the QR flow
|
|
343
|
-
* is its ONLY path.
|
|
344
|
-
*
|
|
435
|
+
* is its ONLY path. DingTalk uses `'dingtalk-connector'` and currently has a direct config path
|
|
436
|
+
* only on the public API; its product QR flow is not exposed here. See {@link AddChannelPlatform}.
|
|
345
437
|
*/
|
|
346
|
-
export type ChannelPlatform = 'feishu' | 'slack' | 'wecom' | 'weixin';
|
|
438
|
+
export type ChannelPlatform = 'feishu' | 'slack' | 'wecom' | 'weixin' | 'dingtalk-connector';
|
|
347
439
|
/**
|
|
348
440
|
* The platforms {@link ZooworkClient.addChannel} accepts — every {@link ChannelPlatform}
|
|
349
441
|
* except WeChat, which refuses explicit config and takes the QR flow only.
|
|
350
442
|
*/
|
|
351
|
-
export type AddChannelPlatform = 'feishu' | 'slack' | 'wecom';
|
|
443
|
+
export type AddChannelPlatform = 'feishu' | 'slack' | 'wecom' | 'dingtalk-connector';
|
|
352
444
|
/**
|
|
353
445
|
* The platforms with a server-driven QR flow: {@link ZooworkClient.startChannelSetup} →
|
|
354
446
|
* render the URI → poll. Slack is absent by design, not by omission.
|
|
@@ -397,7 +489,7 @@ export interface AddChannelInput {
|
|
|
397
489
|
*/
|
|
398
490
|
account?: string;
|
|
399
491
|
display_name?: string;
|
|
400
|
-
/** Server default: `'open'`. `'pairing'` is rejected
|
|
492
|
+
/** Server default: `'open'`. DingTalk accepts only `'open'`; `'pairing'` is rejected everywhere. */
|
|
401
493
|
dm_policy?: string;
|
|
402
494
|
/** Server default: `'open'`. */
|
|
403
495
|
group_policy?: string;
|
|
@@ -411,8 +503,11 @@ export interface AddChannelInput {
|
|
|
411
503
|
* needs the app-level token as well as the bot token)
|
|
412
504
|
* - `wecom` — `{ botId, secret }`, both required
|
|
413
505
|
* - `feishu` — `{ appId, appSecret, domain }`, only when skipping the QR flow
|
|
506
|
+
* - `dingtalk-connector` — `{ clientId, clientSecret }`; no public guided QR route
|
|
414
507
|
*/
|
|
415
508
|
config?: Record<string, unknown>;
|
|
509
|
+
/** Feishu only. Enable document-permission administration; defaults to false. */
|
|
510
|
+
permission_admin_enabled?: boolean;
|
|
416
511
|
}
|
|
417
512
|
export interface UpdateChannelInput {
|
|
418
513
|
/** Which binding to touch — see {@link AddChannelInput.account}. Server default: `'default'`. */
|
|
@@ -420,6 +515,8 @@ export interface UpdateChannelInput {
|
|
|
420
515
|
dm_policy?: string;
|
|
421
516
|
group_policy?: string;
|
|
422
517
|
enabled?: boolean;
|
|
518
|
+
/** Feishu only. Other platforms reject this field when it is present. */
|
|
519
|
+
permission_admin_enabled?: boolean;
|
|
423
520
|
}
|
|
424
521
|
/**
|
|
425
522
|
* Body for {@link ZooworkClient.startChannelSetup}. Every field is optional, and each platform
|
|
@@ -462,6 +559,8 @@ export interface ChannelSetupInput {
|
|
|
462
559
|
dm_policy?: string;
|
|
463
560
|
/** Server default: `'open'`. Ignored by WeChat, which forces `'disabled'`. */
|
|
464
561
|
group_policy?: string;
|
|
562
|
+
/** Feishu only. Enable document-permission administration; defaults to false. */
|
|
563
|
+
permission_admin_enabled?: boolean;
|
|
465
564
|
}
|
|
466
565
|
/** @deprecated Use {@link ChannelSetupInput}; this is the same shape under the old name. */
|
|
467
566
|
export type FeishuSetupInput = ChannelSetupInput;
|
|
@@ -624,6 +723,8 @@ export interface SessionRecord {
|
|
|
624
723
|
run_status?: string | null;
|
|
625
724
|
/** Pending approval count on getSession; not included in every session projection. */
|
|
626
725
|
pending_approvals?: number;
|
|
726
|
+
/** Pending application-executed custom-tool count on getSession. */
|
|
727
|
+
pending_custom_tool_calls?: number;
|
|
627
728
|
/**
|
|
628
729
|
* `running` on a `createSession` receipt, nullable on `getSession`, and absent from
|
|
629
730
|
* `listSessions` rows. This is not the run outcome; read {@link SessionRecord.run_status}
|
|
@@ -632,12 +733,20 @@ export interface SessionRecord {
|
|
|
632
733
|
status?: string | null;
|
|
633
734
|
metadata?: Record<string, unknown>;
|
|
634
735
|
archived?: boolean;
|
|
736
|
+
/** Present on filtered pages only when `includeDeleted` was requested. */
|
|
737
|
+
deleted?: boolean;
|
|
738
|
+
runtime_mode?: 'active' | 'preview' | 'authoring' | 'evaluation' | string;
|
|
739
|
+
config_version?: number;
|
|
635
740
|
updated_at?: string;
|
|
741
|
+
/** Activity sort key used by filtered cursor listing. */
|
|
742
|
+
last_activity_at?: string;
|
|
743
|
+
/** Opaque per-row resume cursor returned only by {@link ZooworkClient.listSessionPage}. */
|
|
744
|
+
list_cursor?: string;
|
|
636
745
|
/** Present only when the read asked for `history: true`; the most recent `limit` rows, in order. */
|
|
637
746
|
history?: SessionHistoryEntry[];
|
|
638
747
|
[k: string]: unknown;
|
|
639
748
|
}
|
|
640
|
-
/** Write-side events
|
|
749
|
+
/** Write-side events, including `user.custom_tool_result`; unsupported types are rejected by the API. */
|
|
641
750
|
export interface OutboundEvent {
|
|
642
751
|
type: string;
|
|
643
752
|
content?: unknown;
|
|
@@ -655,6 +764,59 @@ export interface OutboundEvent {
|
|
|
655
764
|
};
|
|
656
765
|
[k: string]: unknown;
|
|
657
766
|
}
|
|
767
|
+
export type CustomToolResultImageMimeType = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
|
|
768
|
+
/** One content block returned by an application-executed custom tool. */
|
|
769
|
+
export type CustomToolResultContent = {
|
|
770
|
+
type: 'text';
|
|
771
|
+
text: string;
|
|
772
|
+
} | {
|
|
773
|
+
type: 'json';
|
|
774
|
+
value: unknown;
|
|
775
|
+
} | {
|
|
776
|
+
type: 'image';
|
|
777
|
+
source: {
|
|
778
|
+
type: 'base64';
|
|
779
|
+
media_type: CustomToolResultImageMimeType;
|
|
780
|
+
data: string;
|
|
781
|
+
};
|
|
782
|
+
} | {
|
|
783
|
+
type: 'image';
|
|
784
|
+
data: string;
|
|
785
|
+
mime_type: CustomToolResultImageMimeType;
|
|
786
|
+
};
|
|
787
|
+
/** Write-side result event for {@link ZooworkClient.postEvents}. */
|
|
788
|
+
export type CustomToolResultEvent = OutboundEvent & {
|
|
789
|
+
type: 'user.custom_tool_result';
|
|
790
|
+
content: CustomToolResultContent[];
|
|
791
|
+
is_error?: boolean;
|
|
792
|
+
idempotency_key?: string;
|
|
793
|
+
} & ({
|
|
794
|
+
custom_tool_use_id: string;
|
|
795
|
+
call_id?: never;
|
|
796
|
+
} | {
|
|
797
|
+
call_id: string;
|
|
798
|
+
custom_tool_use_id?: never;
|
|
799
|
+
});
|
|
800
|
+
/** Options for the filtered cursor lane. Filters are part of the cursor scope. */
|
|
801
|
+
export interface SessionListPageOptions {
|
|
802
|
+
/** Opaque cursor returned by this same filter scope. Omit to start at `sls1:0`. */
|
|
803
|
+
cursor?: string;
|
|
804
|
+
/** 1–100; server default 50. */
|
|
805
|
+
limit?: number;
|
|
806
|
+
excludeChannels?: string[];
|
|
807
|
+
includeSurfaces?: string[];
|
|
808
|
+
runtimeModes?: Array<'active' | 'preview' | 'authoring' | 'evaluation'>;
|
|
809
|
+
includeArchived?: boolean;
|
|
810
|
+
/** Include deleted Session tombstones for history reconciliation. Changes the cursor scope. */
|
|
811
|
+
includeDeleted?: boolean;
|
|
812
|
+
}
|
|
813
|
+
/** One filtered session page. `next_cursor` is null at the end. */
|
|
814
|
+
export interface SessionListPage {
|
|
815
|
+
sessions: SessionRecord[];
|
|
816
|
+
next_cursor: string | null;
|
|
817
|
+
/** Present and true only when deleted tombstones were requested. */
|
|
818
|
+
includes_deleted?: true;
|
|
819
|
+
}
|
|
658
820
|
/** One `postEvents` receipt. An accepted event carries the full event object's fields too. */
|
|
659
821
|
export interface PostEventReceipt {
|
|
660
822
|
id?: string | null;
|
|
@@ -898,6 +1060,24 @@ export interface ApprovalRecord {
|
|
|
898
1060
|
created_at?: string;
|
|
899
1061
|
[k: string]: unknown;
|
|
900
1062
|
}
|
|
1063
|
+
export type CustomToolCallStatus = 'pending' | 'completed' | 'timeout' | 'cancelled' | string;
|
|
1064
|
+
/** One application-executed custom-tool call. Unknown response fields are preserved. */
|
|
1065
|
+
export interface CustomToolCallRecord {
|
|
1066
|
+
call_id: string;
|
|
1067
|
+
session_id: string;
|
|
1068
|
+
tool_call_id: string;
|
|
1069
|
+
name: string;
|
|
1070
|
+
input: Record<string, unknown>;
|
|
1071
|
+
status: CustomToolCallStatus;
|
|
1072
|
+
requested_at: string;
|
|
1073
|
+
timeout_at?: string;
|
|
1074
|
+
resolved_by?: string;
|
|
1075
|
+
resolved_at?: string;
|
|
1076
|
+
is_error?: boolean;
|
|
1077
|
+
/** Resolve receipt: true when a pending call was signaled, false when it was already terminal. */
|
|
1078
|
+
signaled?: boolean;
|
|
1079
|
+
[k: string]: unknown;
|
|
1080
|
+
}
|
|
901
1081
|
/** Artifact lifecycle. Only a `ready` row carries a resolvable `url`. */
|
|
902
1082
|
export type ArtifactStatus = 'pending' | 'ready' | 'failed' | 'deleted' | string;
|
|
903
1083
|
/**
|
|
@@ -1416,10 +1596,15 @@ export interface ZooworkClient {
|
|
|
1416
1596
|
history?: boolean;
|
|
1417
1597
|
limit?: number;
|
|
1418
1598
|
}): Promise<SessionRecord>;
|
|
1419
|
-
/**
|
|
1599
|
+
/** Legacy newest-first numeric page lane: 50 per page, `page` is 1-based. */
|
|
1420
1600
|
listSessions(agentId: string, opts?: {
|
|
1421
1601
|
page?: number;
|
|
1422
1602
|
}): Promise<SessionRecord[]>;
|
|
1603
|
+
/**
|
|
1604
|
+
* Filtered cursor lane. It is separate from {@link listSessions} so existing numeric-page
|
|
1605
|
+
* callers keep their contract. Cursors are opaque and valid only with the same filters.
|
|
1606
|
+
*/
|
|
1607
|
+
listSessionPage(agentId: string, opts?: SessionListPageOptions): Promise<SessionListPage>;
|
|
1423
1608
|
/**
|
|
1424
1609
|
* Stamp `archived_at`. Afterwards writes are `409 session_archived` while reads keep working.
|
|
1425
1610
|
* Interrupt an in-flight run first, or the archive races it.
|
|
@@ -1490,6 +1675,19 @@ export interface ZooworkClient {
|
|
|
1490
1675
|
cursor?: string;
|
|
1491
1676
|
signal?: AbortSignal;
|
|
1492
1677
|
}): AsyncGenerator<SessionEvent>;
|
|
1678
|
+
/** Pending calls only. Any other status is rejected by the API. */
|
|
1679
|
+
listCustomToolCalls(agentId: string, opts?: {
|
|
1680
|
+
status?: 'pending';
|
|
1681
|
+
}): Promise<CustomToolCallRecord[]>;
|
|
1682
|
+
/**
|
|
1683
|
+
* Return one call's result. A pending call answers 202/signaled:true but stays pending until
|
|
1684
|
+
* the paused run consumes it; an already-terminal call answers 200/signaled:false.
|
|
1685
|
+
*/
|
|
1686
|
+
resolveCustomToolCall(agentId: string, callId: string, input: {
|
|
1687
|
+
content: CustomToolResultContent[];
|
|
1688
|
+
isError?: boolean;
|
|
1689
|
+
resolvedBy?: string;
|
|
1690
|
+
}): Promise<CustomToolCallRecord>;
|
|
1493
1691
|
/**
|
|
1494
1692
|
* Tool calls parked on a human decision. `status` may ONLY be omitted or `'pending'` —
|
|
1495
1693
|
* staging-verified 2026-08-07; any other value is rejected, so there is no way to list
|
package/dist/client.js
CHANGED
|
@@ -543,6 +543,22 @@ export function createZooworkClient(cfg = {}) {
|
|
|
543
543
|
const data = await json(`${sessions(agentId)}${query({ page: opts.page })}`);
|
|
544
544
|
return data.sessions ?? [];
|
|
545
545
|
},
|
|
546
|
+
listSessionPage: async (agentId, opts = {}) => {
|
|
547
|
+
const data = await json(`${sessions(agentId)}${query({
|
|
548
|
+
cursor: opts.cursor ?? 'sls1:0',
|
|
549
|
+
limit: opts.limit,
|
|
550
|
+
exclude_channels: opts.excludeChannels?.join(','),
|
|
551
|
+
include_surfaces: opts.includeSurfaces?.join(','),
|
|
552
|
+
runtime_modes: opts.runtimeModes?.join(','),
|
|
553
|
+
include_archived: opts.includeArchived === undefined ? undefined : String(opts.includeArchived),
|
|
554
|
+
include_deleted: opts.includeDeleted === undefined ? undefined : String(opts.includeDeleted),
|
|
555
|
+
})}`);
|
|
556
|
+
return {
|
|
557
|
+
sessions: data.sessions ?? [],
|
|
558
|
+
next_cursor: data.next_cursor ?? null,
|
|
559
|
+
...(data.includes_deleted === true ? { includes_deleted: true } : {}),
|
|
560
|
+
};
|
|
561
|
+
},
|
|
546
562
|
archiveSession: async (agentId, sessionId) => {
|
|
547
563
|
const data = await json(`${sessions(agentId)}/${encodeURIComponent(sessionId)}/archive`, { method: 'POST' });
|
|
548
564
|
return { ...data, archived: data.archived ?? false };
|
|
@@ -651,6 +667,14 @@ export function createZooworkClient(cfg = {}) {
|
|
|
651
667
|
throw e;
|
|
652
668
|
}
|
|
653
669
|
},
|
|
670
|
+
listCustomToolCalls: async (agentId, opts = {}) => {
|
|
671
|
+
const data = await json(`${agents(agentId)}/custom_tool_calls${query({ status: opts.status })}`);
|
|
672
|
+
return data.custom_tool_calls ?? [];
|
|
673
|
+
},
|
|
674
|
+
resolveCustomToolCall: (agentId, callId, input) => json(`${agents(agentId)}/custom_tool_calls/${encodeURIComponent(callId)}/result`, {
|
|
675
|
+
method: 'POST',
|
|
676
|
+
body: JSON.stringify(input),
|
|
677
|
+
}),
|
|
654
678
|
listApprovals: async (agentId, opts = {}) => {
|
|
655
679
|
const data = await json(`${agents(agentId)}/approvals${query({ status: opts.status })}`);
|
|
656
680
|
return data.approvals ?? [];
|
package/dist/events.d.ts
CHANGED
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
* and may add types within a version.
|
|
18
18
|
*/
|
|
19
19
|
/** SESSION_EVENT_TYPES, mirrored from the API. */
|
|
20
|
-
export declare const SESSION_EVENT_TYPES: readonly ["run.started", "run.finished", "chat.delta", "chat.final", "chat.aborted", "chat.error", "agent.lifecycle", "agent.assistant", "agent.thinking", "agent.tool", "agent.item", "agent.plan", "agent.approval", "agent.command_output", "agent.patch", "agent.compaction", "agent.error", "attachment.created", "message.outbound"];
|
|
20
|
+
export declare const SESSION_EVENT_TYPES: readonly ["run.started", "run.finished", "chat.delta", "chat.final", "chat.aborted", "chat.error", "agent.lifecycle", "agent.assistant", "agent.thinking", "agent.tool", "agent.item", "agent.plan", "agent.approval", "agent.custom_tool_use", "agent.command_output", "agent.patch", "agent.compaction", "agent.error", "attachment.created", "message.outbound"];
|
|
21
21
|
export type SessionEventType = (typeof SESSION_EVENT_TYPES)[number];
|
|
22
22
|
/** Your own inputs, echoed back in the unified event history. */
|
|
23
|
-
export declare const PUBLIC_INPUT_EVENT_TYPES: readonly ["user.message", "user.interrupt", "user.tool_confirmation", "system.message"];
|
|
23
|
+
export declare const PUBLIC_INPUT_EVENT_TYPES: readonly ["user.message", "user.interrupt", "user.tool_confirmation", "user.custom_tool_result", "system.message"];
|
|
24
24
|
export type PublicInputEventType = (typeof PUBLIC_INPUT_EVENT_TYPES)[number];
|
|
25
25
|
/** A durable session event, normalized across the REST and SSE shapes. */
|
|
26
26
|
export interface SessionEvent {
|
|
@@ -74,6 +74,20 @@ export interface ToolCall {
|
|
|
74
74
|
isError?: boolean;
|
|
75
75
|
resultPreview?: string;
|
|
76
76
|
}
|
|
77
|
+
export interface CustomToolUse {
|
|
78
|
+
phase: 'requested' | 'resolved';
|
|
79
|
+
callId: string;
|
|
80
|
+
toolCallId?: string;
|
|
81
|
+
name?: string;
|
|
82
|
+
input?: Record<string, unknown>;
|
|
83
|
+
timeoutAt?: string;
|
|
84
|
+
outcome?: 'completed' | 'timeout' | 'cancelled';
|
|
85
|
+
isError?: boolean;
|
|
86
|
+
resolvedBy?: string;
|
|
87
|
+
resolutionChannel?: string;
|
|
88
|
+
}
|
|
89
|
+
/** Application-executed custom-tool activity; undefined for every other event type. */
|
|
90
|
+
export declare function customToolUse(e: SessionEvent): CustomToolUse | undefined;
|
|
77
91
|
/**
|
|
78
92
|
* Tool activity for an `agent.tool` event; undefined for every other type.
|
|
79
93
|
*
|
package/dist/events.js
CHANGED
|
@@ -31,6 +31,7 @@ export const SESSION_EVENT_TYPES = [
|
|
|
31
31
|
'agent.item',
|
|
32
32
|
'agent.plan',
|
|
33
33
|
'agent.approval',
|
|
34
|
+
'agent.custom_tool_use',
|
|
34
35
|
'agent.command_output',
|
|
35
36
|
'agent.patch',
|
|
36
37
|
'agent.compaction',
|
|
@@ -43,6 +44,7 @@ export const PUBLIC_INPUT_EVENT_TYPES = [
|
|
|
43
44
|
'user.message',
|
|
44
45
|
'user.interrupt',
|
|
45
46
|
'user.tool_confirmation',
|
|
47
|
+
'user.custom_tool_result',
|
|
46
48
|
'system.message',
|
|
47
49
|
];
|
|
48
50
|
const isObj = (v) => !!v && typeof v === 'object';
|
|
@@ -124,6 +126,25 @@ export function thinkingText(e) {
|
|
|
124
126
|
return '';
|
|
125
127
|
return typeof e.payload.text === 'string' ? e.payload.text : '';
|
|
126
128
|
}
|
|
129
|
+
/** Application-executed custom-tool activity; undefined for every other event type. */
|
|
130
|
+
export function customToolUse(e) {
|
|
131
|
+
if (e.eventType !== 'agent.custom_tool_use')
|
|
132
|
+
return undefined;
|
|
133
|
+
const p = e.payload;
|
|
134
|
+
const outcome = p.outcome === 'completed' || p.outcome === 'timeout' || p.outcome === 'cancelled' ? p.outcome : undefined;
|
|
135
|
+
return {
|
|
136
|
+
phase: p.phase === 'resolved' ? 'resolved' : 'requested',
|
|
137
|
+
callId: typeof p.callId === 'string' ? p.callId : '',
|
|
138
|
+
...(typeof p.toolCallId === 'string' ? { toolCallId: p.toolCallId } : {}),
|
|
139
|
+
...(typeof p.name === 'string' ? { name: p.name } : {}),
|
|
140
|
+
...(isObj(p.input) ? { input: p.input } : {}),
|
|
141
|
+
...(typeof p.timeoutAt === 'string' ? { timeoutAt: p.timeoutAt } : {}),
|
|
142
|
+
...(outcome ? { outcome } : {}),
|
|
143
|
+
...(typeof p.isError === 'boolean' ? { isError: p.isError } : {}),
|
|
144
|
+
...(typeof p.resolvedBy === 'string' ? { resolvedBy: p.resolvedBy } : {}),
|
|
145
|
+
...(typeof p.resolutionChannel === 'string' ? { resolutionChannel: p.resolutionChannel } : {}),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
127
148
|
/**
|
|
128
149
|
* Tool activity for an `agent.tool` event; undefined for every other type.
|
|
129
150
|
*
|
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 AgentListParams, type AgentPage, type AgentPagePromise, 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 SkillVersionRecord, 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
|
-
export { SESSION_EVENT_TYPES, type SessionEventType, PUBLIC_INPUT_EVENT_TYPES, type PublicInputEventType, normalizeEvent, isRunFinished, runOutcome, messageText, assistantText, thinkingText, toolCall, type ToolCall, } from './events.js';
|
|
1
|
+
export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient, type ZooworkConfig, type ZooworkAuth, type Ownership, type ModelInfo, type AgentResource, type AgentRecord, type AgentListParams, type AgentPage, type AgentPagePromise, type AgentStatus, type AgentSkill, type AgentChannel, type AgentChannelCapabilitySync, type AgentChannelCapabilities, type FeishuChannelProviderStatus, type FeishuDocumentsCapability, type ChannelPlatform, type AddChannelPlatform, type GuidedSetupPlatform, type AddChannelInput, type UpdateChannelInput, type ChannelSetupInput, type ChannelSetupSession, type ChannelPollResult, type FeishuSetupInput, type FeishuSetupSession, type FeishuPollResult, type McpContextConfig, type McpServerDeclaration, type McpToolPermission, type McpToolPermissionOverride, type CustomToolDeclaration, type CustomToolResultImageMimeType, type CustomToolResultContent, type CustomToolResultEvent, type SkillRecord, type SkillVersionRecord, type SessionRecord, type SessionListPageOptions, type SessionListPage, type SessionHistoryEntry, type SessionEvent, type SessionEventPage, type OutboundEvent, type PostEventReceipt, type ApprovalDecision, type ApprovalRecord, type CustomToolCallStatus, type CustomToolCallRecord, 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
|
+
export { SESSION_EVENT_TYPES, type SessionEventType, PUBLIC_INPUT_EVENT_TYPES, type PublicInputEventType, normalizeEvent, isRunFinished, runOutcome, messageText, assistantText, thinkingText, customToolUse, type CustomToolUse, toolCall, type ToolCall, } from './events.js';
|
|
3
3
|
export { parseSSE, type SSEMessage } from './sse.js';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, } from './client.js';
|
|
2
|
-
export { SESSION_EVENT_TYPES, PUBLIC_INPUT_EVENT_TYPES, normalizeEvent, isRunFinished, runOutcome, messageText, assistantText, thinkingText, toolCall, } from './events.js';
|
|
2
|
+
export { SESSION_EVENT_TYPES, PUBLIC_INPUT_EVENT_TYPES, normalizeEvent, isRunFinished, runOutcome, messageText, assistantText, thinkingText, customToolUse, toolCall, } from './events.js';
|
|
3
3
|
export { parseSSE } from './sse.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoowork-ai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "TypeScript SDK for the ZooWork Managed Agents API (Developer Preview)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zoowork",
|
|
@@ -39,12 +39,6 @@
|
|
|
39
39
|
"publishConfig": {
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
|
-
"devDependencies": {
|
|
43
|
-
"@types/node": "^22.20.1",
|
|
44
|
-
"tsx": "^4.23.7",
|
|
45
|
-
"typescript": "^5.6.0",
|
|
46
|
-
"vitest": "^3.0.0"
|
|
47
|
-
},
|
|
48
42
|
"scripts": {
|
|
49
43
|
"build": "tsc -p tsconfig.build.json",
|
|
50
44
|
"typecheck": "tsc --noEmit",
|
|
@@ -55,6 +49,13 @@
|
|
|
55
49
|
"test:e2e:offline": "node --import tsx --test --test-reporter=spec e2e/*.test.ts",
|
|
56
50
|
"e2e:prepare": "node e2e/runner.ts prepare",
|
|
57
51
|
"e2e:run": "node e2e/runner.ts run",
|
|
58
|
-
"e2e:verify": "node e2e/runner.ts verify"
|
|
52
|
+
"e2e:verify": "node e2e/runner.ts verify",
|
|
53
|
+
"prepack": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && npm run build"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^22.20.1",
|
|
57
|
+
"tsx": "^4.23.7",
|
|
58
|
+
"typescript": "^5.6.0",
|
|
59
|
+
"vitest": "^3.0.0"
|
|
59
60
|
}
|
|
60
|
-
}
|
|
61
|
+
}
|