@zoowork-ai/sdk 0.9.0 → 0.10.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 CHANGED
@@ -3,7 +3,20 @@
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
- ## Unreleased
6
+ ## 0.10.0 — 2026-10-03
7
+
8
+ - Add Files, read-only Agent Database, Usage, Run Output, action paging/detail and Agent webhook management helpers.
9
+ - Add typed MCP confirmation, active Session creation and configuration concurrency metadata.
10
+ - Align onboarding and capability examples with Platform Project keys.
11
+
12
+ ### Known service and documentation limitations
13
+
14
+ Verified against production on 2026-10-03; these are not resolved by this SDK release:
15
+
16
+ - Workspace Files read/write APIs return HTTP 502 with both Platform and legacy keys ([ecap #4006](https://github.com/SerendipityOneInc/ecap-workspace/issues/4006)).
17
+ - Legacy keys cannot update or remove visible global Skill assignments on their own Agents; Platform keys succeed ([ecap #4007](https://github.com/SerendipityOneInc/ecap-workspace/issues/4007)).
18
+ - Published Authentication URLs redirect to Quickstart, including the AI Markdown entry ([docs #56](https://github.com/SerendipityOneInc/zoowork-agents-docs/issues/56)).
19
+ - Agent Database reads depend on deployment support. The production viewer was disabled, so its successful read path has not been validated.
7
20
 
8
21
  ## 0.9.0 — 2026-10-01
9
22
 
@@ -23,7 +36,7 @@ day the behaviour was verified, not the day it was written.
23
36
  - **The webhook event vocabulary.** `WEBHOOK_EVENT_TYPES` lists the sixteen types Engine
24
37
  delivers today, with a `data` shape per type behind `WebhookEventFor<T>` and
25
38
  `knownWebhookEvent()`. `WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES` declares the five schedule
26
- configuration events whose server side is not deployed yet. A type the release does not know
39
+ configuration events for schedule configuration changes. A type the release does not know
27
40
  passes through with its raw `type` and `data` instead of throwing, so a receiver stays
28
41
  forward compatible.
29
42
  - Fixed cross-language signing vectors in `src/__vectors__/webhook-vectors.json`, copied verbatim
@@ -39,9 +52,8 @@ day the behaviour was verified, not the day it was written.
39
52
 
40
53
  ### Changed
41
54
 
42
- - Local E2E checks accept Platform `zwp_live_` keys as well as legacy `zct_` keys. Production
43
- checks require an explicit URL and confirmation, and record their scope separately from
44
- staging checks. The SDK already accepts Platform keys without a client API change.
55
+ - Local E2E checks accept Platform Project keys. Production checks require an explicit URL
56
+ and confirmation, and record their scope separately from staging checks.
45
57
  - Live smoke tests select only selectable catalog models.
46
58
 
47
59
  ## 0.8.0 — 2026-09-20
@@ -220,8 +232,7 @@ No runtime change — comments only.
220
232
  - `createZooclawClient` → `createZooworkClient`; `ZooclawClient`, `ZooclawError`,
221
233
  `ZooclawAuth`, `ZooclawConfig` → `Zoowork*`.
222
234
  - `ZOOCLAW_API_KEY` / `ZOOCLAW_BASE_URL` → `ZOOWORK_API_KEY` / `ZOOWORK_BASE_URL`.
223
- - Server-side identifiers are unchanged: API keys still start with `zct_`, and skill or
224
- environment names the API returns (e.g. `zooclaw-tts`) are whatever the server says.
235
+ - Server-side identifiers and resource names remain opaque.
225
236
 
226
237
  ## 0.3.4 — 2026-08-25
227
238
 
package/README.md CHANGED
@@ -10,9 +10,7 @@ npm install @zoowork-ai/sdk
10
10
 
11
11
  ## Quickstart
12
12
 
13
- Platform Project keys (`zwp_live_...`) and existing Work tokens (`zct_...`) both work with `apiKey`. Platform scopes Agent and Session access to the key’s Project and requires initialized Org billing and bound owner credentials. Rebind the key after signing in when the API requests it.
14
-
15
- Create a Project key in Platform, or a Work token under **Settings → API Keys** in the ZooWork App. Secrets are shown once at creation. Keep them server-side: Platform keys carry Project scope, while Work tokens use the existing organization authorization contract.
13
+ Create a Project API key in [ZooWork Platform](https://platform.zoowork.ai). The secret is shown once. Save it as `ZOOWORK_API_KEY` on your server. Agent and Session access is scoped to the key's Project. Initialize Organization billing and bind owner credentials; sign in and rebind when the API requests it.
16
14
 
17
15
  ```ts
18
16
  import { createZooworkClient } from '@zoowork-ai/sdk'
@@ -68,12 +66,6 @@ separately.
68
66
 
69
67
  An explicit option always beats the environment variable.
70
68
 
71
- > **Finding the agent you built in the app.** The first path segment of a ZooWork chat URL
72
- > (`/chat/<32-hex>/sessions/…`) is a *workspace* id, not an `agt_…`. Resolve it with
73
- > `zc.listAgents({ labels: { workspace_id: '<32-hex>' } })`; use the pagination patterns
74
- > below to read one page or traverse every match. Scope is `owner_uid AND org_id` — an agent a *colleague*
75
- > created in your org is fetchable by id but will not appear in your list.
76
-
77
69
  > **Wait on `status.desired_state`, never on `status.actual_state`.**
78
70
  > `actual_state` reports chat-channel connectivity. An API-only agent has no channels,
79
71
  > but its projection depends on the channel-status capability: a GET can report `active`
@@ -155,30 +147,9 @@ must authenticate the user and authorize the session; `actor.ref` does neither.
155
147
  isolate the shared agent's sandbox files or erase a session's previous context. Omit `actor`
156
148
  to use the owner; IM sessions reject it. See the field's SDK comment for input constraints.
157
149
 
158
- ## Bring your own skill
159
-
160
- A skill is a zip. One upload creates the skill *and* its first version; `putAgentSkill` attaches it.
161
-
162
- ```ts
163
- import { readFile } from 'node:fs/promises'
164
-
165
- const skill = await zc.uploadSkill(await readFile('market-research.zip'), { scope: 'org' })
166
- await zc.putAgentSkill(agent.agent_id, skill.skill_id)
167
- ```
168
-
169
- The zip's single top-level directory must be named exactly like the `name` in its `SKILL.md`
170
- frontmatter — `market-research/SKILL.md` declaring `name: market-research`. A mismatch is a 400,
171
- and it is the first one nearly everyone gets. `scope` is `org` or `personal`; the preinstalled
172
- `global` skills are listable but not installable with an API key, so this is the only way to
173
- control what a skill says. `uploadSkillVersion` publishes an update, and agents that installed it
174
- unpinned follow along without another `putAgentSkill`.
150
+ ## Agent Skills
175
151
 
176
- `uploadSkillVersion` returns a `SkillVersionRecord` with `version` and `state`, not the
177
- `latest_version` and `status` of the `SkillRecord` returned by `uploadSkill`. This return
178
- contract is source-reviewed, not a new live recording. On initial create, put the description
179
- in the zip's frontmatter: the gateway drops the `description` option. Version uploads can
180
- use that override. A successful create retried under the same name can return `409 skill_exists`;
181
- read back first. Version uploads deduplicate identical content for the same skill, not HTTP keys.
152
+ New Agents receive global Skills by default. Use `listAgentSkills(agentId)` to inspect attached Skills. At create time, `resource.skills` accepts a catalog name or `skill_id`; `include_global_skills: false` or an explicit empty list opts out of automatic Skills. Root Skill uploads are unavailable to Project keys. Keep source changes in your application or the Agent workspace through the Files API.
182
153
 
183
154
  ## Schedules, wake and exec
184
155
 
@@ -249,20 +220,7 @@ Approval response fields are source-reviewed, not end-to-end verified: read `req
249
220
  `allowed_decisions` and optional timeout/resolution fields defensively. `signaled: true` means
250
221
  the resolution was accepted; a returned `status: 'pending'` is not completed execution.
251
222
 
252
- `listEnvironments`, `getEnvironment`, `createEnvironment`, `createEnvironmentVersion`,
253
- `getEnvironmentVersion` and `archiveEnvironment` manage prebuilt sandbox images (apt/npm/pip
254
- packages, files, a build script, and an outbound allowlist). Two facts worth having before you
255
- start: an agent's Environment **freezes on its first sandbox creation** — after that every change
256
- is `409 environment_locked`, and stopping the agent does not clear it — and sandbox networking
257
- defaults to unrestricted unless the Environment declares `networking: { type: 'limited' }`.
258
-
259
- Build polling must have a deadline and handle `partial_ready`: some resource classes can be
260
- ready while others are building or failed. `getEnvironmentVersion(id, version, { resourceClass:
261
- 'starter' })` selects one class; omitting the option keeps the aggregate read. Re-read the
262
- aggregate before concluding the build is fully ready. These details are source-reviewed.
263
-
264
- Channel callers must not use `allow_from` as an access-control list: the public gateway ignores
265
- it. Use supported `dm_policy` settings.
223
+ Platform uses its managed Environment. Root Environment administration and Channel binding return `404 service_api.not_found` for Project keys. An exported method does not expand a key's permissions.
266
224
 
267
225
  ## Artifacts and the system prompt
268
226
 
@@ -291,7 +249,9 @@ and answers the new pin plus the version bump it cost.
291
249
 
292
250
  Verification needs the **raw request bytes**. `express.json()` and most framework body parsers
293
251
  consume them, and a `JSON.parse` → `JSON.stringify` round trip does not reproduce them byte for
294
- byte, so read the body before anything else touches it:
252
+ byte, so read the body before anything else touches it. The example requires your
253
+ application to supply `acceptOnce`, an atomic durable insert plus work-item enqueue, before it
254
+ returns 204. A worker processes that item separately:
295
255
 
296
256
  ```ts
297
257
  import { createServer } from 'node:http'
@@ -315,12 +275,15 @@ createServer(async (req, res) => {
315
275
  throw error
316
276
  }
317
277
 
318
- // Acknowledge first, then do the work: the sender retries a slow or failed response, and
319
- // `event.id` is stable across retries, so it is also your deduplication key.
278
+ // Validate identity, then atomically persist the event and a durable work item.
279
+ // Implement acceptOnce with a unique webhook-id; a duplicate is successful too.
280
+ if (event.id !== req.headers['webhook-id']) { res.writeHead(400).end(); return }
281
+ try { await acceptOnce(event.id, event) } catch { res.writeHead(503).end(); return }
320
282
  res.writeHead(204).end()
321
283
 
284
+ // Dispatch this switch in the durable worker.
322
285
  const known = knownWebhookEvent(event)
323
- if (!known) return // a type this release does not know: already acknowledged, ignore it
286
+ if (!known) return // keep unknown events accepted without side effects
324
287
  switch (known.type) {
325
288
  case 'run.finished':
326
289
  console.log(known.data.run_id, known.data.status)
@@ -363,7 +326,7 @@ Four more things worth knowing:
363
326
  resolved to one of its values: choosing would be a guess about which send arrived. The Python
364
327
  SDK rejects it too.
365
328
  - **`unwrapWebhook` checks six fields and no more** — `object`, `id`, `type`, `schema_version`,
366
- `created_at`, `data` — so a field or event type a later Engine release adds is not a reason to
329
+ `created_at`, `data` — so a field or event type a later API release adds is not a reason to
367
330
  drop a delivery. `schema_version` must be a number with an **integer value**: `1` and `1.0` both
368
331
  pass, since JSON has one numeric type and they are the same number, while `1.5` is rejected with
369
332
  `invalid_payload`. The Python SDK reaches the same verdict on the same envelope.
@@ -374,7 +337,7 @@ Four more things worth knowing:
374
337
  it extends `Error`, while the Python SDK makes it a subclass of its own `ZooworkError` carrying a
375
338
  400. Match on `code`, and do not port `instanceof` checks between the two.
376
339
 
377
- You do not have to use this SDK to verify. Engine emits plain
340
+ You do not have to use this SDK to verify. ZooWork emits plain
378
341
  [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks), so the official
379
342
  library for any language works with the same `whsec_` secret and the same raw body — npm
380
343
  [`standardwebhooks`](https://www.npmjs.com/package/standardwebhooks), PyPI
@@ -439,3 +402,39 @@ before creating the GitHub Release when live verification is required. Use
439
402
  ## License
440
403
 
441
404
  MIT
405
+
406
+ ## Developer API helpers
407
+
408
+ These helpers require an SDK release that includes them. Check the installed declarations before using an example; use the documented HTTP endpoint if the installed release lacks the method.
409
+
410
+ ```ts
411
+ const files = await zc.getWorkspaceFile(agentId, '/workspace')
412
+ await zc.writeWorkspaceFile(agentId, '/workspace/input.txt', 'hello')
413
+ const bytes = await zc.getWorkspaceFileContent(agentId, '/workspace/result.bin')
414
+ const database = await zc.getAgentDatabase(agentId) // reading never provisions it
415
+ const rows = await zc.getAgentDatabaseRows(agentId, 'results', { limit: 100, offset: 0 })
416
+ const usage = await zc.getUsage({ range: '7d', view: 'both' })
417
+ const endpoint = await zc.createAgentWebhook(agentId, {
418
+ url: 'https://receiver.example/webhook', event_types: ['run.finished'],
419
+ }, 'register-hook-v1')
420
+ // Save signing_secret securely when present; an idempotent replay can return null.
421
+ const hooks = await zc.listAgentWebhooks(agentId) // hooks.webhooks
422
+ const output = await zc.getRunOutput(agentId, sessionId, runId)
423
+ const approvals = await zc.listApprovalPage(agentId, { sessionId })
424
+ ```
425
+
426
+ File reads derive `owner_uid` and `org_id` from the Agent projection. Raw file content is
427
+ `Uint8Array`; text writes are not binary uploads. Database inspection is read-only. Usage stays
428
+ within the current key scope. Page helpers retain `next_cursor` and `has_more`; replay cursors
429
+ verbatim. `getApproval` and `getCustomToolCall` read terminal as well as pending actions.
430
+
431
+ Agent webhook methods include get/update/delete, `rotateAgentWebhookSecret`, `testAgentWebhook`,
432
+ `getAgentWebhookEvent`, delivery list/detail and single/batch redelivery. Pass a stable idempotency
433
+ key to create, rotation, test and redelivery. A 202 receipt confirms queuing; query delivery
434
+ records to learn the result. SDK writes do not retry automatically.
435
+
436
+ `createSession` accepts `runtime_mode: 'active'` to pin the current active configuration at
437
+ creation. Omit it to resolve active configuration on later turns. `idle_compaction` preserves
438
+ false, null and omission. MCP tool overrides accept `requireConfirmation?: boolean`.
439
+ `updateAgent` accepts `expected_config_version`; a stale version returns
440
+ `409 active_config_changed`. Ownership-only changes do not increment the configuration version.
package/dist/client.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * ZooWork Managed Agents SDK — core client. Developer Preview.
3
3
  *
4
- * Authenticate with your organization API key (`zct_…`). It carries full tenant
5
- * authority, so it is SERVER-SIDE ONLY: never ship it in a browser or mobile bundle.
4
+ * Create a Project API key at https://platform.zoowork.ai. Keep it server-side: never ship it in a browser or mobile bundle.
6
5
  *
7
6
  * IDs are opaque strings and unknown response fields must be ignored — both are
8
7
  * forward-compatibility rules, not suggestions. Errors surface an `error.type`; match on
9
8
  * that, never on the message text.
10
9
  */
10
+ import { type DeveloperApi } from './developer-api.js';
11
11
  import { type SessionEvent } from './events.js';
12
12
  /**
13
13
  * The production API base URL — the default. You should not need to set this:
@@ -22,9 +22,9 @@ export type ZooworkAuth = {
22
22
  };
23
23
  export interface ZooworkConfig {
24
24
  /**
25
- * Your API key (`zct_...`). Defaults to `ZOOWORK_API_KEY`.
25
+ * Your Platform Project API key (`zwp_live_...`). Defaults to `ZOOWORK_API_KEY`.
26
26
  *
27
- * Server-side only: it authenticates as your whole organization, not as one end user.
27
+ * Server-side only: access is scoped to the selected Project. Authorize application users separately.
28
28
  */
29
29
  apiKey?: string;
30
30
  /**
@@ -115,6 +115,8 @@ export declare class ZooworkError extends Error {
115
115
  export interface Ownership {
116
116
  owner_uid: string;
117
117
  org_id: string;
118
+ project_id?: string | null;
119
+ visibility?: 'private' | 'project';
118
120
  }
119
121
  export interface ModelInfo {
120
122
  model: string;
@@ -143,6 +145,9 @@ export interface McpContextConfig {
143
145
  }
144
146
  export interface McpToolPermissionOverride {
145
147
  permission: McpToolPermission;
148
+ /** True requires permission: 'always_ask' and a decision for each call, even with a persistent grant.
149
+ * Only allow-once or deny is offered. False/omission retains permission policy behavior. */
150
+ requireConfirmation?: boolean;
146
151
  }
147
152
  /**
148
153
  * One remote MCP server, declared as `resource.mcp[]` on create or update.
@@ -298,10 +303,15 @@ export interface AgentResource {
298
303
  seed_policy?: string;
299
304
  }[];
300
305
  };
301
- skills?: {
306
+ skills?: (({
302
307
  skill_id: string;
308
+ name?: string;
309
+ } | {
310
+ name: string;
311
+ skill_id?: string;
312
+ }) & {
303
313
  version?: number | 'latest';
304
- }[];
314
+ })[];
305
315
  /**
306
316
  * Defaults to true. False disables automatic global Skills without removing explicitly
307
317
  * listed Skills. An explicit empty `skills` array also opts out.
@@ -655,6 +665,7 @@ export interface AgentRecord {
655
665
  environment_locked_at?: string | null;
656
666
  status?: AgentStatus;
657
667
  ownership?: Ownership;
668
+ sandbox_resource_class?: string;
658
669
  [k: string]: unknown;
659
670
  }
660
671
  /**
@@ -725,6 +736,10 @@ export interface SessionRecord {
725
736
  pending_approvals?: number;
726
737
  /** Pending application-executed custom-tool count on getSession. */
727
738
  pending_custom_tool_calls?: number;
739
+ pending_approval_ids?: string[];
740
+ pending_approval_ids_complete?: boolean;
741
+ pending_custom_tool_call_ids?: string[];
742
+ pending_custom_tool_call_ids_complete?: boolean;
728
743
  /**
729
744
  * `running` on a `createSession` receipt, nullable on `getSession`, and absent from
730
745
  * `listSessions` rows. This is not the run outcome; read {@link SessionRecord.run_status}
@@ -735,6 +750,8 @@ export interface SessionRecord {
735
750
  archived?: boolean;
736
751
  /** Present on filtered pages only when `includeDeleted` was requested. */
737
752
  deleted?: boolean;
753
+ idle_compaction?: boolean | null;
754
+ pinned_config_version?: number | null;
738
755
  runtime_mode?: 'active' | 'preview' | 'authoring' | 'evaluation' | string;
739
756
  config_version?: number;
740
757
  updated_at?: string;
@@ -940,12 +957,13 @@ export interface ScheduleUpdate {
940
957
  * - `scheduleId` is the FULLY-QUALIFIED name `cron/{computer_id}/{agent_id}/{schedule_id}`, not
941
958
  * the id you chose. Your id is `name`.
942
959
  *
943
- * The three responses also disagree with each other: `POST` answers with only snake_case
944
- * `schedule_name`; `GET /schedules/{id}` answers the camelCase projection below; `GET /schedules`
960
+ * Create receipts include the public `schedule_id` and snake_case `schedule_name`; `GET /schedules/{id}` answers the camelCase projection below; `GET /schedules`
945
961
  * answers the raw Temporal describe (`spec` / `state` / `memo` / `next_action_times`) with the
946
962
  * camelCase projection merged on top. Read defensively and match on what you find.
947
963
  */
948
964
  export interface ScheduleRecord {
965
+ /** Public opaque id, also present on create receipts. */
966
+ schedule_id?: string;
949
967
  /** FULLY-QUALIFIED: `cron/{computer_id}/{agent_id}/{schedule_id}`. Not the id you passed in. */
950
968
  scheduleId?: string;
951
969
  /** The `schedule_id` you chose. This is the one you pass back to get/update/delete. */
@@ -1016,6 +1034,9 @@ export interface ScheduleRecord {
1016
1034
  export interface ScheduleRun {
1017
1035
  /** Which projection this row came from. Decides which of the field groups below is populated. */
1018
1036
  source?: 'temporal' | 'run_projection' | string;
1037
+ linked_by?: string;
1038
+ run_id?: string;
1039
+ trigger?: string;
1019
1040
  /** Present only when a session can be associated with this fire. */
1020
1041
  session_id?: string;
1021
1042
  /** Un-qualified `schedule_id`. */
@@ -1043,6 +1064,9 @@ export type ApprovalDecision = 'allow-once' | 'allow-always' | 'deny';
1043
1064
  * completion of the tool or run. Verify the resulting state separately.
1044
1065
  */
1045
1066
  export interface ApprovalRecord {
1067
+ run_id?: string;
1068
+ tool_call_id?: string;
1069
+ resolution_channel?: string;
1046
1070
  approval_id?: string;
1047
1071
  session_id?: string;
1048
1072
  tool_name?: string;
@@ -1063,6 +1087,8 @@ export interface ApprovalRecord {
1063
1087
  export type CustomToolCallStatus = 'pending' | 'completed' | 'timeout' | 'cancelled' | string;
1064
1088
  /** One application-executed custom-tool call. Unknown response fields are preserved. */
1065
1089
  export interface CustomToolCallRecord {
1090
+ run_id?: string;
1091
+ resolution_channel?: string;
1066
1092
  call_id: string;
1067
1093
  session_id: string;
1068
1094
  tool_call_id: string;
@@ -1302,26 +1328,21 @@ export interface WakeResult {
1302
1328
  triggered: boolean;
1303
1329
  }
1304
1330
  export type { SessionEvent } from './events.js';
1305
- export interface ZooworkClient {
1331
+ export interface ZooworkClient extends DeveloperApi {
1306
1332
  listModels(): Promise<ModelInfo[]>;
1307
1333
  /**
1308
1334
  * Create an agent. The gateway derives ownership from your API key and always skips the
1309
1335
  * interactive onboarding interview — the agent answers your first message directly.
1310
- * `ownership` is accepted for callers that talk to the engine without the gateway;
1311
- * through the gateway it is overwritten and can be omitted.
1336
+ * Ownership is derived from the key. Omit caller-supplied ownership.
1312
1337
  */
1313
1338
  createAgent(input: {
1314
1339
  resource: AgentResource;
1315
1340
  ownership?: Ownership;
1316
1341
  }, idempotencyKey?: string): Promise<AgentRecord>;
1317
1342
  /**
1318
- * List the agents owned by your key's bound user (engine query: `owner_uid AND org_id`,
1319
- * both injected by the gateway). `labels` filters on declared labels — e.g.
1320
- * `{ labels: { workspace_id: '…' } }` resolves an app workspace id (the first path
1321
- * segment of a ZooWork chat URL) to its agent. Page size is fixed at 100 by the engine.
1322
- *
1323
- * Note the scope is `owner_uid AND org_id`: an agent a colleague created in your org is
1324
- * fetchable by `getAgent` but will not appear here.
1343
+ * List Agents within the key's Project and applicable owner visibility. Labels filter
1344
+ * declared labels, and page size is 100. Reads by id still recheck authorization;
1345
+ * a colleague's Agent is not automatically accessible.
1325
1346
  *
1326
1347
  * `await listAgents()` returns one {@link AgentPage}; read `.data` for its agents and
1327
1348
  * `.next_page` / `.hasNextPage()` for continuation. `for await (const agent of listAgents())`
@@ -1329,7 +1350,8 @@ export interface ZooworkClient {
1329
1350
  */
1330
1351
  listAgents(opts?: AgentListParams): AgentPagePromise;
1331
1352
  getAgent(agentId: string): Promise<AgentRecord>;
1332
- /** PUT declared sections; bumps config_version on EVERY call — gate on drift, don't blind-retry. */
1353
+ /** PUT declared sections. Ownership-only changes do not bump config_version.
1354
+ * Supply expected_config_version for an atomic version check; a mismatch returns 409 active_config_changed. */
1333
1355
  updateAgent(agentId: string, sections: Record<string, unknown>): Promise<AgentRecord>;
1334
1356
  /**
1335
1357
  * Soft delete: the agent stops resolving on the API, but this is not a resource purge.
@@ -1591,6 +1613,8 @@ export interface ZooworkClient {
1591
1613
  createSession(agentId: string, input: {
1592
1614
  initial_events?: OutboundEvent[];
1593
1615
  metadata?: Record<string, unknown>;
1616
+ runtime_mode?: 'active';
1617
+ idle_compaction?: boolean | null;
1594
1618
  }, idempotencyKey?: string): Promise<SessionRecord>;
1595
1619
  getSession(agentId: string, sessionId: string, opts?: {
1596
1620
  history?: boolean;
@@ -1678,6 +1702,7 @@ export interface ZooworkClient {
1678
1702
  /** Pending calls only. Any other status is rejected by the API. */
1679
1703
  listCustomToolCalls(agentId: string, opts?: {
1680
1704
  status?: 'pending';
1705
+ sessionId?: string;
1681
1706
  }): Promise<CustomToolCallRecord[]>;
1682
1707
  /**
1683
1708
  * Return one call's result. A pending call answers 202/signaled:true but stays pending until
@@ -1700,6 +1725,7 @@ export interface ZooworkClient {
1700
1725
  */
1701
1726
  listApprovals(agentId: string, opts?: {
1702
1727
  status?: 'pending';
1728
+ sessionId?: string;
1703
1729
  }): Promise<ApprovalRecord[]>;
1704
1730
  /** Resolve one approval. `decision` is exactly one of allow-once / allow-always / deny. */
1705
1731
  resolveApproval(agentId: string, approvalId: string, input: {
@@ -1857,7 +1883,7 @@ export interface ZooworkClient {
1857
1883
  * Create a client.
1858
1884
  *
1859
1885
  * ```ts
1860
- * const zc = createZooworkClient({ apiKey: 'zct_...' })
1886
+ * const zc = createZooworkClient({ apiKey: 'zwp_live_...' })
1861
1887
  * const zc = createZooworkClient() // reads ZOOWORK_API_KEY
1862
1888
  * ```
1863
1889
  *
package/dist/client.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * ZooWork Managed Agents SDK — core client. Developer Preview.
3
3
  *
4
- * Authenticate with your organization API key (`zct_…`). It carries full tenant
5
- * authority, so it is SERVER-SIDE ONLY: never ship it in a browser or mobile bundle.
4
+ * Create a Project API key at https://platform.zoowork.ai. Keep it server-side: never ship it in a browser or mobile bundle.
6
5
  *
7
6
  * IDs are opaque strings and unknown response fields must be ignored — both are
8
7
  * forward-compatibility rules, not suggestions. Errors surface an `error.type`; match on
9
8
  * that, never on the message text.
10
9
  */
10
+ import { createDeveloperApi } from './developer-api.js';
11
11
  import { parseSSE, isObj } from './sse.js';
12
12
  import { normalizeEvent } from './events.js';
13
13
  /**
@@ -143,7 +143,7 @@ function httpError(res, text) {
143
143
  * Create a client.
144
144
  *
145
145
  * ```ts
146
- * const zc = createZooworkClient({ apiKey: 'zct_...' })
146
+ * const zc = createZooworkClient({ apiKey: 'zwp_live_...' })
147
147
  * const zc = createZooworkClient() // reads ZOOWORK_API_KEY
148
148
  * ```
149
149
  *
@@ -165,7 +165,7 @@ export function createZooworkClient(cfg = {}) {
165
165
  })());
166
166
  if (!auth) {
167
167
  throw new Error('No ZooWork API key. Pass createZooworkClient({ apiKey }) or set ZOOWORK_API_KEY. ' +
168
- 'Keys look like zct_… and are issued by an organization administrator.');
168
+ 'Create a Project API key at https://platform.zoowork.ai.');
169
169
  }
170
170
  const bearer = 'serviceToken' in auth ? auth.serviceToken : auth.apiKey;
171
171
  /**
@@ -282,13 +282,20 @@ export function createZooworkClient(cfg = {}) {
282
282
  const own = projection.ownership;
283
283
  if (!own?.owner_uid || !own.org_id) {
284
284
  throw new ZooworkError(500, `agent ${agentId} projection carries no ownership — cannot derive the owner_uid/org_id ` +
285
- 'selectors the artifact routes require', 'ownership_unavailable');
285
+ 'selectors the file and artifact routes require', 'ownership_unavailable');
286
286
  }
287
287
  const sel = { owner_uid: own.owner_uid, org_id: own.org_id };
288
288
  ownershipByAgent.set(agentId, sel);
289
289
  return sel;
290
290
  };
291
+ const bytes = async (path) => {
292
+ const res = await doFetch(`${base}${path}`, { headers: { Authorization: `Bearer ${bearer}` } });
293
+ if (!res.ok)
294
+ throw httpError(res, await res.text());
295
+ return new Uint8Array(await res.arrayBuffer());
296
+ };
291
297
  const client = {
298
+ ...createDeveloperApi(json, bytes, artifactSelectors),
292
299
  listModels: async () => {
293
300
  const data = await json('/models');
294
301
  return Array.isArray(data) ? data : (data.models ?? []);
@@ -668,7 +675,7 @@ export function createZooworkClient(cfg = {}) {
668
675
  }
669
676
  },
670
677
  listCustomToolCalls: async (agentId, opts = {}) => {
671
- const data = await json(`${agents(agentId)}/custom_tool_calls${query({ status: opts.status })}`);
678
+ const data = await json(`${agents(agentId)}/custom_tool_calls${query({ status: opts.status, session_id: opts.sessionId })}`);
672
679
  return data.custom_tool_calls ?? [];
673
680
  },
674
681
  resolveCustomToolCall: (agentId, callId, input) => json(`${agents(agentId)}/custom_tool_calls/${encodeURIComponent(callId)}/result`, {
@@ -676,7 +683,7 @@ export function createZooworkClient(cfg = {}) {
676
683
  body: JSON.stringify(input),
677
684
  }),
678
685
  listApprovals: async (agentId, opts = {}) => {
679
- const data = await json(`${agents(agentId)}/approvals${query({ status: opts.status })}`);
686
+ const data = await json(`${agents(agentId)}/approvals${query({ status: opts.status, session_id: opts.sessionId })}`);
680
687
  return data.approvals ?? [];
681
688
  },
682
689
  resolveApproval: (agentId, approvalId, input) => json(`${agents(agentId)}/approvals/${encodeURIComponent(approvalId)}/resolve`, {
@@ -0,0 +1,200 @@
1
+ import type { ApprovalRecord, CustomToolCallRecord, Ownership } from './client.js';
2
+ import type { WebhookEventType } from './webhooks.js';
3
+ /** Response fields retain their API spelling; unknown additions are preserved. */
4
+ export type ApiObject = Record<string, unknown>;
5
+ export interface CursorOptions {
6
+ cursor?: string;
7
+ limit?: number;
8
+ }
9
+ export interface ActionListOptions extends CursorOptions {
10
+ status?: 'pending';
11
+ sessionId?: string;
12
+ }
13
+ export interface ApprovalPage extends ApiObject {
14
+ approvals: ApprovalRecord[];
15
+ has_more: boolean;
16
+ next_cursor: string | null;
17
+ }
18
+ export interface CustomToolCallPage extends ApiObject {
19
+ custom_tool_calls: CustomToolCallRecord[];
20
+ has_more: boolean;
21
+ next_cursor: string | null;
22
+ }
23
+ export interface WorkspaceFileEntry extends ApiObject {
24
+ name: string;
25
+ type: string;
26
+ size?: number;
27
+ updated_at?: string;
28
+ }
29
+ export type WorkspaceFile = (ApiObject & {
30
+ path: string;
31
+ content: string;
32
+ }) | (ApiObject & {
33
+ path: string;
34
+ entries: WorkspaceFileEntry[];
35
+ });
36
+ export interface AgentDatabase extends ApiObject {
37
+ status: 'not_provisioned' | 'ready';
38
+ tables?: {
39
+ name: unknown;
40
+ kind: unknown;
41
+ }[];
42
+ }
43
+ export interface AgentDatabaseRows extends ApiObject {
44
+ status: 'not_provisioned' | 'ready';
45
+ table?: string;
46
+ schema?: unknown[][];
47
+ columns?: string[];
48
+ rows?: unknown[][];
49
+ limit?: number;
50
+ offset?: number;
51
+ }
52
+ export interface UsageOptions {
53
+ range?: '24h' | '7d' | '30d';
54
+ timezone?: string;
55
+ groupBy?: 'session' | 'api_key';
56
+ view?: 'groups' | 'records' | 'both';
57
+ sessionId?: string;
58
+ apiKeyId?: string;
59
+ rootSessionId?: string;
60
+ attribution?: 'exact' | 'shared' | 'non_api' | 'unattributed';
61
+ page?: number;
62
+ perPage?: number;
63
+ asOf?: string;
64
+ snapshot?: string;
65
+ cursor?: string;
66
+ }
67
+ export interface UsageResult extends ApiObject {
68
+ groups?: ApiObject[];
69
+ records?: ApiObject[];
70
+ }
71
+ export interface RunOutputArtifact extends ApiObject {
72
+ artifact_id: string | null;
73
+ name: string;
74
+ content_type: string;
75
+ size: number;
76
+ }
77
+ export interface RunOutputItem extends ApiObject {
78
+ seq: number;
79
+ kind: string;
80
+ source: string;
81
+ text?: string;
82
+ artifacts: RunOutputArtifact[];
83
+ }
84
+ export interface RunOutput extends ApiObject {
85
+ run: ApiObject;
86
+ items: RunOutputItem[];
87
+ has_more: boolean;
88
+ next_cursor: string | null;
89
+ output_complete: boolean;
90
+ }
91
+ export interface AgentWebhookInput {
92
+ url: string;
93
+ event_types: Exclude<WebhookEventType, 'webhook.test'>[];
94
+ description?: string | null;
95
+ session_scope?: 'api' | 'all';
96
+ enabled?: boolean;
97
+ }
98
+ export interface AgentWebhookEndpoint extends ApiObject {
99
+ id: string;
100
+ url?: string;
101
+ event_types?: string[];
102
+ description?: string | null;
103
+ session_scope?: string;
104
+ enabled?: boolean;
105
+ }
106
+ export interface AgentWebhookPage extends ApiObject {
107
+ webhooks: AgentWebhookEndpoint[];
108
+ has_more: boolean;
109
+ next_cursor: string | null;
110
+ }
111
+ export interface AgentWebhookCreated extends ApiObject {
112
+ endpoint: AgentWebhookEndpoint;
113
+ signing_secret: string | null;
114
+ signing_secret_version: number;
115
+ signing_secret_available: boolean;
116
+ }
117
+ export interface AgentWebhookSecretRotation extends ApiObject {
118
+ endpoint_id: string;
119
+ signing_secret: string | null;
120
+ signing_secret_version: number;
121
+ signing_secret_available: boolean;
122
+ previous_versions?: unknown[];
123
+ }
124
+ export interface WebhookDeliveryOptions extends CursorOptions {
125
+ status?: 'pending' | 'in_flight' | 'succeeded' | 'dead' | 'cancelled';
126
+ eventType?: string;
127
+ eventId?: string;
128
+ sessionId?: string;
129
+ runId?: string;
130
+ scheduleId?: string;
131
+ }
132
+ export interface WebhookDeliveryPage extends ApiObject {
133
+ deliveries: ApiObject[];
134
+ has_more: boolean;
135
+ next_cursor: string | null;
136
+ }
137
+ /** These receipts acknowledge queuing, not receiver or business processing. */
138
+ export interface WebhookTestReceipt extends ApiObject {
139
+ object: 'webhook_test';
140
+ endpoint_id: string;
141
+ receipt_id: string;
142
+ }
143
+ export interface WebhookRedeliveryReceipt extends ApiObject {
144
+ object: 'webhook_redelivery';
145
+ delivery_id: string;
146
+ round: number;
147
+ deadline_at: string;
148
+ }
149
+ export interface WebhookBatchRedeliveryReceipt extends ApiObject {
150
+ object: 'webhook_redelivery_batch';
151
+ count: number;
152
+ }
153
+ export interface WebhookBatchRedeliveryInput {
154
+ status?: 'dead';
155
+ since?: string | null;
156
+ event_types?: string[] | null;
157
+ limit?: number;
158
+ }
159
+ export interface DeveloperApi {
160
+ getWorkspaceFile(agentId: string, path: string, opts?: {
161
+ showHidden?: boolean;
162
+ }): Promise<WorkspaceFile>;
163
+ writeWorkspaceFile(agentId: string, path: string, content: string): Promise<ApiObject>;
164
+ getWorkspaceFileContent(agentId: string, path: string, opts?: {
165
+ download?: boolean;
166
+ }): Promise<Uint8Array>;
167
+ getAgentDatabase(agentId: string): Promise<AgentDatabase>;
168
+ getAgentDatabaseRows(agentId: string, tableName: string, opts?: {
169
+ limit?: number;
170
+ offset?: number;
171
+ }): Promise<AgentDatabaseRows>;
172
+ getUsage(opts?: UsageOptions): Promise<UsageResult>;
173
+ getRunOutput(agentId: string, sessionId: string, runId: string, opts?: CursorOptions): Promise<RunOutput>;
174
+ getApproval(agentId: string, approvalId: string): Promise<ApprovalRecord>;
175
+ getCustomToolCall(agentId: string, callId: string): Promise<CustomToolCallRecord>;
176
+ listApprovalPage(agentId: string, opts?: ActionListOptions): Promise<ApprovalPage>;
177
+ listCustomToolCallPage(agentId: string, opts?: ActionListOptions): Promise<CustomToolCallPage>;
178
+ listAgentWebhooks(agentId: string, opts?: CursorOptions): Promise<AgentWebhookPage>;
179
+ createAgentWebhook(agentId: string, input: AgentWebhookInput, idempotencyKey: string): Promise<AgentWebhookCreated>;
180
+ getAgentWebhook(agentId: string, webhookId: string): Promise<AgentWebhookEndpoint>;
181
+ updateAgentWebhook(agentId: string, webhookId: string, input: Partial<AgentWebhookInput>): Promise<AgentWebhookEndpoint>;
182
+ deleteAgentWebhook(agentId: string, webhookId: string): Promise<void>;
183
+ rotateAgentWebhookSecret(agentId: string, webhookId: string, input: {
184
+ revoke_previous_after: 0 | 86400;
185
+ }, idempotencyKey: string): Promise<AgentWebhookSecretRotation>;
186
+ testAgentWebhook(agentId: string, webhookId: string, idempotencyKey: string): Promise<WebhookTestReceipt>;
187
+ getAgentWebhookEvent(agentId: string, eventId: string): Promise<ApiObject>;
188
+ listAgentWebhookDeliveries(agentId: string, webhookId: string, opts?: WebhookDeliveryOptions): Promise<WebhookDeliveryPage>;
189
+ getAgentWebhookDelivery(agentId: string, webhookId: string, deliveryId: string): Promise<ApiObject>;
190
+ redeliverAgentWebhookDelivery(agentId: string, webhookId: string, deliveryId: string, idempotencyKey: string): Promise<WebhookRedeliveryReceipt>;
191
+ redeliverAgentWebhookDeliveries(agentId: string, webhookId: string, input: WebhookBatchRedeliveryInput, idempotencyKey: string): Promise<WebhookBatchRedeliveryReceipt>;
192
+ }
193
+ type Request = <T>(path: string, init?: {
194
+ method?: string;
195
+ body?: string;
196
+ headers?: Record<string, string>;
197
+ }) => Promise<T>;
198
+ /** Uses the same authentication/error transport as the existing client. Never retries writes. */
199
+ export declare function createDeveloperApi(json: Request, bytes: (path: string) => Promise<Uint8Array>, selectors: (agentId: string) => Promise<Pick<Ownership, 'owner_uid' | 'org_id'>>): DeveloperApi;
200
+ export {};
@@ -0,0 +1,42 @@
1
+ const segment = encodeURIComponent;
2
+ function query(params) {
3
+ const result = new URLSearchParams();
4
+ for (const [key, value] of Object.entries(params))
5
+ if (value !== undefined)
6
+ result.set(key, String(value));
7
+ return result.size ? `?${result}` : '';
8
+ }
9
+ function post(body, idempotencyKey) {
10
+ return { method: 'POST', body: JSON.stringify(body), ...(idempotencyKey !== undefined ? { headers: { 'Idempotency-Key': idempotencyKey } } : {}) };
11
+ }
12
+ /** Uses the same authentication/error transport as the existing client. Never retries writes. */
13
+ export function createDeveloperApi(json, bytes, selectors) {
14
+ const agent = (id) => `/agents/${segment(id)}`;
15
+ const webhooks = (id) => `${agent(id)}/webhooks`;
16
+ const endpoint = (id, webhookId) => `${webhooks(id)}/${segment(webhookId)}`;
17
+ return {
18
+ getWorkspaceFile: async (id, path, opts = {}) => json(`${agent(id)}/files${query({ ...await selectors(id), path, showHidden: opts.showHidden })}`),
19
+ writeWorkspaceFile: (id, path, content) => json(`${agent(id)}/files`, post({ path, content })),
20
+ getWorkspaceFileContent: async (id, path, opts = {}) => bytes(`${agent(id)}/files/content${query({ ...await selectors(id), path, download: opts.download })}`),
21
+ getAgentDatabase: (id) => json(`${agent(id)}/database`),
22
+ getAgentDatabaseRows: (id, table, opts = {}) => json(`${agent(id)}/database/tables/${segment(table)}/rows${query({ limit: opts.limit, offset: opts.offset })}`),
23
+ getUsage: (opts = {}) => json(`/usage${query({ range: opts.range, timezone: opts.timezone, group_by: opts.groupBy, view: opts.view, session_id: opts.sessionId, api_key_id: opts.apiKeyId, root_session_id: opts.rootSessionId, attribution: opts.attribution, page: opts.page, per_page: opts.perPage, as_of: opts.asOf, snapshot: opts.snapshot, cursor: opts.cursor })}`),
24
+ getRunOutput: (id, sid, rid, opts = {}) => json(`${agent(id)}/sessions/${segment(sid)}/runs/${segment(rid)}/output${query({ cursor: opts.cursor, limit: opts.limit })}`),
25
+ getApproval: (id, aid) => json(`${agent(id)}/approvals/${segment(aid)}`),
26
+ getCustomToolCall: (id, cid) => json(`${agent(id)}/custom_tool_calls/${segment(cid)}`),
27
+ listApprovalPage: (id, opts = {}) => json(`${agent(id)}/approvals${query({ status: opts.status, session_id: opts.sessionId, cursor: opts.cursor, limit: opts.limit ?? 50 })}`),
28
+ listCustomToolCallPage: (id, opts = {}) => json(`${agent(id)}/custom_tool_calls${query({ status: opts.status, session_id: opts.sessionId, cursor: opts.cursor, limit: opts.limit ?? 50 })}`),
29
+ listAgentWebhooks: (id, opts = {}) => json(`${webhooks(id)}${query({ cursor: opts.cursor, limit: opts.limit })}`),
30
+ createAgentWebhook: (id, input, key) => json(webhooks(id), post(input, key)),
31
+ getAgentWebhook: (id, wid) => json(endpoint(id, wid)),
32
+ updateAgentWebhook: (id, wid, input) => json(`${endpoint(id, wid)}/update`, post(input)),
33
+ deleteAgentWebhook: async (id, wid) => { await json(`${endpoint(id, wid)}/delete`, post({})); },
34
+ rotateAgentWebhookSecret: (id, wid, input, key) => json(`${endpoint(id, wid)}/rotate-secret`, post(input, key)),
35
+ testAgentWebhook: (id, wid, key) => json(`${endpoint(id, wid)}/test`, post({}, key)),
36
+ getAgentWebhookEvent: (id, eid) => json(`${webhooks(id)}/events/${segment(eid)}`),
37
+ listAgentWebhookDeliveries: (id, wid, opts = {}) => json(`${endpoint(id, wid)}/deliveries${query({ cursor: opts.cursor, limit: opts.limit, status: opts.status, event_type: opts.eventType, event_id: opts.eventId, session_id: opts.sessionId, run_id: opts.runId, schedule_id: opts.scheduleId })}`),
38
+ getAgentWebhookDelivery: (id, wid, did) => json(`${endpoint(id, wid)}/deliveries/${segment(did)}`),
39
+ redeliverAgentWebhookDelivery: (id, wid, did, key) => json(`${endpoint(id, wid)}/deliveries/${segment(did)}/redeliver`, post({}, key)),
40
+ redeliverAgentWebhookDeliveries: (id, wid, input, key) => json(`${endpoint(id, wid)}/deliveries/redeliver`, post(input, key)),
41
+ };
42
+ }
package/dist/index.d.ts CHANGED
@@ -2,3 +2,4 @@ export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient
2
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';
4
4
  export { WEBHOOK_EVENT_TYPES, WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES, type WebhookEventType, isKnownWebhookEventType, knownWebhookEvent, verifyWebhookSignature, unwrapWebhook, signWebhook, ZooworkWebhookError, type WebhookErrorCode, WEBHOOK_ID_HEADER, WEBHOOK_TIMESTAMP_HEADER, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_SECRET_ENV, WEBHOOK_TOLERANCE_SECONDS, WEBHOOK_DEFAULT_MAX_BODY_BYTES, type WebhookEvent, type WebhookEventFor, type KnownWebhookEvent, type WebhookEventData, type WebhookEventDataByType, type WebhookEventAttribution, type WebhookScheduleRunRef, type WebhookWaitingOnRef, type WebhookRunEventData, type WebhookRunStartedData, type WebhookRunFinishedData, type WebhookRunYieldedData, type WebhookApprovalEventData, type WebhookApprovalRequestedData, type WebhookApprovalResolvedData, type WebhookCustomToolEventData, type WebhookCustomToolRequestedData, type WebhookCustomToolResolvedData, type WebhookOutcomeEvaluatedData, type WebhookSessionCreatedData, type WebhookSessionArchivedData, type WebhookSessionDeletedData, type WebhookScheduleFireData, type WebhookScheduleDispatchedData, type WebhookScheduleDispatchFailedData, type WebhookScheduleSkippedData, type WebhookScheduleFinishedData, type WebhookScheduleConfigData, type WebhookTestData, type WebhookHeaders, type WebhookHeaderSource, type WebhookSignatureHeaders, type VerifyWebhookInput, type VerifiedWebhook, type SignWebhookInput, } from './webhooks.js';
5
+ export type { ApiObject, CursorOptions, ActionListOptions, ApprovalPage, CustomToolCallPage, WorkspaceFileEntry, WorkspaceFile, AgentDatabase, AgentDatabaseRows, UsageOptions, UsageResult, RunOutputArtifact, RunOutputItem, RunOutput, AgentWebhookInput, AgentWebhookEndpoint, AgentWebhookPage, AgentWebhookCreated, AgentWebhookSecretRotation, WebhookDeliveryOptions, WebhookDeliveryPage, WebhookTestReceipt, WebhookRedeliveryReceipt, WebhookBatchRedeliveryReceipt, WebhookBatchRedeliveryInput, DeveloperApi, } from './developer-api.js';
@@ -0,0 +1,2 @@
1
+ /** Fixture safety only; authentication treats keys as opaque values. */
2
+ export declare function redactApiKeys(text: string, knownKey?: string): string;
@@ -0,0 +1,10 @@
1
+ /** Fixture safety only; authentication treats keys as opaque values. */
2
+ export function redactApiKeys(text, knownKey) {
3
+ let clean = text;
4
+ if (knownKey && knownKey.length >= 8)
5
+ clean = clean.split(knownKey).join('REDACTED');
6
+ return clean
7
+ .replace(/zwp_live_[A-Za-z0-9_-]{8,}/g, 'zwp_live_REDACTED')
8
+ .replace(/zct_[A-Za-z0-9_-]{8,}/g, 'zct_REDACTED')
9
+ .replace(/(Bearer )[A-Za-z0-9._~+/-]{8,}=*/g, '$1REDACTED');
10
+ }
@@ -46,10 +46,7 @@ export declare const WEBHOOK_EVENT_TYPES: readonly ["run.started", "run.finished
46
46
  /**
47
47
  * Schedule CONFIGURATION changes, as distinct from the fire events above.
48
48
  *
49
- * Declared here so a receiver can write the subscription and the handler now, but the server
50
- * side ships with Engine E5a and is NOT emitted yet — the projector currently retires such a
51
- * receipt as `unknown_source`. Do not read a delivered one of these as evidence the feature is
52
- * live; check the Engine release notes.
49
+ * Subscribe to these types for schedule configuration changes. Deliveries may be reordered.
53
50
  */
54
51
  export declare const WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES: readonly ["schedule.created", "schedule.updated", "schedule.paused", "schedule.resumed", "schedule.deleted"];
55
52
  export type WebhookEventType = (typeof WEBHOOK_EVENT_TYPES)[number] | (typeof WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES)[number];
@@ -217,7 +214,7 @@ export interface WebhookScheduleFinishedData extends WebhookScheduleFireData {
217
214
  }
218
215
  /**
219
216
  * A schedule's configuration changed. See {@link WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES}: declared,
220
- * not yet delivered.
217
+ * delivered for schedule configuration changes.
221
218
  */
222
219
  export interface WebhookScheduleConfigData extends WebhookEventAttribution {
223
220
  /**
package/dist/webhooks.js CHANGED
@@ -64,10 +64,7 @@ export const WEBHOOK_EVENT_TYPES = [
64
64
  /**
65
65
  * Schedule CONFIGURATION changes, as distinct from the fire events above.
66
66
  *
67
- * Declared here so a receiver can write the subscription and the handler now, but the server
68
- * side ships with Engine E5a and is NOT emitted yet — the projector currently retires such a
69
- * receipt as `unknown_source`. Do not read a delivered one of these as evidence the feature is
70
- * live; check the Engine release notes.
67
+ * Subscribe to these types for schedule configuration changes. Deliveries may be reordered.
71
68
  */
72
69
  export const WEBHOOK_SCHEDULE_CONFIG_EVENT_TYPES = [
73
70
  'schedule.created',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoowork-ai/sdk",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "TypeScript SDK for the ZooWork Managed Agents API (Developer Preview)",
5
5
  "keywords": [
6
6
  "zoowork",