@code-harness/sdk 0.0.0-stage → 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.
Files changed (42) hide show
  1. package/dist/browser.d.ts +65 -0
  2. package/dist/browser.js +60 -0
  3. package/dist/browser.js.map +1 -0
  4. package/dist/cjs/browser.d.ts +65 -0
  5. package/dist/cjs/core/client.d.ts +27 -0
  6. package/dist/cjs/core/index.d.ts +4 -0
  7. package/dist/cjs/core/index.js +304 -0
  8. package/dist/cjs/core/sandbox.d.ts +63 -0
  9. package/dist/cjs/errors.d.ts +8 -0
  10. package/dist/cjs/package.json +1 -0
  11. package/dist/client.d.ts +8 -0
  12. package/dist/client.js +16 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/core/client.d.ts +27 -0
  15. package/dist/core/client.js +66 -0
  16. package/dist/core/client.js.map +1 -0
  17. package/dist/core/index.d.ts +4 -0
  18. package/dist/core/index.js +5 -0
  19. package/dist/core/index.js.map +1 -0
  20. package/dist/core/sandbox.d.ts +63 -0
  21. package/dist/core/sandbox.js +117 -0
  22. package/dist/core/sandbox.js.map +1 -0
  23. package/dist/errors.d.ts +8 -0
  24. package/dist/errors.js +29 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.js +8 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/integration/langchain/browser-use.d.ts +7 -0
  30. package/dist/integration/langchain/browser-use.js +74 -0
  31. package/dist/integration/langchain/browser-use.js.map +1 -0
  32. package/dist/integration/langchain/code-harness.d.ts +5 -0
  33. package/dist/integration/langchain/code-harness.js +40 -0
  34. package/dist/integration/langchain/code-harness.js.map +1 -0
  35. package/dist/integration/langchain/skill-use.d.ts +6 -0
  36. package/dist/integration/langchain/skill-use.js +5 -0
  37. package/dist/integration/langchain/skill-use.js.map +1 -0
  38. package/dist/sandbox.d.ts +31 -0
  39. package/dist/sandbox.js +46 -0
  40. package/dist/sandbox.js.map +1 -0
  41. package/package.json +70 -4
  42. package/README.md +0 -3
