@shardflux/sdk 0.6.2 → 0.7.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.
@@ -3,13 +3,15 @@
3
3
  * tool tokens and cell clients (one per agent label / tool set).
4
4
  */
5
5
  import type { ClientContext, DiskLayout, ForkTarget, Operation, WaitOptions, WorkspaceLifetime, WorkspaceOrigin, WorkspacePurpose, WorkspaceView } from './client.js';
6
- import { CellClient } from './cell.js';
6
+ import { CAPTURE_BARRIER, CellClient } from './cell.js';
7
+ import { ToolCallCapture } from './capture.js';
8
+ import type { ToolCallCaptureOptions } from './capture.js';
7
9
  import type { FinishedOperation, LifecycleOptions, WaitedLifecycleOptions } from './lifecycle.js';
8
10
  import { Trace } from './progress.js';
9
11
  import type { LifecycleTiming, ProgressListener } from './progress.js';
10
12
  import { WorkspaceSecrets } from './secrets.js';
11
13
  import type { CellClientOptions, WorkspaceChangesPage, WorkspaceChangesParams } from './cell.js';
12
- import type { SaveAsTemplateParams, SaveAsTemplateResponse } from './templates.js';
14
+ import type { SaveAsTemplateParams, SaveAsTemplateResponse, WorkspaceStartup } from './templates.js';
13
15
  import { ToolTokenManager } from './tokens.js';
14
16
  import type { ToolName, ToolToken } from './tokens.js';
