@bctrl/sdk 1.0.3 → 1.0.4

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/README.md CHANGED
@@ -24,19 +24,17 @@ const space = await bctrl.spaces.create({
24
24
  region: 'us-east-1',
25
25
  });
26
26
 
27
- const runtime = await space.runtimes.create({
27
+ const createdRuntime = await space.runtimes.create({
28
28
  type: 'browser',
29
29
  name: 'browser-task',
30
30
  config: {
31
- browser: { profile: false },
31
+ profile: false,
32
32
  },
33
33
  });
34
- const { runtime: browser } = await runtime.start();
34
+ const started = await createdRuntime.start();
35
+ console.log(started.run.id, started.browser.cdpUrl);
35
36
 
36
- const connection = await browser.connect();
37
- console.log(connection.wsUrl);
38
-
39
- const invocation = await browser.invocations.create({
37
+ const invocation = await started.runtime.invocations.create({
40
38
  provider: 'stagehand',
41
39
  method: 'act',
42
40
  input: { instruction: 'Open https://example.com' },
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { BctrlError, BctrlApiError, BctrlAuthenticationError, BctrlConflictError
3
3
  export { V1FileResource, V1FilesClient, V1RunFilesClient } from './files.js';
4
4
  export { V1InvocationsClient, V1InvocationResource, V1RuntimeBrowserUseInvocationsClient, V1RuntimeInvocationsClient, V1RuntimeStagehandInvocationsClient, } from './invocations.js';
5
5
  export type { BrowserUseAgentOptions, StagehandActOptions, StagehandAgentOptions, StagehandExtractOptions, StagehandObserveOptions, StagehandVariablePrimitive, StagehandVariableValue, StagehandVariables, } from './invocations.js';
6
- export { V1RuntimeConnectionResource, V1RuntimeConnectionsClient, V1RuntimeFilesClient, V1RuntimeResource, V1RuntimeRunsClient, V1RuntimesClient, } from './runtimes.js';
7
- export { V1RunCommandsClient, V1RunEventsClient, V1RunResource, V1RunsClient, } from './runs.js';
6
+ export { V1RuntimeFilesClient, V1RuntimeResource, V1RuntimeRunsClient, V1RuntimesClient, } from './runtimes.js';
7
+ export { V1RunCommandsClient, V1RunEventsClient, V1RunResource, V1RunsClient } from './runs.js';
8
8
  export { V1SpaceEnvironmentClient, V1SpaceResource, V1SpaceRuntimesClient, V1SpacesClient, } from './spaces.js';
9
9
  export type * from './types.js';
package/dist/index.js CHANGED
@@ -2,6 +2,6 @@ export { Bctrl, BctrlV1 } from './bctrl.js';
2
2
  export { BctrlError, BctrlApiError, BctrlAuthenticationError, BctrlConflictError, BctrlNetworkError, BctrlNotFoundError, BctrlNotReadyError, BctrlPermissionError, BctrlRateLimitError, BctrlUnsupportedError, BctrlValidationError, isControllerBusy, } from './errors.js';
3
3
  export { V1FileResource, V1FilesClient, V1RunFilesClient } from './files.js';
4
4
  export { V1InvocationsClient, V1InvocationResource, V1RuntimeBrowserUseInvocationsClient, V1RuntimeInvocationsClient, V1RuntimeStagehandInvocationsClient, } from './invocations.js';
5
- export { V1RuntimeConnectionResource, V1RuntimeConnectionsClient, V1RuntimeFilesClient, V1RuntimeResource, V1RuntimeRunsClient, V1RuntimesClient, } from './runtimes.js';
6
- export { V1RunCommandsClient, V1RunEventsClient, V1RunResource, V1RunsClient, } from './runs.js';
5
+ export { V1RuntimeFilesClient, V1RuntimeResource, V1RuntimeRunsClient, V1RuntimesClient, } from './runtimes.js';
6
+ export { V1RunCommandsClient, V1RunEventsClient, V1RunResource, V1RunsClient } from './runs.js';
7
7
  export { V1SpaceEnvironmentClient, V1SpaceResource, V1SpaceRuntimesClient, V1SpacesClient, } from './spaces.js';
package/dist/runs.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { V1HttpClient } from './http.js';
2
2
  import { V1RunFilesClient } from './files.js';
3
- import type { V1ListEnvelope, V1Run, V1RunCommand, V1RunCommandsListQuery, V1RunEvent, V1RunEventsListQuery, V1RunEventsWaitRequest, V1RunEventsWaitResponse, V1RunListQuery, V1RunLiveRequest, V1RunLiveResponse, V1RunRecordingRequest, V1RunRecordingResponse, V1RunUsage } from './types.js';
3
+ import type { V1ListEnvelope, V1Run, V1RunCommand, V1RunCommandsListQuery, V1RunEvent, V1RunEventsListQuery, V1RunEventsWaitRequest, V1RunEventsWaitResponse, V1RunListQuery, V1RunLiveRequest, V1RunLiveResponse, V1RunRecordingRequest, V1RunRecordingResponse, V1RuntimeStartRun, V1RunUsage } from './types.js';
4
4
  export declare class V1RunEventsClient {
5
5
  private readonly http;
6
6
  private readonly runId;
@@ -19,11 +19,11 @@ export declare class V1RunCommandsClient {
19
19
  }
20
20
  export declare class V1RunResource {
21
21
  private readonly http;
22
- readonly data: V1Run;
22
+ readonly data: V1Run | V1RuntimeStartRun;
23
23
  readonly events: V1RunEventsClient;
24
24
  readonly commands: V1RunCommandsClient;
25
25
  readonly files: V1RunFilesClient;
26
- constructor(http: V1HttpClient, data: V1Run);
26
+ constructor(http: V1HttpClient, data: V1Run | V1RuntimeStartRun);
27
27
  get id(): string;
28
28
  refresh(): Promise<V1RunResource>;
29
29
  live(request?: V1RunLiveRequest): Promise<V1RunLiveResponse>;
@@ -1,24 +1,12 @@
1
1
  import type { V1HttpClient } from './http.js';
2
2
  import { V1RuntimeInvocationsClient } from './invocations.js';
3
3
  import { V1RunResource } from './runs.js';
4
- import type { V1ListEnvelope, V1File, V1Runtime, V1RuntimeConnection, V1RuntimeConnectionCreateOptions, V1RuntimeConnectionCreateResponse, V1RuntimeCreateRequest, V1RuntimeFileCollectRequest, V1RuntimeFileStageRequest, V1RuntimeFileUploadRequest, V1RuntimeFileUploadResponse, V1RuntimeStagedFile, V1RuntimeListQuery, V1RuntimeRunListQuery, V1RunSummary, V1SpaceRuntimeCreateRequest } from './types.js';
5
- export declare class V1RuntimeConnectionResource {
6
- private readonly http;
7
- private readonly runtimeId;
8
- readonly data: V1RuntimeConnectionCreateResponse;
9
- constructor(http: V1HttpClient, runtimeId: string, data: V1RuntimeConnectionCreateResponse);
10
- get id(): string;
11
- get endpoint(): V1RuntimeConnectionCreateResponse['endpoint'];
12
- get wsUrl(): string | undefined;
13
- close(): Promise<V1RuntimeConnection>;
14
- }
15
- export declare class V1RuntimeConnectionsClient {
16
- private readonly http;
17
- private readonly runtimeId;
18
- constructor(http: V1HttpClient, runtimeId: string);
19
- create(request?: V1RuntimeConnectionCreateOptions): Promise<V1RuntimeConnectionResource>;
20
- delete(connectionId: string): Promise<V1RuntimeConnection>;
21
- }
4
+ import type { V1ListEnvelope, V1File, V1Runtime, V1RuntimeCreateRequest, V1RuntimeFileCollectRequest, V1RuntimeFileStageRequest, V1RuntimeFileUploadRequest, V1RuntimeFileUploadResponse, V1RuntimeStagedFile, V1RuntimeListQuery, V1RuntimeRunListQuery, V1RuntimeStartBrowser, V1RuntimeStartRuntime, V1RunSummary, V1SpaceRuntimeCreateRequest } from './types.js';
5
+ export type V1RuntimeStartResult = {
6
+ runtime: V1RuntimeResource;
7
+ run: V1RunResource;
8
+ browser: V1RuntimeStartBrowser;
9
+ };
22
10
  export declare class V1RuntimeRunsClient {
23
11
  private readonly http;
24
12
  private readonly runtimeId;
@@ -36,20 +24,15 @@ export declare class V1RuntimeFilesClient {
36
24
  }
37
25
  export declare class V1RuntimeResource {
38
26
  private readonly http;
39
- readonly data: V1Runtime;
40
- readonly connections: V1RuntimeConnectionsClient;
27
+ readonly data: V1Runtime | V1RuntimeStartRuntime;
41
28
  readonly files: V1RuntimeFilesClient;
42
29
  readonly runs: V1RuntimeRunsClient;
43
30
  readonly invocations: V1RuntimeInvocationsClient;
44
- constructor(http: V1HttpClient, data: V1Runtime);
31
+ constructor(http: V1HttpClient, data: V1Runtime | V1RuntimeStartRuntime);
45
32
  get id(): string;
46
33
  get activeRunId(): string | null;
47
34
  refresh(): Promise<V1RuntimeResource>;
48
- connect(request?: V1RuntimeConnectionCreateOptions): Promise<V1RuntimeConnectionResource>;
49
- start(): Promise<{
50
- runtime: V1RuntimeResource;
51
- run: V1RunResource;
52
- }>;
35
+ start(): Promise<V1RuntimeStartResult>;
53
36
  stop(): Promise<V1Runtime>;
54
37
  run(): Promise<V1RunResource>;
55
38
  }
@@ -62,8 +45,5 @@ export declare class V1RuntimesClient {
62
45
  createInSpace(spaceId: string, request: V1SpaceRuntimeCreateRequest): Promise<V1RuntimeResource>;
63
46
  get(id: string): Promise<V1RuntimeResource>;
64
47
  stop(id: string): Promise<V1Runtime>;
65
- start(id: string): Promise<{
66
- runtime: V1RuntimeResource;
67
- run: V1RunResource;
68
- }>;
48
+ start(id: string): Promise<V1RuntimeStartResult>;
69
49
  }
package/dist/runtimes.js CHANGED
@@ -2,49 +2,6 @@ import { BctrlValidationError } from './errors.js';
2
2
  import { V1RuntimeInvocationsClient } from './invocations.js';
3
3
  import { iterateV1Pages } from './pagination.js';
4
4
  import { V1RunResource } from './runs.js';
5
- export class V1RuntimeConnectionResource {
6
- http;
7
- runtimeId;
8
- data;
9
- constructor(http, runtimeId, data) {
10
- this.http = http;
11
- this.runtimeId = runtimeId;
12
- this.data = data;
13
- }
14
- get id() {
15
- return this.data.id;
16
- }
17
- get endpoint() {
18
- return this.data.endpoint;
19
- }
20
- get wsUrl() {
21
- return this.data.endpoint.type === 'websocket' ? this.data.endpoint.url : undefined;
22
- }
23
- close() {
24
- return this.http.request(`/runtimes/${encodeURIComponent(this.runtimeId)}/connections/${encodeURIComponent(this.id)}`, { method: 'DELETE' });
25
- }
26
- }
27
- export class V1RuntimeConnectionsClient {
28
- http;
29
- runtimeId;
30
- constructor(http, runtimeId) {
31
- this.http = http;
32
- this.runtimeId = runtimeId;
33
- }
34
- async create(request = {}) {
35
- const response = await this.http.request(`/runtimes/${encodeURIComponent(this.runtimeId)}/connections`, {
36
- method: 'POST',
37
- body: {
38
- protocol: request.protocol ?? 'cdp',
39
- ...request,
40
- },
41
- });
42
- return new V1RuntimeConnectionResource(this.http, this.runtimeId, response);
43
- }
44
- delete(connectionId) {
45
- return this.http.request(`/runtimes/${encodeURIComponent(this.runtimeId)}/connections/${encodeURIComponent(connectionId)}`, { method: 'DELETE' });
46
- }
47
- }
48
5
  export class V1RuntimeRunsClient {
49
6
  http;
50
7
  runtimeId;
@@ -100,14 +57,12 @@ export class V1RuntimeFilesClient {
100
57
  export class V1RuntimeResource {
101
58
  http;
102
59
  data;
103
- connections;
104
60
  files;
105
61
  runs;
106
62
  invocations;
107
63
  constructor(http, data) {
108
64
  this.http = http;
109
65
  this.data = data;
110
- this.connections = new V1RuntimeConnectionsClient(http, data.id);
111
66
  this.files = new V1RuntimeFilesClient(http, data.id);
112
67
  this.runs = new V1RuntimeRunsClient(http, data.id);
113
68
  this.invocations = new V1RuntimeInvocationsClient(http, data.id);
@@ -116,19 +71,17 @@ export class V1RuntimeResource {
116
71
  return this.data.id;
117
72
  }
118
73
  get activeRunId() {
119
- return this.data.activeRunId;
74
+ return 'activeRunId' in this.data ? this.data.activeRunId : null;
120
75
  }
121
76
  refresh() {
122
77
  return new V1RuntimesClient(this.http).get(this.id);
123
78
  }
124
- async connect(request) {
125
- return this.connections.create(request);
126
- }
127
79
  async start() {
128
80
  const response = await this.http.request(`/runtimes/${encodeURIComponent(this.id)}/start`, { method: 'POST' });
129
81
  return {
130
82
  runtime: new V1RuntimeResource(this.http, response.runtime),
131
83
  run: new V1RunResource(this.http, response.run),
84
+ browser: response.browser,
132
85
  };
133
86
  }
134
87
  stop() {
@@ -138,25 +91,26 @@ export class V1RuntimeResource {
138
91
  }
139
92
  async run() {
140
93
  const runtime = await this.refresh();
141
- if (!runtime.activeRunId) {
94
+ const activeRunId = runtime.activeRunId;
95
+ if (!activeRunId) {
142
96
  throw new BctrlValidationError('Runtime does not have an active run yet', 'runtime.no_active_run', {
143
97
  runtimeId: this.id,
144
98
  });
145
99
  }
146
- const run = await this.http.request(`/runs/${encodeURIComponent(runtime.activeRunId)}`);
100
+ const run = await this.http.request(`/runs/${encodeURIComponent(activeRunId)}`);
147
101
  return new V1RunResource(this.http, run);
148
102
  }
149
103
  }
150
104
  function validateRuntimeCreateRequest(request) {
151
- const profileBacked = request.config?.browser?.profile === true;
105
+ const profileBacked = request.config?.profile === true;
152
106
  if (!profileBacked)
153
107
  return;
154
108
  if (!request.name?.trim()) {
155
- throw new BctrlValidationError('name is required when config.browser.profile is true', 'runtime.profile_name_required');
109
+ throw new BctrlValidationError('name is required when config.profile is true', 'runtime.profile_name_required');
156
110
  }
157
111
  const unsupported = ['stealth', 'proxy', 'fingerprint', 'extensions'].filter((key) => request.config?.[key] !== undefined);
158
112
  if (unsupported.length > 0) {
159
- throw new BctrlValidationError('Only config.browser.profile and config.lifecycle are supported for profile-backed browser runtimes', 'runtime.profile_config_unsupported', { unsupported });
113
+ throw new BctrlValidationError('Only config.profile, config.idleTimeoutMinutes, config.webRtcProxyOnly, and config.forceOpenShadowRoots are supported for profile-backed browser runtimes', 'runtime.profile_config_unsupported', { unsupported });
160
114
  }
161
115
  }
162
116
  export class V1RuntimesClient {
package/dist/types.d.ts CHANGED
@@ -54,18 +54,15 @@ export interface V1RuntimeFingerprintCreateConfig {
54
54
  browser?: string;
55
55
  locale?: string;
56
56
  }
57
- export interface V1RuntimeLifecycleConfig {
58
- idleTimeoutMinutes?: number;
59
- }
60
57
  export interface V1BrowserRuntimeCreateConfig {
61
- browser?: {
62
- profile?: boolean;
63
- };
58
+ profile?: boolean;
64
59
  stealth?: V1BrowserStealth;
65
60
  proxy?: V1ProxyInput | null;
66
61
  fingerprint?: V1RuntimeFingerprintCreateConfig;
67
62
  extensions?: string[];
68
- lifecycle?: V1RuntimeLifecycleConfig;
63
+ idleTimeoutMinutes?: number;
64
+ webRtcProxyOnly?: boolean;
65
+ forceOpenShadowRoots?: boolean;
69
66
  }
70
67
  export interface V1RuntimeCreateRequest {
71
68
  spaceId: string;
@@ -93,44 +90,26 @@ export interface V1Runtime extends V1RuntimeSummary {
93
90
  config?: JsonObject;
94
91
  metadata?: JsonObject | null;
95
92
  }
96
- export type V1ConnectionProtocol = 'cdp' | 'cua' | 'rdp' | 'vnc' | 'mcp' | 'http';
97
- export type V1ConnectionEndpoint = {
98
- type: 'websocket';
99
- url: string;
100
- } | {
101
- type: 'http';
102
- baseUrl: string;
103
- } | {
104
- type: 'rdp';
105
- host: string;
106
- port: number;
107
- username: string;
108
- password: string;
109
- } | {
110
- type: 'composite';
111
- endpoints: Record<string, string>;
112
- };
113
- export interface V1RuntimeConnectionCreateRequest {
114
- protocol: 'cdp';
115
- options?: JsonObject;
116
- }
117
- export type V1RuntimeConnectionCreateOptions = Partial<V1RuntimeConnectionCreateRequest>;
118
- export interface V1RuntimeConnection {
93
+ export interface V1RuntimeStartRuntime {
119
94
  id: string;
120
- protocol: V1ConnectionProtocol;
121
- status: string;
122
- runId: string;
123
- createdAt: string;
124
- expiresAt: string | null;
125
- closedAt?: string | null;
126
- revokedAt?: string | null;
95
+ name: string;
96
+ type: V1RuntimeType;
97
+ status: V1RuntimeStatus;
98
+ }
99
+ export interface V1RuntimeStartRun extends V1RunSummary {
100
+ durationMs?: number | null;
101
+ lastSeenAt?: string | null;
102
+ endedReason?: string | null;
103
+ failureReason?: string | null;
127
104
  }
128
- export interface V1RuntimeConnectionCreateResponse extends V1RuntimeConnection {
129
- endpoint: V1ConnectionEndpoint;
105
+ export interface V1RuntimeStartBrowser {
106
+ cdpUrl: string;
107
+ connectionId: string;
130
108
  }
131
109
  export interface V1RuntimeStartResponse {
132
- runtime: V1Runtime;
133
- run: V1Run;
110
+ runtime: V1RuntimeStartRuntime;
111
+ run: V1RuntimeStartRun;
112
+ browser: V1RuntimeStartBrowser;
134
113
  }
135
114
  export interface V1RunListQuery extends V1PageQuery {
136
115
  status?: string | string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bctrl/sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "BCTRL SDK - Remote browser automation",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,20 +11,9 @@
11
11
  "import": "./dist/index.js"
12
12
  }
13
13
  },
14
- "scripts": {
15
- "clean": "rm -rf dist",
16
- "build": "pnpm run clean && tsc -p tsconfig.json",
17
- "prepack": "pnpm run build",
18
- "dev": "tsc --watch",
19
- "test": "tsx --test tests/v1/*.test.ts tests/v1/e2e/*.test.ts",
20
- "test:v1": "tsx --test tests/v1/*.test.ts tests/v1/e2e/*.test.ts",
21
- "test:v1:e2e": "BCTRL_E2E=1 tsx --test tests/v1/e2e/**/*.test.ts",
22
- "typecheck": "tsc --noEmit"
23
- },
24
14
  "keywords": [],
25
15
  "author": "",
26
16
  "license": "ISC",
27
- "packageManager": "pnpm@10.12.4",
28
17
  "devDependencies": {
29
18
  "@types/node": "^25.0.3",
30
19
  "@typescript-eslint/eslint-plugin": "^8.56.0",
@@ -35,5 +24,14 @@
35
24
  },
36
25
  "files": [
37
26
  "dist"
38
- ]
39
- }
27
+ ],
28
+ "scripts": {
29
+ "clean": "rm -rf dist",
30
+ "build": "pnpm run clean && tsc -p tsconfig.json",
31
+ "dev": "tsc --watch",
32
+ "test": "tsx --test tests/v1/*.test.ts tests/v1/e2e/*.test.ts",
33
+ "test:v1": "tsx --test tests/v1/*.test.ts tests/v1/e2e/*.test.ts",
34
+ "test:v1:e2e": "BCTRL_E2E=1 tsx --test tests/v1/e2e/**/*.test.ts",
35
+ "typecheck": "tsc --noEmit"
36
+ }
37
+ }