@shardflux/sdk 0.7.0 → 0.9.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/dist/http.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { RetryRecord } from './progress.js';
2
- export declare const SDK_VERSION = "0.7.0";
2
+ export declare const SDK_VERSION = "0.9.0";
3
3
  export interface RequestOptions {
4
4
  query?: Record<string, string | number | boolean | undefined | null>;
5
5
  json?: unknown;
@@ -8,6 +8,8 @@ export interface RequestOptions {
8
8
  accept?: string;
9
9
  headers?: Record<string, string>;
10
10
  idempotencyKey?: string;
11
+ /** The request has no effect a retry could duplicate (a read-only POST such as files/search): retried like a GET. */
12
+ idempotent?: boolean;
11
13
  signal?: AbortSignal;
12
14
  /** Override the client's default request timeout (ms); 0 disables it (streams). */
13
15
  timeoutMs?: number;
@@ -22,6 +24,8 @@ export interface HttpOptions {
22
24
  maxRetries: number;
23
25
  source: 'api' | 'cell';
24
26
  sleep?: (ms: number) => Promise<void>;
27
+ /** Called after each 2xx response (never throws into the request; the version check starts from it). */
28
+ onSuccess?: (() => void) | undefined;
25
29
  }
26
30
  export declare const defaultSleep: (ms: number) => Promise<void>;
27
31
  /**
@@ -35,6 +39,8 @@ export declare const defaultSleep: (ms: number) => Promise<void>;
35
39
  */
36
40
  export declare function defaultFetch(env?: Record<string, string | undefined> | undefined, undiciVersion?: string | undefined): typeof fetch;
37
41
  export declare function buildUrl(base: string, path: string, query?: RequestOptions['query']): string;
42
+ /** `X-Tree-Revision` (file-first workspaces, contracts §29.8): a non-negative integer, else null. */
43
+ export declare function treeRevisionOf(headers: Headers): number | null;
38
44
  /** Turns a non-2xx response into a ShardfluxApiError (or a protocol error for undocumented bodies). */
39
45
  export declare function errorFrom(res: Response, source: 'api' | 'cell'): Promise<Error>;
40
46
  export declare class HttpClient {
package/dist/http.js CHANGED
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * Minimal HTTP layer shared by the application API client and the cell
3
3
  * client: JSON in/out, structured errors, per-request timeout, and bounded
4
- * retries only where a retry cannot duplicate an effect (safe methods, or
5
- * requests carrying an Idempotency-Key).
4
+ * retries only where a retry cannot duplicate an effect (safe methods,
5
+ * requests carrying an Idempotency-Key, and read-only POSTs marked
6
+ * `idempotent`). A retryable 429/502/503/504 (e.g. 503 `host_capacity`, 503
7
+ * `wake_failed`) waits `Retry-After` (at most 5 s) before the retry.
6
8
  */
7
- import { ShardfluxApiError, ShardfluxProtocolError, isErrorBody } from "./errors.js";
9
+ import { ShardfluxApiError, ShardfluxProtocolError, apiError, isErrorBody } from "./errors.js";
8
10
  import { describeFailure } from "./progress.js";
9
- export const SDK_VERSION = '0.7.0';
11
+ export const SDK_VERSION = '0.9.0';
10
12
  export const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
11
13
  /**
12
14
  * The fetch the SDK uses when none is given. On runtimes whose bundled undici is 8.x (Node 26) it sends
@@ -43,6 +45,14 @@ function retryAfterSeconds(res) {
43
45
  const n = Number(v);
44
46
  return Number.isFinite(n) && n >= 0 ? n : undefined;
45
47
  }
48
+ /** `X-Tree-Revision` (file-first workspaces, contracts §29.8): a non-negative integer, else null. */
49
+ export function treeRevisionOf(headers) {
50
+ const v = headers.get('x-tree-revision');
51
+ if (v === null || !/^\d{1,19}$/.test(v))
52
+ return null;
53
+ const n = Number(v);
54
+ return Number.isSafeInteger(n) ? n : null;
55
+ }
46
56
  /** Turns a non-2xx response into a ShardfluxApiError (or a protocol error for undocumented bodies). */
47
57
  export async function errorFrom(res, source) {
48
58
  const text = await res.text();
@@ -54,7 +64,7 @@ export async function errorFrom(res, source) {
54
64
  parsed = null;
55
65
  }
56
66
  if (isErrorBody(parsed))
57
- return new ShardfluxApiError(res.status, parsed, source, retryAfterSeconds(res));
67
+ return apiError(res.status, parsed, source, retryAfterSeconds(res), treeRevisionOf(res.headers) ?? undefined);
58
68
  return new ShardfluxProtocolError(`HTTP ${res.status} from ${source === 'api' ? 'the Shardflux API' : 'the cell gateway'} without an error body`, res.status);
59
69
  }
60
70
  export class HttpClient {
@@ -66,7 +76,7 @@ export class HttpClient {
66
76
  async raw(method, path, init = {}, authorization) {
67
77
  const url = buildUrl(this.opts.baseUrl, path, init.query);
68
78
  const safe = method === 'GET' || method === 'HEAD';
69
- const retriable = safe || init.idempotencyKey !== undefined;
79
+ const retriable = safe || init.idempotencyKey !== undefined || init.idempotent === true;
70
80
  const sleep = this.opts.sleep ?? defaultSleep;
71
81
  for (let attempt = 0;; attempt += 1) {
72
82
  const headers = {
@@ -102,8 +112,17 @@ export class HttpClient {
102
112
  await sleep(delayMs);
103
113
  continue;
104
114
  }
105
- if (res.ok)
115
+ if (res.ok) {
116
+ if (this.opts.onSuccess) {
117
+ try {
118
+ this.opts.onSuccess();
119
+ }
120
+ catch {
121
+ // A hook never fails the request.
122
+ }
123
+ }
106
124
  return res;
125
+ }
107
126
  const error = await errorFrom(res, this.opts.source);
108
127
  const retryableStatus = res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504;
109
128
  const retryableError = error instanceof ShardfluxApiError ? error.retryable && retryableStatus : retryableStatus;
package/dist/index.d.ts CHANGED
@@ -6,16 +6,21 @@
6
6
  * const workspace = await cloud.workspaces.open({ key: `${customerId}/${projectId}`, template: 'python-node-browser' });
7
7
  * await agent.run({ input: userMessage, tools: workspaceTools(workspace) });
8
8
  *
9
+ * File-first workspaces (`mode: 'file_first'`, contracts §29) keep a versioned file tree and run each command as an
10
+ * execution: `await workspace.executions.run(['bash', '-lc', 'pytest -q'])`.
11
+ *
9
12
  * Types come from the committed OpenAPI documents: application API
10
13
  * and cell gateway.
11
14
  */
12
15
  export type { components, operations, paths } from './generated/app-api.js';
13
16
  export type { components as CellComponents, paths as CellPaths } from './generated/cell-api.js';
14
17
  export { BillingApi, Shardflux, WorkspacesApi, fetchBillingCatalog, pickByKey } from './client.js';
15
- export type { AgentSession, BillingCatalog, BillingSubscription, Caps, CheckoutSession, DiskLayout, Entitlements, FindByKeyOptions, ForkTarget, Invoice, InvoicePage, LifetimeFilter, ListParams, Me, OpenParams, OpenResponse, Operation, Page, PortalSession, PurposeFilter, ResetWorkspaceBody, ShardfluxOptions, UpdatePolicy, WaitOptions, WorkspaceInputs, WorkspaceLifetime, WorkspaceOrigin, WorkspacePurpose, WorkspaceView, } from './client.js';
16
- export type { FinishedOperation, LifecycleOptions, WaitedLifecycleOptions } from './lifecycle.js';
18
+ export type { AgentSession, BillingCatalog, BillingSubscription, Caps, CheckoutSession, DiskLayout, Entitlements, FindByKeyOptions, ForkTarget, Invoice, InvoicePage, LifetimeFilter, ListParams, Me, OpenParams, OpenResponse, Operation, Page, PortalSession, PurposeFilter, ResetWorkspaceBody, ResumeAnswer, ResumeRequestOptions, ResumeResponse, ShardfluxOptions, UpdatePolicy, WaitOptions, WorkspaceInputs, WorkspaceLifetime, WorkspaceOrigin, WorkspacePurpose, WorkspaceView, } from './client.js';
19
+ export type { FinishedOperation, LifecycleOptions, ResumeOptions, WaitedLifecycleOptions, WaitedResumeOptions } from './lifecycle.js';
17
20
  export { formatTiming } from './progress.js';
18
21
  export type { LifecycleAction, LifecyclePhase, LifecycleTiming, ProgressEvent, ProgressListener, RetryRecord, ServerTiming, TimingOutcome, TimingPhase, } from './progress.js';
22
+ export { FEEDBACK_CATEGORIES, FEEDBACK_MESSAGE_MAX_LENGTH } from './feedback.js';
23
+ export type { AccountFeedbackParams, FeedbackCategory, FeedbackContext, FeedbackReceipt, SendFeedbackParams } from './feedback.js';
19
24
  export { UsageApi } from './usage.js';
20
25
  export type { Grants, Spend, SpendPolicy, UsageEstimate, UsageMeter, UsageSeries, UsageSeriesParams, UsageSummary } from './usage.js';
21
26
  export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplateDraftApi, TemplatePackagesApi, TemplateUploadError, TemplateUploadsApi, TemplateVersionTestInstancesApi, TemplateVersionsApi, TemplatesApi, buildSettled, saveAsTemplateBody, } from './templates.js';
@@ -33,16 +38,22 @@ export type { AttachVolumeParams, AttachmentResult, CreateVolumeParams, DeleteVo
33
38
  export { AuditApi, auditQuery, parseAuditNdjson } from './audit.js';
34
39
  export type { AuditActorType, AuditEvent, AuditFilters, AuditListParams, AuditOutcome, AuditSource } from './audit.js';
35
40
  export { Workspace } from './workspace.js';
36
- export type { WakeOptions } from './workspace.js';
41
+ export type { HintOptions, HintResult, WakeOptions } from './workspace.js';
37
42
  export { CellClient, DEFAULT_TRANSITION_TIMEOUT_MS, cellPath, ndjson } from './cell.js';
38
- export type { BrowserContent, BrowserContentRequest, BrowserScreenshotRequest, CellClientOptions, ExecSession, ExecStartRequest, FileInfo, FileList, FileWriteResult, GitResult, GitStatus, OutputEvent, ProcessList, PtyOpenRequest, PtySession, RunOptions, RunResult, Signal, WorkspaceChange, WorkspaceChangeKind, WorkspaceChangesPage, WorkspaceChangesParams, WorkspaceChangesSummary, } from './cell.js';
43
+ export { EXECUTION_ID, ExecutionResult, newExecutionId } from './executions.js';
44
+ export type { ExecutionChange, ExecutionError, ExecutionGetOptions, ExecutionResultBody, ExecutionRunOptions, ExecutionState } from './executions.js';
45
+ export type { TreeRevisionOptions, BrowserContent, BrowserContentRequest, BrowserScreenshotRequest, CellClientOptions, ExecSession, ExecStartRequest, FileEdit, FileInfo, FileList, FilePatchEdit, FilePatchParams, FilePatchRequest, FilePatchResult, FileReadResult, FileRevision, FileSearchMatch, FileSearchOptions, FileSearchRequest, FileSearchResponse, FileSearchResult, FileWriteResult, GitResult, GitStatus, OutputEvent, ProcessList, PtyOpenRequest, PtySession, Residency, RunOptions, RunResult, ServedFrom, Signal, WakeHintResult, WorkspaceChange, WorkspaceChangeKind, WorkspaceChangesPage, WorkspaceChangesParams, WorkspaceChangesSummary, } from './cell.js';
39
46
  export { ToolTokenManager } from './tokens.js';
40
47
  export type { ToolName, ToolToken, ToolTokenOptions } from './tokens.js';
41
48
  export { ToolArgumentError, executeToolCall, toAnthropicTools, toOpenAITools, validateArgs, workspaceTools } from './tools.js';
42
- export type { JsonSchema, WorkspaceTool, WorkspaceToolsOptions } from './tools.js';
49
+ export type { AnthropicToolDefinition, JsonSchema, OpenAIChatToolDefinition, OpenAIResponsesToolDefinition, WorkspaceTool, WorkspaceToolsOptions } from './tools.js';
43
50
  export { CaptureError, ToolCallCapture, captureTool } from './capture.js';
44
51
  export type { CallLike, CallRef, CaptureCall, CaptureErrorKind, CaptureEvent, CaptureFlushResult, CapturePart, CaptureSelector, CaptureSource, CaptureStats, CaptureStatus, DropReason, ToolCallCaptureOptions, WrapOptions, } from './capture.js';
45
52
  export type { AiSdkAdapter, AiSdkToolEndEvent, AnthropicAdapter, ClaudeAdapter, ClaudeCaptureHooks, ClaudeHookCallback, ClaudeHookMatcher, LangChainAdapter, LangChainToolHandler, MastraAdapter, MastraAfterToolCallContext, McpAdapter, OpenAIAgentsAdapter, } from './capture-adapters.js';
46
- export { OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError } from './errors.js';
47
- export type { AppErrorCode, CellErrorCode, ErrorCode, ErrorReason, KnownErrorReason } from './errors.js';
53
+ export { NotSupportedForModeError, OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError, TreeRevisionMismatchError } from './errors.js';
54
+ export type { AppErrorCode, CellErrorCode, ErrorCode, ErrorReason, KnownErrorReason, WorkspaceMode } from './errors.js';
48
55
  export { SDK_VERSION } from './http.js';
56
+ export { API_KEY_TOOL_PERMISSIONS, AccountApiKeysApi, AccountAuditApi, AccountAuthApi, AccountBillingApi, AccountExportsApi, AccountInvitationsApi, AccountMembersApi, AccountOrganizationsApi, AccountProjectsApi, AccountTemplatesApi, AccountTotpApi, AccountUserApi, CheckoutTimeoutError, OrganizationExportsApi, SESSION_TOKEN_PATTERN, ShardfluxAccount, isSessionToken, parseEmailToken, } from './account.js';
57
+ export type { AccountClientOptions, AccountDeletion, AccountDeletionCanceled, AccountDeletionScheduled, ApiKey, ApiKeyPage, ApiKeyToolPermission, AuditExportParams, AuthSessionInfo, AuthSessionPage, AuthSessionState, AuthUser, BillingInvoicePage, BillingPortalSession, CheckoutStatus, CreateApiKeyParams, CreatedApiKey, DataExport, EmailChangeConfirmResult, EmailChangeResult, Invitation, InvitationPage, LoginResult, Member, MemberPage, MemberRole, MfaChallengeResult, Organization, OrganizationDeletion, OrganizationDeletionResult, OrganizationPage, OrganizationRole, OrganizationWorkspacePage, OrganizationWorkspacesParams, PageParams, PasswordChangeResult, PasswordResetConfirmResult, PasswordResetRequestResult, Project, ProjectPage, RecoveryCodes, RegisterResult, ResendVerificationResult, SessionTokenUpdate, ShardfluxAccountOptions, StepUpResult, TotpConfirmResult, TotpDisableResult, TotpEnrollment, VerifyEmailResult, WaitForCheckoutOptions, } from './account.js';
58
+ export { checkClientVersion, clientVersionStatus, compareVersions, versionCheckDisabledByEnv } from './version-check.js';
59
+ export type { CheckClientVersionOptions, ClientEcosystem, ClientVersionEntry, ClientVersionStatus, ClientVersionStatusKind, ClientVersions, VersionCheckIdentity, VersionCheckOption, } from './version-check.js';
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { BillingApi, Shardflux, WorkspacesApi, fetchBillingCatalog, pickByKey } from "./client.js";
2
2
  export { formatTiming } from "./progress.js";
3
+ export { FEEDBACK_CATEGORIES, FEEDBACK_MESSAGE_MAX_LENGTH } from "./feedback.js";
3
4
  export { UsageApi } from "./usage.js";
4
5
  export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplateDraftApi, TemplatePackagesApi, TemplateUploadError, TemplateUploadsApi, TemplateVersionTestInstancesApi, TemplateVersionsApi, TemplatesApi, buildSettled, saveAsTemplateBody, } from "./templates.js";
5
6
  export { TemplateFileError, packDirectory, parseTemplateText, readTemplateFile } from "./template-file.js";
@@ -10,8 +11,11 @@ export { VolumesApi } from "./volumes.js";
10
11
  export { AuditApi, auditQuery, parseAuditNdjson } from "./audit.js";
11
12
  export { Workspace } from "./workspace.js";
12
13
  export { CellClient, DEFAULT_TRANSITION_TIMEOUT_MS, cellPath, ndjson } from "./cell.js";
14
+ export { EXECUTION_ID, ExecutionResult, newExecutionId } from "./executions.js";
13
15
  export { ToolTokenManager } from "./tokens.js";
14
16
  export { ToolArgumentError, executeToolCall, toAnthropicTools, toOpenAITools, validateArgs, workspaceTools } from "./tools.js";
15
17
  export { CaptureError, ToolCallCapture, captureTool } from "./capture.js";
16
- export { OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError } from "./errors.js";
18
+ export { NotSupportedForModeError, OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError, TreeRevisionMismatchError } from "./errors.js";
17
19
  export { SDK_VERSION } from "./http.js";
20
+ export { API_KEY_TOOL_PERMISSIONS, AccountApiKeysApi, AccountAuditApi, AccountAuthApi, AccountBillingApi, AccountExportsApi, AccountInvitationsApi, AccountMembersApi, AccountOrganizationsApi, AccountProjectsApi, AccountTemplatesApi, AccountTotpApi, AccountUserApi, CheckoutTimeoutError, OrganizationExportsApi, SESSION_TOKEN_PATTERN, ShardfluxAccount, isSessionToken, parseEmailToken, } from "./account.js";
21
+ export { checkClientVersion, clientVersionStatus, compareVersions, versionCheckDisabledByEnv } from "./version-check.js";
@@ -6,10 +6,11 @@
6
6
  * and resolves when the change has FINISHED, returning the succeeded operation (typed FinishedOperation) and, on a
7
7
  * workspace handle, the refreshed view. Both paths are traced (see progress.ts).
8
8
  */
9
- import type { ClientContext, Operation, WaitOptions } from './client.js';
9
+ import type { ClientContext, Operation, WaitOptions, WorkspaceView } from './client.js';
10
10
  import type { RequestOptions } from './http.js';
11
11
  import { Trace } from './progress.js';
12
12
  import type { LifecycleAction, ProgressListener } from './progress.js';
13
+ import type { ToolName, ToolToken } from './tokens.js';
13
14
  /** An operation that has finished successfully: what a lifecycle call with `wait` resolves to. */
14
15
  export type FinishedOperation = Operation & {
15
16
  state: 'succeeded';
@@ -31,15 +32,39 @@ export interface LifecycleOptions {
31
32
  export type WaitedLifecycleOptions = LifecycleOptions & {
32
33
  wait: true | WaitOptions;
33
34
  };
35
+ /**
36
+ * `resume()` options (0.9.0). With `wait`, the server holds the resume until the workspace runs and returns a tool token
37
+ * with it (contracts §22.6): `agentLabel` and `tools` choose that token (defaults: a workspace handle's own, those given
38
+ * to open(); `workspaces.resume(id)` otherwise the key's tools and label `default`). A handle keeps it for its `cell()`
39
+ * clients of the same label and tools; `workspaces.resume(id)` only attributes it.
40
+ */
41
+ export interface ResumeOptions extends LifecycleOptions {
42
+ agentLabel?: string;
43
+ tools?: ToolName[];
44
+ }
45
+ export type WaitedResumeOptions = ResumeOptions & {
46
+ wait: true | WaitOptions;
47
+ };
34
48
  /** Internal: the trace a wait continues instead of starting its own (open(), wake() and waited lifecycle calls). */
35
49
  export declare const TRACE: unique symbol;
36
50
  /** Internal: work a workspace handle does after the operation finished, inside the same trace (refreshing its view). */
37
51
  export declare const AFTER_WAIT: unique symbol;
52
+ /**
53
+ * Internal: a workspace handle's part in a held resume (contracts §22.6): the tool token to ask for, and how it takes the
54
+ * running workspace and that token from a 200 (instead of reading the view and fetching a token afterwards).
55
+ */
56
+ export declare const HELD_RESUME: unique symbol;
57
+ export interface HeldResumeTarget {
58
+ agentLabel: string | undefined;
59
+ tools: readonly ToolName[] | undefined;
60
+ adopt(view: WorkspaceView, token: ToolToken | null): void;
61
+ }
38
62
  export type InternalWaitOptions = WaitOptions & {
39
63
  [TRACE]?: Trace;
40
64
  };
41
- export type InternalLifecycleOptions = LifecycleOptions & {
65
+ export type InternalLifecycleOptions = ResumeOptions & {
42
66
  [AFTER_WAIT]?: (trace: Trace, operation: Operation) => Promise<void>;
67
+ [HELD_RESUME]?: HeldResumeTarget;
43
68
  };
44
69
  export declare function waitOptionsOf(opts: LifecycleOptions): WaitOptions | null;
45
70
  /**
package/dist/lifecycle.js CHANGED
@@ -4,6 +4,11 @@ import { Trace, combineListeners, traced } from "./progress.js";
4
4
  export const TRACE = Symbol('shardflux.trace');
5
5
  /** Internal: work a workspace handle does after the operation finished, inside the same trace (refreshing its view). */
6
6
  export const AFTER_WAIT = Symbol('shardflux.afterWait');
7
+ /**
8
+ * Internal: a workspace handle's part in a held resume (contracts §22.6): the tool token to ask for, and how it takes the
9
+ * running workspace and that token from a 200 (instead of reading the view and fetching a token afterwards).
10
+ */
11
+ export const HELD_RESUME = Symbol('shardflux.heldResume');
7
12
  export function waitOptionsOf(opts) {
8
13
  if (opts.wait === undefined || opts.wait === false)
9
14
  return null;
package/dist/progress.js CHANGED
@@ -81,8 +81,10 @@ export function describeFailure(err, timeoutMs) {
81
81
  if (err.name === 'TimeoutError')
82
82
  return timeoutMs !== undefined ? `timeout after ${timeoutMs} ms` : 'timeout';
83
83
  const e = err;
84
- if (e.name === 'ShardfluxApiError' || e.name === 'ShardfluxProtocolError')
85
- return `HTTP ${e.status}${e.code ? ` ${e.code}` : ''}`;
84
+ // ShardfluxApiError and its subclasses (typed by reason) carry requestId; a protocol error only a status.
85
+ if (e.name === 'ShardfluxProtocolError' || (typeof e.status === 'number' && typeof e.requestId === 'string')) {
86
+ return `HTTP ${e.status}${e.code ? ` ${e.code}` : ''}${typeof e.reason === 'string' ? ` ${e.reason}` : ''}`;
87
+ }
86
88
  return `network: ${e.cause?.code ?? e.cause?.message ?? e.message}`;
87
89
  }
88
90
  return 'network error';
package/dist/templates.js CHANGED
@@ -241,7 +241,7 @@ export class TemplateBuildsApi {
241
241
  * Throws TemplateBuildTimeoutError at the deadline (default 30 min); the build continues.
242
242
  */
243
243
  async waitForBuild(organizationId, buildId, opts = {}) {
244
- const { sleep, http, authorization } = this.#ctx();
244
+ const { sleep, http } = this.#ctx();
245
245
  const timeoutMs = opts.timeoutMs ?? 1_800_000;
246
246
  const maxInterval = opts.maxPollIntervalMs ?? 10_000;
247
247
  let interval = opts.pollIntervalMs ?? 1_000;
@@ -252,7 +252,7 @@ export class TemplateBuildsApi {
252
252
  throw opts.signal.reason instanceof Error ? opts.signal.reason : new Error('aborted');
253
253
  const waitS = opts.serverWait === false ? 0 : (timeoutMs - (Date.now() - started)) / 1000;
254
254
  const t0 = Date.now();
255
- const { body: build, applied } = await pollWithWait(http, `/v1/organizations/${enc(organizationId)}/template-builds/${enc(buildId)}`, authorization, waitS, opts.signal);
255
+ const { body: build, applied } = await pollWithWait(http, `/v1/organizations/${enc(organizationId)}/template-builds/${enc(buildId)}`, this.#ctx().authorization, waitS, opts.signal);
256
256
  const key = `${build.state}/${build.registration.state}`;
257
257
  const changed = key !== lastKey;
258
258
  lastKey = key;
package/dist/tools.d.ts CHANGED
@@ -1,7 +1,13 @@
1
1
  import type { CellClientOptions } from './cell.js';
2
+ import type { WorkspaceMode } from './errors.js';
2
3
  import type { ToolName } from './tokens.js';
3
4
  import type { Workspace } from './workspace.js';
4
- export interface JsonSchema {
5
+ /**
6
+ * The JSON Schema subset of the tool definitions. A type alias rather than an interface (0.8.0+), so a schema is
7
+ * assignable to the providers' open schema types (`{ [key: string]: unknown }`) without a cast, and an object literal
8
+ * typed as JsonSchema still rejects a misspelt keyword.
9
+ */
10
+ export type JsonSchema = {
5
11
  type?: 'object' | 'string' | 'integer' | 'number' | 'boolean' | 'array';
6
12
  description?: string;
7
13
  properties?: Record<string, JsonSchema>;
@@ -13,10 +19,12 @@ export interface JsonSchema {
13
19
  maximum?: number;
14
20
  minLength?: number;
15
21
  maxLength?: number;
22
+ /** ECMAScript regular expression a string must match (0.7.0+). */
23
+ pattern?: string;
16
24
  minItems?: number;
17
25
  maxItems?: number;
18
26
  default?: unknown;
19
- }
27
+ };
20
28
  export interface WorkspaceTool<A extends Record<string, unknown> = Record<string, unknown>, R = unknown> {
21
29
  name: string;
22
30
  description: string;
@@ -39,7 +47,12 @@ export declare class ToolArgumentError extends Error {
39
47
  /** Validates the JSON-Schema subset used by the tool definitions. Returns problems (empty = valid). */
40
48
  export declare function validateArgs(schema: JsonSchema, value: unknown, path?: string): string[];
41
49
  export interface WorkspaceToolsOptions {
42
- /** Tool permissions to expose (default: the tools of the workspace's last token, else all). */
50
+ /**
51
+ * Tool permissions to expose (default: the tools of the workspace's last token, else all). A file-first workspace
52
+ * (`workspace.mode`, contracts §29) gets only the `exec` and `files` tools: `exec` runs each command as an execution
53
+ * (a fresh VM on the workspace's files; the result adds `execution_id`, `state`, `changed` and `tree_revision`), and
54
+ * the process, terminal, git and browser tools are not offered because nothing runs between executions.
55
+ */
43
56
  tools?: ToolName[];
44
57
  /** Attribution label for the tokens these tools use (one agent session per label). */
45
58
  agentLabel?: string;
@@ -53,47 +66,84 @@ export interface WorkspaceToolsOptions {
53
66
  wake?: CellClientOptions['wake'];
54
67
  /** Bound on lifecycle waits (busy waits plus wakes) per tool call (CellClientOptions.transitionTimeoutMs). */
55
68
  transitionTimeoutMs?: number;
69
+ /**
70
+ * Send `workspace.hint()` when a tool call starts, without waiting for it (default true; 0.9.0+), so a parked
71
+ * workspace is being restored while the call is prepared. Pass false when you call `workspace.hint()` yourself
72
+ * earlier (e.g. when the model starts streaming a tool call). `read_file`, `list_files` and `search_files` never send
73
+ * it: a sleeping workspace serves them from its disk without waking (contracts §26.4), and the hint would wake a
74
+ * suspended workspace (or restore a hibernated one) that the read does not need.
75
+ */
76
+ hint?: boolean;
77
+ /**
78
+ * The mode to build the tools for (0.9.0+; default `workspace.mode`). Given, the workspace is not touched until a tool
79
+ * runs, so definitions can be built without one (e.g. to publish them before any workspace exists).
80
+ */
81
+ mode?: WorkspaceMode;
82
+ /**
83
+ * File-first workspaces: called with the execution id before the `exec` tool sends its execution (0.9.0+). An
84
+ * execution cannot be canceled, so a caller that stops waiting (an aborted signal) can still fetch its result later
85
+ * with `workspace.executions.get(id)`.
86
+ */
87
+ onExecution?: (executionId: string) => void;
56
88
  }
57
89
  /** Builds the tool list for a workspace. Synchronous: tokens are fetched on first use. */
58
90
  export declare function workspaceTools(workspace: Workspace, opts?: WorkspaceToolsOptions): WorkspaceTool[];
59
- /** OpenAI tool definitions: Chat Completions (`{type:'function', function:{...}}`) or Responses API. */
60
- export declare function toOpenAITools(tools: readonly WorkspaceTool[], opts?: {
61
- api?: 'chat' | 'responses';
62
- }): {
63
- type: "function";
91
+ /** Anthropic Messages API tool definition; assignable to `Anthropic.Tool` (0.8.0+). */
92
+ export type AnthropicToolDefinition = {
64
93
  name: string;
65
94
  description: string;
66
- parameters: JsonSchema & {
67
- type: "object";
95
+ input_schema: JsonSchema & {
96
+ type: 'object';
68
97
  };
69
- strict: boolean;
70
- }[] | {
71
- type: "function";
98
+ };
99
+ /** OpenAI Chat Completions tool definition; assignable to `OpenAI.Chat.ChatCompletionFunctionTool` (0.8.0+). */
100
+ export type OpenAIChatToolDefinition = {
101
+ type: 'function';
72
102
  function: {
73
103
  name: string;
74
104
  description: string;
75
105
  parameters: JsonSchema & {
76
- type: "object";
106
+ type: 'object';
77
107
  };
78
108
  };
79
- }[];
80
- /** Anthropic Messages API tool definitions (`{ name, description, input_schema }`). */
81
- export declare function toAnthropicTools(tools: readonly WorkspaceTool[]): {
109
+ };
110
+ /** OpenAI Responses API tool definition; assignable to `OpenAI.Responses.FunctionTool` (0.8.0+). */
111
+ export type OpenAIResponsesToolDefinition = {
112
+ type: 'function';
82
113
  name: string;
83
114
  description: string;
84
- input_schema: JsonSchema & {
85
- type: "object";
115
+ parameters: JsonSchema & {
116
+ type: 'object';
86
117
  };
87
- }[];
118
+ strict: boolean;
119
+ };
120
+ /**
121
+ * OpenAI tool definitions: Chat Completions (`{type:'function', function:{...}}`, the default) or, with
122
+ * `{ api: 'responses' }`, the Responses API. The return type follows `api` (0.8.0+); an `api` known only at run time
123
+ * gives either array.
124
+ */
125
+ export declare function toOpenAITools(tools: readonly WorkspaceTool[], opts: {
126
+ api: 'responses';
127
+ }): OpenAIResponsesToolDefinition[];
128
+ export declare function toOpenAITools(tools: readonly WorkspaceTool[], opts?: {
129
+ api?: 'chat';
130
+ }): OpenAIChatToolDefinition[];
131
+ export declare function toOpenAITools(tools: readonly WorkspaceTool[], opts?: {
132
+ api?: 'chat' | 'responses';
133
+ }): OpenAIChatToolDefinition[] | OpenAIResponsesToolDefinition[];
134
+ /** Anthropic Messages API tool definitions (`{ name, description, input_schema }`). */
135
+ export declare function toAnthropicTools(tools: readonly WorkspaceTool[]): AnthropicToolDefinition[];
88
136
  /**
89
137
  * Runs a model's tool call: `arguments` may be the JSON string (OpenAI) or an object (Anthropic
90
138
  * `input`). Throws for unknown tools and invalid arguments (ToolArgumentError). The call's `id` / `call_id` is passed
91
- * to `execute` as `toolCallId` (0.7.0+), so `executeToolCall(capture.tools(tools), call)` records it.
139
+ * to `execute` as `toolCallId` (0.7.0+), so `executeToolCall(capture.tools(tools), call)` records it. `input` is
140
+ * `unknown` (0.8.0+), as in the Anthropic SDK's `ToolUseBlock`, so a tool_use block is passed as it is; `execute`
141
+ * validates it.
92
142
  */
93
143
  export declare function executeToolCall(tools: readonly WorkspaceTool[], call: {
94
144
  name: string;
95
145
  arguments?: string | Record<string, unknown>;
96
- input?: Record<string, unknown>;
146
+ input?: unknown;
97
147
  id?: string;
98
148
  call_id?: string;
99
149
  }, options?: {