@code-harness/sdk 0.1.0 → 0.1.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/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Client } from './client.js';
1
+ import type { BaseClient } from './core/client.js';
2
2
  export interface WaitFor {
3
3
  selector?: string;
4
4
  text?: string;
@@ -32,7 +32,7 @@ export declare class Browser {
32
32
  #private;
33
33
  readonly sandboxId: string | null;
34
34
  readonly record: boolean;
35
- constructor(client: Client, { id, sandboxId, record }: {
35
+ constructor(client: BaseClient, { id, sandboxId, record }: {
36
36
  id: string | null;
37
37
  sandboxId: string | null;
38
38
  record: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { BaseClient } from './core/client.js';
2
+ export interface WaitFor {
3
+ selector?: string;
4
+ text?: string;
5
+ timeoutMs?: number;
6
+ }
7
+ export interface PageRef {
8
+ ref: number;
9
+ tag: string;
10
+ role: string | null;
11
+ name: string;
12
+ value: string;
13
+ placeholder: string;
14
+ href: string;
15
+ }
16
+ export interface Page {
17
+ title: string;
18
+ url: string;
19
+ text: string;
20
+ refs: PageRef[];
21
+ }
22
+ export interface NavigatedPage extends Page {
23
+ status: number | null;
24
+ error: string | null;
25
+ }
26
+ export interface RunResult {
27
+ result: unknown;
28
+ error: string | null;
29
+ durationMs: number;
30
+ }
31
+ export declare class Browser {
32
+ #private;
33
+ readonly sandboxId: string | null;
34
+ readonly record: boolean;
35
+ constructor(client: BaseClient, { id, sandboxId, record }: {
36
+ id: string | null;
37
+ sandboxId: string | null;
38
+ record: boolean;
39
+ });
40
+ get id(): string | null;
41
+ navigate(url: string, options?: {
42
+ until?: WaitFor;
43
+ }): Promise<NavigatedPage>;
44
+ read(options?: {
45
+ maxChars?: number;
46
+ waitFor?: WaitFor;
47
+ }): Promise<Page>;
48
+ click(ref: number, options?: {
49
+ waitFor?: WaitFor;
50
+ }): Promise<Page>;
51
+ type(ref: number, text: string, options?: {
52
+ submit?: boolean;
53
+ waitFor?: WaitFor;
54
+ }): Promise<Page>;
55
+ screenshot(options?: {
56
+ fullPage?: boolean;
57
+ waitFor?: WaitFor;
58
+ }): Promise<{
59
+ path: string;
60
+ }>;
61
+ run(code: string, options?: {
62
+ timeoutMs?: number;
63
+ }): Promise<RunResult>;
64
+ close(): Promise<void>;
65
+ }
@@ -0,0 +1,27 @@
1
+ import { Browser } from '../browser.js';
2
+ import { Sandbox, type SandboxOptions } from './sandbox.js';
3
+ export interface ClientOptions {
4
+ baseUrl?: string;
5
+ token?: string;
6
+ fetch?: typeof fetch;
7
+ }
8
+ export interface CreateSandboxOptions extends SandboxOptions {
9
+ name?: string;
10
+ env?: Record<string, string>;
11
+ }
12
+ export declare class BaseClient {
13
+ #private;
14
+ readonly baseUrl: string;
15
+ constructor(options?: ClientOptions);
16
+ me(): Promise<{
17
+ id: string;
18
+ email: string;
19
+ }>;
20
+ createBrowser(): Promise<Browser>;
21
+ getBrowser(id: string): Browser;
22
+ request(method: string, path: string, body?: unknown): Promise<Response>;
23
+ }
24
+ export declare class Client extends BaseClient {
25
+ createSandbox({ name, env, ...options }?: CreateSandboxOptions): Promise<Sandbox>;
26
+ getSandbox(id: string, options?: SandboxOptions): Promise<Sandbox>;
27
+ }
@@ -0,0 +1,4 @@
1
+ export { Browser, type NavigatedPage, type Page, type PageRef, type RunResult, type WaitFor } from '../browser.js';
2
+ export { CodeHarnessError, type CodeHarnessErrorCode } from '../errors.js';
3
+ export { Client, type ClientOptions, type CreateSandboxOptions } from './client.js';
4
+ export { Sandbox, type ExecuteResponse, type FileDownloadResponse, type FileOperationError, type FileUploadResponse, type LaunchOptions, type SandboxOptions, } from './sandbox.js';
@@ -0,0 +1,304 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ function __accessProp(key) {
6
+ return this[key];
7
+ }
8
+ var __toCommonJS = (from) => {
9
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
10
+ if (entry)
11
+ return entry;
12
+ entry = __defProp({}, "__esModule", { value: true });
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (var key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(entry, key))
16
+ __defProp(entry, key, {
17
+ get: __accessProp.bind(from, key),
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
21
+ __moduleCache.set(from, entry);
22
+ return entry;
23
+ };
24
+ var __moduleCache;
25
+ var __returnValue = (v) => v;
26
+ function __exportSetter(name, newValue) {
27
+ this[name] = __returnValue.bind(null, newValue);
28
+ }
29
+ var __export = (target, all) => {
30
+ for (var name in all)
31
+ __defProp(target, name, {
32
+ get: all[name],
33
+ enumerable: true,
34
+ configurable: true,
35
+ set: __exportSetter.bind(all, name)
36
+ });
37
+ };
38
+
39
+ // src/core/index.ts
40
+ var exports_core = {};
41
+ __export(exports_core, {
42
+ Browser: () => Browser,
43
+ Client: () => Client,
44
+ CodeHarnessError: () => CodeHarnessError,
45
+ Sandbox: () => Sandbox
46
+ });
47
+ module.exports = __toCommonJS(exports_core);
48
+
49
+ // src/errors.ts
50
+ var CODES = {
51
+ 400: "INVALID_REQUEST",
52
+ 401: "AUTHENTICATION_FAILED",
53
+ 404: "NOT_FOUND",
54
+ 409: "CONFLICT",
55
+ 413: "TOO_LARGE",
56
+ 429: "RATE_LIMITED",
57
+ 502: "UPSTREAM_FAILED",
58
+ 504: "TIMEOUT"
59
+ };
60
+ var SANDBOX_ERROR = Symbol.for("sandbox.error");
61
+
62
+ class CodeHarnessError extends Error {
63
+ code;
64
+ status;
65
+ name = "CodeHarnessError";
66
+ constructor(message, code, status = null, cause) {
67
+ super(message, { cause });
68
+ this.code = code;
69
+ this.status = status;
70
+ Object.defineProperty(this, SANDBOX_ERROR, { value: true });
71
+ }
72
+ static async fromResponse(response) {
73
+ const body = await response.json().catch(() => null);
74
+ const message = body?.message ?? body?.error ?? response.statusText;
75
+ return new CodeHarnessError(message, CODES[response.status] ?? "UNKNOWN", response.status);
76
+ }
77
+ }
78
+
79
+ // src/browser.ts
80
+ class Browser {
81
+ sandboxId;
82
+ record;
83
+ #client;
84
+ #id;
85
+ #creating = null;
86
+ constructor(client, { id, sandboxId, record }) {
87
+ this.#client = client;
88
+ this.#id = id;
89
+ this.sandboxId = sandboxId;
90
+ this.record = record;
91
+ }
92
+ get id() {
93
+ return this.#id;
94
+ }
95
+ navigate(url, options = {}) {
96
+ return this.#call("navigate", { url, ...options });
97
+ }
98
+ read(options = {}) {
99
+ return this.#call("read", options);
100
+ }
101
+ click(ref, options = {}) {
102
+ return this.#call("click", { ref, ...options });
103
+ }
104
+ type(ref, text, options = {}) {
105
+ return this.#call("type", { ref, text, ...options });
106
+ }
107
+ screenshot(options = {}) {
108
+ return this.#call("screenshot", options);
109
+ }
110
+ run(code, options = {}) {
111
+ return this.#call("run", { code, ...options });
112
+ }
113
+ async close() {
114
+ if (!this.#id)
115
+ return;
116
+ await this.#client.request("DELETE", `/browser/${this.#id}`).catch((err) => {
117
+ if (!(err instanceof CodeHarnessError && err.code === "NOT_FOUND"))
118
+ throw err;
119
+ });
120
+ }
121
+ async#call(action, body) {
122
+ const id = await this.#sessionId();
123
+ return (await this.#client.request("POST", `/browser/${id}/${action}`, body)).json();
124
+ }
125
+ async#sessionId() {
126
+ if (this.#id)
127
+ return this.#id;
128
+ this.#creating ??= this.#client.request("POST", "/browser", { workspaceId: this.sandboxId, record: this.record }).then((response) => response.json()).then((session) => this.#id = session.id).finally(() => this.#creating = null);
129
+ return this.#creating;
130
+ }
131
+ }
132
+ // src/core/sandbox.ts
133
+ var ROOT = "/workspace";
134
+ var DEFAULT_TIMEOUT_MS = 120000;
135
+ var UTF8 = new TextDecoder("utf-8", { fatal: true });
136
+ var relativePath = (path) => {
137
+ if (path === ROOT)
138
+ return "";
139
+ return path.startsWith(`${ROOT}/`) ? path.slice(ROOT.length + 1) : path.startsWith("/") ? null : path;
140
+ };
141
+ var encodePath = (relative) => relative.split("/").map(encodeURIComponent).join("/");
142
+ var fileError = (err) => {
143
+ if (err instanceof CodeHarnessError && err.code === "NOT_FOUND")
144
+ return "file_not_found";
145
+ if (err instanceof CodeHarnessError && err.code === "INVALID_REQUEST")
146
+ return "invalid_path";
147
+ throw err;
148
+ };
149
+
150
+ class Sandbox {
151
+ id;
152
+ name;
153
+ envKeys;
154
+ createdAt;
155
+ browser;
156
+ #client;
157
+ #timeoutMs;
158
+ constructor(client, workspace, { timeoutMs = DEFAULT_TIMEOUT_MS, record = false } = {}) {
159
+ this.#client = client;
160
+ this.#timeoutMs = timeoutMs;
161
+ this.id = workspace.id;
162
+ this.name = workspace.name;
163
+ this.envKeys = workspace.defaultEnvKeys;
164
+ this.createdAt = new Date(workspace.createdAt);
165
+ this.browser = new Browser(client, { id: null, sandboxId: workspace.id, record });
166
+ }
167
+ async execute(command) {
168
+ const response = await this.#client.request("POST", `/workspaces/${this.id}/sandbox/exec`, {
169
+ command,
170
+ timeoutMs: this.#timeoutMs
171
+ });
172
+ const result = await response.json();
173
+ return {
174
+ output: result.timedOut ? `${result.output}
175
+ timed out after ${this.#timeoutMs} ms` : result.output,
176
+ exitCode: result.exitCode,
177
+ truncated: false
178
+ };
179
+ }
180
+ async uploadFiles(files) {
181
+ const results = [];
182
+ for (const [path, bytes] of files) {
183
+ const relative = relativePath(path);
184
+ if (!relative) {
185
+ results.push({ path, error: "invalid_path" });
186
+ continue;
187
+ }
188
+ let content;
189
+ try {
190
+ content = UTF8.decode(bytes);
191
+ } catch {
192
+ results.push({ path, error: "invalid_path" });
193
+ continue;
194
+ }
195
+ const error = await this.#client.request("PUT", `/workspaces/${this.id}/files/${encodePath(relative)}`, { content }).then(() => null, fileError);
196
+ results.push({ path, error });
197
+ }
198
+ return results;
199
+ }
200
+ async downloadFiles(paths) {
201
+ const results = [];
202
+ for (const path of paths) {
203
+ const relative = relativePath(path);
204
+ if (!relative) {
205
+ results.push({ path, content: null, error: "invalid_path" });
206
+ continue;
207
+ }
208
+ try {
209
+ const response = await this.#client.request("GET", `/workspaces/${this.id}/files/${encodePath(relative)}?raw=true`);
210
+ results.push({ path, content: new Uint8Array(await response.arrayBuffer()), error: null });
211
+ } catch (err) {
212
+ results.push({ path, content: null, error: fileError(err) });
213
+ }
214
+ }
215
+ return results;
216
+ }
217
+ async uploadAsZip(zip, { path = "" } = {}) {
218
+ const relative = relativePath(path);
219
+ if (relative === null)
220
+ throw new CodeHarnessError(`${path} is outside ${ROOT}`, "INVALID_REQUEST");
221
+ const form = new FormData;
222
+ form.append("path", relative);
223
+ form.append("file", zip instanceof Blob ? zip : new Blob([zip]), "upload.zip");
224
+ return (await this.#client.request("PUT", `/workspaces/${this.id}/upload`, form)).json();
225
+ }
226
+ async launch(options) {
227
+ return (await this.#client.request("POST", `/workspaces/${this.id}/sandbox/launch`, options)).json();
228
+ }
229
+ async logs({ tail } = {}) {
230
+ const query = tail === undefined ? "" : `?tail=${tail}`;
231
+ const response = await this.#client.request("GET", `/workspaces/${this.id}/sandbox/logs${query}`);
232
+ return (await response.json()).lines;
233
+ }
234
+ async stop() {
235
+ await this.#client.request("POST", `/workspaces/${this.id}/sandbox/stop`);
236
+ }
237
+ async close() {
238
+ await this.browser.close();
239
+ await this.#client.request("DELETE", `/workspaces/${this.id}`);
240
+ }
241
+ }
242
+
243
+ // src/core/client.ts
244
+ var API_PREFIX = "/api/v1";
245
+
246
+ class BaseClient {
247
+ baseUrl;
248
+ #token;
249
+ #fetch;
250
+ constructor(options = {}) {
251
+ const env = typeof process === "undefined" ? {} : process.env;
252
+ const baseUrl = options.baseUrl ?? env.CODE_HARNESS_BASE_URL;
253
+ const token = options.token ?? env.CODE_HARNESS_TOKEN;
254
+ if (!baseUrl || !token)
255
+ throw new CodeHarnessError("Pass baseUrl and token, or set CODE_HARNESS_BASE_URL and CODE_HARNESS_TOKEN", "AUTHENTICATION_FAILED");
256
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
257
+ this.#token = token;
258
+ this.#fetch = options.fetch ?? fetch;
259
+ }
260
+ async me() {
261
+ return (await this.request("GET", "/me")).json();
262
+ }
263
+ async createBrowser() {
264
+ const session = await (await this.request("POST", "/browser", {})).json();
265
+ return new Browser(this, { id: session.id, sandboxId: null, record: false });
266
+ }
267
+ getBrowser(id) {
268
+ return new Browser(this, { id, sandboxId: null, record: false });
269
+ }
270
+ async request(method, path, body) {
271
+ const headers = { authorization: `Bearer ${this.#token}` };
272
+ const isJson = body !== undefined && !(body instanceof FormData);
273
+ if (isJson)
274
+ headers["content-type"] = "application/json";
275
+ let response;
276
+ try {
277
+ response = await this.#fetch(`${this.baseUrl}${API_PREFIX}${path}`, {
278
+ method,
279
+ headers,
280
+ body: isJson ? JSON.stringify(body) : body
281
+ });
282
+ } catch (err) {
283
+ const cause = err instanceof Error ? err : new Error(String(err));
284
+ throw new CodeHarnessError(`Can't reach ${this.baseUrl}: ${cause.message}`, "NETWORK_ERROR", null, cause);
285
+ }
286
+ if (!response.ok)
287
+ throw await CodeHarnessError.fromResponse(response);
288
+ return response;
289
+ }
290
+ }
291
+
292
+ class Client extends BaseClient {
293
+ async createSandbox({ name, env, ...options } = {}) {
294
+ const response = await this.request("POST", "/workspaces", {
295
+ name: name ?? `sandbox-${Date.now()}`,
296
+ defaultEnv: env
297
+ });
298
+ return new Sandbox(this, await response.json(), options);
299
+ }
300
+ async getSandbox(id, options = {}) {
301
+ const response = await this.request("GET", `/workspaces/${encodeURIComponent(id)}`);
302
+ return new Sandbox(this, await response.json(), options);
303
+ }
304
+ }
@@ -0,0 +1,63 @@
1
+ import { Browser } from '../browser.js';
2
+ import type { BaseClient } from './client.js';
3
+ export declare const ROOT = "/workspace";
4
+ export type FileOperationError = 'file_not_found' | 'permission_denied' | 'is_directory' | 'invalid_path';
5
+ export interface ExecuteResponse {
6
+ output: string;
7
+ exitCode: number | null;
8
+ truncated: boolean;
9
+ }
10
+ export interface FileUploadResponse {
11
+ path: string;
12
+ error: FileOperationError | null;
13
+ }
14
+ export interface FileDownloadResponse {
15
+ path: string;
16
+ content: Uint8Array | null;
17
+ error: FileOperationError | null;
18
+ }
19
+ export interface SandboxOptions {
20
+ timeoutMs?: number;
21
+ record?: boolean;
22
+ }
23
+ export interface LaunchOptions {
24
+ command: string;
25
+ port: number;
26
+ env?: Record<string, string>;
27
+ network?: {
28
+ allow?: string[];
29
+ deny?: string[];
30
+ };
31
+ }
32
+ export interface Workspace {
33
+ id: string;
34
+ name: string;
35
+ defaultEnvKeys: string[];
36
+ createdAt: string;
37
+ }
38
+ export declare class Sandbox {
39
+ #private;
40
+ readonly id: string;
41
+ readonly name: string;
42
+ readonly envKeys: string[];
43
+ readonly createdAt: Date;
44
+ readonly browser: Browser;
45
+ constructor(client: BaseClient, workspace: Workspace, { timeoutMs, record }?: SandboxOptions);
46
+ execute(command: string): Promise<ExecuteResponse>;
47
+ uploadFiles(files: Array<[string, Uint8Array]>): Promise<FileUploadResponse[]>;
48
+ downloadFiles(paths: string[]): Promise<FileDownloadResponse[]>;
49
+ uploadAsZip(zip: Blob | Uint8Array<ArrayBuffer> | ArrayBuffer, { path }?: {
50
+ path?: string;
51
+ }): Promise<{
52
+ path: string;
53
+ files: number;
54
+ }>;
55
+ launch(options: LaunchOptions): Promise<{
56
+ url: string;
57
+ }>;
58
+ logs({ tail }?: {
59
+ tail?: number;
60
+ }): Promise<string[]>;
61
+ stop(): Promise<void>;
62
+ close(): Promise<void>;
63
+ }
@@ -0,0 +1,8 @@
1
+ export type CodeHarnessErrorCode = 'INVALID_REQUEST' | 'AUTHENTICATION_FAILED' | 'NOT_FOUND' | 'CONFLICT' | 'TOO_LARGE' | 'RATE_LIMITED' | 'UPSTREAM_FAILED' | 'TIMEOUT' | 'NETWORK_ERROR' | 'UNKNOWN';
2
+ export declare class CodeHarnessError extends Error {
3
+ readonly code: CodeHarnessErrorCode;
4
+ readonly status: number | null;
5
+ readonly name: string;
6
+ constructor(message: string, code: CodeHarnessErrorCode, status?: number | null, cause?: Error);
7
+ static fromResponse(response: Response): Promise<CodeHarnessError>;
8
+ }
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
package/dist/client.d.ts CHANGED
@@ -1,25 +1,8 @@
1
- import { Browser } from './browser.js';
2
- import { Sandbox, type SandboxOptions } from './sandbox.js';
3
- export interface ClientOptions {
4
- baseUrl?: string;
5
- token?: string;
6
- fetch?: typeof fetch;
7
- }
8
- export interface CreateSandboxOptions extends SandboxOptions {
9
- name?: string;
10
- env?: Record<string, string>;
11
- }
12
- export declare class Client {
13
- #private;
14
- readonly baseUrl: string;
15
- constructor(options?: ClientOptions);
16
- me(): Promise<{
17
- id: string;
18
- email: string;
19
- }>;
1
+ import { BaseClient, type CreateSandboxOptions } from './core/client.js';
2
+ import type { SandboxOptions } from './core/sandbox.js';
3
+ import { Sandbox } from './sandbox.js';
4
+ export type { ClientOptions, CreateSandboxOptions } from './core/client.js';
5
+ export declare class Client extends BaseClient {
20
6
  createSandbox({ name, env, ...options }?: CreateSandboxOptions): Promise<Sandbox>;
21
7
  getSandbox(id: string, options?: SandboxOptions): Promise<Sandbox>;
22
- createBrowser(): Promise<Browser>;
23
- getBrowser(id: string): Browser;
24
- request(method: string, path: string, body?: unknown): Promise<Response>;
25
8
  }
package/dist/client.js CHANGED
@@ -1,24 +1,6 @@
1
- import { Browser } from './browser.js';
2
- import { CodeHarnessError } from './errors.js';
1
+ import { BaseClient } from './core/client.js';
3
2
  import { Sandbox } from './sandbox.js';
4
- const API_PREFIX = '/api/v1';
5
- export class Client {
6
- baseUrl;
7
- #token;
8
- #fetch;
9
- constructor(options = {}) {
10
- const env = typeof process === 'undefined' ? {} : process.env;
11
- const baseUrl = options.baseUrl ?? env.CODE_HARNESS_BASE_URL;
12
- const token = options.token ?? env.CODE_HARNESS_TOKEN;
13
- if (!baseUrl || !token)
14
- throw new CodeHarnessError('Pass baseUrl and token, or set CODE_HARNESS_BASE_URL and CODE_HARNESS_TOKEN', 'AUTHENTICATION_FAILED');
15
- this.baseUrl = baseUrl.replace(/\/+$/, '');
16
- this.#token = token;
17
- this.#fetch = options.fetch ?? fetch;
18
- }
19
- async me() {
20
- return (await this.request('GET', '/me')).json();
21
- }
3
+ export class Client extends BaseClient {
22
4
  async createSandbox({ name, env, ...options } = {}) {
23
5
  const response = await this.request('POST', '/workspaces', {
24
6
  name: name ?? `sandbox-${Date.now()}`,
@@ -30,34 +12,5 @@ export class Client {
30
12
  const response = await this.request('GET', `/workspaces/${encodeURIComponent(id)}`);
31
13
  return new Sandbox(this, (await response.json()), options);
32
14
  }
33
- async createBrowser() {
34
- const session = (await (await this.request('POST', '/browser', {})).json());
35
- return new Browser(this, { id: session.id, sandboxId: null, record: false });
36
- }
37
- getBrowser(id) {
38
- return new Browser(this, { id, sandboxId: null, record: false });
39
- }
40
- // Sends one call to /api/v1, a FormData body as multipart and any other as JSON, and throws CodeHarnessError unless it answers 2xx.
41
- async request(method, path, body) {
42
- const headers = { authorization: `Bearer ${this.#token}` };
43
- const isJson = body !== undefined && !(body instanceof FormData);
44
- if (isJson)
45
- headers['content-type'] = 'application/json';
46
- let response;
47
- try {
48
- response = await this.#fetch(`${this.baseUrl}${API_PREFIX}${path}`, {
49
- method,
50
- headers,
51
- body: isJson ? JSON.stringify(body) : body,
52
- });
53
- }
54
- catch (err) {
55
- const cause = err instanceof Error ? err : new Error(String(err));
56
- throw new CodeHarnessError(`Can't reach ${this.baseUrl}: ${cause.message}`, 'NETWORK_ERROR', null, cause);
57
- }
58
- if (!response.ok)
59
- throw await CodeHarnessError.fromResponse(response);
60
- return response;
61
- }
62
15
  }
63
16
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA6B,MAAM,kBAAkB,CAAA;AAExE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAItC,MAAM,OAAO,MAAO,SAAQ,UAAU;IACpC,KAAK,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,GAAyB,EAAE;QACtE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE;YACzD,IAAI,EAAE,IAAI,IAAI,WAAW,IAAI,CAAC,GAAG,EAAE,EAAE;YACrC,UAAU,EAAE,GAAG;SAChB,CAAC,CAAA;QAEF,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAc,EAAE,OAAO,CAAC,CAAA;IACzE,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,EAAU,EAAE,OAAO,GAAmB,EAAE;QACvD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,eAAe,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QAEnF,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAc,EAAE,OAAO,CAAC,CAAA;IACzE,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ import { Browser } from '../browser.js';
2
+ import { Sandbox, type SandboxOptions } from './sandbox.js';
3
+ export interface ClientOptions {
4
+ baseUrl?: string;
5
+ token?: string;
6
+ fetch?: typeof fetch;
7
+ }
8
+ export interface CreateSandboxOptions extends SandboxOptions {
9
+ name?: string;
10
+ env?: Record<string, string>;
11
+ }
12
+ export declare class BaseClient {
13
+ #private;
14
+ readonly baseUrl: string;
15
+ constructor(options?: ClientOptions);
16
+ me(): Promise<{
17
+ id: string;
18
+ email: string;
19
+ }>;
20
+ createBrowser(): Promise<Browser>;
21
+ getBrowser(id: string): Browser;
22
+ request(method: string, path: string, body?: unknown): Promise<Response>;
23
+ }
24
+ export declare class Client extends BaseClient {
25
+ createSandbox({ name, env, ...options }?: CreateSandboxOptions): Promise<Sandbox>;
26
+ getSandbox(id: string, options?: SandboxOptions): Promise<Sandbox>;
27
+ }
@@ -0,0 +1,66 @@
1
+ import { Browser } from '../browser.js';
2
+ import { CodeHarnessError } from '../errors.js';
3
+ import { Sandbox } from './sandbox.js';
4
+ const API_PREFIX = '/api/v1';
5
+ // everything but sandboxes, which each entry's Client adds with its own Sandbox
6
+ export class BaseClient {
7
+ baseUrl;
8
+ #token;
9
+ #fetch;
10
+ constructor(options = {}) {
11
+ const env = typeof process === 'undefined' ? {} : process.env;
12
+ const baseUrl = options.baseUrl ?? env.CODE_HARNESS_BASE_URL;
13
+ const token = options.token ?? env.CODE_HARNESS_TOKEN;
14
+ if (!baseUrl || !token)
15
+ throw new CodeHarnessError('Pass baseUrl and token, or set CODE_HARNESS_BASE_URL and CODE_HARNESS_TOKEN', 'AUTHENTICATION_FAILED');
16
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
17
+ this.#token = token;
18
+ this.#fetch = options.fetch ?? fetch;
19
+ }
20
+ async me() {
21
+ return (await this.request('GET', '/me')).json();
22
+ }
23
+ async createBrowser() {
24
+ const session = (await (await this.request('POST', '/browser', {})).json());
25
+ return new Browser(this, { id: session.id, sandboxId: null, record: false });
26
+ }
27
+ getBrowser(id) {
28
+ return new Browser(this, { id, sandboxId: null, record: false });
29
+ }
30
+ // Sends one call to /api/v1, a FormData body as multipart and any other as JSON, and throws CodeHarnessError unless it answers 2xx.
31
+ async request(method, path, body) {
32
+ const headers = { authorization: `Bearer ${this.#token}` };
33
+ const isJson = body !== undefined && !(body instanceof FormData);
34
+ if (isJson)
35
+ headers['content-type'] = 'application/json';
36
+ let response;
37
+ try {
38
+ response = await this.#fetch(`${this.baseUrl}${API_PREFIX}${path}`, {
39
+ method,
40
+ headers,
41
+ body: isJson ? JSON.stringify(body) : body,
42
+ });
43
+ }
44
+ catch (err) {
45
+ const cause = err instanceof Error ? err : new Error(String(err));
46
+ throw new CodeHarnessError(`Can't reach ${this.baseUrl}: ${cause.message}`, 'NETWORK_ERROR', null, cause);
47
+ }
48
+ if (!response.ok)
49
+ throw await CodeHarnessError.fromResponse(response);
50
+ return response;
51
+ }
52
+ }
53
+ export class Client extends BaseClient {
54
+ async createSandbox({ name, env, ...options } = {}) {
55
+ const response = await this.request('POST', '/workspaces', {
56
+ name: name ?? `sandbox-${Date.now()}`,
57
+ defaultEnv: env,
58
+ });
59
+ return new Sandbox(this, (await response.json()), options);
60
+ }
61
+ async getSandbox(id, options = {}) {
62
+ const response = await this.request('GET', `/workspaces/${encodeURIComponent(id)}`);
63
+ return new Sandbox(this, (await response.json()), options);
64
+ }
65
+ }
66
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/core/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { Browser, type NavigatedPage, type Page, type PageRef, type RunResult, type WaitFor } from '../browser.js';
2
+ export { CodeHarnessError, type CodeHarnessErrorCode } from '../errors.js';
3
+ export { Client, type ClientOptions, type CreateSandboxOptions } from './client.js';
4
+ export { Sandbox, type ExecuteResponse, type FileDownloadResponse, type FileOperationError, type FileUploadResponse, type LaunchOptions, type SandboxOptions, } from './sandbox.js';
@@ -0,0 +1,5 @@
1
+ export { Browser } from '../browser.js';
2
+ export { CodeHarnessError } from '../errors.js';
3
+ export { Client } from './client.js';
4
+ export { Sandbox, } from './sandbox.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAA6E,MAAM,eAAe,CAAA;AAClH,OAAO,EAAE,gBAAgB,EAA6B,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,MAAM,EAAiD,MAAM,aAAa,CAAA;AACnF,OAAO,EACL,OAAO,GAOR,MAAM,cAAc,CAAA"}
@@ -0,0 +1,63 @@
1
+ import { Browser } from '../browser.js';
2
+ import type { BaseClient } from './client.js';
3
+ export declare const ROOT = "/workspace";
4
+ export type FileOperationError = 'file_not_found' | 'permission_denied' | 'is_directory' | 'invalid_path';
5
+ export interface ExecuteResponse {
6
+ output: string;
7
+ exitCode: number | null;
8
+ truncated: boolean;
9
+ }
10
+ export interface FileUploadResponse {
11
+ path: string;
12
+ error: FileOperationError | null;
13
+ }
14
+ export interface FileDownloadResponse {
15
+ path: string;
16
+ content: Uint8Array | null;
17
+ error: FileOperationError | null;
18
+ }
19
+ export interface SandboxOptions {
20
+ timeoutMs?: number;
21
+ record?: boolean;
22
+ }
23
+ export interface LaunchOptions {
24
+ command: string;
25
+ port: number;
26
+ env?: Record<string, string>;
27
+ network?: {
28
+ allow?: string[];
29
+ deny?: string[];
30
+ };
31
+ }
32
+ export interface Workspace {
33
+ id: string;
34
+ name: string;
35
+ defaultEnvKeys: string[];
36
+ createdAt: string;
37
+ }
38
+ export declare class Sandbox {
39
+ #private;
40
+ readonly id: string;
41
+ readonly name: string;
42
+ readonly envKeys: string[];
43
+ readonly createdAt: Date;
44
+ readonly browser: Browser;
45
+ constructor(client: BaseClient, workspace: Workspace, { timeoutMs, record }?: SandboxOptions);
46
+ execute(command: string): Promise<ExecuteResponse>;
47
+ uploadFiles(files: Array<[string, Uint8Array]>): Promise<FileUploadResponse[]>;
48
+ downloadFiles(paths: string[]): Promise<FileDownloadResponse[]>;
49
+ uploadAsZip(zip: Blob | Uint8Array<ArrayBuffer> | ArrayBuffer, { path }?: {
50
+ path?: string;
51
+ }): Promise<{
52
+ path: string;
53
+ files: number;
54
+ }>;
55
+ launch(options: LaunchOptions): Promise<{
56
+ url: string;
57
+ }>;
58
+ logs({ tail }?: {
59
+ tail?: number;
60
+ }): Promise<string[]>;
61
+ stop(): Promise<void>;
62
+ close(): Promise<void>;
63
+ }
@@ -0,0 +1,117 @@
1
+ import { Browser } from '../browser.js';
2
+ import { CodeHarnessError } from '../errors.js';
3
+ export const ROOT = '/workspace';
4
+ const DEFAULT_TIMEOUT_MS = 120_000;
5
+ const UTF8 = new TextDecoder('utf-8', { fatal: true });
6
+ // /workspace/src/a.ts or src/a.ts → src/a.ts, /workspace → ''; null for a path outside /workspace
7
+ const relativePath = (path) => {
8
+ if (path === ROOT)
9
+ return '';
10
+ return path.startsWith(`${ROOT}/`) ? path.slice(ROOT.length + 1) : path.startsWith('/') ? null : path;
11
+ };
12
+ const encodePath = (relative) => relative.split('/').map(encodeURIComponent).join('/');
13
+ // a file route's answer for one path; anything else, like a 401, isn't about the path and is thrown
14
+ const fileError = (err) => {
15
+ if (err instanceof CodeHarnessError && err.code === 'NOT_FOUND')
16
+ return 'file_not_found';
17
+ if (err instanceof CodeHarnessError && err.code === 'INVALID_REQUEST')
18
+ return 'invalid_path';
19
+ throw err;
20
+ };
21
+ export class Sandbox {
22
+ id;
23
+ name;
24
+ envKeys;
25
+ createdAt;
26
+ browser;
27
+ #client;
28
+ #timeoutMs;
29
+ constructor(client, workspace, { timeoutMs = DEFAULT_TIMEOUT_MS, record = false } = {}) {
30
+ this.#client = client;
31
+ this.#timeoutMs = timeoutMs;
32
+ this.id = workspace.id;
33
+ this.name = workspace.name;
34
+ this.envKeys = workspace.defaultEnvKeys;
35
+ this.createdAt = new Date(workspace.createdAt);
36
+ this.browser = new Browser(client, { id: null, sandboxId: workspace.id, record });
37
+ }
38
+ async execute(command) {
39
+ const response = await this.#client.request('POST', `/workspaces/${this.id}/sandbox/exec`, {
40
+ command,
41
+ timeoutMs: this.#timeoutMs,
42
+ });
43
+ const result = (await response.json());
44
+ return {
45
+ output: result.timedOut ? `${result.output}\ntimed out after ${this.#timeoutMs} ms` : result.output,
46
+ exitCode: result.exitCode,
47
+ truncated: false,
48
+ };
49
+ }
50
+ async uploadFiles(files) {
51
+ const results = [];
52
+ for (const [path, bytes] of files) {
53
+ const relative = relativePath(path);
54
+ if (!relative) {
55
+ results.push({ path, error: 'invalid_path' });
56
+ continue;
57
+ }
58
+ let content;
59
+ try {
60
+ content = UTF8.decode(bytes);
61
+ }
62
+ catch {
63
+ // the files route takes text only
64
+ results.push({ path, error: 'invalid_path' });
65
+ continue;
66
+ }
67
+ const error = await this.#client
68
+ .request('PUT', `/workspaces/${this.id}/files/${encodePath(relative)}`, { content })
69
+ .then(() => null, fileError);
70
+ results.push({ path, error });
71
+ }
72
+ return results;
73
+ }
74
+ async downloadFiles(paths) {
75
+ const results = [];
76
+ for (const path of paths) {
77
+ const relative = relativePath(path);
78
+ if (!relative) {
79
+ results.push({ path, content: null, error: 'invalid_path' });
80
+ continue;
81
+ }
82
+ try {
83
+ const response = await this.#client.request('GET', `/workspaces/${this.id}/files/${encodePath(relative)}?raw=true`);
84
+ results.push({ path, content: new Uint8Array(await response.arrayBuffer()), error: null });
85
+ }
86
+ catch (err) {
87
+ results.push({ path, content: null, error: fileError(err) });
88
+ }
89
+ }
90
+ return results;
91
+ }
92
+ async uploadAsZip(zip, { path = '' } = {}) {
93
+ const relative = relativePath(path);
94
+ if (relative === null)
95
+ throw new CodeHarnessError(`${path} is outside ${ROOT}`, 'INVALID_REQUEST');
96
+ const form = new FormData();
97
+ form.append('path', relative);
98
+ form.append('file', zip instanceof Blob ? zip : new Blob([zip]), 'upload.zip');
99
+ return (await this.#client.request('PUT', `/workspaces/${this.id}/upload`, form)).json();
100
+ }
101
+ async launch(options) {
102
+ return (await this.#client.request('POST', `/workspaces/${this.id}/sandbox/launch`, options)).json();
103
+ }
104
+ async logs({ tail } = {}) {
105
+ const query = tail === undefined ? '' : `?tail=${tail}`;
106
+ const response = await this.#client.request('GET', `/workspaces/${this.id}/sandbox/logs${query}`);
107
+ return (await response.json()).lines;
108
+ }
109
+ async stop() {
110
+ await this.#client.request('POST', `/workspaces/${this.id}/sandbox/stop`);
111
+ }
112
+ async close() {
113
+ await this.browser.close();
114
+ await this.#client.request('DELETE', `/workspaces/${this.id}`);
115
+ }
116
+ }
117
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/core/sandbox.ts"],"names":[],"mappings":"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"}
package/dist/errors.d.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { SandboxError } from 'deepagents';
2
1
  export type CodeHarnessErrorCode = 'INVALID_REQUEST' | 'AUTHENTICATION_FAILED' | 'NOT_FOUND' | 'CONFLICT' | 'TOO_LARGE' | 'RATE_LIMITED' | 'UPSTREAM_FAILED' | 'TIMEOUT' | 'NETWORK_ERROR' | 'UNKNOWN';
3
- export declare class CodeHarnessError extends SandboxError {
2
+ export declare class CodeHarnessError extends Error {
3
+ readonly code: CodeHarnessErrorCode;
4
4
  readonly status: number | null;
5
5
  readonly name: string;
6
- readonly code: CodeHarnessErrorCode;
7
6
  constructor(message: string, code: CodeHarnessErrorCode, status?: number | null, cause?: Error);
8
7
  static fromResponse(response: Response): Promise<CodeHarnessError>;
9
8
  }
package/dist/errors.js CHANGED
@@ -1,4 +1,3 @@
1
- import { SandboxError } from 'deepagents';
2
1
  const CODES = {
3
2
  400: 'INVALID_REQUEST',
4
3
  401: 'AUTHENTICATION_FAILED',
@@ -9,13 +8,17 @@ const CODES = {
9
8
  502: 'UPSTREAM_FAILED',
10
9
  504: 'TIMEOUT',
11
10
  };
12
- export class CodeHarnessError extends SandboxError {
11
+ // deepagents' SandboxError.isInstance checks this symbol, so the client entry needn't load deepagents
12
+ const SANDBOX_ERROR = Symbol.for('sandbox.error');
13
+ export class CodeHarnessError extends Error {
14
+ code;
13
15
  status;
14
16
  name = 'CodeHarnessError';
15
17
  constructor(message, code, status = null, cause) {
16
- super(message, code, cause);
18
+ super(message, { cause });
19
+ this.code = code;
17
20
  this.status = status;
18
- Object.setPrototypeOf(this, CodeHarnessError.prototype);
21
+ Object.defineProperty(this, SANDBOX_ERROR, { value: true });
19
22
  }
20
23
  static async fromResponse(response) {
21
24
  const body = (await response.json().catch(() => null));
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC,MAAM,KAAK,GAAyC;IAClD,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,uBAAuB;IAC5B,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,SAAS;CACf,CAAA;AAcD,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAOrC,MAAM;IANC,IAAI,GAAW,kBAAkB,CAAA;IAGnD,YACE,OAAe,EACf,IAA0B,EACjB,MAAM,GAAkB,IAAI,EACrC,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;sBAHlB,MAAM;QAIf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAA;IACzD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAkB;QAC1C,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAgD,CAAA;QACrG,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAA;QAEnE,OAAO,IAAI,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC5F,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GAAyC;IAClD,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,uBAAuB;IAC5B,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,SAAS;CACf,CAAA;AAcD,sGAAsG;AACtG,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;AAEjD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAK9B,IAAI;IACJ,MAAM;IALC,IAAI,GAAW,kBAAkB,CAAA;IAEnD,YACE,OAAe,EACN,IAA0B,EAC1B,MAAM,GAAkB,IAAI,EACrC,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;oBAJhB,IAAI;sBACJ,MAAM;QAIf,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC7D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,QAAkB;QAC1C,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAgD,CAAA;QACrG,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,EAAE,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAA;QAEnE,OAAO,IAAI,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC5F,CAAC;CACF"}
package/dist/sandbox.d.ts CHANGED
@@ -1,26 +1,8 @@
1
1
  import { BaseSandbox, type ExecuteResponse, type FileDownloadResponse, type FileUploadResponse } from 'deepagents';
2
- import { Browser } from './browser.js';
3
- import type { Client } from './client.js';
4
- export declare const ROOT = "/workspace";
5
- export interface SandboxOptions {
6
- timeoutMs?: number;
7
- record?: boolean;
8
- }
9
- export interface LaunchOptions {
10
- command: string;
11
- port: number;
12
- env?: Record<string, string>;
13
- network?: {
14
- allow?: string[];
15
- deny?: string[];
16
- };
17
- }
18
- export interface Workspace {
19
- id: string;
20
- name: string;
21
- defaultEnvKeys: string[];
22
- createdAt: string;
23
- }
2
+ import type { Browser } from './browser.js';
3
+ import type { BaseClient } from './core/client.js';
4
+ import { type LaunchOptions, type SandboxOptions, type Workspace } from './core/sandbox.js';
5
+ export { ROOT, type LaunchOptions, type SandboxOptions, type Workspace } from './core/sandbox.js';
24
6
  export declare class Sandbox extends BaseSandbox {
25
7
  #private;
26
8
  readonly id: string;
@@ -28,11 +10,11 @@ export declare class Sandbox extends BaseSandbox {
28
10
  readonly envKeys: string[];
29
11
  readonly createdAt: Date;
30
12
  readonly browser: Browser;
31
- constructor(client: Client, workspace: Workspace, { timeoutMs, record }?: SandboxOptions);
13
+ constructor(client: BaseClient, workspace: Workspace, options?: SandboxOptions);
32
14
  execute(command: string): Promise<ExecuteResponse>;
33
15
  uploadFiles(files: Array<[string, Uint8Array]>): Promise<FileUploadResponse[]>;
34
16
  downloadFiles(paths: string[]): Promise<FileDownloadResponse[]>;
35
- uploadAsZip(zip: Blob | Uint8Array<ArrayBuffer> | ArrayBuffer, { path }?: {
17
+ uploadAsZip(zip: Blob | Uint8Array<ArrayBuffer> | ArrayBuffer, options?: {
36
18
  path?: string;
37
19
  }): Promise<{
38
20
  path: string;
@@ -41,7 +23,7 @@ export declare class Sandbox extends BaseSandbox {
41
23
  launch(options: LaunchOptions): Promise<{
42
24
  url: string;
43
25
  }>;
44
- logs({ tail }?: {
26
+ logs(options?: {
45
27
  tail?: number;
46
28
  }): Promise<string[]>;
47
29
  stop(): Promise<void>;
package/dist/sandbox.js CHANGED
@@ -1,119 +1,46 @@
1
1
  import { BaseSandbox, } from 'deepagents';
2
- import { Browser } from './browser.js';
3
- import { CodeHarnessError } from './errors.js';
4
- export const ROOT = '/workspace';
5
- const DEFAULT_TIMEOUT_MS = 120_000;
6
- const UTF8 = new TextDecoder('utf-8', { fatal: true });
7
- // /workspace/src/a.ts or src/a.ts → src/a.ts, /workspace → ''; null for a path outside /workspace
8
- const relativePath = (path) => {
9
- if (path === ROOT)
10
- return '';
11
- return path.startsWith(`${ROOT}/`) ? path.slice(ROOT.length + 1) : path.startsWith('/') ? null : path;
12
- };
13
- const encodePath = (relative) => relative.split('/').map(encodeURIComponent).join('/');
14
- // a file route's answer for one path; anything else, like a 401, isn't about the path and is thrown
15
- const fileError = (err) => {
16
- if (err instanceof CodeHarnessError && err.code === 'NOT_FOUND')
17
- return 'file_not_found';
18
- if (err instanceof CodeHarnessError && err.code === 'INVALID_REQUEST')
19
- return 'invalid_path';
20
- throw err;
21
- };
2
+ import { Sandbox as CoreSandbox } from './core/sandbox.js';
3
+ export { ROOT } from './core/sandbox.js';
4
+ // deepagents' BaseSandbox over the client entry's Sandbox, which holds the calls
22
5
  export class Sandbox extends BaseSandbox {
23
6
  id;
24
7
  name;
25
8
  envKeys;
26
9
  createdAt;
27
10
  browser;
28
- #client;
29
- #timeoutMs;
30
- constructor(client, workspace, { timeoutMs = DEFAULT_TIMEOUT_MS, record = false } = {}) {
11
+ #sandbox;
12
+ constructor(client, workspace, options = {}) {
31
13
  super();
32
- this.#client = client;
33
- this.#timeoutMs = timeoutMs;
34
- this.id = workspace.id;
35
- this.name = workspace.name;
36
- this.envKeys = workspace.defaultEnvKeys;
37
- this.createdAt = new Date(workspace.createdAt);
38
- this.browser = new Browser(client, { id: null, sandboxId: workspace.id, record });
14
+ this.#sandbox = new CoreSandbox(client, workspace, options);
15
+ this.id = this.#sandbox.id;
16
+ this.name = this.#sandbox.name;
17
+ this.envKeys = this.#sandbox.envKeys;
18
+ this.createdAt = this.#sandbox.createdAt;
19
+ this.browser = this.#sandbox.browser;
39
20
  }
40
- async execute(command) {
41
- const response = await this.#client.request('POST', `/workspaces/${this.id}/sandbox/exec`, {
42
- command,
43
- timeoutMs: this.#timeoutMs,
44
- });
45
- const result = (await response.json());
46
- return {
47
- output: result.timedOut ? `${result.output}\ntimed out after ${this.#timeoutMs} ms` : result.output,
48
- exitCode: result.exitCode,
49
- truncated: false,
50
- };
21
+ execute(command) {
22
+ return this.#sandbox.execute(command);
51
23
  }
52
- async uploadFiles(files) {
53
- const results = [];
54
- for (const [path, bytes] of files) {
55
- const relative = relativePath(path);
56
- if (!relative) {
57
- results.push({ path, error: 'invalid_path' });
58
- continue;
59
- }
60
- let content;
61
- try {
62
- content = UTF8.decode(bytes);
63
- }
64
- catch {
65
- // the files route takes text only
66
- results.push({ path, error: 'invalid_path' });
67
- continue;
68
- }
69
- const error = await this.#client
70
- .request('PUT', `/workspaces/${this.id}/files/${encodePath(relative)}`, { content })
71
- .then(() => null, fileError);
72
- results.push({ path, error });
73
- }
74
- return results;
24
+ uploadFiles(files) {
25
+ return this.#sandbox.uploadFiles(files);
75
26
  }
76
- async downloadFiles(paths) {
77
- const results = [];
78
- for (const path of paths) {
79
- const relative = relativePath(path);
80
- if (!relative) {
81
- results.push({ path, content: null, error: 'invalid_path' });
82
- continue;
83
- }
84
- try {
85
- const response = await this.#client.request('GET', `/workspaces/${this.id}/files/${encodePath(relative)}?raw=true`);
86
- results.push({ path, content: new Uint8Array(await response.arrayBuffer()), error: null });
87
- }
88
- catch (err) {
89
- results.push({ path, content: null, error: fileError(err) });
90
- }
91
- }
92
- return results;
27
+ downloadFiles(paths) {
28
+ return this.#sandbox.downloadFiles(paths);
93
29
  }
94
- async uploadAsZip(zip, { path = '' } = {}) {
95
- const relative = relativePath(path);
96
- if (relative === null)
97
- throw new CodeHarnessError(`${path} is outside ${ROOT}`, 'INVALID_REQUEST');
98
- const form = new FormData();
99
- form.append('path', relative);
100
- form.append('file', zip instanceof Blob ? zip : new Blob([zip]), 'upload.zip');
101
- return (await this.#client.request('PUT', `/workspaces/${this.id}/upload`, form)).json();
30
+ uploadAsZip(zip, options = {}) {
31
+ return this.#sandbox.uploadAsZip(zip, options);
102
32
  }
103
- async launch(options) {
104
- return (await this.#client.request('POST', `/workspaces/${this.id}/sandbox/launch`, options)).json();
33
+ launch(options) {
34
+ return this.#sandbox.launch(options);
105
35
  }
106
- async logs({ tail } = {}) {
107
- const query = tail === undefined ? '' : `?tail=${tail}`;
108
- const response = await this.#client.request('GET', `/workspaces/${this.id}/sandbox/logs${query}`);
109
- return (await response.json()).lines;
36
+ logs(options = {}) {
37
+ return this.#sandbox.logs(options);
110
38
  }
111
- async stop() {
112
- await this.#client.request('POST', `/workspaces/${this.id}/sandbox/stop`);
39
+ stop() {
40
+ return this.#sandbox.stop();
113
41
  }
114
- async close() {
115
- await this.browser.close();
116
- await this.#client.request('DELETE', `/workspaces/${this.id}`);
42
+ close() {
43
+ return this.#sandbox.close();
117
44
  }
118
45
  }
119
46
  //# sourceMappingURL=sandbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,GAIZ,MAAM,YAAY,CAAA;AAInB,OAAO,EAAE,OAAO,IAAI,WAAW,EAA2D,MAAM,mBAAmB,CAAA;AAEnH,OAAO,EAAE,IAAI,EAA2D,MAAM,mBAAmB,CAAA;AAEjG,iFAAiF;AACjF,MAAM,OAAO,OAAQ,SAAQ,WAAW;IAC7B,EAAE,CAAQ;IACV,IAAI,CAAQ;IACZ,OAAO,CAAU;IACjB,SAAS,CAAM;IACf,OAAO,CAAS;IAChB,QAAQ,CAAa;IAE9B,YAAY,MAAkB,EAAE,SAAoB,EAAE,OAAO,GAAmB,EAAE;QAChF,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;QAC3D,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAA;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAA;QACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAA;QACxC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAA;IACtC,CAAC;IAED,OAAO,CAAC,OAAe;QACrB,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IACvC,CAAC;IAED,WAAW,CAAC,KAAkC;QAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IACzC,CAAC;IAED,aAAa,CAAC,KAAe;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAC3C,CAAC;IAED,WAAW,CACT,GAAiD,EACjD,OAAO,GAAsB,EAAE;QAE/B,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAChD,CAAC;IAED,MAAM,CAAC,OAAsB;QAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,IAAI,CAAC,OAAO,GAAsB,EAAE;QAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACpC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;IAC9B,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-harness/sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "TypeScript client for Code-Harness sandboxes and browsers, with a deepagents backend and LangChain middleware",
5
5
  "type": "module",
6
6
  "repository": {
@@ -18,6 +18,16 @@
18
18
  "types": "./dist/index.d.ts",
19
19
  "default": "./dist/index.js"
20
20
  },
21
+ "./client": {
22
+ "import": {
23
+ "types": "./dist/core/index.d.ts",
24
+ "default": "./dist/core/index.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/cjs/core/index.d.ts",
28
+ "default": "./dist/cjs/core/index.js"
29
+ }
30
+ },
21
31
  "./package.json": "./package.json"
22
32
  },
23
33
  "files": ["dist"],
@@ -25,9 +35,10 @@
25
35
  "node": ">=20"
26
36
  },
27
37
  "scripts": {
28
- "build": "rm -rf dist && tsc -p tsconfig.build.json",
38
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && bun run build:cjs",
29
39
  "typecheck": "tsc",
30
- "test": "bun test"
40
+ "test": "bun test",
41
+ "build:cjs": "bun build src/core/index.ts --format=cjs --target=node --outfile dist/cjs/core/index.js && cp dist/browser.d.ts dist/errors.d.ts dist/cjs/ && cp dist/core/*.d.ts dist/cjs/core/ && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json"
31
42
  },
32
43
  "peerDependencies": {
33
44
  "@langchain/core": "^1.3.2",
@@ -35,6 +46,20 @@
35
46
  "langchain": "^1.6.0",
36
47
  "zod": "^4.0.0"
37
48
  },
49
+ "peerDependenciesMeta": {
50
+ "@langchain/core": {
51
+ "optional": true
52
+ },
53
+ "deepagents": {
54
+ "optional": true
55
+ },
56
+ "langchain": {
57
+ "optional": true
58
+ },
59
+ "zod": {
60
+ "optional": true
61
+ }
62
+ },
38
63
  "devDependencies": {
39
64
  "@langchain/core": "^1.3.4",
40
65
  "@types/bun": "^1.4.3",