@zoowork-ai/sdk 0.10.1 → 0.11.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,6 +3,22 @@
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.11.0 — 2026-10-04
7
+
8
+ - Add `uploadFile(agentId, path, content)`, which copies a file into an Agent's sandbox through
9
+ `exec` and verifies its SHA-256 there. Verified against staging on 2026-10-04 with files up
10
+ to 3 MiB.
11
+ - Deprecate `getWorkspaceFile`, `writeWorkspaceFile` and `getWorkspaceFileContent`. The hosted
12
+ service does not enable the workspace Files routes, so these calls fail with HTTP 501 or 502
13
+ ([ecap #4006](https://github.com/SerendipityOneInc/ecap-workspace/issues/4006)). The methods
14
+ remain callable.
15
+
16
+ ## 0.10.2 — 2026-10-04
17
+
18
+ - Accept `project` in `uploadSkill` for named Project keys.
19
+ - Clarify Skill registry read/write scopes, version publishing, and Agent bindings for Platform keys.
20
+ - Existing calls remain compatible. Project-scoped uploads require service-side support; this SDK release does not deploy the service.
21
+
6
22
  ## 0.10.1 — 2026-10-03
7
23
 
8
24
  - Correct production availability guidance for Files, Database viewer, Schedules and Agent configuration updates.
package/README.md CHANGED
@@ -165,6 +165,20 @@ await zc.wake(agent.agent_id, { text: 'Review the pending deployment.' }) // at
165
165
  const { exit_code, stdout } = await zc.exec(agent.agent_id, ['bash', '-lc', 'pwd'])
166
166
  ```
167
167
 
168
+ ## Send a file to an Agent
169
+
170
+ ```ts
171
+ import { readFile } from 'node:fs/promises'
172
+
173
+ const file = await zc.uploadFile(agent.agent_id, 'input/report.pdf', await readFile('report.pdf'))
174
+ // file.path === '/workspace/input/report.pdf'; tell the Agent to read that path.
175
+ ```
176
+
177
+ `uploadFile` copies bytes or a string into the Agent's sandbox and verifies the SHA-256 there
178
+ before the file appears at its path. A relative path resolves against `/workspace`. It sends the
179
+ content through `exec` about 72 KB per call, so it suits files up to a few megabytes, and it
180
+ needs an agent-scope sandbox.
181
+
168
182
  - **Schedules outlive their agent.** `stopAgent` and `deleteAgent` leave them running; list and
169
183
  delete them yourself. Also available: `getSchedule`, `updateSchedule`, `triggerSchedule`,
170
184
  `listScheduleRuns`.
@@ -418,9 +432,11 @@ const output = await zc.getRunOutput(agentId, sessionId, runId)
418
432
  const approvals = await zc.listApprovalPage(agentId, { sessionId })
419
433
  ```
420
434
 
421
- Direct workspace Files and the database viewer are not supported production workflows.
422
- Supply text in Session messages, ask the Agent to create and publish Artifacts, and download
423
- those through the Artifact API. The Agent can use `agent_db` and return query results in its
435
+ The workspace Files methods (`getWorkspaceFile`, `writeWorkspaceFile`,
436
+ `getWorkspaceFileContent`) are deprecated: the hosted service does not enable those routes.
437
+ Send a file to an Agent with `uploadFile`, and retrieve results by asking the Agent to publish
438
+ Artifacts and downloading those through the Artifact API. The database viewer is not a
439
+ supported production workflow. The Agent can use `agent_db` and return query results in its
424
440
  reply. Method presence is not production availability. Usage stays within the current key scope. Page helpers retain `next_cursor` and `has_more`; replay cursors
425
441
  verbatim. `getApproval` and `getCustomToolCall` read terminal as well as pending actions.
426
442
 
package/dist/client.d.ts CHANGED
@@ -676,7 +676,7 @@ export interface AgentRecord {
676
676
  */
677
677
  export interface SkillRecord {
678
678
  skill_id: string;
679
- scope?: 'org' | 'personal' | 'global' | 'pack' | string;
679
+ scope?: 'project' | 'org' | 'personal' | 'global' | 'pack' | string;
680
680
  name?: string;
681
681
  description?: string;
682
682
  latest_version?: number | string | null;
@@ -694,6 +694,7 @@ export interface SkillRecord {
694
694
  ownership?: {
695
695
  owner_uid?: string | null;
696
696
  org_id?: string | null;
697
+ project_id?: string | null;
697
698
  [k: string]: unknown;
698
699
  };
699
700
  [k: string]: unknown;
@@ -1320,6 +1321,15 @@ export interface ExecResult {
1320
1321
  stdout: string;
1321
1322
  stderr: string;
1322
1323
  }
1324
+ /** What {@link ZooworkClient.uploadFile} wrote. */
1325
+ export interface UploadFileResult {
1326
+ /** Absolute path of the file in the sandbox. */
1327
+ path: string;
1328
+ /** Bytes written. */
1329
+ size: number;
1330
+ /** Lowercase hex SHA-256 of the content, verified inside the sandbox. */
1331
+ sha256: string;
1332
+ }
1323
1333
  export interface WakeResult {
1324
1334
  mode: 'now' | 'next-heartbeat' | string;
1325
1335
  /** The reminder was written to the pending queue. */
@@ -1408,9 +1418,10 @@ export interface ZooworkClient extends DeveloperApi {
1408
1418
  verbose?: boolean;
1409
1419
  }): Promise<AgentSkill[]>;
1410
1420
  /**
1411
- * Attach a skill by id. Only skills the caller's tenant owns are installable
1412
- * through the `/service/v1` gateway (`org` / `personal` scope); `global`
1413
- * catalog entries are listable but answer 404 here.
1421
+ * Attach a visible Skill by id. Platform keys can attach global, same-org org,
1422
+ * same-Project project, and eligible owner-personal Skills. Binding a visible Skill
1423
+ * does not grant permission to publish its versions or delete its registry record.
1424
+ * Work service tokens retain their org/personal visibility rules.
1414
1425
  */
1415
1426
  putAgentSkill(agentId: string, skillId: string, opts?: {
1416
1427
  enabled?: boolean;
@@ -1574,14 +1585,18 @@ export interface ZooworkClient extends DeveloperApi {
1574
1585
  * accepted. `SKILL.md` must be non-empty and declare both `name` and `description`.
1575
1586
  * 50 MB expanded, zip only (store/deflate), encrypted zips rejected.
1576
1587
  *
1577
- * scope is org or personal. Other values are rejected by the public gateway with HTTP 400.
1578
- * Ownership comes from your key. On this CREATE operation the public gateway drops the
1588
+ * Platform keys on deployments with Project Skill registry support use project scope for a
1589
+ * named Project and org scope for the Default Project. Ownership is derived from the key;
1590
+ * Default Project org Skills are shared across the Organization. Other scopes return
1591
+ * 400 service_api.invalid_body. Work service tokens retain org/personal create scopes.
1592
+ * Older deployments may reject Platform registry requests with 404; SDK support alone
1593
+ * does not prove deployment availability. On CREATE the public gateway drops the
1579
1594
  * description option: put the description in the zip's frontmatter instead.
1580
1595
  * idempotencyKey is retained as a transport option, not a replay guarantee for Skill uploads.
1581
1596
  * A retry after a successful create can return 409 skill_exists; read back before retrying.
1582
1597
  */
1583
1598
  uploadSkill(zip: Blob | ArrayBuffer | Uint8Array, opts: {
1584
- scope: 'org' | 'personal';
1599
+ scope: 'project' | 'org' | 'personal';
1585
1600
  fileName?: string;
1586
1601
  description?: string;
1587
1602
  idempotencyKey?: string;
@@ -1592,6 +1607,10 @@ export interface ZooworkClient extends DeveloperApi {
1592
1607
  * skill's name. Unlike root create, description can override the frontmatter here.
1593
1608
  * Returns a version row (version/state), not a SkillRecord (latest_version/status).
1594
1609
  * Identical content for the same skill is deduplicated by content, not by Idempotency-Key.
1610
+ * Platform keys can publish only within their write scope: their own named Project's
1611
+ * project Skills, or their Organization's org Skills for a Default Project key. Visible
1612
+ * global/personal Skills and a named Project's visible org Skills remain read-only in the
1613
+ * registry; writes return 404 service_api.not_found. Requires Project registry deployment support.
1595
1614
  *
1596
1615
  * Agents that installed the skill unpinned follow the new version on their own — the registry
1597
1616
  * bumps their `config_version`; you do not re-`putAgentSkill`.
@@ -1602,16 +1621,24 @@ export interface ZooworkClient extends DeveloperApi {
1602
1621
  idempotencyKey?: string;
1603
1622
  }): Promise<SkillVersionRecord>;
1604
1623
  /**
1605
- * The catalog visible to your key: global skills plus your org/personal ones. `q` matches on
1606
- * name; `page` is 1-based with a fixed page size of 100. Only the `org`/`personal` rows are
1607
- * installable — `global` entries list but answer 404 from `putAgentSkill`.
1624
+ * One page of the visible catalog. With Project registry deployment support, Platform keys
1625
+ * see global Skills, their Organization's org Skills, their named Project's project Skills,
1626
+ * and eligible personal Skills owned by the key's owner. Visibility does not grant registry
1627
+ * write permission. Ownership selectors come from the key. Work service tokens retain their
1628
+ * existing catalog behavior. `q` matches name; `page` is 1-based with a page size of 100.
1608
1629
  */
1609
1630
  listSkills(opts?: {
1610
- scope?: 'org' | 'personal' | 'global' | string;
1631
+ scope?: 'project' | 'org' | 'personal' | 'global' | string;
1611
1632
  q?: string;
1612
1633
  page?: number;
1613
1634
  }): Promise<SkillRecord[]>;
1614
- /** 204. No in-use guard for org/personal skills: agents holding it just lose it. */
1635
+ /**
1636
+ * Delete the registry Skill (204), not just one Agent binding. Platform keys require Project
1637
+ * registry deployment support and may delete only their own named Project's project Skills
1638
+ * or, for a Default Project key, their Organization's org Skills. Other IDs, including visible
1639
+ * read-only Skills, return 404 service_api.not_found. Check consumers before deleting a shared
1640
+ * org Skill; use deleteAgentSkill to detach only one Agent.
1641
+ */
1615
1642
  deleteSkill(skillId: string): Promise<void>;
1616
1643
  createSession(agentId: string, input: {
1617
1644
  initial_events?: OutboundEvent[];
@@ -1837,6 +1864,23 @@ export interface ZooworkClient extends DeveloperApi {
1837
1864
  * agent's tool path.
1838
1865
  */
1839
1866
  exec(agentId: string, args: string[]): Promise<ExecResult>;
1867
+ /**
1868
+ * Copy a file into the agent's sandbox so the Agent can read it by path.
1869
+ *
1870
+ * `path` is absolute, or relative to `/workspace`; parent directories are created. A string is
1871
+ * written as UTF-8. The content travels through {@link ZooworkClient.exec} in base64 chunks,
1872
+ * lands in a temporary file beside the target, is checked against its SHA-256 inside the
1873
+ * sandbox, and only then moves into place, so a failed upload leaves nothing at `path`. The
1874
+ * file and any directory created for it take the owner of the nearest existing ancestor, so
1875
+ * the Agent's own tools can modify them.
1876
+ *
1877
+ * Each chunk is one `exec` call carrying about 72 KB, so this suits files up to a few
1878
+ * megabytes. It has exec's requirements: an agent-scope sandbox and a rendered config.
1879
+ *
1880
+ * Rejects with `ZooworkError` when a call fails, and with `Error` when a sandbox command exits
1881
+ * non-zero or the checksum does not match.
1882
+ */
1883
+ uploadFile(agentId: string, path: string, content: Blob | ArrayBuffer | Uint8Array | string): Promise<UploadFileResult>;
1840
1884
  /**
1841
1885
  * Environments visible to your org, 1-based `page`. Note that the platform DEFAULT
1842
1886
  * Environment — the one a fresh agent is pinned to — is not in here and is not fetchable: the
package/dist/client.js CHANGED
@@ -294,6 +294,54 @@ export function createZooworkClient(cfg = {}) {
294
294
  throw httpError(res, await res.text());
295
295
  return new Uint8Array(await res.arrayBuffer());
296
296
  };
297
+ const exec = (agentId, args) => json(`${agents(agentId)}/exec`, { method: 'POST', body: JSON.stringify({ args }) });
298
+ /**
299
+ * Linux caps one argv string at 128 KiB. 72,000 bytes is 96,000 base64 characters, which
300
+ * leaves room under that cap and is a multiple of 3, so every chunk decodes on its own.
301
+ */
302
+ const UPLOAD_CHUNK_BYTES = 72_000;
303
+ const uploadFile = async (agentId, path, content) => {
304
+ if (path === '')
305
+ throw new Error('uploadFile: path is required');
306
+ const data = typeof content === 'string' ? new TextEncoder().encode(content)
307
+ : content instanceof Blob ? new Uint8Array(await content.arrayBuffer())
308
+ : content instanceof ArrayBuffer ? new Uint8Array(content)
309
+ : content;
310
+ const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', data));
311
+ const sha256 = Array.from(digest, (byte) => byte.toString(16).padStart(2, '0')).join('');
312
+ // `bash -c SCRIPT NAME ARG…`: values arrive as "$1", "$2", … and are never parsed as shell.
313
+ const sh = async (script, ...args) => {
314
+ const res = await exec(agentId, ['bash', '-c', script, 'upload', ...args]);
315
+ if (res.exit_code !== 0) {
316
+ throw new Error(`uploadFile: sandbox command exited ${res.exit_code}: ${res.stderr.trim().slice(0, 500)}`);
317
+ }
318
+ return res;
319
+ };
320
+ const partial = `${path}.upload-${crypto.randomUUID()}`;
321
+ try {
322
+ // exec may run as root while the Agent's tools do not. Give the file, and any directory
323
+ // created for it, the owner of the nearest existing ancestor so the Agent can edit them.
324
+ await sh('dir=$(dirname "$1"); top=; probe=$dir; '
325
+ + 'while [ ! -e "$probe" ]; do top=$probe; probe=$(dirname "$probe"); done; '
326
+ + 'owner=$(stat -c %u:%g "$probe"); mkdir -p "$dir" && : > "$1" || exit 1; '
327
+ + 'chown "$owner" "$1" 2>/dev/null; [ -z "$top" ] || chown -R "$owner" "$top" 2>/dev/null; true', partial);
328
+ for (let offset = 0; offset < data.length; offset += UPLOAD_CHUNK_BYTES) {
329
+ let binary = '';
330
+ for (const byte of data.subarray(offset, offset + UPLOAD_CHUNK_BYTES))
331
+ binary += String.fromCharCode(byte);
332
+ await sh('printf %s "$2" | base64 -d >> "$1"', partial, btoa(binary));
333
+ }
334
+ const moved = await sh('actual=$(sha256sum "$1" | cut -d" " -f1); '
335
+ + 'if [ "$actual" != "$3" ]; then echo "checksum mismatch: got $actual" >&2; exit 3; fi; '
336
+ + 'mv -f "$1" "$2" && realpath "$2"', partial, path, sha256);
337
+ return { path: moved.stdout.trim(), size: data.length, sha256 };
338
+ }
339
+ catch (error) {
340
+ // Best effort: the original failure is what the caller needs to see.
341
+ await exec(agentId, ['rm', '-f', partial]).catch(() => undefined);
342
+ throw error;
343
+ }
344
+ };
297
345
  const client = {
298
346
  ...createDeveloperApi(json, bytes, artifactSelectors),
299
347
  listModels: async () => {
@@ -758,7 +806,8 @@ export function createZooworkClient(cfg = {}) {
758
806
  return data.runs ?? [];
759
807
  },
760
808
  wake: (agentId, input) => json(`${agents(agentId)}/wake`, { method: 'POST', body: JSON.stringify(input) }),
761
- exec: (agentId, args) => json(`${agents(agentId)}/exec`, { method: 'POST', body: JSON.stringify({ args }) }),
809
+ exec,
810
+ uploadFile,
762
811
  listEnvironments: async (opts = {}) => {
763
812
  const data = await json(`/environments${query({ page: opts.page })}`);
764
813
  return data.environments ?? [];
@@ -157,10 +157,22 @@ export interface WebhookBatchRedeliveryInput {
157
157
  limit?: number;
158
158
  }
159
159
  export interface DeveloperApi {
160
+ /**
161
+ * @deprecated The hosted service does not enable the workspace Files routes; this call
162
+ * fails with HTTP 501 or 502. Ask the Agent to publish an Artifact and download that.
163
+ */
160
164
  getWorkspaceFile(agentId: string, path: string, opts?: {
161
165
  showHidden?: boolean;
162
166
  }): Promise<WorkspaceFile>;
167
+ /**
168
+ * @deprecated The hosted service does not enable the workspace Files routes; this call
169
+ * fails with HTTP 501 or 502. Use `uploadFile` to send a file to an Agent.
170
+ */
163
171
  writeWorkspaceFile(agentId: string, path: string, content: string): Promise<ApiObject>;
172
+ /**
173
+ * @deprecated The hosted service does not enable the workspace Files routes; this call
174
+ * fails with HTTP 501 or 502. Ask the Agent to publish an Artifact and download that.
175
+ */
164
176
  getWorkspaceFileContent(agentId: string, path: string, opts?: {
165
177
  download?: boolean;
166
178
  }): Promise<Uint8Array>;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient, type ZooworkConfig, type ZooworkAuth, type Ownership, type ModelInfo, type AgentResource, type AgentRecord, type AgentListParams, type AgentPage, type AgentPagePromise, type AgentStatus, type AgentSkill, type AgentChannel, type AgentChannelCapabilitySync, type AgentChannelCapabilities, type FeishuChannelProviderStatus, type FeishuDocumentsCapability, type ChannelPlatform, type AddChannelPlatform, type GuidedSetupPlatform, type AddChannelInput, type UpdateChannelInput, type ChannelSetupInput, type ChannelSetupSession, type ChannelPollResult, type FeishuSetupInput, type FeishuSetupSession, type FeishuPollResult, type McpContextConfig, type McpServerDeclaration, type McpToolPermission, type McpToolPermissionOverride, type CustomToolDeclaration, type CustomToolResultImageMimeType, type CustomToolResultContent, type CustomToolResultEvent, type SkillRecord, type SkillVersionRecord, type SessionRecord, type SessionListPageOptions, type SessionListPage, type SessionHistoryEntry, type SessionEvent, type SessionEventPage, type OutboundEvent, type PostEventReceipt, type ApprovalDecision, type ApprovalRecord, type CustomToolCallStatus, type CustomToolCallRecord, type ArtifactPage, type ArtifactRecord, type ArtifactStatus, type OutcomeConfig, type OutcomeEvaluator, type SystemPromptDeclaration, type SystemPromptInfo, type SystemPromptPreview, type SystemPromptPreviewInput, type SystemPromptUpgrade, type ScheduleSpec, type SchedulePayload, type ScheduleInput, type ScheduleUpdate, type ScheduleRecord, type ScheduleRun, type WakeResult, type ExecResult, type EnvironmentConfig, type EnvironmentResource, type EnvironmentRecord, type EnvironmentVersionRecord, } from './client.js';
1
+ export { createZooworkClient, DEFAULT_BASE_URL, ZooworkError, type ZooworkClient, type ZooworkConfig, type ZooworkAuth, type Ownership, type ModelInfo, type AgentResource, type AgentRecord, type AgentListParams, type AgentPage, type AgentPagePromise, type AgentStatus, type AgentSkill, type AgentChannel, type AgentChannelCapabilitySync, type AgentChannelCapabilities, type FeishuChannelProviderStatus, type FeishuDocumentsCapability, type ChannelPlatform, type AddChannelPlatform, type GuidedSetupPlatform, type AddChannelInput, type UpdateChannelInput, type ChannelSetupInput, type ChannelSetupSession, type ChannelPollResult, type FeishuSetupInput, type FeishuSetupSession, type FeishuPollResult, type McpContextConfig, type McpServerDeclaration, type McpToolPermission, type McpToolPermissionOverride, type CustomToolDeclaration, type CustomToolResultImageMimeType, type CustomToolResultContent, type CustomToolResultEvent, type SkillRecord, type SkillVersionRecord, type SessionRecord, type SessionListPageOptions, type SessionListPage, type SessionHistoryEntry, type SessionEvent, type SessionEventPage, type OutboundEvent, type PostEventReceipt, type ApprovalDecision, type ApprovalRecord, type CustomToolCallStatus, type CustomToolCallRecord, type ArtifactPage, type ArtifactRecord, type ArtifactStatus, type OutcomeConfig, type OutcomeEvaluator, type SystemPromptDeclaration, type SystemPromptInfo, type SystemPromptPreview, type SystemPromptPreviewInput, type SystemPromptUpgrade, type ScheduleSpec, type SchedulePayload, type ScheduleInput, type ScheduleUpdate, type ScheduleRecord, type ScheduleRun, type WakeResult, type ExecResult, type UploadFileResult, 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, 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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zoowork-ai/sdk",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "description": "TypeScript SDK for the ZooWork Managed Agents API (Developer Preview)",
5
5
  "keywords": [
6
6
  "zoowork",