@parall/daemon 1.32.1 → 1.33.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.
Files changed (46) hide show
  1. package/bundle/bb-browser-daemon.js +15628 -0
  2. package/bundle/buildDomTree.js +1501 -0
  3. package/bundle/manifest.json +19 -11
  4. package/bundle/parall-claude-agent.js +170 -22
  5. package/bundle/parall-codex-agent.js +170 -22
  6. package/bundle/parall-daemon.js +4625 -2854
  7. package/bundle/parall-openclaw-agent.js +4 -3
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +8 -2
  10. package/dist/clip-runtime/browser-dependency.d.ts +20 -0
  11. package/dist/clip-runtime/browser-dependency.d.ts.map +1 -0
  12. package/dist/clip-runtime/browser-dependency.js +52 -0
  13. package/dist/clip-runtime/browser-profile-manager.d.ts +67 -0
  14. package/dist/clip-runtime/browser-profile-manager.d.ts.map +1 -0
  15. package/dist/clip-runtime/browser-profile-manager.js +595 -0
  16. package/dist/clip-runtime/clip-provider.d.ts +10 -1
  17. package/dist/clip-runtime/clip-provider.d.ts.map +1 -1
  18. package/dist/clip-runtime/clip-provider.js +63 -21
  19. package/dist/clip-runtime/hub-client.d.ts +79 -0
  20. package/dist/clip-runtime/hub-client.d.ts.map +1 -0
  21. package/dist/clip-runtime/hub-client.js +320 -0
  22. package/dist/clip-runtime/index.d.ts +2 -0
  23. package/dist/clip-runtime/index.d.ts.map +1 -1
  24. package/dist/clip-runtime/index.js +2 -0
  25. package/dist/clip-runtime/ipc.d.ts +6 -0
  26. package/dist/clip-runtime/ipc.d.ts.map +1 -1
  27. package/dist/clip-runtime/manifest.d.ts +16 -8
  28. package/dist/clip-runtime/manifest.d.ts.map +1 -1
  29. package/dist/clip-runtime/manifest.js +13 -0
  30. package/dist/clip-runtime/process-manager.d.ts +55 -3
  31. package/dist/clip-runtime/process-manager.d.ts.map +1 -1
  32. package/dist/clip-runtime/process-manager.js +226 -48
  33. package/dist/clip-runtime/process.d.ts +15 -1
  34. package/dist/clip-runtime/process.d.ts.map +1 -1
  35. package/dist/clip-runtime/process.js +73 -10
  36. package/dist/config.d.ts +9 -0
  37. package/dist/config.d.ts.map +1 -1
  38. package/dist/config.js +12 -0
  39. package/dist/index.js +46 -5
  40. package/dist/runtime-bin-resolver.d.ts +7 -0
  41. package/dist/runtime-bin-resolver.d.ts.map +1 -0
  42. package/dist/runtime-bin-resolver.js +292 -0
  43. package/dist/supervisor.d.ts +53 -4
  44. package/dist/supervisor.d.ts.map +1 -1
  45. package/dist/supervisor.js +449 -117
  46. package/package.json +7 -6
@@ -1,28 +1,36 @@
1
1
  {
2
- "version": "1.32.1",
3
- "built_at": "2026-06-02T14:24:57.505Z",
2
+ "version": "1.33.0",
3
+ "built_at": "2026-06-08T13:37:00.737Z",
4
4
  "min_node_version": "20.0.0",
5
5
  "files": {
6
+ "bb-browser-daemon.js": {
7
+ "sha256": "9d80592a220f94141c57b2729e5a3ae0db8796274924612b38ce066eef54d435",
8
+ "size": 575667
9
+ },
10
+ "buildDomTree.js": {
11
+ "sha256": "485c7f690be7fd517e84cb0281de5e399404ac25630a564d9c1d2aeb2c32e064",
12
+ "size": 52306
13
+ },
6
14
  "package.json": {
7
15
  "sha256": "1239d4d885dcad42201a27ed9324f8f0f760b78700d8db9ced39a511cffe7eae",
8
16
  "size": 18
9
17
  },
10
18
  "parall-claude-agent.js": {
11
- "sha256": "eeb0e9458c678d1edc467c0e1d2dc25a0fc5d6d110ab01a5997a2de4fdce776c",
12
- "size": 1537100
19
+ "sha256": "fd2395bb9ba5bc2912175d42419c4073ae581bd9382be6447d9169ce177e915c",
20
+ "size": 1544348
13
21
  },
14
22
  "parall-codex-agent.js": {
15
- "sha256": "b9af840b8d787d2725540e432b416a489851d01a969b0eb45a0291dec8d70362",
16
- "size": 1568189
23
+ "sha256": "fa93fb3b2aab23b6f3ecd218a0c0124bbe323af11c0ced898c2d057ad293f03b",
24
+ "size": 1575437
17
25
  },
18
26
  "parall-daemon.js": {
19
- "sha256": "44fcf2c6817a56243bd3391eaf49decd5ce4d8953d0bebb1cfba06a54e5719d7",
20
- "size": 1499163
27
+ "sha256": "83d37677018aa1bf0a37df14baaade7738bec2f907fa5d1f66b4bcad77430535",
28
+ "size": 1565851
21
29
  },
22
30
  "parall-openclaw-agent.js": {
23
- "sha256": "657263cec61e6d26496389ec90ffe0716616a20e082e12c5a17bf6ffd5d1cdd6",
24
- "size": 9727
31
+ "sha256": "505433b4bf3a4b8dbb7b96978d8693d6c48079f4513282ff1ee59a6d13b3eddf",
32
+ "size": 9801
25
33
  }
26
34
  },
27
- "signature": "03XcA+dVTwzforsxVlxsVXHjHJMKJ/yfCHsrddoGTNN7PjK7hdmkT3fRsQqzA3M1hni+7AT++ZGKT4k25Oc6Cg=="
35
+ "signature": "z7sT/o8aV5gfuQpr9TYQ+IkY3+IfdC5EiKrFKoQ4kz3TO1zXBC1RQ4xh1M0cFdB9KCDbaGeti2smdYAAczoCAQ=="
28
36
  }
