@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.
- package/bundle/manifest.json +11 -11
- package/bundle/parall-browser-pod.js +161 -7
- package/bundle/parall-claude-agent.js +188 -7
- package/bundle/parall-codex-agent.js +188 -7
- package/bundle/parall-daemon.js +693 -232
- package/dist/local-control.d.ts +59 -0
- package/dist/local-control.d.ts.map +1 -0
- package/dist/local-control.js +230 -0
- package/dist/local-profile-control.d.ts +77 -0
- package/dist/local-profile-control.d.ts.map +1 -0
- package/dist/local-profile-control.js +108 -0
- package/dist/supervisor.d.ts +13 -0
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +42 -0
- package/package.json +6 -6
|
@@ -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
|
-
/**
|
|
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
|
|
52727
|
-
|
|
52728
|
-
|
|
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 —
|
|
53550
|
-
*
|
|
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.
|