@parall/parall 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 (2) hide show
  1. package/dist/index.bundle.mjs +170 -22
  2. package/package.json +3 -3
@@ -27092,6 +27092,7 @@ var ENDPOINTS = {
27092
27092
  MACHINE_AGENT_DAEMON_CONFIG: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/daemon-config`,
27093
27093
  MACHINE_AGENT_WORKSPACE_SETUP: (orgId, machineId, agentId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/agents/${agentId}/workspace/setup`,
27094
27094
  MACHINE_LLM_SOURCE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/llm-source`,
27095
+ MACHINE_PROVIDER_ENABLED: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/provider-enabled`,
27095
27096
  MACHINE_RUNTIME_AUTH: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth`,
27096
27097
  MACHINE_KEYS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys`,
27097
27098
  MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
@@ -27105,8 +27106,9 @@ var ENDPOINTS = {
27105
27106
  MACHINES_ME: `${API_BASE}/machines/me`,
27106
27107
  MACHINES_ME_AGENTS: `${API_BASE}/machines/me/agents`,
27107
27108
  MACHINES_ME_HEALTH: `${API_BASE}/machines/me/health`,
27108
- MACHINES_ME_CLIP_INSTALLS: `${API_BASE}/machines/me/clip-installs`,
27109
- MACHINES_ME_CLIP_INSTALL_DONE: (clipId) => `${API_BASE}/machines/me/clip-installs/${clipId}/installed`,
27109
+ MACHINES_ME_CLIPS: `${API_BASE}/machines/me/clips`,
27110
+ MACHINES_ME_BROWSER_PROFILES: `${API_BASE}/machines/me/browser-profiles`,
27111
+ MACHINES_ME_BROWSER_PROFILE_STATUS: (profileId) => `${API_BASE}/machines/me/browser-profiles/${profileId}/status`,
27110
27112
  MACHINES_ME_AGENT_LAUNCH_CREDENTIAL: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/launch-credential`,
27111
27113
  MACHINES_ME_AGENT_WORKSPACE_STATE: (agentId) => `${API_BASE}/machines/me/agents/${agentId}/workspace-state`,
27112
27114
  MACHINES_ME_WS_TICKET: `${API_BASE}/machines/me/ws/ticket`,
@@ -27205,6 +27207,7 @@ var ENDPOINTS = {
27205
27207
  DISPATCH_RECEIVED: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/received`,
27206
27208
  DISPATCH_ACK: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/ack`,
27207
27209
  DISPATCH_ACK_BY_ID: (orgId, id) => `${API_BASE}/orgs/${orgId}/dispatch/${id}/ack`,
27210
+ DISPATCH_EXPIRE: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/expire`,
27208
27211
  DISPATCH_BY_MESSAGES: (orgId) => `${API_BASE}/orgs/${orgId}/dispatch/by-messages`,
27209
27212
  // Unread
27210
27213
  UNREAD: `${API_BASE}/me/unread`,
@@ -27243,6 +27246,13 @@ var ENDPOINTS = {
27243
27246
  AGENT_CLIP: (orgId, agentId, clipId) => `${CLIP_BASE}/orgs/${orgId}/agents/${agentId}/clips/${clipId}`,
27244
27247
  CLIP_INVOKE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/invoke`,
27245
27248
  CLIP_ONLINE: (orgId) => `${CLIP_BASE}/orgs/${orgId}/online`,
27249
+ BROWSER_PROFILES: (orgId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles`,
27250
+ BROWSER_PROFILE: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}`,
27251
+ BROWSER_PROFILE_OPEN: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/open`,
27252
+ BROWSER_PROFILE_STOP: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/stop`,
27253
+ BROWSER_PROFILE_RESET: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/reset`,
27254
+ BROWSER_PROFILE_CONSENTS: (orgId, profileId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents`,
27255
+ BROWSER_PROFILE_CONSENT: (orgId, profileId, clipId) => `${CLIP_BASE}/orgs/${orgId}/browser-profiles/${profileId}/consents/${clipId}`,
27246
27256
  // Clip registry (global, served by clip-service → Pinix Hub proxy)
27247
27257
  CLIP_REGISTRY: () => `${CLIP_BASE}/registry/clips`
27248
27258
  };
@@ -27317,9 +27327,10 @@ var WS_EVENTS = {
27317
27327
  MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
27318
27328
  MACHINE_UPDATE: "machine.update",
27319
27329
  MACHINE_CONFIG_UPDATED: "machine.config.updated",
27320
- MACHINE_CLIP_INSTALL: "machine.clip.install",
27330
+ MACHINE_CLIP_SYNC: "machine.clip.sync",
27331
+ MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
27321
27332
  AGENT_NEW_SESSION: "agent.new_session",
27322
- CLIP_INSTALLED: "clip.installed",
27333
+ CLIP_CREATED: "clip.created",
27323
27334
  CLIP_REMOVED: "clip.removed",
27324
27335
  CLIP_UPDATED: "clip.updated"
27325
27336
  };
@@ -27772,8 +27783,8 @@ var ParallClient = class _ParallClient {
27772
27783
  const res = await this.request("GET", ENDPOINTS.CHAT_MEMBERS(orgId, chatId));
27773
27784
  return res.data;
27774
27785
  }
27775
- async addChatMember(orgId, chatId, userId, role) {
27776
- return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId, role });
27786
+ async addChatMember(orgId, chatId, userId) {
27787
+ return this.request("POST", ENDPOINTS.CHAT_MEMBERS(orgId, chatId), { user_id: userId });
27777
27788
  }
27778
27789
  async removeChatMember(orgId, chatId, userId) {
27779
27790
  return this.request("DELETE", ENDPOINTS.CHAT_MEMBER(orgId, chatId, userId));
@@ -28032,6 +28043,16 @@ var ParallClient = class _ParallClient {
28032
28043
  llm_source: llmSource
28033
28044
  });
28034
28045
  }
28046
+ /**
28047
+ * Toggle whether the machine contributes its local clips as a hub provider
28048
+ * — org-admin-gated (RequireOrgAdmin), like all machine management. See
28049
+ * docs/engineering-design/clip-provider-sharing-design.md.
28050
+ */
28051
+ async patchMachineProviderEnabled(orgId, machineId, providerEnabled) {
28052
+ return this.request("PATCH", ENDPOINTS.MACHINE_PROVIDER_ENABLED(orgId, machineId), {
28053
+ provider_enabled: providerEnabled
28054
+ });
28055
+ }
28035
28056
  /** Get machine-level runtime auth state. */
28036
28057
  async getMachineRuntimeAuth(orgId, machineId) {
28037
28058
  return this.request("GET", ENDPOINTS.MACHINE_RUNTIME_AUTH(orgId, machineId));
@@ -28065,25 +28086,39 @@ var ParallClient = class _ParallClient {
28065
28086
  const res = await this.request("GET", ENDPOINTS.MACHINES_ME_AGENTS);
28066
28087
  return res.data;
28067
28088
  }
28068
- /** `GET /machines/me/clip-installs` — registry clips this machine should
28069
- * install but hasn't yet (durable reconcile, mck_-authed). */
28070
- async listClipInstalls() {
28071
- const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIP_INSTALLS);
28089
+ /** `GET /machines/me/clips` — executable Clip definitions assigned to this machine. */
28090
+ async listMachineClips() {
28091
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_CLIPS);
28072
28092
  return res.data;
28073
28093
  }
28074
- /** `POST /machines/me/clip-installs/{clipId}/installed` — report a finished install. */
28075
- async reportClipInstall(clipId, version) {
28076
- return this.request("POST", ENDPOINTS.MACHINES_ME_CLIP_INSTALL_DONE(clipId), version ? { version } : void 0);
28094
+ /** `GET /machines/me/browser-profiles` — browser profiles hosted by this machine. */
28095
+ async listMachineBrowserProfiles() {
28096
+ const res = await this.request("GET", ENDPOINTS.MACHINES_ME_BROWSER_PROFILES);
28097
+ return res.data;
28098
+ }
28099
+ /** `POST /machines/me/browser-profiles/{profileId}/status` — report runtime status. */
28100
+ async reportBrowserProfileStatus(profileId, status, errorMsg) {
28101
+ await this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_STATUS(profileId), {
28102
+ status,
28103
+ ...errorMsg ? { error_msg: errorMsg } : {}
28104
+ });
28077
28105
  }
28078
28106
  /**
28079
- * `POST /machines/me/health` — bump the Machine's `updated_at` to now.
28080
- * Body is intentionally empty; the server ignores any payload. The
28081
- * daemon should call this on a fixed cadence (e.g. every 30s) so an
28082
- * external observer can detect a wedged supervisor.
28107
+ * `POST /machines/me/health` — bump the Machine's `updated_at` to now and
28108
+ * report daemon state. The daemon should call this on a fixed cadence (e.g.
28109
+ * every 30s) so an external observer can detect a wedged supervisor. Both
28110
+ * fields are optional and only persisted when changed:
28111
+ * - `daemonVersion` — the running bundle/launcher version.
28112
+ * - `selfUpdateCapable` — whether the daemon can act on a machine.update
28113
+ * signal (true under a service manager, false for bare `npx` foreground).
28083
28114
  */
28084
- async postMachineHeartbeat(daemonVersion) {
28085
- const body = daemonVersion ? { daemon_version: daemonVersion } : void 0;
28086
- return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, body);
28115
+ async postMachineHeartbeat(opts) {
28116
+ const body = {};
28117
+ if (opts?.daemonVersion)
28118
+ body.daemon_version = opts.daemonVersion;
28119
+ if (opts?.selfUpdateCapable !== void 0)
28120
+ body.self_update_capable = opts.selfUpdateCapable;
28121
+ return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, Object.keys(body).length > 0 ? body : void 0);
28087
28122
  }
28088
28123
  async reportAgentWorkspaceState(agentId, state) {
28089
28124
  const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
@@ -28185,6 +28220,10 @@ var ParallClient = class _ParallClient {
28185
28220
  async ackDispatchByID(orgId, id) {
28186
28221
  return this.request("POST", ENDPOINTS.DISPATCH_ACK_BY_ID(orgId, id));
28187
28222
  }
28223
+ async expireDispatch(orgId, maxAgeHours) {
28224
+ const params = maxAgeHours !== void 0 ? { max_age_hours: String(maxAgeHours) } : void 0;
28225
+ return this.request("POST", ENDPOINTS.DISPATCH_EXPIRE(orgId), void 0, params);
28226
+ }
28188
28227
  async getDispatchByMessages(orgId, chatId, messageIds) {
28189
28228
  const params = { chat_id: chatId, message_ids: messageIds.join(",") };
28190
28229
  return this.request("GET", ENDPOINTS.DISPATCH_BY_MESSAGES(orgId), void 0, params);
@@ -28665,6 +28704,41 @@ var ParallClient = class _ParallClient {
28665
28704
  const resp = await this.request("GET", ENDPOINTS.CLIP_ONLINE(orgId));
28666
28705
  return resp.data;
28667
28706
  }
28707
+ async listBrowserProfiles(orgId) {
28708
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILES(orgId));
28709
+ return resp.data;
28710
+ }
28711
+ async createBrowserProfile(orgId, req) {
28712
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILES(orgId), req);
28713
+ }
28714
+ async getBrowserProfile(orgId, profileId) {
28715
+ return this.request("GET", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28716
+ }
28717
+ async updateBrowserProfile(orgId, profileId, req) {
28718
+ return this.request("PATCH", ENDPOINTS.BROWSER_PROFILE(orgId, profileId), req);
28719
+ }
28720
+ async deleteBrowserProfile(orgId, profileId) {
28721
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE(orgId, profileId));
28722
+ }
28723
+ async openBrowserProfile(orgId, profileId, req = {}) {
28724
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_OPEN(orgId, profileId), req);
28725
+ }
28726
+ async stopBrowserProfile(orgId, profileId) {
28727
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_STOP(orgId, profileId), {});
28728
+ }
28729
+ async resetBrowserProfile(orgId, profileId) {
28730
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_RESET(orgId, profileId));
28731
+ }
28732
+ async listBrowserProfileConsents(orgId, profileId) {
28733
+ const resp = await this.request("GET", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId));
28734
+ return resp.data;
28735
+ }
28736
+ async grantBrowserProfileConsent(orgId, profileId, req) {
28737
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_CONSENTS(orgId, profileId), req);
28738
+ }
28739
+ async revokeBrowserProfileConsent(orgId, profileId, clipId) {
28740
+ await this.request("DELETE", ENDPOINTS.BROWSER_PROFILE_CONSENT(orgId, profileId, clipId));
28741
+ }
28668
28742
  async listRegistryClips(q) {
28669
28743
  const url = ENDPOINTS.CLIP_REGISTRY() + (q ? `?q=${encodeURIComponent(q)}` : "");
28670
28744
  const resp = await this.request("GET", url);
@@ -30648,8 +30722,28 @@ var ParallAgentGateway = class {
30648
30722
  return dispatched;
30649
30723
  }
30650
30724
  async catchUpFromDispatch() {
30725
+ const OVERFLOW_THRESHOLD = 500;
30726
+ const EXPIRE_AGE_HOURS = 24;
30727
+ const CATCHUP_MAX = 10;
30728
+ let expireSummary = null;
30729
+ let overflowMode = false;
30730
+ try {
30731
+ const { count } = await this.opts.client.getDispatchPendingCount(this.opts.config.org_id);
30732
+ if (count > OVERFLOW_THRESHOLD) {
30733
+ overflowMode = true;
30734
+ const result = await this.opts.client.expireDispatch(this.opts.config.org_id, EXPIRE_AGE_HOURS);
30735
+ if (result.total > 0) {
30736
+ this.opts.log?.warn(`dispatch catch-up overflow: ${count} pending, expired ${result.total} events older than ${EXPIRE_AGE_HOURS}h`);
30737
+ expireSummary = this.buildOfflineSummary(result.groups);
30738
+ }
30739
+ }
30740
+ } catch (err) {
30741
+ this.opts.log?.warn(`dispatch catch-up overflow check failed: ${String(err)}`);
30742
+ }
30651
30743
  let cursor;
30652
30744
  let processed = 0;
30745
+ let skipped = 0;
30746
+ const skippedByType = /* @__PURE__ */ new Map();
30653
30747
  do {
30654
30748
  const page = await this.opts.client.getDispatch(this.opts.config.org_id, {
30655
30749
  limit: 50,
@@ -30658,6 +30752,17 @@ var ParallAgentGateway = class {
30658
30752
  for (const item of page.data ?? []) {
30659
30753
  if (this.shuttingDown)
30660
30754
  break;
30755
+ if (overflowMode && processed >= CATCHUP_MAX) {
30756
+ try {
30757
+ await this.opts.client.ackDispatchByID(this.opts.config.org_id, item.id);
30758
+ skipped++;
30759
+ const key = item.event_type;
30760
+ skippedByType.set(key, (skippedByType.get(key) ?? 0) + 1);
30761
+ } catch {
30762
+ this.opts.log?.warn(`catch-up skip ack failed for ${item.id}, leaving pending`);
30763
+ }
30764
+ continue;
30765
+ }
30661
30766
  processed++;
30662
30767
  try {
30663
30768
  let dispatched = false;
@@ -30732,9 +30837,52 @@ var ParallAgentGateway = class {
30732
30837
  }
30733
30838
  cursor = !this.shuttingDown && page.has_more ? page.next_cursor : void 0;
30734
30839
  } while (cursor);
30735
- if (processed > 0) {
30736
- this.opts.log?.info(`dispatch catch-up: processed ${processed}`);
30840
+ if (expireSummary || skipped > 0) {
30841
+ const parts = [];
30842
+ if (expireSummary)
30843
+ parts.push(expireSummary);
30844
+ if (skipped > 0) {
30845
+ const recentLines = [...skippedByType.entries()].map(([type, count]) => `- ${count} recent ${type.replace(".", " ").replace("_", " ")} events`).join("\n");
30846
+ parts.push(expireSummary ? `Additionally, ${skipped} recent events exceeded the catch-up limit and were skipped:
30847
+ ${recentLines}` : `[Offline Summary] You were offline. ${skipped} pending events exceeded the catch-up limit and were skipped:
30848
+ ${recentLines}
30849
+
30850
+ Use your tools (read messages, check tasks) to review anything still relevant.`);
30851
+ }
30852
+ const fullSummary = parts.join("\n\n");
30853
+ this.pendingRestartNotification = this.pendingRestartNotification ? `${this.pendingRestartNotification}
30854
+
30855
+ ${fullSummary}` : fullSummary;
30856
+ }
30857
+ if (processed > 0 || skipped > 0) {
30858
+ this.opts.log?.info(`dispatch catch-up: processed ${processed}, skipped ${skipped}`);
30859
+ }
30860
+ }
30861
+ buildOfflineSummary(groups) {
30862
+ const lines = [
30863
+ "[Offline Summary] You were offline and had a large backlog of pending events. The following old events were skipped:"
30864
+ ];
30865
+ for (const g of groups) {
30866
+ const age = this.formatAge(g.oldest);
30867
+ if (g.chat_id && g.event_type === "message") {
30868
+ const name = g.chat_name ?? g.chat_id;
30869
+ lines.push(`- ${g.count} messages in "${name}" (oldest: ${age})`);
30870
+ } else {
30871
+ const label = g.event_type.replace(".", " ").replace("_", " ");
30872
+ lines.push(`- ${g.count} ${label} events (oldest: ${age})`);
30873
+ }
30737
30874
  }
30875
+ lines.push("");
30876
+ lines.push("These events were too old to process individually. Use your tools (read messages, check tasks) to review anything still relevant.");
30877
+ return lines.join("\n");
30878
+ }
30879
+ formatAge(iso) {
30880
+ const ms = Date.now() - new Date(iso).getTime();
30881
+ const hours = Math.floor(ms / 36e5);
30882
+ if (hours < 24)
30883
+ return `${hours}h ago`;
30884
+ const days = Math.floor(hours / 24);
30885
+ return `${days}d ago`;
30738
30886
  }
30739
30887
  async handleHello(data) {
30740
30888
  const { client, config, log } = this.opts;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.32.1",
3
+ "version": "1.33.0",
4
4
  "description": "OpenClaw channel plugin for Parall IM",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,8 +16,8 @@
16
16
  "openclaw.plugin.json"
17
17
  ],
18
18
  "dependencies": {
19
- "@parall/agent-core": "1.32.1",
20
- "@parall/sdk": "1.32.1"
19
+ "@parall/agent-core": "1.33.0",
20
+ "@parall/sdk": "1.33.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0",