@shardflux/sdk 0.13.1 → 0.15.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 +134 -0
- package/README.md +233 -13
- package/dist/account.d.ts +41 -2
- package/dist/account.js +36 -2
- package/dist/cell.d.ts +39 -0
- package/dist/cell.js +71 -0
- package/dist/client.d.ts +115 -6
- package/dist/client.js +205 -5
- package/dist/codex-proof.d.ts +53 -0
- package/dist/codex-proof.js +200 -0
- package/dist/computer.d.ts +143 -0
- package/dist/computer.js +146 -0
- package/dist/errors.d.ts +1 -1
- package/dist/generated/app-api.d.ts +2649 -540
- package/dist/generated/cell-api.d.ts +338 -0
- package/dist/http.d.ts +1 -1
- package/dist/http.js +1 -1
- package/dist/index.d.ts +14 -6
- package/dist/index.js +7 -2
- package/dist/ports.d.ts +117 -0
- package/dist/ports.js +62 -0
- package/dist/progress.d.ts +11 -7
- package/dist/progress.js +2 -0
- package/dist/templates.d.ts +12 -0
- package/dist/templates.js +9 -0
- package/dist/tools.d.ts +24 -3
- package/dist/tools.js +131 -22
- package/dist/workspace-ref.d.ts +83 -0
- package/dist/workspace-ref.js +149 -0
- package/dist/workspace.d.ts +48 -1
- package/dist/workspace.js +71 -0
- package/package.json +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { CAPTURE_BARRIER } from "./cell.js";
|
|
2
|
+
import { ShardfluxApiError, isWorkspaceGone } from "./errors.js";
|
|
3
|
+
import { workspaceTools } from "./tools.js";
|
|
4
|
+
const FILE_METHODS = ['read', 'readText', 'readWithInfo', 'write', 'list', 'stat', 'remove', 'mkdir', 'move', 'search', 'patch'];
|
|
5
|
+
/**
|
|
6
|
+
* A workspace named by its key. Nothing is requested until the first call: `exec()`, `files`, a tool from `tools()`,
|
|
7
|
+
* `hint()` or `open()`. Concurrent first calls share one open; a failed open is not kept, so the next call opens again.
|
|
8
|
+
* A workspace deleted under the ref (409 `workspace_deleted`, `isWorkspaceGone`) fails the call that meets it and is
|
|
9
|
+
* forgotten: the next call opens the key again (a new workspace, as `open()` would). `open()` returns the full
|
|
10
|
+
* `Workspace` (suspend, fork, ports, computer, tool-call capture).
|
|
11
|
+
*/
|
|
12
|
+
export class WorkspaceRef {
|
|
13
|
+
key;
|
|
14
|
+
#api;
|
|
15
|
+
#params;
|
|
16
|
+
#grants;
|
|
17
|
+
#workspace = null;
|
|
18
|
+
#opening = null;
|
|
19
|
+
/** Internal: use `cloud.workspace(key, params)` or the module-level `workspace(key, params)`. */
|
|
20
|
+
constructor(api, key, params, grants) {
|
|
21
|
+
if (typeof key !== 'string' || key.length === 0)
|
|
22
|
+
throw new TypeError('workspace(key, params): key must be a non-empty string');
|
|
23
|
+
if (params.create !== false && (typeof params.template !== 'string' || params.template.length === 0)) {
|
|
24
|
+
throw new TypeError(`workspace("${key}", params): params.template is required (a template slug, e.g. "default")`);
|
|
25
|
+
}
|
|
26
|
+
this.key = key;
|
|
27
|
+
this.#api = api;
|
|
28
|
+
this.#params = params;
|
|
29
|
+
this.#grants = grants;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Whether the open that produced the current workspace created it (contracts §46.2): undefined until the ref has
|
|
33
|
+
* opened (or when the API does not report it), false for `create: false`.
|
|
34
|
+
*/
|
|
35
|
+
get created() {
|
|
36
|
+
if (!this.#workspace)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (this.#params.create === false)
|
|
39
|
+
return false;
|
|
40
|
+
return this.#workspace.created ?? undefined;
|
|
41
|
+
}
|
|
42
|
+
/** The opened workspace's mode, else the params' (`processful` when neither says). */
|
|
43
|
+
get mode() {
|
|
44
|
+
return this.#workspace?.mode ?? this.#params.mode ?? 'processful';
|
|
45
|
+
}
|
|
46
|
+
/** Tools granted by the opened workspace's last token; null before the open. */
|
|
47
|
+
get grantedTools() {
|
|
48
|
+
return this.#workspace?.grantedTools ?? null;
|
|
49
|
+
}
|
|
50
|
+
/** The workspace: opened (or, with `create: false`, found) on the first call and kept. */
|
|
51
|
+
open() {
|
|
52
|
+
if (this.#workspace)
|
|
53
|
+
return Promise.resolve(this.#workspace);
|
|
54
|
+
this.#opening ??= this.#open().then((ws) => {
|
|
55
|
+
this.#workspace = ws;
|
|
56
|
+
this.#opening = null;
|
|
57
|
+
return ws;
|
|
58
|
+
}, (err) => {
|
|
59
|
+
this.#opening = null;
|
|
60
|
+
throw err;
|
|
61
|
+
});
|
|
62
|
+
return this.#opening;
|
|
63
|
+
}
|
|
64
|
+
async #open() {
|
|
65
|
+
const params = this.#params;
|
|
66
|
+
// open() sends only the open's own parameters (`create` is the ref's).
|
|
67
|
+
if (params.create !== false)
|
|
68
|
+
return this.#api.open({ ...params, key: this.key });
|
|
69
|
+
const found = await this.#api.findByKey(this.key, {
|
|
70
|
+
includeDeleted: false,
|
|
71
|
+
...(params.projectId !== undefined ? { projectId: params.projectId } : {}),
|
|
72
|
+
...(params.agentLabel !== undefined ? { agentLabel: params.agentLabel } : {}),
|
|
73
|
+
...(params.tools !== undefined ? { tools: params.tools } : {}),
|
|
74
|
+
});
|
|
75
|
+
if (found)
|
|
76
|
+
return found;
|
|
77
|
+
throw new ShardfluxApiError(404, { error: { code: 'not_found', message: `No workspace with key "${this.key}" in this project (create: false).`, request_id: '', retryable: false, details: { key: this.key } } }, 'api');
|
|
78
|
+
}
|
|
79
|
+
/** Runs `fn` on the workspace; a workspace found deleted is forgotten so the next call opens the key again. */
|
|
80
|
+
async #use(fn) {
|
|
81
|
+
const ws = await this.open();
|
|
82
|
+
try {
|
|
83
|
+
return await fn(ws);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
if (isWorkspaceGone(err) && this.#workspace === ws)
|
|
87
|
+
this.#workspace = null;
|
|
88
|
+
throw err;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Runs a command and collects its output (`cell().exec.run()`). A string runs through `bash -lc`, so shell syntax
|
|
93
|
+
* works; an argv array runs without a shell. A file-first workspace runs commands with `executions.run()`.
|
|
94
|
+
*/
|
|
95
|
+
exec(command, opts = {}) {
|
|
96
|
+
const argv = typeof command === 'string' ? ['bash', '-lc', command] : [...command];
|
|
97
|
+
return this.#use((ws) => ws.cell().exec.run(argv, opts));
|
|
98
|
+
}
|
|
99
|
+
/** The workspace's files, as on `cell().files`. */
|
|
100
|
+
files = Object.fromEntries(FILE_METHODS.map((name) => [
|
|
101
|
+
name,
|
|
102
|
+
(...args) => this.#use((ws) => ws.cell().files[name](...args)),
|
|
103
|
+
]));
|
|
104
|
+
/** A file-first workspace's executions (`run`, `get`), as on `Workspace.executions`. */
|
|
105
|
+
executions = {
|
|
106
|
+
run: (argv, opts = {}) => this.#use((ws) => ws.executions.run(argv, opts)),
|
|
107
|
+
get: (executionId, opts = {}) => this.#use((ws) => ws.executions.get(executionId, opts)),
|
|
108
|
+
};
|
|
109
|
+
/** The workspace's cell client (`Workspace.cell()`), opening the key first if needed. */
|
|
110
|
+
async cell(opts = {}) {
|
|
111
|
+
return (await this.open()).cell(opts);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Says a tool call is coming. Before the first open it starts the open in the background (`wake` resolves when the
|
|
115
|
+
* workspace runs; nothing has to await it), unless `wake: null`; afterwards it is `Workspace.hint()`.
|
|
116
|
+
*/
|
|
117
|
+
async hint(opts = {}) {
|
|
118
|
+
if (this.#workspace)
|
|
119
|
+
return this.#workspace.hint(opts);
|
|
120
|
+
if (opts.wake === null)
|
|
121
|
+
return { residency: null, wake: null };
|
|
122
|
+
const wake = this.open().then(() => true);
|
|
123
|
+
wake.catch(() => undefined); // a failed open is left to the next call, which opens again
|
|
124
|
+
return { residency: null, wake };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Workspace tools for this key (`workspaceTools`), built before any VM exists: the definitions come from the API
|
|
128
|
+
* key's tool permissions (`GET /v1/me`, read once per client), and `computer` only with `computerUse: true` in the
|
|
129
|
+
* params or on an opened workspace whose computer use is on. The first tool call opens the key.
|
|
130
|
+
*/
|
|
131
|
+
async tools(opts = {}) {
|
|
132
|
+
// create: false finds the workspace now (a lookup, no VM start), so the tools match its mode.
|
|
133
|
+
if (this.#params.create === false)
|
|
134
|
+
await this.open();
|
|
135
|
+
let tools = opts.tools ?? this.grantedTools ?? undefined;
|
|
136
|
+
if (tools === undefined) {
|
|
137
|
+
const granted = await this.#grants();
|
|
138
|
+
if (granted) {
|
|
139
|
+
const computer = this.#workspace ? this.#workspace.computerUse.enabled : this.#params.computerUse === true;
|
|
140
|
+
tools = granted.filter((t) => t !== 'computer' || computer);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return workspaceTools(this, { ...opts, ...(tools !== undefined ? { tools } : {}) });
|
|
144
|
+
}
|
|
145
|
+
/** Internal: tool-call capture's read-your-writes barrier, once the workspace is open. */
|
|
146
|
+
[CAPTURE_BARRIER]() {
|
|
147
|
+
return this.#workspace?.[CAPTURE_BARRIER]();
|
|
148
|
+
}
|
|
149
|
+
}
|
package/dist/workspace.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A workspace handle: the latest view from the application API plus managed
|
|
3
3
|
* tool tokens and cell clients (one per agent label / tool set).
|
|
4
4
|
*/
|
|
5
|
-
import type { AllocationMode, ClientContext, IdlePolicy, DiskLayout, ForkTarget, Operation, SuspendRequest, SuspendWhenIdleOptions, SuspendWhenIdleResult, WaitOptions, WorkspaceLifetime, WorkspaceMemory, WorkspaceOrigin, WorkspacePurpose, WorkspaceView } from './client.js';
|
|
5
|
+
import type { AllocationMode, ComputerUse, ClientContext, IdlePolicy, DiskLayout, ForkTarget, Operation, ResizeParams, ResizeResult, SuspendRequest, SuspendWhenIdleOptions, SuspendWhenIdleResult, WaitOptions, WorkspaceLifetime, WorkspaceMemory, WorkspaceOrigin, WorkspacePurpose, WorkspaceView } from './client.js';
|
|
6
6
|
import { CAPTURE_BARRIER, CellClient } from './cell.js';
|
|
7
7
|
import { ToolCallCapture } from './capture.js';
|
|
8
8
|
import type { ToolCallCaptureOptions } from './capture.js';
|
|
@@ -10,6 +10,8 @@ import type { WorkspaceMode } from './errors.js';
|
|
|
10
10
|
import type { FinishedOperation, ForkOptions, LifecycleOptions, ResumeOptions, SuspendOptions, WaitedForkOptions, WaitedLifecycleOptions, WaitedResumeOptions, WaitedSuspendOptions } from './lifecycle.js';
|
|
11
11
|
import { Trace } from './progress.js';
|
|
12
12
|
import type { LifecycleTiming, ProgressListener } from './progress.js';
|
|
13
|
+
import { WorkspaceComputer } from './computer.js';
|
|
14
|
+
import { WorkspacePorts } from './ports.js';
|
|
13
15
|
import { WorkspaceSecrets } from './secrets.js';
|
|
14
16
|
import type { CellClientOptions, Residency, WorkspaceChangesPage, WorkspaceChangesParams } from './cell.js';
|
|
15
17
|
import type { SaveAsTemplateParams, SaveAsTemplateResponse, WorkspaceStartup } from './templates.js';
|
|
@@ -56,11 +58,18 @@ export interface HintResult {
|
|
|
56
58
|
}
|
|
57
59
|
export declare class Workspace {
|
|
58
60
|
#private;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the open() that returned this handle created the workspace (0.15.0+, contracts §46.2): true for a new key
|
|
63
|
+
* (or a key whose session ended), false when it reconnected to or resumed an existing workspace. Null for handles
|
|
64
|
+
* from get(), list() and findByKey(), and from an API that does not report it.
|
|
65
|
+
*/
|
|
66
|
+
readonly created: boolean | null;
|
|
59
67
|
constructor(ctx: ClientContext, view: WorkspaceView, opts?: {
|
|
60
68
|
agentLabel?: string | undefined;
|
|
61
69
|
tools?: ToolName[] | undefined;
|
|
62
70
|
token?: ToolToken | null;
|
|
63
71
|
trace?: Trace;
|
|
72
|
+
created?: boolean | null;
|
|
64
73
|
});
|
|
65
74
|
/**
|
|
66
75
|
* Where the time went in the last lifecycle call made through this handle: open(), wake() (also when a tool call
|
|
@@ -150,6 +159,29 @@ export declare class Workspace {
|
|
|
150
159
|
get executions(): CellClient['executions'];
|
|
151
160
|
/** Secret names bound to this workspace (injected into every exec/PTY start): `get()`, `set(names)`. */
|
|
152
161
|
get secrets(): WorkspaceSecrets;
|
|
162
|
+
/**
|
|
163
|
+
* Inbound ports (0.14.0): serve a TCP port of the workspace at its own private HTTPS URL. A request wakes a parked or
|
|
164
|
+
* suspended workspace and is served once it runs.
|
|
165
|
+
*
|
|
166
|
+
* const { url } = await workspace.ports.expose(3000); // the server listens on 0.0.0.0:3000
|
|
167
|
+
* const { token } = await workspace.ports.token(3000); // Authorization: Bearer <token>
|
|
168
|
+
* const link = await workspace.ports.link(3000); // open link.url in a browser
|
|
169
|
+
*/
|
|
170
|
+
get ports(): WorkspacePorts;
|
|
171
|
+
/**
|
|
172
|
+
* The workspace desktop (0.15.0+, contracts §45): `act(actions)`, `screenshot()`, `stream()` (a private link to watch
|
|
173
|
+
* it), `status()`, `start()`, `stop()`. Needs computer use on (`setComputerUse(true)`, or the template's switch); the
|
|
174
|
+
* platform starts the desktop on the first call that needs it.
|
|
175
|
+
*/
|
|
176
|
+
get computer(): WorkspaceComputer;
|
|
177
|
+
/** Computer use (0.15.0+): `enabled` is what tool tokens carry; `workspace` null follows the `template`'s switch. */
|
|
178
|
+
get computerUse(): ComputerUse;
|
|
179
|
+
/**
|
|
180
|
+
* Switches computer use on or off for this workspace (null follows the template). Takes effect on the next tool token:
|
|
181
|
+
* this handle's cached tokens are dropped. 409 `computer_use_unavailable` when its template version cannot run a
|
|
182
|
+
* desktop.
|
|
183
|
+
*/
|
|
184
|
+
setComputerUse(enabled: boolean | null): Promise<this>;
|
|
153
185
|
/** The workspace's text inputs `{NAME: value}` (0.7.0; secret inputs are bound secrets, never listed here). */
|
|
154
186
|
inputs(): Promise<Record<string, string>>;
|
|
155
187
|
get labels(): Record<string, string>;
|
|
@@ -200,6 +232,21 @@ export declare class Workspace {
|
|
|
200
232
|
* A suspend the request already started is not undone (it shows as `activeOperation`).
|
|
201
233
|
*/
|
|
202
234
|
cancelSuspendWhenIdle(): Promise<this>;
|
|
235
|
+
/**
|
|
236
|
+
* Resizes this workspace (0.14.0): memory, the held floor, the allocation mode, CPU and disk, whether it is running or
|
|
237
|
+
* suspended, fixed or elastic, without a restart or a fork. Memory changes live on a running workspace (a shrink gives
|
|
238
|
+
* back what the guest frees: `memory.converged`); a suspended one gets its new size when it resumes, before its first
|
|
239
|
+
* call. CPU changes live up to the vCPUs the workspace booted with, beyond that at its next start. Disks grow online.
|
|
240
|
+
* The new caps are stored, so every later start uses them. Resolves once the resize has finished, with per resource
|
|
241
|
+
* when it applies (`now`, `resume` or `next_start` with the `reason`); the handle's view is refreshed. See
|
|
242
|
+
* WorkspacesApi.resize for the errors. A file-first workspace (no VM to resize) is refused locally with
|
|
243
|
+
* NotSupportedForModeError.
|
|
244
|
+
*
|
|
245
|
+
* const r = await workspace.resize({ memoryMib: 6144, cpuMillis: 4000 });
|
|
246
|
+
* r.memory?.applies_at; // 'now'
|
|
247
|
+
* r.cpu?.applies_at; // 'next_start' (reason 'boot_vcpus': more vCPUs than it booted with)
|
|
248
|
+
*/
|
|
249
|
+
resize(params: ResizeParams): Promise<ResizeResult>;
|
|
203
250
|
/**
|
|
204
251
|
* Resumes a suspended workspace. Resolves when the resume is REQUESTED; with `{ wait: true }`, once the workspace runs.
|
|
205
252
|
* Tool calls wake a suspended workspace by themselves, so this is rarely needed. With `wait` (0.9.0) it is one held
|
package/dist/workspace.js
CHANGED
|
@@ -4,6 +4,8 @@ import { NotSupportedForModeError, OperationFailedError, ShardfluxApiError } fro
|
|
|
4
4
|
import { SERVER_WAIT_MAX_S, defaultSleep, randomId } from "./http.js";
|
|
5
5
|
import { AFTER_WAIT, HELD_RESUME, TRACE } from "./lifecycle.js";
|
|
6
6
|
import { Trace, combineListeners, traced } from "./progress.js";
|
|
7
|
+
import { WorkspaceComputer } from "./computer.js";
|
|
8
|
+
import { WorkspacePorts } from "./ports.js";
|
|
7
9
|
import { WorkspaceSecrets } from "./secrets.js";
|
|
8
10
|
import { ToolTokenManager } from "./tokens.js";
|
|
9
11
|
const notRunning = (e) => e instanceof ShardfluxApiError && (e.code === 'workspace_not_running' || (e.code === 'conflict' && e.reason === 'workspace_not_running'));
|
|
@@ -20,8 +22,15 @@ export class Workspace {
|
|
|
20
22
|
#lastTiming;
|
|
21
23
|
/** The newest tree revision seen (file-first): the view's, or any cell response's since. */
|
|
22
24
|
#treeRevision;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the open() that returned this handle created the workspace (0.15.0+, contracts §46.2): true for a new key
|
|
27
|
+
* (or a key whose session ended), false when it reconnected to or resumed an existing workspace. Null for handles
|
|
28
|
+
* from get(), list() and findByKey(), and from an API that does not report it.
|
|
29
|
+
*/
|
|
30
|
+
created;
|
|
23
31
|
constructor(ctx, view, opts = {}) {
|
|
24
32
|
this.#ctx = ctx;
|
|
33
|
+
this.created = opts.created ?? null;
|
|
25
34
|
this.#view = view;
|
|
26
35
|
this.#treeRevision = view.mode === 'file_first' && typeof view.tree_revision === 'number' ? view.tree_revision : null;
|
|
27
36
|
this.#defaults = { agentLabel: opts.agentLabel, tools: opts.tools };
|
|
@@ -200,6 +209,45 @@ export class Workspace {
|
|
|
200
209
|
get secrets() {
|
|
201
210
|
return new WorkspaceSecrets(this.#ctx, this.id);
|
|
202
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Inbound ports (0.14.0): serve a TCP port of the workspace at its own private HTTPS URL. A request wakes a parked or
|
|
214
|
+
* suspended workspace and is served once it runs.
|
|
215
|
+
*
|
|
216
|
+
* const { url } = await workspace.ports.expose(3000); // the server listens on 0.0.0.0:3000
|
|
217
|
+
* const { token } = await workspace.ports.token(3000); // Authorization: Bearer <token>
|
|
218
|
+
* const link = await workspace.ports.link(3000); // open link.url in a browser
|
|
219
|
+
*/
|
|
220
|
+
get ports() {
|
|
221
|
+
return new WorkspacePorts(this.#ctx, this.id);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The workspace desktop (0.15.0+, contracts §45): `act(actions)`, `screenshot()`, `stream()` (a private link to watch
|
|
225
|
+
* it), `status()`, `start()`, `stop()`. Needs computer use on (`setComputerUse(true)`, or the template's switch); the
|
|
226
|
+
* platform starts the desktop on the first call that needs it.
|
|
227
|
+
*/
|
|
228
|
+
get computer() {
|
|
229
|
+
return new WorkspaceComputer({
|
|
230
|
+
cell: () => this.cell(),
|
|
231
|
+
ports: () => this.ports,
|
|
232
|
+
setEnabled: (enabled) => this.setComputerUse(enabled).then(() => this.computerUse),
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** Computer use (0.15.0+): `enabled` is what tool tokens carry; `workspace` null follows the `template`'s switch. */
|
|
236
|
+
get computerUse() {
|
|
237
|
+
return this.#view.computer_use;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Switches computer use on or off for this workspace (null follows the template). Takes effect on the next tool token:
|
|
241
|
+
* this handle's cached tokens are dropped. 409 `computer_use_unavailable` when its template version cannot run a
|
|
242
|
+
* desktop.
|
|
243
|
+
*/
|
|
244
|
+
async setComputerUse(enabled) {
|
|
245
|
+
const cu = await this.#ctx.workspaces.setComputerUse(this.id, enabled);
|
|
246
|
+
this.#view = { ...this.#view, computer_use: cu };
|
|
247
|
+
for (const m of this.#managers.values())
|
|
248
|
+
m.invalidate();
|
|
249
|
+
return this;
|
|
250
|
+
}
|
|
203
251
|
/** The workspace's text inputs `{NAME: value}` (0.7.0; secret inputs are bound secrets, never listed here). */
|
|
204
252
|
inputs() {
|
|
205
253
|
return this.#ctx.workspaces.inputs(this.id);
|
|
@@ -274,6 +322,29 @@ export class Workspace {
|
|
|
274
322
|
this.#view = (await this.#ctx.workspaces.cancelSuspendWhenIdle(this.id)).data;
|
|
275
323
|
return this;
|
|
276
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Resizes this workspace (0.14.0): memory, the held floor, the allocation mode, CPU and disk, whether it is running or
|
|
327
|
+
* suspended, fixed or elastic, without a restart or a fork. Memory changes live on a running workspace (a shrink gives
|
|
328
|
+
* back what the guest frees: `memory.converged`); a suspended one gets its new size when it resumes, before its first
|
|
329
|
+
* call. CPU changes live up to the vCPUs the workspace booted with, beyond that at its next start. Disks grow online.
|
|
330
|
+
* The new caps are stored, so every later start uses them. Resolves once the resize has finished, with per resource
|
|
331
|
+
* when it applies (`now`, `resume` or `next_start` with the `reason`); the handle's view is refreshed. See
|
|
332
|
+
* WorkspacesApi.resize for the errors. A file-first workspace (no VM to resize) is refused locally with
|
|
333
|
+
* NotSupportedForModeError.
|
|
334
|
+
*
|
|
335
|
+
* const r = await workspace.resize({ memoryMib: 6144, cpuMillis: 4000 });
|
|
336
|
+
* r.memory?.applies_at; // 'now'
|
|
337
|
+
* r.cpu?.applies_at; // 'next_start' (reason 'boot_vcpus': more vCPUs than it booted with)
|
|
338
|
+
*/
|
|
339
|
+
async resize(params) {
|
|
340
|
+
const refusal = this.#needsVm('resize');
|
|
341
|
+
if (refusal)
|
|
342
|
+
throw refusal;
|
|
343
|
+
const out = await this.#ctx.workspaces.resize(this.id, this.#tracked(params));
|
|
344
|
+
// The resize has happened: a failed view read leaves the old view (the next refresh() reads it again).
|
|
345
|
+
await this.refresh().catch(() => undefined);
|
|
346
|
+
return out;
|
|
347
|
+
}
|
|
277
348
|
resume(opts = {}) {
|
|
278
349
|
const refusal = this.#needsVm('resume');
|
|
279
350
|
if (refusal)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shardflux/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shardflux TypeScript SDK: open persistent agent workspaces by key and give your agent workspace tools (exec, files, processes, PTY, git, browser).",
|
|
6
6
|
"license": "Apache-2.0",
|