@bctrl/sdk 1.0.8 → 1.0.10

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 BCTRL
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any purpose
6
+ with or without fee is hereby granted, provided that the above copyright notice
7
+ and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
11
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
13
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14
+ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
15
+ THIS SOFTWARE.
package/README.md CHANGED
@@ -1,72 +1,116 @@
1
- # @bctrl/sdk
2
-
3
- TypeScript SDK for BCTRL v1 spaces, browser runtimes, invocations, runs, and files.
4
-
5
- ## Install
6
-
7
- ```bash
8
- npm install @bctrl/sdk
9
- ```
10
-
11
- Node 18+ is required.
12
-
13
- ## Quick start
14
-
15
- ```ts
16
- import { Bctrl } from '@bctrl/sdk';
17
- import { z } from 'zod';
18
-
19
- const bctrl = new Bctrl({
20
- apiKey: process.env.BCTRL_API_KEY!,
21
- });
22
-
23
- const runtime = await bctrl.runtimes.create({
24
- type: 'browser',
25
- name: 'browser-task',
26
- });
27
- const started = await bctrl.runtimes.start(runtime.id);
28
- console.log(started.runId, started.connectUrl);
29
-
30
- const invocation = await bctrl.runtimes.invocations.createAndWait(
31
- started.runtimeId,
32
- {
33
- action: 'extract',
34
- instruction: 'Extract the page title.',
35
- schema: z.object({
36
- title: z.string(),
37
- }),
38
- },
39
- { timeoutMs: 60_000 }
40
- );
41
-
42
- console.log(invocation.status, invocation.output);
43
-
44
- await bctrl.runtimes.stop(started.runtimeId);
45
- ```
46
-
47
- The public SDK targets `https://api.bctrl.ai/v1`. For local development, pass a
48
- local origin or v1 base URL:
49
-
50
- ```ts
51
- const bctrl = new Bctrl({
52
- apiKey: process.env.BCTRL_API_KEY!,
53
- baseUrl: 'http://localhost:8787',
54
- });
55
- ```
56
-
57
- `baseUrl` may include or omit `/v1`; the client normalizes either form.
58
-
59
- ## Entry points
60
-
61
- - `@bctrl/sdk`: v1 client, resources, errors, and public types
62
-
63
- ## Documentation
64
-
65
- - SDK reference: https://platform.bctrl.ai/api-reference/sdk/overview
66
- - Product site: https://bctrl.ai
67
-
68
- ## Telemetry
69
-
70
- The published SDK does not include vendor-owned telemetry or usage analytics.
71
-
72
- If you want observability around SDK calls, instrument your application directly with your own logging or error tracking.
1
+ # @bctrl/sdk
2
+
3
+ TypeScript and JavaScript SDK for BCTRL cloud browser automation. Create browser runtimes, start live sessions, run hosted browser agents, inspect runs, and manage platform resources from Node.js.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @bctrl/sdk
9
+ ```
10
+
11
+ Requires Node.js 22.14 or newer.
12
+
13
+ ## Quick Start
14
+
15
+ ```ts
16
+ import { Bctrl } from '@bctrl/sdk';
17
+
18
+ const bctrl = new Bctrl({
19
+ apiKey: process.env.BCTRL_API_KEY!,
20
+ });
21
+
22
+ const runtime = await bctrl.runtimes.create({
23
+ type: 'browser',
24
+ name: 'browser-task',
25
+ });
26
+
27
+ const started = await bctrl.runtimes.start(runtime.id);
28
+ console.log(started.runId, started.connectUrl);
29
+
30
+ await bctrl.runtimes.targets.create(started.runtimeId, {
31
+ uri: 'https://example.com',
32
+ activate: true,
33
+ });
34
+
35
+ await bctrl.runtimes.stop(started.runtimeId);
36
+ ```
37
+
38
+ ## Hosted Invocations
39
+
40
+ Use invocations when you want BCTRL to drive the browser for you.
41
+
42
+ ```ts
43
+ import { Bctrl } from '@bctrl/sdk';
44
+ import { z } from 'zod';
45
+
46
+ const bctrl = new Bctrl();
47
+
48
+ const invocation = await bctrl.runtimes.invocations.createAndWait(
49
+ '<runtime-id>',
50
+ {
51
+ action: 'extract',
52
+ instruction: 'Extract the product name and price.',
53
+ schema: z.object({
54
+ name: z.string(),
55
+ price: z.string(),
56
+ }),
57
+ },
58
+ { timeoutSeconds: 60 }
59
+ );
60
+
61
+ console.log(invocation.status, invocation.output);
62
+ ```
63
+
64
+ The SDK accepts Zod schemas or plain JSON Schema for structured extraction. On the wire, they are sent as `outputSchema`.
65
+
66
+ ## Configuration
67
+
68
+ The client reads `BCTRL_API_KEY` by default:
69
+
70
+ ```ts
71
+ const bctrl = new Bctrl();
72
+ ```
73
+
74
+ You can also pass configuration explicitly:
75
+
76
+ ```ts
77
+ const bctrl = new Bctrl({
78
+ apiKey: 'bctrl_...',
79
+ timeoutMs: 30_000,
80
+ maxRetries: 2,
81
+ });
82
+ ```
83
+
84
+ For subaccount-scoped calls:
85
+
86
+ ```ts
87
+ const scoped = bctrl.withSubaccount('<subaccount-id>');
88
+ ```
89
+
90
+ ## Errors
91
+
92
+ API failures throw typed errors with status, code, request id, and response body context:
93
+
94
+ ```ts
95
+ import { BctrlApiError } from '@bctrl/sdk';
96
+
97
+ try {
98
+ await bctrl.runtimes.get('<runtime-id>');
99
+ } catch (error) {
100
+ if (error instanceof BctrlApiError) {
101
+ console.error(error.status, error.code, error.requestId);
102
+ }
103
+ }
104
+ ```
105
+
106
+ The client retries retryable GET requests by default. Mutating requests are retried only when you provide an idempotency key.
107
+
108
+ ## Documentation
109
+
110
+ - SDK guide: https://platform.bctrl.ai/sdk
111
+ - API reference: https://platform.bctrl.ai/api-reference
112
+ - Product: https://bctrl.ai
113
+
114
+ ## Telemetry
115
+
116
+ The SDK does not include vendor-owned telemetry or usage analytics. Instrument your application directly if you want request logging or tracing.
package/dist/account.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { V1HttpClient } from './http.js';
2
+ import { V1NotificationRecipientsClient } from './notificationRecipients.js';
2
3
  import type { V1AccountUsage, V1ApiKey, V1ApiKeyCreateRequest, V1ApiKeyCreateResponse, V1ApiKeyDeleteResponse, V1ApiKeyListQuery, V1AuthWhoamiResponse, V1ListEnvelope, V1Subaccount, V1SubaccountArchiveResponse, V1SubaccountCreateRequest, V1SubaccountGetQuery, V1SubaccountListQuery, V1SubaccountUpdateRequest, V1SubaccountUsage, V1SubaccountUsageListQuery } from './types.js';
3
4
  export declare class V1AuthClient {
4
5
  private readonly http;
@@ -37,6 +38,7 @@ export declare class V1UsageClient {
37
38
  }
38
39
  export declare class V1AccountClient {
39
40
  readonly apiKeys: V1ApiKeysClient;
41
+ readonly notificationRecipients: V1NotificationRecipientsClient;
40
42
  readonly subaccounts: V1SubaccountsClient;
41
43
  readonly usage: V1UsageClient;
42
44
  constructor(http: V1HttpClient);
package/dist/account.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { V1NotificationRecipientsClient } from './notificationRecipients.js';
1
2
  import { iterateV1Pages } from './pagination.js';
2
3
  export class V1AuthClient {
3
4
  http;
@@ -90,10 +91,12 @@ export class V1UsageClient {
90
91
  }
91
92
  export class V1AccountClient {
92
93
  apiKeys;
94
+ notificationRecipients;
93
95
  subaccounts;
94
96
  usage;
95
97
  constructor(http) {
96
98
  this.apiKeys = new V1ApiKeysClient(http);
99
+ this.notificationRecipients = new V1NotificationRecipientsClient(http);
97
100
  this.subaccounts = new V1SubaccountsClient(http);
98
101
  this.usage = new V1UsageClient(http);
99
102
  }
package/dist/bctrl.d.ts CHANGED
@@ -4,6 +4,7 @@ import { V1BrowserExtensionsClient } from './browserExtensions.js';
4
4
  import { V1FilesClient } from './files.js';
5
5
  import { V1HelpClient } from './help.js';
6
6
  import { type V1ClientOptions } from './http.js';
7
+ import { V1NotificationRecipientsClient } from './notificationRecipients.js';
7
8
  import { V1ProxiesClient } from './proxies.js';
8
9
  import { V1RunsClient } from './runs.js';
9
10
  import { V1RuntimesClient } from './runtimes.js';
@@ -14,6 +15,7 @@ import { V1ToolsetsClient } from './toolsets.js';
14
15
  import { V1VaultClient } from './vault.js';
15
16
  export type BctrlV1Options = V1ClientOptions;
16
17
  export declare class BctrlV1 {
18
+ private readonly options;
17
19
  private readonly http;
18
20
  private _spaces;
19
21
  private _runtimes;
@@ -32,8 +34,10 @@ export declare class BctrlV1 {
32
34
  private _auth;
33
35
  private _subaccounts;
34
36
  private _usage;
37
+ private _notificationRecipients;
35
38
  static isControllerBusy(error: unknown): boolean;
36
39
  constructor(options?: BctrlV1Options);
40
+ withSubaccount(subaccountId: string): BctrlV1;
37
41
  get spaces(): V1SpacesClient;
38
42
  get runtimes(): V1RuntimesClient;
39
43
  get runs(): V1RunsClient;
@@ -51,5 +55,6 @@ export declare class BctrlV1 {
51
55
  get auth(): V1AuthClient;
52
56
  get subaccounts(): V1SubaccountsClient;
53
57
  get usage(): V1UsageClient;
58
+ get notificationRecipients(): V1NotificationRecipientsClient;
54
59
  }
55
60
  export { BctrlV1 as Bctrl };
package/dist/bctrl.js CHANGED
@@ -5,6 +5,7 @@ import { isControllerBusy } from './errors.js';
5
5
  import { V1FilesClient } from './files.js';
6
6
  import { V1HelpClient } from './help.js';
7
7
  import { V1HttpClient } from './http.js';
8
+ import { V1NotificationRecipientsClient } from './notificationRecipients.js';
8
9
  import { V1ProxiesClient } from './proxies.js';
9
10
  import { V1RunsClient } from './runs.js';
10
11
  import { V1RuntimesClient } from './runtimes.js';
@@ -14,6 +15,7 @@ import { V1ToolsClient } from './tools.js';
14
15
  import { V1ToolsetsClient } from './toolsets.js';
15
16
  import { V1VaultClient } from './vault.js';
16
17
  export class BctrlV1 {
18
+ options;
17
19
  http;
18
20
  _spaces = null;
19
21
  _runtimes = null;
@@ -32,11 +34,16 @@ export class BctrlV1 {
32
34
  _auth = null;
33
35
  _subaccounts = null;
34
36
  _usage = null;
37
+ _notificationRecipients = null;
35
38
  static isControllerBusy(error) {
36
39
  return isControllerBusy(error);
37
40
  }
38
41
  constructor(options = {}) {
39
- this.http = new V1HttpClient(options);
42
+ this.options = { ...options };
43
+ this.http = new V1HttpClient(this.options);
44
+ }
45
+ withSubaccount(subaccountId) {
46
+ return new BctrlV1({ ...this.options, subaccountId });
40
47
  }
41
48
  get spaces() {
42
49
  this._spaces ??= new V1SpacesClient(this.http);
@@ -106,5 +113,9 @@ export class BctrlV1 {
106
113
  this._usage ??= new V1UsageClient(this.http);
107
114
  return this._usage;
108
115
  }
116
+ get notificationRecipients() {
117
+ this._notificationRecipients ??= new V1NotificationRecipientsClient(this.http);
118
+ return this._notificationRecipients;
119
+ }
109
120
  }
110
121
  export { BctrlV1 as Bctrl };
@@ -8,8 +8,6 @@ export interface V1BrowserExtensionUploadRequest {
8
8
  file: Blob;
9
9
  /** Optional display name. Defaults to manifest.name. */
10
10
  name?: string;
11
- /** Parent/org keys may create inside a child subaccount. */
12
- subaccountId?: string;
13
11
  }
14
12
  export type V1BrowserExtensionImportRequest = OpenApiSchemas['BrowserExtensionImportRequest'];
15
13
  export type V1BrowserExtensionUpdateRequest = OpenApiSchemas['BrowserExtensionUpdateRequest'];
@@ -25,9 +25,6 @@ export class V1BrowserExtensionsClient {
25
25
  if (request.name) {
26
26
  form.set('name', request.name);
27
27
  }
28
- if (request.subaccountId) {
29
- form.set('subaccountId', request.subaccountId);
30
- }
31
28
  return this.http.request('/browser-extensions/upload', {
32
29
  method: 'POST',
33
30
  body: form,