@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 +56 -1
- package/README.md +57 -34
- package/dist/client.d.ts +46 -45
- package/dist/client.js +46 -60
- package/dist/client.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/errors.d.ts +17 -16
- package/dist/errors.js +24 -23
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/session.d.ts +16 -3
- package/dist/session.js +19 -3
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +196 -126
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
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.
|
|
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
|
-
|
|
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
|
-
- [
|
|
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
|
|
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
|
-
##
|
|
253
|
+
## Credentials and browser profiles
|
|
249
254
|
|
|
250
|
-
|
|
251
|
-
|
|
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.
|
|
255
|
-
await bx.
|
|
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:
|
|
258
|
-
const s = await bx.sessions.create({ shell: true, env: { REGION: "eu" },
|
|
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", {
|
|
276
|
+
await s.exec("./deploy.sh", { credentials: ["DEPLOY_KEY"] }); // this one command only
|
|
261
277
|
|
|
262
|
-
// For the AI: typed
|
|
263
|
-
await s.step("
|
|
264
|
-
await bx.agent.run({ task: "Sign in to https://example.com with %
|
|
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
|
|
267
|
-
await bx.
|
|
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.
|
|
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
|
|
273
|
-
tries to steer. Export only what you accept that for; keep passwords at scope `"agent"` with `origins`.
|
|
274
|
-
values in output is a guard against accidents, not a boundary.
|
|
275
|
-
- `
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
`
|
|
280
|
-
|
|
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`, `
|
|
401
|
-
`crawl.list`, `extensions.list`, `tasks.list`, `tasks.runs`, `
|
|
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`, `
|
|
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,
|
|
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
|
-
|
|
|
454
|
-
|
|
|
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
|
-
| `
|
|
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,
|
|
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
|
|
37
|
+
readonly profiles: Profiles;
|
|
38
38
|
readonly crawl: Crawl;
|
|
39
39
|
readonly agent: Agent;
|
|
40
40
|
readonly tasks: Tasks;
|
|
41
|
-
readonly
|
|
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
|
-
/**
|
|
288
|
-
export declare class
|
|
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
|
|
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
|
|
295
|
-
* `
|
|
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<
|
|
302
|
-
get(id: string, options?: RequestOptions): Promise<
|
|
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<
|
|
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
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
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
|
-
|
|
322
|
-
|
|
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
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
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
|
|
323
|
+
export declare class Credentials {
|
|
331
324
|
private readonly client;
|
|
332
325
|
constructor(client: Boxline);
|
|
333
|
-
/** The project's
|
|
334
|
-
list(params?: ListParams, options?: RequestOptions): PagePromise<
|
|
326
|
+
/** The project's credentials, in name order, without their values. */
|
|
327
|
+
list(params?: ListParams, options?: RequestOptions): PagePromise<Credential>;
|
|
335
328
|
/**
|
|
336
|
-
* Stores a
|
|
337
|
-
*
|
|
338
|
-
*
|
|
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:
|
|
341
|
-
|
|
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
|
|
344
|
-
*
|
|
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:
|
|
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
|
|
350
|
-
audit(params?:
|
|
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,
|
|
500
|
-
* and
|
|
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
|
-
|
|
26
|
+
profiles;
|
|
27
27
|
crawl;
|
|
28
28
|
agent;
|
|
29
29
|
tasks;
|
|
30
|
-
|
|
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.
|
|
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.
|
|
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
|
-
// ----------------------------------------------------------------
|
|
471
|
-
/**
|
|
472
|
-
export class
|
|
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
|
|
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
|
|
481
|
-
* `
|
|
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/
|
|
484
|
+
return this.client.request("POST", "/v1/profiles", params, options);
|
|
485
485
|
}
|
|
486
486
|
get(id, options) {
|
|
487
|
-
return this.client.request("GET", `/v1/
|
|
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/
|
|
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
|
-
*
|
|
501
|
-
*
|
|
502
|
-
*
|
|
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
|
-
|
|
505
|
-
return this.client.request("
|
|
500
|
+
update(id, changes, options) {
|
|
501
|
+
return this.client.request("PATCH", `/v1/profiles/${encodeURIComponent(id)}`, changes, options);
|
|
506
502
|
}
|
|
507
|
-
|
|
508
|
-
|
|
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
|
-
// ----------------------------------------------------------------
|
|
522
|
-
const
|
|
507
|
+
// ---------------------------------------------------------------- credentials
|
|
508
|
+
const credentialPath = (name) => `/v1/credentials/${encodeURIComponent(name)}`;
|
|
523
509
|
/**
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
*
|
|
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
|
|
515
|
+
export class Credentials {
|
|
529
516
|
client;
|
|
530
517
|
constructor(client) {
|
|
531
518
|
this.client = client;
|
|
532
519
|
}
|
|
533
|
-
/** The project's
|
|
520
|
+
/** The project's credentials, in name order, without their values. */
|
|
534
521
|
list(params = {}, options) {
|
|
535
|
-
return this.client.list("/v1/
|
|
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/
|
|
525
|
+
return this.client.request("POST", "/v1/credentials", params, options);
|
|
544
526
|
}
|
|
545
527
|
get(name, options) {
|
|
546
|
-
return this.client.request("GET",
|
|
528
|
+
return this.client.request("GET", credentialPath(name), undefined, options);
|
|
547
529
|
}
|
|
548
530
|
/**
|
|
549
|
-
* Changes the fields you send
|
|
550
|
-
*
|
|
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",
|
|
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",
|
|
543
|
+
return this.client.request("DELETE", credentialPath(name), undefined, options);
|
|
558
544
|
}
|
|
559
|
-
/** Changes to
|
|
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/
|
|
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,
|
|
826
|
-
* and
|
|
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.
|