@@ -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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"}
@@ -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
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,29 @@
1
+ const CODES = {
2
+ 400: 'INVALID_REQUEST',
3
+ 401: 'AUTHENTICATION_FAILED',
4
+ 404: 'NOT_FOUND',
5
+ 409: 'CONFLICT',
6
+ 413: 'TOO_LARGE',
7
+ 429: 'RATE_LIMITED',
8
+ 502: 'UPSTREAM_FAILED',
9
+ 504: 'TIMEOUT',
10
+ };
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;
15
+ status;
16
+ name = 'CodeHarnessError';
17
+ constructor(message, code, status = null, cause) {
18
+ super(message, { cause });
19
+ this.code = code;
20
+ this.status = status;
21
+ Object.defineProperty(this, SANDBOX_ERROR, { value: true });
22
+ }
23
+ static async fromResponse(response) {
24
+ const body = (await response.json().catch(() => null));
25
+ const message = body?.message ?? body?.error ?? response.statusText;
26
+ return new CodeHarnessError(message, CODES[response.status] ?? 'UNKNOWN', response.status);
27
+ }
28
+ }
29
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,7 @@
1
+ export { Browser, type NavigatedPage, type Page, type PageRef, type RunResult, type WaitFor } from './browser.js';
2
+ export { Client, type ClientOptions, type CreateSandboxOptions } from './client.js';
3
+ export { CodeHarnessError, type CodeHarnessErrorCode } from './errors.js';
4
+ export { createBrowserUseMiddleware } from './integration/langchain/browser-use.js';
5
+ export { createCodeHarnessMiddleware } from './integration/langchain/code-harness.js';
6
+ export { createSkillUseMiddleware } from './integration/langchain/skill-use.js';
7
+ export { Sandbox, type LaunchOptions, type SandboxOptions } from './sandbox.js';
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { Browser } from './browser.js';
2
+ export { Client } from './client.js';
3
+ export { CodeHarnessError } from './errors.js';
4
+ export { createBrowserUseMiddleware } from './integration/langchain/browser-use.js';
5
+ export { createCodeHarnessMiddleware } from './integration/langchain/code-harness.js';
6
+ export { createSkillUseMiddleware } from './integration/langchain/skill-use.js';
7
+ export { Sandbox } from './sandbox.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAA6E,MAAM,cAAc,CAAA;AACjH,OAAO,EAAE,MAAM,EAAiD,MAAM,aAAa,CAAA;AACnF,OAAO,EAAE,gBAAgB,EAA6B,MAAM,aAAa,CAAA;AACzE,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAA;AACnF,OAAO,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAA;AACrF,OAAO,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAA;AAC/E,OAAO,EAAE,OAAO,EAA2C,MAAM,cAAc,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { type StructuredTool } from 'langchain';
2
+ import type { Browser } from '../../browser.js';
3
+ export declare const attempt: (call: () => Promise<unknown>) => Promise<string>;
4
+ export declare const browserTools: (browser: Browser) => StructuredTool[];
5
+ export declare function createBrowserUseMiddleware({ browser }: {
6
+ browser: Browser;
7
+ }): import("langchain").AgentMiddleware<undefined, undefined, unknown, StructuredTool<import("@langchain/core/tools").ToolSchemaBase, any, any, any, unknown>[], readonly []>;
@@ -0,0 +1,74 @@
1
+ import { createMiddleware, tool } from 'langchain';
2
+ import { z } from 'zod';
3
+ import { CodeHarnessError } from '../../errors.js';
4
+ import { ROOT } from '../../sandbox.js';
5
+ const WaitFor = z
6
+ .object({
7
+ selector: z.string().optional().describe('CSS selector of an element to wait for'),
8
+ text: z.string().optional().describe('Text to wait for on the page'),
9
+ timeoutMs: z.number().int().optional().describe('How long to wait, 10000 by default, 60000 at most'),
10
+ })
11
+ .optional();
12
+ // a tool's answer; an error goes back to the model as text, so it can recover instead of ending the run
13
+ export const attempt = async (call) => {
14
+ try {
15
+ const result = await call();
16
+ return typeof result === 'string' ? result : JSON.stringify(result);
17
+ }
18
+ catch (err) {
19
+ if (err instanceof CodeHarnessError)
20
+ return `Error: ${err.status ?? err.code} ${err.message}`;
21
+ return `Error: ${err instanceof Error ? err.message : String(err)}`;
22
+ }
23
+ };
24
+ export const browserTools = (browser) => {
25
+ const tools = [
26
+ tool(({ url, until }) => attempt(() => browser.navigate(url, { until })), {
27
+ name: 'browser_navigate',
28
+ description: browser.sandboxId
29
+ ? 'Open a URL in the browser and return the page as text and numbered refs. A path like "/" opens the launched app.'
30
+ : 'Open a URL in the browser and return the page as text and numbered refs.',
31
+ schema: z.object({
32
+ url: z.string().describe(browser.sandboxId ? 'A path in the app, or a public URL' : 'A public URL'),
33
+ until: WaitFor,
34
+ }),
35
+ }),
36
+ tool(({ maxChars, waitFor }) => attempt(() => browser.read({ maxChars, waitFor })), {
37
+ name: 'browser_read',
38
+ description: 'Read the current page as text and numbered refs.',
39
+ schema: z.object({ maxChars: z.number().int().optional(), waitFor: WaitFor }),
40
+ }),
41
+ tool(({ ref, waitFor }) => attempt(() => browser.click(ref, { waitFor })), {
42
+ name: 'browser_click',
43
+ description: 'Click the element with this ref and return the page after.',
44
+ schema: z.object({ ref: z.number().int().describe('A ref from the last page read'), waitFor: WaitFor }),
45
+ }),
46
+ tool(({ ref, text, submit, waitFor }) => attempt(() => browser.type(ref, text, { submit, waitFor })), {
47
+ name: 'browser_type',
48
+ description: 'Type into the field with this ref and return the page after.',
49
+ schema: z.object({
50
+ ref: z.number().int().describe('A ref from the last page read'),
51
+ text: z.string(),
52
+ submit: z.boolean().optional().describe('Press Enter after typing'),
53
+ waitFor: WaitFor,
54
+ }),
55
+ }),
56
+ ];
57
+ if (browser.record)
58
+ tools.push(tool(({ fullPage, waitFor }) => attempt(async () => `${ROOT}/${(await browser.screenshot({ fullPage, waitFor })).path}`), {
59
+ name: 'browser_screenshot',
60
+ description: 'Take a PNG screenshot of the page and return its path, which read_file opens.',
61
+ schema: z.object({ fullPage: z.boolean().optional(), waitFor: WaitFor }),
62
+ }));
63
+ return tools;
64
+ };
65
+ export function createBrowserUseMiddleware({ browser }) {
66
+ return createMiddleware({
67
+ name: 'BrowserUseMiddleware',
68
+ tools: browserTools(browser),
69
+ afterAgent: async () => {
70
+ await browser.close();
71
+ },
72
+ });
73
+ }
74
+ //# sourceMappingURL=browser-use.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-use.js","sourceRoot":"","sources":["../../../src/integration/langchain/browser-use.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type StructuredTool } from 'langchain';
2
+ import { type Sandbox } from '../../sandbox.js';
3
+ export declare function createCodeHarnessMiddleware({ sandbox }: {
4
+ sandbox: Sandbox;
5
+ }): import("langchain").AgentMiddleware<undefined, undefined, unknown, StructuredTool<import("@langchain/core/tools").ToolSchemaBase, any, any, any, unknown>[], readonly []>;
@@ -0,0 +1,40 @@
1
+ import { createMiddleware, tool } from 'langchain';
2
+ import { z } from 'zod';
3
+ import { ROOT } from '../../sandbox.js';
4
+ import { attempt, browserTools } from './browser-use.js';
5
+ const PROMPT = `## Code-Harness sandbox
6
+
7
+ Your files are in ${ROOT}, and execute runs commands from there. Install dependencies in the same command that needs them; a later command may not have them.
8
+ Start the app with launch_app, then open it with the browser tools at a path like "/" or "/login". When it fails, read app_logs.`;
9
+ export function createCodeHarnessMiddleware({ sandbox }) {
10
+ const { browser } = sandbox;
11
+ const tools = [
12
+ tool(({ command, port, env }) => attempt(async () => {
13
+ await sandbox.stop();
14
+ return (await sandbox.launch({ command, port, env })).url;
15
+ }), {
16
+ name: 'launch_app',
17
+ description: 'Start the app in the background, stopping the one running, and return its public URL once it listens on port. Put the install step in the command, like "npm ci && npm start".',
18
+ schema: z.object({
19
+ command: z.string().describe('Shell command that starts the app'),
20
+ port: z.number().int().describe('Port the app listens on; PORT is set to it'),
21
+ env: z.record(z.string(), z.string()).optional().describe('Env for the app'),
22
+ }),
23
+ }),
24
+ tool(({ tail }) => attempt(async () => (await sandbox.logs({ tail })).join('\n')), {
25
+ name: 'app_logs',
26
+ description: 'The last lines the app wrote. After it ends, the last line says how.',
27
+ schema: z.object({ tail: z.number().int().optional().describe('How many lines, 200 by default, 1000 at most') }),
28
+ }),
29
+ ...browserTools(browser),
30
+ ];
31
+ return createMiddleware({
32
+ name: 'CodeHarnessMiddleware',
33
+ tools,
34
+ wrapModelCall: (request, handler) => handler({ ...request, systemMessage: request.systemMessage.concat(PROMPT) }),
35
+ afterAgent: async () => {
36
+ await browser.close();
37
+ },
38
+ });
39
+ }
40
+ //# sourceMappingURL=code-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-harness.js","sourceRoot":"","sources":["../../../src/integration/langchain/code-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAuB,IAAI,EAAE,MAAM,WAAW,CAAA;AACvE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,IAAI,EAAgB,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAExD,MAAM,MAAM,GAAG;;oBAEK,IAAI;iIACyG,CAAA;AAEjI,MAAM,UAAU,2BAA2B,CAAC,EAAE,OAAO,EAAwB;IAC3E,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IAE3B,MAAM,KAAK,GAAqB;QAC9B,IAAI,CACF,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CACzB,OAAO,CAAC,KAAK,IAAI,EAAE;YACjB,MAAM,OAAO,CAAC,IAAI,EAAE,CAAA;YACpB,OAAO,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;QAC3D,CAAC,CAAC,EACJ;YACE,IAAI,EAAE,YAAY;YAClB,WAAW,EACT,gLAAgL;YAClL,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;gBACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;gBACjE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;gBAC7E,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;aAC7E,CAAC;SACH,CACF;QACD,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;YACjF,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,sEAAsE;YACnF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC,EAAE,CAAC;SACjH,CAAC;QACF,GAAG,YAAY,CAAC,OAAO,CAAC;KACzB,CAAA;IAED,OAAO,gBAAgB,CAAC;QACtB,IAAI,EAAE,uBAAuB;QAC7B,KAAK;QACL,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACjH,UAAU,EAAE,KAAK,IAAI,EAAE;YACrB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;QACvB,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { createSkillsMiddleware } from 'deepagents';
2
+ import type { Sandbox } from '../../sandbox.js';
3
+ export declare function createSkillUseMiddleware({ sandbox, sources, }: {
4
+ sandbox: Sandbox;
5
+ sources: string[];
6
+ }): ReturnType<typeof createSkillsMiddleware>;
@@ -0,0 +1,5 @@
1
+ import { createSkillsMiddleware } from 'deepagents';
2
+ export function createSkillUseMiddleware({ sandbox, sources, }) {
3
+ return createSkillsMiddleware({ backend: sandbox, sources });
4
+ }
5
+ //# sourceMappingURL=skill-use.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-use.js","sourceRoot":"","sources":["../../../src/integration/langchain/skill-use.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAInD,MAAM,UAAU,wBAAwB,CAAC,EACvC,OAAO,EACP,OAAO,GAIR;IACC,OAAO,sBAAsB,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;AAC9D,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { BaseSandbox, type ExecuteResponse, type FileDownloadResponse, type FileUploadResponse } from 'deepagents';
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';
6
+ export declare class Sandbox extends BaseSandbox {
7
+ #private;
8
+ readonly id: string;
9
+ readonly name: string;
10
+ readonly envKeys: string[];
11
+ readonly createdAt: Date;
12
+ readonly browser: Browser;
13
+ constructor(client: BaseClient, workspace: Workspace, options?: SandboxOptions);
14
+ execute(command: string): Promise<ExecuteResponse>;
15
+ uploadFiles(files: Array<[string, Uint8Array]>): Promise<FileUploadResponse[]>;
16
+ downloadFiles(paths: string[]): Promise<FileDownloadResponse[]>;
17
+ uploadAsZip(zip: Blob | Uint8Array<ArrayBuffer> | ArrayBuffer, options?: {
18
+ path?: string;
19
+ }): Promise<{
20
+ path: string;
21
+ files: number;
22
+ }>;
23
+ launch(options: LaunchOptions): Promise<{
24
+ url: string;
25
+ }>;
26
+ logs(options?: {
27
+ tail?: number;
28
+ }): Promise<string[]>;
29
+ stop(): Promise<void>;
30
+ close(): Promise<void>;
31
+ }
@@ -0,0 +1,46 @@
1
+ import { BaseSandbox, } from 'deepagents';
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
5
+ export class Sandbox extends BaseSandbox {
6
+ id;
7
+ name;
8
+ envKeys;
9
+ createdAt;
10
+ browser;
11
+ #sandbox;
12
+ constructor(client, workspace, options = {}) {
13
+ super();
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;
20
+ }
21
+ execute(command) {
22
+ return this.#sandbox.execute(command);
23
+ }
24
+ uploadFiles(files) {
25
+ return this.#sandbox.uploadFiles(files);
26
+ }
27
+ downloadFiles(paths) {
28
+ return this.#sandbox.downloadFiles(paths);
29
+ }
30
+ uploadAsZip(zip, options = {}) {
31
+ return this.#sandbox.uploadAsZip(zip, options);
32
+ }
33
+ launch(options) {
34
+ return this.#sandbox.launch(options);
35
+ }
36
+ logs(options = {}) {
37
+ return this.#sandbox.logs(options);
38
+ }
39
+ stop() {
40
+ return this.#sandbox.stop();
41
+ }
42
+ close() {
43
+ return this.#sandbox.close();
44
+ }
45
+ }
46
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
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"}