15
17
  export interface WakeOptions {
@@ -59,10 +61,18 @@ export declare class Workspace {
59
61
  get origin(): WorkspaceOrigin | null;
60
62
  /** How a session ended (closed, idle_timeout, draft_discarded); null while live or for a plain delete. */
61
63
  get endedReason(): WorkspaceView['ended_reason'];
64
+ /**
65
+ * Start commands and services of the workspace's template version (0.7.0; contracts §24.4): `state` pending, running,
66
+ * ready or failed (the failed step, its exit code, reason and output tail). Null when the version has neither, or on
67
+ * an older API. A failed startup leaves the workspace running for inspection; the next open runs the failed step again.
68
+ */
69
+ get startup(): WorkspaceStartup | null;
62
70
  /** The raw view (GET /v1/workspaces/{id}). */
63
71
  get data(): WorkspaceView;
64
72
  /** Secret names bound to this workspace (injected into every exec/PTY start): `get()`, `set(names)`. */
65
73
  get secrets(): WorkspaceSecrets;
74
+ /** The workspace's text inputs `{NAME: value}` (0.7.0; secret inputs are bound secrets, never listed here). */
75
+ inputs(): Promise<Record<string, string>>;
66
76
  refresh(): Promise<this>;
67
77
  /** Waits for the active operation (if any) and refreshes. */
68
78
  waitUntilReady(opts?: WaitOptions): Promise<this>;
@@ -123,6 +133,19 @@ export declare class Workspace {
123
133
  */
124
134
  reset(opts: WaitedLifecycleOptions): Promise<FinishedOperation>;
125
135
  reset(opts?: LifecycleOptions): Promise<Operation>;
136
+ /**
137
+ * Captures the tool calls of your agent harness into this workspace (docs/decisions/0006-tool-call-capture.md): each
138
+ * call's input and full output become files under `dir` (default `/home/user/tool-calls/<run>/`), so the agent can
139
+ * work on them with code, and they are in snapshots and forks. Wrapped tools return exactly what they returned before;
140
+ * capture never throws into the harness. Shardflux calls through this client (exec, files, workspaceTools, snapshot,
141
+ * fork, suspend, close, saveAsTemplate) first wait for writes recorded before them; delete and reset drop them.
142
+ *
143
+ * const capture = workspace.captureToolCalls();
144
+ * const out = await capture.run(block, () => myTools[block.name](block.input));
145
+ */
146
+ captureToolCalls(opts?: ToolCallCaptureOptions): ToolCallCapture;
147
+ /** Internal: waits for tool-call capture writes recorded so far (workspaceTools calls it before each tool). */
148
+ [CAPTURE_BARRIER](): Promise<void> | undefined;
126
149
  /** Saves this layered workspace as the next version of an organization template (contracts §19.8). */
127
150
  saveAsTemplate(params: SaveAsTemplateParams): Promise<SaveAsTemplateResponse>;
128
151
  /**
package/dist/workspace.js CHANGED
@@ -1,6 +1,7 @@
1
- import { CellClient, DEFAULT_TRANSITION_TIMEOUT_MS } from "./cell.js";
1
+ import { CAPTURE_BARRIER, CellClient, DEFAULT_TRANSITION_TIMEOUT_MS } from "./cell.js";
2
+ import { ToolCallCapture } from "./capture.js";
2
3
  import { OperationFailedError, ShardfluxApiError } from "./errors.js";
3
- import { randomId } from "./http.js";
4
+ import { defaultSleep, randomId } from "./http.js";
4
5
  import { AFTER_WAIT, TRACE } from "./lifecycle.js";
5
6
  import { Trace, combineListeners, traced } from "./progress.js";
6
7
  import { WorkspaceSecrets } from "./secrets.js";
@@ -107,6 +108,14 @@ export class Workspace {
107
108
  get endedReason() {
108
109
  return this.#view.ended_reason ?? null;
109
110
  }
111
+ /**
112
+ * Start commands and services of the workspace's template version (0.7.0; contracts §24.4): `state` pending, running,
113
+ * ready or failed (the failed step, its exit code, reason and output tail). Null when the version has neither, or on
114
+ * an older API. A failed startup leaves the workspace running for inspection; the next open runs the failed step again.
115
+ */
116
+ get startup() {
117
+ return this.#view.startup ?? null;
118
+ }
110
119
  /** The raw view (GET /v1/workspaces/{id}). */
111
120
  get data() {
112
121
  return this.#view;
@@ -115,6 +124,10 @@ export class Workspace {
115
124
  get secrets() {
116
125
  return new WorkspaceSecrets(this.#ctx, this.id);
117
126
  }
127
+ /** The workspace's text inputs `{NAME: value}` (0.7.0; secret inputs are bound secrets, never listed here). */
128
+ inputs() {
129
+ return this.#ctx.workspaces.inputs(this.id);
130
+ }
118
131
  async refresh() {
119
132
  this.#view = await this.#ctx.http.json('GET', `/v1/workspaces/${encodeURIComponent(this.id)}`, {}, this.#ctx.authorization);
120
133
  return this;
@@ -142,6 +155,8 @@ export class Workspace {
142
155
  return this.#ctx.workspaces.fork(this.id, target, this.#tracked(opts));
143
156
  }
144
157
  async close(opts = {}) {
158
+ // Closing aborts in-flight cell requests: tool-call capture writes recorded before it are flushed first (bounded).
159
+ await this.#ctx.captures.settle(this.id);
145
160
  for (const c of this.#cells.values())
146
161
  c.close();
147
162
  this.#cells.clear();
@@ -159,6 +174,37 @@ export class Workspace {
159
174
  m.invalidate();
160
175
  return op;
161
176
  }
177
+ /**
178
+ * Captures the tool calls of your agent harness into this workspace (docs/decisions/0006-tool-call-capture.md): each
179
+ * call's input and full output become files under `dir` (default `/home/user/tool-calls/<run>/`), so the agent can
180
+ * work on them with code, and they are in snapshots and forks. Wrapped tools return exactly what they returned before;
181
+ * capture never throws into the harness. Shardflux calls through this client (exec, files, workspaceTools, snapshot,
182
+ * fork, suspend, close, saveAsTemplate) first wait for writes recorded before them; delete and reset drop them.
183
+ *
184
+ * const capture = workspace.captureToolCalls();
185
+ * const out = await capture.run(block, () => myTools[block.name](block.input));
186
+ */
187
+ captureToolCalls(opts = {}) {
188
+ const defaults = this.#defaults.tools;
189
+ const tools = defaults && !defaults.includes('files') ? [...defaults, 'files'] : defaults;
190
+ const agentLabel = opts.agentLabel ?? this.#defaults.agentLabel;
191
+ const manager = this.tokens({ ...(agentLabel !== undefined ? { agentLabel } : {}), ...(tools !== undefined ? { tools } : {}) });
192
+ // The capture's own client: not in #cells (close() flushes it before aborting those) and without the barrier.
193
+ const cell = new CellClient(this.id, manager, {
194
+ fetch: this.#ctx.fetch,
195
+ userAgent: this.#ctx.userAgent,
196
+ sleep: this.#ctx.sleep,
197
+ maxRetries: 0,
198
+ ...(opts.transitionTimeoutMs !== undefined ? { transitionTimeoutMs: opts.transitionTimeoutMs } : {}),
199
+ ...(this.#ctx.onProgress ? { onProgress: this.#ctx.onProgress } : {}),
200
+ wake: opts.wake === undefined ? (timeoutMs, signal) => this.wake({ timeoutMs, ...(signal ? { signal } : {}) }) : opts.wake,
201
+ });
202
+ return new ToolCallCapture({ workspaceId: this.id, cell, registry: this.#ctx.captures, ...(this.#ctx.sleep !== defaultSleep ? { sleep: this.#ctx.sleep } : {}) }, opts);
203
+ }
204
+ /** Internal: waits for tool-call capture writes recorded so far (workspaceTools calls it before each tool). */
205
+ [CAPTURE_BARRIER]() {
206
+ return this.#ctx.captures.settle(this.id);
207
+ }
162
208
  /** Saves this layered workspace as the next version of an organization template (contracts §19.8). */
163
209
  saveAsTemplate(params) {
164
210
  return this.#ctx.workspaces.saveAsTemplate(this.id, params);
@@ -205,6 +251,7 @@ export class Workspace {
205
251
  ...cellOpts,
206
252
  ...(listener ? { onProgress: listener } : {}),
207
253
  wake: wake === undefined ? (timeoutMs, signal) => this.wake({ timeoutMs, ...(signal ? { signal } : {}), ...(onProgress ? { onProgress } : {}) }) : wake,
254
+ [CAPTURE_BARRIER]: () => this.#ctx.captures.settle(this.id),
208
255
  });
209
256
  this.#cells.set(k, c);
210
257
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shardflux/sdk",
3
- "version": "0.6.2",
3
+ "version": "0.7.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",
@@ -36,13 +36,35 @@
36
36
  "publishConfig": {
37
37
  "access": "public"
38
38
  },
39
+ "peerDependencies": {
40
+ "yaml": "^2.4.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "yaml": {
44
+ "optional": true
45
+ }
46
+ },
39
47
  "devDependencies": {
48
+ "@ai-sdk/provider": "4.0.18",
49
+ "@anthropic-ai/claude-agent-sdk": "0.3.283",
50
+ "@anthropic-ai/sdk": "0.128.0",
40
51
  "@eslint/js": "10.0.1",
52
+ "@langchain/core": "1.2.13",
53
+ "@langchain/langgraph": "1.4.18",
54
+ "@mastra/core": "1.71.0",
55
+ "@modelcontextprotocol/client": "2.1.0",
56
+ "@modelcontextprotocol/sdk": "1.30.0",
57
+ "@openai/agents-core": "0.18.0",
41
58
  "@types/node": "24.13.6",
59
+ "ai": "7.0.118",
60
+ "ajv": "8.20.0",
42
61
  "eslint": "10.11.0",
62
+ "langchain": "1.5.14",
43
63
  "openapi-typescript": "7.13.0",
44
64
  "typescript": "5.9.3",
45
- "typescript-eslint": "8.70.1"
65
+ "typescript-eslint": "8.70.1",
66
+ "yaml": "2.9.1",
67
+ "zod": "4.6.5"
46
68
  },
47
69
  "scripts": {
48
70
  "build": "node scripts/build.mjs",