@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.
@@ -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, path12) {
52680
52701
  return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path12 }, 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.