@parall/parall 1.47.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.
@@ -51649,10 +51649,17 @@ var ENDPOINTS = {
51649
51649
  ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
51650
51650
  ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
51651
51651
  ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
51652
+ ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
51652
51653
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
51653
51654
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
51655
+ ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
51654
51656
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
51655
- CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
51657
+ CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
51658
+ // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
51659
+ // Pinix Hub catalog proxy above is a different, id-less surface)
51660
+ ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
51661
+ ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
51662
+ ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
51656
51663
  };
51657
51664
  var WS_EVENTS = {
51658
51665
  // Client -> Server
@@ -53593,6 +53600,31 @@ var ParallClient = class _ParallClient {
53593
53600
  const resp = await this.request("GET", url);
53594
53601
  return resp.data;
53595
53602
  }
53603
+ // ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
53604
+ /**
53605
+ * List registry clips visible to the org: its own plus public+approved
53606
+ * cross-org entries. This is the surface `installRegistryClip` and clip
53607
+ * connections operate on — NOT the Pinix catalog proxy
53608
+ * ({@link listRegistryClips}), whose entries carry no `crg_` id.
53609
+ */
53610
+ async listOrgRegistryClips(orgId) {
53611
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
53612
+ return resp ?? [];
53613
+ }
53614
+ /**
53615
+ * Install a registry clip into the org (a reference in `clip_installs`, not a
53616
+ * copy). Idempotent: installing an already-installed clip returns the same
53617
+ * `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
53618
+ * not eligible (cross-org requires public + approved).
53619
+ */
53620
+ async installRegistryClip(orgId, clipId) {
53621
+ return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
53622
+ }
53623
+ /** List the org's installed registry clips (full entries). */
53624
+ async listInstalledRegistryClips(orgId) {
53625
+ const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
53626
+ return resp ?? [];
53627
+ }
53596
53628
  // ---- Edge devices ----
53597
53629
  async listEdgeDevices(orgId) {
53598
53630
  return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
@@ -53610,8 +53642,8 @@ var ParallClient = class _ParallClient {
53610
53642
  return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
53611
53643
  }
53612
53644
  /**
53613
- * Delete a hosted Cloud Profile. Hosted only — a BYOC device is removed by
53614
- * uninstalling Parall Clip on that machine (`400 EDGE_PLACEMENT_UNSUPPORTED`).
53645
+ * Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
53646
+ * for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
53615
53647
  *
53616
53648
  * Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
53617
53649
  * call and on every repeat. The device stops being usable immediately (no exec, no
@@ -53621,12 +53653,68 @@ var ParallClient = class _ParallClient {
53621
53653
  async deleteEdgeDevice(orgId, edgeId) {
53622
53654
  return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
53623
53655
  }
53656
+ /**
53657
+ * Remove the interactive human caller's own offline BYOC registration.
53658
+ *
53659
+ * Synchronous and idempotent: a committed removal and a repeat after removal
53660
+ * both resolve with no response body. A live connection returns `EDGE_ONLINE`;
53661
+ * callers must not clear local device identity until this method resolves.
53662
+ */
53663
+ async unregisterEdgeDevice(orgId, edgeId) {
53664
+ await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
53665
+ }
53624
53666
  async getEdgeOnboarding(orgId) {
53625
53667
  return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
53626
53668
  }
53627
53669
  async listEdgeProfiles(orgId, edgeId) {
53628
53670
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
53629
53671
  }
53672
+ /**
53673
+ * Execute a registry clip command on an Edge device.
53674
+ *
53675
+ * A hosted (Cloud Profile) device is reachable ONLY through an explicit
53676
+ * `connection` (id `ccn_…` or alias) — there is no implicit route to an
53677
+ * org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
53678
+ * nothing for the caller's own online device).
53679
+ *
53680
+ * Returns the result envelope on completion (`success` may be false when the
53681
+ * command RAN and failed — `error`/`error_code` describe why). Everything
53682
+ * else throws a typed {@link ApiError}; match on `err.code`:
53683
+ *
53684
+ * Safe to retry (guaranteed nothing was dispatched):
53685
+ * - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
53686
+ * Bounded backoff, same `correlation_id` across the loop.
53687
+ * - `EDGE_BUSY` 409 — the device is executing another request.
53688
+ * - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
53689
+ * - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
53690
+ *
53691
+ * NOT retryable:
53692
+ * - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
53693
+ * MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
53694
+ * automatically: verify the effect first, then decide. The message carries
53695
+ * the request id for audit.
53696
+ * - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
53697
+ * - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
53698
+ * `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
53699
+ * - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
53700
+ * `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
53701
+ * `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
53702
+ */
53703
+ async execEdgeClip(orgId, req) {
53704
+ const t = req.timeout;
53705
+ const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
53706
+ const timeoutMs = serverTimeout + 1e4;
53707
+ try {
53708
+ return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
53709
+ timeoutMs
53710
+ });
53711
+ } catch (err) {
53712
+ if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
53713
+ err.code = err.extras.error_code;
53714
+ }
53715
+ throw err;
53716
+ }
53717
+ }
53630
53718
  // ---- Clip connections ----
