@parall/daemon 1.55.4 → 1.56.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.
@@ -51481,6 +51481,12 @@ function isForwardedMessageBody(body) {
51481
51481
  function sanitizeMeta(value) {
51482
51482
  return value.replace(/[\r\n]+/g, " ").replace(/[[\]|]/g, " ").trim();
51483
51483
  }
51484
+ function formatApprovalDecisionReason(status, reason) {
51485
+ const normalized = reason?.trim();
51486
+ if (status !== "rejected" || !normalized)
51487
+ return "";
51488
+ return `Reason (JSON): ${JSON.stringify(normalized)}`;
51489
+ }
51484
51490
  function buildEventBody(event) {
51485
51491
  const lines = [];
51486
51492
  if (event.type === "message") {
@@ -51498,6 +51504,8 @@ function buildEventBody(event) {
51498
51504
  ].filter(Boolean).join(" | ");
51499
51505
  lines.push(`[Thread: ${threadMeta}]`);
51500
51506
  }
51507
+ if (event.deliveryReason)
51508
+ lines.push(`[Delivery: ${sanitizeMeta(event.deliveryReason)}]`);
51501
51509
  if (event.unreadCount != null && event.unreadCount > 1) {
51502
51510
  const countStr = event.unreadCount >= 1e3 ? "999+" : String(event.unreadCount);
51503
51511
  const sinceStr = event.unreadSince ? ` | since: prll://${event.unreadSince}` : "";
@@ -51701,6 +51709,16 @@ function browserViewerRequestOptions(command, opts) {
51701
51709
  };
51702
51710
  }
51703
51711
 
51712
+ // ts/sdk/dist/attachment-endpoints.js
51713
+ function attachmentEndpoints(apiBase) {
51714
+ return {
51715
+ UPLOAD_PRESIGN: (orgId) => `${apiBase}/orgs/${orgId}/upload/presign`,
51716
+ UPLOAD_COMPLETE: (orgId) => `${apiBase}/orgs/${orgId}/upload/complete`,
51717
+ UPLOAD_ABORT: (orgId) => `${apiBase}/orgs/${orgId}/upload/abort`,
51718
+ FILE: (id) => `${apiBase}/files/${id}`
51719
+ };
51720
+ }
51721
+
51704
51722
  // ts/sdk/dist/constants.js
51705
51723
  var API_BASE = "/api/v1";
51706
51724
  var WIKI_BASE = "/wiki/v1";
@@ -51773,9 +51791,7 @@ var ENDPOINTS = {
51773
51791
  MESSAGE_REACTIONS: (id) => `${API_BASE}/messages/${id}/reactions`,
51774
51792
  MESSAGE_REACTION: (id, emoji) => `${API_BASE}/messages/${id}/reactions/${encodeURIComponent(emoji)}`,
51775
51793
  // Upload (org-scoped)
51776
- UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
51777
- UPLOAD_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/upload/complete`,
51778
- FILE: (id) => `${API_BASE}/files/${id}`,
51794
+ ...attachmentEndpoints(API_BASE),
51779
51795
  // Approval requests (org-scoped)
51780
51796
  APPROVAL_REQUESTS: (orgId) => `${API_BASE}/orgs/${orgId}/approval-requests`,
51781
51797
  // Approvals (global)
@@ -51861,6 +51877,7 @@ var ENDPOINTS = {
51861
51877
  TASKS: (orgId) => `${API_BASE}/orgs/${orgId}/tasks`,
51862
51878
  TASK_SUBTASK_SUMMARY: (orgId) => `${API_BASE}/orgs/${orgId}/tasks/subtask-summary`,
51863
51879
  TASK: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}`,
51880
+ TASK_MOVE: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}/move`,
51864
51881
  TASK_ARCHIVE: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}/archive`,
51865
51882
  TASK_RESTORE: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}/restore`,
51866
51883
  TASK_WATCH: (orgId, taskId) => `${API_BASE}/orgs/${orgId}/tasks/${taskId}/watch`,
@@ -51956,6 +51973,8 @@ var ENDPOINTS = {
51956
51973
  // backend router so `deleted` isn't captured as a {wikiId}; the SDK builder
51957
51974
  // is just a string.
51958
51975
  WIKIS_DELETED: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis/deleted`,
51976
+ // Org-wide changeset listing across readable wikis (Working on tab).
51977
+ WIKI_ORG_CHANGESETS: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wiki-changesets`,
51959
51978
  // Detail URL — also reused for DELETE (soft-delete) and `${WIKI}/restore`.
51960
51979
  WIKI: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
51961
51980
  WIKI_RESTORE: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restore`,
@@ -51985,6 +52004,12 @@ var ENDPOINTS = {
51985
52004
  // Wiki Path Restrictions (AFCS narrowing ACL — private subtrees)
51986
52005
  WIKI_RESTRICTIONS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions`,
51987
52006
  WIKI_RESTRICTION: (orgId, wikiId, restrictionId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/restrictions/${restrictionId}`,
52007
+ WIKI_ACCESS_POLICY: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-policy`,
52008
+ WIKI_ACCESS_POLICY_MEMBERS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-policy/members`,
52009
+ WIKI_MEMBERSHIP_SELF: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/membership/self`,
52010
+ // Library-level star (self-scoped bookmark; POST = star, DELETE = unstar).
52011
+ WIKI_STARS_SELF: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/stars/self`,
52012
+ WIKI_MEMBERS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/members`,
51988
52013
  WIKI_ACCESS_STATUS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-status`,
51989
52014
  WIKI_ACCESS_REQUESTS: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}/access-requests`,
51990
52015
  // Wiki History (commits, file commits, blame)
@@ -52105,6 +52130,21 @@ var ENDPOINTS = {
52105
52130
  ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
52106
52131
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
52107
52132
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
52133
+ ORG_EDGE_PROFILE_OPERATIONS: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profile-operations`,
52134
+ ORG_EDGE_PROFILE_OPERATION: (orgId, edgeId, operationId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profile-operations/${operationId}`,
52135
+ ORG_EDGE_PROFILE_OPERATION_CONFIRM: (orgId, edgeId, operationId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profile-operations/${operationId}/confirm`,
52136
+ ORG_BROWSER_ALIASES: (orgId) => `/api/v1/orgs/${orgId}/browser-aliases`,
52137
+ ORG_BROWSER_ALIAS: (orgId, aliasId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}`,
52138
+ ORG_BROWSER_ALIAS_READINESS_CHECKS: (orgId, aliasId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}/readiness-checks`,
52139
+ ORG_BROWSER_ALIAS_READINESS_CHECK: (orgId, aliasId, checkId) => `/api/v1/orgs/${orgId}/browser-aliases/${aliasId}/readiness-checks/${checkId}`,
52140
+ ORG_API_KEY_BROWSER_ALIAS_GRANTS: (orgId, keyId) => `/api/v1/orgs/${orgId}/api-keys/${keyId}/browser-alias-grants`,
52141
+ ORG_API_KEY_BROWSER_ALIAS_GRANT: (orgId, keyId, aliasId) => `/api/v1/orgs/${orgId}/api-keys/${keyId}/browser-alias-grants/${aliasId}`,
52142
+ ORG_MANAGED_ALIASES: (orgId) => `/api/v1/orgs/${orgId}/aliases`,
52143
+ ORG_MANAGED_ALIAS: (orgId, aliasName) => `/api/v1/orgs/${orgId}/aliases/${encodeURIComponent(aliasName)}`,
52144
+ ORG_BROWSER_ALIAS_EXECUTIONS: (orgId) => `/api/v1/orgs/${orgId}/executions`,
52145
+ ORG_BROWSER_ALIAS_EXECUTION: (orgId, requestId) => `/api/v1/orgs/${orgId}/executions/${encodeURIComponent(requestId)}`,
52146
+ ORG_BROWSER_USE_OPERATIONS: (orgId) => `/api/v1/orgs/${orgId}/browser-use/operations`,
52147
+ ORG_BROWSER_USE_OPERATION: (orgId, operationId) => `/api/v1/orgs/${orgId}/browser-use/operations/${encodeURIComponent(operationId)}`,
52108
52148
  // Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
52109
52149
  ORG_EDGE_PROFILE_PROXY: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
52110
52150
  // Per-profile one-shot cookie seed (hosted Cloud Profiles; manager-only,
@@ -52119,6 +52159,8 @@ var ENDPOINTS = {
52119
52159
  CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
52120
52160
  // Clip registry (v3, org-scoped, served by api-server — `crg_` entries)
52121
52161
  ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
52162
+ ORG_CLIP_REGISTRY_RESOLVE: (orgId) => `/api/v1/orgs/${orgId}/clip-registry/resolve`,
52163
+ ORG_CLIP_REGISTRY_SEARCH: (orgId) => `/api/v1/orgs/${orgId}/clip-registry/search`,
52122
52164
  ORG_CLIP_REGISTRY_CLIP: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}`,
52123
52165
  ORG_CLIP_REGISTRY_PUBLISH: (orgId) => `/api/v1/orgs/${orgId}/clip-registry/publish`,
52124
52166
  ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
@@ -52252,6 +52294,15 @@ var ProjectTaskClient = class {
52252
52294
  async deleteTask(orgId, taskId, opts) {
52253
52295
  return this.request("DELETE", ENDPOINTS.TASK(orgId, taskId), void 0, opts?.force ? { force: "true" } : void 0);
52254
52296
  }
52297
+ /**
52298
+ * Moves a task and its whole subtree into another project (renumbering it
52299
+ * there; old identifiers stay resolvable as aliases). The caller needs
52300
+ * update access on the task (source project membership) and read access to
52301
+ * the target project.
52302
+ */
52303
+ async moveTask(orgId, taskId, data) {
52304
+ return this.request("POST", ENDPOINTS.TASK_MOVE(orgId, taskId), data);
52305
+ }
52255
52306
  async archiveTask(orgId, taskId) {
52256
52307
  return this.request("POST", ENDPOINTS.TASK_ARCHIVE(orgId, taskId));
52257
52308
  }
@@ -52455,8 +52506,44 @@ var WechatClient = class extends TaskLabelClient {
52455
52506
  }
52456
52507
  };
52457
52508
 
52509
+ // ts/sdk/dist/attachment-client.js
52510
+ var COMPLETION_RETRY_DELAYS_MS = [250, 750];
52511
+ function isRetryableCompletionError(error) {
52512
+ if (!error || typeof error !== "object" || !("status" in error))
52513
+ return false;
52514
+ const status = error.status;
52515
+ return status === 0 || typeof status === "number" && status >= 500;
52516
+ }
52517
+ var AttachmentClient = class extends WechatClient {
52518
+ async getUploadPresignUrl(orgId, req) {
52519
+ return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
52520
+ }
52521
+ async completeUpload(orgId, attachmentId, parts) {
52522
+ const body = {
52523
+ attachment_id: attachmentId,
52524
+ parts
52525
+ };
52526
+ for (let attempt = 0; ; attempt += 1) {
52527
+ try {
52528
+ return await this.request("POST", ENDPOINTS.UPLOAD_COMPLETE(orgId), body);
52529
+ } catch (error) {
52530
+ const delay = COMPLETION_RETRY_DELAYS_MS[attempt];
52531
+ if (delay === void 0 || !isRetryableCompletionError(error))
52532
+ throw error;
52533
+ await new Promise((resolve3) => setTimeout(resolve3, delay));
52534
+ }
52535
+ }
52536
+ }
52537
+ async abortUpload(orgId, attachmentId) {
52538
+ return this.request("POST", ENDPOINTS.UPLOAD_ABORT(orgId), { attachment_id: attachmentId });
52539
+ }
52540
+ async getFileUrl(id, opts) {
52541
+ return this.request("GET", ENDPOINTS.FILE(id), void 0, opts?.download ? { download: true } : void 0);
52542
+ }
52543
+ };
52544
+
52458
52545
  // ts/sdk/dist/client.js
52459
- var ParallClient = class _ParallClient extends WechatClient {
52546
+ var ParallClient = class _ParallClient extends AttachmentClient {
52460
52547
  baseUrl;
52461
52548
  wikiBaseUrl;
52462
52549
  token;
@@ -53103,16 +53190,6 @@ var ParallClient = class _ParallClient extends WechatClient {
53103
53190
  const res = await this.request("GET", ENDPOINTS.MESSAGE_REACTIONS(messageId));
53104
53191
  return res.reactions;
53105
53192
  }
53106
- // ---- File Upload ----
53107
- async getUploadPresignUrl(orgId, req) {
53108
- return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
53109
- }
53110
- async completeUpload(orgId, attachmentId) {
53111
- return this.request("POST", ENDPOINTS.UPLOAD_COMPLETE(orgId), { attachment_id: attachmentId });
53112
- }
53113
- async getFileUrl(id, opts) {
53114
- return this.request("GET", ENDPOINTS.FILE(id), void 0, opts?.download ? { download: true } : void 0);
53115
- }
53116
53193
  // ---- Approvals ----
53117
53194
  async getApproval(id) {
53118
53195
  return this.request("GET", ENDPOINTS.APPROVAL(id));
@@ -53120,8 +53197,14 @@ var ParallClient = class _ParallClient extends WechatClient {
53120
53197
  async requestApproval(orgId, req) {
53121
53198
  return this.request("POST", ENDPOINTS.APPROVAL_REQUESTS(orgId), req);
53122
53199
  }
53123
- async decideApproval(id, decision) {
53124
- return this.request("POST", ENDPOINTS.APPROVAL_DECIDE(id), { decision });
53200
+ async decideApproval(id, decision, reason) {
53201
+ if (decision === "approve" && reason?.trim()) {
53202
+ throw new ApiError(400, "Approval reason is only allowed for rejection decisions", "INVALID_DECISION_REASON");
53203
+ }
53204
+ return this.request("POST", ENDPOINTS.APPROVAL_DECIDE(id), {
53205
+ decision,
53206
+ ...decision === "reject" && reason !== void 0 ? { reason } : {}
53207
+ });
53125
53208
  }
53126
53209
  async cancelApproval(id) {
53127
53210
  return this.request("POST", ENDPOINTS.APPROVAL_CANCEL(id));
@@ -53954,6 +54037,17 @@ var ParallClient = class _ParallClient extends WechatClient {
53954
54037
  const res = await this.request("GET", ENDPOINTS.WIKI_CHANGESETS(orgId, wikiId));
53955
54038
  return res.data.map(normalizeWikiChangeset);
53956
54039
  }
54040
+ /** Org-wide changeset listing across every wiki the caller can read.
54041
+ * Server default (no `status`) is the pending set: proposed,
54042
+ * approval_pending, approved. */
54043
+ async getOrgWikiChangesets(orgId, opts) {
54044
+ const params = new URLSearchParams();
54045
+ for (const s of opts?.status ?? [])
54046
+ params.append("status", s);
54047
+ const qs = params.toString();
54048
+ const res = await this.request("GET", `${ENDPOINTS.WIKI_ORG_CHANGESETS(orgId)}${qs ? `?${qs}` : ""}`);
54049
+ return (res.data ?? []).map(normalizeWikiChangeset);
54050
+ }
53957
54051
  async getWikiChangeset(orgId, wikiId, changesetId) {
53958
54052
  return normalizeWikiChangeset(await this.request("GET", ENDPOINTS.WIKI_CHANGESET(orgId, wikiId, changesetId)));
53959
54053
  }
@@ -54042,6 +54136,46 @@ var ParallClient = class _ParallClient extends WechatClient {
54042
54136
  async getWikiAccessStatus(orgId, wikiId, path11) {
54043
54137
  return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path11 ? { path: path11 } : void 0);
54044
54138
  }
54139
+ // ---- Wiki membership projection (who-can-access, invites, join/leave) ----
54140
+ async getWikiAccessPolicy(orgId, wikiId, path11 = "") {
54141
+ return this.request("GET", ENDPOINTS.WIKI_ACCESS_POLICY(orgId, wikiId), void 0, path11 ? { path: path11 } : void 0);
54142
+ }
54143
+ async putWikiAccessPolicy(orgId, wikiId, policy) {
54144
+ return this.request("PUT", ENDPOINTS.WIKI_ACCESS_POLICY(orgId, wikiId), policy);
54145
+ }
54146
+ /** Add-only invite (viewer/editor); allowed for managers, and for editors
54147
+ * when the library enables editors_can_invite. */
54148
+ async addWikiMember(orgId, wikiId, subject, role) {
54149
+ await this.request("POST", ENDPOINTS.WIKI_ACCESS_POLICY_MEMBERS(orgId, wikiId), {
54150
+ subject,
54151
+ role
54152
+ });
54153
+ }
54154
+ /** Join a PUBLIC library as an explicit member (lands at the library's
54155
+ * default role). Restricted libraries answer 409 JOIN_REQUIRES_REQUEST —
54156
+ * go through createWikiAccessRequest instead. */
54157
+ async joinWiki(orgId, wikiId) {
54158
+ await this.request("POST", ENDPOINTS.WIKI_MEMBERSHIP_SELF(orgId, wikiId));
54159
+ }
54160
+ /** Remove the caller's explicit membership (team-granted membership stays). */
54161
+ async leaveWiki(orgId, wikiId) {
54162
+ await this.request("DELETE", ENDPOINTS.WIKI_MEMBERSHIP_SELF(orgId, wikiId));
54163
+ }
54164
+ /** Star a library for the caller (sidebar Starred group). Idempotent —
54165
+ * re-starring is a 204 no-op. Requires read access; hidden private
54166
+ * libraries answer 404 like absent IDs. */
54167
+ async starWiki(orgId, wikiId) {
54168
+ await this.request("POST", ENDPOINTS.WIKI_STARS_SELF(orgId, wikiId));
54169
+ }
54170
+ /** Remove the caller's star. Idempotent — unstarring a never-starred
54171
+ * library is a 204 no-op. */
54172
+ async unstarWiki(orgId, wikiId) {
54173
+ await this.request("DELETE", ENDPOINTS.WIKI_STARS_SELF(orgId, wikiId));
54174
+ }
54175
+ async getWikiMembers(orgId, wikiId) {
54176
+ const res = await this.request("GET", ENDPOINTS.WIKI_MEMBERS(orgId, wikiId));
54177
+ return res.data ?? [];
54178
+ }
54045
54179
  async createWikiAccessRequest(orgId, wikiId, data) {
54046
54180
  await this.request("POST", ENDPOINTS.WIKI_ACCESS_REQUESTS(orgId, wikiId), data);
54047
54181
  }
@@ -54391,6 +54525,31 @@ var ParallClient = class _ParallClient extends WechatClient {
54391
54525
  const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
54392
54526
  return resp ?? [];
54393
54527
  }
54528
+ /**
54529
+ * Resolve an exact `<publisher org, name>` reference to its registry entry —
54530
+ * the npm-style point read. Deliberately independent of catalog size: no
54531
+ * Search, no pagination, same read-visibility boundary as `getRegistryClip`
54532
+ * (cross-org requires public + approved). 404 `NOT_FOUND` when the publisher
54533
+ * org has no visible clip of that exact name.
54534
+ */
54535
+ async resolveRegistryClip(orgId, publisherOrgId, name) {
54536
+ const params = new URLSearchParams({ org_id: publisherOrgId, name });
54537
+ return this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY_RESOLVE(orgId)}?${params}`);
54538
+ }
54539
+ /**
54540
+ * Server-side fuzzy discovery over the visible registry (name/description
54541
+ * substring match), paginated. The discovery verb: rows carry the `crg_` id
54542
+ * that {@link installRegistryClip} takes.
54543
+ */
54544
+ async searchOrgRegistryClips(orgId, query, opts) {
54545
+ const params = new URLSearchParams({ q: query });
54546
+ if (opts?.limit !== void 0)
54547
+ params.set("limit", String(opts.limit));
54548
+ if (opts?.offset !== void 0)
54549
+ params.set("offset", String(opts.offset));
54550
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY_SEARCH(orgId)}?${params}`);
54551
+ return resp ?? [];
54552
+ }
54394
54553
  /**
54395
54554
  * Install a registry clip into the org (a reference in `clip_installs`, not a
54396
54555
  * copy). Idempotent: installing an already-installed clip returns the same
@@ -54504,6 +54663,86 @@ var ParallClient = class _ParallClient extends WechatClient {
54504
54663
  async listEdgeProfiles(orgId, edgeId) {
54505
54664
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
54506
54665
  }
54666
+ /** Start one durable Local BYOC Profile operation. Network-unknown callers
54667
+ * must retry with the same key or recover by operation id; a different body
54668
+ * under the same key is rejected. */
54669
+ async createEdgeProfileOperation(orgId, edgeId, request3, idempotencyKey) {
54670
+ return this.request("POST", ENDPOINTS.ORG_EDGE_PROFILE_OPERATIONS(orgId, edgeId), request3, void 0, false, { headers: { "Idempotency-Key": idempotencyKey } });
54671
+ }
54672
+ /** Strong-confirm the exact durable Delete impact. A changed impact returns
54673
+ * PROFILE_DELETE_IMPACT_CHANGED with a replacement receipt in
54674
+ * `ApiError.extras.details.operation`. */
54675
+ async confirmEdgeProfileOperation(orgId, edgeId, operationId, request3) {
54676
+ return this.request("POST", ENDPOINTS.ORG_EDGE_PROFILE_OPERATION_CONFIRM(orgId, edgeId, operationId), request3);
54677
+ }
54678
+ /** Sole read/recovery surface. The server may reconcile an already durable
54679
+ * dispatch/finalization while returning this receipt. */
54680
+ async getEdgeProfileOperation(orgId, edgeId, operationId) {
54681
+ return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_OPERATION(orgId, edgeId, operationId));
54682
+ }
54683
+ /** Create and atomically materialize one Local BYOC Browser Alias. A replay
54684
+ * with the same idempotency key and body returns the original stable ccn_. */
54685
+ async createBrowserAlias(orgId, request3) {
54686
+ return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIASES(orgId), request3);
54687
+ }
54688
+ async listBrowserAliases(orgId) {
54689
+ return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIASES(orgId));
54690
+ }
54691
+ async getBrowserAlias(orgId, aliasId) {
54692
+ return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId));
54693
+ }
54694
+ async renameBrowserAlias(orgId, aliasId, request3) {
54695
+ return this.request("PATCH", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId), request3);
54696
+ }
54697
+ async deleteBrowserAlias(orgId, aliasId, request3) {
54698
+ return this.request("DELETE", ENDPOINTS.ORG_BROWSER_ALIAS(orgId, aliasId), request3);
54699
+ }
54700
+ /** Start one durable readiness check. The key is carried as the standard
54701
+ * Idempotency-Key header; the request body is intentionally empty. */
54702
+ async createBrowserAliasReadinessCheck(orgId, aliasId, request3) {
54703
+ return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIAS_READINESS_CHECKS(orgId, aliasId), void 0, void 0, false, { headers: { "Idempotency-Key": request3.idempotency_key } });
54704
+ }
54705
+ /** Sole durable recovery surface for one readiness request. */
54706
+ async getBrowserAliasReadinessCheck(orgId, aliasId, checkId) {
54707
+ return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS_READINESS_CHECK(orgId, aliasId, checkId));
54708
+ }
54709
+ /** Organization Owner view. Hashes, reviewed snapshots and deltas are
54710
+ * intentionally available only on this human-JWT management surface. */
54711
+ async listBrowserAliasGrants(orgId, keyId) {
54712
+ return this.request("GET", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANTS(orgId, keyId));
54713
+ }
54714
+ async getBrowserAliasGrant(orgId, keyId, aliasId) {
54715
+ return this.request("GET", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANT(orgId, keyId, aliasId));
54716
+ }
54717
+ async replaceBrowserAliasGrant(orgId, keyId, aliasId, request3) {
54718
+ return this.request("PUT", ENDPOINTS.ORG_API_KEY_BROWSER_ALIAS_GRANT(orgId, keyId, aliasId), request3);
54719
+ }
54720
+ /** Managed-key discovery. The response is already grant-filtered and never
54721
+ * carries contract hashes, review snapshots, Edge IDs or Profile IDs. */
54722
+ async listManagedBrowserAliases(orgId) {
54723
+ return this.request("GET", ENDPOINTS.ORG_MANAGED_ALIASES(orgId));
54724
+ }
54725
+ async getManagedBrowserAlias(orgId, aliasName) {
54726
+ return this.request("GET", ENDPOINTS.ORG_MANAGED_ALIAS(orgId, aliasName));
54727
+ }
54728
+ /** Accept and dispatch one @alias command. request_id is generated by the
54729
+ * caller before local validation and is also the sole durable recovery key. */
54730
+ async createBrowserAliasExecution(orgId, request3) {
54731
+ return this.request("POST", ENDPOINTS.ORG_BROWSER_ALIAS_EXECUTIONS(orgId), request3);
54732
+ }
54733
+ async getBrowserAliasExecution(orgId, requestId) {
54734
+ return this.request("GET", ENDPOINTS.ORG_BROWSER_ALIAS_EXECUTION(orgId, requestId));
54735
+ }
54736
+ /** Accept one idempotent Browser Use operation for an explicit Profile.
54737
+ * The Server resolves Profile→Edge; callers never select an Edge directly. */
54738
+ async createBrowserUseOperation(orgId, request3) {
54739
+ return this.request("POST", ENDPOINTS.ORG_BROWSER_USE_OPERATIONS(orgId), request3);
54740
+ }
54741
+ /** Recover the durable receipt. Successful data is present only inside the
54742
+ * Server's short encrypted result TTL; terminal proof remains afterwards. */
54743
+ async getBrowserUseOperation(orgId, operationId) {
54744
+ return this.request("GET", ENDPOINTS.ORG_BROWSER_USE_OPERATION(orgId, operationId));
54745
+ }
54507
54746
  /**
54508
54747
  * Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
54509
54748
  * human maintainer or org admin). Sanitized — the password never comes back.
@@ -58752,11 +58991,28 @@ var ParallAgentGateway = class {
58752
58991
  const hasAttachments = message.attachments?.length;
58753
58992
  if (!body && !hasAttachments)
58754
58993
  return { action: "skip" };
58755
- if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
58756
- const mentions = content.mentions ?? [];
58757
- const isMentioned = mentions.some((mention) => mentionTargetsUser(mention.user_id, this.opts.agentUserId, "agent"));
58758
- if (!isMentioned)
58994
+ const mentions = content.mentions ?? [];
58995
+ const isMentioned = mentions.some((mention) => mentionTargetsUser(mention.user_id, this.opts.agentUserId, "agent"));
58996
+ let deliveryReason;
58997
+ if (message.thread_root_id) {
58998
+ if (isMentioned) {
58999
+ deliveryReason = "mention";
59000
+ } else {
59001
+ let watching;
59002
+ try {
59003
+ watching = await this.opts.client.isWatchingThread(message.thread_root_id);
59004
+ } catch {
59005
+ return { action: "retry" };
59006
+ }
59007
+ if (!watching)
59008
+ return { action: "skip" };
59009
+ deliveryReason = "watcher";
59010
+ }
59011
+ } else if (chatInfo.type === "group") {
59012
+ if (chatInfo.agentRoutingMode !== "active" && !isMentioned)
58759
59013
  return { action: "skip" };
59014
+ if (isMentioned)
59015
+ deliveryReason = "mention";
58760
59016
  }
58761
59017
  const attachments = (message.attachments ?? []).map((a) => ({
58762
59018
  id: a.id,
@@ -58797,6 +59053,7 @@ var ParallAgentGateway = class {
58797
59053
  messageId: message.id,
58798
59054
  body: body || "[attachment]",
58799
59055
  threadRootId: message.thread_root_id ?? void 0,
59056
+ deliveryReason,
58800
59057
  noReply: message.hints?.no_reply ?? false,
58801
59058
  attachments: attachments.length > 0 ? attachments : void 0,
58802
59059
  sentAt: message.created_at,
@@ -59274,7 +59531,10 @@ var ParallAgentGateway = class {
59274
59531
  this.opts.log?.info(`approval decided: ${approval.id} (${approval.status})`);
59275
59532
  const statusLabel = approval.status === "approved" ? "Approved" : "Rejected";
59276
59533
  const execInfo = approval.execution_status ? ` | execution: ${approval.execution_status}` : "";
59277
- const body = `${statusLabel}: ${approval.title}${execInfo}`;
59534
+ const reasonLine = formatApprovalDecisionReason(approval.status, approval.decision_reason);
59535
+ const reasonInfo = reasonLine ? `
59536
+ ${reasonLine}` : "";
59537
+ const body = `${statusLabel}: ${approval.title}${execInfo}${reasonInfo}`;
59278
59538
  const event = {
59279
59539
  type: "approval",
59280
59540
  targetId: chatId ?? approval.chat_id,
@@ -59888,7 +60148,7 @@ parall dm prll://usr_xxx --text-file /tmp/reply.md
59888
60148
  parall dm "Alice" --text "Hello"
59889
60149
 
59890
60150
  # Thread reply
59891
- parall messages send prll://cht_xxx --text-file /tmp/reply.md --thread-root-id 01JWC...
60151
+ parall messages send prll://cht_xxx --text-file /tmp/reply.md --thread-root-id prll://msg_xxx
59892
60152
 
59893
60153
  # FYI message (no response expected \u2014 the recipient sees \`[Hint: no_reply]\`)
59894
60154
  parall messages send prll://cht_xxx --text "FYI: done" --no-reply
@@ -59899,6 +60159,27 @@ parall messages send prll://cht_xxx --text "FYI: done" --no-reply
59899
60159
  parall no-reply --reason "ack only, nothing to add"
59900
60160
  \`\`\`
59901
60161
 
60162
+ ## Thread Subscriptions
60163
+
60164
+ Replying in a thread subscribes you to it: every later reply reaches you as
60165
+ \`[Event: message.new]\` with a \`[Thread: ...]\` line, marked
60166
+ \`[Delivery: watcher]\`. You are also auto-subscribed when a thread reply
60167
+ @-mentions you personally, and when someone replies to a thread whose root
60168
+ message you wrote. \`[Delivery: mention]\` means you were @-mentioned in that
60169
+ message.
60170
+
60171
+ \`\`\`bash
60172
+ parall messages watch prll://msg_xxx # follow a thread without replying (ID = the thread's root message)
60173
+ parall messages unwatch prll://msg_xxx # stop receiving a thread's replies
60174
+ parall messages watchers prll://msg_xxx # list who is watching a thread
60175
+ \`\`\`
60176
+
60177
+ Unwatch is sticky: no automatic source (including later @-mentions \u2014 you
60178
+ still get the one-off mention, just no subscription) re-subscribes you.
60179
+ Only replying in the thread yourself or an explicit \`watch\` does. Unwatch
60180
+ threads you have nothing more to contribute to instead of ignoring their
60181
+ wake-ups.
60182
+
59902
60183
  ## Files & Attachments
59903
60184
 
59904
60185
  Attachments appear in events as \`[Attachment: prll://att_xxx | mime | size | name]\`.
@@ -61006,7 +61287,7 @@ bound to whatever profile the connection selected.
61006
61287
  var SKILLS = [
61007
61288
  {
61008
61289
  name: "parall-platform",
61009
- description: "Parall platform queries and lightweight agent provisioning: list org members, agents, chats, read message history, check identity, create another agent, or walk the prll:// reference graph (resolve URIs, backlinks, multi-hop graph). Use when: user asks about org members, who's online, chat history, agent list, creating an agent, identity/auth questions, or you need to find what an entity is connected to / who references it.",
61290
+ description: "Parall platform queries and lightweight agent provisioning: list org members, agents, chats, read message history, watch/unwatch threads, check identity, create another agent, or walk the prll:// reference graph (resolve URIs, backlinks, multi-hop graph). Use when: user asks about org members, who's online, chat history, agent list, creating an agent, identity/auth questions, you want to follow or mute a thread (e.g. after `[Delivery: watcher]` wake-ups), or you need to find what an entity is connected to / who references it.",
61010
61291
  content: PARALL_PLATFORM_SKILL
61011
61292
  },
61012
61293
  {