@parall/daemon 1.46.0 → 1.48.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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.46.0",
3
- "built_at": "2026-07-16T19:15:13.903Z",
2
+ "version": "1.48.0",
3
+ "built_at": "2026-07-21T07:52:25.995Z",
4
4
  "min_node_version": "20.0.0",
5
5
  "files": {
6
6
  "bb-browser-daemon.js": {
@@ -16,29 +16,29 @@
16
16
  "size": 18
17
17
  },
18
18
  "parall-browser-pod.js": {
19
- "sha256": "cf07c471424ed728b1576b9c002eee4d32d01f9212612f3768576a363a4801df",
20
- "size": 2886066
19
+ "sha256": "d35ed50bf1fc1266cb8001c9dd3e694dff9847738d125582ccaca81bc3db45d5",
20
+ "size": 2894062
21
21
  },
22
22
  "parall-channel-exec.js": {
23
23
  "sha256": "7c2a6e12483a45e9eb4a42cd7d4cdd3c4fa21dd09ac1347d9a3e177b4ddee930",
24
24
  "size": 7220
25
25
  },
26
26
  "parall-claude-agent.js": {
27
- "sha256": "fdae94bac193fb2f645f488874bdb795965173cd1e13ff60363b6fb622e7f932",
28
- "size": 2717830
27
+ "sha256": "852f7b7d3840f243d39d5ec2f23735ee80fce6fb9c5f8ab5ff1cfb7d5281ad51",
28
+ "size": 2727384
29
29
  },
30
30
  "parall-codex-agent.js": {
31
- "sha256": "729dd09421cbf60d046060df0084ac1aed976f33df9b90f449bebf23a11bf3c4",
32
- "size": 2759570
31
+ "sha256": "c331674763f9c237d6a3ee03d9bc8f4137c154e2e576caa5fd23bbe32f0f2b49",
32
+ "size": 2769124
33
33
  },
34
34
  "parall-daemon.js": {
35
- "sha256": "7db4991b1de426126d86f04ebbc91004d5012708e2e4638c44727ef065d99c35",
36
- "size": 2935538
35
+ "sha256": "0c41c7255f98339d095faf96e7b712c150d442696eefcb3965d3e59ad0f251fa",
36
+ "size": 2955625
37
37
  },
38
38
  "parall-openclaw-agent.js": {
39
39
  "sha256": "856a1c3a9ae0ffef8efe2481fa1171dbeb1d67cccb88616aa9bf16da96a69355",
40
40
  "size": 9923
41
41
  }
42
42
  },
43
- "signature": "mrgNk35+8SZTRSfZVFcN6rThJ1RvMzcZcUhzQbq79qRcmmRHL3Whll/AIZlHzixmdSJHAApQVBBT4Cci6iE/BQ=="
43
+ "signature": "u4mhCrFPCejnf/mBjQdNvKkDaQE0MjumZpTc5eHA+Qz7cbemy1WDRhy+j0A4pMvBezJqwUIoyQqn84jfjcgBDA=="
44
44
  }