@@ -27163,6 +27163,7 @@ var ENDPOINTS = {
27163
27163
  MACHINE_AGENT_DAEMON_CONFIG: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/daemon-config`,
27164
27164
  MACHINE_AGENT_WORKSPACE_SETUP: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
27165
27165
  MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
27166
+ MACHINE_PROVIDER_ENABLED: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/provider-enabled`,
27166
27167
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
27167
27168
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
27168
27169
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
@@ -27176,8 +27177,9 @@ var ENDPOINTS = {
27176
27177
  MACHINES_ME: `${API_BASE}/machines/me`,
27177
27178
  MACHINES_ME_AGENTS: `${API_BASE}/machines/me/agents`,
27178
27179
  MACHINES_ME_HEALTH: `${API_BASE}/machines/me/health`,
27179
- MACHINES_ME_CLIP_INSTALLS: `${API_BASE}/machines/me/clip-installs`,
27180
- MACHINES_ME_CLIP_INSTALL_DONE: (clipId) => `${API_BASE}/machines/me/clip-installs/${clipId}/installed`,
27180
+ MACHINES_ME_CLIPS: `${API_BASE}/machines/me/clips`,
27181
+ MACHINES_ME_BROWSER_PROFILES: `${API_BASE}/machines/me/browser-profiles`,
27182
+ MACHINES_ME_BROWSER_PROFILE_STATUS: (profileId) => `${API_BASE}/machines/me/browser-profiles/${profileId}/status`,
27181
27183
  MACHINES_ME_AGENT_LAUNCH_CREDENTIAL: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/launch-credential`,
27182
27184
  MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
27183
27185
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
@@ -27276,6 +27278,7 @@ var ENDPOINTS = {
27276
27278
  DISPATCH_RECEIVED: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/received`,
27277
27279
  DISPATCH_ACK: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/ack`,
27278
27280
  DISPATCH_ACK_BY_ID: (orgId, id) => `${API_BASE}/orgs/${orgId}/dispatch/${id}/ack`,
27281
+ DISPATCH_EXPIRE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/expire`,
27279
27282
  DISPATCH_BY_MESSAGES: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/by-messages`,
27280
27283
  // Unread
27281
27284
  UNREAD: `${API_BASE}/me/unread`,
@@ -27314,6 +27317,13 @@ var ENDPOINTS = {
27314
27317
  AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
27315
27318
  CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
27316
27319
  CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
27320
+ BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
27321
+ BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
27322
+ BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
27323
+ BROWSER_PROFILE_STOP: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/stop`,
27324
+ BROWSER_PROFILE_RESET: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/reset`,
27325
+ BROWSER_PROFILE_CONSENTS: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
27326
+ BROWSER_PROFILE_CONSENT: (orgId, profileId, clipId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
27317
27327
  // Clip registry (global, served by clip-service → Pinix Hub proxy)
27318
27328
  CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`
27319
27329
  };
@@ -27388,9 +27398,10 @@ var WS_EVENTS = {
27388
27398
  MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
27389
27399
  MACHINE_UPDATE: "machine.update",
27390
27400
  MACHINE_CONFIG_UPDATED: "machine.config.updated",
27391
- MACHINE_CLIP_INSTALL: "machine.clip.install",
27401
+ MACHINE_CLIP_SYNC: "machine.clip.sync",
27402
+ MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
27392
27403
  AGENT_NEW_SESSION: "agent.new_session",
27393
- CLIP_INSTALLED: "clip.installed",
27404
+ CLIP_CREATED: "clip.created",
27394
27405
  CLIP_REMOVED: "clip.removed",
27395
27406
  CLIP_UPDATED: "clip.updated"
27396
27407
  };
@@ -27843,8 +27854,8 @@ var ParallClient = class _ParallClient {
27843
27854
  const res = await this.request("GET", ENDPOINTS.CHAT_MEMBERS(orgId, chatId));
27844
27855
  return res.data;
27845
27856
  }
27846
- async addChatMember(orgId, chatId, userId, role) {
27847
- return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId, role });
27857
+ async addChatMember(orgId, chatId, userId) {
27858
+ return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId });
27848
27859
  }
