@shardflux/sdk 0.5.0 → 0.6.1
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 +73 -0
- package/README.md +228 -24
- package/dist/cell.d.ts +67 -2
- package/dist/cell.js +98 -8
- package/dist/client.d.ts +148 -22
- package/dist/client.js +237 -29
- package/dist/errors.d.ts +20 -0
- package/dist/errors.js +10 -0
- package/dist/generated/app-api.d.ts +10223 -5857
- package/dist/generated/cell-api.d.ts +140 -8
- package/dist/http.d.ts +30 -1
- package/dist/http.js +57 -3
- package/dist/index.d.ts +13 -9
- package/dist/index.js +5 -4
- package/dist/lifecycle.d.ts +48 -0
- package/dist/lifecycle.js +33 -0
- package/dist/progress.d.ts +166 -0
- package/dist/progress.js +240 -0
- package/dist/secrets.d.ts +83 -6
- package/dist/secrets.js +53 -1
- package/dist/templates.d.ts +279 -7
- package/dist/templates.js +216 -4
- package/dist/tokens.d.ts +8 -3
- package/dist/tokens.js +25 -13
- package/dist/tools.d.ts +17 -0
- package/dist/tools.js +5 -1
- package/dist/workspace.d.ts +112 -20
- package/dist/workspace.js +176 -10
- package/package.json +2 -1
|
@@ -585,10 +585,14 @@ export interface paths {
|
|
|
585
585
|
/**
|
|
586
586
|
* Idle policy, activity and the projected automatic suspend
|
|
587
587
|
* @description `idle_since` = max(`last_tool_at`, `last_attach_at`, `keepalive_until`,
|
|
588
|
-
* `running_since
|
|
589
|
-
*
|
|
588
|
+
* `running_since`, the work horizon of running exec commands) (null when
|
|
589
|
+
* none is known; in the future while a keepalive or a running command is
|
|
590
|
+
* active). A running exec command counts as work until min(its start +
|
|
591
|
+
* `IDLE_COMMAND_MAX_SECONDS`, its start + `timeout_ms`), and its end is
|
|
592
|
+
* activity (contracts §20.6). `suspend_at` = `idle_since` + `idle_minutes` when
|
|
590
593
|
* the policy is `suspend_after` and automatic suspend is enabled, else
|
|
591
|
-
* null
|
|
594
|
+
* null; the idle loop acts within `2 x ACTIVITY_FLUSH_MS` after it.
|
|
595
|
+
* Activity lags tool traffic by up to `ACTIVITY_FLUSH_MS`. Any
|
|
592
596
|
* tool granted by the token authorizes the call; the tool gate does not
|
|
593
597
|
* apply and the call is not tool activity.
|
|
594
598
|
*/
|
|
@@ -601,6 +605,49 @@ export interface paths {
|
|
|
601
605
|
patch?: never;
|
|
602
606
|
trace?: never;
|
|
603
607
|
};
|
|
608
|
+
"/v1/workspaces/{workspace_id}/changes": {
|
|
609
|
+
parameters: {
|
|
610
|
+
query?: never;
|
|
611
|
+
header?: never;
|
|
612
|
+
path: {
|
|
613
|
+
workspace_id: components["parameters"]["WorkspaceId"];
|
|
614
|
+
};
|
|
615
|
+
cookie?: never;
|
|
616
|
+
};
|
|
617
|
+
/**
|
|
618
|
+
* The workspace's changes against its template (layered workspaces)
|
|
619
|
+
* @description Templates v2 (contracts §19.10). Lists what the workspace changed
|
|
620
|
+
* relative to its template chain: the guest walks its workspace layer's
|
|
621
|
+
* overlay upper directory in raw path-byte order and classifies each
|
|
622
|
+
* entry against the template: `added` (absent in the template),
|
|
623
|
+
* `modified` (a regular file or symlink that exists in both),
|
|
624
|
+
* `metadata` (only with `hash=true`, when the content equals the
|
|
625
|
+
* template's), `deleted` (a whiteout over an existing template path) and
|
|
626
|
+
* `replaced` (an opaque directory hiding the template's contents).
|
|
627
|
+
* Directories that exist in both appear only when their mode or owner
|
|
628
|
+
* differ, or when they are opaque; ancestors copied up because a child
|
|
629
|
+
* changed are not reported.
|
|
630
|
+
*
|
|
631
|
+
* Requires a tool token with the `files` tool. It is a read-only action
|
|
632
|
+
* (served while a snapshot holds the tool gate `read_only`) and counts as
|
|
633
|
+
* tool activity. `hash=true` hashes regular files of 16 MiB or less;
|
|
634
|
+
* larger ones get `sha256: null, hash_skipped: true`.
|
|
635
|
+
*
|
|
636
|
+
* Errors: `409 workspace_not_running` (not running; a suspended
|
|
637
|
+
* workspace's changes are not served), `409 conflict` with
|
|
638
|
+
* `details.reason = legacy_disk_layout` (a legacy workspace has no
|
|
639
|
+
* workspace layer) or `guest_feature_unavailable` (the template's guest
|
|
640
|
+
* agent lacks `layer_changes.v1`).
|
|
641
|
+
*/
|
|
642
|
+
get: operations["workspaceChanges"];
|
|
643
|
+
put?: never;
|
|
644
|
+
post?: never;
|
|
645
|
+
delete?: never;
|
|
646
|
+
options?: never;
|
|
647
|
+
head?: never;
|
|
648
|
+
patch?: never;
|
|
649
|
+
trace?: never;
|
|
650
|
+
};
|
|
604
651
|
}
|
|
605
652
|
export type webhooks = Record<string, never>;
|
|
606
653
|
export interface components {
|
|
@@ -818,6 +865,49 @@ export interface components {
|
|
|
818
865
|
entries: components["schemas"]["FileInfo"][];
|
|
819
866
|
truncated: boolean;
|
|
820
867
|
};
|
|
868
|
+
WorkspaceChange: {
|
|
869
|
+
path: string;
|
|
870
|
+
/** @enum {string} */
|
|
871
|
+
change: "added" | "modified" | "metadata" | "deleted" | "replaced";
|
|
872
|
+
/**
|
|
873
|
+
* @description The upper entry's type; for `deleted`, the template entry's type.
|
|
874
|
+
* @enum {string}
|
|
875
|
+
*/
|
|
876
|
+
type: "file" | "dir" | "symlink" | "char" | "block" | "fifo";
|
|
877
|
+
/** Format: int64 */
|
|
878
|
+
size_bytes: number;
|
|
879
|
+
/** @description Octal permission bits, e.g. "0644". */
|
|
880
|
+
mode: string;
|
|
881
|
+
uid: number;
|
|
882
|
+
gid: number;
|
|
883
|
+
/** Format: date-time */
|
|
884
|
+
modified_at: string | null;
|
|
885
|
+
/** @description Only with hash=true, for regular files of 16 MiB or less. */
|
|
886
|
+
sha256: string | null;
|
|
887
|
+
hash_skipped: boolean;
|
|
888
|
+
link_target: string | null;
|
|
889
|
+
};
|
|
890
|
+
WorkspaceChangesSummary: {
|
|
891
|
+
/** Format: int64 */
|
|
892
|
+
added: number;
|
|
893
|
+
/** Format: int64 */
|
|
894
|
+
modified: number;
|
|
895
|
+
/** Format: int64 */
|
|
896
|
+
deleted: number;
|
|
897
|
+
/** Format: int64 */
|
|
898
|
+
replaced: number;
|
|
899
|
+
/**
|
|
900
|
+
* Format: int64
|
|
901
|
+
* @description Sum of the sizes of added and modified regular files.
|
|
902
|
+
*/
|
|
903
|
+
bytes: number;
|
|
904
|
+
};
|
|
905
|
+
WorkspaceChangesPage: {
|
|
906
|
+
data: components["schemas"]["WorkspaceChange"][];
|
|
907
|
+
/** @description Opaque; null when there are no more changes under path_prefix. */
|
|
908
|
+
next_cursor: string | null;
|
|
909
|
+
summary?: components["schemas"]["WorkspaceChangesSummary"];
|
|
910
|
+
};
|
|
821
911
|
FileWriteResult: {
|
|
822
912
|
path: string;
|
|
823
913
|
/** Format: int64 */
|
|
@@ -927,15 +1017,25 @@ export interface components {
|
|
|
927
1017
|
keepalive_until: string;
|
|
928
1018
|
};
|
|
929
1019
|
IdlePolicy: {
|
|
930
|
-
/**
|
|
931
|
-
|
|
932
|
-
|
|
1020
|
+
/**
|
|
1021
|
+
* @description adaptive = the learned timeout (contracts §20.7, the default); suspend_after = a fixed timeout;
|
|
1022
|
+
* never (or the legacy hot) = no automatic suspend.
|
|
1023
|
+
* @enum {string}
|
|
1024
|
+
*/
|
|
1025
|
+
mode: "hot" | "suspend_after" | "adaptive" | "never";
|
|
1026
|
+
/** @description Set when mode is suspend_after (rounded up from idle_seconds). */
|
|
933
1027
|
idle_minutes: number | null;
|
|
1028
|
+
/** @description The fixed timeout in seconds when mode is suspend_after. */
|
|
1029
|
+
idle_seconds?: number | null;
|
|
1030
|
+
/** @description The timeout applied to the current idle period (adaptive or fixed); null while none applies. */
|
|
1031
|
+
timeout_seconds?: number | null;
|
|
1032
|
+
/** @description What the timeout comes from, e.g. "learned from 37 idle periods (active-hours)", "template prior", "default". */
|
|
1033
|
+
basis?: string | null;
|
|
934
1034
|
/**
|
|
935
|
-
* @description workspace = the workspace's own policy; default = the cell default (IDLE_DEFAULT_MODE
|
|
1035
|
+
* @description workspace = the workspace's own policy; template = the template's default; default = the cell default (IDLE_DEFAULT_MODE).
|
|
936
1036
|
* @enum {string}
|
|
937
1037
|
*/
|
|
938
|
-
source: "workspace" | "default";
|
|
1038
|
+
source: "workspace" | "template" | "default";
|
|
939
1039
|
};
|
|
940
1040
|
IdleAutoSuspend: {
|
|
941
1041
|
/** @description Policy is suspend_after and automatic suspend was not disabled (e.g. after repeated failures). */
|
|
@@ -1829,4 +1929,36 @@ export interface operations {
|
|
|
1829
1929
|
default: components["responses"]["Error"];
|
|
1830
1930
|
};
|
|
1831
1931
|
};
|
|
1932
|
+
workspaceChanges: {
|
|
1933
|
+
parameters: {
|
|
1934
|
+
query?: {
|
|
1935
|
+
/** @description Absolute path; only entries at or below it. */
|
|
1936
|
+
path_prefix?: string;
|
|
1937
|
+
limit?: number;
|
|
1938
|
+
/** @description `next_cursor` of the previous page. */
|
|
1939
|
+
cursor?: string;
|
|
1940
|
+
hash?: boolean;
|
|
1941
|
+
/** @description Also return totals over everything under path_prefix. */
|
|
1942
|
+
summary?: boolean;
|
|
1943
|
+
};
|
|
1944
|
+
header?: never;
|
|
1945
|
+
path: {
|
|
1946
|
+
workspace_id: components["parameters"]["WorkspaceId"];
|
|
1947
|
+
};
|
|
1948
|
+
cookie?: never;
|
|
1949
|
+
};
|
|
1950
|
+
requestBody?: never;
|
|
1951
|
+
responses: {
|
|
1952
|
+
/** @description One page of changes, in raw path-byte order. */
|
|
1953
|
+
200: {
|
|
1954
|
+
headers: {
|
|
1955
|
+
[name: string]: unknown;
|
|
1956
|
+
};
|
|
1957
|
+
content: {
|
|
1958
|
+
"application/json": components["schemas"]["WorkspaceChangesPage"];
|
|
1959
|
+
};
|
|
1960
|
+
};
|
|
1961
|
+
default: components["responses"]["Error"];
|
|
1962
|
+
};
|
|
1963
|
+
};
|
|
1832
1964
|
}
|
package/dist/http.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RetryRecord } from './progress.js';
|
|
2
|
+
export declare const SDK_VERSION = "0.6.1";
|
|
2
3
|
export interface RequestOptions {
|
|
3
4
|
query?: Record<string, string | number | boolean | undefined | null>;
|
|
4
5
|
json?: unknown;
|
|
@@ -10,6 +11,8 @@ export interface RequestOptions {
|
|
|
10
11
|
signal?: AbortSignal;
|
|
11
12
|
/** Override the client's default request timeout (ms); 0 disables it (streams). */
|
|
12
13
|
timeoutMs?: number;
|
|
14
|
+
/** Called before each retry of a transient failure (lifecycle timing records these). */
|
|
15
|
+
onRetry?: (retry: Omit<RetryRecord, 'atMs'>) => void;
|
|
13
16
|
}
|
|
14
17
|
export interface HttpOptions {
|
|
15
18
|
baseUrl: string;
|
|
@@ -21,6 +24,16 @@ export interface HttpOptions {
|
|
|
21
24
|
sleep?: (ms: number) => Promise<void>;
|
|
22
25
|
}
|
|
23
26
|
export declare const defaultSleep: (ms: number) => Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* The fetch the SDK uses when none is given. On runtimes whose bundled undici is 8.x (Node 26) it sends
|
|
29
|
+
* `Connection: close`: undici 8.9 intermittently stalls a request on a reused keep-alive connection after the
|
|
30
|
+
* connection sat idle for a few seconds (measured against the staging API: 20.9 s and 26.3 s stalls in 50 requests
|
|
31
|
+
* with 0.2-12 s gaps; Node 22 / undici 6.28 max 351 ms; Node 26 with `Connection: close` max 435 ms; node:http2 on the
|
|
32
|
+
* same load balancer and gaps max 193 ms, and the load balancer's idle timeout is 3600 s, so it is not an idle-timeout
|
|
33
|
+
* interaction). The CLI and MCP server do the same. Other runtimes keep the runtime's keep-alive pooling.
|
|
34
|
+
* `SHARDFLUX_HTTP_KEEPALIVE=1` disables the workaround.
|
|
35
|
+
*/
|
|
36
|
+
export declare function defaultFetch(env?: Record<string, string | undefined> | undefined, undiciVersion?: string | undefined): typeof fetch;
|
|
24
37
|
export declare function buildUrl(base: string, path: string, query?: RequestOptions['query']): string;
|
|
25
38
|
/** Turns a non-2xx response into a ShardfluxApiError (or a protocol error for undocumented bodies). */
|
|
26
39
|
export declare function errorFrom(res: Response, source: 'api' | 'cell'): Promise<Error>;
|
|
@@ -30,10 +43,26 @@ export declare class HttpClient {
|
|
|
30
43
|
/** Performs the request and returns the raw Response (2xx), throwing structured errors otherwise. */
|
|
31
44
|
raw(method: string, path: string, init?: RequestOptions, authorization?: string): Promise<Response>;
|
|
32
45
|
json<T>(method: string, path: string, init?: RequestOptions, authorization?: string): Promise<T>;
|
|
46
|
+
/** Like json() but also returns the status and the response headers (bounded waits read Preference-Applied). */
|
|
47
|
+
jsonWithHeaders<T>(method: string, path: string, init?: RequestOptions, authorization?: string): Promise<{
|
|
48
|
+
status: number;
|
|
49
|
+
headers: Headers;
|
|
50
|
+
body: T;
|
|
51
|
+
}>;
|
|
33
52
|
/** Like json() but also returns the HTTP status (open() distinguishes 200 from 202). */
|
|
34
53
|
jsonWithStatus<T>(method: string, path: string, init?: RequestOptions, authorization?: string): Promise<{
|
|
35
54
|
status: number;
|
|
36
55
|
body: T;
|
|
37
56
|
}>;
|
|
38
57
|
}
|
|
58
|
+
/** Longest server-side wait the SDK asks for (contracts §3: servers cap `Prefer: wait` at 20 s). */
|
|
59
|
+
export declare const SERVER_WAIT_MAX_S = 20;
|
|
60
|
+
/**
|
|
61
|
+
* One bounded-wait poll (contracts §3): GET `path` with `Prefer: wait=<s>` when `waitS` >= 1. `applied` is true only
|
|
62
|
+
* when the server says it waited (Preference-Applied); otherwise the caller keeps its own backoff.
|
|
63
|
+
*/
|
|
64
|
+
export declare function pollWithWait<T>(http: HttpClient, path: string, authorization: string, waitS: number, signal?: AbortSignal, onRetry?: RequestOptions['onRetry']): Promise<{
|
|
65
|
+
body: T;
|
|
66
|
+
applied: boolean;
|
|
67
|
+
}>;
|
|
39
68
|
export declare function randomId(prefix?: string): string;
|
package/dist/http.js
CHANGED
|
@@ -5,8 +5,29 @@
|
|
|
5
5
|
* requests carrying an Idempotency-Key).
|
|
6
6
|
*/
|
|
7
7
|
import { ShardfluxApiError, ShardfluxProtocolError, isErrorBody } from "./errors.js";
|
|
8
|
-
|
|
8
|
+
import { describeFailure } from "./progress.js";
|
|
9
|
+
export const SDK_VERSION = '0.6.1';
|
|
9
10
|
export const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11
|
+
/**
|
|
12
|
+
* The fetch the SDK uses when none is given. On runtimes whose bundled undici is 8.x (Node 26) it sends
|
|
13
|
+
* `Connection: close`: undici 8.9 intermittently stalls a request on a reused keep-alive connection after the
|
|
14
|
+
* connection sat idle for a few seconds (measured against the staging API: 20.9 s and 26.3 s stalls in 50 requests
|
|
15
|
+
* with 0.2-12 s gaps; Node 22 / undici 6.28 max 351 ms; Node 26 with `Connection: close` max 435 ms; node:http2 on the
|
|
16
|
+
* same load balancer and gaps max 193 ms, and the load balancer's idle timeout is 3600 s, so it is not an idle-timeout
|
|
17
|
+
* interaction). The CLI and MCP server do the same. Other runtimes keep the runtime's keep-alive pooling.
|
|
18
|
+
* `SHARDFLUX_HTTP_KEEPALIVE=1` disables the workaround.
|
|
19
|
+
*/
|
|
20
|
+
export function defaultFetch(env = globalThis.process?.env, undiciVersion = globalThis.process?.versions?.undici) {
|
|
21
|
+
const base = (input, init) => fetch(input, init);
|
|
22
|
+
const major = Number((undiciVersion ?? '').split('.')[0]);
|
|
23
|
+
if (!(major >= 8) || env?.SHARDFLUX_HTTP_KEEPALIVE === '1')
|
|
24
|
+
return base;
|
|
25
|
+
return (input, init) => {
|
|
26
|
+
const headers = new Headers(init?.headers);
|
|
27
|
+
headers.set('connection', 'close');
|
|
28
|
+
return fetch(input, { ...init, headers });
|
|
29
|
+
};
|
|
30
|
+
}
|
|
10
31
|
export function buildUrl(base, path, query) {
|
|
11
32
|
const u = new URL(base.replace(/\/+$/, '') + path);
|
|
12
33
|
for (const [k, v] of Object.entries(query ?? {})) {
|
|
@@ -76,7 +97,9 @@ export class HttpClient {
|
|
|
76
97
|
throw err;
|
|
77
98
|
if (!retriable || attempt >= this.opts.maxRetries)
|
|
78
99
|
throw err;
|
|
79
|
-
|
|
100
|
+
const delayMs = Math.min(2_000, 200 * 2 ** attempt);
|
|
101
|
+
init.onRetry?.({ request: `${method} ${path}`, attempt: attempt + 1, cause: describeFailure(err, timeoutMs), delayMs });
|
|
102
|
+
await sleep(delayMs);
|
|
80
103
|
continue;
|
|
81
104
|
}
|
|
82
105
|
if (res.ok)
|
|
@@ -87,7 +110,9 @@ export class HttpClient {
|
|
|
87
110
|
if (!retriable || !retryableError || attempt >= this.opts.maxRetries)
|
|
88
111
|
throw error;
|
|
89
112
|
const hinted = error instanceof ShardfluxApiError ? error.retryAfterSeconds : undefined;
|
|
90
|
-
|
|
113
|
+
const delayMs = Math.min(5_000, hinted !== undefined ? hinted * 1000 : 200 * 2 ** attempt);
|
|
114
|
+
init.onRetry?.({ request: `${method} ${path}`, attempt: attempt + 1, cause: describeFailure(error), delayMs });
|
|
115
|
+
await sleep(delayMs);
|
|
91
116
|
}
|
|
92
117
|
}
|
|
93
118
|
async json(method, path, init = {}, authorization) {
|
|
@@ -104,6 +129,17 @@ export class HttpClient {
|
|
|
104
129
|
throw new ShardfluxProtocolError(`${method} ${path}: response is not JSON`, res.status);
|
|
105
130
|
}
|
|
106
131
|
}
|
|
132
|
+
/** Like json() but also returns the status and the response headers (bounded waits read Preference-Applied). */
|
|
133
|
+
async jsonWithHeaders(method, path, init = {}, authorization) {
|
|
134
|
+
const res = await this.raw(method, path, init, authorization);
|
|
135
|
+
const text = await res.text();
|
|
136
|
+
try {
|
|
137
|
+
return { status: res.status, headers: res.headers, body: (text.length === 0 ? undefined : JSON.parse(text)) };
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
throw new ShardfluxProtocolError(`${method} ${path}: response is not JSON`, res.status);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
107
143
|
/** Like json() but also returns the HTTP status (open() distinguishes 200 from 202). */
|
|
108
144
|
async jsonWithStatus(method, path, init = {}, authorization) {
|
|
109
145
|
const res = await this.raw(method, path, init, authorization);
|
|
@@ -116,6 +152,24 @@ export class HttpClient {
|
|
|
116
152
|
}
|
|
117
153
|
}
|
|
118
154
|
}
|
|
155
|
+
/** Longest server-side wait the SDK asks for (contracts §3: servers cap `Prefer: wait` at 20 s). */
|
|
156
|
+
export const SERVER_WAIT_MAX_S = 20;
|
|
157
|
+
/**
|
|
158
|
+
* One bounded-wait poll (contracts §3): GET `path` with `Prefer: wait=<s>` when `waitS` >= 1. `applied` is true only
|
|
159
|
+
* when the server says it waited (Preference-Applied); otherwise the caller keeps its own backoff.
|
|
160
|
+
*/
|
|
161
|
+
export async function pollWithWait(http, path, authorization, waitS, signal, onRetry) {
|
|
162
|
+
const s = Math.min(SERVER_WAIT_MAX_S, Math.floor(waitS));
|
|
163
|
+
const init = { ...(signal ? { signal } : {}), ...(onRetry ? { onRetry } : {}) };
|
|
164
|
+
if (s >= 1) {
|
|
165
|
+
init.headers = { prefer: `wait=${s}` };
|
|
166
|
+
// The held response may take the whole wait: the request timeout must outlast it.
|
|
167
|
+
init.timeoutMs = Math.max(http.opts.timeoutMs, s * 1000 + 10_000);
|
|
168
|
+
}
|
|
169
|
+
const res = await http.jsonWithHeaders('GET', path, init, authorization);
|
|
170
|
+
const pa = res.headers.get('preference-applied');
|
|
171
|
+
return { body: res.body, applied: s >= 1 && pa !== null && /\bwait\s*=/i.test(pa) };
|
|
172
|
+
}
|
|
119
173
|
export function randomId(prefix = '') {
|
|
120
174
|
return `${prefix}${crypto.randomUUID()}`;
|
|
121
175
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,14 +11,17 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export type { components, operations, paths } from './generated/app-api.js';
|
|
13
13
|
export type { components as CellComponents, paths as CellPaths } from './generated/cell-api.js';
|
|
14
|
-
export { BillingApi, Shardflux, WorkspacesApi, fetchBillingCatalog } from './client.js';
|
|
15
|
-
export type { AgentSession, BillingCatalog, BillingSubscription, Caps, CheckoutSession, Entitlements, Invoice, InvoicePage, ListParams, Me, OpenParams, OpenResponse, Operation, Page, PortalSession, ShardfluxOptions, WaitOptions, WorkspaceView, } from './client.js';
|
|
14
|
+
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, WorkspaceLifetime, WorkspaceOrigin, WorkspacePurpose, WorkspaceView, } from './client.js';
|
|
16
|
+
export type { FinishedOperation, LifecycleOptions, WaitedLifecycleOptions } from './lifecycle.js';
|
|
17
|
+
export { formatTiming } from './progress.js';
|
|
18
|
+
export type { LifecycleAction, LifecyclePhase, LifecycleTiming, ProgressEvent, ProgressListener, RetryRecord, ServerTiming, TimingOutcome, TimingPhase, } from './progress.js';
|
|
16
19
|
export { UsageApi } from './usage.js';
|
|
17
20
|
export type { Grants, Spend, SpendPolicy, UsageEstimate, UsageMeter, UsageSeries, UsageSeriesParams, UsageSummary } from './usage.js';
|
|
18
|
-
export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplatesApi, buildSettled } from './templates.js';
|
|
19
|
-
export type { BuilderAvailability, CreateTemplateBuildParams, TemplateBuild, TemplateBuildLogUrl, TemplateBuildRegistrationState, TemplateBuildState, TemplateDetail, TemplateOwner, TemplateRecipe, TemplateSummary, TemplateVersion, TemplateVersionState, WaitForBuildOptions, } from './templates.js';
|
|
20
|
-
export { SecretsApi } from './secrets.js';
|
|
21
|
-
export type { CreateSecretParams, Secret, SecretPermissions, SecretScope, SecretVersion, UpdateSecretParams } from './secrets.js';
|
|
21
|
+
export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplateDraftApi, TemplatesApi, buildSettled, saveAsTemplateBody } from './templates.js';
|
|
22
|
+
export type { BuilderAvailability, CreateDraftBody, CreateDraftParams, CreateTemplateBuildParams, CreateTestInstanceBody, DraftOpened, DraftState, OpenTestInstanceParams, OrgTemplateStorage, PublishDraftBody, PublishDraftParams, SaveAsTemplateBody, SaveAsTemplateParams, SaveAsTemplateResponse, TemplateBuild, TemplateBuildLogUrl, TemplateBuildRegistrationState, TemplateBuildState, TemplateDefaults, TemplateDefaultsInput, TemplateDetail, TemplateDiffChange, TemplateDiffEntry, TemplateDiffPage, TemplateDiffParams, TemplateDraft, TemplateDraftSummary, TemplateFileEntry, TemplateFilePage, TemplateFilesParams, TemplateFilesSummary, TemplateOwner, TemplateRecipe, TemplateSource, TemplateStorage, TemplateStorageWarning, TemplateSummary, TemplateVersion, TemplateVersionState, WaitForBuildOptions, } from './templates.js';
|
|
23
|
+
export { SecretsApi, WorkspaceSecrets } from './secrets.js';
|
|
24
|
+
export type { BoundSecretStatus, CreateOrganizationSecretParams, CreateSecretParams, Secret, SecretAccessEvent, SecretPermissions, SecretScope, SecretVersion, UpdateSecretParams, WorkspaceSecretBindings, } from './secrets.js';
|
|
22
25
|
export { EgressPolicyApi } from './egress.js';
|
|
23
26
|
export type { EffectiveEgressPolicy, EgressEnforcement, EgressMode, EgressPolicyInput, EgressPolicyVersion, EgressRule, EgressRuleInput, OrganizationEgressOverride, ProjectEgressPolicy, WorkspaceEgressPolicy, } from './egress.js';
|
|
24
27
|
export { VolumesApi } from './volumes.js';
|
|
@@ -26,12 +29,13 @@ export type { AttachVolumeParams, AttachmentResult, CreateVolumeParams, DeleteVo
|
|
|
26
29
|
export { AuditApi, auditQuery, parseAuditNdjson } from './audit.js';
|
|
27
30
|
export type { AuditActorType, AuditEvent, AuditFilters, AuditListParams, AuditOutcome, AuditSource } from './audit.js';
|
|
28
31
|
export { Workspace } from './workspace.js';
|
|
29
|
-
export {
|
|
30
|
-
export
|
|
32
|
+
export type { WakeOptions } from './workspace.js';
|
|
33
|
+
export { CellClient, DEFAULT_TRANSITION_TIMEOUT_MS, cellPath, ndjson } from './cell.js';
|
|
34
|
+
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';
|
|
31
35
|
export { ToolTokenManager } from './tokens.js';
|
|
32
36
|
export type { ToolName, ToolToken, ToolTokenOptions } from './tokens.js';
|
|
33
37
|
export { ToolArgumentError, executeToolCall, toAnthropicTools, toOpenAITools, validateArgs, workspaceTools } from './tools.js';
|
|
34
38
|
export type { JsonSchema, WorkspaceTool, WorkspaceToolsOptions } from './tools.js';
|
|
35
39
|
export { OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError } from './errors.js';
|
|
36
|
-
export type { AppErrorCode, CellErrorCode, ErrorCode } from './errors.js';
|
|
40
|
+
export type { AppErrorCode, CellErrorCode, ErrorCode, ErrorReason, KnownErrorReason } from './errors.js';
|
|
37
41
|
export { SDK_VERSION } from './http.js';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
export { BillingApi, Shardflux, WorkspacesApi, fetchBillingCatalog } from "./client.js";
|
|
1
|
+
export { BillingApi, Shardflux, WorkspacesApi, fetchBillingCatalog, pickByKey } from "./client.js";
|
|
2
|
+
export { formatTiming } from "./progress.js";
|
|
2
3
|
export { UsageApi } from "./usage.js";
|
|
3
|
-
export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplatesApi, buildSettled } from "./templates.js";
|
|
4
|
-
export { SecretsApi } from "./secrets.js";
|
|
4
|
+
export { TemplateBuildTimeoutError, TemplateBuildsApi, TemplateDraftApi, TemplatesApi, buildSettled, saveAsTemplateBody } from "./templates.js";
|
|
5
|
+
export { SecretsApi, WorkspaceSecrets } from "./secrets.js";
|
|
5
6
|
export { EgressPolicyApi } from "./egress.js";
|
|
6
7
|
export { VolumesApi } from "./volumes.js";
|
|
7
8
|
export { AuditApi, auditQuery, parseAuditNdjson } from "./audit.js";
|
|
8
9
|
export { Workspace } from "./workspace.js";
|
|
9
|
-
export { CellClient, cellPath, ndjson } from "./cell.js";
|
|
10
|
+
export { CellClient, DEFAULT_TRANSITION_TIMEOUT_MS, cellPath, ndjson } from "./cell.js";
|
|
10
11
|
export { ToolTokenManager } from "./tokens.js";
|
|
11
12
|
export { ToolArgumentError, executeToolCall, toAnthropicTools, toOpenAITools, validateArgs, workspaceTools } from "./tools.js";
|
|
12
13
|
export { OperationFailedError, OperationTimeoutError, ShardfluxApiError, ShardfluxProtocolError } from "./errors.js";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle calls (suspend, resume, snapshot, fork, delete, close, reset): "requested" or "finished".
|
|
3
|
+
*
|
|
4
|
+
* Every lifecycle endpoint answers once the operation is accepted, while it is usually still `queued`. By default the
|
|
5
|
+
* SDK returns that operation: the call resolves when the change is REQUESTED. With `wait`, it waits for the operation
|
|
6
|
+
* and resolves when the change has FINISHED, returning the succeeded operation (typed FinishedOperation) and, on a
|
|
7
|
+
* workspace handle, the refreshed view. Both paths are traced (see progress.ts).
|
|
8
|
+
*/
|
|
9
|
+
import type { ClientContext, Operation, WaitOptions } from './client.js';
|
|
10
|
+
import type { RequestOptions } from './http.js';
|
|
11
|
+
import { Trace } from './progress.js';
|
|
12
|
+
import type { LifecycleAction, ProgressListener } from './progress.js';
|
|
13
|
+
/** An operation that has finished successfully: what a lifecycle call with `wait` resolves to. */
|
|
14
|
+
export type FinishedOperation = Operation & {
|
|
15
|
+
state: 'succeeded';
|
|
16
|
+
completed_at: string;
|
|
17
|
+
};
|
|
18
|
+
export interface LifecycleOptions {
|
|
19
|
+
idempotencyKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Default (false): resolve once the change is requested; the returned operation is usually still `queued`.
|
|
22
|
+
* `true` or WaitOptions: resolve once it has finished (the operation `succeeded`); throws OperationFailedError when it
|
|
23
|
+
* fails and OperationTimeoutError after `timeoutMs` (default 5 minutes; the operation continues server side).
|
|
24
|
+
*/
|
|
25
|
+
wait?: boolean | WaitOptions;
|
|
26
|
+
/** Progress events of this call (phases, retries, and `done` with its timing). */
|
|
27
|
+
onProgress?: ProgressListener;
|
|
28
|
+
}
|
|
29
|
+
/** Lifecycle options the options of a waited call narrow to. */
|
|
30
|
+
export type WaitedLifecycleOptions = LifecycleOptions & {
|
|
31
|
+
wait: true | WaitOptions;
|
|
32
|
+
};
|
|
33
|
+
/** Internal: the trace a wait continues instead of starting its own (open(), wake() and waited lifecycle calls). */
|
|
34
|
+
export declare const TRACE: unique symbol;
|
|
35
|
+
/** Internal: work a workspace handle does after the operation finished, inside the same trace (refreshing its view). */
|
|
36
|
+
export declare const AFTER_WAIT: unique symbol;
|
|
37
|
+
export type InternalWaitOptions = WaitOptions & {
|
|
38
|
+
[TRACE]?: Trace;
|
|
39
|
+
};
|
|
40
|
+
export type InternalLifecycleOptions = LifecycleOptions & {
|
|
41
|
+
[AFTER_WAIT]?: (trace: Trace, operation: Operation) => Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
export declare function waitOptionsOf(opts: LifecycleOptions): WaitOptions | null;
|
|
44
|
+
/**
|
|
45
|
+
* Starts a lifecycle operation with `start` and, when `opts.wait` asks for it, waits for it to finish. The trace covers
|
|
46
|
+
* the request, every observed state, and `AFTER_WAIT`; it ends with `done` either way.
|
|
47
|
+
*/
|
|
48
|
+
export declare function runLifecycle(ctx: ClientContext, kind: LifecycleAction, workspaceId: string, start: (init: Pick<RequestOptions, 'onRetry'>) => Promise<Operation>, opts: InternalLifecycleOptions): Promise<Operation>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { OperationFailedError } from "./errors.js";
|
|
2
|
+
import { Trace, combineListeners, traced } from "./progress.js";
|
|
3
|
+
/** Internal: the trace a wait continues instead of starting its own (open(), wake() and waited lifecycle calls). */
|
|
4
|
+
export const TRACE = Symbol('shardflux.trace');
|
|
5
|
+
/** Internal: work a workspace handle does after the operation finished, inside the same trace (refreshing its view). */
|
|
6
|
+
export const AFTER_WAIT = Symbol('shardflux.afterWait');
|
|
7
|
+
export function waitOptionsOf(opts) {
|
|
8
|
+
if (opts.wait === undefined || opts.wait === false)
|
|
9
|
+
return null;
|
|
10
|
+
return opts.wait === true ? {} : opts.wait;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Starts a lifecycle operation with `start` and, when `opts.wait` asks for it, waits for it to finish. The trace covers
|
|
14
|
+
* the request, every observed state, and `AFTER_WAIT`; it ends with `done` either way.
|
|
15
|
+
*/
|
|
16
|
+
export async function runLifecycle(ctx, kind, workspaceId, start, opts) {
|
|
17
|
+
const waitOpts = waitOptionsOf(opts);
|
|
18
|
+
const trace = new Trace(kind, combineListeners(ctx.onProgress, opts.onProgress, waitOpts?.onProgress), { workspaceId });
|
|
19
|
+
return traced(trace, async () => {
|
|
20
|
+
trace.phase('request');
|
|
21
|
+
const operation = await start({ onRetry: trace.onRetry });
|
|
22
|
+
trace.observe(operation);
|
|
23
|
+
if (!waitOpts)
|
|
24
|
+
return operation;
|
|
25
|
+
let final = operation;
|
|
26
|
+
if (operation.state === 'failed' || operation.state === 'canceled')
|
|
27
|
+
throw new OperationFailedError(operation);
|
|
28
|
+
if (operation.state !== 'succeeded')
|
|
29
|
+
final = await ctx.workspaces.waitForOperation(operation.id, { ...waitOpts, [TRACE]: trace });
|
|
30
|
+
await opts[AFTER_WAIT]?.(trace, final);
|
|
31
|
+
return final;
|
|
32
|
+
});
|
|
33
|
+
}
|