@@ -63685,10 +63685,17 @@ var ENDPOINTS = {
63685
63685
  CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
63686
63686
  CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
63687
63687
  CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
63688
+ CHANNEL_SLACK_MANIFEST_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/slack/manifest-link`,
63688
63689
  CHANNEL_PROVISIONING_SESSION: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
63689
63690
  CHANNEL_PROVISIONING_CANCEL: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
63690
63691
  // Tier-B platform verb (agent-only): send one message as the bound bot.
63691
63692
  CHANNEL_SEND: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/channel-send`,
63693
+ // Tier-B read verbs (agent-only): workspace visibility as the bot sees it.
63694
+ SLACK_CHANNELS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/channels`,
63695
+ SLACK_USERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/users`,
63696
+ SLACK_HISTORY: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/history`,
63697
+ SLACK_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/members`,
63698
+ SLACK_STATUS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/status`,
63692
63699
  // Invitations (org-scoped, admin)
63693
63700
  ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
63694
63701
  ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
@@ -63783,6 +63790,7 @@ var ENDPOINTS = {
63783
63790
  ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
63784
63791
  CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
63785
63792
  THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
63793
+ THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
63786
63794
  // References (org-scoped)
63787
63795
  REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
63788
63796
  REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
@@ -63844,10 +63852,17 @@ var ENDPOINTS = {
63844
63852
  ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
63845
63853
  ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
63846
63854
  ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
63855
+ ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
63847
63856
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
63848
63857
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
63858
+ ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
63849
63859
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
63850
- CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
63860
+ CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
63861
+ // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
63862
+ // Pinix Hub catalog proxy above is a different, id-less surface)
63863
+ ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
63864
+ ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
63865
+ ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
63851
63866
  };
63852
63867
 
63853
63868
  // ts/sdk/dist/client.js
@@ -64789,10 +64804,16 @@ var ParallClient = class _ParallClient {
64789
64804
  async resizeMachine(orgId, machineId, spec) {
64790
64805
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
64791
64806
  }
64792
- /** Signal a local daemon-mode Machine to check for and apply an update. */
64807
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
64808
+ * daemons update autonomously (CDN poll + platform release signal). The
64809
+ * endpoint now answers 409 LOCAL_UPDATE_NOT_SUPPORTED unconditionally. */
64793
64810
  async requestMachineUpdate(orgId, machineId, mandatory = false) {
64794
64811
  await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
64795
64812
  }
64813
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
64814
+ * remote filesystem browse of a member's machine was remote device access.
64815
+ * The endpoint now answers 409 LOCAL_BROWSE_NOT_SUPPORTED unconditionally;
64816
+ * workspace paths are typed in (or picked on the machine's own Desktop). */
64796
64817
  async browseMachineFilesystem(orgId, machineId, path7) {
64797
64818
  return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path7 }, void 0, false, { timeoutMs: 15e3 });
64798
64819
  }
@@ -64817,6 +64838,14 @@ var ParallClient = class _ParallClient {
64817
64838
  async getThreadUnread(orgId, chatId, threadRootId) {
64818
64839
  return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
64819
64840
  }
64841
+ /** Advance the per-thread read cursor (forward-only). The server auto-clears
64842
+ * thread-scoped inbox items (thread_reply + in-thread mentions) the cursor
64843
+ * now covers. */
64844
+ async markThreadRead(orgId, chatId, threadRootId, messageId) {
64845
+ return this.request("POST", ENDPOINTS.THREAD_READ(orgId, chatId, threadRootId), {
64846
+ message_id: messageId
64847
+ });
64848
+ }
64820
64849
  // ---- Inbox ----
64821
64850
  async getInbox(orgId, params) {
64822
64851
  return this.request("GET", ENDPOINTS.INBOX(orgId), void 0, params);
@@ -64840,9 +64869,12 @@ var ParallClient = class _ParallClient {
64840
64869
  async archiveAllInbox(orgId) {
64841
64870
  return this.request("POST", ENDPOINTS.INBOX_ARCHIVE_ALL(orgId));
64842
64871
  }
64843
- /** Mark an inbox item as read by its source (source_type + source_id) rather than inbox item ID. */
64844
- async ackInbox(orgId, source) {
64845
- return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), source);
64872
+ /** Mark inbox items as read by their source (source_type + source_id) or by
64873
+ * group_key, rather than by inbox item ID. The group_key form clears a whole
64874
+ * group at once (e.g. `task:{taskId}` — task_assign/task_update/task_comment
64875
+ * share it), used by the task detail view's auto-ack on open. */
64876
+ async ackInbox(orgId, target) {
64877
+ return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), target);
64846
64878
  }
64847
64879
  async deleteInboxItem(orgId, id) {
64848
64880
  return this.request("DELETE", ENDPOINTS.INBOX_ITEM(orgId, id));
@@ -65124,6 +65156,15 @@ var ParallClient = class _ParallClient {
65124
65156
  async initiateChannelProvisioning(orgId, input) {
65125
65157
  return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
65126
65158
  }
65159
+ /**
65160
+ * Mint a pending slack connection + api.slack.com manifest-prefill link
65161
+ * (guided manual path). Activate the returned connection_id with
65162
+ * deliverChannelCredentials once the user brings back the bot token +
65163
+ * signing secret.
65164
+ */
65165
+ async createSlackManifestLink(orgId, input) {
65166
+ return this.request("POST", ENDPOINTS.CHANNEL_SLACK_MANIFEST_LINK(orgId), input);
65167
+ }
65127
65168
  /**
65128
65169
  * Lazy status poll — server-side this may forward one provider poll, so
65129
65170
  * call it at the session's `poll_interval_seconds` cadence, not faster.
@@ -65142,6 +65183,38 @@ var ParallClient = class _ParallClient {
65142
65183
  async sendChannelMessage(orgId, input) {
65143
65184
  return this.request("POST", ENDPOINTS.CHANNEL_SEND(orgId), input);
65144
65185
  }
65186
+ slackReadQuery(base, query, extra) {
65187
+ const params = new URLSearchParams();
65188
+ if (query?.cursor)
65189
+ params.set("cursor", query.cursor);
65190
+ if (query?.limit)
65191
+ params.set("limit", String(query.limit));
65192
+ for (const [k5, v] of Object.entries(extra ?? {}))
65193
+ params.set(k5, v);
65194
+ const qs = params.toString();
65195
+ return qs ? `${base}?${qs}` : base;
65196
+ }
65197
+ /**
65198
+ * Tier-B read verbs (agent-only): workspace visibility as the bot sees
65199
+ * it. Same live gate as the send verb; authorization beyond it is the
65200
+ * bot's own Slack permissions.
65201
+ */
65202
+ async listSlackChannels(orgId, query) {
65203
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_CHANNELS(orgId), query));
65204
+ }
65205
+ async listSlackUsers(orgId, query) {
65206
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_USERS(orgId), query));
65207
+ }
65208
+ async slackHistory(orgId, conversationId, query) {
65209
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_HISTORY(orgId), query, { conversation: conversationId }));
65210
+ }
65211
+ async slackMembers(orgId, conversationId, query) {
65212
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_MEMBERS(orgId), query, { conversation: conversationId }));
65213
+ }
65214
+ /** Set/clear the Agents-pane "typing…" indicator (best-effort cosmetic). */
65215
+ async setSlackStatus(orgId, input) {
65216
+ await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
65217
+ }
65145
65218
  async listChannelConversations(orgId, connectionId) {
65146
65219
  return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
65147
65220
  }
@@ -65646,6 +65719,31 @@ var ParallClient = class _ParallClient {
65646
65719
  const resp = await this.request("GET", url);
65647
65720
  return resp.data;
65648
65721
  }
65722
+ // ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
65723
+ /**
65724
+ * List registry clips visible to the org: its own plus public+approved
65725
+ * cross-org entries. This is the surface `installRegistryClip` and clip
65726
+ * connections operate on — NOT the Pinix catalog proxy
65727
+ * ({@link listRegistryClips}), whose entries carry no `crg_` id.
65728
+ */
65729
+ async listOrgRegistryClips(orgId) {
65730
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
65731
+ return resp ?? [];
65732
+ }
65733
+ /**
65734
+ * Install a registry clip into the org (a reference in `clip_installs`, not a
65735
+ * copy). Idempotent: installing an already-installed clip returns the same
65736
+ * `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
65737
+ * not eligible (cross-org requires public + approved).
65738
+ */
65739
+ async installRegistryClip(orgId, clipId) {
65740
+ return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
65741
+ }
65742
+ /** List the org's installed registry clips (full entries). */
65743
+ async listInstalledRegistryClips(orgId) {
65744
+ const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
65745
+ return resp ?? [];
65746
+ }
65649
65747
  // ---- Edge devices ----
65650
65748
  async listEdgeDevices(orgId) {
65651
65749
  return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
@@ -65663,8 +65761,8 @@ var ParallClient = class _ParallClient {
65663
65761
  return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
65664
65762
  }
65665
65763
  /**
65666
- * Delete a hosted Cloud Profile. Hosted only — a BYOC device is removed by
65667
- * uninstalling Parall Clip on that machine (`400 EDGE_PLACEMENT_UNSUPPORTED`).
65764
+ * Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
65765
+ * for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
65668
65766
  *
65669
65767
  * Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
65670
65768
  * call and on every repeat. The device stops being usable immediately (no exec, no
@@ -65674,12 +65772,68 @@ var ParallClient = class _ParallClient {
65674
65772
  async deleteEdgeDevice(orgId, edgeId) {
65675
65773
  return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
65676
65774
  }
65775
+ /**
65776
+ * Remove the interactive human caller's own offline BYOC registration.
65777
+ *
65778
+ * Synchronous and idempotent: a committed removal and a repeat after removal
65779
+ * both resolve with no response body. A live connection returns `EDGE_ONLINE`;
65780
+ * callers must not clear local device identity until this method resolves.
65781
+ */
65782
+ async unregisterEdgeDevice(orgId, edgeId) {
65783
+ await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
65784
+ }
65677
65785
  async getEdgeOnboarding(orgId) {
65678
65786
  return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
65679
65787
  }
65680
65788
  async listEdgeProfiles(orgId, edgeId) {
65681
65789
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
65682
65790
  }
65791
+ /**
65792
+ * Execute a registry clip command on an Edge device.
65793
+ *
65794
+ * A hosted (Cloud Profile) device is reachable ONLY through an explicit
65795
+ * `connection` (id `ccn_…` or alias) — there is no implicit route to an
65796
+ * org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
65797
+ * nothing for the caller's own online device).
65798
+ *
65799
+ * Returns the result envelope on completion (`success` may be false when the
65800
+ * command RAN and failed — `error`/`error_code` describe why). Everything
65801
+ * else throws a typed {@link ApiError}; match on `err.code`:
65802
+ *
65803
+ * Safe to retry (guaranteed nothing was dispatched):
65804
+ * - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
65805
+ * Bounded backoff, same `correlation_id` across the loop.
65806
+ * - `EDGE_BUSY` 409 — the device is executing another request.
65807
+ * - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
65808
+ * - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
65809
+ *
65810
+ * NOT retryable:
65811
+ * - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
65812
+ * MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
65813
+ * automatically: verify the effect first, then decide. The message carries
65814
+ * the request id for audit.
65815
+ * - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
65816
+ * - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
65817
+ * `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
65818
+ * - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
65819
+ * `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
65820
+ * `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
65821
+ */
65822
+ async execEdgeClip(orgId, req) {
65823
+ const t = req.timeout;
65824
+ const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
65825
+ const timeoutMs = serverTimeout + 1e4;
65826
+ try {
65827
+ return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
65828
+ timeoutMs
65829
+ });
65830
+ } catch (err) {
65831
+ if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
65832
+ err.code = err.extras.error_code;
65833
+ }
65834
+ throw err;
65835
+ }
65836
+ }
65683
65837
  // ---- Clip connections ----
