@boxline/sdk 1.1.0 → 1.3.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 +93 -1
- package/README.md +92 -34
- package/dist/client.d.ts +67 -45
- package/dist/client.js +87 -62
- 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 +60 -16
- package/dist/errors.js +72 -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 +31 -3
- package/dist/session.js +45 -4
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +296 -133
- 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,99 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@boxline/sdk`. The SDK follows [semantic versioning](https://semver.org).
|
|
4
4
|
|
|
5
|
-
## 1.
|
|
5
|
+
## 1.3.0 (2026-10-03)
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Time limits that fit the server.** `session.login`, `typeCredential` with `field: "otp"` and plain-English steps that use `%NAME.otp%` or
|
|
10
|
+
`%NAME.link%` wait as long as the server may (up to 24 minutes for `login`, 16 for a code), instead of the
|
|
11
|
+
default 120 s that cut off a login waiting for a pushed code.
|
|
12
|
+
|
|
13
|
+
- **Codes from your own system.** A password credential's `codeSource` is `"totp"` (the authenticator key,
|
|
14
|
+
`totpSecret`; `totpSecret` alone still means this), `"push"` or `"url"`, or null for no 2FA; with `"push"` or
|
|
15
|
+
`"url"` a run, action or `boxline-otp` that needs a code (or a sign-in link) waits for a fresh one, up to
|
|
16
|
+
`codeTimeoutSeconds` (5 to 900, default 300). `credentials.create` and `credentials.update` take `codeSource`,
|
|
17
|
+
`codeUrl` (a public HTTPS endpoint the platform asks with a signed POST) and `codeTimeoutSeconds`; a `PasswordCredential`
|
|
18
|
+
shows `codeSource`, `codeUrl` and `codeTimeoutSeconds`. Changing `codeSource` or `codeUrl` needs the `password` again
|
|
19
|
+
(400 `invalid_request`, 409 `conflict` on a race). With a `codeUrl` the answer has `codeUrlSecret` once (type
|
|
20
|
+
`CredentialWritten`). Types `CredentialCodeSource` and `CredentialWritten`.
|
|
21
|
+
- **`credentials.pushCode(name, {code} | {link})`**: sends the code or sign-in link the site emailed or texted to a wait
|
|
22
|
+
in progress (used once, kept sealed for 10 minutes; a link must be on one of the credential's sites). Types
|
|
23
|
+
`CredentialCodePush` and `CredentialCodeAccepted`. Not retried by the SDK.
|
|
24
|
+
- **`credentials.rotateCodeUrlSecret(name)`**: a new `codeUrlSecret` for the requests to `codeUrl` (check them with
|
|
25
|
+
`verifyWebhook`).
|
|
26
|
+
- **`session.login(credential?, {url?, allowWithExtensions?})`** and the `login` action: signs the browser in with a
|
|
27
|
+
password credential in one call (a short browser-only agent run with that one credential and its sites). Resolves to
|
|
28
|
+
`{url, title, runId}` (`LoginValue`); an `ActionResult` of a failed `login` has `runId` and a `code`.
|
|
29
|
+
- Errors `CredentialCodeTimeoutError` (`credential_code_timeout`: no code or link in time), `CredentialLinkWrongSiteError`
|
|
30
|
+
(`credential_link_wrong_site`), `CredentialLoginFailedError` (`credential_login_failed`, with `runId`),
|
|
31
|
+
`CredentialLoginTimeoutError` (`credential_login_timeout`: the login ran out of time, 15 steps plus the credential's
|
|
32
|
+
`codeTimeoutSeconds` for a pushed or asked code, and its run was canceled; a kind of `CredentialLoginFailedError`) and
|
|
33
|
+
`CodeUrlNotAllowedError` (`code_url_not_allowed`), and the matching `ErrorCode` values.
|
|
34
|
+
- `session.login` resolves to the page's origin only (`value.url`) when the page is the one a sign-in link opened, since
|
|
35
|
+
such a link can keep its token in the path.
|
|
36
|
+
- The webhook event `credential.code_needed` (`WebhookCredentialCodeNeededData`: `credential`, `type`, `sessionId`,
|
|
37
|
+
`runId`): a run waits for a code or link, so forward the site's email or SMS now. Never a code or link.
|
|
38
|
+
- The credentials audit has `action: "code"` for a pushed code or link (never its value).
|
|
39
|
+
- An agent run's steps (and `agent.stream` events) have `type: "code"` while it waits for a code or link: `state`
|
|
40
|
+
`"waiting"` (push it now), then `"received"` or `"timeout"`, with `credential` and `kind`; never the value.
|
|
41
|
+
|
|
42
|
+
## 1.2.0 (2026-10-03)
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- **Credentials**: `bx.credentials.list/create/get/update/delete/audit` (`/v1/credentials`), one place for what the AI
|
|
47
|
+
types and the shell uses, with a typed union per type: a **password** (`origins`, `username`, `password`, optional
|
|
48
|
+
`totpSecret`; shown as `PasswordCredential` with `username` and `hasTotp`) and a **secret** (`value`, optional
|
|
49
|
+
`origins`; shown as `SecretCredential` with `preview`). `credentials.create` returns the matching type; `scope`,
|
|
50
|
+
`shell`, `description` and the write-only rules are as for secrets. Types `Credential`, `CredentialType`,
|
|
51
|
+
`CredentialScope`, `CredentialField`, `PasswordCredential`, `SecretCredential`, `CredentialCreateParams`,
|
|
52
|
+
`PasswordCredentialCreateParams`, `SecretCredentialCreateParams`, `CredentialUpdateParams`,
|
|
53
|
+
`CredentialAuditEntry` (with `type`, and the new `usedBy` kinds `action` and `otp`) and `CredentialAuditParams`.
|
|
54
|
+
Passwords need the plan's `loginDetails`; `PlanLimit` is `maxCredentials`.
|
|
55
|
+
- `credentials.update` that makes an AI-only credential readable by shells (`scope` to `"shell"` or `"all"`, or
|
|
56
|
+
`shell: true`) needs the values again in the same call, like a new site (the API answers 400 `invalid_request`
|
|
57
|
+
otherwise, 409 `conflict` when the sites, scope or `shell` changed meanwhile).
|
|
58
|
+
- **`credentials: ["NAME"]`** where the API takes them: `sessions.create` (exported into the shell: a secret as `$NAME`,
|
|
59
|
+
a password as `$NAME_USERNAME` and `$NAME_PASSWORD`; `boxline-otp NAME` prints its 2FA code), `exec` and `execStream`,
|
|
60
|
+
`agent.run` and `session.step()` and the step action (placeholders `%NAME%`, `%NAME.username%`, `%NAME.password%`,
|
|
61
|
+
`%NAME.otp%`), `runScript`, and `tasks.create` / `tasks.update` (a task shows its `credentials`). A `Session` lists
|
|
62
|
+
the exported `credentials`.
|
|
63
|
+
- **`session.typeCredential(name, {field, selector, allowWithExtensions})`** and the `type` action with `credential`
|
|
64
|
+
(and `field`: `"username"`, `"password"` or `"otp"`): a credential's value typed into a field without passing
|
|
65
|
+
through your code, only on the credential's sites.
|
|
66
|
+
- **`profiles.update(id, {name?, credential?})`**: rename a profile and/or link the password credential it signs in
|
|
67
|
+
with (`credential: null` unlinks it). A `Profile` has `credential`; sessions with the profile, and the agent runs,
|
|
68
|
+
task runs and steps in them, get that credential as if it were listed.
|
|
69
|
+
- Errors `CredentialExistsError` (409 `credential_exists`), `CredentialNotAllowedError` (400 `credential_not_for_ai`
|
|
70
|
+
/ `credential_not_for_shell`), `TooManyCredentialValuesError` (409 `too_many_credential_values`) and
|
|
71
|
+
`ErrorCode.credentialNotFound` (404 `credential_not_found`, a `NotFoundError`). The webhook event `credential.changed`
|
|
72
|
+
(`WebhookCredentialChangedData`: `name`, `action`, `type`, `by`, `changed`).
|
|
73
|
+
- `examples/credentials.ts`.
|
|
74
|
+
|
|
75
|
+
### Changed (breaking)
|
|
76
|
+
|
|
77
|
+
Nothing above shipped before, so these old names are gone with no aliases.
|
|
78
|
+
|
|
79
|
+
- **Secrets and profile login details became credentials.** `bx.secrets` is `bx.credentials`; `secrets` on
|
|
80
|
+
`sessions.create`, `exec`, `agent.run`, steps, `runScript` and tasks is `credentials` (`Session.secrets` is
|
|
81
|
+
`Session.credentials`, `Task.secrets` is `Task.credentials`); `login: true` on `runScript` is gone (list the
|
|
82
|
+
credential); `profiles.setLogin`, `updateLogin` and `deleteLogin`, `Profile.login`, `LoginDetails`,
|
|
83
|
+
`LoginDetailsUpdate` and the placeholders `%login.username%`, `%login.password%` and `%login.otp%` are gone: create a
|
|
84
|
+
password credential and link it with `profiles.update(id, {credential})`. Types `Secret`, `SecretScope`,
|
|
85
|
+
`SecretCreateParams`, `SecretUpdateParams`, `SecretAuditEntry` and `SecretAuditParams` are replaced by the credential
|
|
86
|
+
types above; `SecretExistsError`, `SecretNotAllowedError` and `TooManySecretValuesError` by `CredentialExistsError`,
|
|
87
|
+
`CredentialNotAllowedError` and `TooManyCredentialValuesError`; the plan field `maxSecrets` is `maxCredentials`; the
|
|
88
|
+
webhook event `secret.changed` is `credential.changed`.
|
|
89
|
+
- **Saved logins (contexts) are now browser profiles.** `bx.contexts` is `bx.profiles` (`create`, `get`, `list`,
|
|
90
|
+
`update`, `delete`; the routes are `/v1/profiles`; `contexts.rename` is `profiles.update(id, {name})`). Sessions and
|
|
91
|
+
agent runs take `profile: {id, persist?}` instead of `context`; tasks take `profile` instead of `savedLogin` (and
|
|
92
|
+
show it); a `Session` has `profileId` and `profilePersist` instead of `contextId` and `contextPersist`; the plan
|
|
93
|
+
fields are `maxProfiles` and `maxProfileBytes`, the plan feature is `"profiles"`, and the error code is
|
|
94
|
+
`ErrorCode.profileTooLarge` (`profile_too_large`). Types: `Profile` (was `ContextInfo`) and `TaskProfile`; the class
|
|
95
|
+
`Contexts` is `Profiles`. New profiles have ids starting with `prof_`. The old names are gone.
|
|
96
|
+
|
|
97
|
+
## 1.1.0 (2026-10-02)
|
|
6
98
|
|
|
7
99
|
### Added
|
|
8
100
|
|
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,100 @@ 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
|
|
277
|
+
|
|
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" });
|
|
261
283
|
|
|
262
|
-
//
|
|
263
|
-
await
|
|
264
|
-
|
|
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" });
|
|
286
|
+
|
|
287
|
+
for await (const e of bx.credentials.audit({ name: "SHOP" })) console.log(e.at, e.action, e.actor, e.usedBy?.type);
|
|
288
|
+
```
|
|
289
|
+
|
|
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, and
|
|
295
|
+
so does a change of where the codes come from (`codeSource`, `codeUrl`: the `password` again).
|
|
296
|
+
- `runScript(code, { credentials })` lets the script's `step()` calls use credentials (the values never enter the
|
|
297
|
+
machine). In a session with Chrome extensions, steps, scripts and the `type` action with credentials need
|
|
298
|
+
`allowWithExtensions: true`, as agent runs with variables do.
|
|
299
|
+
- Errors: `CredentialExistsError` (use `update`), `CredentialNotAllowedError` (the scope does not allow that use),
|
|
300
|
+
`NotFoundError` (`credential_not_found`), `TooManyCredentialValuesError` (the session hides as many values as it can:
|
|
301
|
+
start a new one), `FeatureNotInPlanError` (a password needs the plan's `loginDetails`), `MachineTooOldError` (during
|
|
302
|
+
a deploy), `PlanLimitError` (beyond the plan's `maxCredentials`), `CredentialCodeTimeoutError` (no code or link came
|
|
303
|
+
in time), `CredentialLinkWrongSiteError` (a sign-in link not on the credential's sites), `CredentialLoginFailedError`
|
|
304
|
+
(`session.login` could not sign in; `runId` is the run that tried), `CodeUrlNotAllowedError` (a `codeUrl` that is not a
|
|
305
|
+
public HTTPS address).
|
|
306
|
+
- The `credential.changed` webhook event says a credential was created, changed (or linked to a profile) or deleted,
|
|
307
|
+
never a value.
|
|
308
|
+
|
|
309
|
+
### Codes sent by email or SMS, and signing in in one call
|
|
310
|
+
|
|
311
|
+
A password's 2FA codes can come from an authenticator key (`codeSource: "totp"`, what `totpSecret` alone means), from
|
|
312
|
+
**your system** (`"push"`) or from **an endpoint of yours** (`"url"`). The site's email or SMS goes to you; the AI
|
|
313
|
+
never sees the code or a sign-in ("magic") link.
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
await bx.credentials.create({
|
|
317
|
+
name: "SHOP", type: "password", origins: ["https://shop.example.com"], username: "ops@example.com",
|
|
318
|
+
password: process.env.SHOP_PASSWORD!,
|
|
319
|
+
codeSource: "push", // or "url" with codeUrl: "https://ops.example.com/boxline-codes"
|
|
320
|
+
codeTimeoutSeconds: 300, // how long a run waits for a code (5 to 900)
|
|
321
|
+
});
|
|
265
322
|
|
|
266
|
-
// A
|
|
267
|
-
|
|
323
|
+
// A run, an action or `boxline-otp SHOP` that needs a code waits for a fresh one. The webhook credential.code_needed
|
|
324
|
+
// ({credential, type: "code" | "link", sessionId, runId}) says when; then push what the site sent:
|
|
325
|
+
await bx.credentials.pushCode("SHOP", { code: "482913" }); // a 2FA code
|
|
326
|
+
await bx.credentials.pushCode("SHOP", { link: "https://shop.example.com/magic?t=…" }); // or a sign-in link
|
|
268
327
|
|
|
269
|
-
|
|
328
|
+
// Sign in in one call: a short browser-only run with this one credential (default: the session's profile's).
|
|
329
|
+
const page = await s.login("SHOP", { url: "https://shop.example.com/login" }); // {url, title, runId}
|
|
270
330
|
```
|
|
271
331
|
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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`).
|
|
332
|
+
- A pushed code or link is used once, by a wait that began before it arrived, and kept sealed for 10 minutes. A link must
|
|
333
|
+
be on one of the credential's sites. `pushCode` is not retried by the SDK (a second push is a second code).
|
|
334
|
+
- With `codeSource: "url"` the platform asks your `codeUrl` every 5 s while a run waits (a signed POST; check it with
|
|
335
|
+
`verifyWebhook` and the `codeUrlSecret` that `create` and `update` return once; `credentials.rotateCodeUrlSecret(name)`
|
|
336
|
+
makes a new one). Answer `{code}` or `{link}`, or 204 for "not yet".
|
|
337
|
+
- Without a code in time a step, action or `login` throws `CredentialCodeTimeoutError`.
|
|
281
338
|
|
|
282
339
|
## A script with useModel
|
|
283
340
|
|
|
@@ -397,8 +454,8 @@ for await (const e of session.events({ types: ["console", "error"] })) console.l
|
|
|
397
454
|
for await (const p of page.iterPages()) console.log(p.data.length);
|
|
398
455
|
```
|
|
399
456
|
|
|
400
|
-
Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `
|
|
401
|
-
`crawl.list`, `extensions.list`, `tasks.list`, `tasks.runs`, `
|
|
457
|
+
Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `profiles.list`, `apiKeys.list`, `agent.list`,
|
|
458
|
+
`crawl.list`, `extensions.list`, `tasks.list`, `tasks.runs`, `credentials.list`, `credentials.audit`, and a crawl's pages (`crawl.get(id, {after})`, or
|
|
402
459
|
`for await (const p of bx.crawl.pages(id))`).
|
|
403
460
|
|
|
404
461
|
## Errors, retries and time limits
|
|
@@ -411,13 +468,14 @@ Lists: `sessions.list`, `sessions.events`, `sessions.pages`, `contexts.list`, `a
|
|
|
411
468
|
`OutOfViewportError`, `WebhookUrlNotAllowedError`, `WebhooksUnavailableError`, `WebhookDisabledError`,
|
|
412
469
|
`PayloadExpiredError`, `WebhookSignatureError` (from verifyWebhook), `VariablesWithExtensionsError`,
|
|
413
470
|
`InvalidExtensionError`, `PayloadTooLargeError`, `LimitReachedError`, `ExtensionDeniedError`, `CrossSiteRequestError`,
|
|
414
|
-
`MissingVariablesError`, `PlanLimitError`, `
|
|
471
|
+
`MissingVariablesError`, `PlanLimitError`, `CredentialExistsError`, `CredentialNotAllowedError`, `TooManyCredentialValuesError`,
|
|
472
|
+
`CredentialCodeTimeoutError`, `CredentialLinkWrongSiteError`, `CredentialLoginFailedError`, `CodeUrlNotAllowedError`,
|
|
415
473
|
`MachineTooOldError`, `NotContinuableError`, `TooManyMessagesError`, `SessionNotRunningError`, `AuthenticationError`,
|
|
416
474
|
`NotFoundError`, and
|
|
417
475
|
`BoxlineConnectionError` /
|
|
418
476
|
`BoxlineTimeoutError` when no answer came back. `ErrorCode` has the codes.
|
|
419
477
|
- **Retries.** GETs, and the calls that create or start something (sessions, bulk, agent runs, continued runs, messages
|
|
420
|
-
to runs, crawls, API keys,
|
|
478
|
+
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
479
|
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
480
|
`RateLimitError`). Other POSTs (exec, actions, fetch…) are never retried: they could run twice.
|
|
423
481
|
- **Idempotency keys.** The SDK sends a new `Idempotency-Key` with every create, and the same one on its retries, so a
|
|
@@ -446,12 +504,12 @@ same methods without it (`session.pause()`).
|
|
|
446
504
|
| Account | `me`, `hasFeature`, `auth.signup`, `auth.login`, `auth.logout`, `project.trajectories`, `project.setTrajectories`, `project.settings`, `project.setSettings`, `apiKeys.list`, `apiKeys.create`, `apiKeys.revoke` |
|
|
447
505
|
| Webhooks | `webhooks.create`, `list`, `get`, `update`, `delete`, `rotateSecret`, `test`, `deliveries`, `retryDelivery`; `verifyWebhook` (no request) |
|
|
448
506
|
| 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` |
|
|
507
|
+
| 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
508
|
| Shell and scripts | `sessions.exec`, `execStream`, `runScript`, `restartShell` |
|
|
451
509
|
| Files | `sessions.files.list`, `read`, `readText`, `write`, `delete`, `waitFor` |
|
|
452
510
|
| Logs | `sessions.events`, `streamEvents`, `pages`, `recording`, `recordingFrame`; on a session: `waitForHuman`, `onCaptcha` |
|
|
453
|
-
|
|
|
454
|
-
|
|
|
511
|
+
| Browser profiles | `profiles.create`, `get`, `list`, `update`, `delete` |
|
|
512
|
+
| Credentials | `credentials.create`, `list`, `get`, `update`, `delete`, `audit`, `pushCode`, `rotateCodeUrlSecret`; on a session: `typeCredential`, `login` |
|
|
455
513
|
| Extensions | `extensions.upload`, `list`, `get`, `delete` |
|
|
456
514
|
| Web | `fetch`, `screenshot`, `pdf`, `extract`, `search`, `crawl.start`, `get`, `list`, `cancel`, `pages`, `wait` |
|
|
457
515
|
| Agent | `agent.models`, `run`, `get`, `list`, `takeover`, `handBack`, `cancel`, `continueRun`, `sendMessage`, `stream`, `wait` |
|
|
@@ -477,7 +535,7 @@ reach, so run them with `BOXLINE_API_URL=http://localhost:8080`; `search.ts` and
|
|
|
477
535
|
| `webhooks.ts` | endpoints, deliveries and their history, re-sending, rotating the secret, a test event |
|
|
478
536
|
| `agent-variables.ts` | an agent run with `%email%` / `%password%` limited to one site |
|
|
479
537
|
| `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
|
-
| `
|
|
538
|
+
| `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
539
|
| `script-use-model.ts` | `useModel`, `step()` and `extract()` in a script |
|
|
482
540
|
| `captcha.ts` | noticing a CAPTCHA and handing it to a person |
|
|
483
541
|
| `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, CredentialCodeAccepted, CredentialCodePush, CredentialAuditParams, CredentialCreateParams, CredentialUpdateParams, CredentialWritten, 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,92 @@ 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 where its 2FA codes come from: `codeSource: "totp"` with `totpSecret`, `"push"` (send
|
|
331
|
+
* each code or sign-in link with `pushCode`) or `"url"` with `codeUrl` (needs the plan's `loginDetails`:
|
|
332
|
+
* FeatureNotInPlanError); `type: "secret"` takes `value`. CredentialExistsError for a name the project has (change it
|
|
333
|
+
* with update), PlanLimitError beyond the plan's `maxCredentials`; 400 `code_url_not_allowed` for a `codeUrl` that is
|
|
334
|
+
* not a public HTTPS address. With `codeUrl` the answer has `codeUrlSecret`, the key that signs the platform's
|
|
335
|
+
* requests, shown this once. Not retried by the SDK (the API takes no Idempotency-Key here): a retry after a lost
|
|
336
|
+
* answer may meet CredentialExistsError.
|
|
339
337
|
*/
|
|
340
|
-
create(params:
|
|
341
|
-
|
|
338
|
+
create(params: PasswordCredentialCreateParams, options?: RequestOptions): Promise<CredentialWritten<PasswordCredential>>;
|
|
339
|
+
create(params: SecretCredentialCreateParams, options?: RequestOptions): Promise<CredentialWritten<SecretCredential>>;
|
|
340
|
+
create(params: CredentialCreateParams, options?: RequestOptions): Promise<CredentialWritten>;
|
|
341
|
+
get(name: string, options?: RequestOptions): Promise<Credential>;
|
|
342
342
|
/**
|
|
343
|
-
* Changes the fields you send
|
|
344
|
-
*
|
|
343
|
+
* Changes the fields you send (the type cannot change: delete it and create it again). A new site, or a `scope`
|
|
344
|
+
* or `shell` that makes an AI-only credential readable by shells, needs the sensitive values again in the same call
|
|
345
|
+
* (a secret's `value`; a password's `password`, and `totpSecret` when it has 2FA), else a 400 `invalid_request`; so
|
|
346
|
+
* does a change of where a password's codes come from (`codeSource`, removing 2FA included, or `codeUrl`: the
|
|
347
|
+
* `password` again). A 409 `conflict` when the sites, scope, `shell`, `codeSource` or `codeUrl` changed meanwhile
|
|
348
|
+
* (send it again). A new `codeUrl` answers with a new `codeUrlSecret`, shown once. A running agent run keeps the
|
|
349
|
+
* values it started with; a session that exports the credential gets the new ones on its next machine (move,
|
|
350
|
+
* resume, recovery).
|
|
345
351
|
*/
|
|
346
|
-
update(name: string, patch:
|
|
347
|
-
/** Deletes it; sessions that exported it no longer get it on their next machine. */
|
|
352
|
+
update(name: string, patch: CredentialUpdateParams, options?: RequestOptions): Promise<CredentialWritten>;
|
|
353
|
+
/** Deletes it; profiles that link it are unlinked, and sessions that exported it no longer get it on their next machine. */
|
|
348
354
|
delete(name: string, options?: RequestOptions): Promise<void>;
|
|
349
|
-
/**
|
|
350
|
-
|
|
355
|
+
/**
|
|
356
|
+
* For a password with `codeSource: "push"`: sends the code (`{code}`) or the sign-in link (`{link}`) the site emailed
|
|
357
|
+
* or texted, for a run, action or `boxline-otp` that waits for it (the webhook `credential.code_needed` says when).
|
|
358
|
+
* It is kept sealed for up to 10 minutes and used once, by a wait that began before it arrived. A link must be on one of
|
|
359
|
+
* the credential's sites (400 `credential_link_wrong_site`). 400 `invalid_request` for a credential whose source is
|
|
360
|
+
* not "push"; NotFoundError for one the project does not have. Not retried by the SDK (a second push is a second
|
|
361
|
+
* code). The value is never logged or returned.
|
|
362
|
+
*/
|
|
363
|
+
pushCode(name: string, code: CredentialCodePush, options?: RequestOptions): Promise<CredentialCodeAccepted>;
|
|
364
|
+
/**
|
|
365
|
+
* For a password with `codeSource: "url"`: a new `codeUrlSecret` (`whsec_…`, shown this once). Requests to `codeUrl` are
|
|
366
|
+
* signed with it from now on (check them with `verifyWebhook`); the old one stops at once.
|
|
367
|
+
*/
|
|
368
|
+
rotateCodeUrlSecret(name: string, options?: RequestOptions): Promise<{
|
|
369
|
+
codeUrlSecret: string;
|
|
370
|
+
}>;
|
|
371
|
+
/** Changes to credentials and each use (once per session, command, run, script, task run, typed field or 2FA code) and pushed codes, newest first. */
|
|
372
|
+
audit(params?: CredentialAuditParams, options?: RequestOptions): PagePromise<CredentialAuditEntry>;
|
|
351
373
|
}
|
|
352
374
|
/** Crawls: follow links from a start URL in the background (robots.txt respected); poll with get() or wait(). */
|
|
353
375
|
export declare class Crawl {
|
|
@@ -496,8 +518,8 @@ export declare class Agent {
|
|
|
496
518
|
cancel(id: string, options?: RequestOptions): Promise<AgentRun>;
|
|
497
519
|
/**
|
|
498
520
|
* 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
|
|
521
|
+
* while its `continuable` is set: a new run in the same session, with the same model, mode, output schema, credentials
|
|
522
|
+
* and profile, and a compact record of what the previous run did. Returns the new run (`continuedFrom` links
|
|
501
523
|
* back); wait for it with `wait(run.id)` or `stream(run.id)` like any run. A run that had `variables` needs them again
|
|
502
524
|
* (MissingVariablesError otherwise). NotContinuableError: it did not stop at a limit, was continued already, or its
|
|
503
525
|
* window passed. An Idempotency-Key is sent, so a retry never starts a second run.
|