@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.
- package/dist/index.bundle.mjs +91 -3
- package/package.json +3 -3
- package/skills/parall-clips/SKILL.md +27 -0
package/dist/index.bundle.mjs
CHANGED
|
@@ -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 —
|
|
53614
|
-
*
|
|
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.
|
|
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/
|
|
20
|
-
"@parall/
|
|
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.
|