@zoowork-ai/sdk 0.5.1 → 0.6.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 +27 -0
- package/README.md +122 -11
- package/dist/client.d.ts +150 -60
- package/dist/client.js +52 -7
- package/dist/index.d.ts +1 -1
- package/dist/sse.d.ts +4 -8
- package/dist/sse.js +3 -7
- package/package.json +14 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,33 @@
|
|
|
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.6.0 — 2026-09-11
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **Breaking: `listAgents()` now resolves to an `AgentPage`, not an array.** Read `.data`
|
|
11
|
+
for the current page. The SDK preserves `page`, `page_size`, and `total`, and derives a
|
|
12
|
+
numeric `next_page` (`null` at the end). Existing one-page callers should replace
|
|
13
|
+
`const agents = await zc.listAgents(opts)` with `const { data: agents } = await zc.listAgents(opts)`.
|
|
14
|
+
- **Agent lists support automatic and manual pagination.** Use
|
|
15
|
+
`for await (const agent of zc.listAgents(opts))`, or `page.hasNextPage()` /
|
|
16
|
+
`page.getNextPage()`. Resolved pages are async iterable and provide `iterPages()`.
|
|
17
|
+
Later requests preserve the original label filters; early loop exit stops further fetches.
|
|
18
|
+
- Missing, invalid, or non-advancing agent pagination metadata now raises an error instead
|
|
19
|
+
of hiding a partial result. The API's fixed 100-item numeric pagination is unchanged.
|
|
20
|
+
Cross-page behavior is verified with synthetic offline HTTP tests; the live release
|
|
21
|
+
smoke covers one Agent/Session turn and cleanup, not a 101-agent pagination walk.
|
|
22
|
+
|
|
23
|
+
## 0.5.2 — 2026-09-04
|
|
24
|
+
|
|
25
|
+
### Documentation
|
|
26
|
+
|
|
27
|
+
- **`SessionRecord` now describes the response fields the API actually returns.**
|
|
28
|
+
`createSession()` returns the legacy `status: "running"` field without `run_status`;
|
|
29
|
+
later reads expose the latest run state through `run_status`, while `status` is nullable
|
|
30
|
+
and is not the run outcome. This changes the JSDoc emitted in the published declaration
|
|
31
|
+
files; runtime code and TypeScript signatures are unchanged.
|
|
32
|
+
|
|
6
33
|
## 0.5.1 — 2026-08-31
|
|
7
34
|
|
|
8
35
|
### Added
|
package/README.md
CHANGED
|
@@ -26,9 +26,14 @@ The base URL has a working default, so you do not configure an endpoint. Overrid
|
|
|
26
26
|
|
|
27
27
|
```ts
|
|
28
28
|
// 1. Create an agent. Ownership is derived from your key, so `resource` is all you
|
|
29
|
-
// send
|
|
29
|
+
// send. Select a model returned by this deployment instead of relying on a
|
|
30
|
+
// remembered id or on a server default that can rotate.
|
|
31
|
+
const models = await zc.listModels()
|
|
32
|
+
const primary = models.find((model) => model.model === 'litellm/gpt-5.6-terra')?.model
|
|
33
|
+
if (!primary) throw new Error('Choose a model returned by listModels()')
|
|
34
|
+
|
|
30
35
|
const agent = await zc.createAgent({
|
|
31
|
-
resource: { name: 'research-agent', model: { primary
|
|
36
|
+
resource: { name: 'research-agent', model: { primary } },
|
|
32
37
|
})
|
|
33
38
|
|
|
34
39
|
// 2. Start it. Without this, createSession() returns 409 agent_not_running.
|
|
@@ -52,15 +57,58 @@ An explicit option always beats the environment variable.
|
|
|
52
57
|
|
|
53
58
|
> **Finding the agent you built in the app.** The first path segment of a ZooWork chat URL
|
|
54
59
|
> (`/chat/<32-hex>/sessions/…`) is a *workspace* id, not an `agt_…`. Resolve it with
|
|
55
|
-
> `zc.listAgents({ labels: { workspace_id: '<32-hex>' } })`;
|
|
56
|
-
>
|
|
60
|
+
> `zc.listAgents({ labels: { workspace_id: '<32-hex>' } })`; use the pagination patterns
|
|
61
|
+
> below to read one page or traverse every match. Scope is `owner_uid AND org_id` — an agent a *colleague*
|
|
57
62
|
> created in your org is fetchable by id but will not appear in your list.
|
|
58
63
|
|
|
59
64
|
> **Wait on `status.desired_state`, never on `status.actual_state`.**
|
|
60
65
|
> `actual_state` reports chat-channel connectivity. An API-only agent has no channels,
|
|
61
|
-
>
|
|
62
|
-
>
|
|
63
|
-
>
|
|
66
|
+
> but its projection depends on the channel-status capability: a GET can report `active`
|
|
67
|
+
> with zero channel counts and a `status_message` saying health was not verified when that
|
|
68
|
+
> capability is unsupported, while a transient health lookup failure remains `activating`.
|
|
69
|
+
> List and GET can therefore briefly disagree. None of these values is readiness, and
|
|
70
|
+
> `running` is not an `actual_state` value. Use `await zc.waitUntilRunning(agentId)`; it
|
|
71
|
+
> correctly polls `desired_state`.
|
|
72
|
+
|
|
73
|
+
## Listing agents and pagination
|
|
74
|
+
|
|
75
|
+
`listAgents()` returns an awaitable, async-iterable request. Use `for await` to traverse all
|
|
76
|
+
matching agents; the SDK requests each next page only as you consume the results:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
for await (const agent of zc.listAgents({ labels: { project: 'research' } })) {
|
|
80
|
+
console.log(agent.agent_id)
|
|
81
|
+
// break when you have enough; later pages will not be fetched.
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For a single page, `await` the request and read `.data`. The page preserves `page`,
|
|
86
|
+
`page_size`, and `total`, and exposes `next_page` (`null` when there are no more results):
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
const page = await zc.listAgents()
|
|
90
|
+
console.log(page.data, page.total, page.next_page)
|
|
91
|
+
|
|
92
|
+
if (page.hasNextPage()) {
|
|
93
|
+
const next = await page.getNextPage() // retains the original label filters
|
|
94
|
+
console.log(next.data)
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can also use `for await (const agent of page)` to iterate from an already-fetched page,
|
|
99
|
+
or `for await (const batch of page.iterPages())` to process one page at a time.
|
|
100
|
+
`getNextPage()` rejects if there is no next page; errors fetching later pages reject iteration.
|
|
101
|
+
|
|
102
|
+
The API uses **numeric pages starting at 1**, with a fixed page size of 100. The SDK derives
|
|
103
|
+
`next_page` from the returned `page`, `page_size`, and `total`; it is a number, not an opaque
|
|
104
|
+
cursor. To resume explicitly, use `zc.listAgents({ page: nextPage, labels: originalLabels })`.
|
|
105
|
+
There is no configurable `limit`. Pagination is not a snapshot: concurrent additions or
|
|
106
|
+
deletions can shift results between pages.
|
|
107
|
+
|
|
108
|
+
**Migration from the array return:** replace `const agents = await zc.listAgents(opts)` with
|
|
109
|
+
`const { data: agents } = await zc.listAgents(opts)` to keep reading one page, or switch to
|
|
110
|
+
`for await` to read every match. Missing or invalid pagination metadata now raises an error
|
|
111
|
+
instead of silently returning an empty or apparently complete array.
|
|
64
112
|
|
|
65
113
|
## Streaming a turn
|
|
66
114
|
|
|
@@ -85,8 +133,14 @@ for await (const ev of zc.streamEvents(agent.agent_id, session.session_id)) {
|
|
|
85
133
|
Three things worth knowing before you write that loop:
|
|
86
134
|
|
|
87
135
|
- **The stream is session-scoped and does not close when a turn ends.** The server closes it after an idle period. Break on `isRunFinished(ev)` yourself, or you block until that timeout.
|
|
88
|
-
- **
|
|
89
|
-
- **REST and SSE
|
|
136
|
+
- **Save the opaque cursor.** After consuming an event, retain `ev.cursor` and resume with `{ cursor }`. Do not derive it from `seq` or mix it with `after`: `after` selects the deprecated event lane, which omits user-input events. The SDK sends the cursor in the query; do not rely on a raw `Last-Event-ID` header passing through the public gateway.
|
|
137
|
+
- **The default unified REST and SSE wire formats use snake_case.** Older event formats differ; the SDK normalizes both into `SessionEvent`, where you read `eventType`. Keep the cursor unchanged.
|
|
138
|
+
|
|
139
|
+
For API sessions, `user.message` can carry `actor: { ref: 'customer-42' }`, including in
|
|
140
|
+
`initial_events`. This source-reviewed field selects per-user memory attribution. Your server
|
|
141
|
+
must authenticate the user and authorize the session; `actor.ref` does neither. It does not
|
|
142
|
+
isolate the shared agent's sandbox files or erase a session's previous context. Omit `actor`
|
|
143
|
+
to use the owner; IM sessions reject it. See the field's SDK comment for input constraints.
|
|
90
144
|
|
|
91
145
|
## Bring your own skill
|
|
92
146
|
|
|
@@ -106,6 +160,13 @@ and it is the first one nearly everyone gets. `scope` is `org` or `personal`; th
|
|
|
106
160
|
control what a skill says. `uploadSkillVersion` publishes an update, and agents that installed it
|
|
107
161
|
unpinned follow along without another `putAgentSkill`.
|
|
108
162
|
|
|
163
|
+
`uploadSkillVersion` returns a `SkillVersionRecord` with `version` and `state`, not the
|
|
164
|
+
`latest_version` and `status` of the `SkillRecord` returned by `uploadSkill`. This return
|
|
165
|
+
contract is source-reviewed, not a new live recording. On initial create, put the description
|
|
166
|
+
in the zip's frontmatter: the gateway drops the `description` option. Version uploads can
|
|
167
|
+
use that override. A successful create retried under the same name can return `409 skill_exists`;
|
|
168
|
+
read back first. Version uploads deduplicate identical content for the same skill, not HTTP keys.
|
|
169
|
+
|
|
109
170
|
## Schedules, wake and exec
|
|
110
171
|
|
|
111
172
|
```ts
|
|
@@ -125,6 +186,10 @@ const { exit_code, stdout } = await zc.exec(agent.agent_id, ['bash', '-lc', 'pwd
|
|
|
125
186
|
`listScheduleRuns`.
|
|
126
187
|
- **`updateSchedule` must omit `sessionTarget`.** It is immutable, and echoing it back from a
|
|
127
188
|
`getSchedule` result — the obvious thing to do — is a 400. The types refuse it for you.
|
|
189
|
+
- **An interval uses `{ kind: 'every', everyMs: 60_000 }`.** Optional `anchorMs` aligns it.
|
|
190
|
+
The earlier `every` type was incorrect; migrate explicitly, without guessing string units.
|
|
191
|
+
This correction and optional `ScheduleRun.session_id` are source-reviewed. Use that session
|
|
192
|
+
link only when present; it is not a run-success indicator.
|
|
128
193
|
- **`exec` resolves on a failed command.** A non-zero exit is still HTTP 200: check `exit_code`,
|
|
129
194
|
don't wait for a rejection. It runs in `/workspace` and needs an agent-scope sandbox.
|
|
130
195
|
- **A cron job can carry an outcome gate.** `payload.outcome` says what "done" looks like — a
|
|
@@ -141,8 +206,12 @@ const { exit_code, stdout } = await zc.exec(agent.agent_id, ['bash', '-lc', 'pwd
|
|
|
141
206
|
creation time.
|
|
142
207
|
|
|
143
208
|
`listApprovals` / `resolveApproval` expose the approvals resource — `decision` is one of
|
|
144
|
-
`allow-once`, `allow-always`, `deny`.
|
|
145
|
-
|
|
209
|
+
`allow-once`, `allow-always`, `deny`. End-to-end approval and turn-budget behavior need
|
|
210
|
+
separate verification on the deployment you use.
|
|
211
|
+
|
|
212
|
+
Approval response fields are source-reviewed, not end-to-end verified: read `requested_at`,
|
|
213
|
+
`allowed_decisions` and optional timeout/resolution fields defensively. `signaled: true` means
|
|
214
|
+
the resolution was accepted; a returned `status: 'pending'` is not completed execution.
|
|
146
215
|
|
|
147
216
|
`listEnvironments`, `getEnvironment`, `createEnvironment`, `createEnvironmentVersion`,
|
|
148
217
|
`getEnvironmentVersion` and `archiveEnvironment` manage prebuilt sandbox images (apt/npm/pip
|
|
@@ -151,6 +220,14 @@ start: an agent's Environment **freezes on its first sandbox creation** — afte
|
|
|
151
220
|
is `409 environment_locked`, and stopping the agent does not clear it — and sandbox networking
|
|
152
221
|
defaults to unrestricted unless the Environment declares `networking: { type: 'limited' }`.
|
|
153
222
|
|
|
223
|
+
Build polling must have a deadline and handle `partial_ready`: some resource classes can be
|
|
224
|
+
ready while others are building or failed. `getEnvironmentVersion(id, version, { resourceClass:
|
|
225
|
+
'starter' })` selects one class; omitting the option keeps the aggregate read. Re-read the
|
|
226
|
+
aggregate before concluding the build is fully ready. These details are source-reviewed.
|
|
227
|
+
|
|
228
|
+
Channel callers must not use `allow_from` as an access-control list: the public gateway ignores
|
|
229
|
+
it. Use supported `dm_policy` settings.
|
|
230
|
+
|
|
154
231
|
## Artifacts and the system prompt
|
|
155
232
|
|
|
156
233
|
```ts
|
|
@@ -193,6 +270,40 @@ Runnable examples in [`examples/`](examples):
|
|
|
193
270
|
- [`live-smoke.ts`](examples/live-smoke.ts) — drive one agent through one turn and verify the REST and SSE reads agree.
|
|
194
271
|
- [`capability-probe.ts`](examples/capability-probe.ts) — create a throwaway agent, walk the whole lifecycle, and print a verdict per capability.
|
|
195
272
|
|
|
273
|
+
## Testing and publishing (maintainers)
|
|
274
|
+
|
|
275
|
+
Testing and publishing are independent commands. After cloning this repository on a new
|
|
276
|
+
machine, install its locked development dependencies:
|
|
277
|
+
|
|
278
|
+
```sh
|
|
279
|
+
pnpm install --frozen-lockfile
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Run staging E2E explicitly when you want to verify the SDK (Node 22.20+):
|
|
283
|
+
|
|
284
|
+
```sh
|
|
285
|
+
pnpm test:e2e
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
The command prepares an isolated test package, prints individual offline cases and timed live
|
|
289
|
+
steps, and asks for a staging API key with input hidden. Submitting the key authorizes one
|
|
290
|
+
temporary Agent/Session, one potentially billable model turn and cleanup. JSON reports remain
|
|
291
|
+
in its printed private directory. The test never publishes. Normal `pnpm test` is offline
|
|
292
|
+
and needs no key. See [E2E and recovery instructions](e2e/README.md) for scope and options.
|
|
293
|
+
|
|
294
|
+
To publish the checked-out version, use npm normally:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
npm login
|
|
298
|
+
npm publish
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The `prepack` hook rebuilds `dist` from source; `npm publish` then publishes that package with
|
|
302
|
+
your npm account. It does not run E2E, read a staging key or require an E2E result directory.
|
|
303
|
+
You choose when to test and publish, including on different machines. Check the version and
|
|
304
|
+
changelog before publishing; existing npm versions cannot be overwritten. Use
|
|
305
|
+
`npm publish --dry-run` to inspect the package without uploading it.
|
|
306
|
+
|
|
196
307
|
## License
|
|
197
308
|
|
|
198
309
|
MIT
|
package/dist/client.d.ts
CHANGED
|
@@ -42,6 +42,29 @@ export interface ZooworkConfig {
|
|
|
42
42
|
/** Injected fetch for edge runtimes/tests; defaults to globalThis.fetch. */
|
|
43
43
|
fetch?: (input: string, init?: RequestInit) => Promise<Response>;
|
|
44
44
|
}
|
|
45
|
+
export interface AgentListParams {
|
|
46
|
+
labels?: Record<string, string>;
|
|
47
|
+
/** Starting page, numbered from 1. The API fixes page size at 100. */
|
|
48
|
+
page?: number;
|
|
49
|
+
}
|
|
50
|
+
/** A single page. Iterating this object asynchronously continues through subsequent pages. */
|
|
51
|
+
export interface AgentPage extends AsyncIterable<AgentRecord> {
|
|
52
|
+
/** Agents in this page only. */
|
|
53
|
+
readonly data: AgentRecord[];
|
|
54
|
+
readonly page: number;
|
|
55
|
+
readonly page_size: number;
|
|
56
|
+
readonly total: number;
|
|
57
|
+
/** Next numeric page to pass to listAgents, or null at the end. */
|
|
58
|
+
readonly next_page: number | null;
|
|
59
|
+
hasNextPage(): boolean;
|
|
60
|
+
/** Fetch the next page with the same filters. Rejects when there is no next page. */
|
|
61
|
+
getNextPage(): Promise<AgentPage>;
|
|
62
|
+
/** Iterate this and subsequent pages, fetching each only when needed. */
|
|
63
|
+
iterPages(): AsyncIterableIterator<AgentPage>;
|
|
64
|
+
}
|
|
65
|
+
/** Await one page, or use for-await directly to traverse all remaining agents. */
|
|
66
|
+
export interface AgentPagePromise extends Promise<AgentPage>, AsyncIterable<AgentRecord> {
|
|
67
|
+
}
|
|
45
68
|
export declare class ZooworkError extends Error {
|
|
46
69
|
status: number;
|
|
47
70
|
/**
|
|
@@ -114,9 +137,12 @@ export interface ModelInfo {
|
|
|
114
137
|
* other way to store it, so an authenticated MCP server cannot be made to work today.
|
|
115
138
|
* Declare public servers only.
|
|
116
139
|
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
140
|
+
* Remote HTTP only; no stdio. Catalog failures emit `agent.error` with
|
|
141
|
+
* `kind: 'mcp_connection_failed'` or `'mcp_authentication_failed'`, a server name,
|
|
142
|
+
* an errorMessage and an optional reason. Preserve unknown reason values.
|
|
143
|
+
* Healthy catalogs remain tied to the configuration. Transient failed catalogs can expire:
|
|
144
|
+
* a later catalog resolution may probe again, not a periodic retry or recovery guarantee.
|
|
145
|
+
* These failure/recovery details are source-reviewed, not deployment-verified here.
|
|
120
146
|
*/
|
|
121
147
|
export interface McpServerDeclaration {
|
|
122
148
|
/** Server slug. Appears in every tool name as `mcp__<name>__<tool>`. No underscores. */
|
|
@@ -129,6 +155,12 @@ export interface McpServerDeclaration {
|
|
|
129
155
|
credential?: string;
|
|
130
156
|
/** Expose only these tool names from this server. Omit for all of them. */
|
|
131
157
|
toolFilter?: string[];
|
|
158
|
+
/**
|
|
159
|
+
* How tools reach the model. `deferred` (the default when omitted) keeps them behind
|
|
160
|
+
* `tool_search` / `tool_describe` until loaded; `direct` declares them on the first request.
|
|
161
|
+
* There is no `auto` value.
|
|
162
|
+
*/
|
|
163
|
+
exposure?: 'deferred' | 'direct';
|
|
132
164
|
[k: string]: unknown;
|
|
133
165
|
}
|
|
134
166
|
/**
|
|
@@ -197,7 +229,12 @@ export interface OutcomeConfig {
|
|
|
197
229
|
}
|
|
198
230
|
export interface AgentResource {
|
|
199
231
|
name: string;
|
|
200
|
-
/**
|
|
232
|
+
/**
|
|
233
|
+
* Omit this section to pin the platform's current model defaults at create time. Those
|
|
234
|
+
* defaults can rotate; call `listModels()` and set `primary` explicitly for deterministic
|
|
235
|
+
* provisioning. `max_tokens` caps output tokens per model request; omit only that field to
|
|
236
|
+
* use the platform token limit.
|
|
237
|
+
*/
|
|
201
238
|
model?: {
|
|
202
239
|
primary: string;
|
|
203
240
|
input?: string[];
|
|
@@ -235,15 +272,18 @@ export interface AgentResource {
|
|
|
235
272
|
environment_version?: number;
|
|
236
273
|
}
|
|
237
274
|
/**
|
|
238
|
-
* Agent lifecycle state. Two fields, two very different meanings
|
|
239
|
-
* 2026-08-06:
|
|
275
|
+
* Agent lifecycle state. Two fields, two very different meanings:
|
|
240
276
|
*
|
|
241
277
|
* - `desired_state` is the one that gates the API. `running` is the precondition for
|
|
242
278
|
* createSession/postEvents; anything else is `409 agent_not_running`.
|
|
243
|
-
* - `actual_state` is CHANNEL
|
|
244
|
-
*
|
|
245
|
-
* `
|
|
246
|
-
*
|
|
279
|
+
* - `actual_state` is a best-effort CHANNEL-health projection, not API readiness. When
|
|
280
|
+
* route-status is unsupported, GET can report `active` with zero channel counts and a
|
|
281
|
+
* `status_message` saying health was not verified; a transient unknown remains
|
|
282
|
+
* `activating`. `listAgents` does not make the same foreground health query, so list and
|
|
283
|
+
* GET can briefly differ. Never gate on this field, and never poll it for `running` —
|
|
284
|
+
* that is not one of its values.
|
|
285
|
+
*
|
|
286
|
+
* The channel fallback behavior is source-reviewed, not deployment-verified here.
|
|
247
287
|
*/
|
|
248
288
|
export interface AgentStatus {
|
|
249
289
|
desired_state?: 'running' | 'stopped' | 'deleted' | string;
|
|
@@ -361,7 +401,7 @@ export interface AddChannelInput {
|
|
|
361
401
|
dm_policy?: string;
|
|
362
402
|
/** Server default: `'open'`. */
|
|
363
403
|
group_policy?: string;
|
|
364
|
-
/**
|
|
404
|
+
/** Retained for compatibility; the public gateway ignores this field. It is NOT an access allowlist. Use supported dm_policy settings. */
|
|
365
405
|
allow_from?: string[];
|
|
366
406
|
/**
|
|
367
407
|
* Platform credentials for the direct (non-QR) path. Keys are platform-specific and
|
|
@@ -548,6 +588,16 @@ export interface SkillRecord {
|
|
|
548
588
|
};
|
|
549
589
|
[k: string]: unknown;
|
|
550
590
|
}
|
|
591
|
+
/**
|
|
592
|
+
* The version row returned by uploadSkillVersion, not a SkillRecord.
|
|
593
|
+
* Source-reviewed fields; no new live recording is implied. The response stays unmodified.
|
|
594
|
+
*/
|
|
595
|
+
export interface SkillVersionRecord {
|
|
596
|
+
skill_id: string;
|
|
597
|
+
version: string | number;
|
|
598
|
+
state: 'pending' | 'ready' | 'failed' | string;
|
|
599
|
+
[k: string]: unknown;
|
|
600
|
+
}
|
|
551
601
|
/**
|
|
552
602
|
* One `session_transcripts` row, as projected by `getSession(…, { history: true })`.
|
|
553
603
|
*
|
|
@@ -568,12 +618,17 @@ export interface SessionRecord {
|
|
|
568
618
|
/** `api` for sessions you create, `cron` for ones a schedule fired. */
|
|
569
619
|
channel?: string;
|
|
570
620
|
/**
|
|
571
|
-
* `listSessions`
|
|
572
|
-
*
|
|
573
|
-
|
|
621
|
+
* `getSession` and `listSessions` carry the latest run state (`running`, `succeeded`, …) here.
|
|
622
|
+
* The `createSession` receipt does not include this field.
|
|
623
|
+
*/
|
|
624
|
+
run_status?: string | null;
|
|
625
|
+
/** Pending approval count on getSession; not included in every session projection. */
|
|
626
|
+
pending_approvals?: number;
|
|
627
|
+
/**
|
|
628
|
+
* `running` on a `createSession` receipt, nullable on `getSession`, and absent from
|
|
629
|
+
* `listSessions` rows. This is not the run outcome; read {@link SessionRecord.run_status}
|
|
630
|
+
* from a later read instead.
|
|
574
631
|
*/
|
|
575
|
-
run_status?: string;
|
|
576
|
-
/** Observed `null` on `getSession`. Prefer {@link SessionRecord.run_status} from `listSessions`. */
|
|
577
632
|
status?: string | null;
|
|
578
633
|
metadata?: Record<string, unknown>;
|
|
579
634
|
archived?: boolean;
|
|
@@ -586,6 +641,18 @@ export interface SessionRecord {
|
|
|
586
641
|
export interface OutboundEvent {
|
|
587
642
|
type: string;
|
|
588
643
|
content?: unknown;
|
|
644
|
+
/**
|
|
645
|
+
* user.message on an API session only, including createSession.initial_events.
|
|
646
|
+
* ref is 1–200 ASCII characters from [A-Za-z0-9._:@+-]. Omit actor to use the owner.
|
|
647
|
+
* Map an authenticated application user to a stable opaque ref on YOUR server.
|
|
648
|
+
* This selects memory attribution, not authentication, session authorization or file isolation.
|
|
649
|
+
* IM sessions reject actor; token and other actor keys are rejected with HTTP 400.
|
|
650
|
+
* Source-reviewed; deployment availability must be verified separately.
|
|
651
|
+
*/
|
|
652
|
+
actor?: {
|
|
653
|
+
ref: string;
|
|
654
|
+
token?: never;
|
|
655
|
+
};
|
|
589
656
|
[k: string]: unknown;
|
|
590
657
|
}
|
|
591
658
|
/** One `postEvents` receipt. An accepted event carries the full event object's fields too. */
|
|
@@ -602,11 +669,10 @@ export interface SessionEventPage {
|
|
|
602
669
|
nextCursor?: string | null;
|
|
603
670
|
}
|
|
604
671
|
/**
|
|
605
|
-
* When a schedule fires
|
|
606
|
-
*
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
* than guessed at, so anything the engine accepts still type-checks.
|
|
672
|
+
* When a schedule fires: cron expression, everyMs interval in milliseconds (optional
|
|
673
|
+
* anchorMs), or an ISO instant in at. The everyMs contract is source-reviewed; it was
|
|
674
|
+
* previously misdeclared as every. Use everyMs explicitly: the SDK does not convert units
|
|
675
|
+
* or rename the obsolete every field at runtime.
|
|
610
676
|
*
|
|
611
677
|
* Cron is a five-field expression. Macros and a `CRON_TZ=` prefix are rejected; overlap is
|
|
612
678
|
* fixed to SKIP server-side, so a fire that lands on a still-running one is dropped, not queued.
|
|
@@ -618,7 +684,8 @@ export type ScheduleSpec = {
|
|
|
618
684
|
[k: string]: unknown;
|
|
619
685
|
} | {
|
|
620
686
|
kind: 'every';
|
|
621
|
-
|
|
687
|
+
everyMs: number;
|
|
688
|
+
anchorMs?: number;
|
|
622
689
|
tz?: string;
|
|
623
690
|
[k: string]: unknown;
|
|
624
691
|
} | {
|
|
@@ -779,13 +846,16 @@ export interface ScheduleRecord {
|
|
|
779
846
|
* This is the only row that carries `status` (e.g. `skipped` for a fire against a disabled
|
|
780
847
|
* schedule).
|
|
781
848
|
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
849
|
+
* Source-reviewed additions can include session_id when the fire has a known session.
|
|
850
|
+
* It is optional, not proof of success, and may be absent for command jobs or an unlinked
|
|
851
|
+
* fire. Older recordings above omit it. Without it, list the agent's sessions and match
|
|
852
|
+
* channel: 'cron' with the session_key prefix agent:{agent_id}:cron:{schedule_id}:.
|
|
785
853
|
*/
|
|
786
854
|
export interface ScheduleRun {
|
|
787
855
|
/** Which projection this row came from. Decides which of the field groups below is populated. */
|
|
788
856
|
source?: 'temporal' | 'run_projection' | string;
|
|
857
|
+
/** Present only when a session can be associated with this fire. */
|
|
858
|
+
session_id?: string;
|
|
789
859
|
/** Un-qualified `schedule_id`. */
|
|
790
860
|
schedule_id?: string;
|
|
791
861
|
fired_at?: string;
|
|
@@ -806,15 +876,25 @@ export type ApprovalDecision = 'allow-once' | 'allow-always' | 'deny';
|
|
|
806
876
|
/**
|
|
807
877
|
* A tool call parked on a human decision.
|
|
808
878
|
*
|
|
809
|
-
*
|
|
810
|
-
*
|
|
811
|
-
*
|
|
879
|
+
* Fields below are source-reviewed; the existing live recordings have empty lists.
|
|
880
|
+
* A resolve receipt can have signaled:true while status is still pending: acceptance is not
|
|
881
|
+
* completion of the tool or run. Verify the resulting state separately.
|
|
812
882
|
*/
|
|
813
883
|
export interface ApprovalRecord {
|
|
814
884
|
approval_id?: string;
|
|
815
885
|
session_id?: string;
|
|
816
886
|
tool_name?: string;
|
|
817
887
|
status?: string;
|
|
888
|
+
arguments_preview?: string;
|
|
889
|
+
stake?: unknown;
|
|
890
|
+
requested_at?: string;
|
|
891
|
+
timeout_at?: string;
|
|
892
|
+
allowed_decisions?: ApprovalDecision[];
|
|
893
|
+
resolved_by?: string;
|
|
894
|
+
resolved_at?: string;
|
|
895
|
+
signaled?: boolean;
|
|
896
|
+
decision?: ApprovalDecision;
|
|
897
|
+
/** Legacy compatibility field; current source projects requested_at instead. */
|
|
818
898
|
created_at?: string;
|
|
819
899
|
[k: string]: unknown;
|
|
820
900
|
}
|
|
@@ -990,10 +1070,11 @@ export interface EnvironmentRecord {
|
|
|
990
1070
|
[k: string]: unknown;
|
|
991
1071
|
}
|
|
992
1072
|
/**
|
|
993
|
-
* One immutable Environment version. Builds
|
|
994
|
-
*
|
|
995
|
-
*
|
|
996
|
-
*
|
|
1073
|
+
* One immutable Environment version's build state. Builds can be queued, submitting, building,
|
|
1074
|
+
* verifying, partial_ready, ready or failed. partial_ready means some resource classes are
|
|
1075
|
+
* ready; others may still be building or may have failed. It is not by itself a success/failure
|
|
1076
|
+
* verdict for your selected class. Poll with a deadline; optionally read that resourceClass
|
|
1077
|
+
* and re-read the aggregate before drawing a conclusion.
|
|
997
1078
|
*
|
|
998
1079
|
* THE FIELD IS `status`, NOT `state` — staging-verified 2026-08-07. A poll loop written against
|
|
999
1080
|
* `state` compares `undefined` to `'ready'` forever and never terminates, which is precisely the
|
|
@@ -1002,8 +1083,8 @@ export interface EnvironmentRecord {
|
|
|
1002
1083
|
export interface EnvironmentVersionRecord {
|
|
1003
1084
|
environment_id?: string;
|
|
1004
1085
|
version?: number;
|
|
1005
|
-
/**
|
|
1006
|
-
status?: 'queued' | 'submitting' | 'building' | 'verifying' | 'ready' | 'failed' | string;
|
|
1086
|
+
/** Build status; partial_ready may be transient or a partial terminal result. */
|
|
1087
|
+
status?: 'queued' | 'submitting' | 'building' | 'verifying' | 'partial_ready' | 'ready' | 'failed' | string;
|
|
1007
1088
|
/** The normalized config this version was built from — not the one you posted verbatim. */
|
|
1008
1089
|
config?: EnvironmentConfig;
|
|
1009
1090
|
base_environment_id?: string;
|
|
@@ -1061,11 +1142,12 @@ export interface ZooworkClient {
|
|
|
1061
1142
|
*
|
|
1062
1143
|
* Note the scope is `owner_uid AND org_id`: an agent a colleague created in your org is
|
|
1063
1144
|
* fetchable by `getAgent` but will not appear here.
|
|
1145
|
+
*
|
|
1146
|
+
* `await listAgents()` returns one {@link AgentPage}; read `.data` for its agents and
|
|
1147
|
+
* `.next_page` / `.hasNextPage()` for continuation. `for await (const agent of listAgents())`
|
|
1148
|
+
* automatically fetches subsequent pages. Breaking the loop stops further requests.
|
|
1064
1149
|
*/
|
|
1065
|
-
listAgents(opts?:
|
|
1066
|
-
labels?: Record<string, string>;
|
|
1067
|
-
page?: number;
|
|
1068
|
-
}): Promise<AgentRecord[]>;
|
|
1150
|
+
listAgents(opts?: AgentListParams): AgentPagePromise;
|
|
1069
1151
|
getAgent(agentId: string): Promise<AgentRecord>;
|
|
1070
1152
|
/** PUT declared sections; bumps config_version on EVERY call — gate on drift, don't blind-retry. */
|
|
1071
1153
|
updateAgent(agentId: string, sections: Record<string, unknown>): Promise<AgentRecord>;
|
|
@@ -1078,13 +1160,17 @@ export interface ZooworkClient {
|
|
|
1078
1160
|
deleteAgent(agentId: string): Promise<void>;
|
|
1079
1161
|
/**
|
|
1080
1162
|
* Flip `desired_state` to `running` — the precondition for every session call.
|
|
1081
|
-
*
|
|
1082
|
-
*
|
|
1083
|
-
* because it has no chat-channel routes to reload. Do not treat it as failure.
|
|
1163
|
+
* A successful response can contain warnings. A non-2xx response still throws ZooworkError;
|
|
1164
|
+
* warnings are not guaranteed on each start/stop and are not a substitute for error handling.
|
|
1084
1165
|
*/
|
|
1085
1166
|
startAgent(agentId: string): Promise<{
|
|
1086
1167
|
warnings: string[];
|
|
1087
1168
|
}>;
|
|
1169
|
+
/**
|
|
1170
|
+
* Request stopped state. Dependency failures can reject after desired_state changes.
|
|
1171
|
+
* Read back and reconcile; desired_state alone does not prove all runtime work is cleaned up.
|
|
1172
|
+
* A successful response's warnings and a rejected HTTP call are different outcomes.
|
|
1173
|
+
*/
|
|
1088
1174
|
stopAgent(agentId: string): Promise<{
|
|
1089
1175
|
warnings: string[];
|
|
1090
1176
|
}>;
|
|
@@ -1283,10 +1369,11 @@ export interface ZooworkClient {
|
|
|
1283
1369
|
* accepted. `SKILL.md` must be non-empty and declare both `name` and `description`.
|
|
1284
1370
|
* 50 MB expanded, zip only (store/deflate), encrypted zips rejected.
|
|
1285
1371
|
*
|
|
1286
|
-
*
|
|
1287
|
-
*
|
|
1288
|
-
*
|
|
1289
|
-
*
|
|
1372
|
+
* scope is org or personal. Other values are rejected by the public gateway with HTTP 400.
|
|
1373
|
+
* Ownership comes from your key. On this CREATE operation the public gateway drops the
|
|
1374
|
+
* description option: put the description in the zip's frontmatter instead.
|
|
1375
|
+
* idempotencyKey is retained as a transport option, not a replay guarantee for Skill uploads.
|
|
1376
|
+
* A retry after a successful create can return 409 skill_exists; read back before retrying.
|
|
1290
1377
|
*/
|
|
1291
1378
|
uploadSkill(zip: Blob | ArrayBuffer | Uint8Array, opts: {
|
|
1292
1379
|
scope: 'org' | 'personal';
|
|
@@ -1297,7 +1384,9 @@ export interface ZooworkClient {
|
|
|
1297
1384
|
/**
|
|
1298
1385
|
* Publish a new version of an existing skill from a zip. Same zip rules as
|
|
1299
1386
|
* {@link ZooworkClient.uploadSkill}, plus: the frontmatter `name` must match the target
|
|
1300
|
-
* skill's name.
|
|
1387
|
+
* skill's name. Unlike root create, description can override the frontmatter here.
|
|
1388
|
+
* Returns a version row (version/state), not a SkillRecord (latest_version/status).
|
|
1389
|
+
* Identical content for the same skill is deduplicated by content, not by Idempotency-Key.
|
|
1301
1390
|
*
|
|
1302
1391
|
* Agents that installed the skill unpinned follow the new version on their own — the registry
|
|
1303
1392
|
* bumps their `config_version`; you do not re-`putAgentSkill`.
|
|
@@ -1306,7 +1395,7 @@ export interface ZooworkClient {
|
|
|
1306
1395
|
fileName?: string;
|
|
1307
1396
|
description?: string;
|
|
1308
1397
|
idempotencyKey?: string;
|
|
1309
|
-
}): Promise<
|
|
1398
|
+
}): Promise<SkillVersionRecord>;
|
|
1310
1399
|
/**
|
|
1311
1400
|
* The catalog visible to your key: global skills plus your org/personal ones. `q` matches on
|
|
1312
1401
|
* name; `page` is 1-based with a fixed page size of 100. Only the `org`/`personal` rows are
|
|
@@ -1406,11 +1495,10 @@ export interface ZooworkClient {
|
|
|
1406
1495
|
* staging-verified 2026-08-07; any other value is rejected, so there is no way to list
|
|
1407
1496
|
* resolved ones.
|
|
1408
1497
|
*
|
|
1409
|
-
* Approvals are a REST resource here,
|
|
1410
|
-
*
|
|
1411
|
-
*
|
|
1412
|
-
*
|
|
1413
|
-
* on an approval burns its whole turn budget waiting.
|
|
1498
|
+
* Approvals are a REST resource here, not an interchangeable user.tool_confirmation
|
|
1499
|
+
* payload. A deployment without approval support can return 501 not_configured.
|
|
1500
|
+
* The response contract is source-reviewed; end-to-end approval and turn-budget behavior
|
|
1501
|
+
* need separate verification on the deployment you use.
|
|
1414
1502
|
*/
|
|
1415
1503
|
listApprovals(agentId: string, opts?: {
|
|
1416
1504
|
status?: 'pending';
|
|
@@ -1419,7 +1507,7 @@ export interface ZooworkClient {
|
|
|
1419
1507
|
resolveApproval(agentId: string, approvalId: string, input: {
|
|
1420
1508
|
decision: ApprovalDecision;
|
|
1421
1509
|
resolvedBy?: string;
|
|
1422
|
-
}): Promise<
|
|
1510
|
+
}): Promise<ApprovalRecord>;
|
|
1423
1511
|
/**
|
|
1424
1512
|
* Artifacts this agent published, one page per call — but unlike `listEvents`, the page SAYS
|
|
1425
1513
|
* when it truncated: read `has_more`. `limit` defaults to 50, capped at 100; filter by
|
|
@@ -1537,9 +1625,9 @@ export interface ZooworkClient {
|
|
|
1537
1625
|
*
|
|
1538
1626
|
* `resource.config` takes exactly four keys — packages / files / build / networking — and
|
|
1539
1627
|
* anything else is `400 invalid_environment_config`. Building is asynchronous: poll
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1542
|
-
*
|
|
1628
|
+
* getEnvironmentVersion with a deadline before pinning it on an agent. Handle failed and
|
|
1629
|
+
* partial_ready explicitly; selected-class readiness is different from aggregate readiness.
|
|
1630
|
+
* The field is status, not state. A loop without a timeout can otherwise wait forever.
|
|
1543
1631
|
*/
|
|
1544
1632
|
createEnvironment(input: {
|
|
1545
1633
|
resource: EnvironmentResource;
|
|
@@ -1555,15 +1643,17 @@ export interface ZooworkClient {
|
|
|
1555
1643
|
*/
|
|
1556
1644
|
archiveEnvironment(environmentId: string): Promise<EnvironmentRecord>;
|
|
1557
1645
|
/**
|
|
1558
|
-
* Add
|
|
1559
|
-
*
|
|
1646
|
+
* Add a new immutable configuration version to an existing Environment. This is NOT the
|
|
1647
|
+
* separate operation that retries an existing failed version; the SDK does not wrap retry.
|
|
1560
1648
|
*
|
|
1561
1649
|
* The route is reachable, but the request body was not exercised against staging on
|
|
1562
1650
|
* 2026-08-07 — the SDK sends `{ resource: { config } }`, mirroring create.
|
|
1563
1651
|
*/
|
|
1564
1652
|
createEnvironmentVersion(environmentId: string, config: EnvironmentConfig, idempotencyKey?: string): Promise<EnvironmentVersionRecord>;
|
|
1565
|
-
/**
|
|
1566
|
-
getEnvironmentVersion(environmentId: string, version: number
|
|
1653
|
+
/** Read aggregate build state, or one resource class. Source-reviewed selector; use bounded polling. */
|
|
1654
|
+
getEnvironmentVersion(environmentId: string, version: number, opts?: {
|
|
1655
|
+
resourceClass?: 'starter' | 'pro' | 'ultra';
|
|
1656
|
+
}): Promise<EnvironmentVersionRecord>;
|
|
1567
1657
|
}
|
|
1568
1658
|
/**
|
|
1569
1659
|
* Create a client.
|
package/dist/client.js
CHANGED
|
@@ -308,12 +308,57 @@ export function createZooworkClient(cfg = {}) {
|
|
|
308
308
|
...(idempotencyKey ? { headers: { 'Idempotency-Key': idempotencyKey } } : {}),
|
|
309
309
|
});
|
|
310
310
|
},
|
|
311
|
-
listAgents:
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
311
|
+
listAgents: (opts = {}) => {
|
|
312
|
+
// Capture the filters once so caller mutations cannot change the scope mid-walk.
|
|
313
|
+
const labels = { ...opts.labels };
|
|
314
|
+
const fetchPage = async (pageNumber) => {
|
|
315
|
+
if (pageNumber !== undefined && (!Number.isSafeInteger(pageNumber) || pageNumber < 1)) {
|
|
316
|
+
throw new RangeError('Agent list page must be a positive safe integer');
|
|
317
|
+
}
|
|
318
|
+
const params = { page: pageNumber };
|
|
319
|
+
for (const [k, v] of Object.entries(labels))
|
|
320
|
+
params[`label.${k}`] = v;
|
|
321
|
+
const body = await json(`/agents${query(params)}`);
|
|
322
|
+
// Missing metadata must not silently turn a partial result into the last page.
|
|
323
|
+
// Check advancement too, so a server ignoring page cannot cause an endless walk.
|
|
324
|
+
if (!body || !Array.isArray(body.agents) || body.page !== (pageNumber ?? 1)
|
|
325
|
+
|| !Number.isSafeInteger(body.page_size) || body.page_size < 1
|
|
326
|
+
|| !Number.isSafeInteger(body.total) || body.total < 0) {
|
|
327
|
+
throw new Error('Invalid agent list pagination: expected agents, page, page_size, and total for the requested page');
|
|
328
|
+
}
|
|
329
|
+
const nextPage = body.page < Math.ceil(body.total / body.page_size) ? body.page + 1 : null;
|
|
330
|
+
const result = {
|
|
331
|
+
data: body.agents,
|
|
332
|
+
page: body.page,
|
|
333
|
+
page_size: body.page_size,
|
|
334
|
+
total: body.total,
|
|
335
|
+
next_page: nextPage,
|
|
336
|
+
hasNextPage: () => nextPage !== null,
|
|
337
|
+
getNextPage: async () => {
|
|
338
|
+
if (nextPage === null)
|
|
339
|
+
throw new Error('No next page');
|
|
340
|
+
return fetchPage(nextPage);
|
|
341
|
+
},
|
|
342
|
+
async *iterPages() {
|
|
343
|
+
let page = result;
|
|
344
|
+
while (true) {
|
|
345
|
+
yield page;
|
|
346
|
+
if (!page.hasNextPage())
|
|
347
|
+
return;
|
|
348
|
+
page = await page.getNextPage();
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
async *[Symbol.asyncIterator]() {
|
|
352
|
+
for await (const page of result.iterPages())
|
|
353
|
+
yield* page.data;
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
return result;
|
|
357
|
+
};
|
|
358
|
+
const request = fetchPage(opts.page);
|
|
359
|
+
return Object.assign(request, {
|
|
360
|
+
async *[Symbol.asyncIterator]() { yield* await request; },
|
|
361
|
+
});
|
|
317
362
|
},
|
|
318
363
|
getAgent: (agentId) => json(agents(agentId)),
|
|
319
364
|
updateAgent: (agentId, sections) => json(agents(agentId), { method: 'PUT', body: JSON.stringify(sections) }),
|
|
@@ -700,7 +745,7 @@ export function createZooworkClient(cfg = {}) {
|
|
|
700
745
|
body: JSON.stringify({ resource: { config } }),
|
|
701
746
|
...(idempotencyKey ? { headers: { 'Idempotency-Key': idempotencyKey } } : {}),
|
|
702
747
|
}),
|
|
703
|
-
getEnvironmentVersion: (environmentId, version) => json(`${environments(environmentId)}/versions/${encodeURIComponent(String(version))}`),
|
|
748
|
+
getEnvironmentVersion: (environmentId, version, opts = {}) => json(`${environments(environmentId)}/versions/${encodeURIComponent(String(version))}${query({ resource_class: opts.resourceClass })}`),
|
|
704
749
|
};
|
|
705
750
|
return client;
|
|
706
751
|
}
|
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 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';
|
|
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
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';
|
package/dist/sse.d.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SSE line parser for the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* live wire and needed no changes. The `id:` field matters: The server frames each durable
|
|
6
|
-
* event as `id: <seq>` + `data: <json>`, so dropping the id line would freeze the resume
|
|
7
|
-
* cursor. Web Streams + TextDecoder only, so this runs in workers and browsers as well as
|
|
8
|
-
* Node.
|
|
2
|
+
* SSE line parser for the /events/stream endpoint.
|
|
3
|
+
* Preserve id as an opaque string: unified events use it as a resume cursor, while the
|
|
4
|
+
* legacy lane can send numeric ids. Web Streams + TextDecoder only.
|
|
9
5
|
*/
|
|
10
6
|
export interface SSEMessage {
|
|
11
7
|
event: string;
|
|
12
|
-
/** The SSE
|
|
8
|
+
/** The SSE id field, unchanged. Do not parse an opaque resume cursor as a number. */
|
|
13
9
|
id?: string;
|
|
14
10
|
data: unknown;
|
|
15
11
|
}
|
package/dist/sse.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SSE line parser for the
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* live wire and needed no changes. The `id:` field matters: The server frames each durable
|
|
6
|
-
* event as `id: <seq>` + `data: <json>`, so dropping the id line would freeze the resume
|
|
7
|
-
* cursor. Web Streams + TextDecoder only, so this runs in workers and browsers as well as
|
|
8
|
-
* Node.
|
|
2
|
+
* SSE line parser for the /events/stream endpoint.
|
|
3
|
+
* Preserve id as an opaque string: unified events use it as a resume cursor, while the
|
|
4
|
+
* legacy lane can send numeric ids. Web Streams + TextDecoder only.
|
|
9
5
|
*/
|
|
10
6
|
export const isObj = (v) => !!v && typeof v === 'object';
|
|
11
7
|
export async function* parseSSE(body) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoowork-ai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript SDK for the ZooWork Managed Agents API (Developer Preview)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"zoowork",
|
|
@@ -39,16 +39,22 @@
|
|
|
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
|
+
},
|
|
42
48
|
"scripts": {
|
|
43
49
|
"build": "tsc -p tsconfig.build.json",
|
|
44
50
|
"typecheck": "tsc --noEmit",
|
|
45
51
|
"test": "tsc --noEmit && vitest run",
|
|
46
52
|
"test:watch": "vitest",
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
+
"test:e2e": "node e2e/command.ts",
|
|
54
|
+
"typecheck:e2e": "tsc -p tsconfig.e2e.json",
|
|
55
|
+
"test:e2e:offline": "node --import tsx --test --test-reporter=spec e2e/*.test.ts",
|
|
56
|
+
"e2e:prepare": "node e2e/runner.ts prepare",
|
|
57
|
+
"e2e:run": "node e2e/runner.ts run",
|
|
58
|
+
"e2e:verify": "node e2e/runner.ts verify"
|
|
53
59
|
}
|
|
54
|
-
}
|
|
60
|
+
}
|