65684
65838
  async listClipConnections(orgId, clipId) {
65685
65839
  return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
@@ -51484,10 +51484,17 @@ var ENDPOINTS = {
51484
51484
  CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
51485
51485
  CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
51486
51486
  CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
51487
+ CHANNEL_SLACK_MANIFEST_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/slack/manifest-link`,
51487
51488
  CHANNEL_PROVISIONING_SESSION: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
51488
51489
  CHANNEL_PROVISIONING_CANCEL: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
51489
51490
  // Tier-B platform verb (agent-only): send one message as the bound bot.
51490
51491
  CHANNEL_SEND: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/channel-send`,
51492
+ // Tier-B read verbs (agent-only): workspace visibility as the bot sees it.
51493
+ SLACK_CHANNELS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/channels`,
51494
+ SLACK_USERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/users`,
51495
+ SLACK_HISTORY: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/history`,
51496
+ SLACK_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/members`,
51497
+ SLACK_STATUS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/status`,
51491
51498
  // Invitations (org-scoped, admin)
51492
51499
  ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
51493
51500
  ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
@@ -51582,6 +51589,7 @@ var ENDPOINTS = {
51582
51589
  ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
51583
51590
  CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
51584
51591
  THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
51592
+ THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
51585
51593
  // References (org-scoped)
51586
51594
  REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
51587
51595
  REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
@@ -51643,10 +51651,17 @@ var ENDPOINTS = {
51643
51651
  ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
51644
51652
  ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
51645
51653
  ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
51654
+ ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
51646
51655
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
51647
51656
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
51657
+ ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
51648
51658
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
51649
- CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
51659
+ CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
51660
+ // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
51661
+ // Pinix Hub catalog proxy above is a different, id-less surface)
51662
+ ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
51663
+ ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
51664
+ ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
51650
51665
  };
51651
51666
  var WS_EVENTS = {
51652
51667
  // Client -> Server
@@ -52672,10 +52687,16 @@ var ParallClient = class _ParallClient {
52672
52687
  async resizeMachine(orgId, machineId, spec) {
52673
52688
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
52674
52689
  }
52675
- /** Signal a local daemon-mode Machine to check for and apply an update. */
52690
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
52691
+ * daemons update autonomously (CDN poll + platform release signal). The
52692
+ * endpoint now answers 409 LOCAL_UPDATE_NOT_SUPPORTED unconditionally. */
52676
52693
  async requestMachineUpdate(orgId, machineId, mandatory = false) {
52677
52694
  await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
52678
52695
  }
52696
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
52697
+ * remote filesystem browse of a member's machine was remote device access.
52698
+ * The endpoint now answers 409 LOCAL_BROWSE_NOT_SUPPORTED unconditionally;
52699
+ * workspace paths are typed in (or picked on the machine's own Desktop). */
52679
52700
  async browseMachineFilesystem(orgId, machineId, path11) {
52680
52701
  return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path11 }, void 0, false, { timeoutMs: 15e3 });
52681
52702
  }
@@ -52700,6 +52721,14 @@ var ParallClient = class _ParallClient {
52700
52721
  async getThreadUnread(orgId, chatId, threadRootId) {
52701
52722
  return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
52702
52723
  }
52724
+ /** Advance the per-thread read cursor (forward-only). The server auto-clears
52725
+ * thread-scoped inbox items (thread_reply + in-thread mentions) the cursor
52726
+ * now covers. */
52727
+ async markThreadRead(orgId, chatId, threadRootId, messageId) {
52728
+ return this.request("POST", ENDPOINTS.THREAD_READ(orgId, chatId, threadRootId), {
52729
+ message_id: messageId
52730
+ });
52731
+ }
52703
52732
  // ---- Inbox ----
52704
52733
  async getInbox(orgId, params) {
52705
52734
  return this.request("GET", ENDPOINTS.INBOX(orgId), void 0, params);
@@ -52723,9 +52752,12 @@ var ParallClient = class _ParallClient {
52723
52752
  async archiveAllInbox(orgId) {
52724
52753
  return this.request("POST", ENDPOINTS.INBOX_ARCHIVE_ALL(orgId));
52725
52754
  }
52726
- /** Mark an inbox item as read by its source (source_type + source_id) rather than inbox item ID. */
52727
- async ackInbox(orgId, source) {
52728
- return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), source);
52755
+ /** Mark inbox items as read by their source (source_type + source_id) or by
52756
+ * group_key, rather than by inbox item ID. The group_key form clears a whole
52757
+ * group at once (e.g. `task:{taskId}` — task_assign/task_update/task_comment
52758
+ * share it), used by the task detail view's auto-ack on open. */
52759
+ async ackInbox(orgId, target) {
52760
+ return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), target);
52729
52761
  }
52730
52762
  async deleteInboxItem(orgId, id) {
52731
52763
  return this.request("DELETE", ENDPOINTS.INBOX_ITEM(orgId, id));
@@ -53007,6 +53039,15 @@ var ParallClient = class _ParallClient {
53007
53039
  async initiateChannelProvisioning(orgId, input) {
53008
53040
  return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
53009
53041
  }
53042
+ /**
53043
+ * Mint a pending slack connection + api.slack.com manifest-prefill link
53044
+ * (guided manual path). Activate the returned connection_id with
53045
+ * deliverChannelCredentials once the user brings back the bot token +
53046
+ * signing secret.
53047
+ */
53048
+ async createSlackManifestLink(orgId, input) {
53049
+ return this.request("POST", ENDPOINTS.CHANNEL_SLACK_MANIFEST_LINK(orgId), input);
53050
+ }
53010
53051
  /**
53011
53052
  * Lazy status poll — server-side this may forward one provider poll, so
53012
53053
  * call it at the session's `poll_interval_seconds` cadence, not faster.
@@ -53025,6 +53066,38 @@ var ParallClient = class _ParallClient {
53025
53066
  async sendChannelMessage(orgId, input) {
53026
53067
  return this.request("POST", ENDPOINTS.CHANNEL_SEND(orgId), input);
53027
53068
  }
53069
+ slackReadQuery(base, query, extra) {
53070
+ const params = new URLSearchParams();
53071
+ if (query?.cursor)
53072
+ params.set("cursor", query.cursor);
53073
+ if (query?.limit)
53074
+ params.set("limit", String(query.limit));
53075
+ for (const [k, v] of Object.entries(extra ?? {}))
53076
+ params.set(k, v);
53077
+ const qs = params.toString();
53078
+ return qs ? `${base}?${qs}` : base;
53079
+ }
53080
+ /**
53081
+ * Tier-B read verbs (agent-only): workspace visibility as the bot sees
53082
+ * it. Same live gate as the send verb; authorization beyond it is the
53083
+ * bot's own Slack permissions.
53084
+ */
53085
+ async listSlackChannels(orgId, query) {
53086
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_CHANNELS(orgId), query));
53087
+ }
53088
+ async listSlackUsers(orgId, query) {
53089
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_USERS(orgId), query));
53090
+ }
53091
+ async slackHistory(orgId, conversationId, query) {
53092
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_HISTORY(orgId), query, { conversation: conversationId }));
53093
+ }
53094
+ async slackMembers(orgId, conversationId, query) {
53095
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_MEMBERS(orgId), query, { conversation: conversationId }));
53096
+ }
53097
+ /** Set/clear the Agents-pane "typing…" indicator (best-effort cosmetic). */
53098
+ async setSlackStatus(orgId, input) {
53099
+ await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
53100
+ }
53028
53101
  async listChannelConversations(orgId, connectionId) {
53029
53102
  return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
53030
53103
  }
@@ -53529,6 +53602,31 @@ var ParallClient = class _ParallClient {
53529
53602
  const resp = await this.request("GET", url);
53530
53603
  return resp.data;
53531
53604
  }
53605
+ // ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
53606
+ /**
53607
+ * List registry clips visible to the org: its own plus public+approved
53608
+ * cross-org entries. This is the surface `installRegistryClip` and clip
53609
+ * connections operate on — NOT the Pinix catalog proxy
53610
+ * ({@link listRegistryClips}), whose entries carry no `crg_` id.
53611
+ */
53612
+ async listOrgRegistryClips(orgId) {
53613
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
53614
+ return resp ?? [];
53615
+ }
53616
+ /**
53617
+ * Install a registry clip into the org (a reference in `clip_installs`, not a
53618
+ * copy). Idempotent: installing an already-installed clip returns the same
53619
+ * `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
53620
+ * not eligible (cross-org requires public + approved).
53621
+ */
53622
+ async installRegistryClip(orgId, clipId) {
53623
+ return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
53624
+ }
53625
+ /** List the org's installed registry clips (full entries). */
53626
+ async listInstalledRegistryClips(orgId) {
53627
+ const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
53628
+ return resp ?? [];
53629
+ }
53532
53630
  // ---- Edge devices ----
53533
53631
  async listEdgeDevices(orgId) {
53534
53632
  return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
@@ -53546,8 +53644,8 @@ var ParallClient = class _ParallClient {
53546
53644
  return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
53547
53645
  }
53548
53646
  /**
53549
- * Delete a hosted Cloud Profile. Hosted only — a BYOC device is removed by
53550
- * uninstalling Parall Clip on that machine (`400 EDGE_PLACEMENT_UNSUPPORTED`).
53647
+ * Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
53648
+ * for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
53551
53649
  *
53552
53650
  * Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
53553
53651
  * call and on every repeat. The device stops being usable immediately (no exec, no
@@ -53557,12 +53655,68 @@ var ParallClient = class _ParallClient {
53557
53655
  async deleteEdgeDevice(orgId, edgeId) {
53558
53656
  return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
53559
53657
  }
53658
+ /**
53659
+ * Remove the interactive human caller's own offline BYOC registration.
53660
+ *
53661
+ * Synchronous and idempotent: a committed removal and a repeat after removal
53662
+ * both resolve with no response body. A live connection returns `EDGE_ONLINE`;
53663
+ * callers must not clear local device identity until this method resolves.
53664
+ */
53665
+ async unregisterEdgeDevice(orgId, edgeId) {
53666
+ await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
53667
+ }
53560
53668
  async getEdgeOnboarding(orgId) {
53561
53669
  return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
53562
53670
  }
53563
53671
  async listEdgeProfiles(orgId, edgeId) {
53564
53672
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
53565
53673
  }
53674
+ /**
53675
+ * Execute a registry clip command on an Edge device.
53676
+ *
53677
+ * A hosted (Cloud Profile) device is reachable ONLY through an explicit
53678
+ * `connection` (id `ccn_…` or alias) — there is no implicit route to an
53679
+ * org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
53680
+ * nothing for the caller's own online device).
53681
+ *
53682
+ * Returns the result envelope on completion (`success` may be false when the
53683
+ * command RAN and failed — `error`/`error_code` describe why). Everything
53684
+ * else throws a typed {@link ApiError}; match on `err.code`:
53685
+ *
53686
+ * Safe to retry (guaranteed nothing was dispatched):
53687
+ * - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
53688
+ * Bounded backoff, same `correlation_id` across the loop.
53689
+ * - `EDGE_BUSY` 409 — the device is executing another request.
53690
+ * - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
53691
+ * - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
53692
+ *
53693
+ * NOT retryable:
53694
+ * - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
53695
+ * MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
53696
+ * automatically: verify the effect first, then decide. The message carries
53697
+ * the request id for audit.
53698
+ * - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
53699
+ * - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
53700
+ * `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
53701
+ * - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
53702
+ * `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
53703
+ * `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
53704
+ */
53705
+ async execEdgeClip(orgId, req) {
53706
+ const t = req.timeout;
53707
+ const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
53708
+ const timeoutMs = serverTimeout + 1e4;
53709
+ try {
53710
+ return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
53711
+ timeoutMs
53712
+ });
53713
+ } catch (err) {
53714
+ if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
53715
+ err.code = err.extras.error_code;
53716
+ }
53717
+ throw err;
53718
+ }
53719
+ }
53566
53720
  // ---- Clip connections ----
