@parall/daemon 1.36.1 → 1.37.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 +307 -27
- package/bundle/parall-claude-agent.js +363 -50
- package/bundle/parall-codex-agent.js +362 -48
- package/bundle/parall-daemon.js +33473 -31706
- 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.37.0",
|
|
3
|
+
"built_at": "2026-07-05T18:08:07.005Z",
|
|
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": "2c6b8429e4c071ca05115399012eedaf23da69962cd693fd05a65fde959f0e0c",
|
|
20
|
+
"size": 1694822
|
|
21
21
|
},
|
|
22
22
|
"parall-claude-agent.js": {
|
|
23
|
-
"sha256": "
|
|
24
|
-
"size":
|
|
23
|
+
"sha256": "4e48c965fa659f8a6780229f17dfdfecb612378dfe207f0c68a50060c5d57976",
|
|
24
|
+
"size": 1591442
|
|
25
25
|
},
|
|
26
26
|
"parall-codex-agent.js": {
|
|
27
|
-
"sha256": "
|
|
28
|
-
"size":
|
|
27
|
+
"sha256": "2da2dfdb17ceee2ac3e7da7ffd61bd2e9f3c437142378560c03108f87d681ee6",
|
|
28
|
+
"size": 1622518
|
|
29
29
|
},
|
|
30
30
|
"parall-daemon.js": {
|
|
31
|
-
"sha256": "
|
|
32
|
-
"size":
|
|
31
|
+
"sha256": "fe5a959f1b828721f6c5e667fbf0154b10e0c51c291658538e5d91263cf95dce",
|
|
32
|
+
"size": 1714111
|
|
33
33
|
},
|
|
34
34
|
"parall-openclaw-agent.js": {
|
|
35
35
|
"sha256": "505433b4bf3a4b8dbb7b96978d8693d6c48079f4513282ff1ee59a6d13b3eddf",
|
|
36
36
|
"size": 9801
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
|
-
"signature": "
|
|
39
|
+
"signature": "Wgi0cpQWhO2PzfVA73VYOkOCWc6NJJKLiC780OhOA4ttfY+qVXq3KWgZjU2v3GfVbV3Ukh2X0q1WnlshNyJVDQ=="
|
|
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`,
|
|
@@ -35364,6 +35385,14 @@ var ENDPOINTS = {
|
|
|
35364
35385
|
BILLING_AUTO_RELOAD: (orgId) => `${API_BASE}/orgs/${orgId}/billing/auto-reload`,
|
|
35365
35386
|
BILLING_SETUP_INTENT: (orgId) => `${API_BASE}/orgs/${orgId}/billing/setup-intent`,
|
|
35366
35387
|
COMPUTE_PRICING: () => `${API_BASE}/billing/compute-pricing`,
|
|
35388
|
+
// Runtime capability table (public, no auth) — SSOT for the create/settings
|
|
35389
|
+
// interlock: per-runtime compute modes, native model family, cross-family
|
|
35390
|
+
// availability, and recommended model.
|
|
35391
|
+
RUNTIMES: () => `${API_BASE}/runtimes`,
|
|
35392
|
+
// Model catalog (public, no auth) — served from the server's DB-backed
|
|
35393
|
+
// snapshot. Optional include_model keeps an agent's pinned hidden legacy
|
|
35394
|
+
// model representable in settings pickers.
|
|
35395
|
+
MODELS: (includeModel) => includeModel ? `${API_BASE}/models?include_model=${encodeURIComponent(includeModel)}` : `${API_BASE}/models`,
|
|
35367
35396
|
// ADMIN_GRANTS intentionally NOT exported here — it sits under the
|
|
35368
35397
|
// unauthenticated `/internal/admin/*` surface and must not bleed into the
|
|
35369
35398
|
// public SDK. Admin dashboard hits the URL directly from its own client.
|
|
@@ -35376,6 +35405,7 @@ var ENDPOINTS = {
|
|
|
35376
35405
|
AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
|
|
35377
35406
|
CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
|
|
35378
35407
|
CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
|
|
35408
|
+
BROWSER_RUNTIME_STATUS: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-runtime/status`,
|
|
35379
35409
|
BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
|
|
35380
35410
|
BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
|
|
35381
35411
|
BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
|
|
@@ -35720,6 +35750,13 @@ var ParallClient = class _ParallClient {
|
|
|
35720
35750
|
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS(orgId));
|
|
35721
35751
|
return res.data;
|
|
35722
35752
|
}
|
|
35753
|
+
/** User IDs of soft-removed (former) org members — for marking their avatar /
|
|
35754
|
+
* name as "left" where dormant relations still surface them (DMs, task
|
|
35755
|
+
* assignees, message history). */
|
|
35756
|
+
async getFormerMemberIds(orgId) {
|
|
35757
|
+
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_FORMER(orgId));
|
|
35758
|
+
return res.user_ids ?? [];
|
|
35759
|
+
}
|
|
35723
35760
|
async getTeams(orgId) {
|
|
35724
35761
|
const res = await this.request("GET", ENDPOINTS.TEAMS(orgId));
|
|
35725
35762
|
return res.data;
|
|
@@ -36208,20 +36245,25 @@ var ParallClient = class _ParallClient {
|
|
|
36208
36245
|
return res.data;
|
|
36209
36246
|
}
|
|
36210
36247
|
/** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
|
|
36211
|
-
async reportBrowserProfileStatus(profileId, status, errorMsg) {
|
|
36248
|
+
async reportBrowserProfileStatus(profileId, status, errorMsg, generation) {
|
|
36212
36249
|
await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
|
|
36213
36250
|
status,
|
|
36214
|
-
...errorMsg ? { error_msg: errorMsg } : {}
|
|
36251
|
+
...errorMsg ? { error_msg: errorMsg } : {},
|
|
36252
|
+
...generation !== void 0 ? { generation } : {}
|
|
36215
36253
|
});
|
|
36216
36254
|
}
|
|
36217
36255
|
/**
|
|
36218
36256
|
* `POST /machines/me/health` — bump the Machine's `updated_at` to now and
|
|
36219
|
-
* report daemon state. The daemon
|
|
36220
|
-
*
|
|
36257
|
+
* report daemon state. The daemon calls this on startup and again whenever
|
|
36258
|
+
* periodic runtime re-detection produces a CHANGED result (there is no
|
|
36259
|
+
* fixed-cadence keepalive loop today — steady state posts nothing). All
|
|
36221
36260
|
* fields are optional and only persisted when changed:
|
|
36222
36261
|
* - `daemonVersion` — the running bundle/launcher version.
|
|
36223
36262
|
* - `selfUpdateCapable` — whether the daemon can act on a machine.update
|
|
36224
36263
|
* signal (true under a service manager, false for bare `npx` foreground).
|
|
36264
|
+
* - `detectedRuntimes` — runtime CLIs found on the host. Omitted = no
|
|
36265
|
+
* report this beat (server keeps the stored value); [] = detection ran
|
|
36266
|
+
* and found nothing (server clears to empty).
|
|
36225
36267
|
*/
|
|
36226
36268
|
async postMachineHeartbeat(opts) {
|
|
36227
36269
|
const body = {};
|
|
@@ -36229,6 +36271,8 @@ var ParallClient = class _ParallClient {
|
|
|
36229
36271
|
body.daemon_version = opts.daemonVersion;
|
|
36230
36272
|
if (opts?.selfUpdateCapable !== void 0)
|
|
36231
36273
|
body.self_update_capable = opts.selfUpdateCapable;
|
|
36274
|
+
if (opts?.detectedRuntimes !== void 0)
|
|
36275
|
+
body.detected_runtimes = opts.detectedRuntimes;
|
|
36232
36276
|
return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
|
|
36233
36277
|
}
|
|
36234
36278
|
async reportAgentWorkspaceState(agentId, state2) {
|
|
@@ -36547,6 +36591,59 @@ var ParallClient = class _ParallClient {
|
|
|
36547
36591
|
async deleteExternalConnection(orgId, connectionId) {
|
|
36548
36592
|
return this.request("DELETE", ENDPOINTS.EXTERNAL_CONNECTION(orgId, connectionId));
|
|
36549
36593
|
}
|
|
36594
|
+
// ---- External IM channel (org-scoped) ----
|
|
36595
|
+
async createChannelConnection(orgId, input) {
|
|
36596
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTIONS(orgId), input);
|
|
36597
|
+
}
|
|
36598
|
+
async listChannelConnections(orgId) {
|
|
36599
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTIONS(orgId));
|
|
36600
|
+
}
|
|
36601
|
+
async getChannelConnection(orgId, connectionId) {
|
|
36602
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
36603
|
+
}
|
|
36604
|
+
async updateChannelConnection(orgId, connectionId, patch) {
|
|
36605
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId), patch);
|
|
36606
|
+
}
|
|
36607
|
+
async archiveChannelConnection(orgId, connectionId) {
|
|
36608
|
+
return this.request("DELETE", ENDPOINTS.CHANNEL_CONNECTION(orgId, connectionId));
|
|
36609
|
+
}
|
|
36610
|
+
async deliverChannelCredentials(orgId, connectionId, credentials) {
|
|
36611
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_CREDENTIALS(orgId, connectionId), credentials);
|
|
36612
|
+
}
|
|
36613
|
+
async regenerateChannelIngressToken(orgId, connectionId) {
|
|
36614
|
+
return this.request("POST", ENDPOINTS.CHANNEL_CONNECTION_INGRESS_TOKEN_REGENERATE(orgId, connectionId));
|
|
36615
|
+
}
|
|
36616
|
+
/** Start a Feishu one-click provisioning session (device flow QR). */
|
|
36617
|
+
async initiateChannelProvisioning(orgId, input) {
|
|
36618
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
|
|
36619
|
+
}
|
|
36620
|
+
/**
|
|
36621
|
+
* Lazy status poll — server-side this may forward one provider poll, so
|
|
36622
|
+
* call it at the session's `poll_interval_seconds` cadence, not faster.
|
|
36623
|
+
*/
|
|
36624
|
+
async getChannelProvisioningSession(orgId, sessionId) {
|
|
36625
|
+
return this.request("GET", ENDPOINTS.CHANNEL_PROVISIONING_SESSION(orgId, sessionId));
|
|
36626
|
+
}
|
|
36627
|
+
async cancelChannelProvisioning(orgId, sessionId) {
|
|
36628
|
+
return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING_CANCEL(orgId, sessionId));
|
|
36629
|
+
}
|
|
36630
|
+
async listChannelConversations(orgId, connectionId) {
|
|
36631
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
|
|
36632
|
+
}
|
|
36633
|
+
async getChannelConversation(orgId, conversationId) {
|
|
36634
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION(orgId, conversationId));
|
|
36635
|
+
}
|
|
36636
|
+
async listChannelConversationMessages(orgId, conversationId, limit) {
|
|
36637
|
+
return this.request("GET", ENDPOINTS.CHANNEL_CONVERSATION_MESSAGES(orgId, conversationId), void 0, { limit });
|
|
36638
|
+
}
|
|
36639
|
+
async setChannelConversationSession(orgId, conversationId, agentSessionId) {
|
|
36640
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONVERSATION_SESSION(orgId, conversationId), {
|
|
36641
|
+
agent_session_id: agentSessionId
|
|
36642
|
+
});
|
|
36643
|
+
}
|
|
36644
|
+
async getChannelMessage(orgId, messageId) {
|
|
36645
|
+
return this.request("GET", ENDPOINTS.CHANNEL_MESSAGE(orgId, messageId));
|
|
36646
|
+
}
|
|
36550
36647
|
async getExternalTriggerSchema(orgId, connectionId) {
|
|
36551
36648
|
return this.request("GET", ENDPOINTS.EXTERNAL_TRIGGER_SCHEMA(orgId, connectionId));
|
|
36552
36649
|
}
|
|
@@ -36588,6 +36685,23 @@ var ParallClient = class _ParallClient {
|
|
|
36588
36685
|
async getWiki(orgId, wikiId) {
|
|
36589
36686
|
return this.request("GET", ENDPOINTS.WIKI(orgId, wikiId));
|
|
36590
36687
|
}
|
|
36688
|
+
/** Soft-delete an entire wiki (org owner only; the default wiki is
|
|
36689
|
+
* protected → 403 WIKI_PROTECTED). Returns the deleted wiki. Recoverable
|
|
36690
|
+
* via restoreWiki within the retention window. */
|
|
36691
|
+
async deleteWiki(orgId, wikiId) {
|
|
36692
|
+
return this.request("DELETE", ENDPOINTS.WIKI(orgId, wikiId));
|
|
36693
|
+
}
|
|
36694
|
+
/** Restore a soft-deleted wiki (org owner only). 409 WIKI_PURGE_STARTED once
|
|
36695
|
+
* purge has been claimed (no longer restorable), or 404 once the row is gone.
|
|
36696
|
+
* Returns the restored wiki. */
|
|
36697
|
+
async restoreWiki(orgId, wikiId) {
|
|
36698
|
+
return this.request("POST", ENDPOINTS.WIKI_RESTORE(orgId, wikiId));
|
|
36699
|
+
}
|
|
36700
|
+
/** Recycle bin — list soft-deleted wikis for the org (owner only). */
|
|
36701
|
+
async getDeletedWikis(orgId) {
|
|
36702
|
+
const res = await this.request("GET", ENDPOINTS.WIKIS_DELETED(orgId));
|
|
36703
|
+
return res.data;
|
|
36704
|
+
}
|
|
36591
36705
|
async getWikiTree(orgId, wikiId, params) {
|
|
36592
36706
|
return this.request("GET", ENDPOINTS.WIKI_TREE(orgId, wikiId), void 0, params);
|
|
36593
36707
|
}
|
|
@@ -36621,6 +36735,15 @@ var ParallClient = class _ParallClient {
|
|
|
36621
36735
|
blob.signed_url = this.absoluteMediaUrl(blob.signed_url);
|
|
36622
36736
|
return blob;
|
|
36623
36737
|
}
|
|
36738
|
+
/**
|
|
36739
|
+
* Copy one wiki file to another path as an independent snapshot (no sync).
|
|
36740
|
+
* Used to "share a private file out": copy a file from the caller's personal
|
|
36741
|
+
* namespace (`users/{userId}/…`) into the public wiki, leaving the original
|
|
36742
|
+
* untouched. 409 `FILE_EXISTS` if `dest_path` already exists.
|
|
36743
|
+
*/
|
|
36744
|
+
async copyWikiFile(orgId, wikiId, req) {
|
|
36745
|
+
return this.request("POST", ENDPOINTS.WIKI_COPY(orgId, wikiId), req);
|
|
36746
|
+
}
|
|
36624
36747
|
async getWikiNodeSections(orgId, wikiId, params) {
|
|
36625
36748
|
return this.request("GET", ENDPOINTS.WIKI_NODE_SECTIONS(orgId, wikiId), void 0, params);
|
|
36626
36749
|
}
|
|
@@ -36894,6 +37017,19 @@ var ParallClient = class _ParallClient {
|
|
|
36894
37017
|
const resp = await this.request("GET", ENDPOINTS.COMPUTE_PRICING());
|
|
36895
37018
|
return resp.data;
|
|
36896
37019
|
}
|
|
37020
|
+
/** Runtime capability table (public) — SSOT for the create/settings interlock. */
|
|
37021
|
+
async getRuntimes() {
|
|
37022
|
+
const resp = await this.request("GET", ENDPOINTS.RUNTIMES());
|
|
37023
|
+
return resp.data;
|
|
37024
|
+
}
|
|
37025
|
+
/**
|
|
37026
|
+
* Platform model catalog (public) — DB-backed, replaces the compile-time
|
|
37027
|
+
* PLATFORM_MODELS constant. Pass includeModel to keep an agent's pinned
|
|
37028
|
+
* hidden legacy model representable (settings picker).
|
|
37029
|
+
*/
|
|
37030
|
+
async getModels(includeModel) {
|
|
37031
|
+
return this.request("GET", ENDPOINTS.MODELS(includeModel));
|
|
37032
|
+
}
|
|
36897
37033
|
// ---- Clips ----
|
|
36898
37034
|
async listClips(orgId) {
|
|
36899
37035
|
const resp = await this.request("GET", ENDPOINTS.CLIPS(orgId));
|
|
@@ -36938,6 +37074,11 @@ var ParallClient = class _ParallClient {
|
|
|
36938
37074
|
const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
|
|
36939
37075
|
return resp.data;
|
|
36940
37076
|
}
|
|
37077
|
+
/** Deployment-wide hosted browser runtime availability — drives whether the
|
|
37078
|
+
* create UI offers the platform-hosted placement. Fail-closed server-side. */
|
|
37079
|
+
async getBrowserRuntimeStatus(orgId) {
|
|
37080
|
+
return this.request("GET", ENDPOINTS.BROWSER_RUNTIME_STATUS(orgId));
|
|
37081
|
+
}
|
|
36941
37082
|
/** Org-wide browser-profile discovery list. Returns the sanitized
|
|
36942
37083
|
* {@link BrowserProfileListItem} shape (not the full domain model), each row
|
|
36943
37084
|
* carrying a per-viewer `can_open` control hint. */
|
|
@@ -37046,6 +37187,50 @@ import { createRequire } from "node:module";
|
|
|
37046
37187
|
import * as path from "node:path";
|
|
37047
37188
|
import { fileURLToPath } from "node:url";
|
|
37048
37189
|
|
|
37190
|
+
// ts/daemon/dist/clip-runtime/browser-daemon-env.js
|
|
37191
|
+
var BROWSER_DAEMON_STRIPPED_ENV = [
|
|
37192
|
+
"PRLL_API_KEY",
|
|
37193
|
+
// machine key (mck_) — BYOC + agent control plane
|
|
37194
|
+
"PRLL_PROVIDER_CONFIG",
|
|
37195
|
+
// JSON ProviderConfig blob — may carry BYO LLM api keys
|
|
37196
|
+
"PRLL_ASSIGNMENT_TOKEN",
|
|
37197
|
+
// hosted pod platform assignment token (pba_)
|
|
37198
|
+
"PRLL_POOL_TOKEN",
|
|
37199
|
+
// hosted warm-pool bootstrap token (pba_)
|
|
37200
|
+
"AWS_ACCESS_KEY_ID",
|
|
37201
|
+
// hosted S3 browser-state STS creds (browser-pod.ts)
|
|
37202
|
+
"AWS_SECRET_ACCESS_KEY",
|
|
37203
|
+
"AWS_SESSION_TOKEN",
|
|
37204
|
+
// AWS credential-RESOLUTION vars: the SDK derives creds from these too (IRSA
|
|
37205
|
+
// web-identity, ECS/EKS container creds, named profile, on-disk cred/config
|
|
37206
|
+
// files), so a child inheriting them could assume the pod's role even without
|
|
37207
|
+
// the static keys above. bb-browser uses none of them.
|
|
37208
|
+
"AWS_WEB_IDENTITY_TOKEN_FILE",
|
|
37209
|
+
"AWS_ROLE_ARN",
|
|
37210
|
+
"AWS_ROLE_SESSION_NAME",
|
|
37211
|
+
"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI",
|
|
37212
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
37213
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN",
|
|
37214
|
+
"AWS_PROFILE",
|
|
37215
|
+
"AWS_SHARED_CREDENTIALS_FILE",
|
|
37216
|
+
"AWS_CONFIG_FILE",
|
|
37217
|
+
"AWS_REGION",
|
|
37218
|
+
// hosted browser-state config — bb-browser does not use it
|
|
37219
|
+
"PRLL_BROWSER_STATE_REGION",
|
|
37220
|
+
// browser-pod AWS_REGION fallback — same config family
|
|
37221
|
+
"PRLL_BROWSER_STATE_BUCKET",
|
|
37222
|
+
"PRLL_STATE_GENERATION",
|
|
37223
|
+
"PRLL_BROWSER_STATE_ENDPOINT"
|
|
37224
|
+
];
|
|
37225
|
+
function buildBrowserDaemonEnv(baseEnv, homeDir) {
|
|
37226
|
+
const env = { ...baseEnv, BB_BROWSER_HOME: homeDir };
|
|
37227
|
+
clearAllProviderCreds(env);
|
|
37228
|
+
for (const key of BROWSER_DAEMON_STRIPPED_ENV) {
|
|
37229
|
+
delete env[key];
|
|
37230
|
+
}
|
|
37231
|
+
return env;
|
|
37232
|
+
}
|
|
37233
|
+
|
|
37049
37234
|
// ts/daemon/dist/clip-runtime/browser-viewer-streamer.js
|
|
37050
37235
|
import { spawn } from "node:child_process";
|
|
37051
37236
|
|
|
@@ -37075,6 +37260,41 @@ async function findFreePort() {
|
|
|
37075
37260
|
function sleep(ms) {
|
|
37076
37261
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
37077
37262
|
}
|
|
37263
|
+
function waitForChildExit(child, log, graceMs = 5e3, hardCapMs = 15e3) {
|
|
37264
|
+
if (child.exitCode !== null || child.signalCode !== null)
|
|
37265
|
+
return Promise.resolve();
|
|
37266
|
+
return new Promise((resolve2) => {
|
|
37267
|
+
let killTimer;
|
|
37268
|
+
let capTimer;
|
|
37269
|
+
const finish = () => {
|
|
37270
|
+
child.removeListener("exit", finish);
|
|
37271
|
+
if (killTimer)
|
|
37272
|
+
clearTimeout(killTimer);
|
|
37273
|
+
if (capTimer)
|
|
37274
|
+
clearTimeout(capTimer);
|
|
37275
|
+
resolve2();
|
|
37276
|
+
};
|
|
37277
|
+
child.once("exit", finish);
|
|
37278
|
+
try {
|
|
37279
|
+
child.kill("SIGTERM");
|
|
37280
|
+
} catch {
|
|
37281
|
+
}
|
|
37282
|
+
killTimer = setTimeout(() => {
|
|
37283
|
+
if (child.exitCode === null && child.signalCode === null) {
|
|
37284
|
+
try {
|
|
37285
|
+
child.kill("SIGKILL");
|
|
37286
|
+
} catch {
|
|
37287
|
+
}
|
|
37288
|
+
}
|
|
37289
|
+
}, graceMs);
|
|
37290
|
+
capTimer = setTimeout(() => {
|
|
37291
|
+
log?.warn(`child did not exit within ${hardCapMs}ms after SIGKILL; proceeding`);
|
|
37292
|
+
finish();
|
|
37293
|
+
}, hardCapMs);
|
|
37294
|
+
killTimer.unref?.();
|
|
37295
|
+
capTimer.unref?.();
|
|
37296
|
+
});
|
|
37297
|
+
}
|
|
37078
37298
|
|
|
37079
37299
|
// ts/daemon/dist/clip-runtime/browser-viewer-streamer.js
|
|
37080
37300
|
var BB_VIEWER_HEALTH_TIMEOUT_MS = 1e4;
|
|
@@ -37653,6 +37873,7 @@ function filterTabListToAccount(result, account) {
|
|
|
37653
37873
|
|
|
37654
37874
|
// ts/daemon/dist/clip-runtime/browser-profile-manager.js
|
|
37655
37875
|
var BB_BROWSER_DAEMON_START_TIMEOUT_MS = 15e3;
|
|
37876
|
+
var BB_BROWSER_DAEMON_START_ATTEMPTS = 3;
|
|
37656
37877
|
var BrowserCommandError = class extends Error {
|
|
37657
37878
|
method;
|
|
37658
37879
|
account;
|
|
@@ -37668,6 +37889,11 @@ var BrowserProfileManager = class {
|
|
|
37668
37889
|
daemon = null;
|
|
37669
37890
|
starting = null;
|
|
37670
37891
|
restarting = null;
|
|
37892
|
+
// Set by stop() and never reset (stop() is terminal — the pool disposes the
|
|
37893
|
+
// manager and the hosted pod exits). Makes a startDaemon() that resolves after
|
|
37894
|
+
// stop() began un-adoptable, so a late child can't be reassigned to this.daemon
|
|
37895
|
+
// and escape teardown.
|
|
37896
|
+
stopping = false;
|
|
37671
37897
|
ensuredAccounts = /* @__PURE__ */ new Set();
|
|
37672
37898
|
ensuringAccounts = /* @__PURE__ */ new Map();
|
|
37673
37899
|
reportedStatuses = /* @__PURE__ */ new Map();
|
|
@@ -37718,9 +37944,12 @@ var BrowserProfileManager = class {
|
|
|
37718
37944
|
throw err;
|
|
37719
37945
|
}
|
|
37720
37946
|
}
|
|
37721
|
-
async ensureRuntime(profileId) {
|
|
37947
|
+
async ensureRuntime(profileId, opts = {}) {
|
|
37722
37948
|
if (!profileId)
|
|
37723
37949
|
throw new Error("browser profile id is required");
|
|
37950
|
+
if (opts.forceStatusReport) {
|
|
37951
|
+
this.reportedStatuses.delete(profileId);
|
|
37952
|
+
}
|
|
37724
37953
|
try {
|
|
37725
37954
|
await this.withDaemonRecovery(() => this.ensureAccount(profileId), `ensure runtime for ${profileId}`);
|
|
37726
37955
|
this.reportStatus(profileId, "running");
|
|
@@ -37769,22 +37998,36 @@ var BrowserProfileManager = class {
|
|
|
37769
37998
|
}
|
|
37770
37999
|
}
|
|
37771
38000
|
async stop() {
|
|
38001
|
+
this.stopping = true;
|
|
37772
38002
|
this.viewer.shutdown();
|
|
38003
|
+
const inflight = this.starting;
|
|
38004
|
+
const restarting = this.restarting;
|
|
37773
38005
|
const daemon = this.daemon;
|
|
37774
38006
|
this.daemon = null;
|
|
37775
38007
|
this.starting = null;
|
|
37776
38008
|
this.ensuredAccounts.clear();
|
|
37777
38009
|
this.ensuringAccounts.clear();
|
|
37778
38010
|
this.reportedStatuses.clear();
|
|
37779
|
-
if (
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
|
|
38011
|
+
if (restarting) {
|
|
38012
|
+
try {
|
|
38013
|
+
await restarting;
|
|
38014
|
+
} catch {
|
|
38015
|
+
}
|
|
37784
38016
|
}
|
|
37785
|
-
|
|
37786
|
-
|
|
38017
|
+
let started = null;
|
|
38018
|
+
if (inflight) {
|
|
38019
|
+
try {
|
|
38020
|
+
started = await inflight;
|
|
38021
|
+
} catch {
|
|
38022
|
+
}
|
|
37787
38023
|
}
|
|
38024
|
+
await Promise.all([daemon, started].filter((d5) => d5 !== null).map(async (d5) => {
|
|
38025
|
+
try {
|
|
38026
|
+
await this.post("/shutdown", d5, void 0, 3e3);
|
|
38027
|
+
} catch {
|
|
38028
|
+
}
|
|
38029
|
+
await waitForChildExit(d5.child, this.opts.log);
|
|
38030
|
+
}));
|
|
37788
38031
|
}
|
|
37789
38032
|
/**
|
|
37790
38033
|
* Viewer control command entrypoint — delegates to BrowserViewerStreamer
|
|
@@ -38010,17 +38253,28 @@ var BrowserProfileManager = class {
|
|
|
38010
38253
|
async ensureDaemon() {
|
|
38011
38254
|
if (this.restarting)
|
|
38012
38255
|
await this.restarting;
|
|
38256
|
+
if (this.stopping)
|
|
38257
|
+
throw new Error("browser profile manager is stopping");
|
|
38013
38258
|
if (this.daemon && this.daemon.child.exitCode === null && this.daemon.child.signalCode === null) {
|
|
38014
38259
|
return this.daemon;
|
|
38015
38260
|
}
|
|
38016
|
-
if (this.starting)
|
|
38017
|
-
|
|
38261
|
+
if (this.starting) {
|
|
38262
|
+
const started = await this.starting;
|
|
38263
|
+
if (this.stopping)
|
|
38264
|
+
throw new Error("browser profile manager is stopping");
|
|
38265
|
+
return started;
|
|
38266
|
+
}
|
|
38018
38267
|
this.starting = this.startDaemon();
|
|
38268
|
+
const startPromise = this.starting;
|
|
38019
38269
|
try {
|
|
38020
|
-
|
|
38270
|
+
const started = await startPromise;
|
|
38271
|
+
if (this.stopping)
|
|
38272
|
+
throw new Error("browser profile manager is stopping");
|
|
38273
|
+
this.daemon = started;
|
|
38021
38274
|
return this.daemon;
|
|
38022
38275
|
} finally {
|
|
38023
|
-
this.starting
|
|
38276
|
+
if (this.starting === startPromise)
|
|
38277
|
+
this.starting = null;
|
|
38024
38278
|
}
|
|
38025
38279
|
}
|
|
38026
38280
|
async withDaemonRecovery(operation2, label) {
|
|
@@ -38056,20 +38310,46 @@ var BrowserProfileManager = class {
|
|
|
38056
38310
|
await this.post("/shutdown", daemon, void 0, 3e3);
|
|
38057
38311
|
} catch {
|
|
38058
38312
|
}
|
|
38059
|
-
|
|
38060
|
-
daemon.child.kill("SIGTERM");
|
|
38061
|
-
}
|
|
38313
|
+
await waitForChildExit(daemon.child, this.opts.log);
|
|
38062
38314
|
}
|
|
38063
38315
|
async startDaemon() {
|
|
38316
|
+
let lastErr;
|
|
38317
|
+
for (let attempt = 1; attempt <= BB_BROWSER_DAEMON_START_ATTEMPTS; attempt++) {
|
|
38318
|
+
try {
|
|
38319
|
+
return await this.startDaemonAttempt();
|
|
38320
|
+
} catch (err) {
|
|
38321
|
+
lastErr = err;
|
|
38322
|
+
if (attempt < BB_BROWSER_DAEMON_START_ATTEMPTS) {
|
|
38323
|
+
this.opts.log.warn(`[bb-browser] daemon start attempt ${attempt} failed; retrying with fresh ports: ${String(err)}`);
|
|
38324
|
+
}
|
|
38325
|
+
}
|
|
38326
|
+
}
|
|
38327
|
+
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
|
|
38328
|
+
}
|
|
38329
|
+
async startDaemonAttempt() {
|
|
38064
38330
|
const host = "127.0.0.1";
|
|
38065
38331
|
const port = await findFreePort();
|
|
38332
|
+
let cdpPort = await findFreePort();
|
|
38333
|
+
for (let i5 = 0; cdpPort === port && i5 < 5; i5++) {
|
|
38334
|
+
cdpPort = await findFreePort();
|
|
38335
|
+
}
|
|
38336
|
+
if (cdpPort === port) {
|
|
38337
|
+
throw new Error("bb-browser: could not allocate distinct HTTP and CDP ports");
|
|
38338
|
+
}
|
|
38066
38339
|
const token = randomToken();
|
|
38067
38340
|
const daemonPath = resolveBbBrowserDaemonPath();
|
|
38068
|
-
const child = spawn2(process.execPath, [
|
|
38069
|
-
|
|
38070
|
-
|
|
38071
|
-
|
|
38072
|
-
|
|
38341
|
+
const child = spawn2(process.execPath, [
|
|
38342
|
+
daemonPath,
|
|
38343
|
+
"--host",
|
|
38344
|
+
host,
|
|
38345
|
+
"--port",
|
|
38346
|
+
String(port),
|
|
38347
|
+
"--token",
|
|
38348
|
+
token,
|
|
38349
|
+
"--cdp-port",
|
|
38350
|
+
String(cdpPort)
|
|
38351
|
+
], {
|
|
38352
|
+
env: buildBrowserDaemonEnv(process.env, this.opts.homeDir),
|
|
38073
38353
|
stdio: ["ignore", "ignore", "pipe"]
|
|
38074
38354
|
});
|
|
38075
38355
|
let childError = null;
|
|
@@ -38098,7 +38378,7 @@ var BrowserProfileManager = class {
|
|
|
38098
38378
|
await sleep(200);
|
|
38099
38379
|
}
|
|
38100
38380
|
}
|
|
38101
|
-
child.
|
|
38381
|
+
await waitForChildExit(child, this.opts.log);
|
|
38102
38382
|
throw new Error("bb-browser-daemon did not start in time");
|
|
38103
38383
|
}
|
|
38104
38384
|
async post(pathName, daemon, body, timeoutMs = 1e4) {
|