27849
27860
  async removeChatMember(orgId, chatId, userId) {
27850
27861
  return this.request("DELETE", ENDPOINTS.CHAT_MEMBER(orgId, chatId, userId));
@@ -28103,6 +28114,16 @@ var ParallClient = class _ParallClient {
28103
28114
  llm_source: llmSource2
28104
28115
  });
28105
28116
  }
28117
+ /**
28118
+ * Toggle whether the machine contributes its local clips as a hub provider
28119
+ * — org-admin-gated (RequireOrgAdmin), like all machine management. See
28120
+ * docs/engineering-design/clip-provider-sharing-design.md.
28121
+ */
28122
+ async patchMachineProviderEnabled(orgId, machineId, providerEnabled) {
28123
+ return this.request("PATCH", ENDPOINTS.MACHINE_PROVIDER_ENABLED(orgId, machineId), {
28124
+ provider_enabled: providerEnabled
28125
+ });
28126
+ }
28106
28127
  /** Get machine-level runtime auth state. */
28107
28128
  async getMachineRuntimeAuth(orgId, machineId) {
28108
28129
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
@@ -28136,25 +28157,39 @@ var ParallClient = class _ParallClient {
28136
28157
  const res = await this.request("GET", ENDPOINTS.MACHINES_ME_AGENTS);
28137
28158
  return res.data;
28138
28159
  }
28139
- /** `GET /machines/me/clip-installs` — registry clips this machine should
28140
- * install but hasn't yet (durable reconcile, mck_-authed). */
28141
- async listClipInstalls() {
28142
- const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIP_INSTALLS);
28160
+ /** `GET /machines/me/clips` — executable Clip definitions assigned to this machine. */
28161
+ async listMachineClips() {
28162
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIPS);
28143
28163
  return res.data;
28144
28164
  }
28145
- /** `POST /machines/me/clip-installs/{clipId}/installed` — report a finished install. */
28146
- async reportClipInstall(clipId, version) {
28147
- return this.request("POST", ENDPOINTS.MACHINES_ME_CLIP_INSTALL_DONE(clipId), version ? { version } : void 0);
28165
+ /** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine. */
28166
+ async listMachineBrowserProfiles() {
28167
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_BROWSER_PROFILES);
28168
+ return res.data;
28169
+ }
28170
+ /** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
28171
+ async reportBrowserProfileStatus(profileId, status, errorMsg) {
28172
+ await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
28173
+ status,
28174
+ ...errorMsg ? { error_msg: errorMsg } : {}
28175
+ });
28148
28176
  }
28149
28177
  /**
28150
- * `POST /machines/me/health` — bump the Machine's `updated_at` to now.
28151
- * Body is intentionally empty; the server ignores any payload. The
28152
- * daemon should call this on a fixed cadence (e.g. every 30s) so an
28153
- * external observer can detect a wedged supervisor.
28178
+ * `POST /machines/me/health` — bump the Machine's `updated_at` to now and
28179
+ * report daemon state. The daemon should call this on a fixed cadence (e.g.
28180
+ * every 30s) so an external observer can detect a wedged supervisor. Both
28181
+ * fields are optional and only persisted when changed:
28182
+ * - `daemonVersion` — the running bundle/launcher version.
28183
+ * - `selfUpdateCapable` — whether the daemon can act on a machine.update
28184
+ * signal (true under a service manager, false for bare `npx` foreground).
28154
28185
  */
28155
- async postMachineHeartbeat(daemonVersion) {
28156
- const body = daemonVersion ? { daemon_version: daemonVersion } : void 0;
28157
- return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, body);
28186
+ async postMachineHeartbeat(opts) {
28187
+ const body = {};
28188
+ if (opts?.daemonVersion)
28189
+ body.daemon_version = opts.daemonVersion;
28190
+ if (opts?.selfUpdateCapable !== void 0)
28191
+ body.self_update_capable = opts.selfUpdateCapable;
28192
+ return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
28158
28193
  }
