@parall/daemon 1.47.0 → 1.49.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.
@@ -191,6 +191,8 @@ var init_constants = __esm({
191
191
  MESSAGE_WATCH: (id) => `${API_BASE}/messages/${id}/watch`,
192
192
  MESSAGE_WATCHERS: (id) => `${API_BASE}/messages/${id}/watchers`,
193
193
  MESSAGE_WATCHING: (id) => `${API_BASE}/messages/${id}/watching`,
194
+ MESSAGE_REACTIONS: (id) => `${API_BASE}/messages/${id}/reactions`,
195
+ MESSAGE_REACTION: (id, emoji) => `${API_BASE}/messages/${id}/reactions/${encodeURIComponent(emoji)}`,
194
196
  // Upload (org-scoped)
195
197
  UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
196
198
  UPLOAD_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/upload/complete`,
@@ -428,11 +430,13 @@ var init_constants = __esm({
428
430
  UNREAD: `${API_BASE}/me/unread`,
429
431
  ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
430
432
  CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
433
+ CHAT_READ_ALL: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read-all`,
431
434
  THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
432
435
  THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
433
436
  // References (org-scoped)
434
437
  REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
435
438
  REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
439
+ REFS_OUTBOUND: (orgId) => `${API_BASE}/orgs/${orgId}/refs/outbound`,
436
440
  REFS_GRAPH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/graph`,
437
441
  REFS_CHECK: (orgId) => `${API_BASE}/orgs/${orgId}/refs/check`,
438
442
  // Platform config (agent-scoped, not org-scoped)
@@ -491,10 +495,23 @@ var init_constants = __esm({
491
495
  ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
492
496
  ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
493
497
  ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
498
+ ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
494
499
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
495
500
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
501
+ // Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
502
+ ORG_EDGE_PROFILE_PROXY: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
503
+ ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
504
+ // Cloud Edge live viewer command (V1b) — api-server, gated on cap:edge-viewer.
505
+ // Same request/reply shape as the v2 browser-profile viewer, on the v3 edge
506
+ // pipe. Additive: does NOT replace BROWSER_PROFILE_VIEWER_COMMAND.
507
+ ORG_EDGE_VIEWER_COMMAND: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/viewer/command`,
496
508
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
497
- CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
509
+ CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
510
+ // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
511
+ // Pinix Hub catalog proxy above is a different, id-less surface)
512
+ ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
513
+ ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
514
+ ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
498
515
  };
499
516
  WS_EVENTS = {
500
517
  // Client -> Server
@@ -510,6 +527,7 @@ var init_constants = __esm({
510
527
  MESSAGE_PATCH: "message.patch",
511
528
  MESSAGE_EDIT: "message.edit",
512
529
  MESSAGE_DELETE: "message.delete",
530
+ MESSAGE_REACTION_UPDATED: "message.reaction.updated",
513
531
  TYPING_UPDATE: "typing.update",
514
532
  CHAT_UPDATE: "chat.update",
515
533
  CHAT_DELETED: "chat.deleted",
@@ -551,6 +569,7 @@ var init_constants = __esm({
551
569
  INBOX_UPDATE: "inbox.update",
552
570
  INBOX_BULK_UPDATE: "inbox.bulk_update",
553
571
  READ_POSITION_UPDATED: "read_position.updated",
572
+ THREAD_READ_POSITION_UPDATED: "thread_read_position.updated",
554
573
  DISPATCH_NEW: "dispatch.new",
555
574
  DISPATCH_RECEIVED: "dispatch.received",
556
575
  DISPATCH_RESOLVED: "dispatch.resolved",
@@ -597,6 +616,9 @@ function buildApiError(res, rawErrorBody) {
597
616
  const errMsg = (typeof errorObj?.message === "string" ? errorObj.message : void 0) ?? (typeof errorBody.message === "string" ? errorBody.message : void 0) ?? (typeof errorBody.error === "string" ? errorBody.error : void 0);
598
617
  const errCode = (typeof errorObj?.code === "string" ? errorObj.code : void 0) ?? (typeof errorBody.code === "string" ? errorBody.code : void 0);
599
618
  const apiError = new ApiError(res.status, errMsg ?? res.statusText, errCode);
619
+ const retryAfter = Number(res.headers?.get("Retry-After"));
620
+ if (Number.isFinite(retryAfter) && retryAfter > 0)
621
+ apiError.retryAfterSeconds = retryAfter;
600
622
  const anchors = errorObj ?? errorBody;
601
623
  if (typeof anchors.action === "string")
602
624
  apiError.action = anchors.action;
@@ -777,7 +799,7 @@ var init_client = __esm({
777
799
  if (qs)
778
800
  url += `?${qs}`;
779
801
  }
780
- const headers = this.buildHeaders(path23);
802
+ const headers = this.buildHeaders(path23, opts?.headers);
781
803
  const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
782
804
  const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
783
805
  let res;
@@ -1183,6 +1205,14 @@ var init_client = __esm({
1183
1205
  async getMessageReplies(id, params) {
1184
1206
  return this.request("GET", ENDPOINTS.MESSAGE_REPLIES(id), void 0, params);
1185
1207
  }
1208
+ // ---- Reactions ----
1209
+ async toggleReaction(messageId, emoji) {
1210
+ return this.request("PUT", ENDPOINTS.MESSAGE_REACTION(messageId, emoji));
1211
+ }
1212
+ async listReactions(messageId) {
1213
+ const res = await this.request("GET", ENDPOINTS.MESSAGE_REACTIONS(messageId));
1214
+ return res.reactions;
1215
+ }
1186
1216
  // ---- File Upload ----
1187
1217
  async getUploadPresignUrl(orgId, req) {
1188
1218
  return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
@@ -1558,6 +1588,15 @@ var init_client = __esm({
1558
1588
  async browserViewerCommand(orgId, profileId, req, opts) {
1559
1589
  return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, opts);
1560
1590
  }
1591
+ /**
1592
+ * Drive the Cloud Edge live viewer (V1b, design §6): WebRTC signaling + input +
1593
+ * tab nav for a hosted browser (Cloud Profile). Same request/reply shape as
1594
+ * browserViewerCommand, on the v3 edge pipe; additive — the v2 browser-profile
1595
+ * viewer is unchanged.
1596
+ */
1597
+ async edgeViewerCommand(orgId, edgeId, req, opts) {
1598
+ return this.request("POST", ENDPOINTS.ORG_EDGE_VIEWER_COMMAND(orgId, edgeId), req, void 0, false, opts);
1599
+ }
1561
1600
  async resizeMachine(orgId, machineId, spec) {
1562
1601
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
1563
1602
  }
@@ -1584,14 +1623,23 @@ var init_client = __esm({
1584
1623
  }
1585
1624
  // Wiki mount/token methods removed — wiki-service handles all wiki endpoints.
1586
1625
  // ---- Unread ----
1587
- async getUnreadCounts(orgId) {
1626
+ async getUnreadCounts(orgId, opts) {
1588
1627
  const endpoint = orgId ? ENDPOINTS.ORG_UNREAD(orgId) : ENDPOINTS.UNREAD;
1589
- const res = await this.request("GET", endpoint);
1628
+ const res = await this.request("GET", endpoint, void 0, {
1629
+ include_thread_replies: opts?.includeThreadReplies ? "true" : void 0
1630
+ });
1590
1631
  return res.data;
1591
1632
  }
1592
1633
  async markRead(orgId, chatId, messageId) {
1593
1634
  return this.request("POST", ENDPOINTS.CHAT_READ(orgId, chatId), { message_id: messageId });
1594
1635
  }
1636
+ /** Mark everything in a chat read: the channel cursor jumps to the latest
1637
+ * top-level message and every thread cursor to its latest reply, in one
1638
+ * idempotent call. The server echoes the same per-cursor WS events the
1639
+ * single-cursor routes emit and auto-clears covered inbox items. */
1640
+ async markAllRead(orgId, chatId) {
1641
+ return this.request("POST", ENDPOINTS.CHAT_READ_ALL(orgId, chatId));
1642
+ }
1595
1643
  async getThreadUnread(orgId, chatId, threadRootId) {
1596
1644
  return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
1597
1645
  }
@@ -2266,6 +2314,16 @@ var init_client = __esm({
2266
2314
  async getBacklinks(orgId, params) {
2267
2315
  return this.request("GET", ENDPOINTS.REFS_BACKLINKS(orgId), void 0, params);
2268
2316
  }
2317
+ /**
2318
+ * Outbound prll:// refs authored in a set of sources, as raw ref_links rows
2319
+ * (dedupe/group client-side). Pass `{ thread_root_id }` to list a whole
2320
+ * thread's refs (root + all replies, resolved server-side — the client's
2321
+ * reply window may be partial), or `{ source_type, source_ids }` for
2322
+ * explicit sources (max 500; v1 accepts only message sources).
2323
+ */
2324
+ async listOutboundRefs(orgId, req) {
2325
+ return this.request("POST", ENDPOINTS.REFS_OUTBOUND(orgId), req);
2326
+ }
2269
2327
  /**
2270
2328
  * Bounded multi-hop walk of the prll:// reference graph around `uri`. `uri`
2271
2329
  * must be an entity-level prll:// URI — a refined URI (path/query/fragment) is
@@ -2476,6 +2534,31 @@ var init_client = __esm({
2476
2534
  const resp = await this.request("GET", url);
2477
2535
  return resp.data;
2478
2536
  }
2537
+ // ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
2538
+ /**
2539
+ * List registry clips visible to the org: its own plus public+approved
2540
+ * cross-org entries. This is the surface `installRegistryClip` and clip
2541
+ * connections operate on — NOT the Pinix catalog proxy
2542
+ * ({@link listRegistryClips}), whose entries carry no `crg_` id.
2543
+ */
2544
+ async listOrgRegistryClips(orgId) {
2545
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
2546
+ return resp ?? [];
2547
+ }
2548
+ /**
2549
+ * Install a registry clip into the org (a reference in `clip_installs`, not a
2550
+ * copy). Idempotent: installing an already-installed clip returns the same
2551
+ * `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
2552
+ * not eligible (cross-org requires public + approved).
2553
+ */
2554
+ async installRegistryClip(orgId, clipId) {
2555
+ return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
2556
+ }
2557
+ /** List the org's installed registry clips (full entries). */
2558
+ async listInstalledRegistryClips(orgId) {
2559
+ const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
2560
+ return resp ?? [];
2561
+ }
2479
2562
  // ---- Edge devices ----
2480
2563
  async listEdgeDevices(orgId) {
2481
2564
  return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
@@ -2493,8 +2576,8 @@ var init_client = __esm({
2493
2576
  return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
2494
2577
  }
2495
2578
  /**
2496
- * Delete a hosted Cloud Profile. Hosted only — a BYOC device is removed by
2497
- * uninstalling Parall Clip on that machine (`400 EDGE_PLACEMENT_UNSUPPORTED`).
2579
+ * Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
2580
+ * for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
2498
2581
  *
2499
2582
  * Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
2500
2583
  * call and on every repeat. The device stops being usable immediately (no exec, no
@@ -2504,12 +2587,105 @@ var init_client = __esm({
2504
2587
  async deleteEdgeDevice(orgId, edgeId) {
2505
2588
  return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
2506
2589
  }
2590
+ /**
2591
+ * Remove the interactive human caller's own offline BYOC registration.
2592
+ *
2593
+ * Synchronous and idempotent: a committed removal and a repeat after removal
2594
+ * both resolve with no response body. A live connection returns `EDGE_ONLINE`;
2595
+ * callers must not clear local device identity until this method resolves.
2596
+ */
2597
+ async unregisterEdgeDevice(orgId, edgeId) {
2598
+ await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
2599
+ }
2507
2600
  async getEdgeOnboarding(orgId) {
2508
2601
  return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
2509
2602
  }
2510
2603
  async listEdgeProfiles(orgId, edgeId) {
2511
2604
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
2512
2605
  }
2606
+ /**
2607
+ * Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
2608
+ * human maintainer or org admin). Sanitized — the password never comes back.
2609
+ * Typed errors: `EDGE_NOT_HOSTED` (BYOC device), `PROXY_CONFIG_CORRUPT` /
2610
+ * validation codes as 422 when a stored config no longer passes current rules.
2611
+ * `can_mutate` and `lease_status` are the authoritative idle gate; device
2612
+ * list status is not a substitute.
2613
+ */
2614
+ async getEdgeProfileProxy(orgId, edgeId, profileName) {
2615
+ return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName));
2616
+ }
2617
+ /**
2618
+ * Set/replace the profile's egress proxy (full triple every time) — IDLE
2619
+ * ONLY: while the profile's hosted browser is running (a viewer session is
2620
+ * open or a pod is otherwise live) the server answers 409
2621
+ * `EDGE_PROFILE_IN_USE`; close the viewer, wait for idle scale-to-zero, and
2622
+ * retry. The next cold start uses the new egress; browser login state is
2623
+ * preserved across it. Other typed errors: the validation vocabulary
2624
+ * (`INVALID_PROXY_SERVER`, `PROXY_AUTH_INCOMPLETE`,
2625
+ * `PROXY_SERVER_FORBIDDEN_TARGET`, …), `EDGE_DELETING` (409), and
2626
+ * `SECRETBOX_UNCONFIGURED` (503 — server cannot store credentials safely),
2627
+ * and `EDGE_PROFILE_PROXY_STALE` (409 — expectedVersion lost a tab race).
2628
+ */
2629
+ async setEdgeProfileProxy(orgId, edgeId, profileName, req, expectedVersion) {
2630
+ return this.request("PUT", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), req, void 0, false, {
2631
+ headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
2632
+ });
2633
+ }
2634
+ /**
2635
+ * Clear the profile's egress proxy; the next pod start egresses directly.
2636
+ * Idle-only like set — 409 `EDGE_PROFILE_IN_USE` while the browser is live.
2637
+ */
2638
+ async clearEdgeProfileProxy(orgId, edgeId, profileName, expectedVersion) {
2639
+ return this.request("DELETE", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), void 0, void 0, false, {
2640
+ headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
2641
+ });
2642
+ }
2643
+ /**
2644
+ * Execute a registry clip command on an Edge device.
2645
+ *
2646
+ * A hosted (Cloud Profile) device is reachable ONLY through an explicit
2647
+ * `connection` (id `ccn_…` or alias) — there is no implicit route to an
2648
+ * org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
2649
+ * nothing for the caller's own online device).
2650
+ *
2651
+ * Returns the result envelope on completion (`success` may be false when the
2652
+ * command RAN and failed — `error`/`error_code` describe why). Everything
2653
+ * else throws a typed {@link ApiError}; match on `err.code`:
2654
+ *
2655
+ * Safe to retry (guaranteed nothing was dispatched):
2656
+ * - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
2657
+ * Bounded backoff, same `correlation_id` across the loop.
2658
+ * - `EDGE_BUSY` 409 — the device is executing another request.
2659
+ * - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
2660
+ * - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
2661
+ *
2662
+ * NOT retryable:
2663
+ * - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
2664
+ * MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
2665
+ * automatically: verify the effect first, then decide. The message carries
2666
+ * the request id for audit.
2667
+ * - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
2668
+ * - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
2669
+ * `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
2670
+ * - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
2671
+ * `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
2672
+ * `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
2673
+ */
2674
+ async execEdgeClip(orgId, req) {
2675
+ const t = req.timeout;
2676
+ const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
2677
+ const timeoutMs = serverTimeout + 1e4;
2678
+ try {
2679
+ return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
2680
+ timeoutMs
2681
+ });
2682
+ } catch (err) {
2683
+ if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
2684
+ err.code = err.extras.error_code;
2685
+ }
2686
+ throw err;
2687
+ }
2688
+ }
2513
2689
  // ---- Clip connections ----
2514
2690
  async listClipConnections(orgId, clipId) {
2515
2691
  return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
@@ -2525,6 +2701,8 @@ var init_client = __esm({
2525
2701
  status;
2526
2702
  code;
2527
2703
  extras;
2704
+ /** Retry-After delta seconds when the server supplies one. */
2705
+ retryAfterSeconds;
2528
2706
  /** Attempted action (authorization denials) — e.g. "chat.add_member". */
2529
2707
  action;
2530
2708
  /** Target resource URI that was evaluated — e.g. "prll://cht_…". */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/daemon",
3
- "version": "1.47.0",
3
+ "version": "1.49.0",
4
4
  "description": "Parall local agent runtime — daemon supervisor + bridge runtimes, bundled as standalone JS files",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,11 +33,11 @@
33
33
  "@aws-sdk/client-s3": "3.984.0",
34
34
  "@pinixai/bb-browser-pro": "0.15.0",
35
35
  "ws": "^8.18.0",
36
- "@parall/agent-core": "1.47.0",
37
- "@parall/claude-agent": "1.47.0",
38
- "@parall/openclaw-agent": "1.47.0",
39
- "@parall/sdk": "1.47.0",
40
- "@parall/codex-agent": "1.47.0"
36
+ "@parall/agent-core": "1.49.0",
37
+ "@parall/sdk": "1.49.0",
38
+ "@parall/codex-agent": "1.49.0",
39
+ "@parall/openclaw-agent": "1.49.0",
40
+ "@parall/claude-agent": "1.49.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^22.0.0",