@parall/daemon 1.36.1 → 1.38.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/bundle/manifest.json +11 -11
- package/bundle/parall-browser-pod.js +352 -27
- package/bundle/parall-claude-agent.js +1219 -269
- package/bundle/parall-codex-agent.js +1225 -276
- package/bundle/parall-daemon.js +33552 -31712
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/clip-runtime/browser-daemon-env.d.ts +29 -0
- package/dist/clip-runtime/browser-daemon-env.d.ts.map +1 -0
- package/dist/clip-runtime/browser-daemon-env.js +70 -0
- package/dist/clip-runtime/browser-profile-manager.d.ts +18 -5
- package/dist/clip-runtime/browser-profile-manager.d.ts.map +1 -1
- package/dist/clip-runtime/browser-profile-manager.js +149 -24
- package/dist/clip-runtime/browser-profile-pool.d.ts +250 -0
- package/dist/clip-runtime/browser-profile-pool.d.ts.map +1 -0
- package/dist/clip-runtime/browser-profile-pool.js +581 -0
- package/dist/clip-runtime/index.d.ts +2 -2
- package/dist/clip-runtime/index.d.ts.map +1 -1
- package/dist/clip-runtime/index.js +2 -1
- package/dist/clip-runtime/process-manager.d.ts +5 -3
- package/dist/clip-runtime/process-manager.d.ts.map +1 -1
- package/dist/clip-runtime/subprocess.d.ts +14 -0
- package/dist/clip-runtime/subprocess.d.ts.map +1 -1
- package/dist/clip-runtime/subprocess.js +49 -0
- package/dist/config.d.ts +14 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -26
- package/dist/daemon-main.d.ts +8 -0
- package/dist/daemon-main.d.ts.map +1 -0
- package/dist/daemon-main.js +165 -0
- package/dist/daemon-paths.d.ts +14 -0
- package/dist/daemon-paths.d.ts.map +1 -0
- package/dist/daemon-paths.js +26 -0
- package/dist/daemon-update-mode.d.ts +8 -0
- package/dist/daemon-update-mode.d.ts.map +1 -0
- package/dist/daemon-update-mode.js +18 -0
- package/dist/index.js +41 -167
- package/dist/runtime-bin-resolver.d.ts +4 -0
- package/dist/runtime-bin-resolver.d.ts.map +1 -1
- package/dist/runtime-bin-resolver.js +40 -7
- package/dist/runtime-detector.d.ts +30 -0
- package/dist/runtime-detector.d.ts.map +1 -0
- package/dist/runtime-detector.js +100 -0
- package/dist/supervisor.d.ts +53 -2
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +604 -67
- package/dist/update-health-gate.d.ts +66 -0
- package/dist/update-health-gate.d.ts.map +1 -0
- package/dist/update-health-gate.js +93 -0
- package/dist/updater-manifest.d.ts +2 -1
- package/dist/updater-manifest.d.ts.map +1 -1
- package/dist/updater-manifest.js +38 -7
- package/dist/updater.d.ts +13 -2
- package/dist/updater.d.ts.map +1 -1
- package/dist/updater.js +126 -17
- package/package.json +6 -6
package/bundle/manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"built_at": "2026-
|
|
2
|
+
"version": "1.38.0",
|
|
3
|
+
"built_at": "2026-07-06T10:59:40.316Z",
|
|
4
4
|
"min_node_version": "20.0.0",
|
|
5
5
|
"files": {
|
|
6
6
|
"bb-browser-daemon.js": {
|
|
@@ -16,25 +16,25 @@
|
|
|
16
16
|
"size": 18
|
|
17
17
|
},
|
|
18
18
|
"parall-browser-pod.js": {
|
|
19
|
-
"sha256": "
|
|
20
|
-
"size":
|
|
19
|
+
"sha256": "9426af841c2011c341e28e03a0176da146e6c30da88878cc2e70f3211512e7e8",
|
|
20
|
+
"size": 1697014
|
|
21
21
|
},
|
|
22
22
|
"parall-claude-agent.js": {
|
|
23
|
-
"sha256": "
|
|
24
|
-
"size":
|
|
23
|
+
"sha256": "11436cabd17a19f2af8eb433a506efc6342efb76fbe25c8c882aea13220b5350",
|
|
24
|
+
"size": 1616948
|
|
25
25
|
},
|
|
26
26
|
"parall-codex-agent.js": {
|
|
27
|
-
"sha256": "
|
|
28
|
-
"size":
|
|
27
|
+
"sha256": "5d28aecbd029c64cd1402f748e12ae6bdf502ab38a21b95bb546407469e4d826",
|
|
28
|
+
"size": 1647758
|
|
29
29
|
},
|
|
30
30
|
"parall-daemon.js": {
|
|
31
|
-
"sha256": "
|
|
32
|
-
"size":
|
|
31
|
+
"sha256": "0470fa07cce7477c70c075eb939e9e14b6dab40cfa4a6f609974c68f28537923",
|
|
32
|
+
"size": 1717086
|
|
33
33
|
},
|
|
34
34
|
"parall-openclaw-agent.js": {
|
|
35
35
|
"sha256": "505433b4bf3a4b8dbb7b96978d8693d6c48079f4513282ff1ee59a6d13b3eddf",
|
|
36
36
|
"size": 9801
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
-
"signature": "
|
|
39
|
+
"signature": "bfGTE2slDSlantJRoa8j9CEENod1u89vVzhn0aFI29c+V9Lj2IuXdage/Mu3vfr+kDUYCisH9DPqBD6o7X4kDA=="
|
|
40
40
|
}
|
|
@@ -8055,8 +8055,8 @@ var init_requestBuilder = __esm({
|
|
|
8055
8055
|
async build() {
|
|
8056
8056
|
const { hostname, protocol = "https", port, path: basePath } = await this.context.endpoint();
|
|
8057
8057
|
this.path = basePath;
|
|
8058
|
-
for (const
|
|
8059
|
-
|
|
8058
|
+
for (const resolvePath2 of this.resolvePathStack) {
|
|
8059
|
+
resolvePath2(this.path);
|
|
8060
8060
|
}
|
|
8061
8061
|
return new import_protocol_http5.HttpRequest({
|
|
8062
8062
|
protocol,
|
|
@@ -35113,6 +35113,7 @@ var ENDPOINTS = {
|
|
|
35113
35113
|
// Org-scoped
|
|
35114
35114
|
ORG: (orgId) => `${API_BASE}/orgs/${orgId}`,
|
|
35115
35115
|
ORG_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/members`,
|
|
35116
|
+
ORG_MEMBERS_FORMER: (orgId) => `${API_BASE}/orgs/${orgId}/members/former`,
|
|
35116
35117
|
TEAMS: (orgId) => `${API_BASE}/orgs/${orgId}/teams`,
|
|
35117
35118
|
ORG_MEMBERS_ONLINE: (orgId) => `${API_BASE}/orgs/${orgId}/members/online`,
|
|
35118
35119
|
ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
|
|
@@ -35262,6 +35263,19 @@ var ENDPOINTS = {
|
|
|
35262
35263
|
EXTERNAL_TRIGGER: (orgId, triggerId) => `${API_BASE}/orgs/${orgId}/external-triggers/${triggerId}`,
|
|
35263
35264
|
EXTERNAL_TRIGGER_RUNS: (orgId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs`,
|
|
35264
35265
|
EXTERNAL_TRIGGER_RUN: (orgId, runId) => `${API_BASE}/orgs/${orgId}/external-trigger-runs/${runId}`,
|
|
35266
|
+
// External IM channel (org-scoped, platform-mediated Feishu/Slack)
|
|
35267
|
+
CHANNEL_CONNECTIONS: (orgId) => `${API_BASE}/orgs/${orgId}/channel-connections`,
|
|
35268
|
+
CHANNEL_CONNECTION: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}`,
|
|
35269
|
+
CHANNEL_CONNECTION_CREDENTIALS: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/credentials`,
|
|
35270
|
+
CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/ingress-token/regenerate`,
|
|
35271
|
+
CHANNEL_CONNECTION_CONVERSATIONS: (orgId, connectionId) => `${API_BASE}/orgs/${orgId}/channel-connections/${connectionId}/conversations`,
|
|
35272
|
+
CHANNEL_CONVERSATION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}`,
|
|
35273
|
+
CHANNEL_CONVERSATION_MESSAGES: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/messages`,
|
|
35274
|
+
CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
|
|
35275
|
+
CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
|
|
35276
|
+
CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
|
|
35277
|
+
CHANNEL_PROVISIONING_SESSION: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
|
|
35278
|
+
CHANNEL_PROVISIONING_CANCEL: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
|
|
35265
35279
|
// Invitations (org-scoped, admin)
|
|
35266
35280
|
ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
|
|
35267
35281
|
ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
|
|
@@ -35279,9 +35293,16 @@ var ENDPOINTS = {
|
|
|
35279
35293
|
INVITE_LINK_JOIN: `${API_BASE}/invite-link/join`,
|
|
35280
35294
|
// Wikis (org-scoped, served by wiki-service)
|
|
35281
35295
|
WIKIS: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis`,
|
|
35296
|
+
// Recycle bin — soft-deleted wikis (owner only). Must precede WIKI in the
|
|
35297
|
+
// backend router so `deleted` isn't captured as a {wikiId}; the SDK builder
|
|
35298
|
+
// is just a string.
|
|
35299
|
+
WIKIS_DELETED: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis/deleted`,
|
|
35300
|
+
// Detail URL — also reused for DELETE (soft-delete) and `${WIKI}/restore`.
|
|
35282
35301
|
WIKI: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
|
|
35302
|
+
WIKI_RESTORE: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restore`,
|
|
35283
35303
|
WIKI_TREE: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/tree`,
|
|
35284
35304
|
WIKI_BLOB: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/blob`,
|
|
35305
|
+
WIKI_COPY: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/copy`,
|
|
35285
35306
|
WIKI_NODE_SECTIONS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/node-sections`,
|
|
35286
35307
|
WIKI_SEARCH: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/search`,
|
|
35287
35308
|
WIKI_PAGE_INDEX: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/page-index`,
|
|
@@ -35335,6 +35356,11 @@ var ENDPOINTS = {
|
|
|
35335
35356
|
DISPATCH_ACK_BY_ID: (orgId, id) => `${API_BASE}/orgs/${orgId}/dispatch/${id}/ack`,
|
|
35336
35357
|
DISPATCH_EXPIRE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/expire`,
|
|
35337
35358
|
DISPATCH_BY_MESSAGES: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/by-messages`,
|
|
35359
|
+
DISPATCH_CLAIM: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/claim`,
|
|
35360
|
+
DISPATCH_STEER: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/steer`,
|
|
35361
|
+
DISPATCH_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/complete`,
|
|
35362
|
+
DISPATCH_RELEASE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/release`,
|
|
35363
|
+
DISPATCH_HEARTBEAT: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/heartbeat`,
|
|
35338
35364
|
// Unread
|
|
35339
35365
|
UNREAD: `${API_BASE}/me/unread`,
|
|
35340
35366
|
ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
|
|
@@ -35364,6 +35390,14 @@ var ENDPOINTS = {
|
|
|
35364
35390
|
BILLING_AUTO_RELOAD: (orgId) => `${API_BASE}/orgs/${orgId}/billing/auto-reload`,
|
|
35365
35391
|
BILLING_SETUP_INTENT: (orgId) => `${API_BASE}/orgs/${orgId}/billing/setup-intent`,
|
|
35366
35392
|
COMPUTE_PRICING: () => `${API_BASE}/billing/compute-pricing`,
|
|
35393
|
+
// Runtime capability table (public, no auth) — SSOT for the create/settings
|
|
35394
|
+
// interlock: per-runtime compute modes, native model family, cross-family
|
|
35395
|
+
// availability, and recommended model.
|
|
35396
|
+
RUNTIMES: () => `${API_BASE}/runtimes`,
|
|
35397
|
+
// Model catalog (public, no auth) — served from the server's DB-backed
|
|
35398
|
+
// snapshot. Optional include_model keeps an agent's pinned hidden legacy
|
|
35399
|
+
// model representable in settings pickers.
|
|
35400
|
+
MODELS: (includeModel) => includeModel ? `${API_BASE}/models?include_model=${encodeURIComponent(includeModel)}` : `${API_BASE}/models`,
|
|
35367
35401
|
// ADMIN_GRANTS intentionally NOT exported here — it sits under the
|
|
35368
35402
|
// unauthenticated `/internal/admin/*` surface and must not bleed into the
|
|
35369
35403
|
// public SDK. Admin dashboard hits the URL directly from its own client.
|
|
@@ -35376,6 +35410,7 @@ var ENDPOINTS = {
|
|
|
35376
35410
|
AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
|
|
35377
35411
|
CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
|
|
35378
35412
|
CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
|
|
35413
|
+
BROWSER_RUNTIME_STATUS: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-runtime/status`,
|
|
35379
35414
|
BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
|
|
35380
35415
|
BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
|
|
35381
35416
|
BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
|
|
@@ -35571,6 +35606,7 @@ var ParallClient = class _ParallClient {
|
|
|
35571
35606
|
const rawErrorBody = await res.json().catch(() => ({}));
|
|
35572
35607
|
throw buildApiError(res, rawErrorBody);
|
|
35573
35608
|
}
|
|
35609
|
+
opts?.onStatus?.(res.status);
|
|
35574
35610
|
if (res.status === 204)
|
|
35575
35611
|
return void 0;
|
|
35576
35612
|
if (res.status === 202) {
|
|
@@ -35720,6 +35756,13 @@ var ParallClient = class _ParallClient {
|
|
|
35720
35756
|
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS(orgId));
|
|
35721
35757
|
return res.data;
|
|
35722
35758
|
}
|
|
35759
|
+
/** User IDs of soft-removed (former) org members — for marking their avatar /
|
|
35760
|
+
* name as "left" where dormant relations still surface them (DMs, task
|
|
35761
|
+
* assignees, message history). */
|
|
35762
|
+
async getFormerMemberIds(orgId) {
|
|
35763
|
+
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_FORMER(orgId));
|
|
35764
|
+
return res.user_ids ?? [];
|
|
35765
|
+
}
|
|
35723
35766
|
async getTeams(orgId) {
|
|
35724
35767
|
const res = await this.request("GET", ENDPOINTS.TEAMS(orgId));
|
|
35725
35768
|
return res.data;
|
|
@@ -35897,6 +35940,21 @@ var ParallClient = class _ParallClient {
|
|
|
35897
35940
|
async sendMessage(orgId, chatId, req) {
|
|
35898
35941
|
return this.request("POST", ENDPOINTS.CHAT_MESSAGES(orgId, chatId), req);
|
|
35899
35942
|
}
|
|
35943
|
+
/**
|
|
35944
|
+
* sendMessage variant that also reports whether the server answered with an
|
|
35945
|
+
* idempotent replay (HTTP 200 — the message already existed for this
|
|
35946
|
+
* idempotency/effect key) instead of a fresh create (201). Used by the CLI
|
|
35947
|
+
* to surface "already sent by a previous run (deduplicated)".
|
|
35948
|
+
*/
|
|
35949
|
+
async sendMessageDetailed(orgId, chatId, req) {
|
|
35950
|
+
let status = 0;
|
|
35951
|
+
const message = await this.request("POST", ENDPOINTS.CHAT_MESSAGES(orgId, chatId), req, void 0, false, {
|
|
35952
|
+
onStatus: (s) => {
|
|
35953
|
+
status = s;
|
|
35954
|
+
}
|
|
35955
|
+
});
|
|
35956
|
+
return { message, deduplicated: status === 200 };
|
|
35957
|
+
}
|
|
35900
35958
|
async getMessages(orgId, chatId, params) {
|
|
35901
35959
|
return this.request("GET", ENDPOINTS.CHAT_MESSAGES(orgId, chatId), void 0, params);
|
|
35902
35960
|
}
|
|
@@ -36208,20 +36266,25 @@ var ParallClient = class _ParallClient {
|
|
|
36208
36266
|
return res.data;
|
|
36209
36267
|
}
|
|
36210
36268
|
/** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
|
|
36211
|
-
async reportBrowserProfileStatus(profileId, status, errorMsg) {
|
|
36269
|
+
async reportBrowserProfileStatus(profileId, status, errorMsg, generation) {
|
|
36212
36270
|
await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
|
|
36213
36271
|
status,
|
|
36214
|
-
...errorMsg ? { error_msg: errorMsg } : {}
|
|
36272
|
+
...errorMsg ? { error_msg: errorMsg } : {},
|
|
36273
|
+
...generation !== void 0 ? { generation } : {}
|
|
36215
36274
|
});
|
|
36216
36275
|
}
|
|
36217
36276
|
/**
|
|
36218
36277
|
* `POST /machines/me/health` — bump the Machine's `updated_at` to now and
|
|
36219
|
-
* report daemon state. The daemon
|
|
36220
|
-
*
|
|
36278
|
+
* report daemon state. The daemon calls this on startup and again whenever
|
|
36279
|
+
* periodic runtime re-detection produces a CHANGED result (there is no
|
|
36280
|
+
* fixed-cadence keepalive loop today — steady state posts nothing). All
|
|
36221
36281
|
* fields are optional and only persisted when changed:
|
|
36222
36282
|
* - `daemonVersion` — the running bundle/launcher version.
|
|
36223
36283
|
* - `selfUpdateCapable` — whether the daemon can act on a machine.update
|
|
36224
36284
|
* signal (true under a service manager, false for bare `npx` foreground).
|
|
36285
|
+
* - `detectedRuntimes` — runtime CLIs found on the host. Omitted = no
|
|
36286
|
+
* report this beat (server keeps the stored value); [] = detection ran
|
|
36287
|
+
* and found nothing (server clears to empty).
|
|
36225
36288
|
*/
|
|
36226
36289
|
async postMachineHeartbeat(opts) {
|
|
36227
36290
|
const body = {};
|
|
@@ -36229,6 +36292,8 @@ var ParallClient = class _ParallClient {
|
|
|
36229
36292
|
body.daemon_version = opts.daemonVersion;
|
|
36230
36293
|
if (opts?.selfUpdateCapable !== void 0)
|
|
36231
36294
|
body.self_update_capable = opts.selfUpdateCapable;
|
|
36295
|
+
if (opts?.detectedRuntimes !== void 0)
|
|
36296
|
+
body.detected_runtimes = opts.detectedRuntimes;
|
|
36232
36297
|
return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
|
|
36233
36298
|
}
|
|
36234
36299
|
async reportAgentWorkspaceState(agentId, state2) {
|
|
@@ -36351,6 +36416,30 @@ var ParallClient = class _ParallClient {
|
|
|
36351
36416
|
const params = maxAgeHours !== void 0 ? { max_age_hours: String(maxAgeHours) } : void 0;
|
|
36352
36417
|
return this.request("POST", ENDPOINTS.DISPATCH_EXPIRE(orgId), void 0, params);
|
|
36353
36418
|
}
|
|
36419
|
+
/**
|
|
36420
|
+
* Claim a dispatch lane (explicit consume endpoint). Occupies the
|
|
36421
|
+
* (agent, target, thread) lane and folds claimable WorkItems into it;
|
|
36422
|
+
* `claimed: false` means a healthy incumbent holds the lane.
|
|
36423
|
+
*/
|
|
36424
|
+
async claimDispatch(orgId, req) {
|
|
36425
|
+
return this.request("POST", ENDPOINTS.DISPATCH_CLAIM(orgId), req);
|
|
36426
|
+
}
|
|
36427
|
+
/** Fold a pending same-target WorkItem into a live lane (409 STALE_LANE when dethroned). */
|
|
36428
|
+
async steerDispatch(orgId, req) {
|
|
36429
|
+
return this.request("POST", ENDPOINTS.DISPATCH_STEER(orgId), req);
|
|
36430
|
+
}
|
|
36431
|
+
/** End a turn: no_action sweep of the lane's members + lane release + re-drive check. */
|
|
36432
|
+
async completeDispatch(orgId, req) {
|
|
36433
|
+
return this.request("POST", ENDPOINTS.DISPATCH_COMPLETE(orgId), req);
|
|
36434
|
+
}
|
|
36435
|
+
/** Release a lane on graceful shutdown — members return to pending immediately. */
|
|
36436
|
+
async releaseDispatchLane(orgId, lane) {
|
|
36437
|
+
return this.request("POST", ENDPOINTS.DISPATCH_RELEASE(orgId), { lane });
|
|
36438
|
+
}
|
|
36439
|
+
/** Renew a live lane's lease (long-turn keepalive). 409 STALE_LANE when dethroned. */
|
|
36440
|
+
async heartbeatDispatchLane(orgId, req) {
|
|
36441
|
+
return this.request("POST", ENDPOINTS.DISPATCH_HEARTBEAT(orgId), req);
|
|
36442
|
+
}
|
|
36354
36443
|
async getDispatchByMessages(orgId, chatId, messageIds) {
|
|
36355
36444
|
const params = { chat_id: chatId, message_ids: messageIds.join(",") };
|
|
36356
36445
|
return this.request("GET", ENDPOINTS.DISPATCH_BY_MESSAGES(orgId), void 0, params);
|
|
@@ -36547,6 +36636,59 @@ var ParallClient = class _ParallClient {
|
|
|
36547
36636
|
async deleteExternalConnection(orgId, connectionId) {
|
|
36548
36637
|
return this.request("DELETE", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
36549
36638
|
}
|
|
36639
|
+
// ---- External IM channel (org-scoped) ----
|
|
36640
|
+
async createChannelConnection(orgId, input) {
|
|
36641
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTIONS(orgId), input);
|
|
36642
|
+
}
|
|
36643
|
+
async listChannelConnections(orgId) {
|
|
36644
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTIONS(orgId));
|
|
36645
|
+
}
|
|
36646
|
+
async getChannelConnection(orgId, connectionId) {
|
|
36647
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
36648
|
+
}
|
|
36649
|
+
async updateChannelConnection(orgId, connectionId, patch) {
|
|
36650
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId), patch);
|
|
36651
|
+
}
|
|
36652
|
+
async archiveChannelConnection(orgId, connectionId) {
|
|
36653
|
+
return this.request("DELETE", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
36654
|
+
}
|
|
36655
|
+
async deliverChannelCredentials(orgId, connectionId, credentials) {
|
|
36656
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_CREDENTIALS(orgId, connectionId), credentials);
|
|
36657
|
+
}
|
|
36658
|
+
async regenerateChannelIngressToken(orgId, connectionId) {
|
|
36659
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId));
|
|
36660
|
+
}
|
|
36661
|
+
/** Start a Feishu one-click provisioning session (device flow QR). */
|
|
36662
|
+
async initiateChannelProvisioning(orgId, input) {
|
|
36663
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
|
|
36664
|
+
}
|
|
36665
|
+
/**
|
|
36666
|
+
* Lazy status poll — server-side this may forward one provider poll, so
|
|
36667
|
+
* call it at the session's `poll_interval_seconds` cadence, not faster.
|
|
36668
|
+
*/
|
|
36669
|
+
async getChannelProvisioningSession(orgId, sessionId) {
|
|
36670
|
+
return this.request("GET", ENDPOINTS.CHANNEL_PROVISIONING_SESSION(orgId, sessionId));
|
|
36671
|
+
}
|
|
36672
|
+
async cancelChannelProvisioning(orgId, sessionId) {
|
|
36673
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING_CANCEL(orgId, sessionId));
|
|
36674
|
+
}
|
|
36675
|
+
async listChannelConversations(orgId, connectionId) {
|
|
36676
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
|
|
36677
|
+
}
|
|
36678
|
+
async getChannelConversation(orgId, conversationId) {
|
|
36679
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION(orgId, conversationId));
|
|
36680
|
+
}
|
|
36681
|
+
async listChannelConversationMessages(orgId, conversationId, limit) {
|
|
36682
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION_MESSAGES(orgId, conversationId), void 0, { limit });
|
|
36683
|
+
}
|
|
36684
|
+
async setChannelConversationSession(orgId, conversationId, agentSessionId) {
|
|
36685
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONVERSATION_SESSION(orgId, conversationId), {
|
|
36686
|
+
agent_session_id: agentSessionId
|
|
36687
|
+
});
|
|
36688
|
+
}
|
|
36689
|
+
async getChannelMessage(orgId, messageId) {
|
|
36690
|
+
return this.request("GET", ENDPOINTS.CHANNEL_MESSAGE(orgId, messageId));
|
|
36691
|
+
}
|
|
36550
36692
|
async getExternalTriggerSchema(orgId, connectionId) {
|
|
36551
36693
|
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_SCHEMA(orgId, connectionId));
|
|
36552
36694
|
}
|
|
@@ -36588,6 +36730,23 @@ var ParallClient = class _ParallClient {
|
|
|
36588
36730
|
async getWiki(orgId, wikiId) {
|
|
36589
36731
|
return this.request("GET", ENDPOINTS.WIKI(orgId, wikiId));
|
|
36590
36732
|
}
|
|
36733
|
+
/** Soft-delete an entire wiki (org owner only; the default wiki is
|
|
36734
|
+
* protected → 403 WIKI_PROTECTED). Returns the deleted wiki. Recoverable
|
|
36735
|
+
* via restoreWiki within the retention window. */
|
|
36736
|
+
async deleteWiki(orgId, wikiId) {
|
|
36737
|
+
return this.request("DELETE", ENDPOINTS.WIKI(orgId, wikiId));
|
|
36738
|
+
}
|
|
36739
|
+
/** Restore a soft-deleted wiki (org owner only). 409 WIKI_PURGE_STARTED once
|
|
36740
|
+
* purge has been claimed (no longer restorable), or 404 once the row is gone.
|
|
36741
|
+
* Returns the restored wiki. */
|
|
36742
|
+
async restoreWiki(orgId, wikiId) {
|
|
36743
|
+
return this.request("POST", ENDPOINTS.WIKI_RESTORE(orgId, wikiId));
|
|
36744
|
+
}
|
|
36745
|
+
/** Recycle bin — list soft-deleted wikis for the org (owner only). */
|
|
36746
|
+
async getDeletedWikis(orgId) {
|
|
36747
|
+
const res = await this.request("GET", ENDPOINTS.WIKIS_DELETED(orgId));
|
|
36748
|
+
return res.data;
|
|
36749
|
+
}
|
|
36591
36750
|
async getWikiTree(orgId, wikiId, params) {
|
|
36592
36751
|
return this.request("GET", ENDPOINTS.WIKI_TREE(orgId, wikiId), void 0, params);
|
|
36593
36752
|
}
|
|
@@ -36621,6 +36780,15 @@ var ParallClient = class _ParallClient {
|
|
|
36621
36780
|
blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
36622
36781
|
return blob;
|
|
36623
36782
|
}
|
|
36783
|
+
/**
|
|
36784
|
+
* Copy one wiki file to another path as an independent snapshot (no sync).
|
|
36785
|
+
* Used to "share a private file out": copy a file from the caller's personal
|
|
36786
|
+
* namespace (`users/{userId}/…`) into the public wiki, leaving the original
|
|
36787
|
+
* untouched. 409 `FILE_EXISTS` if `dest_path` already exists.
|
|
36788
|
+
*/
|
|
36789
|
+
async copyWikiFile(orgId, wikiId, req) {
|
|
36790
|
+
return this.request("POST", ENDPOINTS.WIKI_COPY(orgId, wikiId), req);
|
|
36791
|
+
}
|
|
36624
36792
|
async getWikiNodeSections(orgId, wikiId, params) {
|
|
36625
36793
|
return this.request("GET", ENDPOINTS.WIKI_NODE_SECTIONS(orgId, wikiId), void 0, params);
|
|
36626
36794
|
}
|
|
@@ -36894,6 +37062,19 @@ var ParallClient = class _ParallClient {
|
|
|
36894
37062
|
const resp = await this.request("GET", ENDPOINTS.COMPUTE_PRICING());
|
|
36895
37063
|
return resp.data;
|
|
36896
37064
|
}
|
|
37065
|
+
/** Runtime capability table (public) — SSOT for the create/settings interlock. */
|
|
37066
|
+
async getRuntimes() {
|
|
37067
|
+
const resp = await this.request("GET", ENDPOINTS.RUNTIMES());
|
|
37068
|
+
return resp.data;
|
|
37069
|
+
}
|
|
37070
|
+
/**
|
|
37071
|
+
* Platform model catalog (public) — DB-backed, replaces the compile-time
|
|
37072
|
+
* PLATFORM_MODELS constant. Pass includeModel to keep an agent's pinned
|
|
37073
|
+
* hidden legacy model representable (settings picker).
|
|
37074
|
+
*/
|
|
37075
|
+
async getModels(includeModel) {
|
|
37076
|
+
return this.request("GET", ENDPOINTS.MODELS(includeModel));
|
|
37077
|
+
}
|
|
36897
37078
|
// ---- Clips ----
|
|
36898
37079
|
async listClips(orgId) {
|
|
36899
37080
|
const resp = await this.request("GET", ENDPOINTS.CLIPS(orgId));
|
|
@@ -36938,6 +37119,11 @@ var ParallClient = class _ParallClient {
|
|
|
36938
37119
|
const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
|
|
36939
37120
|
return resp.data;
|
|
36940
37121
|
}
|
|
37122
|
+
/** Deployment-wide hosted browser runtime availability — drives whether the
|
|
37123
|
+
* create UI offers the platform-hosted placement. Fail-closed server-side. */
|
|
37124
|
+
async getBrowserRuntimeStatus(orgId) {
|
|
37125
|
+
return this.request("GET", ENDPOINTS.BROWSER_RUNTIME_STATUS(orgId));
|
|
37126
|
+
}
|
|
36941
37127
|
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
36942
37128
|
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
36943
37129
|
* carrying a per-viewer `can_open` control hint. */
|
|
@@ -37046,6 +37232,50 @@ import { createRequire } from "node:module";
|
|
|
37046
37232
|
import * as path from "node:path";
|
|
37047
37233
|
import { fileURLToPath } from "node:url";
|
|
37048
37234
|
|
|
37235
|
+
// ts/daemon/dist/clip-runtime/browser-daemon-env.js
|
|
37236
|
+
var BROWSER_DAEMON_STRIPPED_ENV = [
|
|
37237
|
+
"PRLL_API_KEY",
|
|
37238
|
+
// machine key (mck_) — BYOC + agent control plane
|
|
37239
|
+
"PRLL_PROVIDER_CONFIG",
|
|
37240
|
+
// JSON ProviderConfig blob — may carry BYO LLM api keys
|
|
37241
|
+
"PRLL_ASSIGNMENT_TOKEN",
|
|
37242
|
+
// hosted pod platform assignment token (pba_)
|
|
37243
|
+
"PRLL_POOL_TOKEN",
|
|
37244
|
+
// hosted warm-pool bootstrap token (pba_)
|
|
37245
|
+
"AWS_ACCESS_KEY_ID",
|
|
37246
|
+
// hosted S3 browser-state STS creds (browser-pod.ts)
|
|
37247
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
37248
|
+
"AWS_SESSION_TOKEN",
|
|
37249
|
+
// AWS credential-RESOLUTION vars: the SDK derives creds from these too (IRSA
|
|
37250
|
+
// web-identity, ECS/EKS container creds, named profile, on-disk cred/config
|
|
37251
|
+
// files), so a child inheriting them could assume the pod's role even without
|
|
37252
|
+
// the static keys above. bb-browser uses none of them.
|
|
37253
|
+
"AWS_WEB_IDENTITY_TOKEN_FILE",
|
|
37254
|
+
"AWS_ROLE_ARN",
|
|
37255
|
+
"AWS_ROLE_SESSION_NAME",
|
|
37256
|
+
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
|
|
37257
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
37258
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN",
|
|
37259
|
+
"AWS_PROFILE",
|
|
37260
|
+
"AWS_SHARED_CREDENTIALS_FILE",
|
|
37261
|
+
"AWS_CONFIG_FILE",
|
|
37262
|
+
"AWS_REGION",
|
|
37263
|
+
// hosted browser-state config — bb-browser does not use it
|
|
37264
|
+
"PRLL_BROWSER_STATE_REGION",
|
|
37265
|
+
// browser-pod AWS_REGION fallback — same config family
|
|
37266
|
+
"PRLL_BROWSER_STATE_BUCKET",
|
|
37267
|
+
"PRLL_STATE_GENERATION",
|
|
37268
|
+
"PRLL_BROWSER_STATE_ENDPOINT"
|
|
37269
|
+
];
|
|
37270
|
+
function buildBrowserDaemonEnv(baseEnv, homeDir) {
|
|
37271
|
+
const env = { ...baseEnv, BB_BROWSER_HOME: homeDir };
|
|
37272
|
+
clearAllProviderCreds(env);
|
|
37273
|
+
for (const key of BROWSER_DAEMON_STRIPPED_ENV) {
|
|
37274
|
+
delete env[key];
|
|
37275
|
+
}
|
|
37276
|
+
return env;
|
|
37277
|
+
}
|
|
37278
|
+
|
|
37049
37279
|
// ts/daemon/dist/clip-runtime/browser-viewer-streamer.js
|
|
37050
37280
|
import { spawn } from "node:child_process";
|
|
37051
37281
|
|
|
@@ -37075,6 +37305,41 @@ async function findFreePort() {
|
|
|
37075
37305
|
function sleep(ms) {
|
|
37076
37306
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
37077
37307
|
}
|
|
37308
|
+
function waitForChildExit(child, log, graceMs = 5e3, hardCapMs = 15e3) {
|
|
37309
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
37310
|
+
return Promise.resolve();
|
|
37311
|
+
return new Promise((resolve2) => {
|
|
37312
|
+
let killTimer;
|
|
37313
|
+
let capTimer;
|
|
37314
|
+
const finish = () => {
|
|
37315
|
+
child.removeListener("exit", finish);
|
|
37316
|
+
if (killTimer)
|
|
37317
|
+
clearTimeout(killTimer);
|
|
37318
|
+
if (capTimer)
|
|
37319
|
+
clearTimeout(capTimer);
|
|
37320
|
+
resolve2();
|
|
37321
|
+
};
|
|
37322
|
+
child.once("exit", finish);
|
|
37323
|
+
try {
|
|
37324
|
+
child.kill("SIGTERM");
|
|
37325
|
+
} catch {
|
|
37326
|
+
}
|
|
37327
|
+
killTimer = setTimeout(() => {
|
|
37328
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
37329
|
+
try {
|
|
37330
|
+
child.kill("SIGKILL");
|
|
37331
|
+
} catch {
|
|
37332
|
+
}
|
|
37333
|
+
}
|
|
37334
|
+
}, graceMs);
|
|
37335
|
+
capTimer = setTimeout(() => {
|
|
37336
|
+
log?.warn(`child did not exit within ${hardCapMs}ms after SIGKILL; proceeding`);
|
|
37337
|
+
finish();
|
|
37338
|
+
}, hardCapMs);
|
|
37339
|
+
killTimer.unref?.();
|
|
37340
|
+
capTimer.unref?.();
|
|
37341
|
+
});
|
|
37342
|
+
}
|
|
37078
37343
|
|
|
37079
37344
|
// ts/daemon/dist/clip-runtime/browser-viewer-streamer.js
|
|
37080
37345
|
var BB_VIEWER_HEALTH_TIMEOUT_MS = 1e4;
|
|
@@ -37653,6 +37918,7 @@ function filterTabListToAccount(result, account) {
|
|
|
37653
37918
|
|
|
37654
37919
|
// ts/daemon/dist/clip-runtime/browser-profile-manager.js
|
|
37655
37920
|
var BB_BROWSER_DAEMON_START_TIMEOUT_MS = 15e3;
|
|
37921
|
+
var BB_BROWSER_DAEMON_START_ATTEMPTS = 3;
|
|
37656
37922
|
var BrowserCommandError = class extends Error {
|
|
37657
37923
|
method;
|
|
37658
37924
|
account;
|
|
@@ -37668,6 +37934,11 @@ var BrowserProfileManager = class {
|
|
|
37668
37934
|
daemon = null;
|
|
37669
37935
|
starting = null;
|
|
37670
37936
|
restarting = null;
|
|
37937
|
+
// Set by stop() and never reset (stop() is terminal — the pool disposes the
|
|
37938
|
+
// manager and the hosted pod exits). Makes a startDaemon() that resolves after
|
|
37939
|
+
// stop() began un-adoptable, so a late child can't be reassigned to this.daemon
|
|
37940
|
+
// and escape teardown.
|
|
37941
|
+
stopping = false;
|
|
37671
37942
|
ensuredAccounts = /* @__PURE__ */ new Set();
|
|
37672
37943
|
ensuringAccounts = /* @__PURE__ */ new Map();
|
|
37673
37944
|
reportedStatuses = /* @__PURE__ */ new Map();
|
|
@@ -37718,9 +37989,12 @@ var BrowserProfileManager = class {
|
|
|
37718
37989
|
throw err;
|
|
37719
37990
|
}
|
|
37720
37991
|
}
|
|
37721
|
-
async ensureRuntime(profileId) {
|
|
37992
|
+
async ensureRuntime(profileId, opts = {}) {
|
|
37722
37993
|
if (!profileId)
|
|
37723
37994
|
throw new Error("browser profile id is required");
|
|
37995
|
+
if (opts.forceStatusReport) {
|
|
37996
|
+
this.reportedStatuses.delete(profileId);
|
|
37997
|
+
}
|
|
37724
37998
|
try {
|
|
37725
37999
|
await this.withDaemonRecovery(() => this.ensureAccount(profileId), `ensure runtime for ${profileId}`);
|
|
37726
38000
|
this.reportStatus(profileId, "running");
|
|
@@ -37769,22 +38043,36 @@ var BrowserProfileManager = class {
|
|
|
37769
38043
|
}
|
|
37770
38044
|
}
|
|
37771
38045
|
async stop() {
|
|
38046
|
+
this.stopping = true;
|
|
37772
38047
|
this.viewer.shutdown();
|
|
38048
|
+
const inflight = this.starting;
|
|
38049
|
+
const restarting = this.restarting;
|
|
37773
38050
|
const daemon = this.daemon;
|
|
37774
38051
|
this.daemon = null;
|
|
37775
38052
|
this.starting = null;
|
|
37776
38053
|
this.ensuredAccounts.clear();
|
|
37777
38054
|
this.ensuringAccounts.clear();
|
|
37778
38055
|
this.reportedStatuses.clear();
|
|
37779
|
-
if (
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
|
|
38056
|
+
if (restarting) {
|
|
38057
|
+
try {
|
|
38058
|
+
await restarting;
|
|
38059
|
+
} catch {
|
|
38060
|
+
}
|
|
37784
38061
|
}
|
|
37785
|
-
|
|
37786
|
-
|
|
38062
|
+
let started = null;
|
|
38063
|
+
if (inflight) {
|
|
38064
|
+
try {
|
|
38065
|
+
started = await inflight;
|
|
38066
|
+
} catch {
|
|
38067
|
+
}
|
|
37787
38068
|
}
|
|
38069
|
+
await Promise.all([daemon, started].filter((d5) => d5 !== null).map(async (d5) => {
|
|
38070
|
+
try {
|
|
38071
|
+
await this.post("/shutdown", d5, void 0, 3e3);
|
|
38072
|
+
} catch {
|
|
38073
|
+
}
|
|
38074
|
+
await waitForChildExit(d5.child, this.opts.log);
|
|
38075
|
+
}));
|
|
37788
38076
|
}
|
|
37789
38077
|
/**
|
|
37790
38078
|
* Viewer control command entrypoint — delegates to BrowserViewerStreamer
|
|
@@ -38010,17 +38298,28 @@ var BrowserProfileManager = class {
|
|
|
38010
38298
|
async ensureDaemon() {
|
|
38011
38299
|
if (this.restarting)
|
|
38012
38300
|
await this.restarting;
|
|
38301
|
+
if (this.stopping)
|
|
38302
|
+
throw new Error("browser profile manager is stopping");
|
|
38013
38303
|
if (this.daemon && this.daemon.child.exitCode === null && this.daemon.child.signalCode === null) {
|
|
38014
38304
|
return this.daemon;
|
|
38015
38305
|
}
|
|
38016
|
-
if (this.starting)
|
|
38017
|
-
|
|
38306
|
+
if (this.starting) {
|
|
38307
|
+
const started = await this.starting;
|
|
38308
|
+
if (this.stopping)
|
|
38309
|
+
throw new Error("browser profile manager is stopping");
|
|
38310
|
+
return started;
|
|
38311
|
+
}
|
|
38018
38312
|
this.starting = this.startDaemon();
|
|
38313
|
+
const startPromise = this.starting;
|
|
38019
38314
|
try {
|
|
38020
|
-
|
|
38315
|
+
const started = await startPromise;
|
|
38316
|
+
if (this.stopping)
|
|
38317
|
+
throw new Error("browser profile manager is stopping");
|
|
38318
|
+
this.daemon = started;
|
|
38021
38319
|
return this.daemon;
|
|
38022
38320
|
} finally {
|
|
38023
|
-
this.starting
|
|
38321
|
+
if (this.starting === startPromise)
|
|
38322
|
+
this.starting = null;
|
|
38024
38323
|
}
|
|
38025
38324
|
}
|
|
38026
38325
|
async withDaemonRecovery(operation2, label) {
|
|
@@ -38056,20 +38355,46 @@ var BrowserProfileManager = class {
|
|
|
38056
38355
|
await this.post("/shutdown", daemon, void 0, 3e3);
|
|
38057
38356
|
} catch {
|
|
38058
38357
|
}
|
|
38059
|
-
|
|
38060
|
-
daemon.child.kill("SIGTERM");
|
|
38061
|
-
}
|
|
38358
|
+
await waitForChildExit(daemon.child, this.opts.log);
|
|
38062
38359
|
}
|
|
38063
38360
|
async startDaemon() {
|
|
38361
|
+
let lastErr;
|
|
38362
|
+
for (let attempt = 1; attempt <= BB_BROWSER_DAEMON_START_ATTEMPTS; attempt++) {
|
|
38363
|
+
try {
|
|
38364
|
+
return await this.startDaemonAttempt();
|
|
38365
|
+
} catch (err) {
|
|
38366
|
+
lastErr = err;
|
|
38367
|
+
if (attempt < BB_BROWSER_DAEMON_START_ATTEMPTS) {
|
|
38368
|
+
this.opts.log.warn(`[bb-browser] daemon start attempt ${attempt} failed; retrying with fresh ports: ${String(err)}`);
|
|
38369
|
+
}
|
|
38370
|
+
}
|
|
38371
|
+
}
|
|
38372
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
38373
|
+
}
|
|
38374
|
+
async startDaemonAttempt() {
|
|
38064
38375
|
const host = "127.0.0.1";
|
|
38065
38376
|
const port = await findFreePort();
|
|
38377
|
+
let cdpPort = await findFreePort();
|
|
38378
|
+
for (let i5 = 0; cdpPort === port && i5 < 5; i5++) {
|
|
38379
|
+
cdpPort = await findFreePort();
|
|
38380
|
+
}
|
|
38381
|
+
if (cdpPort === port) {
|
|
38382
|
+
throw new Error("bb-browser: could not allocate distinct HTTP and CDP ports");
|
|
38383
|
+
}
|
|
38066
38384
|
const token = randomToken();
|
|
38067
38385
|
const daemonPath = resolveBbBrowserDaemonPath();
|
|
38068
|
-
const child = spawn2(process.execPath, [
|
|
38069
|
-
|
|
38070
|
-
|
|
38071
|
-
|
|
38072
|
-
|
|
38386
|
+
const child = spawn2(process.execPath, [
|
|
38387
|
+
daemonPath,
|
|
38388
|
+
"--host",
|
|
38389
|
+
host,
|
|
38390
|
+
"--port",
|
|
38391
|
+
String(port),
|
|
38392
|
+
"--token",
|
|
38393
|
+
token,
|
|
38394
|
+
"--cdp-port",
|
|
38395
|
+
String(cdpPort)
|
|
38396
|
+
], {
|
|
38397
|
+
env: buildBrowserDaemonEnv(process.env, this.opts.homeDir),
|
|
38073
38398
|
stdio: ["ignore", "ignore", "pipe"]
|
|
38074
38399
|
});
|
|
38075
38400
|
let childError = null;
|
|
@@ -38098,7 +38423,7 @@ var BrowserProfileManager = class {
|
|
|
38098
38423
|
await sleep(200);
|
|
38099
38424
|
}
|
|
38100
38425
|
}
|
|
38101
|
-
child.
|
|
38426
|
+
await waitForChildExit(child, this.opts.log);
|
|
38102
38427
|
throw new Error("bb-browser-daemon did not start in time");
|
|
38103
38428
|
}
|
|
38104
38429
|
async post(pathName, daemon, body, timeoutMs = 1e4) {
|