28159
28194
  async reportAgentWorkspaceState(agentId, state) {
28160
28195
  const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
@@ -28256,6 +28291,10 @@ var ParallClient = class _ParallClient {
28256
28291
  async ackDispatchByID(orgId, id) {
28257
28292
  return this.request("POST", ENDPOINTS.DISPATCH_ACK_BY_ID(orgId, id));
28258
28293
  }
28294
+ async expireDispatch(orgId, maxAgeHours) {
28295
+ const params = maxAgeHours !== void 0 ? { max_age_hours: String(maxAgeHours) } : void 0;
28296
+ return this.request("POST", ENDPOINTS.DISPATCH_EXPIRE(orgId), void 0, params);
28297
+ }
28259
28298
  async getDispatchByMessages(orgId, chatId, messageIds) {
28260
28299
  const params = { chat_id: chatId, message_ids: messageIds.join(",") };
28261
28300
  return this.request("GET", ENDPOINTS.DISPATCH_BY_MESSAGES(orgId), void 0, params);
@@ -28736,6 +28775,41 @@ var ParallClient = class _ParallClient {
28736
28775
  const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
28737
28776
  return resp.data;
28738
28777
  }
28778
+ async listBrowserProfiles(orgId) {
28779
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILES(orgId));
28780
+ return resp.data;
28781
+ }
28782
+ async createBrowserProfile(orgId, req) {
28783
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILES(orgId), req);
28784
+ }
28785
+ async getBrowserProfile(orgId, profileId) {
28786
+ return this.request("GET", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28787
+ }
28788
+ async updateBrowserProfile(orgId, profileId, req) {
28789
+ return this.request("PATCH", ENDPOINTS.BROWSER_PROFILE(orgId, profileId), req);
28790
+ }
28791
+ async deleteBrowserProfile(orgId, profileId) {
28792
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28793
+ }
28794
+ async openBrowserProfile(orgId, profileId, req = {}) {
28795
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_OPEN(orgId, profileId), req);
28796
+ }
28797
+ async stopBrowserProfile(orgId, profileId) {
28798
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_STOP(orgId, profileId), {});
28799
+ }
28800
+ async resetBrowserProfile(orgId, profileId) {
28801
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_RESET(orgId, profileId));
28802
+ }
28803
+ async listBrowserProfileConsents(orgId, profileId) {
28804
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId));
28805
+ return resp.data;
28806
+ }
28807
+ async grantBrowserProfileConsent(orgId, profileId, req) {
28808
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId), req);
28809
+ }
28810
+ async revokeBrowserProfileConsent(orgId, profileId, clipId) {
28811
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE_CONSENT(orgId, profileId, clipId));
28812
+ }
28739
28813
  async listRegistryClips(q) {
28740
28814
  const url = ENDPOINTS.CLIP_REGISTRY() + (q ? `?q=${encodeURIComponent(q)}` : "");
28741
28815
  const resp = await this.request("GET", url);
@@ -30719,8 +30793,28 @@ var ParallAgentGateway = class {
30719
30793
  return dispatched;
30720
30794
  }
30721
30795
  async catchUpFromDispatch() {
30796
+ const OVERFLOW_THRESHOLD = 500;
30797
+ const EXPIRE_AGE_HOURS = 24;
30798
+ const CATCHUP_MAX = 10;
30799
+ let expireSummary = null;
30800
+ let overflowMode = false;
30801
+ try {
30802
+ const { count } = await this.opts.client.getDispatchPendingCount(this.opts.config.org_id);
30803
+ if (count > OVERFLOW_THRESHOLD) {
30804
+ overflowMode = true;
30805
+ const result = await this.opts.client.expireDispatch(this.opts.config.org_id, EXPIRE_AGE_HOURS);
30806
+ if (result.total > 0) {
30807
+ this.opts.log?.warn(`dispatch catch-up overflow: ${count} pending, expired ${result.total} events older than ${EXPIRE_AGE_HOURS}h`);
30808
+ expireSummary = this.buildOfflineSummary(result.groups);
30809
+ }
30810
+ }
30811
+ } catch (err) {
30812
+ this.opts.log?.warn(`dispatch catch-up overflow check failed: ${String(err)}`);
30813
+ }
30722
30814
  let cursor;
30723
30815
  let processed = 0;
30816
+ let skipped = 0;
30817
+ const skippedByType = /* @__PURE__ */ new Map();
30724
30818
  do {
30725
30819
  const page = await this.opts.client.getDispatch(this.opts.config.org_id, {
30726
30820
  limit: 50,
@@ -30729,6 +30823,17 @@ var ParallAgentGateway = class {
30729
30823
  for (const item of page.data ?? []) {
30730
30824
  if (this.shuttingDown)
30731
30825
  break;
30826
+ if (overflowMode && processed >= CATCHUP_MAX) {
30827
+ try {
30828
+ await this.opts.client.ackDispatchByID(this.opts.config.org_id, item.id);
30829
+ skipped++;
30830
+ const key = item.event_type;
30831
+ skippedByType.set(key, (skippedByType.get(key) ?? 0) + 1);
30832
+ } catch {
30833
+ this.opts.log?.warn(`catch-up skip ack failed for ${item.id}, leaving pending`);
30834
+ }
30835
+ continue;
30836
+ }
30732
30837
  processed++;
30733
30838
  try {
30734
30839
  let dispatched = false;
@@ -30803,9 +30908,52 @@ var ParallAgentGateway = class {
30803
30908
  }
30804
30909
  cursor = !this.shuttingDown && page.has_more ? page.next_cursor : void 0;
30805
30910
  } while (cursor);
30806
- if (processed > 0) {
30807
- this.opts.log?.info(`dispatch catch-up: processed ${processed}`);
30911
+ if (expireSummary || skipped > 0) {
30912
+ const parts = [];
30913
+ if (expireSummary)
30914
+ parts.push(expireSummary);
30915
+ if (skipped > 0) {
30916
+ const recentLines = [...skippedByType.entries()].map(([type, count]) => `- ${count} recent ${type.replace(".", " ").replace("_", " ")} events`).join("\n");
30917
+ parts.push(expireSummary ? `Additionally, ${skipped} recent events exceeded the catch-up limit and were skipped:
30918
+ ${recentLines}` : `[Offline Summary] You were offline. ${skipped} pending events exceeded the catch-up limit and were skipped:
30919
+ ${recentLines}
30920
+
30921
+ Use your tools (read messages, check tasks) to review anything still relevant.`);
30922
+ }
30923
+ const fullSummary = parts.join("\n\n");
30924
+ this.pendingRestartNotification = this.pendingRestartNotification ? `${this.pendingRestartNotification}
30925
+
30926
+ ${fullSummary}` : fullSummary;
30927
+ }
30928
+ if (processed > 0 || skipped > 0) {
30929
+ this.opts.log?.info(`dispatch catch-up: processed ${processed}, skipped ${skipped}`);
30930
+ }
30931
+ }
30932
+ buildOfflineSummary(groups) {
30933
+ const lines = [
30934
+ "[Offline Summary] You were offline and had a large backlog of pending events. The following old events were skipped:"
30935
+ ];
30936
+ for (const g of groups) {
30937
+ const age = this.formatAge(g.oldest);
30938
+ if (g.chat_id && g.event_type === "message") {
30939
+ const name = g.chat_name ?? g.chat_id;
30940
+ lines.push(`- ${g.count} messages in "${name}" (oldest: ${age})`);
30941
+ } else {
30942
+ const label = g.event_type.replace(".", " ").replace("_", " ");
30943
+ lines.push(`- ${g.count} ${label} events (oldest: ${age})`);
30944
+ }
30808
30945
  }
30946
+ lines.push("");
30947
+ lines.push("These events were too old to process individually. Use your tools (read messages, check tasks) to review anything still relevant.");
30948
+ return lines.join("\n");
30949
+ }
30950
+ formatAge(iso) {
30951
+ const ms = Date.now() - new Date(iso).getTime();
30952
+ const hours = Math.floor(ms / 36e5);
30953
+ if (hours < 24)
30954
+ return `${hours}h ago`;
30955
+ const days = Math.floor(hours / 24);
30956
+ return `${days}d ago`;
30809
30957
  }
30810
30958
  async handleHello(data) {
30811
30959
  const { client, config, log: log2 } = this.opts;
@@ -27163,6 +27163,7 @@ var ENDPOINTS = {
27163
27163
  MACHINE_AGENT_DAEMON_CONFIG: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/daemon-config`,
27164
27164
  MACHINE_AGENT_WORKSPACE_SETUP: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
27165
27165
  MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
27166
+ MACHINE_PROVIDER_ENABLED: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/provider-enabled`,
27166
27167
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
27167
27168
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
27168
27169
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
@@ -27176,8 +27177,9 @@ var ENDPOINTS = {
27176
27177
  MACHINES_ME: `${API_BASE}/machines/me`,
27177
27178
  MACHINES_ME_AGENTS: `${API_BASE}/machines/me/agents`,
27178
27179
  MACHINES_ME_HEALTH: `${API_BASE}/machines/me/health`,
27179
- MACHINES_ME_CLIP_INSTALLS: `${API_BASE}/machines/me/clip-installs`,
27180
- MACHINES_ME_CLIP_INSTALL_DONE: (clipId) => `${API_BASE}/machines/me/clip-installs/${clipId}/installed`,
27180
+ MACHINES_ME_CLIPS: `${API_BASE}/machines/me/clips`,
27181
+ MACHINES_ME_BROWSER_PROFILES: `${API_BASE}/machines/me/browser-profiles`,
27182
+ MACHINES_ME_BROWSER_PROFILE_STATUS: (profileId) => `${API_BASE}/machines/me/browser-profiles/${profileId}/status`,
27181
27183
  MACHINES_ME_AGENT_LAUNCH_CREDENTIAL: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/launch-credential`,
27182
27184
  MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
27183
27185
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
@@ -27276,6 +27278,7 @@ var ENDPOINTS = {
27276
27278
  DISPATCH_RECEIVED: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/received`,
27277
27279
  DISPATCH_ACK: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/ack`,
27278
27280
  DISPATCH_ACK_BY_ID: (orgId, id) => `${API_BASE}/orgs/${orgId}/dispatch/${id}/ack`,
27281
+ DISPATCH_EXPIRE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/expire`,
27279
27282
  DISPATCH_BY_MESSAGES: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/by-messages`,
27280
27283
  // Unread
27281
27284
  UNREAD: `${API_BASE}/me/unread`,
@@ -27314,6 +27317,13 @@ var ENDPOINTS = {
27314
27317
  AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
27315
27318
  CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
27316
27319
  CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
27320
+ BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
27321
+ BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
27322
+ BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
27323
+ BROWSER_PROFILE_STOP: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/stop`,
27324
+ BROWSER_PROFILE_RESET: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/reset`,
27325
+ BROWSER_PROFILE_CONSENTS: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
27326
+ BROWSER_PROFILE_CONSENT: (orgId, profileId, clipId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
27317
27327
  // Clip registry (global, served by clip-service → Pinix Hub proxy)
27318
27328
  CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`
27319
27329
  };
@@ -27388,9 +27398,10 @@ var WS_EVENTS = {
27388
27398
  MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
27389
27399
  MACHINE_UPDATE: "machine.update",
27390
27400
  MACHINE_CONFIG_UPDATED: "machine.config.updated",
27391
- MACHINE_CLIP_INSTALL: "machine.clip.install",
27401
+ MACHINE_CLIP_SYNC: "machine.clip.sync",
27402
+ MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
27392
27403
  AGENT_NEW_SESSION: "agent.new_session",
27393
- CLIP_INSTALLED: "clip.installed",
27404
+ CLIP_CREATED: "clip.created",
27394
27405
  CLIP_REMOVED: "clip.removed",
27395
27406
  CLIP_UPDATED: "clip.updated"
27396
27407
  };
@@ -27843,8 +27854,8 @@ var ParallClient = class _ParallClient {
27843
27854
  const res = await this.request("GET", ENDPOINTS.CHAT_MEMBERS(orgId, chatId));
27844
27855
  return res.data;
27845
27856
  }
27846
- async addChatMember(orgId, chatId, userId, role) {
27847
- return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId, role });
27857
+ async addChatMember(orgId, chatId, userId) {
27858
+ return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId });
27848
27859
  }
27849
27860
  async removeChatMember(orgId, chatId, userId) {
27850
27861
  return this.request("DELETE", ENDPOINTS.CHAT_MEMBER(orgId, chatId, userId));
@@ -28103,6 +28114,16 @@ var ParallClient = class _ParallClient {
28103
28114
  llm_source: llmSource2
28104
28115
  });
28105
28116
  }
28117
+ /**
28118
+ * Toggle whether the machine contributes its local clips as a hub provider
28119
+ * — org-admin-gated (RequireOrgAdmin), like all machine management. See
28120
+ * docs/engineering-design/clip-provider-sharing-design.md.
28121
+ */
28122
+ async patchMachineProviderEnabled(orgId, machineId, providerEnabled) {
28123
+ return this.request("PATCH", ENDPOINTS.MACHINE_PROVIDER_ENABLED(orgId, machineId), {
28124
+ provider_enabled: providerEnabled
28125
+ });
28126
+ }
28106
28127
  /** Get machine-level runtime auth state. */
28107
28128
  async getMachineRuntimeAuth(orgId, machineId) {
28108
28129
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
@@ -28136,25 +28157,39 @@ var ParallClient = class _ParallClient {
28136
28157
  const res = await this.request("GET", ENDPOINTS.MACHINES_ME_AGENTS);
28137
28158
  return res.data;
28138
28159
  }
28139
- /** `GET /machines/me/clip-installs` — registry clips this machine should
28140
- * install but hasn't yet (durable reconcile, mck_-authed). */
28141
- async listClipInstalls() {
28142
- const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIP_INSTALLS);
28160
+ /** `GET /machines/me/clips` — executable Clip definitions assigned to this machine. */
28161
+ async listMachineClips() {
28162
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIPS);
28143
28163
  return res.data;
28144
28164
  }
28145
- /** `POST /machines/me/clip-installs/{clipId}/installed` — report a finished install. */
28146
- async reportClipInstall(clipId, version) {
28147
- return this.request("POST", ENDPOINTS.MACHINES_ME_CLIP_INSTALL_DONE(clipId), version ? { version } : void 0);
28165
+ /** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine. */
28166
+ async listMachineBrowserProfiles() {
28167
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_BROWSER_PROFILES);
28168
+ return res.data;
28169
+ }
28170
+ /** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
28171
+ async reportBrowserProfileStatus(profileId, status, errorMsg) {
28172
+ await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
28173
+ status,
28174
+ ...errorMsg ? { error_msg: errorMsg } : {}
28175
+ });
28148
28176
  }
28149
28177
  /**
28150
- * `POST /machines/me/health` — bump the Machine's `updated_at` to now.
28151
- * Body is intentionally empty; the server ignores any payload. The
28152
- * daemon should call this on a fixed cadence (e.g. every 30s) so an
28153
- * external observer can detect a wedged supervisor.
28178
+ * `POST /machines/me/health` — bump the Machine's `updated_at` to now and
28179
+ * report daemon state. The daemon should call this on a fixed cadence (e.g.
28180
+ * every 30s) so an external observer can detect a wedged supervisor. Both
28181
+ * fields are optional and only persisted when changed:
28182
+ * - `daemonVersion` — the running bundle/launcher version.
28183
+ * - `selfUpdateCapable` — whether the daemon can act on a machine.update
28184
+ * signal (true under a service manager, false for bare `npx` foreground).
28154
28185
  */
28155
- async postMachineHeartbeat(daemonVersion) {
28156
- const body = daemonVersion ? { daemon_version: daemonVersion } : void 0;
28157
- return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, body);
28186
+ async postMachineHeartbeat(opts) {
28187
+ const body = {};
28188
+ if (opts?.daemonVersion)
28189
+ body.daemon_version = opts.daemonVersion;
28190
+ if (opts?.selfUpdateCapable !== void 0)
28191
+ body.self_update_capable = opts.selfUpdateCapable;
28192
+ return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
28158
28193
  }
28159
28194
  async reportAgentWorkspaceState(agentId, state) {
28160
28195
  const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
@@ -28256,6 +28291,10 @@ var ParallClient = class _ParallClient {
28256
28291
  async ackDispatchByID(orgId, id) {
28257
28292
  return this.request("POST", ENDPOINTS.DISPATCH_ACK_BY_ID(orgId, id));
28258
28293
  }
28294
+ async expireDispatch(orgId, maxAgeHours) {
28295
+ const params = maxAgeHours !== void 0 ? { max_age_hours: String(maxAgeHours) } : void 0;
28296
+ return this.request("POST", ENDPOINTS.DISPATCH_EXPIRE(orgId), void 0, params);
28297
+ }
28259
28298
  async getDispatchByMessages(orgId, chatId, messageIds) {
28260
28299
  const params = { chat_id: chatId, message_ids: messageIds.join(",") };
28261
28300
  return this.request("GET", ENDPOINTS.DISPATCH_BY_MESSAGES(orgId), void 0, params);
@@ -28736,6 +28775,41 @@ var ParallClient = class _ParallClient {
28736
28775
  const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
28737
28776
  return resp.data;
28738
28777
  }
28778
+ async listBrowserProfiles(orgId) {
28779
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILES(orgId));
28780
+ return resp.data;
28781
+ }
28782
+ async createBrowserProfile(orgId, req) {
28783
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILES(orgId), req);
28784
+ }
28785
+ async getBrowserProfile(orgId, profileId) {
28786
+ return this.request("GET", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28787
+ }
28788
+ async updateBrowserProfile(orgId, profileId, req) {
28789
+ return this.request("PATCH", ENDPOINTS.BROWSER_PROFILE(orgId, profileId), req);
28790
+ }
28791
+ async deleteBrowserProfile(orgId, profileId) {
28792
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28793
+ }
28794
+ async openBrowserProfile(orgId, profileId, req = {}) {
28795
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_OPEN(orgId, profileId), req);
28796
+ }
28797
+ async stopBrowserProfile(orgId, profileId) {
28798
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_STOP(orgId, profileId), {});
28799
+ }
28800
+ async resetBrowserProfile(orgId, profileId) {
28801
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_RESET(orgId, profileId));
28802
+ }
28803
+ async listBrowserProfileConsents(orgId, profileId) {
28804
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId));
28805
+ return resp.data;
28806
+ }
28807
+ async grantBrowserProfileConsent(orgId, profileId, req) {
28808
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId), req);
28809
+ }
28810
+ async revokeBrowserProfileConsent(orgId, profileId, clipId) {
28811
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE_CONSENT(orgId, profileId, clipId));
28812
+ }
28739
28813
  async listRegistryClips(q) {
28740
28814
  const url = ENDPOINTS.CLIP_REGISTRY() + (q ? `?q=${encodeURIComponent(q)}` : "");
28741
28815
  const resp = await this.request("GET", url);
@@ -30719,8 +30793,28 @@ var ParallAgentGateway = class {
30719
30793
  return dispatched;
30720
30794
  }
30721
30795
  async catchUpFromDispatch() {
30796
+ const OVERFLOW_THRESHOLD = 500;
30797
+ const EXPIRE_AGE_HOURS = 24;
30798
+ const CATCHUP_MAX = 10;
30799
+ let expireSummary = null;
30800
+ let overflowMode = false;
30801
+ try {
30802
+ const { count } = await this.opts.client.getDispatchPendingCount(this.opts.config.org_id);
30803
+ if (count > OVERFLOW_THRESHOLD) {
30804
+ overflowMode = true;
30805
+ const result = await this.opts.client.expireDispatch(this.opts.config.org_id, EXPIRE_AGE_HOURS);
30806
+ if (result.total > 0) {
30807
+ this.opts.log?.warn(`dispatch catch-up overflow: ${count} pending, expired ${result.total} events older than ${EXPIRE_AGE_HOURS}h`);
30808
+ expireSummary = this.buildOfflineSummary(result.groups);
30809
+ }
30810
+ }
30811
+ } catch (err) {
30812
+ this.opts.log?.warn(`dispatch catch-up overflow check failed: ${String(err)}`);
30813
+ }
30722
30814
  let cursor;
30723
30815
  let processed = 0;
30816
+ let skipped = 0;
30817
+ const skippedByType = /* @__PURE__ */ new Map();
30724
30818
  do {
30725
30819
  const page = await this.opts.client.getDispatch(this.opts.config.org_id, {
30726
30820
  limit: 50,
@@ -30729,6 +30823,17 @@ var ParallAgentGateway = class {
30729
30823
  for (const item of page.data ?? []) {
30730
30824
  if (this.shuttingDown)
30731
30825
  break;
30826
+ if (overflowMode && processed >= CATCHUP_MAX) {
30827
+ try {
30828
+ await this.opts.client.ackDispatchByID(this.opts.config.org_id, item.id);
30829
+ skipped++;
30830
+ const key = item.event_type;
30831
+ skippedByType.set(key, (skippedByType.get(key) ?? 0) + 1);
30832
+ } catch {
30833
+ this.opts.log?.warn(`catch-up skip ack failed for ${item.id}, leaving pending`);
30834
+ }
30835
+ continue;
30836
+ }
30732
30837
  processed++;
30733
30838
  try {
30734
30839
  let dispatched = false;
@@ -30803,9 +30908,52 @@ var ParallAgentGateway = class {
30803
30908
  }
30804
30909
  cursor = !this.shuttingDown && page.has_more ? page.next_cursor : void 0;
30805
30910
  } while (cursor);
30806
- if (processed > 0) {
30807
- this.opts.log?.info(`dispatch catch-up: processed ${processed}`);
30911
+ if (expireSummary || skipped > 0) {
30912
+ const parts = [];
30913
+ if (expireSummary)
30914
+ parts.push(expireSummary);
30915
+ if (skipped > 0) {
30916
+ const recentLines = [...skippedByType.entries()].map(([type, count]) => `- ${count} recent ${type.replace(".", " ").replace("_", " ")} events`).join("\n");
30917
+ parts.push(expireSummary ? `Additionally, ${skipped} recent events exceeded the catch-up limit and were skipped:
30918
+ ${recentLines}` : `[Offline Summary] You were offline. ${skipped} pending events exceeded the catch-up limit and were skipped:
30919
+ ${recentLines}
30920
+
30921
+ Use your tools (read messages, check tasks) to review anything still relevant.`);
30922
+ }
30923
+ const fullSummary = parts.join("\n\n");
30924
+ this.pendingRestartNotification = this.pendingRestartNotification ? `${this.pendingRestartNotification}
30925
+
30926
+ ${fullSummary}` : fullSummary;
30927
+ }
30928
+ if (processed > 0 || skipped > 0) {
30929
+ this.opts.log?.info(`dispatch catch-up: processed ${processed}, skipped ${skipped}`);
30930
+ }
30931
+ }
30932
+ buildOfflineSummary(groups) {
30933
+ const lines = [
30934
+ "[Offline Summary] You were offline and had a large backlog of pending events. The following old events were skipped:"
30935
+ ];
30936
+ for (const g of groups) {
30937
+ const age = this.formatAge(g.oldest);
30938
+ if (g.chat_id && g.event_type === "message") {
30939
+ const name = g.chat_name ?? g.chat_id;
30940
+ lines.push(`- ${g.count} messages in "${name}" (oldest: ${age})`);
30941
+ } else {
30942
+ const label = g.event_type.replace(".", " ").replace("_", " ");
30943
+ lines.push(`- ${g.count} ${label} events (oldest: ${age})`);
30944
+ }
30808
30945
  }
30946
+ lines.push("");
30947
+ lines.push("These events were too old to process individually. Use your tools (read messages, check tasks) to review anything still relevant.");
30948
+ return lines.join("\n");
30949
+ }
30950
+ formatAge(iso) {
30951
+ const ms = Date.now() - new Date(iso).getTime();
30952
+ const hours = Math.floor(ms / 36e5);
30953
+ if (hours < 24)
30954
+ return `${hours}h ago`;
30955
+ const days = Math.floor(hours / 24);
30956
+ return `${days}d ago`;
30809
30957
  }
30810
30958
  async handleHello(data) {
30811
30959
  const { client, config, log: log2 } = this.opts;