@shardflux/sdk 0.10.2 → 0.11.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 +58 -26
- package/README.md +73 -51
- package/dist/account.d.ts +2 -2
- package/dist/account.js +1 -1
- package/dist/cell.d.ts +21 -21
- package/dist/cell.js +12 -12
- package/dist/client.d.ts +31 -31
- package/dist/client.js +17 -17
- package/dist/egress.d.ts +3 -3
- package/dist/errors.d.ts +18 -18
- package/dist/errors.js +11 -11
- package/dist/executions.d.ts +2 -2
- package/dist/feedback.d.ts +3 -3
- package/dist/generated/app-api.d.ts +1352 -21
- package/dist/http.d.ts +7 -11
- package/dist/http.js +8 -11
- package/dist/index.d.ts +1 -1
- package/dist/lifecycle.d.ts +2 -2
- package/dist/lifecycle.js +1 -1
- package/dist/progress.d.ts +38 -18
- package/dist/progress.js +17 -11
- package/dist/tar.d.ts +1 -1
- package/dist/tar.js +1 -1
- package/dist/template-file.d.ts +1 -1
- package/dist/template-file.js +1 -1
- package/dist/templates.d.ts +21 -21
- package/dist/templates.js +8 -8
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +4 -4
- package/dist/version-check.d.ts +1 -1
- package/dist/volumes.d.ts +1 -1
- package/dist/workspace.d.ts +30 -21
- package/dist/workspace.js +27 -20
- package/package.json +1 -1
package/dist/tools.js
CHANGED
|
@@ -83,11 +83,11 @@ export function validateArgs(schema, value, path = '$') {
|
|
|
83
83
|
return issues;
|
|
84
84
|
}
|
|
85
85
|
const ALL = ['exec', 'files', 'pty', 'process', 'git', 'browser'];
|
|
86
|
-
/** The tool permissions whose tools work on a file-first workspace
|
|
86
|
+
/** The tool permissions whose tools work on a file-first workspace: files and executions. */
|
|
87
87
|
const FILE_FIRST_TOOLS = ['exec', 'files'];
|
|
88
88
|
/** Changed paths returned to the model per execution (the rest is flagged `changed_truncated`). */
|
|
89
89
|
const MAX_CHANGED_LISTED = 200;
|
|
90
|
-
/** Tools served from a sleeping workspace's disk without waking it
|
|
90
|
+
/** Tools served from a sleeping workspace's disk without waking it: the runner sends no hint. */
|
|
91
91
|
const DISK_READS = new Set(['read_file', 'list_files', 'search_files']);
|
|
92
92
|
const obj = (properties, required = []) => ({ type: 'object', properties, required, additionalProperties: false });
|
|
93
93
|
const path = (description = 'Absolute path inside the workspace, e.g. /home/user/project/main.py') => ({ type: 'string', minLength: 1, maxLength: 4096, description });
|
|
@@ -107,7 +107,7 @@ export function workspaceTools(workspace, opts = {}) {
|
|
|
107
107
|
});
|
|
108
108
|
const max = opts.maxOutputBytes ?? 65_536;
|
|
109
109
|
const prefix = opts.prefix ?? '';
|
|
110
|
-
// A file-first workspace
|
|
110
|
+
// A file-first workspace has files and executions only: no processes, terminals, version control or
|
|
111
111
|
// browser between calls, so those tools are not offered, and exec runs each command as an execution.
|
|
112
112
|
const fileFirst = (opts.mode ?? workspace.mode) === 'file_first';
|
|
113
113
|
const allowed = new Set((opts.tools ?? workspace.grantedTools ?? ALL).filter((t) => !fileFirst || FILE_FIRST_TOOLS.includes(t)));
|
|
@@ -436,7 +436,7 @@ export function workspaceTools(workspace, opts = {}) {
|
|
|
436
436
|
const issues = validateArgs(d.parameters, args);
|
|
437
437
|
if (issues.length > 0)
|
|
438
438
|
throw new ToolArgumentError(`${prefix}${d.name}`, issues);
|
|
439
|
-
// Fire and forget: a parked workspace starts restoring while this call is prepared
|
|
439
|
+
// Fire and forget: a parked workspace starts restoring while this call is prepared. Not for
|
|
440
440
|
// the reads a sleeping workspace serves from its disk (§26.4): the hint would wake it for nothing.
|
|
441
441
|
if (opts.hint !== false && !DISK_READS.has(d.name)) {
|
|
442
442
|
workspace
|
package/dist/version-check.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Client version check (
|
|
2
|
+
* Client version check (0.9.0+). `GET /v1/client-versions` (unauthenticated) lists every published
|
|
3
3
|
* client with its `latest` and `minimum_supported` version.
|
|
4
4
|
*
|
|
5
5
|
* const s = await checkClientVersion(); // @shardflux/sdk at SDK_VERSION
|
package/dist/volumes.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared volumes over the application API (/v1
|
|
2
|
+
* Shared volumes over the application API (/v1). Types come from
|
|
3
3
|
* the generated OpenAPI document (schemas `Volume` and `VolumeAttachment`).
|
|
4
4
|
*
|
|
5
5
|
* A volume is persistent shared storage (EFS-backed) owned by a project. It is
|
package/dist/workspace.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export interface WakeOptions {
|
|
|
22
22
|
/** Progress of the wake: the resume request, observed states, conflicts retried, and `done` with the timing. */
|
|
23
23
|
onProgress?: ProgressListener;
|
|
24
24
|
/**
|
|
25
|
-
* The tool token the wake brings back (0.9.0): the held resume
|
|
25
|
+
* The tool token the wake brings back (0.9.0): the held resume returns one with the running
|
|
26
26
|
* workspace, for this agent label and tool set (defaults: those given to open()). It is kept for `cell()` clients of
|
|
27
27
|
* the same label and tools, whose next call then needs no token request. A `cell()` client's own wake passes its
|
|
28
28
|
* label and tools.
|
|
@@ -45,7 +45,7 @@ export interface HintOptions {
|
|
|
45
45
|
}
|
|
46
46
|
/** `workspace.hint()`: what the host found, or the background wake of a workspace that was not running. */
|
|
47
47
|
export interface HintResult {
|
|
48
|
-
/** The VM's residency when the hint arrived
|
|
48
|
+
/** The VM's residency when the hint arrived; null when the workspace was not running. */
|
|
49
49
|
residency: Residency | null;
|
|
50
50
|
/**
|
|
51
51
|
* The wake started in the background because the workspace was not running (409 `workspace_not_running`), else null.
|
|
@@ -65,7 +65,9 @@ export declare class Workspace {
|
|
|
65
65
|
/**
|
|
66
66
|
* Where the time went in the last lifecycle call made through this handle: open(), wake() (also when a tool call
|
|
67
67
|
* woke the workspace), or a lifecycle call with `wait`. Null for handles from get()/list() until such a call.
|
|
68
|
-
* `formatTiming(workspace.lastTiming)` prints it.
|
|
68
|
+
* `formatTiming(workspace.lastTiming)` prints it. After a resume or wake, `server.memoryRestored === false` (0.11.0+)
|
|
69
|
+
* means the workspace booted from its saved disk instead of restoring its memory (`server.resumePath` `cold_boot`,
|
|
70
|
+
* reason in `server.coldBootReason`): files are as of the suspend, running processes were restarted.
|
|
69
71
|
*/
|
|
70
72
|
get lastTiming(): LifecycleTiming | null;
|
|
71
73
|
get id(): string;
|
|
@@ -82,11 +84,11 @@ export declare class Workspace {
|
|
|
82
84
|
get template(): WorkspaceView['template'];
|
|
83
85
|
get pendingReason(): string | null;
|
|
84
86
|
get activeOperation(): WorkspaceView['active_operation'];
|
|
85
|
-
/** persistent or session
|
|
87
|
+
/** persistent or session; immutable. A view without the field (older API) is persistent. */
|
|
86
88
|
get lifetime(): WorkspaceLifetime;
|
|
87
|
-
/** standard, template_draft or template_test
|
|
89
|
+
/** standard, template_draft or template_test. */
|
|
88
90
|
get purpose(): WorkspacePurpose;
|
|
89
|
-
/** legacy or layered
|
|
91
|
+
/** legacy or layered; reset, save-as-template and changes need layered. */
|
|
90
92
|
get diskLayout(): DiskLayout;
|
|
91
93
|
/** Sessions: seconds without activity after which the session ends (null for persistent workspaces). */
|
|
92
94
|
get idleTimeoutSeconds(): number | null;
|
|
@@ -95,7 +97,7 @@ export declare class Workspace {
|
|
|
95
97
|
/** How a session ended (closed, idle_timeout, draft_discarded); null while live or for a plain delete. */
|
|
96
98
|
get endedReason(): WorkspaceView['ended_reason'];
|
|
97
99
|
/**
|
|
98
|
-
* Start commands and services of the workspace's template version (0.7.0
|
|
100
|
+
* Start commands and services of the workspace's template version (0.7.0): `state` pending, running,
|
|
99
101
|
* ready or failed (the failed step, its exit code, reason and output tail). Null when the version has neither, or on
|
|
100
102
|
* an older API. A failed startup leaves the workspace running for inspection; the next open runs the failed step again.
|
|
101
103
|
*/
|
|
@@ -109,7 +111,7 @@ export declare class Workspace {
|
|
|
109
111
|
/** The raw view (GET /v1/workspaces/{id}). */
|
|
110
112
|
get data(): WorkspaceView;
|
|
111
113
|
/**
|
|
112
|
-
* `processful` (one VM keeps processes, memory and files) or `file_first` (0.9.0
|
|
114
|
+
* `processful` (one VM keeps processes, memory and files) or `file_first` (0.9.0: a versioned file
|
|
113
115
|
* tree, commands run as executions). Immutable. A view without the field (older API) is processful.
|
|
114
116
|
*/
|
|
115
117
|
get mode(): WorkspaceMode;
|
|
@@ -121,7 +123,7 @@ export declare class Workspace {
|
|
|
121
123
|
*/
|
|
122
124
|
get treeRevision(): number | null;
|
|
123
125
|
/**
|
|
124
|
-
* Executions of this file-first workspace
|
|
126
|
+
* Executions of this file-first workspace through `cell()`'s default client: `run(argv, opts)` runs
|
|
125
127
|
* a command in a fresh VM on the latest tree and returns an ExecutionResult (output, exit code, `changed`,
|
|
126
128
|
* `treeRevision`); `get(id, { waitMs })` reads one. See CellClient.executions.
|
|
127
129
|
*
|
|
@@ -152,7 +154,7 @@ export declare class Workspace {
|
|
|
152
154
|
suspend(opts: WaitedLifecycleOptions): Promise<FinishedOperation>;
|
|
153
155
|
suspend(opts?: LifecycleOptions): Promise<Operation>;
|
|
154
156
|
/**
|
|
155
|
-
* Suspends the workspace once it has been idle for `afterSeconds` (
|
|
157
|
+
* Suspends the workspace once it has been idle for `afterSeconds` (0..3600, 0 = as soon as it is idle; 0.9.0): call it when your agent's turn
|
|
156
158
|
* ends, so the workspace stops using RAM soon after instead of waiting out its idle policy. A command still running,
|
|
157
159
|
* an attached stream or a keepalive postpones the suspend until `afterSeconds` after it ends; the next tool call (the
|
|
158
160
|
* next turn) or a resume cancels it. Resolves with the recorded `suspendRequest` (also `workspace.suspendRequest`), or
|
|
@@ -170,9 +172,11 @@ export declare class Workspace {
|
|
|
170
172
|
/**
|
|
171
173
|
* Resumes a suspended workspace. Resolves when the resume is REQUESTED; with `{ wait: true }`, once the workspace runs.
|
|
172
174
|
* Tool calls wake a suspended workspace by themselves, so this is rarely needed. With `wait` (0.9.0) it is one held
|
|
173
|
-
* request
|
|
175
|
+
* request: the handle takes the running view and a tool token for `agentLabel`/`tools` (defaults:
|
|
174
176
|
* those given to open()), so `cell()` calls with that label and tools start at once. A workspace that is already
|
|
175
|
-
* running is ShardfluxApiError 409 `conflict` (`already_running`).
|
|
177
|
+
* running is ShardfluxApiError 409 `conflict` (`already_running`). The finished operation's `result.memory_restored`
|
|
178
|
+
* (also `lastTiming.server.memoryRestored`, 0.11.0+) is false when the resume booted the saved disk instead
|
|
179
|
+
* (`resume_path` `cold_boot`): files kept, processes restarted.
|
|
176
180
|
*/
|
|
177
181
|
resume(opts: WaitedResumeOptions): Promise<FinishedOperation>;
|
|
178
182
|
resume(opts?: ResumeOptions): Promise<Operation>;
|
|
@@ -206,7 +210,7 @@ export declare class Workspace {
|
|
|
206
210
|
close(opts: WaitedLifecycleOptions): Promise<FinishedOperation | null>;
|
|
207
211
|
close(opts?: LifecycleOptions): Promise<Operation | null>;
|
|
208
212
|
/**
|
|
209
|
-
* Wipes every change in this layered workspace and restarts it on its template (
|
|
213
|
+
* Wipes every change in this layered workspace and restarts it on its template (sends
|
|
210
214
|
* confirm_destructive). Returns the `reset` operation: requested, or with `{ wait: true }` finished. Tool tokens of
|
|
211
215
|
* the old epoch are dropped.
|
|
212
216
|
*/
|
|
@@ -225,7 +229,7 @@ export declare class Workspace {
|
|
|
225
229
|
captureToolCalls(opts?: ToolCallCaptureOptions): ToolCallCapture;
|
|
226
230
|
/** Internal: waits for tool-call capture writes recorded so far (workspaceTools calls it before each tool). */
|
|
227
231
|
[CAPTURE_BARRIER](): Promise<void> | undefined;
|
|
228
|
-
/** Saves this layered workspace as the next version of an organization template
|
|
232
|
+
/** Saves this layered workspace as the next version of an organization template. */
|
|
229
233
|
saveAsTemplate(params: SaveAsTemplateParams): Promise<SaveAsTemplateResponse>;
|
|
230
234
|
/**
|
|
231
235
|
* The workspace's changes against its template (cell gateway GET /v1/workspaces/{id}/changes; needs the `files` tool).
|
|
@@ -251,26 +255,31 @@ export declare class Workspace {
|
|
|
251
255
|
tools?: ToolName[];
|
|
252
256
|
} & CellClientOptions): CellClient;
|
|
253
257
|
/**
|
|
254
|
-
* Makes a suspended (or suspending/resuming) workspace run again and resolves once it does
|
|
258
|
+
* Makes a suspended (or suspending/resuming) workspace run again and resolves once it does: resume,
|
|
255
259
|
* or join the active resume/open; an active suspend (or other operation) is waited out first. Resolves `true` when it
|
|
256
260
|
* resumed or waited for a lifecycle operation, `false` when the workspace was already running. One deadline
|
|
257
261
|
* (`timeoutMs`, default 120 000 ms) covers every step. Throws OperationFailedError when the resume/open fails,
|
|
258
262
|
* OperationTimeoutError (naming the operation, its state and reason) when it is still queued, running or
|
|
259
263
|
* capacity_pending at the deadline, and any other API error (a conflict other than already_running /
|
|
260
|
-
* operation_in_progress) at once. Cell calls use it automatically when they meet `workspace_not_running`. A
|
|
261
|
-
*
|
|
262
|
-
* stays suspended with its state;
|
|
264
|
+
* operation_in_progress) at once. Cell calls use it automatically when they meet `workspace_not_running`. A queued
|
|
265
|
+
* resume has a deadline 15 minutes after it was created; past it, it fails with `capacity_unavailable`
|
|
266
|
+
* (OperationFailedError, `retryable`: nothing was started and the workspace stays suspended with its state; send it
|
|
267
|
+
* again).
|
|
263
268
|
*
|
|
264
|
-
* Since 0.9.0 the resume is held by the server until the workspace runs
|
|
269
|
+
* Since 0.9.0 the resume is held by the server until the workspace runs: one request returns the
|
|
265
270
|
* running workspace and a tool token for `agentLabel`/`tools`, which this handle keeps, so a tool call that woke the
|
|
266
271
|
* workspace is retried at once (refused call, resume, call). Timing: one `request` phase with reason `held`. A server
|
|
267
272
|
* that does not hold the request answers at once; the wake then waits for the operation and reads the view.
|
|
273
|
+
*
|
|
274
|
+
* A wake whose resume could not restore the workspace's memory (0.11.0+; the platform's VM runtime changed after the
|
|
275
|
+
* suspend) still resolves `true`: the workspace runs from its saved disk, with every process restarted. `lastTiming`
|
|
276
|
+
* and the `done` progress event say so (`server.memoryRestored === false`, `server.resumePath` `cold_boot`).
|
|
268
277
|
*/
|
|
269
278
|
wake(opts?: WakeOptions): Promise<boolean>;
|
|
270
279
|
/**
|
|
271
|
-
* Announces an imminent tool call (cell `POST /wake-hint
|
|
280
|
+
* Announces an imminent tool call (cell `POST /wake-hint`; 0.9.0+) so a parked workspace is restored
|
|
272
281
|
* ahead of it: call it when the model starts emitting a tool call, before its arguments are complete. The agent tools
|
|
273
|
-
* of `workspaceTools()` send it when a call starts. Cheap and
|
|
282
|
+
* of `workspaceTools()` send it when a call starts. Cheap and non-blocking: it returns what the host found. A workspace
|
|
274
283
|
* that is not running (suspended, or a token cannot be issued for it) is woken in the background (`wake`, not awaited
|
|
275
284
|
* here) so the call finds it running sooner. Other errors (network, auth) are thrown; callers that fire and forget
|
|
276
285
|
* should catch them.
|
package/dist/workspace.js
CHANGED
|
@@ -33,7 +33,7 @@ export class Workspace {
|
|
|
33
33
|
if (this.#treeRevision === null || rev > this.#treeRevision)
|
|
34
34
|
this.#treeRevision = rev;
|
|
35
35
|
}
|
|
36
|
-
/** The local refusal of a lifecycle call a file-first workspace does not have
|
|
36
|
+
/** The local refusal of a lifecycle call a file-first workspace does not have. */
|
|
37
37
|
#needsVm(operation) {
|
|
38
38
|
if (this.#view.mode !== 'file_first')
|
|
39
39
|
return null;
|
|
@@ -42,7 +42,9 @@ export class Workspace {
|
|
|
42
42
|
/**
|
|
43
43
|
* Where the time went in the last lifecycle call made through this handle: open(), wake() (also when a tool call
|
|
44
44
|
* woke the workspace), or a lifecycle call with `wait`. Null for handles from get()/list() until such a call.
|
|
45
|
-
* `formatTiming(workspace.lastTiming)` prints it.
|
|
45
|
+
* `formatTiming(workspace.lastTiming)` prints it. After a resume or wake, `server.memoryRestored === false` (0.11.0+)
|
|
46
|
+
* means the workspace booted from its saved disk instead of restoring its memory (`server.resumePath` `cold_boot`,
|
|
47
|
+
* reason in `server.coldBootReason`): files are as of the suspend, running processes were restarted.
|
|
46
48
|
*/
|
|
47
49
|
get lastTiming() {
|
|
48
50
|
return this.#lastTiming ?? this.#openTrace?.finished ?? null;
|
|
@@ -100,15 +102,15 @@ export class Workspace {
|
|
|
100
102
|
get activeOperation() {
|
|
101
103
|
return this.#view.active_operation;
|
|
102
104
|
}
|
|
103
|
-
/** persistent or session
|
|
105
|
+
/** persistent or session; immutable. A view without the field (older API) is persistent. */
|
|
104
106
|
get lifetime() {
|
|
105
107
|
return this.#view.lifetime ?? 'persistent';
|
|
106
108
|
}
|
|
107
|
-
/** standard, template_draft or template_test
|
|
109
|
+
/** standard, template_draft or template_test. */
|
|
108
110
|
get purpose() {
|
|
109
111
|
return this.#view.purpose ?? 'standard';
|
|
110
112
|
}
|
|
111
|
-
/** legacy or layered
|
|
113
|
+
/** legacy or layered; reset, save-as-template and changes need layered. */
|
|
112
114
|
get diskLayout() {
|
|
113
115
|
return this.#view.disk_layout ?? 'legacy';
|
|
114
116
|
}
|
|
@@ -125,7 +127,7 @@ export class Workspace {
|
|
|
125
127
|
return this.#view.ended_reason ?? null;
|
|
126
128
|
}
|
|
127
129
|
/**
|
|
128
|
-
* Start commands and services of the workspace's template version (0.7.0
|
|
130
|
+
* Start commands and services of the workspace's template version (0.7.0): `state` pending, running,
|
|
129
131
|
* ready or failed (the failed step, its exit code, reason and output tail). Null when the version has neither, or on
|
|
130
132
|
* an older API. A failed startup leaves the workspace running for inspection; the next open runs the failed step again.
|
|
131
133
|
*/
|
|
@@ -145,7 +147,7 @@ export class Workspace {
|
|
|
145
147
|
return this.#view;
|
|
146
148
|
}
|
|
147
149
|
/**
|
|
148
|
-
* `processful` (one VM keeps processes, memory and files) or `file_first` (0.9.0
|
|
150
|
+
* `processful` (one VM keeps processes, memory and files) or `file_first` (0.9.0: a versioned file
|
|
149
151
|
* tree, commands run as executions). Immutable. A view without the field (older API) is processful.
|
|
150
152
|
*/
|
|
151
153
|
get mode() {
|
|
@@ -161,7 +163,7 @@ export class Workspace {
|
|
|
161
163
|
return this.mode === 'file_first' ? this.#treeRevision : null;
|
|
162
164
|
}
|
|
163
165
|
/**
|
|
164
|
-
* Executions of this file-first workspace
|
|
166
|
+
* Executions of this file-first workspace through `cell()`'s default client: `run(argv, opts)` runs
|
|
165
167
|
* a command in a fresh VM on the latest tree and returns an ExecutionResult (output, exit code, `changed`,
|
|
166
168
|
* `treeRevision`); `get(id, { waitMs })` reads one. See CellClient.executions.
|
|
167
169
|
*
|
|
@@ -202,7 +204,7 @@ export class Workspace {
|
|
|
202
204
|
return this.#ctx.workspaces.suspend(this.id, { ...this.#tracked(opts), [AFTER_WAIT]: this.#refreshAfterWait() });
|
|
203
205
|
}
|
|
204
206
|
/**
|
|
205
|
-
* Suspends the workspace once it has been idle for `afterSeconds` (
|
|
207
|
+
* Suspends the workspace once it has been idle for `afterSeconds` (0..3600, 0 = as soon as it is idle; 0.9.0): call it when your agent's turn
|
|
206
208
|
* ends, so the workspace stops using RAM soon after instead of waiting out its idle policy. A command still running,
|
|
207
209
|
* an attached stream or a keepalive postpones the suspend until `afterSeconds` after it ends; the next tool call (the
|
|
208
210
|
* next turn) or a resume cancels it. Resolves with the recorded `suspendRequest` (also `workspace.suspendRequest`), or
|
|
@@ -235,7 +237,7 @@ export class Workspace {
|
|
|
235
237
|
const manager = this.tokens({ ...(opts.agentLabel !== undefined ? { agentLabel: opts.agentLabel } : {}), ...(opts.tools !== undefined ? { tools: opts.tools } : {}) });
|
|
236
238
|
return this.#ctx.workspaces.resume(this.id, { ...this.#tracked(opts), [AFTER_WAIT]: this.#refreshAfterWait(), [HELD_RESUME]: this.#heldTarget(manager) });
|
|
237
239
|
}
|
|
238
|
-
/** A held resume's 200
|
|
240
|
+
/** A held resume's 200 goes straight into this handle: the view, and the token for `manager`. */
|
|
239
241
|
#heldTarget(manager) {
|
|
240
242
|
return {
|
|
241
243
|
agentLabel: manager.agentLabel,
|
|
@@ -313,7 +315,7 @@ export class Workspace {
|
|
|
313
315
|
[CAPTURE_BARRIER]() {
|
|
314
316
|
return this.#ctx.captures.settle(this.id);
|
|
315
317
|
}
|
|
316
|
-
/** Saves this layered workspace as the next version of an organization template
|
|
318
|
+
/** Saves this layered workspace as the next version of an organization template. */
|
|
317
319
|
saveAsTemplate(params) {
|
|
318
320
|
const refusal = this.#needsVm('save_as_template');
|
|
319
321
|
if (refusal)
|
|
@@ -376,23 +378,28 @@ export class Workspace {
|
|
|
376
378
|
return c;
|
|
377
379
|
}
|
|
378
380
|
/**
|
|
379
|
-
* Makes a suspended (or suspending/resuming) workspace run again and resolves once it does
|
|
381
|
+
* Makes a suspended (or suspending/resuming) workspace run again and resolves once it does: resume,
|
|
380
382
|
* or join the active resume/open; an active suspend (or other operation) is waited out first. Resolves `true` when it
|
|
381
383
|
* resumed or waited for a lifecycle operation, `false` when the workspace was already running. One deadline
|
|
382
384
|
* (`timeoutMs`, default 120 000 ms) covers every step. Throws OperationFailedError when the resume/open fails,
|
|
383
385
|
* OperationTimeoutError (naming the operation, its state and reason) when it is still queued, running or
|
|
384
386
|
* capacity_pending at the deadline, and any other API error (a conflict other than already_running /
|
|
385
|
-
* operation_in_progress) at once. Cell calls use it automatically when they meet `workspace_not_running`. A
|
|
386
|
-
*
|
|
387
|
-
* stays suspended with its state;
|
|
387
|
+
* operation_in_progress) at once. Cell calls use it automatically when they meet `workspace_not_running`. A queued
|
|
388
|
+
* resume has a deadline 15 minutes after it was created; past it, it fails with `capacity_unavailable`
|
|
389
|
+
* (OperationFailedError, `retryable`: nothing was started and the workspace stays suspended with its state; send it
|
|
390
|
+
* again).
|
|
388
391
|
*
|
|
389
|
-
* Since 0.9.0 the resume is held by the server until the workspace runs
|
|
392
|
+
* Since 0.9.0 the resume is held by the server until the workspace runs: one request returns the
|
|
390
393
|
* running workspace and a tool token for `agentLabel`/`tools`, which this handle keeps, so a tool call that woke the
|
|
391
394
|
* workspace is retried at once (refused call, resume, call). Timing: one `request` phase with reason `held`. A server
|
|
392
395
|
* that does not hold the request answers at once; the wake then waits for the operation and reads the view.
|
|
396
|
+
*
|
|
397
|
+
* A wake whose resume could not restore the workspace's memory (0.11.0+; the platform's VM runtime changed after the
|
|
398
|
+
* suspend) still resolves `true`: the workspace runs from its saved disk, with every process restarted. `lastTiming`
|
|
399
|
+
* and the `done` progress event say so (`server.memoryRestored === false`, `server.resumePath` `cold_boot`).
|
|
393
400
|
*/
|
|
394
401
|
async wake(opts = {}) {
|
|
395
|
-
// A file-first workspace runs from creation and is never suspended
|
|
402
|
+
// A file-first workspace runs from creation and is never suspended: nothing to wake.
|
|
396
403
|
if (this.#view.mode === 'file_first')
|
|
397
404
|
return false;
|
|
398
405
|
const trace = new Trace('wake', combineListeners(this.#ctx.onProgress, this.#tracked(opts).onProgress), { workspaceId: this.id });
|
|
@@ -409,7 +416,7 @@ export class Workspace {
|
|
|
409
416
|
throw opts.signal.reason;
|
|
410
417
|
let active;
|
|
411
418
|
try {
|
|
412
|
-
// Held resume
|
|
419
|
+
// Held resume: answered once the workspace runs, with the view and a token; it returns the
|
|
413
420
|
// active resume/open when there is one, so concurrent wakes join a single operation. The request is made here
|
|
414
421
|
// rather than through resume() so the wake is one trace.
|
|
415
422
|
const waitS = Math.min(SERVER_WAIT_MAX_S, Math.floor((deadline - Date.now()) / 1000));
|
|
@@ -467,9 +474,9 @@ export class Workspace {
|
|
|
467
474
|
throw new Error(`workspace ${this.id} did not become runnable after repeated lifecycle conflicts`);
|
|
468
475
|
}
|
|
469
476
|
/**
|
|
470
|
-
* Announces an imminent tool call (cell `POST /wake-hint
|
|
477
|
+
* Announces an imminent tool call (cell `POST /wake-hint`; 0.9.0+) so a parked workspace is restored
|
|
471
478
|
* ahead of it: call it when the model starts emitting a tool call, before its arguments are complete. The agent tools
|
|
472
|
-
* of `workspaceTools()` send it when a call starts. Cheap and
|
|
479
|
+
* of `workspaceTools()` send it when a call starts. Cheap and non-blocking: it returns what the host found. A workspace
|
|
473
480
|
* that is not running (suspended, or a token cannot be issued for it) is woken in the background (`wake`, not awaited
|
|
474
481
|
* here) so the call finds it running sooner. Other errors (network, auth) are thrown; callers that fire and forget
|
|
475
482
|
* should catch them.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shardflux/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
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",
|