@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.
@@ -324,10 +324,17 @@ var init_constants = __esm({
324
324
  CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
325
325
  CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
326
326
  CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
327
+ CHANNEL_SLACK_MANIFEST_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/slack/manifest-link`,
327
328
  CHANNEL_PROVISIONING_SESSION: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}`,
328
329
  CHANNEL_PROVISIONING_CANCEL: (orgId, sessionId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/${sessionId}/cancel`,
329
330
  // Tier-B platform verb (agent-only): send one message as the bound bot.
330
331
  CHANNEL_SEND: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/channel-send`,
332
+ // Tier-B read verbs (agent-only): workspace visibility as the bot sees it.
333
+ SLACK_CHANNELS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/channels`,
334
+ SLACK_USERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/users`,
335
+ SLACK_HISTORY: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/history`,
336
+ SLACK_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/members`,
337
+ SLACK_STATUS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/status`,
331
338
  // Invitations (org-scoped, admin)
332
339
  ORG_INVITATIONS: (orgId) => `${API_BASE}/orgs/${orgId}/invitations`,
333
340
  ORG_INVITATION: (orgId, invId) => `${API_BASE}/orgs/${orgId}/invitations/${invId}`,
@@ -422,6 +429,7 @@ var init_constants = __esm({
422
429
  ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
423
430
  CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
424
431
  THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
432
+ THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
425
433
  // References (org-scoped)
426
434
  REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
427
435
  REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
@@ -483,10 +491,17 @@ var init_constants = __esm({
483
491
  ORG_EDGE: (orgId) => `/api/v1/orgs/${orgId}/edge`,
484
492
  ORG_EDGE_DEVICES: (orgId) => `/api/v1/orgs/${orgId}/edge/devices`,
485
493
  ORG_EDGE_DEVICE: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}`,
494
+ ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
486
495
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
487
496
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
497
+ ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
488
498
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
489
- CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`
499
+ CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
500
+ // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
501
+ // Pinix Hub catalog proxy above is a different, id-less surface)
502
+ ORG_CLIP_REGISTRY: (orgId) => `/api/v1/orgs/${orgId}/clip-registry`,
503
+ ORG_CLIP_INSTALL: (orgId) => `/api/v1/orgs/${orgId}/clips/install`,
504
+ ORG_CLIPS_INSTALLED: (orgId) => `/api/v1/orgs/${orgId}/clips/installed`
490
505
  };
491
506
  WS_EVENTS = {
492
507
  // Client -> Server
@@ -656,7 +671,7 @@ var init_client = __esm({
656
671
  return apiError;
657
672
  }
658
673
  /** Build headers common to all requests (auth, swimlane). */
659
- buildHeaders(path22, extra) {
674
+ buildHeaders(path23, extra) {
660
675
  const headers = {
661
676
  "Content-Type": "application/json",
662
677
  ...extra
@@ -667,7 +682,7 @@ var init_client = __esm({
667
682
  if (this.swimlaneName) {
668
683
  headers["X-Prll-Swimlane"] = this.swimlaneName;
669
684
  }
670
- if (path22.startsWith(API_BASE)) {
685
+ if (path23.startsWith(API_BASE)) {
671
686
  const overrides = this.getFeatureFlagOverrides?.();
672
687
  if (overrides)
673
688
  headers["X-Prll-FF-Override"] = overrides;
@@ -690,8 +705,8 @@ var init_client = __esm({
690
705
  * is authoritative, so wiki vs api routing can't drift from how a caller
691
706
  * happens to invoke the client.
692
707
  */
693
- baseUrlFor(path22) {
694
- return path22.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
708
+ baseUrlFor(path23) {
709
+ return path23.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
695
710
  }
696
711
  setToken(token) {
697
712
  this.token = token;
@@ -718,10 +733,10 @@ var init_client = __esm({
718
733
  * REFRESH_THRESHOLD_S, refresh it **before** sending the request.
719
734
  * No-op when the token is still fresh, missing, or un-parseable.
720
735
  */
721
- async ensureFreshToken(path22) {
736
+ async ensureFreshToken(path23) {
722
737
  if (!this.token || !this.getRefreshToken)
723
738
  return;
724
- const pathSuffix = path22.replace(/^\/api\/v1/, "");
739
+ const pathSuffix = path23.replace(/^\/api\/v1/, "");
725
740
  if (_ParallClient.AUTH_PATHS.has(pathSuffix))
726
741
  return;
727
742
  const exp = _ParallClient.decodeJwtExp(this.token);
@@ -753,11 +768,11 @@ var init_client = __esm({
753
768
  this.refreshPromise = null;
754
769
  }
755
770
  }
756
- async request(method, path22, body, query, retried = false, opts) {
771
+ async request(method, path23, body, query, retried = false, opts) {
757
772
  if (!retried) {
758
- await this.ensureFreshToken(path22);
773
+ await this.ensureFreshToken(path23);
759
774
  }
760
- let url = `${this.baseUrlFor(path22)}${path22}`;
775
+ let url = `${this.baseUrlFor(path23)}${path23}`;
761
776
  if (query) {
762
777
  const params = new URLSearchParams();
763
778
  for (const [key, value] of Object.entries(query)) {
@@ -769,7 +784,7 @@ var init_client = __esm({
769
784
  if (qs)
770
785
  url += `?${qs}`;
771
786
  }
772
- const headers = this.buildHeaders(path22);
787
+ const headers = this.buildHeaders(path23);
773
788
  const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
774
789
  const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
775
790
  let res;
@@ -787,12 +802,12 @@ var init_client = __esm({
787
802
  throw _ParallClient.normalizeFetchError(err);
788
803
  }
789
804
  if (res.status === 401) {
790
- const pathSuffix = path22.replace(/^\/api\/v1/, "");
805
+ const pathSuffix = path23.replace(/^\/api\/v1/, "");
791
806
  const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
792
807
  if (!retried && !isAuthPath && this.getRefreshToken) {
793
808
  const refreshed = await this.tryRefresh();
794
809
  if (refreshed) {
795
- return this.request(method, path22, body, query, true, opts);
810
+ return this.request(method, path23, body, query, true, opts);
796
811
  }
797
812
  }
798
813
  if (this.onTokenExpired && !isAuthPath) {
@@ -822,15 +837,15 @@ var init_client = __esm({
822
837
  * hit the 100 MiB cap, so a longer 5-minute timeout is used so a
823
838
  * 50 MiB blob on a slow connection doesn't get chopped at 15 s.
824
839
  */
825
- async multipartRequest(method, path22, body, retried = false) {
840
+ async multipartRequest(method, path23, body, retried = false) {
826
841
  if (!retried) {
827
- await this.ensureFreshToken(path22);
842
+ await this.ensureFreshToken(path23);
828
843
  }
829
- const { "Content-Type": _drop, ...headers } = this.buildHeaders(path22);
844
+ const { "Content-Type": _drop, ...headers } = this.buildHeaders(path23);
830
845
  void _drop;
831
846
  let res;
832
847
  try {
833
- res = await fetch(`${this.baseUrlFor(path22)}${path22}`, {
848
+ res = await fetch(`${this.baseUrlFor(path23)}${path23}`, {
834
849
  method,
835
850
  headers,
836
851
  body,
@@ -840,12 +855,12 @@ var init_client = __esm({
840
855
  throw _ParallClient.normalizeFetchError(err);
841
856
  }
842
857
  if (res.status === 401) {
843
- const pathSuffix = path22.replace(/^\/api\/v1/, "");
858
+ const pathSuffix = path23.replace(/^\/api\/v1/, "");
844
859
  const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
845
860
  if (!retried && !isAuthPath && this.getRefreshToken) {
846
861
  const refreshed = await this.tryRefresh();
847
862
  if (refreshed) {
848
- return this.multipartRequest(method, path22, body, true);
863
+ return this.multipartRequest(method, path23, body, true);
849
864
  }
850
865
  }
851
866
  if (this.onTokenExpired && !isAuthPath) {
@@ -1553,12 +1568,18 @@ var init_client = __esm({
1553
1568
  async resizeMachine(orgId, machineId, spec) {
1554
1569
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
1555
1570
  }
1556
- /** Signal a local daemon-mode Machine to check for and apply an update. */
1571
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
1572
+ * daemons update autonomously (CDN poll + platform release signal). The
1573
+ * endpoint now answers 409 LOCAL_UPDATE_NOT_SUPPORTED unconditionally. */
1557
1574
  async requestMachineUpdate(orgId, machineId, mandatory = false) {
1558
1575
  await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
1559
1576
  }
1560
- async browseMachineFilesystem(orgId, machineId, path22) {
1561
- return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path22 }, void 0, false, { timeoutMs: 15e3 });
1577
+ /** @deprecated Retired server-side (daemon-control-authorization §4.2):
1578
+ * remote filesystem browse of a member's machine was remote device access.
1579
+ * The endpoint now answers 409 LOCAL_BROWSE_NOT_SUPPORTED unconditionally;
1580
+ * workspace paths are typed in (or picked on the machine's own Desktop). */
1581
+ async browseMachineFilesystem(orgId, machineId, path23) {
1582
+ return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path23 }, void 0, false, { timeoutMs: 15e3 });
1562
1583
  }
1563
1584
  /** Create a new machine key. Returns the raw key string (shown once) + metadata. */
1564
1585
  async createMachineKey(orgId, machineId, name) {
@@ -1581,6 +1602,14 @@ var init_client = __esm({
1581
1602
  async getThreadUnread(orgId, chatId, threadRootId) {
1582
1603
  return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
1583
1604
  }
1605
+ /** Advance the per-thread read cursor (forward-only). The server auto-clears
1606
+ * thread-scoped inbox items (thread_reply + in-thread mentions) the cursor
1607
+ * now covers. */
1608
+ async markThreadRead(orgId, chatId, threadRootId, messageId) {
1609
+ return this.request("POST", ENDPOINTS.THREAD_READ(orgId, chatId, threadRootId), {
1610
+ message_id: messageId
1611
+ });
1612
+ }
1584
1613
  // ---- Inbox ----
1585
1614
  async getInbox(orgId, params) {
1586
1615
  return this.request("GET", ENDPOINTS.INBOX(orgId), void 0, params);
@@ -1604,9 +1633,12 @@ var init_client = __esm({
1604
1633
  async archiveAllInbox(orgId) {
1605
1634
  return this.request("POST", ENDPOINTS.INBOX_ARCHIVE_ALL(orgId));
1606
1635
  }
1607
- /** Mark an inbox item as read by its source (source_type + source_id) rather than inbox item ID. */
1608
- async ackInbox(orgId, source) {
1609
- return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), source);
1636
+ /** Mark inbox items as read by their source (source_type + source_id) or by
1637
+ * group_key, rather than by inbox item ID. The group_key form clears a whole
1638
+ * group at once (e.g. `task:{taskId}` — task_assign/task_update/task_comment
1639
+ * share it), used by the task detail view's auto-ack on open. */
1640
+ async ackInbox(orgId, target) {
1641
+ return this.request("POST", ENDPOINTS.INBOX_ACK(orgId), target);
1610
1642
  }
1611
1643
  async deleteInboxItem(orgId, id) {
1612
1644
  return this.request("DELETE", ENDPOINTS.INBOX_ITEM(orgId, id));
@@ -1888,6 +1920,15 @@ var init_client = __esm({
1888
1920
  async initiateChannelProvisioning(orgId, input) {
1889
1921
  return this.request("POST", ENDPOINTS.CHANNEL_PROVISIONING(orgId), input);
1890
1922
  }
1923
+ /**
1924
+ * Mint a pending slack connection + api.slack.com manifest-prefill link
1925
+ * (guided manual path). Activate the returned connection_id with
1926
+ * deliverChannelCredentials once the user brings back the bot token +
1927
+ * signing secret.
1928
+ */
1929
+ async createSlackManifestLink(orgId, input) {
1930
+ return this.request("POST", ENDPOINTS.CHANNEL_SLACK_MANIFEST_LINK(orgId), input);
1931
+ }
1891
1932
  /**
1892
1933
  * Lazy status poll — server-side this may forward one provider poll, so
1893
1934
  * call it at the session's `poll_interval_seconds` cadence, not faster.
@@ -1906,6 +1947,38 @@ var init_client = __esm({
1906
1947
  async sendChannelMessage(orgId, input) {
1907
1948
  return this.request("POST", ENDPOINTS.CHANNEL_SEND(orgId), input);
1908
1949
  }
1950
+ slackReadQuery(base, query, extra) {
1951
+ const params = new URLSearchParams();
1952
+ if (query?.cursor)
1953
+ params.set("cursor", query.cursor);
1954
+ if (query?.limit)
1955
+ params.set("limit", String(query.limit));
1956
+ for (const [k, v] of Object.entries(extra ?? {}))
1957
+ params.set(k, v);
1958
+ const qs = params.toString();
1959
+ return qs ? `${base}?${qs}` : base;
1960
+ }
1961
+ /**
1962
+ * Tier-B read verbs (agent-only): workspace visibility as the bot sees
1963
+ * it. Same live gate as the send verb; authorization beyond it is the
1964
+ * bot's own Slack permissions.
1965
+ */
1966
+ async listSlackChannels(orgId, query) {
1967
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_CHANNELS(orgId), query));
1968
+ }
1969
+ async listSlackUsers(orgId, query) {
1970
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_USERS(orgId), query));
1971
+ }
1972
+ async slackHistory(orgId, conversationId, query) {
1973
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_HISTORY(orgId), query, { conversation: conversationId }));
1974
+ }
1975
+ async slackMembers(orgId, conversationId, query) {
1976
+ return this.request("GET", this.slackReadQuery(ENDPOINTS.SLACK_MEMBERS(orgId), query, { conversation: conversationId }));
1977
+ }
1978
+ /** Set/clear the Agents-pane "typing…" indicator (best-effort cosmetic). */
1979
+ async setSlackStatus(orgId, input) {
1980
+ await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
1981
+ }
1909
1982
  async listChannelConversations(orgId, connectionId) {
1910
1983
  return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
1911
1984
  }
@@ -2141,8 +2214,8 @@ var init_client = __esm({
2141
2214
  async deleteWikiRestriction(orgId, wikiId, restrictionId) {
2142
2215
  await this.request("DELETE", ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
2143
2216
  }
2144
- async getWikiAccessStatus(orgId, wikiId, path22) {
2145
- return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path22 ? { path: path22 } : void 0);
2217
+ async getWikiAccessStatus(orgId, wikiId, path23) {
2218
+ return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path23 ? { path: path23 } : void 0);
2146
2219
  }
2147
2220
  async createWikiAccessRequest(orgId, wikiId, data) {
2148
2221
  await this.request("POST", ENDPOINTS.WIKI_ACCESS_REQUESTS(orgId, wikiId), data);
@@ -2151,14 +2224,14 @@ var init_client = __esm({
2151
2224
  async getWikiCommits(orgId, wikiId, params) {
2152
2225
  return this.request("GET", ENDPOINTS.WIKI_COMMITS(orgId, wikiId), void 0, params);
2153
2226
  }
2154
- async getWikiFileCommits(orgId, wikiId, path22, params) {
2227
+ async getWikiFileCommits(orgId, wikiId, path23, params) {
2155
2228
  return this.request("GET", ENDPOINTS.WIKI_FILE_COMMITS(orgId, wikiId), void 0, {
2156
- path: path22,
2229
+ path: path23,
2157
2230
  ...params
2158
2231
  });
2159
2232
  }
2160
- async getWikiBlame(orgId, wikiId, path22, ref) {
2161
- return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path: path22, ref });
2233
+ async getWikiBlame(orgId, wikiId, path23, ref) {
2234
+ return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path: path23, ref });
2162
2235
  }
2163
2236
  // ---- Wiki Operations (audit log) ----
2164
2237
  async getWikiOperations(orgId, wikiId, params) {
@@ -2410,6 +2483,31 @@ var init_client = __esm({
2410
2483
  const resp = await this.request("GET", url);
2411
2484
  return resp.data;
2412
2485
  }
2486
+ // ---- Clip registry (v3, api-server org registry — `crg_` entries) ----
2487
+ /**
2488
+ * List registry clips visible to the org: its own plus public+approved
2489
+ * cross-org entries. This is the surface `installRegistryClip` and clip
2490
+ * connections operate on — NOT the Pinix catalog proxy
2491
+ * ({@link listRegistryClips}), whose entries carry no `crg_` id.
2492
+ */
2493
+ async listOrgRegistryClips(orgId) {
2494
+ const resp = await this.request("GET", `${ENDPOINTS.ORG_CLIP_REGISTRY(orgId)}?limit=100`);
2495
+ return resp ?? [];
2496
+ }
2497
+ /**
2498
+ * Install a registry clip into the org (a reference in `clip_installs`, not a
2499
+ * copy). Idempotent: installing an already-installed clip returns the same
2500
+ * `200 {ok:true}`. Fails closed with `403 CLIP_NOT_APPROVED` when the clip is
2501
+ * not eligible (cross-org requires public + approved).
2502
+ */
2503
+ async installRegistryClip(orgId, clipId) {
2504
+ return this.request("POST", ENDPOINTS.ORG_CLIP_INSTALL(orgId), { clip_id: clipId });
2505
+ }
2506
+ /** List the org's installed registry clips (full entries). */
2507
+ async listInstalledRegistryClips(orgId) {
2508
+ const resp = await this.request("GET", ENDPOINTS.ORG_CLIPS_INSTALLED(orgId));
2509
+ return resp ?? [];
2510
+ }
2413
2511
  // ---- Edge devices ----
2414
2512
  async listEdgeDevices(orgId) {
2415
2513
  return this.request("GET", ENDPOINTS.ORG_EDGE_DEVICES(orgId));
@@ -2427,8 +2525,8 @@ var init_client = __esm({
2427
2525
  return this.request("POST", ENDPOINTS.ORG_EDGE(orgId), input);
2428
2526
  }
2429
2527
  /**
2430
- * Delete a hosted Cloud Profile. Hosted only — a BYOC device is removed by
2431
- * uninstalling Parall Clip on that machine (`400 EDGE_PLACEMENT_UNSUPPORTED`).
2528
+ * Delete a hosted Cloud Profile. Hosted only — use {@link unregisterEdgeDevice}
2529
+ * for an offline BYOC registration (`400 EDGE_PLACEMENT_UNSUPPORTED` here).
2432
2530
  *
2433
2531
  * Idempotent and ASYNC: returns `202` with `hosted_state: 'deleting'` on the first
2434
2532
  * call and on every repeat. The device stops being usable immediately (no exec, no
@@ -2438,12 +2536,68 @@ var init_client = __esm({
2438
2536
  async deleteEdgeDevice(orgId, edgeId) {
2439
2537
  return this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE(orgId, edgeId));
2440
2538
  }
2539
+ /**
2540
+ * Remove the interactive human caller's own offline BYOC registration.
2541
+ *
2542
+ * Synchronous and idempotent: a committed removal and a repeat after removal
2543
+ * both resolve with no response body. A live connection returns `EDGE_ONLINE`;
2544
+ * callers must not clear local device identity until this method resolves.
2545
+ */
2546
+ async unregisterEdgeDevice(orgId, edgeId) {
2547
+ await this.request("DELETE", ENDPOINTS.ORG_EDGE_DEVICE_UNREGISTER(orgId, edgeId));
2548
+ }
2441
2549
  async getEdgeOnboarding(orgId) {
2442
2550
  return this.request("GET", ENDPOINTS.ORG_EDGE_ONBOARDING(orgId));
2443
2551
  }
2444
2552
  async listEdgeProfiles(orgId, edgeId) {
2445
2553
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
2446
2554
  }
2555
+ /**
2556
+ * Execute a registry clip command on an Edge device.
2557
+ *
2558
+ * A hosted (Cloud Profile) device is reachable ONLY through an explicit
2559
+ * `connection` (id `ccn_…` or alias) — there is no implicit route to an
2560
+ * org-shared browser login. BYOC keeps its legacy selectors (`edge_id`, or
2561
+ * nothing for the caller's own online device).
2562
+ *
2563
+ * Returns the result envelope on completion (`success` may be false when the
2564
+ * command RAN and failed — `error`/`error_code` describe why). Everything
2565
+ * else throws a typed {@link ApiError}; match on `err.code`:
2566
+ *
2567
+ * Safe to retry (guaranteed nothing was dispatched):
2568
+ * - `EDGE_ACTIVATING` 503 + `Retry-After` — cold cloud profile is starting.
2569
+ * Bounded backoff, same `correlation_id` across the loop.
2570
+ * - `EDGE_BUSY` 409 — the device is executing another request.
2571
+ * - `EDGE_CONCURRENCY_LIMIT` 429 — org at its concurrent-session limit.
2572
+ * - `EDGE_UNAVAILABLE` 503 — session torn down / replaced mid-dispatch.
2573
+ *
2574
+ * NOT retryable:
2575
+ * - `OUTCOME_UNKNOWN` 504 — dispatched, but no result arrived. The command
2576
+ * MAY HAVE EXECUTED (posted, ordered, deleted…). Never retry
2577
+ * automatically: verify the effect first, then decide. The message carries
2578
+ * the request id for audit.
2579
+ * - `EDGE_DEADLINE_EXCEEDED` 504 — arrived late, provably NOT executed.
2580
+ * - `EDGE_HOSTED_DISABLED_FOR_ORG` 403, `EDGE_REPAIR` 503 (operator-held),
2581
+ * `EDGE_RUNTIME_UNAVAILABLE` 503 (deployment has no hosted runtime).
2582
+ * - Routing errors: `HOSTED_CONNECTION_REQUIRED`, `CONNECTION_NOT_FOUND`,
2583
+ * `CONNECTION_CLIP_MISMATCH`, `CONNECTION_TARGET_GONE`,
2584
+ * `CONNECTION_PROFILE_MISMATCH`, `EDGE_DELETING`, `DEVICE_OFFLINE`.
2585
+ */
2586
+ async execEdgeClip(orgId, req) {
2587
+ const t = req.timeout;
2588
+ const serverTimeout = t !== void 0 && t > 0 && t <= 12e4 ? t : 3e4;
2589
+ const timeoutMs = serverTimeout + 1e4;
2590
+ try {
2591
+ return await this.request("POST", ENDPOINTS.ORG_EDGE_EXEC(orgId), req, void 0, false, {
2592
+ timeoutMs
2593
+ });
2594
+ } catch (err) {
2595
+ if (err instanceof ApiError && err.status === 422 && !err.code && typeof err.extras?.error_code === "string") {
2596
+ err.code = err.extras.error_code;
2597
+ }
2598
+ throw err;
2599
+ }
2600
+ }
2447
2601
  // ---- Clip connections ----
2448
2602
  async listClipConnections(orgId, clipId) {
2449
2603
  return this.request("GET", ENDPOINTS.CLIP_CONNECTIONS(orgId, clipId));
@@ -20619,9 +20773,9 @@ var require_getMachineId_linux = __commonJS({
20619
20773
  var api_1 = (init_esm(), __toCommonJS(esm_exports));
20620
20774
  async function getMachineId() {
20621
20775
  const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
20622
- for (const path22 of paths) {
20776
+ for (const path23 of paths) {
20623
20777
  try {
20624
- const result = await fs_1.promises.readFile(path22, { encoding: "utf8" });
20778
+ const result = await fs_1.promises.readFile(path23, { encoding: "utf8" });
20625
20779
  return result.trim();
20626
20780
  } catch (e) {
20627
20781
  api_1.diag.debug(`error reading machine id: ${e}`);
@@ -24024,7 +24178,7 @@ function appendRootPathToUrlIfNeeded(url) {
24024
24178
  return void 0;
24025
24179
  }
24026
24180
  }
24027
- function appendResourcePathToUrl(url, path22) {
24181
+ function appendResourcePathToUrl(url, path23) {
24028
24182
  try {
24029
24183
  new URL(url);
24030
24184
  } catch (_a) {
@@ -24034,11 +24188,11 @@ function appendResourcePathToUrl(url, path22) {
24034
24188
  if (!url.endsWith("/")) {
24035
24189
  url = url + "/";
24036
24190
  }
24037
- url += path22;
24191
+ url += path23;
24038
24192
  try {
24039
24193
  new URL(url);
24040
24194
  } catch (_b) {
24041
- diag2.warn("Configuration: Provided URL appended with '" + path22 + "' is not a valid URL, using 'undefined' instead of '" + url + "'");
24195
+ diag2.warn("Configuration: Provided URL appended with '" + path23 + "' is not a valid URL, using 'undefined' instead of '" + url + "'");
24042
24196
  return void 0;
24043
24197
  }
24044
24198
  return url;
@@ -30492,7 +30646,7 @@ var require_util2 = __commonJS({
30492
30646
  var { kDestroyed, kBodyUsed, kListeners, kBody } = require_symbols();
30493
30647
  var { IncomingMessage } = __require("node:http");
30494
30648
  var stream = __require("node:stream");
30495
- var net2 = __require("node:net");
30649
+ var net3 = __require("node:net");
30496
30650
  var { stringify } = __require("node:querystring");
30497
30651
  var { EventEmitter: EE } = __require("node:events");
30498
30652
  var timers = require_timers();
@@ -30604,14 +30758,14 @@ var require_util2 = __commonJS({
30604
30758
  }
30605
30759
  const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
30606
30760
  let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
30607
- let path22 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
30761
+ let path23 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
30608
30762
  if (origin[origin.length - 1] === "/") {
30609
30763
  origin = origin.slice(0, origin.length - 1);
30610
30764
  }
30611
- if (path22 && path22[0] !== "/") {
30612
- path22 = `/${path22}`;
30765
+ if (path23 && path23[0] !== "/") {
30766
+ path23 = `/${path23}`;
30613
30767
  }
30614
- return new URL(`${origin}${path22}`);
30768
+ return new URL(`${origin}${path23}`);
30615
30769
  }
30616
30770
  if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
30617
30771
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -30641,7 +30795,7 @@ var require_util2 = __commonJS({
30641
30795
  }
30642
30796
  assert(typeof host === "string");
30643
30797
  const servername = getHostname(host);
30644
- if (net2.isIP(servername)) {
30798
+ if (net3.isIP(servername)) {
30645
30799
  return "";
30646
30800
  }
30647
30801
  return servername;
@@ -31432,9 +31586,9 @@ var require_diagnostics = __commonJS({
31432
31586
  "undici:client:sendHeaders",
31433
31587
  (evt) => {
31434
31588
  const {
31435
- request: { method, path: path22, origin }
31589
+ request: { method, path: path23, origin }
31436
31590
  } = evt;
31437
- debugLog("sending request to %s %s%s", method, origin, path22);
31591
+ debugLog("sending request to %s %s%s", method, origin, path23);
31438
31592
  }
31439
31593
  );
31440
31594
  }
@@ -31452,14 +31606,14 @@ var require_diagnostics = __commonJS({
31452
31606
  "undici:request:headers",
31453
31607
  (evt) => {
31454
31608
  const {
31455
- request: { method, path: path22, origin },
31609
+ request: { method, path: path23, origin },
31456
31610
  response: { statusCode }
31457
31611
  } = evt;
31458
31612
  debugLog(
31459
31613
  "received response to %s %s%s - HTTP %d",
31460
31614
  method,
31461
31615
  origin,
31462
- path22,
31616
+ path23,
31463
31617
  statusCode
31464
31618
  );
31465
31619
  }
@@ -31468,23 +31622,23 @@ var require_diagnostics = __commonJS({
31468
31622
  "undici:request:trailers",
31469
31623
  (evt) => {
31470
31624
  const {
31471
- request: { method, path: path22, origin }
31625
+ request: { method, path: path23, origin }
31472
31626
  } = evt;
31473
- debugLog("trailers received from %s %s%s", method, origin, path22);
31627
+ debugLog("trailers received from %s %s%s", method, origin, path23);
31474
31628
  }
31475
31629
  );
31476
31630
  diagnosticsChannel.subscribe(
31477
31631
  "undici:request:error",
31478
31632
  (evt) => {
31479
31633
  const {
31480
- request: { method, path: path22, origin },
31634
+ request: { method, path: path23, origin },
31481
31635
  error
31482
31636
  } = evt;
31483
31637
  debugLog(
31484
31638
  "request to %s %s%s errored - %s",
31485
31639
  method,
31486
31640
  origin,
31487
- path22,
31641
+ path23,
31488
31642
  error.message
31489
31643
  );
31490
31644
  }
@@ -31587,7 +31741,7 @@ var require_request = __commonJS({
31587
31741
  var kHandler = Symbol("handler");
31588
31742
  var Request = class {
31589
31743
  constructor(origin, {
31590
- path: path22,
31744
+ path: path23,
31591
31745
  method,
31592
31746
  body,
31593
31747
  headers,
@@ -31604,11 +31758,11 @@ var require_request = __commonJS({
31604
31758
  maxRedirections,
31605
31759
  typeOfService
31606
31760
  }, handler) {
31607
- if (typeof path22 !== "string") {
31761
+ if (typeof path23 !== "string") {
31608
31762
  throw new InvalidArgumentError("path must be a string");
31609
- } else if (path22[0] !== "/" && !(path22.startsWith("http://") || path22.startsWith("https://")) && method !== "CONNECT") {
31763
+ } else if (path23[0] !== "/" && !(path23.startsWith("http://") || path23.startsWith("https://")) && method !== "CONNECT") {
31610
31764
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
31611
- } else if (invalidPathRegex.test(path22)) {
31765
+ } else if (invalidPathRegex.test(path23)) {
31612
31766
  throw new InvalidArgumentError("invalid request path");
31613
31767
  }
31614
31768
  if (typeof method !== "string") {
@@ -31683,7 +31837,7 @@ var require_request = __commonJS({
31683
31837
  this.completed = false;
31684
31838
  this.aborted = false;
31685
31839
  this.upgrade = upgrade || null;
31686
- this.path = query ? serializePathWithQuery(path22, query) : path22;
31840
+ this.path = query ? serializePathWithQuery(path23, query) : path23;
31687
31841
  this.origin = origin;
31688
31842
  this.protocol = getProtocolFromUrlString(origin);
31689
31843
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -32262,7 +32416,7 @@ var require_dispatcher_base = __commonJS({
32262
32416
  var require_connect = __commonJS({
32263
32417
  "ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/core/connect.js"(exports2, module2) {
32264
32418
  "use strict";
32265
- var net2 = __require("node:net");
32419
+ var net3 = __require("node:net");
32266
32420
  var assert = __require("node:assert");
32267
32421
  var util = require_util2();
32268
32422
  var { InvalidArgumentError } = require_errors();
@@ -32301,7 +32455,7 @@ var require_connect = __commonJS({
32301
32455
  const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions);
32302
32456
  timeout = timeout == null ? 1e4 : timeout;
32303
32457
  allowH2 = allowH2 != null ? allowH2 : false;
32304
- return function connect3({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
32458
+ return function connect4({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) {
32305
32459
  let socket;
32306
32460
  if (protocol === "https:") {
32307
32461
  if (!tls) {
@@ -32331,7 +32485,7 @@ var require_connect = __commonJS({
32331
32485
  } else {
32332
32486
  assert(!httpSocket, "httpSocket can only be sent on TLS update");
32333
32487
  port = port || 80;
32334
- socket = net2.connect({
32488
+ socket = net3.connect({
32335
32489
  highWaterMark: 64 * 1024,
32336
32490
  // Same as nodejs fs streams.
32337
32491
  ...options,
@@ -36722,7 +36876,7 @@ var require_client_h1 = __commonJS({
36722
36876
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
36723
36877
  }
36724
36878
  function writeH1(client, request3) {
36725
- const { method, path: path22, host, upgrade, blocking, reset } = request3;
36879
+ const { method, path: path23, host, upgrade, blocking, reset } = request3;
36726
36880
  let { body, headers, contentLength } = request3;
36727
36881
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
36728
36882
  if (util.isFormDataLike(body)) {
@@ -36791,7 +36945,7 @@ var require_client_h1 = __commonJS({
36791
36945
  if (socket.setTypeOfService) {
36792
36946
  socket.setTypeOfService(request3.typeOfService);
36793
36947
  }
36794
- let header = `${method} ${path22} HTTP/1.1\r
36948
+ let header = `${method} ${path23} HTTP/1.1\r
36795
36949
  `;
36796
36950
  if (typeof host === "string") {
36797
36951
  header += `host: ${host}\r
@@ -37444,7 +37598,7 @@ var require_client_h2 = __commonJS({
37444
37598
  function writeH2(client, request3) {
37445
37599
  const requestTimeout = request3.bodyTimeout ?? client[kBodyTimeout];
37446
37600
  const session = client[kHTTP2Session];
37447
- const { method, path: path22, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request3;
37601
+ const { method, path: path23, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request3;
37448
37602
  let { body } = request3;
37449
37603
  if (upgrade != null && upgrade !== "websocket") {
37450
37604
  util.errorRequest(client, request3, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -37512,7 +37666,7 @@ var require_client_h2 = __commonJS({
37512
37666
  }
37513
37667
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
37514
37668
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
37515
- headers[HTTP2_HEADER_PATH] = path22;
37669
+ headers[HTTP2_HEADER_PATH] = path23;
37516
37670
  if (protocol === "ws:" || protocol === "wss:") {
37517
37671
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
37518
37672
  } else {
@@ -37553,7 +37707,7 @@ var require_client_h2 = __commonJS({
37553
37707
  stream.setTimeout(requestTimeout);
37554
37708
  return true;
37555
37709
  }
37556
- headers[HTTP2_HEADER_PATH] = path22;
37710
+ headers[HTTP2_HEADER_PATH] = path23;
37557
37711
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
37558
37712
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
37559
37713
  if (body && typeof body.read === "function") {
@@ -37869,7 +38023,7 @@ var require_client = __commonJS({
37869
38023
  "ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/dispatcher/client.js"(exports2, module2) {
37870
38024
  "use strict";
37871
38025
  var assert = __require("node:assert");
37872
- var net2 = __require("node:net");
38026
+ var net3 = __require("node:net");
37873
38027
  var http3 = __require("node:http");
37874
38028
  var util = require_util2();
37875
38029
  var { ClientStats } = require_stats();
@@ -37960,7 +38114,7 @@ var require_client = __commonJS({
37960
38114
  tls,
37961
38115
  strictContentLength,
37962
38116
  maxCachedSessions,
37963
- connect: connect4,
38117
+ connect: connect5,
37964
38118
  maxRequestsPerClient,
37965
38119
  localAddress,
37966
38120
  maxResponseSize,
@@ -38017,13 +38171,13 @@ var require_client = __commonJS({
38017
38171
  if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) {
38018
38172
  throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero");
38019
38173
  }
38020
- if (connect4 != null && typeof connect4 !== "function" && typeof connect4 !== "object") {
38174
+ if (connect5 != null && typeof connect5 !== "function" && typeof connect5 !== "object") {
38021
38175
  throw new InvalidArgumentError("connect must be a function or an object");
38022
38176
  }
38023
38177
  if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) {
38024
38178
  throw new InvalidArgumentError("maxRequestsPerClient must be a positive number");
38025
38179
  }
38026
- if (localAddress != null && (typeof localAddress !== "string" || net2.isIP(localAddress) === 0)) {
38180
+ if (localAddress != null && (typeof localAddress !== "string" || net3.isIP(localAddress) === 0)) {
38027
38181
  throw new InvalidArgumentError("localAddress must be valid string IP address");
38028
38182
  }
38029
38183
  if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) {
@@ -38051,8 +38205,8 @@ var require_client = __commonJS({
38051
38205
  throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0");
38052
38206
  }
38053
38207
  super();
38054
- if (typeof connect4 !== "function") {
38055
- connect4 = buildConnector({
38208
+ if (typeof connect5 !== "function") {
38209
+ connect5 = buildConnector({
38056
38210
  ...tls,
38057
38211
  maxCachedSessions,
38058
38212
  allowH2,
@@ -38060,14 +38214,14 @@ var require_client = __commonJS({
38060
38214
  socketPath,
38061
38215
  timeout: connectTimeout,
38062
38216
  ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
38063
- ...connect4
38217
+ ...connect5
38064
38218
  });
38065
38219
  } else if (socketPath != null) {
38066
- const customConnect = connect4;
38067
- connect4 = (opts, callback) => customConnect({ ...opts, socketPath }, callback);
38220
+ const customConnect = connect5;
38221
+ connect5 = (opts, callback) => customConnect({ ...opts, socketPath }, callback);
38068
38222
  }
38069
38223
  this[kUrl] = util.parseOrigin(url);
38070
- this[kConnector] = connect4;
38224
+ this[kConnector] = connect5;
38071
38225
  this[kPipelining] = pipelining != null ? pipelining : 1;
38072
38226
  this[kMaxHeadersSize] = maxHeaderSize;
38073
38227
  this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout;
@@ -38125,7 +38279,7 @@ var require_client = __commonJS({
38125
38279
  );
38126
38280
  }
38127
38281
  [kConnect](cb) {
38128
- connect3(this);
38282
+ connect4(this);
38129
38283
  this.once("connect", cb);
38130
38284
  }
38131
38285
  [kDispatch](opts, handler) {
@@ -38187,7 +38341,7 @@ var require_client = __commonJS({
38187
38341
  assert(client[kSize] === 0);
38188
38342
  }
38189
38343
  }
38190
- function connect3(client) {
38344
+ function connect4(client) {
38191
38345
  assert(!client[kConnecting]);
38192
38346
  assert(!client[kHTTPContext]);
38193
38347
  let { host, hostname, protocol, port } = client[kUrl];
@@ -38195,7 +38349,7 @@ var require_client = __commonJS({
38195
38349
  const idx = hostname.indexOf("]");
38196
38350
  assert(idx !== -1);
38197
38351
  const ip = hostname.substring(1, idx);
38198
- assert(net2.isIPv6(ip));
38352
+ assert(net3.isIPv6(ip));
38199
38353
  hostname = ip;
38200
38354
  }
38201
38355
  client[kConnecting] = true;
@@ -38366,7 +38520,7 @@ var require_client = __commonJS({
38366
38520
  return;
38367
38521
  }
38368
38522
  if (!client[kHTTPContext]) {
38369
- connect3(client);
38523
+ connect4(client);
38370
38524
  return;
38371
38525
  }
38372
38526
  if (client[kHTTPContext].destroyed) {
@@ -38662,7 +38816,7 @@ var require_pool2 = __commonJS({
38662
38816
  constructor(origin, {
38663
38817
  connections,
38664
38818
  factory = defaultFactory,
38665
- connect: connect3,
38819
+ connect: connect4,
38666
38820
  connectTimeout,
38667
38821
  tls,
38668
38822
  maxCachedSessions,
@@ -38679,24 +38833,24 @@ var require_pool2 = __commonJS({
38679
38833
  if (typeof factory !== "function") {
38680
38834
  throw new InvalidArgumentError("factory must be a function.");
38681
38835
  }
38682
- if (connect3 != null && typeof connect3 !== "function" && typeof connect3 !== "object") {
38836
+ if (connect4 != null && typeof connect4 !== "function" && typeof connect4 !== "object") {
38683
38837
  throw new InvalidArgumentError("connect must be a function or an object");
38684
38838
  }
38685
- if (typeof connect3 !== "function") {
38686
- connect3 = buildConnector({
38839
+ if (typeof connect4 !== "function") {
38840
+ connect4 = buildConnector({
38687
38841
  ...tls,
38688
38842
  maxCachedSessions,
38689
38843
  allowH2,
38690
38844
  socketPath,
38691
38845
  timeout: connectTimeout,
38692
38846
  ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
38693
- ...connect3
38847
+ ...connect4
38694
38848
  });
38695
38849
  }
38696
38850
  super();
38697
38851
  this[kConnections] = connections || null;
38698
38852
  this[kUrl] = util.parseOrigin(origin);
38699
- this[kOptions] = { ...util.deepClone(options), connect: connect3, allowH2, clientTtl, socketPath };
38853
+ this[kOptions] = { ...util.deepClone(options), connect: connect4, allowH2, clientTtl, socketPath };
38700
38854
  this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
38701
38855
  this[kFactory] = factory;
38702
38856
  this.on("connect", (origin2, targets) => {
@@ -38913,7 +39067,7 @@ var require_round_robin_pool = __commonJS({
38913
39067
  constructor(origin, {
38914
39068
  connections,
38915
39069
  factory = defaultFactory,
38916
- connect: connect3,
39070
+ connect: connect4,
38917
39071
  connectTimeout,
38918
39072
  tls,
38919
39073
  maxCachedSessions,
@@ -38930,24 +39084,24 @@ var require_round_robin_pool = __commonJS({
38930
39084
  if (typeof factory !== "function") {
38931
39085
  throw new InvalidArgumentError("factory must be a function.");
38932
39086
  }
38933
- if (connect3 != null && typeof connect3 !== "function" && typeof connect3 !== "object") {
39087
+ if (connect4 != null && typeof connect4 !== "function" && typeof connect4 !== "object") {
38934
39088
  throw new InvalidArgumentError("connect must be a function or an object");
38935
39089
  }
38936
- if (typeof connect3 !== "function") {
38937
- connect3 = buildConnector({
39090
+ if (typeof connect4 !== "function") {
39091
+ connect4 = buildConnector({
38938
39092
  ...tls,
38939
39093
  maxCachedSessions,
38940
39094
  allowH2,
38941
39095
  socketPath,
38942
39096
  timeout: connectTimeout,
38943
39097
  ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
38944
- ...connect3
39098
+ ...connect4
38945
39099
  });
38946
39100
  }
38947
39101
  super();
38948
39102
  this[kConnections] = connections || null;
38949
39103
  this[kUrl] = util.parseOrigin(origin);
38950
- this[kOptions] = { ...util.deepClone(options), connect: connect3, allowH2, clientTtl, socketPath };
39104
+ this[kOptions] = { ...util.deepClone(options), connect: connect4, allowH2, clientTtl, socketPath };
38951
39105
  this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
38952
39106
  this[kFactory] = factory;
38953
39107
  this[kIndex] = -1;
@@ -39021,21 +39175,21 @@ var require_agent = __commonJS({
39021
39175
  return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts);
39022
39176
  }
39023
39177
  var Agent4 = class extends DispatcherBase {
39024
- constructor({ factory = defaultFactory, maxOrigins = Infinity, connect: connect3, ...options } = {}) {
39178
+ constructor({ factory = defaultFactory, maxOrigins = Infinity, connect: connect4, ...options } = {}) {
39025
39179
  if (typeof factory !== "function") {
39026
39180
  throw new InvalidArgumentError("factory must be a function.");
39027
39181
  }
39028
- if (connect3 != null && typeof connect3 !== "function" && typeof connect3 !== "object") {
39182
+ if (connect4 != null && typeof connect4 !== "function" && typeof connect4 !== "object") {
39029
39183
  throw new InvalidArgumentError("connect must be a function or an object");
39030
39184
  }
39031
39185
  if (typeof maxOrigins !== "number" || Number.isNaN(maxOrigins) || maxOrigins <= 0) {
39032
39186
  throw new InvalidArgumentError("maxOrigins must be a number greater than 0");
39033
39187
  }
39034
39188
  super();
39035
- if (connect3 && typeof connect3 !== "function") {
39036
- connect3 = { ...connect3 };
39189
+ if (connect4 && typeof connect4 !== "function") {
39190
+ connect4 = { ...connect4 };
39037
39191
  }
39038
- this[kOptions] = { ...util.deepClone(options), maxOrigins, connect: connect3 };
39192
+ this[kOptions] = { ...util.deepClone(options), maxOrigins, connect: connect4 };
39039
39193
  this[kFactory] = factory;
39040
39194
  this[kClients] = /* @__PURE__ */ new Map();
39041
39195
  this[kOrigins] = /* @__PURE__ */ new Set();
@@ -39138,10 +39292,10 @@ var require_socks5_utils = __commonJS({
39138
39292
  "ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/core/socks5-utils.js"(exports2, module2) {
39139
39293
  "use strict";
39140
39294
  var { Buffer: Buffer2 } = __require("node:buffer");
39141
- var net2 = __require("node:net");
39295
+ var net3 = __require("node:net");
39142
39296
  var { InvalidArgumentError } = require_errors();
39143
39297
  function parseAddress(address) {
39144
- if (net2.isIPv4(address)) {
39298
+ if (net3.isIPv4(address)) {
39145
39299
  const parts = address.split(".").map(Number);
39146
39300
  return {
39147
39301
  type: 1,
@@ -39149,7 +39303,7 @@ var require_socks5_utils = __commonJS({
39149
39303
  buffer: Buffer2.from(parts)
39150
39304
  };
39151
39305
  }
39152
- if (net2.isIPv6(address)) {
39306
+ if (net3.isIPv6(address)) {
39153
39307
  return {
39154
39308
  type: 4,
39155
39309
  // IPv6
@@ -39609,7 +39763,7 @@ var require_socks5_client = __commonJS({
39609
39763
  var require_socks5_proxy_agent = __commonJS({
39610
39764
  "ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js"(exports2, module2) {
39611
39765
  "use strict";
39612
- var net2 = __require("node:net");
39766
+ var net3 = __require("node:net");
39613
39767
  var { URL: URL2 } = __require("node:url");
39614
39768
  var tls;
39615
39769
  var DispatcherBase = require_dispatcher_base();
@@ -39671,7 +39825,7 @@ var require_socks5_proxy_agent = __commonJS({
39671
39825
  socket2.removeListener("connect", onConnect);
39672
39826
  reject(err);
39673
39827
  };
39674
- const socket2 = net2.connect({
39828
+ const socket2 = net3.connect({
39675
39829
  host: proxyHost,
39676
39830
  port: proxyPort
39677
39831
  });
@@ -39830,16 +39984,16 @@ var require_proxy_agent = __commonJS({
39830
39984
  }
39831
39985
  var Http1ProxyWrapper = class extends DispatcherBase {
39832
39986
  #client;
39833
- constructor(proxyUrl, { headers = {}, connect: connect3, factory }) {
39987
+ constructor(proxyUrl, { headers = {}, connect: connect4, factory }) {
39834
39988
  if (!proxyUrl) {
39835
39989
  throw new InvalidArgumentError("Proxy URL is mandatory");
39836
39990
  }
39837
39991
  super();
39838
39992
  this[kProxyHeaders] = headers;
39839
39993
  if (factory) {
39840
- this.#client = factory(proxyUrl, { connect: connect3 });
39994
+ this.#client = factory(proxyUrl, { connect: connect4 });
39841
39995
  } else {
39842
- this.#client = new Client(proxyUrl, { connect: connect3 });
39996
+ this.#client = new Client(proxyUrl, { connect: connect4 });
39843
39997
  }
39844
39998
  }
39845
39999
  [kDispatch](opts, handler) {
@@ -39855,10 +40009,10 @@ var require_proxy_agent = __commonJS({
39855
40009
  };
39856
40010
  const {
39857
40011
  origin,
39858
- path: path22 = "/",
40012
+ path: path23 = "/",
39859
40013
  headers = {}
39860
40014
  } = opts;
39861
- opts.path = origin + path22;
40015
+ opts.path = origin + path23;
39862
40016
  if (!("host" in headers) && !("Host" in headers)) {
39863
40017
  const { host } = new URL(origin);
39864
40018
  headers.host = host;
@@ -39900,7 +40054,7 @@ var require_proxy_agent = __commonJS({
39900
40054
  } else if (username && password) {
39901
40055
  this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString("base64")}`;
39902
40056
  }
39903
- const connect3 = buildConnector({ ...opts.proxyTls });
40057
+ const connect4 = buildConnector({ ...opts.proxyTls });
39904
40058
  this[kConnectEndpoint] = buildConnector({ ...opts.requestTls });
39905
40059
  const agentFactory = opts.factory || defaultAgentFactory;
39906
40060
  const factory = (origin2, options) => {
@@ -39908,7 +40062,7 @@ var require_proxy_agent = __commonJS({
39908
40062
  if (this[kProxy].protocol === "socks5:" || this[kProxy].protocol === "socks:") {
39909
40063
  return new Socks5ProxyAgent(this[kProxy].uri, {
39910
40064
  headers: this[kProxyHeaders],
39911
- connect: connect3,
40065
+ connect: connect4,
39912
40066
  factory: agentFactory,
39913
40067
  username: opts.username || username,
39914
40068
  password: opts.password || password,
@@ -39918,7 +40072,7 @@ var require_proxy_agent = __commonJS({
39918
40072
  if (!this[kTunnelProxy] && protocol2 === "http:" && this[kProxy].protocol === "http:") {
39919
40073
  return new Http1ProxyWrapper(this[kProxy].uri, {
39920
40074
  headers: this[kProxyHeaders],
39921
- connect: connect3,
40075
+ connect: connect4,
39922
40076
  factory: agentFactory
39923
40077
  });
39924
40078
  }
@@ -39927,7 +40081,7 @@ var require_proxy_agent = __commonJS({
39927
40081
  if (protocol === "socks5:" || protocol === "socks:") {
39928
40082
  this[kClient] = null;
39929
40083
  } else {
39930
- this[kClient] = clientFactory(url, { connect: connect3 });
40084
+ this[kClient] = clientFactory(url, { connect: connect4 });
39931
40085
  }
39932
40086
  this[kAgent] = new Agent4({
39933
40087
  ...opts,
@@ -40533,7 +40687,7 @@ var require_h2c_client = __commonJS({
40533
40687
  "h2c-client: Only h2c protocol is supported"
40534
40688
  );
40535
40689
  }
40536
- const { connect: connect3, maxConcurrentStreams, pipelining, ...opts } = clientOpts ?? {};
40690
+ const { connect: connect4, maxConcurrentStreams, pipelining, ...opts } = clientOpts ?? {};
40537
40691
  let defaultMaxConcurrentStreams = 100;
40538
40692
  let defaultPipelining = 100;
40539
40693
  if (maxConcurrentStreams != null && Number.isInteger(maxConcurrentStreams) && maxConcurrentStreams > 0) {
@@ -41715,10 +41869,10 @@ var require_api_connect = __commonJS({
41715
41869
  }
41716
41870
  }
41717
41871
  };
41718
- function connect3(opts, callback) {
41872
+ function connect4(opts, callback) {
41719
41873
  if (callback === void 0) {
41720
41874
  return new Promise((resolve9, reject) => {
41721
- connect3.call(this, opts, (err, data) => {
41875
+ connect4.call(this, opts, (err, data) => {
41722
41876
  return err ? reject(err) : resolve9(data);
41723
41877
  });
41724
41878
  });
@@ -41735,7 +41889,7 @@ var require_api_connect = __commonJS({
41735
41889
  queueMicrotask(() => callback(err, { opaque }));
41736
41890
  }
41737
41891
  }
41738
- module2.exports = connect3;
41892
+ module2.exports = connect4;
41739
41893
  }
41740
41894
  });
41741
41895
 
@@ -41921,20 +42075,20 @@ var require_mock_utils = __commonJS({
41921
42075
  }
41922
42076
  return normalizedQp;
41923
42077
  }
41924
- function safeUrl(path22) {
41925
- if (typeof path22 !== "string") {
41926
- return path22;
42078
+ function safeUrl(path23) {
42079
+ if (typeof path23 !== "string") {
42080
+ return path23;
41927
42081
  }
41928
- const pathSegments = path22.split("?", 3);
42082
+ const pathSegments = path23.split("?", 3);
41929
42083
  if (pathSegments.length !== 2) {
41930
- return path22;
42084
+ return path23;
41931
42085
  }
41932
42086
  const qp = new URLSearchParams(pathSegments.pop());
41933
42087
  qp.sort();
41934
42088
  return [...pathSegments, qp.toString()].join("?");
41935
42089
  }
41936
- function matchKey(mockDispatch2, { path: path22, method, body, headers }) {
41937
- const pathMatch = matchValue(mockDispatch2.path, path22);
42090
+ function matchKey(mockDispatch2, { path: path23, method, body, headers }) {
42091
+ const pathMatch = matchValue(mockDispatch2.path, path23);
41938
42092
  const methodMatch = matchValue(mockDispatch2.method, method);
41939
42093
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
41940
42094
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -41959,8 +42113,8 @@ var require_mock_utils = __commonJS({
41959
42113
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
41960
42114
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
41961
42115
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
41962
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path22, ignoreTrailingSlash }) => {
41963
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path22)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path22), resolvedPath);
42116
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path23, ignoreTrailingSlash }) => {
42117
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path23)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path23), resolvedPath);
41964
42118
  });
41965
42119
  if (matchedMockDispatches.length === 0) {
41966
42120
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -41999,19 +42153,19 @@ var require_mock_utils = __commonJS({
41999
42153
  mockDispatches.splice(index, 1);
42000
42154
  }
42001
42155
  }
42002
- function removeTrailingSlash(path22) {
42003
- while (path22.endsWith("/")) {
42004
- path22 = path22.slice(0, -1);
42156
+ function removeTrailingSlash(path23) {
42157
+ while (path23.endsWith("/")) {
42158
+ path23 = path23.slice(0, -1);
42005
42159
  }
42006
- if (path22.length === 0) {
42007
- path22 = "/";
42160
+ if (path23.length === 0) {
42161
+ path23 = "/";
42008
42162
  }
42009
- return path22;
42163
+ return path23;
42010
42164
  }
42011
42165
  function buildKey(opts) {
42012
- const { path: path22, method, body, headers, query } = opts;
42166
+ const { path: path23, method, body, headers, query } = opts;
42013
42167
  return {
42014
- path: path22,
42168
+ path: path23,
42015
42169
  method,
42016
42170
  body,
42017
42171
  headers,
@@ -42701,10 +42855,10 @@ var require_pending_interceptors_formatter = __commonJS({
42701
42855
  }
42702
42856
  format(pendingInterceptors) {
42703
42857
  const withPrettyHeaders = pendingInterceptors.map(
42704
- ({ method, path: path22, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
42858
+ ({ method, path: path23, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
42705
42859
  Method: method,
42706
42860
  Origin: origin,
42707
- Path: path22,
42861
+ Path: path23,
42708
42862
  "Status code": statusCode,
42709
42863
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
42710
42864
  Invocations: timesInvoked,
@@ -42786,9 +42940,9 @@ var require_mock_agent = __commonJS({
42786
42940
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
42787
42941
  const dispatchOpts = { ...opts };
42788
42942
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
42789
- const [path22, searchParams] = dispatchOpts.path.split("?");
42943
+ const [path23, searchParams] = dispatchOpts.path.split("?");
42790
42944
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
42791
- dispatchOpts.path = `${path22}?${normalizedSearchParams}`;
42945
+ dispatchOpts.path = `${path23}?${normalizedSearchParams}`;
42792
42946
  }
42793
42947
  return this[kAgent].dispatch(dispatchOpts, handler);
42794
42948
  }
@@ -42993,7 +43147,7 @@ var require_snapshot_recorder = __commonJS({
42993
43147
  "ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
42994
43148
  "use strict";
42995
43149
  var { writeFile, readFile, mkdir } = __require("node:fs/promises");
42996
- var { dirname: dirname12, resolve: resolve9 } = __require("node:path");
43150
+ var { dirname: dirname13, resolve: resolve9 } = __require("node:path");
42997
43151
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
42998
43152
  var { InvalidArgumentError, UndiciError } = require_errors();
42999
43153
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -43189,12 +43343,12 @@ var require_snapshot_recorder = __commonJS({
43189
43343
  * @return {Promise<void>} - Resolves when snapshots are loaded
43190
43344
  */
43191
43345
  async loadSnapshots(filePath) {
43192
- const path22 = filePath || this.#snapshotPath;
43193
- if (!path22) {
43346
+ const path23 = filePath || this.#snapshotPath;
43347
+ if (!path23) {
43194
43348
  throw new InvalidArgumentError("Snapshot path is required");
43195
43349
  }
43196
43350
  try {
43197
- const data = await readFile(resolve9(path22), "utf8");
43351
+ const data = await readFile(resolve9(path23), "utf8");
43198
43352
  const parsed = JSON.parse(data);
43199
43353
  if (Array.isArray(parsed)) {
43200
43354
  this.#snapshots.clear();
@@ -43208,7 +43362,7 @@ var require_snapshot_recorder = __commonJS({
43208
43362
  if (error.code === "ENOENT") {
43209
43363
  this.#snapshots.clear();
43210
43364
  } else {
43211
- throw new UndiciError(`Failed to load snapshots from ${path22}`, { cause: error });
43365
+ throw new UndiciError(`Failed to load snapshots from ${path23}`, { cause: error });
43212
43366
  }
43213
43367
  }
43214
43368
  }
@@ -43219,12 +43373,12 @@ var require_snapshot_recorder = __commonJS({
43219
43373
  * @returns {Promise<void>} - Resolves when snapshots are saved
43220
43374
  */
43221
43375
  async saveSnapshots(filePath) {
43222
- const path22 = filePath || this.#snapshotPath;
43223
- if (!path22) {
43376
+ const path23 = filePath || this.#snapshotPath;
43377
+ if (!path23) {
43224
43378
  throw new InvalidArgumentError("Snapshot path is required");
43225
43379
  }
43226
- const resolvedPath = resolve9(path22);
43227
- await mkdir(dirname12(resolvedPath), { recursive: true });
43380
+ const resolvedPath = resolve9(path23);
43381
+ await mkdir(dirname13(resolvedPath), { recursive: true });
43228
43382
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
43229
43383
  hash,
43230
43384
  snapshot
@@ -43848,15 +44002,15 @@ var require_redirect_handler = __commonJS({
43848
44002
  return;
43849
44003
  }
43850
44004
  const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
43851
- const path22 = search ? `${pathname}${search}` : pathname;
43852
- const redirectUrlString = `${origin}${path22}`;
44005
+ const path23 = search ? `${pathname}${search}` : pathname;
44006
+ const redirectUrlString = `${origin}${path23}`;
43853
44007
  for (const historyUrl of this.history) {
43854
44008
  if (historyUrl.toString() === redirectUrlString) {
43855
44009
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
43856
44010
  }
43857
44011
  }
43858
44012
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
43859
- this.opts.path = path22;
44013
+ this.opts.path = path23;
43860
44014
  this.opts.origin = origin;
43861
44015
  this.opts.query = null;
43862
44016
  }
@@ -50063,11 +50217,11 @@ var require_fetch = __commonJS({
50063
50217
  function dispatch({ body }) {
50064
50218
  const url = requestCurrentURL(request3);
50065
50219
  const agent = fetchParams.controller.dispatcher;
50066
- const path22 = url.pathname + url.search;
50220
+ const path23 = url.pathname + url.search;
50067
50221
  const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
50068
50222
  return new Promise((resolve9, reject) => agent.dispatch(
50069
50223
  {
50070
- path: hasTrailingQuestionMark ? `${path22}?` : path22,
50224
+ path: hasTrailingQuestionMark ? `${path23}?` : path23,
50071
50225
  origin: url.origin,
50072
50226
  method: request3.method,
50073
50227
  body: agent.isMockActive ? request3.body && (request3.body.source || request3.body.stream) : body,
@@ -51014,9 +51168,9 @@ var require_util5 = __commonJS({
51014
51168
  }
51015
51169
  }
51016
51170
  }
51017
- function validateCookiePath(path22) {
51018
- for (let i = 0; i < path22.length; ++i) {
51019
- const code = path22.charCodeAt(i);
51171
+ function validateCookiePath(path23) {
51172
+ for (let i = 0; i < path23.length; ++i) {
51173
+ const code = path23.charCodeAt(i);
51020
51174
  if (code < 32 || // exclude CTLs (0-31)
51021
51175
  code === 127 || // DEL
51022
51176
  code === 59) {
@@ -54186,11 +54340,11 @@ var require_undici = __commonJS({
54186
54340
  if (typeof opts.path !== "string") {
54187
54341
  throw new InvalidArgumentError("invalid opts.path");
54188
54342
  }
54189
- let path22 = opts.path;
54343
+ let path23 = opts.path;
54190
54344
  if (!opts.path.startsWith("/")) {
54191
- path22 = `/${path22}`;
54345
+ path23 = `/${path23}`;
54192
54346
  }
54193
- url = new URL(util.parseOrigin(url).origin + path22);
54347
+ url = new URL(util.parseOrigin(url).origin + path23);
54194
54348
  } else {
54195
54349
  if (!opts) {
54196
54350
  opts = typeof url === "object" ? url : {};
@@ -58161,7 +58315,7 @@ var require_websocket2 = __commonJS({
58161
58315
  var EventEmitter = __require("events");
58162
58316
  var https3 = __require("https");
58163
58317
  var http3 = __require("http");
58164
- var net2 = __require("net");
58318
+ var net3 = __require("net");
58165
58319
  var tls = __require("tls");
58166
58320
  var { randomBytes: randomBytes2, createHash: createHash5 } = __require("crypto");
58167
58321
  var { Duplex, Readable: Readable2 } = __require("stream");
@@ -58895,12 +59049,12 @@ var require_websocket2 = __commonJS({
58895
59049
  }
58896
59050
  function netConnect(options) {
58897
59051
  options.path = options.socketPath;
58898
- return net2.connect(options);
59052
+ return net3.connect(options);
58899
59053
  }
58900
59054
  function tlsConnect(options) {
58901
59055
  options.path = void 0;
58902
59056
  if (!options.servername && options.servername !== "") {
58903
- options.servername = net2.isIP(options.host) ? "" : options.host;
59057
+ options.servername = net3.isIP(options.host) ? "" : options.host;
58904
59058
  }
58905
59059
  return tls.connect(options);
58906
59060
  }
@@ -64914,9 +65068,280 @@ var init_filesystem = __esm({
64914
65068
  }
64915
65069
  });
64916
65070
 
65071
+ // ts/daemon/dist/local-control.js
65072
+ import { chmodSync as chmodSync2, existsSync as existsSync10, mkdirSync as mkdirSync8, rmSync as rmSync4, statSync } from "node:fs";
65073
+ import * as net2 from "node:net";
65074
+ import * as path17 from "node:path";
65075
+ function localControlSocketPath(env = process.env) {
65076
+ return path17.join(daemonConfigDir(env), "run", "control.sock");
65077
+ }
65078
+ function isSocketLive(sockPath) {
65079
+ return new Promise((resolve9) => {
65080
+ const probe = net2.connect(sockPath);
65081
+ const done = (live) => {
65082
+ probe.removeAllListeners();
65083
+ probe.destroy();
65084
+ clearTimeout(timer);
65085
+ resolve9(live);
65086
+ };
65087
+ const timer = setTimeout(() => done(true), 1e3);
65088
+ probe.once("connect", () => done(true));
65089
+ probe.once("error", (err) => {
65090
+ done(!(err.code === "ECONNREFUSED" || err.code === "ENOENT"));
65091
+ });
65092
+ });
65093
+ }
65094
+ var LocalControlError, MAX_LINE_BYTES, LocalControlServer;
65095
+ var init_local_control = __esm({
65096
+ "ts/daemon/dist/local-control.js"() {
65097
+ "use strict";
65098
+ init_daemon_paths();
65099
+ LocalControlError = class extends Error {
65100
+ code;
65101
+ constructor(code, message) {
65102
+ super(message);
65103
+ this.code = code;
65104
+ this.name = "LocalControlError";
65105
+ }
65106
+ };
65107
+ MAX_LINE_BYTES = 16 * 1024;
65108
+ LocalControlServer = class {
65109
+ opts;
65110
+ server = null;
65111
+ sockets = /* @__PURE__ */ new Set();
65112
+ constructor(opts) {
65113
+ this.opts = opts;
65114
+ }
65115
+ async start() {
65116
+ if (this.server)
65117
+ throw new Error("local control server already started");
65118
+ const sockPath = this.opts.socketPath;
65119
+ const dir = path17.dirname(sockPath);
65120
+ mkdirSync8(dir, { recursive: true, mode: 448 });
65121
+ try {
65122
+ chmodSync2(dir, 448);
65123
+ } catch (err) {
65124
+ throw new Error(`could not restrict control socket directory: ${String(err)}`);
65125
+ }
65126
+ if (existsSync10(sockPath)) {
65127
+ let st;
65128
+ try {
65129
+ st = statSync(sockPath);
65130
+ } catch (err) {
65131
+ throw new Error(`could not inspect existing control socket: ${String(err)}`);
65132
+ }
65133
+ if (st.isSocket()) {
65134
+ if (await isSocketLive(sockPath)) {
65135
+ throw new Error(`another process is already serving the local control socket at ${sockPath}`);
65136
+ }
65137
+ rmSync4(sockPath, { force: true });
65138
+ }
65139
+ }
65140
+ const server = net2.createServer((socket) => this.handleConnection(socket));
65141
+ this.server = server;
65142
+ await new Promise((resolve9, reject) => {
65143
+ const onError = (err) => {
65144
+ this.server = null;
65145
+ reject(err);
65146
+ };
65147
+ server.once("error", onError);
65148
+ server.listen(sockPath, () => {
65149
+ server.removeListener("error", onError);
65150
+ try {
65151
+ chmodSync2(sockPath, 384);
65152
+ } catch (err) {
65153
+ server.close();
65154
+ this.server = null;
65155
+ reject(new Error(`could not restrict control socket permissions: ${String(err)}`));
65156
+ return;
65157
+ }
65158
+ resolve9();
65159
+ });
65160
+ });
65161
+ server.on("error", (err) => this.opts.log.warn(`local control server error: ${String(err)}`));
65162
+ this.opts.log.info(`local control socket listening at ${sockPath}`);
65163
+ }
65164
+ async stop() {
65165
+ const server = this.server;
65166
+ if (!server)
65167
+ return;
65168
+ this.server = null;
65169
+ for (const s of this.sockets)
65170
+ s.destroy();
65171
+ this.sockets.clear();
65172
+ await new Promise((resolve9) => server.close(() => resolve9()));
65173
+ try {
65174
+ rmSync4(this.opts.socketPath, { force: true });
65175
+ } catch {
65176
+ }
65177
+ }
65178
+ handleConnection(socket) {
65179
+ this.sockets.add(socket);
65180
+ socket.on("close", () => this.sockets.delete(socket));
65181
+ socket.on("error", () => socket.destroy());
65182
+ socket.setEncoding("utf8");
65183
+ let buffer = "";
65184
+ socket.on("data", (chunk) => {
65185
+ buffer += chunk;
65186
+ if (Buffer.byteLength(buffer) > MAX_LINE_BYTES) {
65187
+ this.reply(socket, void 0, { code: "INVALID_REQUEST", message: "request too large" });
65188
+ socket.end();
65189
+ return;
65190
+ }
65191
+ let newline = buffer.indexOf("\n");
65192
+ while (newline !== -1) {
65193
+ const line = buffer.slice(0, newline).trim();
65194
+ buffer = buffer.slice(newline + 1);
65195
+ if (line)
65196
+ void this.handleLine(socket, line);
65197
+ newline = buffer.indexOf("\n");
65198
+ }
65199
+ });
65200
+ }
65201
+ async handleLine(socket, line) {
65202
+ let req;
65203
+ try {
65204
+ const parsed = JSON.parse(line);
65205
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
65206
+ throw new Error("not an object");
65207
+ }
65208
+ req = parsed;
65209
+ } catch {
65210
+ this.reply(socket, void 0, { code: "INVALID_REQUEST", message: "invalid JSON request" });
65211
+ socket.end();
65212
+ return;
65213
+ }
65214
+ const id = typeof req.id === "string" ? req.id : void 0;
65215
+ try {
65216
+ switch (req.command) {
65217
+ case "ping": {
65218
+ const result = await this.opts.handlers.ping();
65219
+ this.reply(socket, id, void 0, result);
65220
+ return;
65221
+ }
65222
+ case "profile.open":
65223
+ case "profile.stop":
65224
+ case "profile.reset": {
65225
+ const action = req.command.slice("profile.".length);
65226
+ const profileId = typeof req.profile_id === "string" ? req.profile_id.trim() : "";
65227
+ const requester = typeof req.requester_user_id === "string" ? req.requester_user_id.trim() : "";
65228
+ if (!profileId || !requester) {
65229
+ throw new LocalControlError("INVALID_REQUEST", "profile_id and requester_user_id are required");
65230
+ }
65231
+ await this.opts.handlers.profileControl(action, profileId, requester);
65232
+ this.reply(socket, id, void 0, { status: "ok" });
65233
+ return;
65234
+ }
65235
+ default:
65236
+ throw new LocalControlError("UNKNOWN_COMMAND", `unknown command ${String(req.command)}`);
65237
+ }
65238
+ } catch (err) {
65239
+ if (err instanceof LocalControlError) {
65240
+ this.reply(socket, id, { code: err.code, message: err.message });
65241
+ } else {
65242
+ this.opts.log.warn(`local control command failed: ${String(err)}`);
65243
+ this.reply(socket, id, {
65244
+ code: "INTERNAL",
65245
+ message: err instanceof Error ? err.message : String(err)
65246
+ });
65247
+ }
65248
+ }
65249
+ }
65250
+ reply(socket, id, error, result) {
65251
+ if (socket.destroyed)
65252
+ return;
65253
+ const payload = { ok: !error };
65254
+ if (id !== void 0)
65255
+ payload.id = id;
65256
+ if (error)
65257
+ payload.error = error;
65258
+ if (result !== void 0)
65259
+ payload.result = result;
65260
+ try {
65261
+ socket.write(`${JSON.stringify(payload)}
65262
+ `);
65263
+ } catch {
65264
+ socket.destroy();
65265
+ }
65266
+ }
65267
+ };
65268
+ }
65269
+ });
65270
+
65271
+ // ts/daemon/dist/local-profile-control.js
65272
+ async function startLocalProfileControl(deps) {
65273
+ if (process.env.KUBERNETES_SERVICE_HOST || process.platform === "win32")
65274
+ return null;
65275
+ const server = new LocalControlServer({
65276
+ socketPath: localControlSocketPath(),
65277
+ log: deps.log,
65278
+ handlers: {
65279
+ ping: async () => ({
65280
+ machine_id: deps.machineId(),
65281
+ org_id: deps.orgId(),
65282
+ profile_control: deps.pool() !== null
65283
+ }),
65284
+ profileControl: (action, profileId, requesterUserId) => handleLocalProfileControl(deps, action, profileId, requesterUserId)
65285
+ }
65286
+ });
65287
+ try {
65288
+ await server.start();
65289
+ return server;
65290
+ } catch (err) {
65291
+ deps.log.warn(`local control socket unavailable: ${String(err)}`);
65292
+ return null;
65293
+ }
65294
+ }
65295
+ async function handleLocalProfileControl(deps, action, profileId, requesterUserId) {
65296
+ const owner = deps.owner();
65297
+ if (!owner || !requesterUserId || requesterUserId !== owner) {
65298
+ throw new LocalControlError("OWNER_MISMATCH", "Only the machine owner can control local browser profiles");
65299
+ }
65300
+ const pool = deps.pool();
65301
+ if (!pool) {
65302
+ throw new LocalControlError("RUNTIME_DISABLED", "Browser profile runtime is disabled on this daemon");
65303
+ }
65304
+ let profiles;
65305
+ try {
65306
+ profiles = await deps.listProfiles();
65307
+ } catch (err) {
65308
+ throw new LocalControlError("SERVER_UNAVAILABLE", `could not verify the profile with the server: ${String(err)}`);
65309
+ }
65310
+ const profile = profiles.find((p) => p.id === profileId && p.machine_id);
65311
+ if (!profile) {
65312
+ throw new LocalControlError("PROFILE_NOT_ON_MACHINE", "Browser profile is not assigned to this machine");
65313
+ }
65314
+ const generation = profile.lifecycle_generation;
65315
+ if (action === "open") {
65316
+ const resetGen = profile.reset_generation ?? 0;
65317
+ const wipeGen = resetGen > pool.appliedResetGeneration(profileId) ? resetGen : null;
65318
+ if (wipeGen !== null)
65319
+ pool.fence(profileId);
65320
+ const sinceSeq = pool.stopSeqOf(profileId);
65321
+ await deps.enqueueRevive(profileId, async () => {
65322
+ if (wipeGen !== null)
65323
+ await deps.wipeBeforeRevive(pool, profileId, wipeGen, generation);
65324
+ await pool.openProfile(profileId, void 0, sinceSeq, generation);
65325
+ });
65326
+ return;
65327
+ }
65328
+ pool.fence(profileId);
65329
+ if (action === "stop") {
65330
+ await deps.enqueueOp(profileId, () => pool.stopProfile(profileId, generation));
65331
+ return;
65332
+ }
65333
+ await deps.enqueueOp(profileId, () => pool.resetProfile(profileId, generation, profile.reset_generation));
65334
+ }
65335
+ var init_local_profile_control = __esm({
65336
+ "ts/daemon/dist/local-profile-control.js"() {
65337
+ "use strict";
65338
+ init_local_control();
65339
+ }
65340
+ });
65341
+
64917
65342
  // ts/daemon/dist/home-isolation.js
64918
65343
  import * as fs10 from "node:fs";
64919
- import * as path17 from "node:path";
65344
+ import * as path18 from "node:path";
64920
65345
  function ensureIsolatedHome(spec, agentId, log2, platform2 = process.platform) {
64921
65346
  fs10.mkdirSync(spec.homeDir, { recursive: true });
64922
65347
  const failures = [];
@@ -64928,18 +65353,18 @@ function ensureIsolatedHome(spec, agentId, log2, platform2 = process.platform) {
64928
65353
  }
64929
65354
  };
64930
65355
  attempt(".claude link", () => {
64931
- fs10.mkdirSync(path17.join(spec.claudeStateRoot, ".claude"), { recursive: true });
64932
- ensureLink(path17.join(spec.homeDir, ".claude"), path17.join(spec.claudeStateRoot, ".claude"), agentId, log2);
65356
+ fs10.mkdirSync(path18.join(spec.claudeStateRoot, ".claude"), { recursive: true });
65357
+ ensureLink(path18.join(spec.homeDir, ".claude"), path18.join(spec.claudeStateRoot, ".claude"), agentId, log2);
64933
65358
  });
64934
- attempt(".claude.json link", () => ensureLink(path17.join(spec.homeDir, ".claude.json"), path17.join(spec.claudeStateRoot, ".claude.json"), agentId, log2));
65359
+ attempt(".claude.json link", () => ensureLink(path18.join(spec.homeDir, ".claude.json"), path18.join(spec.claudeStateRoot, ".claude.json"), agentId, log2));
64935
65360
  if (platform2 === "darwin") {
64936
65361
  attempt("Library/Keychains link", () => {
64937
- fs10.mkdirSync(path17.join(spec.homeDir, "Library"), { recursive: true });
64938
- ensureLink(path17.join(spec.homeDir, "Library", "Keychains"), path17.join(spec.systemHome, "Library", "Keychains"), agentId, log2);
65362
+ fs10.mkdirSync(path18.join(spec.homeDir, "Library"), { recursive: true });
65363
+ ensureLink(path18.join(spec.homeDir, "Library", "Keychains"), path18.join(spec.systemHome, "Library", "Keychains"), agentId, log2);
64939
65364
  });
64940
65365
  }
64941
65366
  attempt(".gitconfig", () => {
64942
- const gitconfig = path17.join(spec.homeDir, ".gitconfig");
65367
+ const gitconfig = path18.join(spec.homeDir, ".gitconfig");
64943
65368
  if (!fs10.existsSync(gitconfig)) {
64944
65369
  fs10.writeFileSync(gitconfig, `[user]
64945
65370
  name = ${gitConfigValue(spec.gitUserName)}
@@ -64965,7 +65390,7 @@ function ensureLink(linkPath, target, agentId, log2) {
64965
65390
  if (existing) {
64966
65391
  if (existing.isSymbolicLink()) {
64967
65392
  const current = fs10.readlinkSync(linkPath);
64968
- if (path17.resolve(path17.dirname(linkPath), current) === path17.resolve(target))
65393
+ if (path18.resolve(path18.dirname(linkPath), current) === path18.resolve(target))
64969
65394
  return;
64970
65395
  fs10.unlinkSync(linkPath);
64971
65396
  log2.info(`agent ${agentId}: relinking ${linkPath} \u2192 ${target}`);
@@ -64978,16 +65403,16 @@ function ensureLink(linkPath, target, agentId, log2) {
64978
65403
  fs10.symlinkSync(target, linkPath);
64979
65404
  }
64980
65405
  function ensureSharedCredentialLink(rootClaudeHome, agentClaudeHome, agentId, log2) {
64981
- const sharedCredentials = path17.resolve(sharedClaudeCredentialsFileFor(rootClaudeHome));
65406
+ const sharedCredentials = path18.resolve(sharedClaudeCredentialsFileFor(rootClaudeHome));
64982
65407
  const agentCredentials = agentClaudeCredentialsFileFor(agentClaudeHome);
64983
- const agentCredentialsDir = path17.dirname(agentCredentials);
64984
- fs10.mkdirSync(path17.dirname(sharedCredentials), { recursive: true });
65408
+ const agentCredentialsDir = path18.dirname(agentCredentials);
65409
+ fs10.mkdirSync(path18.dirname(sharedCredentials), { recursive: true });
64985
65410
  fs10.mkdirSync(agentCredentialsDir, { recursive: true });
64986
65411
  try {
64987
65412
  const existing = fs10.lstatSync(agentCredentials);
64988
65413
  if (existing.isSymbolicLink()) {
64989
65414
  const currentTarget = fs10.readlinkSync(agentCredentials);
64990
- if (path17.resolve(agentCredentialsDir, currentTarget) === sharedCredentials) {
65415
+ if (path18.resolve(agentCredentialsDir, currentTarget) === sharedCredentials) {
64991
65416
  return;
64992
65417
  }
64993
65418
  fs10.unlinkSync(agentCredentials);
@@ -65015,7 +65440,7 @@ var init_home_isolation = __esm({
65015
65440
  import { execFileSync as execFileSync4 } from "node:child_process";
65016
65441
  import * as fs11 from "node:fs";
65017
65442
  import * as os6 from "node:os";
65018
- import * as path18 from "node:path";
65443
+ import * as path19 from "node:path";
65019
65444
  function runtimeBinaryEnvVar(runtimeType) {
65020
65445
  return RUNTIME_BINARIES[runtimeType]?.envVar;
65021
65446
  }
@@ -65092,16 +65517,16 @@ function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbac
65092
65517
  function resolveDirectPath(command) {
65093
65518
  if (!command.includes("/") && !command.includes("\\"))
65094
65519
  return null;
65095
- const abs = path18.isAbsolute(command) ? command : path18.resolve(process.cwd(), command);
65520
+ const abs = path19.isAbsolute(command) ? command : path19.resolve(process.cwd(), command);
65096
65521
  return isExecutable(abs) ? abs : null;
65097
65522
  }
65098
65523
  function resolveFromPath(command, pathValue, env, platform2) {
65099
65524
  if (!pathValue || command.includes("/") || command.includes("\\"))
65100
65525
  return null;
65101
- const dirs = pathValue.split(path18.delimiter).filter(Boolean);
65526
+ const dirs = pathValue.split(path19.delimiter).filter(Boolean);
65102
65527
  for (const dir of dirs) {
65103
65528
  for (const file of commandCandidates(command, env, platform2)) {
65104
- const candidate = path18.join(dir, file);
65529
+ const candidate = path19.join(dir, file);
65105
65530
  if (isExecutable(candidate))
65106
65531
  return { binaryPath: candidate, pathValue };
65107
65532
  }
@@ -65142,7 +65567,7 @@ __PRLL_PATH__%s
65142
65567
  if (line.startsWith("__PRLL_PATH__"))
65143
65568
  pathValue = line.slice("__PRLL_PATH__".length);
65144
65569
  }
65145
- if (path18.isAbsolute(binaryPath) && isExecutable(binaryPath)) {
65570
+ if (path19.isAbsolute(binaryPath) && isExecutable(binaryPath)) {
65146
65571
  return { binaryPath, pathValue: pathValue || void 0 };
65147
65572
  }
65148
65573
  } catch {
@@ -65162,18 +65587,18 @@ function cachedCandidatePathPlan(env, platform2) {
65162
65587
  function candidatePathPlan(env, platform2 = process.platform) {
65163
65588
  const home = env.HOME || os6.homedir();
65164
65589
  if (platform2 === "win32") {
65165
- const appData = env.APPDATA || path18.join(home, "AppData", "Roaming");
65166
- const localAppData = env.LOCALAPPDATA || path18.join(home, "AppData", "Local");
65590
+ const appData = env.APPDATA || path19.join(home, "AppData", "Roaming");
65591
+ const localAppData = env.LOCALAPPDATA || path19.join(home, "AppData", "Local");
65167
65592
  const winPrimaryDirs = [
65168
65593
  ...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
65169
65594
  ...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
65170
- path18.dirname(process.execPath),
65595
+ path19.dirname(process.execPath),
65171
65596
  env.PNPM_HOME,
65172
- path18.join(appData, "npm"),
65173
- path18.join(localAppData, "pnpm"),
65174
- path18.join(localAppData, "Volta", "bin"),
65175
- path18.join(home, ".volta", "bin"),
65176
- path18.join(home, ".bun", "bin")
65597
+ path19.join(appData, "npm"),
65598
+ path19.join(localAppData, "pnpm"),
65599
+ path19.join(localAppData, "Volta", "bin"),
65600
+ path19.join(home, ".volta", "bin"),
65601
+ path19.join(home, ".bun", "bin")
65177
65602
  ];
65178
65603
  return {
65179
65604
  primaryDirs: unique(winPrimaryDirs).filter((dir) => !!dir && isDirectory(dir)),
@@ -65183,21 +65608,21 @@ function candidatePathPlan(env, platform2 = process.platform) {
65183
65608
  const primaryDirs = [
65184
65609
  ...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
65185
65610
  ...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
65186
- path18.dirname(process.execPath),
65187
- path18.join(path18.dirname(process.execPath), "bin"),
65188
- path18.resolve(path18.dirname(process.execPath), "..", "Resources", "bin"),
65189
- path18.join(home, ".local", "bin"),
65190
- path18.join(home, "bin"),
65191
- path18.join(home, ".npm-global", "bin"),
65192
- path18.join(home, "Library", "pnpm"),
65193
- path18.join(home, ".local", "share", "pnpm"),
65194
- path18.join(home, ".volta", "bin"),
65195
- path18.join(home, ".bun", "bin"),
65196
- path18.join(home, ".asdf", "shims"),
65197
- path18.join(home, ".local", "share", "mise", "shims"),
65198
- path18.join(home, ".mise", "shims"),
65199
- path18.join(home, ".fnm", "aliases", "default", "bin"),
65200
- path18.join(home, "Library", "Application Support", "fnm", "aliases", "default", "bin"),
65611
+ path19.dirname(process.execPath),
65612
+ path19.join(path19.dirname(process.execPath), "bin"),
65613
+ path19.resolve(path19.dirname(process.execPath), "..", "Resources", "bin"),
65614
+ path19.join(home, ".local", "bin"),
65615
+ path19.join(home, "bin"),
65616
+ path19.join(home, ".npm-global", "bin"),
65617
+ path19.join(home, "Library", "pnpm"),
65618
+ path19.join(home, ".local", "share", "pnpm"),
65619
+ path19.join(home, ".volta", "bin"),
65620
+ path19.join(home, ".bun", "bin"),
65621
+ path19.join(home, ".asdf", "shims"),
65622
+ path19.join(home, ".local", "share", "mise", "shims"),
65623
+ path19.join(home, ".mise", "shims"),
65624
+ path19.join(home, ".fnm", "aliases", "default", "bin"),
65625
+ path19.join(home, "Library", "Application Support", "fnm", "aliases", "default", "bin"),
65201
65626
  "/opt/homebrew/bin",
65202
65627
  "/usr/local/bin",
65203
65628
  "/usr/bin",
@@ -65216,19 +65641,19 @@ function candidatePathPlan(env, platform2 = process.platform) {
65216
65641
  };
65217
65642
  }
65218
65643
  function nvmVersionBinDirs(home) {
65219
- const root = path18.join(home, ".nvm", "versions", "node");
65644
+ const root = path19.join(home, ".nvm", "versions", "node");
65220
65645
  let versions;
65221
65646
  try {
65222
65647
  versions = fs11.readdirSync(root);
65223
65648
  } catch {
65224
65649
  return [];
65225
65650
  }
65226
- return sortVersionNamesDesc(versions).map((version) => path18.join(root, version, "bin"));
65651
+ return sortVersionNamesDesc(versions).map((version) => path19.join(root, version, "bin"));
65227
65652
  }
65228
65653
  function fnmVersionBinDirs(home) {
65229
65654
  const roots = [
65230
- path18.join(home, ".fnm", "node-versions"),
65231
- path18.join(home, "Library", "Application Support", "fnm", "node-versions")
65655
+ path19.join(home, ".fnm", "node-versions"),
65656
+ path19.join(home, "Library", "Application Support", "fnm", "node-versions")
65232
65657
  ];
65233
65658
  const dirs = [];
65234
65659
  for (const root of roots) {
@@ -65238,7 +65663,7 @@ function fnmVersionBinDirs(home) {
65238
65663
  } catch {
65239
65664
  continue;
65240
65665
  }
65241
- dirs.push(...sortVersionNamesDesc(versions).map((version) => path18.join(root, version, "installation", "bin")));
65666
+ dirs.push(...sortVersionNamesDesc(versions).map((version) => path19.join(root, version, "installation", "bin")));
65242
65667
  }
65243
65668
  return dirs;
65244
65669
  }
@@ -65260,13 +65685,13 @@ function parseVersionName(value) {
65260
65685
  return value.replace(/^v/i, "").split(".").map((part) => Number.parseInt(part, 10)).filter((part) => Number.isFinite(part));
65261
65686
  }
65262
65687
  function splitPath(value) {
65263
- return value?.split(path18.delimiter).filter(Boolean) ?? [];
65688
+ return value?.split(path19.delimiter).filter(Boolean) ?? [];
65264
65689
  }
65265
65690
  function mergePath(prependDirs, existing) {
65266
- return unique([...prependDirs, ...splitPath(existing)]).join(path18.delimiter);
65691
+ return unique([...prependDirs, ...splitPath(existing)]).join(path19.delimiter);
65267
65692
  }
65268
65693
  function anchorResolvedPath(pathValue, resolution) {
65269
- return mergePath([path18.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
65694
+ return mergePath([path19.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
65270
65695
  }
65271
65696
  function commandCandidates(command, env, platform2 = process.platform) {
65272
65697
  if (platform2 !== "win32")
@@ -65421,7 +65846,7 @@ var init_runtime_detector = __esm({
65421
65846
  import { spawn as spawn5 } from "node:child_process";
65422
65847
  import { createHash as createHash4 } from "node:crypto";
65423
65848
  import * as fs12 from "node:fs";
65424
- import * as path19 from "node:path";
65849
+ import * as path20 from "node:path";
65425
65850
  async function prepareWorkspace(opts) {
65426
65851
  const prior = opts.attached.workspace_state;
65427
65852
  const plan = buildWorkspacePlan(opts.attached.daemon_config, opts.defaultWorkspaceDir, prior?.config_hash);
@@ -65566,8 +65991,8 @@ async function ensureWorkspace(plan, log2) {
65566
65991
  assertSafeCustomWorkspacePath(plan);
65567
65992
  }
65568
65993
  if (!fs12.existsSync(plan.workspaceDir)) {
65569
- fs12.mkdirSync(path19.dirname(plan.workspaceDir), { recursive: true });
65570
- assertWritableWorkspaceDir(path19.dirname(plan.workspaceDir));
65994
+ fs12.mkdirSync(path20.dirname(plan.workspaceDir), { recursive: true });
65995
+ assertWritableWorkspaceDir(path20.dirname(plan.workspaceDir));
65571
65996
  await runCommand("git", ["clone", remote, plan.workspaceDir], process.cwd());
65572
65997
  } else {
65573
65998
  const st = fs12.statSync(plan.workspaceDir);
@@ -65749,10 +66174,10 @@ ${tail}`)));
65749
66174
  });
65750
66175
  }
65751
66176
  function requireAbsolute(value, field) {
65752
- if (!value || !path19.isAbsolute(value)) {
66177
+ if (!value || !path20.isAbsolute(value)) {
65753
66178
  throw new Error(`${field} must be an absolute path`);
65754
66179
  }
65755
- return path19.resolve(value);
66180
+ return path20.resolve(value);
65756
66181
  }
65757
66182
  function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
65758
66183
  if (!plan.customWorkspaceField)
@@ -65762,14 +66187,14 @@ function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
65762
66187
  if (reason) {
65763
66188
  throw new Error(`${plan.customWorkspaceField} must point to a project folder, not ${reason}: ${normalized}`);
65764
66189
  }
65765
- const defaultWorkspace = path19.resolve(plan.defaultWorkspaceDir);
66190
+ const defaultWorkspace = path20.resolve(plan.defaultWorkspaceDir);
65766
66191
  if (isAncestorPath(normalized, defaultWorkspace) || normalized === defaultWorkspace) {
65767
66192
  throw new Error(`${plan.customWorkspaceField} must not point at daemon state directories: ${normalized}`);
65768
66193
  }
65769
66194
  }
65770
66195
  function assertWritableWorkspaceDir(dir) {
65771
66196
  fs12.accessSync(dir, fs12.constants.R_OK | fs12.constants.W_OK | fs12.constants.X_OK);
65772
- const probe = path19.join(dir, `.parall-workspace-check-${process.pid}-${Date.now()}`);
66197
+ const probe = path20.join(dir, `.parall-workspace-check-${process.pid}-${Date.now()}`);
65773
66198
  const fd = fs12.openSync(probe, "wx", 384);
65774
66199
  fs12.closeSync(fd);
65775
66200
  fs12.unlinkSync(probe);
@@ -65833,11 +66258,11 @@ function workspacePathDenyReason(value) {
65833
66258
  return "";
65834
66259
  }
65835
66260
  function isAncestorPath(parent, child) {
65836
- const relative2 = path19.relative(parent, child);
65837
- return relative2 !== "" && !relative2.startsWith("..") && !path19.isAbsolute(relative2);
66261
+ const relative2 = path20.relative(parent, child);
66262
+ return relative2 !== "" && !relative2.startsWith("..") && !path20.isAbsolute(relative2);
65838
66263
  }
65839
66264
  function toPolicyPath(value) {
65840
- return path19.resolve(value).split(path19.sep).join("/");
66265
+ return path20.resolve(value).split(path20.sep).join("/");
65841
66266
  }
65842
66267
  function isNodeError(err) {
65843
66268
  return err instanceof Error && "code" in err;
@@ -65856,7 +66281,7 @@ var init_workspace = __esm({
65856
66281
  import { spawn as spawn6 } from "node:child_process";
65857
66282
  import * as fs13 from "node:fs";
65858
66283
  import * as os7 from "node:os";
65859
- import * as path20 from "node:path";
66284
+ import * as path21 from "node:path";
65860
66285
  function sleepCancellable(ms, signal) {
65861
66286
  if (signal.aborted)
65862
66287
  return Promise.resolve(false);
@@ -65885,6 +66310,7 @@ var init_supervisor = __esm({
65885
66310
  init_config();
65886
66311
  init_browser_profile_reconcile();
65887
66312
  init_filesystem();
66313
+ init_local_profile_control();
65888
66314
  init_home_isolation();
65889
66315
  init_runtimes();
65890
66316
  init_runtime_bin_resolver();
@@ -65938,6 +66364,11 @@ var init_supervisor = __esm({
65938
66364
  running = false;
65939
66365
  machineId = null;
65940
66366
  machineOrgId = null;
66367
+ // machines.created_by — the machine owner. The local control socket's profile
66368
+ // commands are authorized against it (requester must BE the owner); kept
66369
+ // fresh via bootstrap + refreshMachineConfig. Null until bootstrap → the
66370
+ // local control plane fails closed.
66371
+ machineCreatedBy = null;
65941
66372
  machineLlmSource = "parall";
65942
66373
  // Whether this machine contributes its local clips as a hub provider. The
65943
66374
  // org admin toggles it via PATCH /machines/{id}/provider-enabled; default true.
@@ -65956,6 +66387,7 @@ var init_supervisor = __esm({
65956
66387
  // browserProfilePool replaces the old single browserProfileManager.
65957
66388
  healthGate = null;
65958
66389
  browserProfilePool = null;
66390
+ localControl = null;
65959
66391
  clipManager = null;
65960
66392
  clipProvider = null;
65961
66393
  clipReconcileTimer = null;
@@ -66009,7 +66441,7 @@ var init_supervisor = __esm({
66009
66441
  this.migrateFlatLayout();
66010
66442
  if (process.env.PRLL_CLIP_RUNTIME_ENABLED === "true") {
66011
66443
  this.browserProfilePool = new BrowserProfilePool({
66012
- baseHomeDir: path20.join(this.config.rootStateDir, "bb-browser"),
66444
+ baseHomeDir: path21.join(this.config.rootStateDir, "bb-browser"),
66013
66445
  log: this.log,
66014
66446
  reportStatus: (profileId, status, errorMsg, generation) => {
66015
66447
  this.client.reportBrowserProfileStatus(profileId, status, errorMsg, generation).catch((err) => this.log.warn(`browser profile status report failed: ${String(err)}`));
@@ -66018,8 +66450,8 @@ var init_supervisor = __esm({
66018
66450
  proxyProbeUrl: this.resolveBrowserProxyProbeUrl()
66019
66451
  });
66020
66452
  this.clipManager = new ClipProcessManager({
66021
- clipsDir: path20.join(this.config.rootStateDir, "clips"),
66022
- dataDir: path20.join(this.config.rootStateDir, "clip-data"),
66453
+ clipsDir: path21.join(this.config.rootStateDir, "clips"),
66454
+ dataDir: path21.join(this.config.rootStateDir, "clip-data"),
66023
66455
  browserProfileManager: this.browserProfilePool,
66024
66456
  // Execution side: nested browser dependency invokes resolve their
66025
66457
  // binding and route through the hub (no local shortcut).
@@ -66039,6 +66471,7 @@ var init_supervisor = __esm({
66039
66471
  await this.applyClipProviderState();
66040
66472
  this.startClipReconcileTimer();
66041
66473
  }
66474
+ this.localControl = await startLocalProfileControl(this.localProfileControlDeps());
66042
66475
  void this.detectAndReportRuntimes(true);
66043
66476
  this.runtimeDetectTimer = setInterval(() => {
66044
66477
  void this.detectAndReportRuntimes(false);
@@ -66164,6 +66597,10 @@ var init_supervisor = __esm({
66164
66597
  }
66165
66598
  exits.push(this.terminateChild(state));
66166
66599
  }
66600
+ if (this.localControl) {
66601
+ exits.push(this.localControl.stop());
66602
+ this.localControl = null;
66603
+ }
66167
66604
  if (this.clipProvider) {
66168
66605
  exits.push(this.clipProvider.disconnect());
66169
66606
  this.clipProvider = null;
@@ -66192,6 +66629,7 @@ var init_supervisor = __esm({
66192
66629
  const machine = await this.client.getMachineSelf();
66193
66630
  this.machineId = machine.id;
66194
66631
  this.machineOrgId = machine.org_id;
66632
+ this.machineCreatedBy = machine.created_by ?? null;
66195
66633
  this.machineLlmSource = machine.llm_source ?? "parall";
66196
66634
  this.machineProviderEnabled = machine.provider_enabled ?? true;
66197
66635
  this.machineClipProviderUrl = machine.clip_provider_url ?? null;
@@ -66365,12 +66803,12 @@ var init_supervisor = __esm({
66365
66803
  */
66366
66804
  migrateFlatLayout() {
66367
66805
  const root = this.config.rootStateDir;
66368
- const agentsDir = path20.join(root, "agents");
66369
- const flatWorkspace = path20.join(root, "workspace");
66806
+ const agentsDir = path21.join(root, "agents");
66807
+ const flatWorkspace = path21.join(root, "workspace");
66370
66808
  if (!fs13.existsSync(flatWorkspace) || fs13.existsSync(agentsDir))
66371
66809
  return;
66372
66810
  let ownerAgentId;
66373
- const sessionsDir = path20.join(root, "sessions");
66811
+ const sessionsDir = path21.join(root, "sessions");
66374
66812
  if (fs13.existsSync(sessionsDir)) {
66375
66813
  try {
66376
66814
  for (const file of fs13.readdirSync(sessionsDir)) {
@@ -66387,13 +66825,13 @@ var init_supervisor = __esm({
66387
66825
  }
66388
66826
  }
66389
66827
  const targetId = ownerAgentId ?? "_orphan";
66390
- const targetDir = path20.join(agentsDir, targetId);
66828
+ const targetDir = path21.join(agentsDir, targetId);
66391
66829
  try {
66392
66830
  fs13.mkdirSync(targetDir, { recursive: true });
66393
66831
  for (const sub of ["workspace", "sessions", "dispatch-context"]) {
66394
- const src = path20.join(root, sub);
66832
+ const src = path21.join(root, sub);
66395
66833
  if (fs13.existsSync(src)) {
66396
- fs13.renameSync(src, path20.join(targetDir, sub));
66834
+ fs13.renameSync(src, path21.join(targetDir, sub));
66397
66835
  }
66398
66836
  }
66399
66837
  this.log.info(`migrated legacy flat state \u2192 agents/${targetId}/`);
@@ -66527,6 +66965,28 @@ var init_supervisor = __esm({
66527
66965
  const op = () => this.handleBrowserProfileLifecycle(data, sinceSeq);
66528
66966
  return data.action === "open" ? this.enqueueBrowserProfileRevive(data.profile_id, op) : this.enqueueBrowserProfileOp(data.profile_id, op);
66529
66967
  }
66968
+ /**
66969
+ * What the supervisor lends the local control plane: identity, pool, queues.
66970
+ * Getters, not values — owner and pool both change over the daemon's life
66971
+ * (bootstrap / refresh / provider state), so the handler must read what is
66972
+ * true AT CALL TIME; a snapshot could authorize against a stale owner.
66973
+ *
66974
+ * One definition, used by both `run()` and the authorization tests, so the
66975
+ * matrix under test is wired exactly like production.
66976
+ */
66977
+ localProfileControlDeps() {
66978
+ return {
66979
+ log: this.log,
66980
+ machineId: () => this.machineId,
66981
+ orgId: () => this.machineOrgId,
66982
+ owner: () => this.machineCreatedBy,
66983
+ pool: () => this.browserProfilePool,
66984
+ listProfiles: () => this.client.listMachineBrowserProfiles(),
66985
+ enqueueRevive: (id, op) => this.enqueueBrowserProfileRevive(id, op),
66986
+ enqueueOp: (id, op) => this.enqueueBrowserProfileOp(id, op),
66987
+ wipeBeforeRevive: (pool, id, resetGen, gen) => this.wipeBeforeRevive(pool, id, resetGen, gen)
66988
+ };
66989
+ }
66530
66990
  enqueueBrowserProfileOp(profileId, op) {
66531
66991
  const previous = this.browserProfileOpQueues.get(profileId) ?? Promise.resolve();
66532
66992
  const next = previous.catch(() => {
@@ -66689,7 +67149,7 @@ var init_supervisor = __esm({
66689
67149
  return this.runtimeDetectInFlight;
66690
67150
  }
66691
67151
  machineClipToConfig(clip) {
66692
- const clipPath = path20.join(this.config.rootStateDir, "clips", clip.alias);
67152
+ const clipPath = path21.join(this.config.rootStateDir, "clips", clip.alias);
66693
67153
  return {
66694
67154
  clipId: clip.clip_id,
66695
67155
  name: clip.alias,
@@ -66755,7 +67215,7 @@ var init_supervisor = __esm({
66755
67215
  if (!sourceRef) {
66756
67216
  throw new Error(`registry clip "${config.name}" is missing source_ref`);
66757
67217
  }
66758
- const expectedPath = path20.join(this.config.rootStateDir, "clips", config.name);
67218
+ const expectedPath = path21.join(this.config.rootStateDir, "clips", config.name);
66759
67219
  const localVersion = this.readInstalledClipVersion(expectedPath);
66760
67220
  if (localVersion && (!config.version || localVersion === config.version)) {
66761
67221
  return { ...config, path: expectedPath, source: expectedPath };
@@ -66773,7 +67233,7 @@ var init_supervisor = __esm({
66773
67233
  const result = await installClip({
66774
67234
  source,
66775
67235
  alias: config.name,
66776
- clipsDir: path20.join(this.config.rootStateDir, "clips"),
67236
+ clipsDir: path21.join(this.config.rootStateDir, "clips"),
66777
67237
  registryUrl: process.env.PRLL_PINIX_REGISTRY_URL?.trim() || void 0
66778
67238
  });
66779
67239
  this.log.info(`clip ensured: ${result.alias} v${result.version} at ${result.path}`);
@@ -66788,7 +67248,7 @@ var init_supervisor = __esm({
66788
67248
  readInstalledClipVersion(dir) {
66789
67249
  for (const file of ["clip.json", "package.json"]) {
66790
67250
  try {
66791
- const raw = fs13.readFileSync(path20.join(dir, file), "utf-8");
67251
+ const raw = fs13.readFileSync(path21.join(dir, file), "utf-8");
66792
67252
  const parsed = JSON.parse(raw);
66793
67253
  if (typeof parsed.version === "string" && parsed.version.trim()) {
66794
67254
  return parsed.version.trim();
@@ -66857,6 +67317,7 @@ var init_supervisor = __esm({
66857
67317
  async refreshMachineConfig() {
66858
67318
  try {
66859
67319
  const machine = await this.client.getMachineSelf();
67320
+ this.machineCreatedBy = machine.created_by ?? null;
66860
67321
  const newSource = machine.llm_source ?? "parall";
66861
67322
  if (newSource !== this.machineLlmSource) {
66862
67323
  this.log.info(`machine config refreshed: llm_source ${this.machineLlmSource} \u2192 ${newSource}`);
@@ -67511,7 +67972,7 @@ var init_daemon_main = __esm({
67511
67972
  init_daemon_paths();
67512
67973
  init_daemon_update_mode();
67513
67974
  import * as fs14 from "node:fs";
67514
- import * as path21 from "node:path";
67975
+ import * as path22 from "node:path";
67515
67976
  var UPDATE_EXIT_CODE2 = 42;
67516
67977
  function formatError2(reason) {
67517
67978
  if (reason instanceof Error) {
@@ -67536,7 +67997,7 @@ function clearRunningMarker(markerPath) {
67536
67997
  }
67537
67998
  function prepareDaemonBootstrap(env = process.env, args = process.argv.slice(2)) {
67538
67999
  const bundleDir = resolveBundleDir(env);
67539
- const runningMarker = path21.join(bundleDir, "daemon-running");
68000
+ const runningMarker = path22.join(bundleDir, "daemon-running");
67540
68001
  const lifecycleMarkerEnabled = args.length === 0 && !isSelfUpdateDisabledByEnv(env) && isSelfUpdateManaged(bundleDir, env);
67541
68002
  if (!lifecycleMarkerEnabled) {
67542
68003
  return { lifecycleMarkerEnabled: false, runningMarker, uncleanPrevExit: false };