@boxline/sdk 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,7 +2,62 @@
2
2
 
3
3
  All notable changes to `@boxline/sdk`. The SDK follows [semantic versioning](https://semver.org).
4
4
 
5
- ## 1.1.0 (not published yet)
5
+ ## 1.2.0 (2026-10-03)
6
+
7
+ ### Added
8
+
9
+ - **Credentials**: `bx.credentials.list/create/get/update/delete/audit` (`/v1/credentials`), one place for what the AI
10
+ types and the shell uses, with a typed union per type: a **password** (`origins`, `username`, `password`, optional
11
+ `totpSecret`; shown as `PasswordCredential` with `username` and `hasTotp`) and a **secret** (`value`, optional
12
+ `origins`; shown as `SecretCredential` with `preview`). `credentials.create` returns the matching type; `scope`,
13
+ `shell`, `description` and the write-only rules are as for secrets. Types `Credential`, `CredentialType`,
14
+ `CredentialScope`, `CredentialField`, `PasswordCredential`, `SecretCredential`, `CredentialCreateParams`,
15
+ `PasswordCredentialCreateParams`, `SecretCredentialCreateParams`, `CredentialUpdateParams`,
16
+ `CredentialAuditEntry` (with `type`, and the new `usedBy` kinds `action` and `otp`) and `CredentialAuditParams`.
17
+ Passwords need the plan's `loginDetails`; `PlanLimit` is `maxCredentials`.
18
+ - `credentials.update` that makes an AI-only credential readable by shells (`scope` to `"shell"` or `"all"`, or
19
+ `shell: true`) needs the values again in the same call, like a new site (the API answers 400 `invalid_request`
20
+ otherwise, 409 `conflict` when the sites, scope or `shell` changed meanwhile).
21
+ - **`credentials: ["NAME"]`** where the API takes them: `sessions.create` (exported into the shell: a secret as `$NAME`,
22
+ a password as `$NAME_USERNAME` and `$NAME_PASSWORD`; `boxline-otp NAME` prints its 2FA code), `exec` and `execStream`,
23
+ `agent.run` and `session.step()` and the step action (placeholders `%NAME%`, `%NAME.username%`, `%NAME.password%`,
24
+ `%NAME.otp%`), `runScript`, and `tasks.create` / `tasks.update` (a task shows its `credentials`). A `Session` lists
25
+ the exported `credentials`.
26
+ - **`session.typeCredential(name, {field, selector, allowWithExtensions})`** and the `type` action with `credential`
27
+ (and `field`: `"username"`, `"password"` or `"otp"`): a credential's value typed into a field without passing
28
+ through your code, only on the credential's sites.
29
+ - **`profiles.update(id, {name?, credential?})`**: rename a profile and/or link the password credential it signs in
30
+ with (`credential: null` unlinks it). A `Profile` has `credential`; sessions with the profile, and the agent runs,
31
+ task runs and steps in them, get that credential as if it were listed.
32
+ - Errors `CredentialExistsError` (409 `credential_exists`), `CredentialNotAllowedError` (400 `credential_not_for_ai`
33
+ / `credential_not_for_shell`), `TooManyCredentialValuesError` (409 `too_many_credential_values`) and
34
+ `ErrorCode.credentialNotFound` (404 `credential_not_found`, a `NotFoundError`). The webhook event `credential.changed`
35
+ (`WebhookCredentialChangedData`: `name`, `action`, `type`, `by`, `changed`).
36
+ - `examples/credentials.ts`.
37
+
38
+ ### Changed (breaking)
39
+
40
+ Nothing above shipped before, so these old names are gone with no aliases.
41
+
42
+ - **Secrets and profile login details became credentials.** `bx.secrets` is `bx.credentials`; `secrets` on
43
+ `sessions.create`, `exec`, `agent.run`, steps, `runScript` and tasks is `credentials` (`Session.secrets` is
44
+ `Session.credentials`, `Task.secrets` is `Task.credentials`); `login: true` on `runScript` is gone (list the
45
+ credential); `profiles.setLogin`, `updateLogin` and `deleteLogin`, `Profile.login`, `LoginDetails`,
46
+ `LoginDetailsUpdate` and the placeholders `%login.username%`, `%login.password%` and `%login.otp%` are gone: create a
47
+ password credential and link it with `profiles.update(id, {credential})`. Types `Secret`, `SecretScope`,
48
+ `SecretCreateParams`, `SecretUpdateParams`, `SecretAuditEntry` and `SecretAuditParams` are replaced by the credential
49
+ types above; `SecretExistsError`, `SecretNotAllowedError` and `TooManySecretValuesError` by `CredentialExistsError`,
50
+ `CredentialNotAllowedError` and `TooManyCredentialValuesError`; the plan field `maxSecrets` is `maxCredentials`; the
51
+ webhook event `secret.changed` is `credential.changed`.
52
+ - **Saved logins (contexts) are now browser profiles.** `bx.contexts` is `bx.profiles` (`create`, `get`, `list`,
53
+ `update`, `delete`; the routes are `/v1/profiles`; `contexts.rename` is `profiles.update(id, {name})`). Sessions and
54
+ agent runs take `profile: {id, persist?}` instead of `context`; tasks take `profile` instead of `savedLogin` (and
55
+ show it); a `Session` has `profileId` and `profilePersist` instead of `contextId` and `contextPersist`; the plan
56
+ fields are `maxProfiles` and `maxProfileBytes`, the plan feature is `"profiles"`, and the error code is
57
+ `ErrorCode.profileTooLarge` (`profile_too_large`). Types: `Profile` (was `ContextInfo`) and `TaskProfile`; the class
58
+ `Contexts` is `Profiles`. New profiles have ids starting with `prof_`. The old names are gone.
59
+
60
+ ## 1.1.0 (2026-10-02)
6
61
 
7
62
  ### Added
8
63
 
package/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Boxline Node SDK
2
2
 
3
- Cloud browsers and shell sandboxes for AI agents. Each session is an isolated machine with a real Chrome and, if you
3
+ **Give your AI agents the infrastructure they need: browsers, shells, storage and isolated machines.**
4
+
5
+ Each session is an isolated machine with a real Chrome and, if you
4
6
  ask for it, a bash shell with Python and Node, sharing one `/workspace` disk.
5
7
 
6
8
  ```bash
@@ -22,7 +24,7 @@ instead of an API key, on the platform's own sites.
22
24
  - [An agent run with variables](#an-agent-run-with-variables)
23
25
  - [Limits, Continue and messages](#limits-continue-and-messages)
24
26
  - [Tasks and structured output](#tasks-and-structured-output)
25
- - [Secrets and saved login details](#secrets-and-saved-login-details)
27
+ - [Credentials and browser profiles](#credentials-and-browser-profiles)
26
28
  - [A script with useModel](#a-script-with-usemodel)
27
29
  - [CAPTCHAs](#captchas)
28
30
  - [Browser settings and extensions](#browser-settings-and-extensions)
@@ -204,7 +206,7 @@ await bx.agent.sendMessage(run.id, "Also open page C and include its heading in
204
206
 
205
207
  ## Tasks and structured output
206
208
 
207
- A task is a saved agent run: an instruction with `%name%` variables, an output schema, browser settings, a saved login,
209
+ A task is a saved agent run: an instruction with `%name%` variables, an output schema, browser settings, a profile,
208
210
  a model and, if you like, a schedule. Run it by hand or on its schedule; every run is an agent run.
209
211
 
210
212
  ```ts
@@ -239,45 +241,66 @@ await bx.tasks.update(task.id, { schedule: { enabled: true } }); // null remove
239
241
  - **Variables**: plain ones are written into the instruction (and kept with the run); `{ name, secret: true, origins }`
240
242
  is never stored, must come with every run, and is typed without the model seeing it. A task with a secret variable
241
243
  cannot have a schedule. A run missing a value throws `MissingVariablesError`.
244
+ - **Credentials**: `credentials: ["SHOP"]` on `tasks.create` gives every run the saved credentials' placeholders (see
245
+ [Credentials and browser profiles](#credentials-and-browser-profiles)); a scheduled task may use them, and the task
246
+ keeps the names only.
242
247
  - **Schedules**: five-field cron (at most every 5 minutes) read in `timezone`. A scheduled run is `queued` until it
243
248
  starts; a time that comes while a run is still going is `skipped`, and times the platform was down for are `missed`
244
249
  (`reason`, `missedCount`). The plan limits tasks and schedules switched on (`PlanLimitError`).
245
250
  - `waitForRun` takes the run from `run()` or `(taskId, taskRunId)`, with `{pollMs, timeoutMs}`; there is no GET for
246
251
  one task run, so it watches the task's unfinished runs.
247
252
 
248
- ## Secrets and saved login details
253
+ ## Credentials and browser profiles
249
254
 
250
- Project secrets are write-only: the value is sealed when stored and never returned or shown. Each secret's `scope` says
251
- where it may be used: `"agent"` (the default: only the AI, as `%NAME%`), `"shell"` (only as `$NAME` in shells) or `"all"`.
255
+ Credentials are write-only: the value is sealed when stored and never returned or shown. There are two types, a website
256
+ **password** (sites, user name, password and an optional 2FA key) and a **secret** (one value, such as an API token).
257
+ The name is the handle: the AI's placeholder (`%GITHUB_TOKEN%`, `%SHOP.password%`) and the shell variable
258
+ (`$GITHUB_TOKEN`, `$SHOP_PASSWORD`). Each credential's `scope` says where it may be used: `"agent"` (the default: only
259
+ the AI), `"shell"` (only as variables in shells) or `"all"`.
252
260
 
253
261
  ```ts
254
- await bx.secrets.create({ name: "GITHUB_TOKEN", value: process.env.GITHUB_TOKEN!, scope: "shell" });
255
- await bx.secrets.create({ name: "SITE_PASSWORD", value: process.env.SITE_PASSWORD!, origins: ["https://example.com"] });
262
+ await bx.credentials.create({ name: "GITHUB_TOKEN", type: "secret", value: process.env.GITHUB_TOKEN!, scope: "shell" });
263
+ const shop = await bx.credentials.create({
264
+ name: "SHOP",
265
+ type: "password",
266
+ origins: ["https://shop.example.com"], // the only site the AI may type it on
267
+ username: "ops@example.com",
268
+ password: process.env.SHOP_PASSWORD!,
269
+ totpSecret: process.env.SHOP_2FA_KEY, // optional: %SHOP.otp% is the current code
270
+ });
271
+ console.log(shop.type, shop.username, shop.hasTotp); // narrowed to PasswordCredential; no value anywhere
256
272
 
257
- // In a shell: exported as $GITHUB_TOKEN, and shown as %GITHUB_TOKEN% wherever it appears in the output.
258
- const s = await bx.sessions.create({ shell: true, env: { REGION: "eu" }, secrets: ["GITHUB_TOKEN"] });
273
+ // In a shell: $GITHUB_TOKEN, shown as %GITHUB_TOKEN% wherever it appears in the output.
274
+ const s = await bx.sessions.create({ shell: true, env: { REGION: "eu" }, credentials: ["GITHUB_TOKEN"] });
259
275
  await s.exec("gh repo list --limit 3");
260
- await s.exec("./deploy.sh", { secrets: ["DEPLOY_KEY"] }); // this one command only
276
+ await s.exec("./deploy.sh", { credentials: ["DEPLOY_KEY"] }); // this one command only
261
277
 
262
- // For the AI: typed as %SITE_PASSWORD% only on its sites, never shown to the model.
263
- await s.step("type %SITE_PASSWORD% into the password field", { secrets: ["SITE_PASSWORD"] });
264
- await bx.agent.run({ task: "Sign in to https://example.com with %SITE_PASSWORD%", secrets: ["SITE_PASSWORD"] });
278
+ // For the AI: typed only on the credential's sites, never shown to the model.
279
+ await s.step("sign in with %SHOP.username% and %SHOP.password%", { credentials: ["SHOP"] });
280
+ await bx.agent.run({ task: "Sign in to https://shop.example.com with %SHOP.username% and %SHOP.password%", credentials: ["SHOP"] });
281
+ // Or type one field yourself without seeing it (the field's own frame must be on one of the credential's sites):
282
+ await s.typeCredential("SHOP", { field: "password", selector: "#password" });
265
283
 
266
- // A saved login's details with 2FA: %login.username%, %login.password% and %login.otp% in sessions started with it.
267
- await bx.contexts.setLogin(context.id, { origin: "https://example.com", username: "ada@example.com", password, totpSecret });
284
+ // A profile keeps cookies; link a password and the AI can sign in again when they expire.
285
+ await bx.profiles.update(profile.id, { credential: "SHOP" });
268
286
 
269
- for await (const e of bx.secrets.audit({ name: "GITHUB_TOKEN" })) console.log(e.at, e.action, e.actor, e.usedBy?.type);
287
+ for await (const e of bx.credentials.audit({ name: "SHOP" })) console.log(e.at, e.action, e.actor, e.usedBy?.type);
270
288
  ```
271
289
 
272
- - **Exported secrets can be read by anything that runs in the shell**, including an agent's commands that a web page
273
- tries to steer. Export only what you accept that for; keep passwords at scope `"agent"` with `origins`. Hiding
274
- values in output is a guard against accidents, not a boundary.
275
- - `runScript(code, { secrets, login: true })` lets the script's `step()` calls use secrets and the saved login's
276
- details (the values never enter the machine). In a session with Chrome extensions, steps and scripts with secrets
277
- need `allowWithExtensions: true`, as agent runs with variables do.
278
- - Errors: `SecretExistsError` (use `update`), `SecretNotAllowedError` (the scope does not allow that use),
279
- `TooManySecretValuesError` (the session hides as many values as it can: start a new one), `MachineTooOldError`
280
- (during a deploy), `PlanLimitError` (beyond the plan's `maxSecrets`).
290
+ - **Exported credentials can be read by anything that runs in the shell**, including an agent's commands that a web
291
+ page tries to steer. Export only what you accept that for; keep website passwords at scope `"agent"` with `origins`.
292
+ Hiding values in output is a guard against accidents, not a boundary. A 2FA key never enters the machine:
293
+ `boxline-otp SHOP` in the shell asks the platform for the current code.
294
+ - `credentials.update` changes the fields you send; a new site needs the sensitive values again in the same call.
295
+ - `runScript(code, { credentials })` lets the script's `step()` calls use credentials (the values never enter the
296
+ machine). In a session with Chrome extensions, steps, scripts and the `type` action with credentials need
297
+ `allowWithExtensions: true`, as agent runs with variables do.
298
+ - Errors: `CredentialExistsError` (use `update`), `CredentialNotAllowedError` (the scope does not allow that use),
299
+ `NotFoundError` (`credential_not_found`), `TooManyCredentialValuesError` (the session hides as many values as it can:
300
+ start a new one), `FeatureNotInPlanError` (a password needs the plan's `loginDetails`), `MachineTooOldError` (during
301
+ a deploy), `PlanLimitError` (beyond the plan's `maxCredentials`).
302
+ - The `credential.changed` webhook event says a credential was created, changed (or linked to a profile) or deleted,
303
+ never a value.
281
304
 
282
305
  ## A script with useModel
283
306
 
@@ -397,8 +420,8 @@ for await (const e of session.events({ types: ["console", "error"] })) console.l
397
420
  for await (const p of page.iterPages()) console.log(p.data.length);
398
421
  ```
399
422
 
400
- Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `contexts.list`, `apiKeys.list`, `agent.list`,
401
- `crawl.list`, `extensions.list`, `tasks.list`, `tasks.runs`, `secrets.list`, `secrets.audit`, and a crawl's pages (`crawl.get(id, {after})`, or
423
+ Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `profiles.list`, `apiKeys.list`, `agent.list`,
424
+ `crawl.list`, `extensions.list`, `tasks.list`, `tasks.runs`, `credentials.list`, `credentials.audit`, and a crawl's pages (`crawl.get(id, {after})`, or
402
425
  `for await (const p of bx.crawl.pages(id))`).
403
426
 
404
427
  ## Errors, retries and time limits
@@ -411,13 +434,13 @@ Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `contexts.list`, `a
411
434
  `OutOfViewportError`, `WebhookUrlNotAllowedError`, `WebhooksUnavailableError`, `WebhookDisabledError`,
412
435
  `PayloadExpiredError`, `WebhookSignatureError` (from verifyWebhook), `VariablesWithExtensionsError`,
413
436
  `InvalidExtensionError`, `PayloadTooLargeError`, `LimitReachedError`, `ExtensionDeniedError`, `CrossSiteRequestError`,
414
- `MissingVariablesError`, `PlanLimitError`, `SecretExistsError`, `SecretNotAllowedError`, `TooManySecretValuesError`,
437
+ `MissingVariablesError`, `PlanLimitError`, `CredentialExistsError`, `CredentialNotAllowedError`, `TooManyCredentialValuesError`,
415
438
  `MachineTooOldError`, `NotContinuableError`, `TooManyMessagesError`, `SessionNotRunningError`, `AuthenticationError`,
416
439
  `NotFoundError`, and
417
440
  `BoxlineConnectionError` /
418
441
  `BoxlineTimeoutError` when no answer came back. `ErrorCode` has the codes.
419
442
  - **Retries.** GETs, and the calls that create or start something (sessions, bulk, agent runs, continued runs, messages
420
- to runs, crawls, API keys, contexts, extension uploads, tasks, task runs), are retried after a network error, a time-out, 429 and 5xx: 2 retries by default, exponential backoff
443
+ to runs, crawls, API keys, profiles, extension uploads, tasks, task runs), are retried after a network error, a time-out, 429 and 5xx: 2 retries by default, exponential backoff
421
444
  from 0.5 s to 8 s with jitter, or what `Retry-After` / `RateLimit-Reset` say (up to 60 s; longer waits go to you as a
422
445
  `RateLimitError`). Other POSTs (exec, actions, fetch…) are never retried: they could run twice.
423
446
  - **Idempotency keys.** The SDK sends a new `Idempotency-Key` with every create, and the same one on its retries, so a
@@ -446,12 +469,12 @@ same methods without it (`session.pause()`).
446
469
  | Account | `me`, `hasFeature`, `auth.signup`, `auth.login`, `auth.logout`, `project.trajectories`, `project.setTrajectories`, `project.settings`, `project.setSettings`, `apiKeys.list`, `apiKeys.create`, `apiKeys.revoke` |
447
470
  | Webhooks | `webhooks.create`, `list`, `get`, `update`, `delete`, `rotateSecret`, `test`, `deliveries`, `retryDelivery`; `verifyWebhook` (no request) |
448
471
  | Sessions | `sessions.create`, `get`, `list`, `update`, `release`, `pause`, `resume`, `move`, `extend`, `rotateProxy`, `rotateUrls`, `live`, `bulk` |
449
- | Browser | `sessions.actions`, `sessions.computer`; on a session: `goto`, `click`, `hover`, `fill`, `type`, `press`, `scroll`, `wait`, `select`, `elements`, `evaluate`, `content`, `screenshot`, `cursor`, `upload`, `tabs`, `newTab`, `switchTab`, `closeTab`, `back`, `forward`, `reload`, `step`, `extract`, `exportCookies`, `computer`, `mouse.move`/`moveBy`/`click`/`down`/`up`/`drag`, `keyboard.key`/`type`/`press` |
472
+ | Browser | `sessions.actions`, `sessions.computer`; on a session: `goto`, `click`, `hover`, `fill`, `type`, `typeCredential`, `press`, `scroll`, `wait`, `select`, `elements`, `evaluate`, `content`, `screenshot`, `cursor`, `upload`, `tabs`, `newTab`, `switchTab`, `closeTab`, `back`, `forward`, `reload`, `step`, `extract`, `exportCookies`, `computer`, `mouse.move`/`moveBy`/`click`/`down`/`up`/`drag`, `keyboard.key`/`type`/`press` |
450
473
  | Shell and scripts | `sessions.exec`, `execStream`, `runScript`, `restartShell` |
451
474
  | Files | `sessions.files.list`, `read`, `readText`, `write`, `delete`, `waitFor` |
452
475
  | Logs | `sessions.events`, `streamEvents`, `pages`, `recording`, `recordingFrame`; on a session: `waitForHuman`, `onCaptcha` |
453
- | Saved logins | `contexts.create`, `get`, `list`, `rename`, `delete`, `setLogin`, `deleteLogin` |
454
- | Secrets | `secrets.create`, `list`, `get`, `update`, `delete`, `audit` |
476
+ | Browser profiles | `profiles.create`, `get`, `list`, `update`, `delete` |
477
+ | Credentials | `credentials.create`, `list`, `get`, `update`, `delete`, `audit`; on a session: `typeCredential` |
455
478
  | Extensions | `extensions.upload`, `list`, `get`, `delete` |
456
479
  | Web | `fetch`, `screenshot`, `pdf`, `extract`, `search`, `crawl.start`, `get`, `list`, `cancel`, `pages`, `wait` |
457
480
  | Agent | `agent.models`, `run`, `get`, `list`, `takeover`, `handBack`, `cancel`, `continueRun`, `sendMessage`, `stream`, `wait` |
@@ -477,7 +500,7 @@ reach, so run them with `BOXLINE_API_URL=http://localhost:8080`; `search.ts` and
477
500
  | `webhooks.ts` | endpoints, deliveries and their history, re-sending, rotating the secret, a test event |
478
501
  | `agent-variables.ts` | an agent run with `%email%` / `%password%` limited to one site |
479
502
  | `tasks.ts` | a task with an output schema on a demo shop: run with a variable, waited for, its history, changed, deleted; an agent run with `output` |
480
- | `secrets.ts` | a secret exported into a shell (its length checked, its value hidden in output), changed, audited, deleted; login details on a saved login |
503
+ | `credentials.ts` | a secret exported into a shell (its length checked, its value hidden in output), changed, audited, deleted; a password with 2FA linked to a profile |
481
504
  | `script-use-model.ts` | `useModel`, `step()` and `extract()` in a script |
482
505
  | `captcha.ts` | noticing a CAPTCHA and handing it to a person |
483
506
  | `block-ads.ts` | a session that blocks ads and trackers, and its `blockedRequests` count |
package/dist/client.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { type CoreConfig, type Query, type RequestOptions, type SendInit } from "./core.js";
2
2
  import { Page, PagePromise } from "./pagination.js";
3
3
  import { Session } from "./session.js";
4
- import type { ActionItem, ActionResult, AgentMessageSent, AgentModelCatalog, AgentRun, AgentRunEvent, AgentRunParams, AgentRunStarted, ContinueRunParams, ApiKeyInfo, BulkResult, ComputerAction, ComputerOptions, ComputerResult, ContextInfo, LoginDetails, LoginDetailsUpdate, MoveShell, Secret, SecretAuditEntry, SecretAuditParams, SecretCreateParams, SecretUpdateParams, CrawlGetParams, CrawlJob, CrawlPage, CrawlParams, CreateSessionParams, ExecExit, ExecOptions, ExecResult, ExtensionInfo, ExtractParams, ExtractResult, FetchParams, FetchResult, FileList, FileRef, ListParams, LoginResponse, Me, MoveTimings, NewApiKey, NewWebhookEndpoint, ProjectSettings as ProjectSettingsData, AgentProvider, ModelKey, ModelKeyParams, CaptchaMode, WebhookCreateParams, WebhookDelivery, WebhookDeliveryListParams, WebhookEndpoint, WebhookEventType, WebhookEventTypeList, WebhookUpdateParams, PdfParams, PlanFeature, Pricing, Recording, RunScriptOptions, ScreenshotParams, ScriptResult, SearchParams, SearchResponse, SessionEvent, SessionEventsParams, SessionListParams, SessionUrls, SignupResponse, Stats, Task, TaskCreateParams, TaskRun, TaskRunListParams, TaskRunParams, TaskUpdateParams, TrajectoriesSetting, UpdateSessionParams, Usage, VisitedPage } from "./types.js";
4
+ import type { ActionItem, ActionResult, AgentMessageSent, AgentModelCatalog, AgentRun, AgentRunEvent, AgentRunParams, AgentRunStarted, ContinueRunParams, ApiKeyInfo, BulkResult, ComputerAction, ComputerOptions, ComputerResult, Profile, ProfileUpdateParams, MoveShell, Credential, CredentialAuditEntry, CredentialAuditParams, CredentialCreateParams, CredentialUpdateParams, PasswordCredential, PasswordCredentialCreateParams, SecretCredential, SecretCredentialCreateParams, CrawlGetParams, CrawlJob, CrawlPage, CrawlParams, CreateSessionParams, ExecExit, ExecOptions, ExecResult, ExtensionInfo, ExtractParams, ExtractResult, FetchParams, FetchResult, FileList, FileRef, ListParams, LoginResponse, Me, MoveTimings, NewApiKey, NewWebhookEndpoint, ProjectSettings as ProjectSettingsData, AgentProvider, ModelKey, ModelKeyParams, CaptchaMode, WebhookCreateParams, WebhookDelivery, WebhookDeliveryListParams, WebhookEndpoint, WebhookEventType, WebhookEventTypeList, WebhookUpdateParams, PdfParams, PlanFeature, Pricing, Recording, RunScriptOptions, ScreenshotParams, ScriptResult, SearchParams, SearchResponse, SessionEvent, SessionEventsParams, SessionListParams, SessionUrls, SignupResponse, Stats, Task, TaskCreateParams, TaskRun, TaskRunListParams, TaskRunParams, TaskUpdateParams, TrajectoriesSetting, UpdateSessionParams, Usage, VisitedPage } from "./types.js";
5
5
  export interface BoxlineOptions {
6
6
  /** Defaults to the BOXLINE_API_KEY environment variable. */
7
7
  apiKey?: string;
@@ -34,11 +34,11 @@ export declare class Boxline {
34
34
  readonly project: ProjectSettings;
35
35
  readonly apiKeys: ApiKeys;
36
36
  readonly sessions: Sessions;
37
- readonly contexts: Contexts;
37
+ readonly profiles: Profiles;
38
38
  readonly crawl: Crawl;
39
39
  readonly agent: Agent;
40
40
  readonly tasks: Tasks;
41
- readonly secrets: Secrets;
41
+ readonly credentials: Credentials;
42
42
  readonly webhooks: Webhooks;
43
43
  readonly extensions: Extensions;
44
44
  /** @internal */
@@ -284,70 +284,71 @@ export declare class SessionFiles {
284
284
  /** Waits for a file matching a glob (e.g. `downloads/*.csv`) that has finished writing. */
285
285
  waitFor(id: string, pattern: string, timeoutMs?: number, options?: RequestOptions): Promise<FileRef>;
286
286
  }
287
- /** Saved logins: cookies and local storage to start sessions with (`context: {id, persist: true}` fills one). */
288
- export declare class Contexts {
287
+ /** Browser profiles: cookies and local storage to start sessions with (`profile: {id, persist: true}` fills one). */
288
+ export declare class Profiles {
289
289
  private readonly client;
290
290
  constructor(client: Boxline);
291
291
  /**
292
- * A new saved login: empty, or with `fromSession` holding that working session's current cookies and site storage
292
+ * A new profile: empty, or with `fromSession` holding that working session's current cookies and site storage
293
293
  * (sign in there first, e.g. in its live view). `attach: true` also makes the session save to it from now on (at its
294
- * checkpoints and when it ends); a session that already has a saved login refuses that (409 `conflict`). 413
295
- * `context_too_large` over 16 MB; PlanLimitError (402) past the plan's `maxContexts` or `maxContextBytes`.
294
+ * checkpoints and when it ends); a session that already has a profile refuses that (409 `conflict`). 413
295
+ * `profile_too_large` over 16 MB; PlanLimitError (402) past the plan's `maxProfiles` or `maxProfileBytes`.
296
296
  */
297
297
  create(params?: {
298
298
  name?: string;
299
299
  fromSession?: string;
300
300
  attach?: boolean;
301
- }, options?: RequestOptions): Promise<ContextInfo>;
302
- get(id: string, options?: RequestOptions): Promise<ContextInfo>;
301
+ }, options?: RequestOptions): Promise<Profile>;
302
+ get(id: string, options?: RequestOptions): Promise<Profile>;
303
303
  /** Newest first; the first page's `total` counts them all. */
304
- list(params?: ListParams, options?: RequestOptions): PagePromise<ContextInfo, Page<ContextInfo> & {
304
+ list(params?: ListParams, options?: RequestOptions): PagePromise<Profile, Page<Profile> & {
305
305
  total: number;
306
306
  }>;
307
- rename(id: string, name: string, options?: RequestOptions): Promise<ContextInfo>;
308
- delete(id: string, options?: RequestOptions): Promise<void>;
309
- /**
310
- * Keeps sign-in details on the saved login (plan feature `loginDetails`), replacing earlier ones: the site, user name,
311
- * password and optionally the 2FA setup key, sealed like secrets. Returns the context, whose `login` shows
312
- * `{origin, username, hasPassword, hasTotp}`, never the password or the 2FA secret.
313
- */
314
- setLogin(id: string, details: LoginDetails, options?: RequestOptions): Promise<ContextInfo>;
315
307
  /**
316
- * Changes some of the login details and keeps the rest (setLogin replaces them all); `totpSecret: null` removes 2FA.
317
- * A password never moves to another site on its own: a new `origin` needs `password` in the same call, and
318
- * `totpSecret` (a new one or null) when the login has 2FA (400 otherwise). A BoxlineError with code `conflict` (409)
319
- * when the login changed meanwhile: send it again.
308
+ * Changes the name and/or the password credential the profile signs in with: `credential: "SHOP"` links a password
309
+ * credential (see `credentials`), so sessions with this profile, and agent runs, task runs and steps in them, get it
310
+ * as if it were listed in their `credentials` and the AI can sign in again when the cookies have expired; `null`
311
+ * unlinks it. NotFoundError (404 `credential_not_found`) for a name the project does not have, a 400 BoxlineError
312
+ * for a secret (only passwords sign in), FeatureNotInPlanError (402) without the plan's `loginDetails`.
320
313
  */
321
- updateLogin(id: string, changes: LoginDetailsUpdate, options?: RequestOptions): Promise<ContextInfo>;
322
- /** Removes the login details (the saved cookies and storage stay). */
323
- deleteLogin(id: string, options?: RequestOptions): Promise<void>;
314
+ update(id: string, changes: ProfileUpdateParams, options?: RequestOptions): Promise<Profile>;
315
+ delete(id: string, options?: RequestOptions): Promise<void>;
324
316
  }
325
317
  /**
326
- * Project secrets: write-only values the AI uses as %NAME% placeholders (`secrets` on agent runs, steps and scripts) and
327
- * shells get as environment variables (`secrets` on sessions.create and exec), depending on each secret's `scope`. The
328
- * value is never returned, logged or shown; every change and use is audited.
318
+ * Credentials: write-only website passwords (with an optional 2FA key) and secrets. The AI uses them as placeholders
319
+ * (`%NAME%`, `%SHOP.password%`) with `credentials` on agent runs, steps, scripts, tasks and `Session.typeCredential`;
320
+ * shells get them as environment variables (`credentials` on sessions.create and exec), depending on each
321
+ * credential's `scope`. A value is never returned, logged or shown; every change and use is audited.
329
322
  */
330
- export declare class Secrets {
323
+ export declare class Credentials {
331
324
  private readonly client;
332
325
  constructor(client: Boxline);
333
- /** The project's secrets, in name order, without their values. */
334
- list(params?: ListParams, options?: RequestOptions): PagePromise<Secret>;
326
+ /** The project's credentials, in name order, without their values. */
327
+ list(params?: ListParams, options?: RequestOptions): PagePromise<Credential>;
335
328
  /**
336
- * Stores a secret, sealed; the answer never has the value. SecretExistsError for a name the project has (change it
337
- * with update), PlanLimitError beyond the plan's `maxSecrets`. Not retried by the SDK (the API takes no
338
- * Idempotency-Key here): a retry after a lost answer may meet SecretExistsError.
329
+ * Stores a credential, sealed; the answer never has a value. `type: "password"` takes `origins`, `username`,
330
+ * `password` and optionally `totpSecret` (needs the plan's `loginDetails`: FeatureNotInPlanError); `type: "secret"`
331
+ * takes `value`. CredentialExistsError for a name the project has (change it with update), PlanLimitError beyond the
332
+ * plan's `maxCredentials`. Not retried by the SDK (the API takes no Idempotency-Key here): a retry after a lost
333
+ * answer may meet CredentialExistsError.
339
334
  */
340
- create(params: SecretCreateParams, options?: RequestOptions): Promise<Secret>;
341
- get(name: string, options?: RequestOptions): Promise<Secret>;
335
+ create(params: PasswordCredentialCreateParams, options?: RequestOptions): Promise<PasswordCredential>;
336
+ create(params: SecretCredentialCreateParams, options?: RequestOptions): Promise<SecretCredential>;
337
+ create(params: CredentialCreateParams, options?: RequestOptions): Promise<Credential>;
338
+ get(name: string, options?: RequestOptions): Promise<Credential>;
342
339
  /**
343
- * Changes the fields you send. A running agent run keeps the value it started with; a session that exports the secret
344
- * gets the new value on its next machine (move, resume, recovery).
340
+ * Changes the fields you send (the type cannot change: delete it and create it again). A new site, or a `scope`
341
+ * or `shell` that makes an AI-only credential readable by shells, needs the sensitive values again in the same call
342
+ * (a secret's `value`; a password's `password`, and `totpSecret` when it has 2FA), else a 400 `invalid_request`; a
343
+ * 409 `conflict` when the sites, scope or `shell` changed meanwhile (send it again). A running
344
+ * agent run keeps the values it started with; a session that exports the credential gets the new ones on its next
345
+ * machine (move, resume, recovery).
345
346
  */
346
- update(name: string, patch: SecretUpdateParams, options?: RequestOptions): Promise<Secret>;
347
- /** Deletes it; sessions that exported it no longer get it on their next machine. */
347
+ update(name: string, patch: CredentialUpdateParams, options?: RequestOptions): Promise<Credential>;
348
+ /** Deletes it; profiles that link it are unlinked, and sessions that exported it no longer get it on their next machine. */
348
349
  delete(name: string, options?: RequestOptions): Promise<void>;
349
- /** Changes to secrets and saved login details, and each use (once per session, command, run or script), newest first. */
350
- audit(params?: SecretAuditParams, options?: RequestOptions): PagePromise<SecretAuditEntry>;
350
+ /** Changes to credentials and each use (once per session, command, run, script, task run, typed field or 2FA code), newest first. */
351
+ audit(params?: CredentialAuditParams, options?: RequestOptions): PagePromise<CredentialAuditEntry>;
351
352
  }
352
353
  /** Crawls: follow links from a start URL in the background (robots.txt respected); poll with get() or wait(). */
353
354
  export declare class Crawl {
@@ -496,8 +497,8 @@ export declare class Agent {
496
497
  cancel(id: string, options?: RequestOptions): Promise<AgentRun>;
497
498
  /**
498
499
  * Continues a run that stopped at one of its limits (errorCode max_steps, max_cost, too_many_errors or no_progress)
499
- * while its `continuable` is set: a new run in the same session, with the same model, mode, output schema, secrets
500
- * and saved login, and a compact record of what the previous run did. Returns the new run (`continuedFrom` links
500
+ * while its `continuable` is set: a new run in the same session, with the same model, mode, output schema, credentials
501
+ * and profile, and a compact record of what the previous run did. Returns the new run (`continuedFrom` links
501
502
  * back); wait for it with `wait(run.id)` or `stream(run.id)` like any run. A run that had `variables` needs them again
502
503
  * (MissingVariablesError otherwise). NotContinuableError: it did not stop at a limit, was continued already, or its
503
504
  * window passed. An Idempotency-Key is sent, so a retry never starts a second run.
package/dist/client.js CHANGED
@@ -23,11 +23,11 @@ export class Boxline {
23
23
  project;
24
24
  apiKeys;
25
25
  sessions;
26
- contexts;
26
+ profiles;
27
27
  crawl;
28
28
  agent;
29
29
  tasks;
30
- secrets;
30
+ credentials;
31
31
  webhooks;
32
32
  extensions;
33
33
  constructor(opts = {}) {
@@ -49,11 +49,11 @@ export class Boxline {
49
49
  this.project = new ProjectSettings(this);
50
50
  this.apiKeys = new ApiKeys(this);
51
51
  this.sessions = new Sessions(this);
52
- this.contexts = new Contexts(this);
52
+ this.profiles = new Profiles(this);
53
53
  this.crawl = new Crawl(this);
54
54
  this.agent = new Agent(this);
55
55
  this.tasks = new Tasks(this);
56
- this.secrets = new Secrets(this);
56
+ this.credentials = new Credentials(this);
57
57
  this.webhooks = new Webhooks(this);
58
58
  this.extensions = new Extensions(this);
59
59
  }
@@ -467,98 +467,84 @@ export class SessionFiles {
467
467
  return this.client.request("GET", this.url(id, { pattern, timeoutMs }, "/wait"), undefined, atLeast(this.client, options, timeoutMs + 30_000));
468
468
  }
469
469
  }
470
- // ---------------------------------------------------------------- contexts
471
- /** Saved logins: cookies and local storage to start sessions with (`context: {id, persist: true}` fills one). */
472
- export class Contexts {
470
+ // ---------------------------------------------------------------- profiles
471
+ /** Browser profiles: cookies and local storage to start sessions with (`profile: {id, persist: true}` fills one). */
472
+ export class Profiles {
473
473
  client;
474
474
  constructor(client) {
475
475
  this.client = client;
476
476
  }
477
477
  /**
478
- * A new saved login: empty, or with `fromSession` holding that working session's current cookies and site storage
478
+ * A new profile: empty, or with `fromSession` holding that working session's current cookies and site storage
479
479
  * (sign in there first, e.g. in its live view). `attach: true` also makes the session save to it from now on (at its
480
- * checkpoints and when it ends); a session that already has a saved login refuses that (409 `conflict`). 413
481
- * `context_too_large` over 16 MB; PlanLimitError (402) past the plan's `maxContexts` or `maxContextBytes`.
480
+ * checkpoints and when it ends); a session that already has a profile refuses that (409 `conflict`). 413
481
+ * `profile_too_large` over 16 MB; PlanLimitError (402) past the plan's `maxProfiles` or `maxProfileBytes`.
482
482
  */
483
483
  create(params = {}, options) {
484
- return this.client.request("POST", "/v1/contexts", params, options);
484
+ return this.client.request("POST", "/v1/profiles", params, options);
485
485
  }
486
486
  get(id, options) {
487
- return this.client.request("GET", `/v1/contexts/${encodeURIComponent(id)}`, undefined, options);
487
+ return this.client.request("GET", `/v1/profiles/${encodeURIComponent(id)}`, undefined, options);
488
488
  }
489
489
  /** Newest first; the first page's `total` counts them all. */
490
490
  list(params = {}, options) {
491
- return this.client.list("/v1/contexts", { ...params }, (c) => c, options);
492
- }
493
- rename(id, name, options) {
494
- return this.client.request("PATCH", `/v1/contexts/${encodeURIComponent(id)}`, { name }, options);
495
- }
496
- delete(id, options) {
497
- return this.client.request("DELETE", `/v1/contexts/${encodeURIComponent(id)}`, undefined, options);
491
+ return this.client.list("/v1/profiles", { ...params }, (c) => c, options);
498
492
  }
499
493
  /**
500
- * Keeps sign-in details on the saved login (plan feature `loginDetails`), replacing earlier ones: the site, user name,
501
- * password and optionally the 2FA setup key, sealed like secrets. Returns the context, whose `login` shows
502
- * `{origin, username, hasPassword, hasTotp}`, never the password or the 2FA secret.
494
+ * Changes the name and/or the password credential the profile signs in with: `credential: "SHOP"` links a password
495
+ * credential (see `credentials`), so sessions with this profile, and agent runs, task runs and steps in them, get it
496
+ * as if it were listed in their `credentials` and the AI can sign in again when the cookies have expired; `null`
497
+ * unlinks it. NotFoundError (404 `credential_not_found`) for a name the project does not have, a 400 BoxlineError
498
+ * for a secret (only passwords sign in), FeatureNotInPlanError (402) without the plan's `loginDetails`.
503
499
  */
504
- setLogin(id, details, options) {
505
- return this.client.request("PUT", `/v1/contexts/${encodeURIComponent(id)}/login`, details, options);
500
+ update(id, changes, options) {
501
+ return this.client.request("PATCH", `/v1/profiles/${encodeURIComponent(id)}`, changes, options);
506
502
  }
507
- /**
508
- * Changes some of the login details and keeps the rest (setLogin replaces them all); `totpSecret: null` removes 2FA.
509
- * A password never moves to another site on its own: a new `origin` needs `password` in the same call, and
510
- * `totpSecret` (a new one or null) when the login has 2FA (400 otherwise). A BoxlineError with code `conflict` (409)
511
- * when the login changed meanwhile: send it again.
512
- */
513
- updateLogin(id, changes, options) {
514
- return this.client.request("PATCH", `/v1/contexts/${encodeURIComponent(id)}/login`, changes, options);
515
- }
516
- /** Removes the login details (the saved cookies and storage stay). */
517
- deleteLogin(id, options) {
518
- return this.client.request("DELETE", `/v1/contexts/${encodeURIComponent(id)}/login`, undefined, options);
503
+ delete(id, options) {
504
+ return this.client.request("DELETE", `/v1/profiles/${encodeURIComponent(id)}`, undefined, options);
519
505
  }
520
506
  }
521
- // ---------------------------------------------------------------- secrets
522
- const secretPath = (name) => `/v1/secrets/${encodeURIComponent(name)}`;
507
+ // ---------------------------------------------------------------- credentials
508
+ const credentialPath = (name) => `/v1/credentials/${encodeURIComponent(name)}`;
523
509
  /**
524
- * Project secrets: write-only values the AI uses as %NAME% placeholders (`secrets` on agent runs, steps and scripts) and
525
- * shells get as environment variables (`secrets` on sessions.create and exec), depending on each secret's `scope`. The
526
- * value is never returned, logged or shown; every change and use is audited.
510
+ * Credentials: write-only website passwords (with an optional 2FA key) and secrets. The AI uses them as placeholders
511
+ * (`%NAME%`, `%SHOP.password%`) with `credentials` on agent runs, steps, scripts, tasks and `Session.typeCredential`;
512
+ * shells get them as environment variables (`credentials` on sessions.create and exec), depending on each
513
+ * credential's `scope`. A value is never returned, logged or shown; every change and use is audited.
527
514
  */
528
- export class Secrets {
515
+ export class Credentials {
529
516
  client;
530
517
  constructor(client) {
531
518
  this.client = client;
532
519
  }
533
- /** The project's secrets, in name order, without their values. */
520
+ /** The project's credentials, in name order, without their values. */
534
521
  list(params = {}, options) {
535
- return this.client.list("/v1/secrets", { ...params }, (s) => s, options);
522
+ return this.client.list("/v1/credentials", { ...params }, (c) => c, options);
536
523
  }
537
- /**
538
- * Stores a secret, sealed; the answer never has the value. SecretExistsError for a name the project has (change it
539
- * with update), PlanLimitError beyond the plan's `maxSecrets`. Not retried by the SDK (the API takes no
540
- * Idempotency-Key here): a retry after a lost answer may meet SecretExistsError.
541
- */
542
524
  create(params, options) {
543
- return this.client.request("POST", "/v1/secrets", params, options);
525
+ return this.client.request("POST", "/v1/credentials", params, options);
544
526
  }
545
527
  get(name, options) {
546
- return this.client.request("GET", secretPath(name), undefined, options);
528
+ return this.client.request("GET", credentialPath(name), undefined, options);
547
529
  }
548
530
  /**
549
- * Changes the fields you send. A running agent run keeps the value it started with; a session that exports the secret
550
- * gets the new value on its next machine (move, resume, recovery).
531
+ * Changes the fields you send (the type cannot change: delete it and create it again). A new site, or a `scope`
532
+ * or `shell` that makes an AI-only credential readable by shells, needs the sensitive values again in the same call
533
+ * (a secret's `value`; a password's `password`, and `totpSecret` when it has 2FA), else a 400 `invalid_request`; a
534
+ * 409 `conflict` when the sites, scope or `shell` changed meanwhile (send it again). A running
535
+ * agent run keeps the values it started with; a session that exports the credential gets the new ones on its next
536
+ * machine (move, resume, recovery).
551
537
  */
552
538
  update(name, patch, options) {
553
- return this.client.request("PATCH", secretPath(name), patch, options);
539
+ return this.client.request("PATCH", credentialPath(name), patch, options);
554
540
  }
555
- /** Deletes it; sessions that exported it no longer get it on their next machine. */
541
+ /** Deletes it; profiles that link it are unlinked, and sessions that exported it no longer get it on their next machine. */
556
542
  delete(name, options) {
557
- return this.client.request("DELETE", secretPath(name), undefined, options);
543
+ return this.client.request("DELETE", credentialPath(name), undefined, options);
558
544
  }
559
- /** Changes to secrets and saved login details, and each use (once per session, command, run or script), newest first. */
545
+ /** Changes to credentials and each use (once per session, command, run, script, task run, typed field or 2FA code), newest first. */
560
546
  audit(params = {}, options) {
561
- return this.client.list("/v1/secrets/audit", { ...params }, (e) => e, options);
547
+ return this.client.list("/v1/credentials/audit", { ...params }, (e) => e, options);
562
548
  }
563
549
  }
564
550
  // ---------------------------------------------------------------- crawl
@@ -822,8 +808,8 @@ export class Agent {
822
808
  }
823
809
  /**
824
810
  * Continues a run that stopped at one of its limits (errorCode max_steps, max_cost, too_many_errors or no_progress)
825
- * while its `continuable` is set: a new run in the same session, with the same model, mode, output schema, secrets
826
- * and saved login, and a compact record of what the previous run did. Returns the new run (`continuedFrom` links
811
+ * while its `continuable` is set: a new run in the same session, with the same model, mode, output schema, credentials
812
+ * and profile, and a compact record of what the previous run did. Returns the new run (`continuedFrom` links
827
813
  * back); wait for it with `wait(run.id)` or `stream(run.id)` like any run. A run that had `variables` needs them again
828
814
  * (MissingVariablesError otherwise). NotContinuableError: it did not stop at a limit, was continued already, or its
829
815
  * window passed. An Idempotency-Key is sent, so a retry never starts a second run.