53631
53719
  async listClipConnections(orgId, clipId) {
53632
53720
  return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.47.0",
3
+ "version": "1.48.0",
4
4
  "description": "OpenClaw channel plugin for Parall IM",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,8 +16,8 @@
16
16
  "openclaw.plugin.json"
17
17
  ],
18
18
  "dependencies": {
19
- "@parall/agent-core": "1.47.0",
20
- "@parall/sdk": "1.47.0"
19
+ "@parall/sdk": "1.48.0",
20
+ "@parall/agent-core": "1.48.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0",
@@ -25,6 +25,27 @@ parall clip invoke github-tools list-repos '{"org":"acme"}'
25
25
 
26
26
  Results are JSON on stdout; failures print an error.
27
27
 
28
+ ## Execute on an Edge device (registry clips)
29
+
30
+ Registry clips run on an Edge — a member's desktop, or an org-shared cloud
31
+ profile. **Name the target explicitly.** A cloud profile has NO implicit
32
+ route; omitting the target entirely is a desktop-only legacy form that
33
+ reaches just YOUR OWN online desktop device — never a shared cloud profile.
34
+
35
+ ```bash
36
+ parall clip exec <clip> <command> [args] --connection <id|alias> # the normal form
37
+ parall clip exec browser-tools screenshot '{"url":"…"}' --connection cloud-main
38
+ ```
39
+
40
+ - A cloud (hosted) profile is reachable ONLY via `--connection` — the clip
41
+ connection its maintainer bound (`ccn_…` id or alias). That binding IS your
42
+ authorization; without one the server answers `HOSTED_CONNECTION_REQUIRED`
43
+ and the fix is to ask an owner/admin to bind the clip, never to retry.
44
+ - `--edge <edgeId>` targets only a desktop device YOU own.
45
+ - Cold cloud profiles are handled by the CLI: it absorbs `EDGE_ACTIVATING`
46
+ with a bounded wait (~60s) while the profile starts. If the command still
47
+ fails, report the error — do not blind-retry in a loop.
48
+
28
49
  ## Behavior rules
29
50
 
30
51
  - An authorization error (clip not bound to you) is a fail-fast: ask the
@@ -34,6 +55,12 @@ Results are JSON on stdout; failures print an error.
34
55
  - Hosted browser activation is handled by the CLI: it waits (bounded) while a
35
56
  cold hosted browser starts, so if the invoke still fails, report the error —
36
57
  do not blind-retry in a loop.
58
+ - **`OUTCOME_UNKNOWN` is never retryable.** It means the command was
59
+ dispatched and MAY HAVE EXECUTED even though no result came back. Retrying
60
+ could post, order or delete twice. Verify the effect through the system you
61
+ acted on (or tell the human, quoting the request id from the error) before
62
+ ever re-running. `EDGE_BUSY` is the opposite: guaranteed-unexecuted — wait
63
+ briefly, then one retry is safe.
37
64
  - A clip may act through a person's real logged-in account — outward,
38
65
  irreversible, or spending actions (post, order, delete, pay) get the same
39
66
  caution as any shared-state change: confirm when intent isn't explicit.