@parall/parall 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.
package/dist/index.bundle.mjs
CHANGED
|
@@ -51349,6 +51349,8 @@ var ENDPOINTS = {
|
|
|
51349
51349
|
MESSAGE_WATCH: (id) => `${API_BASE}/messages/${id}/watch`,
|
|
51350
51350
|
MESSAGE_WATCHERS: (id) => `${API_BASE}/messages/${id}/watchers`,
|
|
51351
51351
|
MESSAGE_WATCHING: (id) => `${API_BASE}/messages/${id}/watching`,
|
|
51352
|
+
MESSAGE_REACTIONS: (id) => `${API_BASE}/messages/${id}/reactions`,
|
|
51353
|
+
MESSAGE_REACTION: (id, emoji) => `${API_BASE}/messages/${id}/reactions/${encodeURIComponent(emoji)}`,
|
|
51352
51354
|
// Upload (org-scoped)
|
|
51353
51355
|
UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
|
|
51354
51356
|
UPLOAD_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/upload/complete`,
|
|
@@ -51586,11 +51588,13 @@ var ENDPOINTS = {
|
|
|
51586
51588
|
UNREAD: `${API_BASE}/me/unread`,
|
|
51587
51589
|
ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
|
|
51588
51590
|
CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
|
|
51591
|
+
CHAT_READ_ALL: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read-all`,
|
|
51589
51592
|
THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
|
|
51590
51593
|
THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
|
|
51591
51594
|
// References (org-scoped)
|
|
51592
51595
|
REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
|
|
51593
51596
|
REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
|
|
51597
|
+
REFS_OUTBOUND: (orgId) => `${API_BASE}/orgs/${orgId}/refs/outbound`,
|
|
51594
51598
|
REFS_GRAPH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/graph`,
|
|
51595
51599
|
REFS_CHECK: (orgId) => `${API_BASE}/orgs/${orgId}/refs/check`,
|
|
51596
51600
|
// Platform config (agent-scoped, not org-scoped)
|
|
@@ -51649,10 +51653,23 @@ var ENDPOINTS = {
|
|
|
51649
51653
|
ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
|
|
51650
51654
|
ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
|
|
51651
51655
|
ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
|
|
51656
|
+
ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
|
|
51652
51657
|
ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
|
|
51653
51658
|
ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
|
|
51659
|
+
// Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
|
|
51660
|
+
ORG_EDGE_PROFILE_PROXY: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
|
|
51661
|
+
ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
|
|
51662
|
+
// Cloud Edge live viewer command (V1b) — api-server, gated on cap:edge-viewer.
|
|
51663
|
+
// Same request/reply shape as the v2 browser-profile viewer, on the v3 edge
|
|
51664
|
+
// pipe. Additive: does NOT replace BROWSER_PROFILE_VIEWER_COMMAND.
|
|
51665
|
+
ORG_EDGE_VIEWER_COMMAND: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/viewer/command`,
|
|
51654
51666
|
CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
|
|
51655
|
-
CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}
|
|
51667
|
+
CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
|
|
51668
|
+
// Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
|
|
51669
|
+
// Pinix Hub catalog proxy above is a different, id-less surface)
|
|
51670
|
+
ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
|
|
51671
|
+
ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
|
|
51672
|
+
ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
|
|
51656
51673
|
};
|
|
51657
51674
|
var WS_EVENTS = {
|
|
51658
51675
|
// Client -> Server
|
|
@@ -51668,6 +51685,7 @@ var WS_EVENTS = {
|
|
|
51668
51685
|
MESSAGE_PATCH: "message.patch",
|
|
51669
51686
|
MESSAGE_EDIT: "message.edit",
|
|
51670
51687
|
MESSAGE_DELETE: "message.delete",
|
|
51688
|
+
MESSAGE_REACTION_UPDATED: "message.reaction.updated",
|
|
51671
51689
|
TYPING_UPDATE: "typing.update",
|
|
51672
51690
|
CHAT_UPDATE: "chat.update",
|
|
51673
51691
|
CHAT_DELETED: "chat.deleted",
|
|
@@ -51709,6 +51727,7 @@ var WS_EVENTS = {
|
|
|
51709
51727
|
INBOX_UPDATE: "inbox.update",
|
|
51710
51728
|
INBOX_BULK_UPDATE: "inbox.bulk_update",
|
|
51711
51729
|
READ_POSITION_UPDATED: "read_position.updated",
|
|
51730
|
+
THREAD_READ_POSITION_UPDATED: "thread_read_position.updated",
|
|
51712
51731
|
DISPATCH_NEW: "dispatch.new",
|
|
51713
51732
|
DISPATCH_RECEIVED: "dispatch.received",
|
|
51714
51733
|
DISPATCH_RESOLVED: "dispatch.resolved",
|
|
@@ -51894,7 +51913,7 @@ var ParallClient = class _ParallClient {
|
|
|
51894
51913
|
if (qs)
|
|
51895
51914
|
url += `?${qs}`;
|
|
51896
51915
|
}
|
|
51897
|
-
const headers = this.buildHeaders(path9);
|
|
51916
|
+
const headers = this.buildHeaders(path9, opts?.headers);
|
|
51898
51917
|
const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
|
|
51899
51918
|
const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
|
|
51900
51919
|
let res;
|
|
@@ -52300,6 +52319,14 @@ var ParallClient = class _ParallClient {
|
|
|
52300
52319
|
async getMessageReplies(id, params) {
|
|
52301
52320
|
return this.request("GET", ENDPOINTS.MESSAGE_REPLIES(id), void 0, params);
|
|
52302
52321
|
}
|
|
52322
|
+
// ---- Reactions ----
|
|
52323
|
+
async toggleReaction(messageId, emoji) {
|
|
52324
|
+
return this.request("PUT", ENDPOINTS.MESSAGE_REACTION(messageId, emoji));
|
|
52325
|
+
}
|
|
52326
|
+
async listReactions(messageId) {
|
|
52327
|
+
const res = await this.request("GET", ENDPOINTS.MESSAGE_REACTIONS(messageId));
|
|
52328
|
+
return res.reactions;
|
|
52329
|
+
}
|
|
52303
52330
|
// ---- File Upload ----
|
|
52304
52331
|
async getUploadPresignUrl(orgId, req) {
|
|
52305
52332
|
return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
|
|
@@ -52675,6 +52702,15 @@ var ParallClient = class _ParallClient {
|
|
|
52675
52702
|
async browserViewerCommand(orgId, profileId, req, opts) {
|
|
52676
52703
|
return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, opts);
|
|
52677
52704
|
}
|
|
52705
|
+
/**
|
|
52706
|
+
* Drive the Cloud Edge live viewer (V1b, design §6): WebRTC signaling + input +
|
|
52707
|
+
* tab nav for a hosted browser (Cloud Profile). Same request/reply shape as
|
|
52708
|
+
* browserViewerCommand, on the v3 edge pipe; additive — the v2 browser-profile
|
|
52709
|
+
* viewer is unchanged.
|
|
52710
|
+
*/
|
|
52711
|
+
async edgeViewerCommand(orgId, edgeId, req, opts) {
|
|
52712
|
+
return this.request("POST", ENDPOINTS.ORG_EDGE_VIEWER_COMMAND(orgId, edgeId), req, void 0, false, opts);
|
|
52713
|
+
}
|
|
52678
52714
|
async resizeMachine(orgId, machineId, spec) {
|
|
52679
52715
|
return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
|
|
52680
52716
|
}
|
|
@@ -52701,14 +52737,23 @@ var ParallClient = class _ParallClient {
|
|
|
52701
52737
|
}
|
|
52702
52738
|
// Wiki mount/token methods removed — wiki-service handles all wiki endpoints.
|
|
52703
52739
|
// ---- Unread ----
|
|
52704
|
-
async getUnreadCounts(orgId) {
|
|
52740
|
+
async getUnreadCounts(orgId, opts) {
|
|
52705
52741
|
const endpoint = orgId ? ENDPOINTS.ORG_UNREAD(orgId) : ENDPOINTS.UNREAD;
|
|
52706
|
-
const res = await this.request("GET", endpoint
|
|
52742
|
+
const res = await this.request("GET", endpoint, void 0, {
|
|
52743
|
+
include_thread_replies: opts?.includeThreadReplies ? "true" : void 0
|
|
52744
|
+
});
|
|
52707
52745
|
return res.data;
|
|
52708
52746
|
}
|
|
52709
52747
|
async markRead(orgId, chatId, messageId) {
|
|
52710
52748
|
return this.request("POST", ENDPOINTS.CHAT_READ(orgId, chatId), { message_id: messageId });
|
|
52711
52749
|
}
|
|
52750
|
+
/** Mark everything in a chat read: the channel cursor jumps to the latest
|
|
52751
|
+
* top-level message and every thread cursor to its latest reply, in one
|
|
52752
|
+
* idempotent call. The server echoes the same per-cursor WS events the
|
|
52753
|
+
* single-cursor routes emit and auto-clears covered inbox items. */
|
|
52754
|
+
async markAllRead(orgId, chatId) {
|
|
52755
|
+
return this.request("POST", ENDPOINTS.CHAT_READ_ALL(orgId, chatId));
|
|
52756
|
+
}
|
|
52712
52757
|
async getThreadUnread(orgId, chatId, threadRootId) {
|
|
52713
52758
|
return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
|
|
52714
52759
|
}
|
|
@@ -53383,6 +53428,16 @@ var ParallClient = class _ParallClient {
|
|
|
53383
53428
|
async getBacklinks(orgId, params) {
|
|
53384
53429
|
return this.request("GET", ENDPOINTS.REFS_BACKLINKS(orgId), void 0, params);
|
|
53385
53430
|
}
|
|
53431
|
+
/**
|
|
53432
|
+
* Outbound prll:// refs authored in a set of sources, as raw ref_links rows
|
|
53433
|
+
* (dedupe/group client-side). Pass `{ thread_root_id }` to list a whole
|
|
53434
|
+
* thread's refs (root + all replies, resolved server-side — the client's
|
|
53435
|
+
* reply window may be partial), or `{ source_type, source_ids }` for
|
|
53436
|
+
* explicit sources (max 500; v1 accepts only message sources).
|
|
53437
|
+
*/
|
|
53438
|
+
async listOutboundRefs(orgId, req) {
|
|
53439
|
+
return this.request("POST", ENDPOINTS.REFS_OUTBOUND(orgId), req);
|
|
53440
|
+
}
|
|
53386
53441
|
/**
|
|
53387
53442
|
* Bounded multi-hop walk of the prll:// reference graph around `uri`. `uri`
|
|
53388
53443
|
* must be an entity-level prll:// URI — a refined URI (path/query/fragment) is
|
|
@@ -53593,6 +53648,31 @@ var ParallClient = class _ParallClient {
|
|
|
53593
53648
|
const resp = await this.request("GET", url);
|
|
53594
53649
|
return resp.data;
|
|
53595
53650
|
}
|
|
53651
|
+
// ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
|
|
53652
|
+
/**
|
|
53653
|
+
* List registry clips visible to the org: its own plus public+approved
|
|
53654
|
+
* cross-org entries. This is the surface `installRegistryClip` and clip
|
|
53655
|
+
* connections operate on — NOT the Pinix catalog proxy
|
|
53656
|
+
* ({@link listRegistryClips}), whose entries carry no `crg_` id.
|
|
53657
|
+
*/
|
|
53658
|
+
async listOrgRegistryClips(orgId) {
|
|
53659
|
+
const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
|
|
53660
|
+
return resp ?? [];
|
|
53661
|
+
}
|
|
53662
|
+
/**
|
|
53663
|
+
* Install a registry clip into the org (a reference in `clip_installs`, not a
|
|
53664
|
+
* copy). Idempotent: installing an already-installed clip returns the same
|
|
53665
|
+
* `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
|
|
53666
|
+
* not eligible (cross-org requires public + approved).
|
|
53667
|
+
*/
|
|
53668
|
+
async installRegistryClip(orgId, clipId) {
|
|
53669
|
+
return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
|
|
53670
|
+
}
|
|
53671
|
+
/** List the org's installed registry clips (full entries). */
|
|
53672
|
+
async listInstalledRegistryClips(orgId) {
|
|
53673
|
+
const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
|
|
53674
|
+
return resp ?? [];
|
|
53675
|
+
}
|
|
53596
53676
|
// ---- Edge devices ----
|
|
53597
53677
|
async listEdgeDevices(orgId) {
|
|
53598
53678
|
return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
|
|
@@ -53610,8 +53690,8 @@ var ParallClient = class _ParallClient {
|
|
|
53610
53690
|
return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
|
|
53611
53691
|
}
|
|
53612
53692
|
/**
|
|
53613
|
-
* Delete a hosted Cloud Profile. Hosted only —
|
|
53614
|
-
*
|
|
53693
|
+
* Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
|
|
53694
|
+
* for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
|
|
53615
53695
|
*
|
|
53616
53696
|
* Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
|
|
53617
53697
|
* call and on every repeat. The device stops being usable immediately (no exec, no
|
|
@@ -53621,12 +53701,105 @@ var ParallClient = class _ParallClient {
|
|
|
53621
53701
|
async deleteEdgeDevice(orgId, edgeId) {
|
|
53622
53702
|
return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
|
|
53623
53703
|
}
|
|
53704
|
+
/**
|
|
53705
|
+
* Remove the interactive human caller's own offline BYOC registration.
|
|
53706
|
+
*
|
|
53707
|
+
* Synchronous and idempotent: a committed removal and a repeat after removal
|
|
53708
|
+
* both resolve with no response body. A live connection returns `EDGE_ONLINE`;
|
|
53709
|
+
* callers must not clear local device identity until this method resolves.
|
|
53710
|
+
*/
|
|
53711
|
+
async unregisterEdgeDevice(orgId, edgeId) {
|
|
53712
|
+
await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
|
|
53713
|
+
}
|
|
53624
53714
|
async getEdgeOnboarding(orgId) {
|
|
53625
53715
|
return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
|
|
53626
53716
|
}
|
|
53627
53717
|
async listEdgeProfiles(orgId, edgeId) {
|
|
53628
53718
|
return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
|
|
53629
53719
|
}
|
|
53720
|
+
/**
|
|
53721
|
+
* Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
|
|
53722
|
+
* human maintainer or org admin). Sanitized — the password never comes back.
|
|
53723
|
+
* Typed errors: `EDGE_NOT_HOSTED` (BYOC device), `PROXY_CONFIG_CORRUPT` /
|
|
53724
|
+
* validation codes as 422 when a stored config no longer passes current rules.
|
|
53725
|
+
* `can_mutate` and `lease_status` are the authoritative idle gate; device
|
|
53726
|
+
* list status is not a substitute.
|
|
53727
|
+
*/
|
|
53728
|
+
async getEdgeProfileProxy(orgId, edgeId, profileName) {
|
|
53729
|
+
return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName));
|
|
53730
|
+
}
|
|
53731
|
+
/**
|
|
53732
|
+
* Set/replace the profile's egress proxy (full triple every time) — IDLE
|
|
53733
|
+
* ONLY: while the profile's hosted browser is running (a viewer session is
|
|
53734
|
+
* open or a pod is otherwise live) the server answers 409
|
|
53735
|
+
* `EDGE_PROFILE_IN_USE`; close the viewer, wait for idle scale-to-zero, and
|
|
53736
|
+
* retry. The next cold start uses the new egress; browser login state is
|
|
53737
|
+
* preserved across it. Other typed errors: the validation vocabulary
|
|
53738
|
+
* (`INVALID_PROXY_SERVER`, `PROXY_AUTH_INCOMPLETE`,
|
|
53739
|
+
* `PROXY_SERVER_FORBIDDEN_TARGET`, …), `EDGE_DELETING` (409), and
|
|
53740
|
+
* `SECRETBOX_UNCONFIGURED` (503 — server cannot store credentials safely),
|
|
53741
|
+
* and `EDGE_PROFILE_PROXY_STALE` (409 — expectedVersion lost a tab race).
|
|
53742
|
+
*/
|
|
53743
|
+
async setEdgeProfileProxy(orgId, edgeId, profileName, req, expectedVersion) {
|
|
53744
|
+
return this.request("PUT", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), req, void 0, false, {
|
|
53745
|
+
headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
|
|
53746
|
+
});
|
|
53747
|
+
}
|
|
53748
|
+
/**
|
|
53749
|
+
* Clear the profile's egress proxy; the next pod start egresses directly.
|
|
53750
|
+
* Idle-only like set — 409 `EDGE_PROFILE_IN_USE` while the browser is live.
|
|
53751
|
+
*/
|
|
53752
|
+
async clearEdgeProfileProxy(orgId, edgeId, profileName, expectedVersion) {
|
|
53753
|
+
return this.request("DELETE", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), void 0, void 0, false, {
|
|
53754
|
+
headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
|
|
53755
|
+
});
|
|
53756
|
+
}
|
|
53757
|
+
/**
|
|
53758
|
+
* Execute a registry clip command on an Edge device.
|
|
53759
|
+
*
|
|
53760
|
+
* A hosted (Cloud Profile) device is reachable ONLY through an explicit
|
|
53761
|
+
* `connection` (id `ccn_…` or alias) — there is no implicit route to an
|
|
53762
|
+
* org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
|
|
53763
|
+
* nothing for the caller's own online device).
|
|
53764
|
+
*
|
|
53765
|
+
* Returns the result envelope on completion (`success` may be false when the
|
|
53766
|
+
* command RAN and failed — `error`/`error_code` describe why). Everything
|
|
53767
|
+
* else throws a typed {@link ApiError}; match on `err.code`:
|
|
53768
|
+
*
|
|
53769
|
+
* Safe to retry (guaranteed nothing was dispatched):
|
|
53770
|
+
* - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
|
|
53771
|
+
* Bounded backoff, same `correlation_id` across the loop.
|
|
53772
|
+
* - `EDGE_BUSY` 409 — the device is executing another request.
|
|
53773
|
+
* - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
|
|
53774
|
+
* - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
|
|
53775
|
+
*
|
|
53776
|
+
* NOT retryable:
|
|
53777
|
+
* - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
|
|
53778
|
+
* MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
|
|
53779
|
+
* automatically: verify the effect first, then decide. The message carries
|
|
53780
|
+
* the request id for audit.
|
|
53781
|
+
* - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
|
|
53782
|
+
* - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
|
|
53783
|
+
* `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
|
|
53784
|
+
* - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
|
|
53785
|
+
* `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
|
|
53786
|
+
* `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
|
|
53787
|
+
*/
|
|
53788
|
+
async execEdgeClip(orgId, req) {
|
|
53789
|
+
const t = req.timeout;
|
|
53790
|
+
const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
|
|
53791
|
+
const timeoutMs = serverTimeout + 1e4;
|
|
53792
|
+
try {
|
|
53793
|
+
return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
|
|
53794
|
+
timeoutMs
|
|
53795
|
+
});
|
|
53796
|
+
} catch (err) {
|
|
53797
|
+
if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
|
|
53798
|
+
err.code = err.extras.error_code;
|
|
53799
|
+
}
|
|
53800
|
+
throw err;
|
|
53801
|
+
}
|
|
53802
|
+
}
|
|
53630
53803
|
// ---- Clip connections ----
|
|
53631
53804
|
async listClipConnections(orgId, clipId) {
|
|
53632
53805
|
return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
|
|
@@ -53649,6 +53822,8 @@ var ApiError = class extends Error {
|
|
|
53649
53822
|
status;
|
|
53650
53823
|
code;
|
|
53651
53824
|
extras;
|
|
53825
|
+
/** Retry-After delta seconds when the server supplies one. */
|
|
53826
|
+
retryAfterSeconds;
|
|
53652
53827
|
/** Attempted action (authorization denials) — e.g. "chat.add_member". */
|
|
53653
53828
|
action;
|
|
53654
53829
|
/** Target resource URI that was evaluated — e.g. "prll://cht_…". */
|
|
@@ -53668,6 +53843,9 @@ function buildApiError(res, rawErrorBody) {
|
|
|
53668
53843
|
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);
|
|
53669
53844
|
const errCode = (typeof errorObj?.code === "string" ? errorObj.code : void 0) ?? (typeof errorBody.code === "string" ? errorBody.code : void 0);
|
|
53670
53845
|
const apiError = new ApiError(res.status, errMsg ?? res.statusText, errCode);
|
|
53846
|
+
const retryAfter = Number(res.headers?.get("Retry-After"));
|
|
53847
|
+
if (Number.isFinite(retryAfter) && retryAfter > 0)
|
|
53848
|
+
apiError.retryAfterSeconds = retryAfter;
|
|
53671
53849
|
const anchors = errorObj ?? errorBody;
|
|
53672
53850
|
if (typeof anchors.action === "string")
|
|
53673
53851
|
apiError.action = anchors.action;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.49.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.
|
|
20
|
-
"@parall/sdk": "1.
|
|
19
|
+
"@parall/agent-core": "1.49.0",
|
|
20
|
+
"@parall/sdk": "1.49.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.
|
|
@@ -39,7 +39,7 @@ parall tasks list --assignee-id prll://usr_xxx # first page only (default 20)
|
|
|
39
39
|
parall tasks subtasks prll://tsk_xxx # children of a single parent task
|
|
40
40
|
|
|
41
41
|
# Create a task (add --parent-id to make it a SUBTASK of another task)
|
|
42
|
-
parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--parent-id prll://tsk_xxx] [--project-id prll://prj_xxx] [--due-date 2026-08-01]
|
|
42
|
+
parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--parent-id prll://tsk_xxx] [--project-id prll://prj_xxx] [--planned-start 2026-07-20] [--due-date 2026-08-01]
|
|
43
43
|
|
|
44
44
|
# Update task status — add --placement end so the task lands at the end of
|
|
45
45
|
# its NEW status column (a bare --status keeps the old column's sort_order)
|
|
@@ -50,6 +50,12 @@ parall tasks update prll://tsk_xxx --status done --placement end
|
|
|
50
50
|
parall tasks update prll://tsk_xxx --due-date 2026-08-01
|
|
51
51
|
parall tasks update prll://tsk_xxx --due-date none
|
|
52
52
|
|
|
53
|
+
# Planned start — same grammar as --due-date; must be on or before the due
|
|
54
|
+
# date when both are set. This is the planned schedule's left-edge date,
|
|
55
|
+
# NOT when work actually began (that stays on lifecycle timestamps)
|
|
56
|
+
parall tasks update prll://tsk_xxx --planned-start 2026-07-20
|
|
57
|
+
parall tasks update prll://tsk_xxx --planned-start none
|
|
58
|
+
|
|
53
59
|
# Move a task to the end of its status column
|
|
54
60
|
parall tasks update prll://tsk_xxx --placement end
|
|
55
61
|
|