53567
53721
  async listClipConnections(orgId, clipId) {
53568
53722
  return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
@@ -59649,6 +59803,27 @@ parall clip invoke github-tools list-repos '{"org":"acme"}'
59649
59803
 
59650
59804
  Results are JSON on stdout; failures print an error.
59651
59805
 
59806
+ ## Execute on an Edge device (registry clips)
59807
+
59808
+ Registry clips run on an Edge \u2014 a member's desktop, or an org-shared cloud
59809
+ profile. **Name the target explicitly.** A cloud profile has NO implicit
59810
+ route; omitting the target entirely is a desktop-only legacy form that
59811
+ reaches just YOUR OWN online desktop device \u2014 never a shared cloud profile.
59812
+
59813
+ \`\`\`bash
59814
+ parall clip exec <clip> <command> [args] --connection <id|alias> # the normal form
59815
+ parall clip exec browser-tools screenshot '{"url":"\u2026"}' --connection cloud-main
59816
+ \`\`\`
59817
+
59818
+ - A cloud (hosted) profile is reachable ONLY via \`--connection\` \u2014 the clip
59819
+ connection its maintainer bound (\`ccn_\u2026\` id or alias). That binding IS your
59820
+ authorization; without one the server answers \`HOSTED_CONNECTION_REQUIRED\`
59821
+ and the fix is to ask an owner/admin to bind the clip, never to retry.
59822
+ - \`--edge <edgeId>\` targets only a desktop device YOU own.
59823
+ - Cold cloud profiles are handled by the CLI: it absorbs \`EDGE_ACTIVATING\`
59824
+ with a bounded wait (~60s) while the profile starts. If the command still
59825
+ fails, report the error \u2014 do not blind-retry in a loop.
59826
+
59652
59827
  ## Behavior rules
59653
59828
 
59654
59829
  - An authorization error (clip not bound to you) is a fail-fast: ask the
@@ -59658,6 +59833,12 @@ Results are JSON on stdout; failures print an error.
59658
59833
  - Hosted browser activation is handled by the CLI: it waits (bounded) while a
59659
59834
  cold hosted browser starts, so if the invoke still fails, report the error \u2014
59660
59835
  do not blind-retry in a loop.
59836
+ - **\`OUTCOME_UNKNOWN\` is never retryable.** It means the command was
59837
+ dispatched and MAY HAVE EXECUTED even though no result came back. Retrying
59838
+ could post, order or delete twice. Verify the effect through the system you
59839
+ acted on (or tell the human, quoting the request id from the error) before
59840
+ ever re-running. \`EDGE_BUSY\` is the opposite: guaranteed-unexecuted \u2014 wait
59841
+ briefly, then one retry is safe.
59661
59842
  - A clip may act through a person's real logged-in account \u2014 outward,
59662
59843
  irreversible, or spending actions (post, order, delete, pay) get the same
59663
59844
  caution as any shared-state change: confirm when intent isn't explicit.