@parall/parall 1.48.0 → 1.50.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.
@@ -1 +1 @@
1
- {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,uGAAuG;AACvG,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACnF,OAAO,EASL,KAAK,eAAe,EAGrB,MAAM,oBAAoB,CAAC;AAqB5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AA2KxD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,IAAI,EAAE,aAAa,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,eAAe,CA8KlB;AAED,eAAO,MAAM,aAAa,EAAE,qBAAqB,CAAC,qBAAqB,CAqLtE,CAAC"}
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,uGAAuG;AACvG,KAAK,qBAAqB,CAAC,CAAC,GAAG,OAAO,IAAI,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACnF,OAAO,EAUL,KAAK,eAAe,EAGrB,MAAM,oBAAoB,CAAC;AAqB5B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AA+KxD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,IAAI,EAAE,aAAa,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,eAAe,CA8KlB;AAED,eAAO,MAAM,aAAa,EAAE,qBAAqB,CAAC,qBAAqB,CAmMtE,CAAC"}
package/dist/gateway.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ParallAgentGateway, capabilityBinDir, dispatchLaneContextDir, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, initAgentTelemetry, createOtelLogger, } from '@parall/agent-core';
1
+ import { ParallAgentGateway, capabilityBinDir, dispatchLaneContextDir, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, identityFromMe, initAgentTelemetry, createOtelLogger, } from '@parall/agent-core';
2
2
  import { appendPreparedLocalAttachmentRefs, ensureLocalAttachmentGitExclude, pinLocalAttachmentPaths, } from '@parall/agent-core/internal/attachment-input';
3
3
  import { ApiError, ParallClient, ParallWs } from '@parall/sdk';
4
4
  import * as crypto from 'node:crypto';
@@ -36,9 +36,12 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
36
36
  throw err;
37
37
  }
38
38
  const user = await client.getMe();
39
- return { ...user, agent_profile: null };
39
+ return { ...user, agent_profile: null, public_profile: null };
40
40
  }
41
41
  }
42
+ // hooks.ts rebuilds the prompt from the process-global identity on EVERY
43
+ // prompt build, so a refreshed identity (via the shared identityFromMe)
44
+ // reaches the very next turn without any restart.
42
45
  function buildInboundCtx(core, accountId, event, sessionKey, bodyForAgent, earlierEvents = []) {
43
46
  const inboundHistory = earlierEvents.length > 0 ? buildInboundHistory(earlierEvents) : undefined;
44
47
  return core.channel.reply.finalizeInboundContext({
@@ -333,11 +336,7 @@ export const parallGateway = {
333
336
  });
334
337
  const me = await getAgentMeWithLegacyFallback(client, config.org_id);
335
338
  const agentUserId = me.id;
336
- setAgentIdentity({
337
- userId: agentUserId,
338
- displayName: me.display_name,
339
- description: me.agent_profile?.description ?? undefined,
340
- });
339
+ setAgentIdentity(identityFromMe(me));
341
340
  log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
342
341
  const telemetry = await initAgentTelemetry('parall-openclaw-agent', 'openclaw');
343
342
  const otelLog = createOtelLogger('agent', 'openclaw-agent');
@@ -436,7 +435,23 @@ export const parallGateway = {
436
435
  forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
437
436
  dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
438
437
  onConfigUpdate: async () => {
439
- await fetchAndApplyPlatformConfig(configManagerOpts);
438
+ // Identity rides the same agent_config.update nudge: refresh the
439
+ // process-global identity so the next prompt build (hooks.ts
440
+ // before_prompt_build) carries the new title / public description /
441
+ // instructions. The finally keeps it running even when the platform
442
+ // config refresh throws (their failure domains are independent);
443
+ // identity failure keeps the last-known-good value.
444
+ try {
445
+ await fetchAndApplyPlatformConfig(configManagerOpts);
446
+ }
447
+ finally {
448
+ try {
449
+ setAgentIdentity(identityFromMe(await getAgentMeWithLegacyFallback(client, config.org_id)));
450
+ }
451
+ catch (err) {
452
+ log?.warn(`parall[${ctx.accountId}]: /agents/me refetch failed (keeping last-known identity): ${String(err)}`);
453
+ }
454
+ }
440
455
  },
441
456
  onSessionReady: async ({ activeSessionId }) => {
442
457
  setParallAccountState(ctx.accountId, {
@@ -51291,6 +51291,17 @@ function laneContextFilePath(contextDir, targetUri, threadRootId) {
51291
51291
 
51292
51292
  // ../sdk/dist/types.js
51293
51293
  var MENTION_ALL_USER_ID = "all";
51294
+ var MENTION_ALL_HUMANS_USER_ID = "allhuman";
51295
+ var MENTION_ALL_AGENTS_USER_ID = "allagent";
51296
+ function mentionTargetsUser(mentionUserId, userId, userType) {
51297
+ if (mentionUserId === userId || mentionUserId === MENTION_ALL_USER_ID)
51298
+ return true;
51299
+ if (mentionUserId === MENTION_ALL_HUMANS_USER_ID)
51300
+ return userType === "human";
51301
+ if (mentionUserId === MENTION_ALL_AGENTS_USER_ID)
51302
+ return userType === "agent";
51303
+ return false;
51304
+ }
51294
51305
 
51295
51306
  // ../sdk/dist/constants.js
51296
51307
  var API_BASE = "/api/v1";
@@ -51326,6 +51337,12 @@ var ENDPOINTS = {
51326
51337
  ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
51327
51338
  ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
51328
51339
  ORG_MEMBER_TASKS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/tasks`,
51340
+ // Org-scoped public profile (title / description). GET readable by every
51341
+ // active member; PATCH is CAS-guarded (expected_version).
51342
+ ORG_MEMBER_PROFILE: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}/profile`,
51343
+ // Private agent Instructions — visibility gated server-side
51344
+ // (agent self + Human org admin/owner). Never cached.
51345
+ AGENT_INSTRUCTIONS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/instructions`,
51329
51346
  REF_SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/search`,
51330
51347
  // Direct messages (org-scoped, atomic find-or-create + send)
51331
51348
  DM: (orgId) => `${API_BASE}/orgs/${orgId}/dm`,
@@ -51349,6 +51366,8 @@ var ENDPOINTS = {
51349
51366
  MESSAGE_WATCH: (id) => `${API_BASE}/messages/${id}/watch`,
51350
51367
  MESSAGE_WATCHERS: (id) => `${API_BASE}/messages/${id}/watchers`,
51351
51368
  MESSAGE_WATCHING: (id) => `${API_BASE}/messages/${id}/watching`,
51369
+ MESSAGE_REACTIONS: (id) => `${API_BASE}/messages/${id}/reactions`,
51370
+ MESSAGE_REACTION: (id, emoji) => `${API_BASE}/messages/${id}/reactions/${encodeURIComponent(emoji)}`,
51352
51371
  // Upload (org-scoped)
51353
51372
  UPLOAD_PRESIGN: (orgId) => `${API_BASE}/orgs/${orgId}/upload/presign`,
51354
51373
  UPLOAD_COMPLETE: (orgId) => `${API_BASE}/orgs/${orgId}/upload/complete`,
@@ -51586,11 +51605,13 @@ var ENDPOINTS = {
51586
51605
  UNREAD: `${API_BASE}/me/unread`,
51587
51606
  ORG_UNREAD: (orgId) => `${API_BASE}/orgs/${orgId}/unread`,
51588
51607
  CHAT_READ: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read`,
51608
+ CHAT_READ_ALL: (orgId, chatId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/read-all`,
51589
51609
  THREAD_UNREAD: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/unread`,
51590
51610
  THREAD_READ: (orgId, chatId, threadRootId) => `${API_BASE}/orgs/${orgId}/chats/${chatId}/threads/${threadRootId}/read`,
51591
51611
  // References (org-scoped)
51592
51612
  REFS_RESOLVE: (orgId) => `${API_BASE}/orgs/${orgId}/refs/resolve`,
51593
51613
  REFS_BACKLINKS: (orgId) => `${API_BASE}/orgs/${orgId}/refs/backlinks`,
51614
+ REFS_OUTBOUND: (orgId) => `${API_BASE}/orgs/${orgId}/refs/outbound`,
51594
51615
  REFS_GRAPH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/graph`,
51595
51616
  REFS_CHECK: (orgId) => `${API_BASE}/orgs/${orgId}/refs/check`,
51596
51617
  // Platform config (agent-scoped, not org-scoped)
@@ -51605,6 +51626,11 @@ var ENDPOINTS = {
51605
51626
  SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/search`,
51606
51627
  // Feature flags (org-scoped, server-evaluated)
51607
51628
  FEATURE_FLAGS: (orgId) => `${API_BASE}/orgs/${orgId}/feature-flags`,
51629
+ // Team templates (org-scoped, owner/admin only)
51630
+ TEMPLATES: (orgId) => `${API_BASE}/orgs/${orgId}/templates`,
51631
+ TEMPLATE: (orgId, templateId) => `${API_BASE}/orgs/${orgId}/templates/${templateId}`,
51632
+ TEMPLATE_DEPLOYMENTS: (orgId) => `${API_BASE}/orgs/${orgId}/template-deployments`,
51633
+ TEMPLATE_DEPLOYMENT: (orgId, deploymentId) => `${API_BASE}/orgs/${orgId}/template-deployments/${deploymentId}`,
51608
51634
  // Billing & Credits (org-scoped)
51609
51635
  BILLING: (orgId) => `${API_BASE}/orgs/${orgId}/billing`,
51610
51636
  BILLING_TRANSACTIONS: (orgId) => `${API_BASE}/orgs/${orgId}/billing/transactions`,
@@ -51652,7 +51678,13 @@ var ENDPOINTS = {
51652
51678
  ORG_EDGE_DEVICE_UNREGISTER: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/unregister`,
51653
51679
  ORG_EDGE_ONBOARDING: (orgId) => `/api/v1/orgs/${orgId}/edge/onboarding`,
51654
51680
  ORG_EDGE_PROFILES: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles`,
51681
+ // Per-profile egress proxy (hosted Cloud Profiles; manager-only, human-only).
51682
+ ORG_EDGE_PROFILE_PROXY: (orgId, edgeId, profileName) => `/api/v1/orgs/${orgId}/edge/${edgeId}/profiles/${encodeURIComponent(profileName)}/proxy`,
51655
51683
  ORG_EDGE_EXEC: (orgId) => `/api/v1/orgs/${orgId}/edge/exec`,
51684
+ // Cloud Edge live viewer command (V1b) — api-server, gated on cap:edge-viewer.
51685
+ // Same request/reply shape as the v2 browser-profile viewer, on the v3 edge
51686
+ // pipe. Additive: does NOT replace BROWSER_PROFILE_VIEWER_COMMAND.
51687
+ ORG_EDGE_VIEWER_COMMAND: (orgId, edgeId) => `/api/v1/orgs/${orgId}/edge/${edgeId}/viewer/command`,
51656
51688
  CLIP_CONNECTIONS: (orgId, clipId) => `/api/v1/orgs/${orgId}/clip-registry/${clipId}/connections`,
51657
51689
  CLIP_CONNECTION: (orgId, connId) => `/api/v1/orgs/${orgId}/clip-connections/${connId}`,
51658
51690
  // Clip registry (v3, org-scoped, served by api-server — `crg_` entries; the
@@ -51675,6 +51707,7 @@ var WS_EVENTS = {
51675
51707
  MESSAGE_PATCH: "message.patch",
51676
51708
  MESSAGE_EDIT: "message.edit",
51677
51709
  MESSAGE_DELETE: "message.delete",
51710
+ MESSAGE_REACTION_UPDATED: "message.reaction.updated",
51678
51711
  TYPING_UPDATE: "typing.update",
51679
51712
  CHAT_UPDATE: "chat.update",
51680
51713
  CHAT_DELETED: "chat.deleted",
@@ -51716,6 +51749,7 @@ var WS_EVENTS = {
51716
51749
  INBOX_UPDATE: "inbox.update",
51717
51750
  INBOX_BULK_UPDATE: "inbox.bulk_update",
51718
51751
  READ_POSITION_UPDATED: "read_position.updated",
51752
+ THREAD_READ_POSITION_UPDATED: "thread_read_position.updated",
51719
51753
  DISPATCH_NEW: "dispatch.new",
51720
51754
  DISPATCH_RECEIVED: "dispatch.received",
51721
51755
  DISPATCH_RESOLVED: "dispatch.resolved",
@@ -51901,7 +51935,7 @@ var ParallClient = class _ParallClient {
51901
51935
  if (qs)
51902
51936
  url += `?${qs}`;
51903
51937
  }
51904
- const headers = this.buildHeaders(path9);
51938
+ const headers = this.buildHeaders(path9, opts?.headers);
51905
51939
  const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
51906
51940
  const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
51907
51941
  let res;
@@ -52117,6 +52151,30 @@ var ParallClient = class _ParallClient {
52117
52151
  async updateOrgMember(orgId, userId, role) {
52118
52152
  return this.request("PATCH", ENDPOINTS.ORG_MEMBER(orgId, userId), { role });
52119
52153
  }
52154
+ /** Org-scoped public profile (title / description) of any active member. */
52155
+ async getMemberProfile(orgId, userId) {
52156
+ return this.request("GET", ENDPOINTS.ORG_MEMBER_PROFILE(orgId, userId));
52157
+ }
52158
+ /**
52159
+ * CAS full-replacement of a member's public profile. Humans edit their
52160
+ * own; Human org admins/owners edit agents'. A stale expected_version
52161
+ * gets 409 PROFILE_VERSION_CONFLICT with error.details.current_version.
52162
+ */
52163
+ async updateMemberProfile(orgId, userId, req) {
52164
+ return this.request("PATCH", ENDPOINTS.ORG_MEMBER_PROFILE(orgId, userId), req);
52165
+ }
52166
+ /** Private agent Instructions — agent self or Human org admin/owner only. */
52167
+ async getAgentInstructions(orgId, agentId) {
52168
+ return this.request("GET", ENDPOINTS.AGENT_INSTRUCTIONS(orgId, agentId));
52169
+ }
52170
+ /**
52171
+ * CAS update of the private Instructions (Human org admin/owner only).
52172
+ * A stale expected_version gets 409 INSTRUCTIONS_VERSION_CONFLICT with
52173
+ * error.details.current_version.
52174
+ */
52175
+ async updateAgentInstructions(orgId, agentId, req) {
52176
+ return this.request("PATCH", ENDPOINTS.AGENT_INSTRUCTIONS(orgId, agentId), req);
52177
+ }
52120
52178
  // Member activity surfaces — chats the member participates in within this org,
52121
52179
  // ordered by most recent activity. Powers the member profile Activity tab.
52122
52180
  async getMemberChats(orgId, memberId, params) {
@@ -52307,6 +52365,14 @@ var ParallClient = class _ParallClient {
52307
52365
  async getMessageReplies(id, params) {
52308
52366
  return this.request("GET", ENDPOINTS.MESSAGE_REPLIES(id), void 0, params);
52309
52367
  }
52368
+ // ---- Reactions ----
52369
+ async toggleReaction(messageId, emoji) {
52370
+ return this.request("PUT", ENDPOINTS.MESSAGE_REACTION(messageId, emoji));
52371
+ }
52372
+ async listReactions(messageId) {
52373
+ const res = await this.request("GET", ENDPOINTS.MESSAGE_REACTIONS(messageId));
52374
+ return res.reactions;
52375
+ }
52310
52376
  // ---- File Upload ----
52311
52377
  async getUploadPresignUrl(orgId, req) {
52312
52378
  return this.request("POST", ENDPOINTS.UPLOAD_PRESIGN(orgId), req);
@@ -52682,6 +52748,15 @@ var ParallClient = class _ParallClient {
52682
52748
  async browserViewerCommand(orgId, profileId, req, opts) {
52683
52749
  return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, opts);
52684
52750
  }
52751
+ /**
52752
+ * Drive the Cloud Edge live viewer (V1b, design §6): WebRTC signaling + input +
52753
+ * tab nav for a hosted browser (Cloud Profile). Same request/reply shape as
52754
+ * browserViewerCommand, on the v3 edge pipe; additive — the v2 browser-profile
52755
+ * viewer is unchanged.
52756
+ */
52757
+ async edgeViewerCommand(orgId, edgeId, req, opts) {
52758
+ return this.request("POST", ENDPOINTS.ORG_EDGE_VIEWER_COMMAND(orgId, edgeId), req, void 0, false, opts);
52759
+ }
52685
52760
  async resizeMachine(orgId, machineId, spec) {
52686
52761
  return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
52687
52762
  }
@@ -52708,14 +52783,23 @@ var ParallClient = class _ParallClient {
52708
52783
  }
52709
52784
  // Wiki mount/token methods removed — wiki-service handles all wiki endpoints.
52710
52785
  // ---- Unread ----
52711
- async getUnreadCounts(orgId) {
52786
+ async getUnreadCounts(orgId, opts) {
52712
52787
  const endpoint = orgId ? ENDPOINTS.ORG_UNREAD(orgId) : ENDPOINTS.UNREAD;
52713
- const res = await this.request("GET", endpoint);
52788
+ const res = await this.request("GET", endpoint, void 0, {
52789
+ include_thread_replies: opts?.includeThreadReplies ? "true" : void 0
52790
+ });
52714
52791
  return res.data;
52715
52792
  }
52716
52793
  async markRead(orgId, chatId, messageId) {
52717
52794
  return this.request("POST", ENDPOINTS.CHAT_READ(orgId, chatId), { message_id: messageId });
52718
52795
  }
52796
+ /** Mark everything in a chat read: the channel cursor jumps to the latest
52797
+ * top-level message and every thread cursor to its latest reply, in one
52798
+ * idempotent call. The server echoes the same per-cursor WS events the
52799
+ * single-cursor routes emit and auto-clears covered inbox items. */
52800
+ async markAllRead(orgId, chatId) {
52801
+ return this.request("POST", ENDPOINTS.CHAT_READ_ALL(orgId, chatId));
52802
+ }
52719
52803
  async getThreadUnread(orgId, chatId, threadRootId) {
52720
52804
  return this.request("GET", ENDPOINTS.THREAD_UNREAD(orgId, chatId, threadRootId));
52721
52805
  }
@@ -53390,6 +53474,16 @@ var ParallClient = class _ParallClient {
53390
53474
  async getBacklinks(orgId, params) {
53391
53475
  return this.request("GET", ENDPOINTS.REFS_BACKLINKS(orgId), void 0, params);
53392
53476
  }
53477
+ /**
53478
+ * Outbound prll:// refs authored in a set of sources, as raw ref_links rows
53479
+ * (dedupe/group client-side). Pass `{ thread_root_id }` to list a whole
53480
+ * thread's refs (root + all replies, resolved server-side — the client's
53481
+ * reply window may be partial), or `{ source_type, source_ids }` for
53482
+ * explicit sources (max 500; v1 accepts only message sources).
53483
+ */
53484
+ async listOutboundRefs(orgId, req) {
53485
+ return this.request("POST", ENDPOINTS.REFS_OUTBOUND(orgId), req);
53486
+ }
53393
53487
  /**
53394
53488
  * Bounded multi-hop walk of the prll:// reference graph around `uri`. `uri`
53395
53489
  * must be an entity-level prll:// URI — a refined URI (path/query/fragment) is
@@ -53424,6 +53518,22 @@ var ParallClient = class _ParallClient {
53424
53518
  async getFeatureFlags(orgId) {
53425
53519
  return this.request("GET", ENDPOINTS.FEATURE_FLAGS(orgId));
53426
53520
  }
53521
+ // ---- Official Template catalog (org-contextual owner/admin reads + Hire) ----
53522
+ async listOfficialTemplates(orgId) {
53523
+ const response = await this.request("GET", ENDPOINTS.TEMPLATES(orgId));
53524
+ return response.templates ?? [];
53525
+ }
53526
+ async getOfficialTemplate(orgId, templateId) {
53527
+ return this.request("GET", ENDPOINTS.TEMPLATE(orgId, templateId));
53528
+ }
53529
+ async deployTemplate(orgId, request3) {
53530
+ return this.request("POST", ENDPOINTS.TEMPLATE_DEPLOYMENTS(orgId), request3, void 0, false, {
53531
+ timeoutMs: 185e3
53532
+ });
53533
+ }
53534
+ async getTemplateDeployment(orgId, deploymentId) {
53535
+ return this.request("GET", ENDPOINTS.TEMPLATE_DEPLOYMENT(orgId, deploymentId));
53536
+ }
53427
53537
  // ---- Billing & Credits (org-scoped) ----
53428
53538
  async getBilling(orgId) {
53429
53539
  return this.request("GET", ENDPOINTS.BILLING(orgId));
@@ -53669,6 +53779,43 @@ var ParallClient = class _ParallClient {
53669
53779
  async listEdgeProfiles(orgId, edgeId) {
53670
53780
  return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILES(orgId, edgeId));
53671
53781
  }
53782
+ /**
53783
+ * Read a hosted Cloud Profile's egress-proxy status (manager-only: hosted
53784
+ * human maintainer or org admin). Sanitized — the password never comes back.
53785
+ * Typed errors: `EDGE_NOT_HOSTED` (BYOC device), `PROXY_CONFIG_CORRUPT` /
53786
+ * validation codes as 422 when a stored config no longer passes current rules.
53787
+ * `can_mutate` and `lease_status` are the authoritative idle gate; device
53788
+ * list status is not a substitute.
53789
+ */
53790
+ async getEdgeProfileProxy(orgId, edgeId, profileName) {
53791
+ return this.request("GET", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName));
53792
+ }
53793
+ /**
53794
+ * Set/replace the profile's egress proxy (full triple every time) — IDLE
53795
+ * ONLY: while the profile's hosted browser is running (a viewer session is
53796
+ * open or a pod is otherwise live) the server answers 409
53797
+ * `EDGE_PROFILE_IN_USE`; close the viewer, wait for idle scale-to-zero, and
53798
+ * retry. The next cold start uses the new egress; browser login state is
53799
+ * preserved across it. Other typed errors: the validation vocabulary
53800
+ * (`INVALID_PROXY_SERVER`, `PROXY_AUTH_INCOMPLETE`,
53801
+ * `PROXY_SERVER_FORBIDDEN_TARGET`, …), `EDGE_DELETING` (409), and
53802
+ * `SECRETBOX_UNCONFIGURED` (503 — server cannot store credentials safely),
53803
+ * and `EDGE_PROFILE_PROXY_STALE` (409 — expectedVersion lost a tab race).
53804
+ */
53805
+ async setEdgeProfileProxy(orgId, edgeId, profileName, req, expectedVersion) {
53806
+ return this.request("PUT", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), req, void 0, false, {
53807
+ headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
53808
+ });
53809
+ }
53810
+ /**
53811
+ * Clear the profile's egress proxy; the next pod start egresses directly.
53812
+ * Idle-only like set — 409 `EDGE_PROFILE_IN_USE` while the browser is live.
53813
+ */
53814
+ async clearEdgeProfileProxy(orgId, edgeId, profileName, expectedVersion) {
53815
+ return this.request("DELETE", ENDPOINTS.ORG_EDGE_PROFILE_PROXY(orgId, edgeId, profileName), void 0, void 0, false, {
53816
+ headers: expectedVersion ? { "If-Match": `"proxy-${expectedVersion}"` } : void 0
53817
+ });
53818
+ }
53672
53819
  /**
53673
53820
  * Execute a registry clip command on an Edge device.
53674
53821
  *
@@ -53737,6 +53884,8 @@ var ApiError = class extends Error {
53737
53884
  status;
53738
53885
  code;
53739
53886
  extras;
53887
+ /** Retry-After delta seconds when the server supplies one. */
53888
+ retryAfterSeconds;
53740
53889
  /** Attempted action (authorization denials) — e.g. "chat.add_member". */
53741
53890
  action;
53742
53891
  /** Target resource URI that was evaluated — e.g. "prll://cht_…". */
@@ -53756,6 +53905,9 @@ function buildApiError(res, rawErrorBody) {
53756
53905
  const errMsg = (typeof errorObj?.message === "string" ? errorObj.message : void 0) ?? (typeof errorBody.message === "string" ? errorBody.message : void 0) ?? (typeof errorBody.error === "string" ? errorBody.error : void 0);
53757
53906
  const errCode = (typeof errorObj?.code === "string" ? errorObj.code : void 0) ?? (typeof errorBody.code === "string" ? errorBody.code : void 0);
53758
53907
  const apiError = new ApiError(res.status, errMsg ?? res.statusText, errCode);
53908
+ const retryAfter = Number(res.headers?.get("Retry-After"));
53909
+ if (Number.isFinite(retryAfter) && retryAfter > 0)
53910
+ apiError.retryAfterSeconds = retryAfter;
53759
53911
  const anchors = errorObj ?? errorBody;
53760
53912
  if (typeof anchors.action === "string")
53761
53913
  apiError.action = anchors.action;
@@ -55052,6 +55204,17 @@ function buildForkResultPrefix(results) {
55052
55204
  }
55053
55205
 
55054
55206
  // ../agent-core/dist/prompt-fragments.js
55207
+ function identityFromMe(me) {
55208
+ return {
55209
+ userId: me.id,
55210
+ displayName: me.display_name,
55211
+ title: me.public_profile?.title || void 0,
55212
+ publicDescription: me.public_profile?.description || void 0,
55213
+ // `||` on purpose: an empty-string instructions must also fall back to
55214
+ // the deprecated description alias (empty means "unset" on this wire).
55215
+ instructions: me.agent_profile?.instructions || me.agent_profile?.description || void 0
55216
+ };
55217
+ }
55055
55218
  var PRLL_IDENTITY_BASE = `## You on Parall
55056
55219
 
55057
55220
  Parall is a shared workspace where humans and agents work side by side as equals.
@@ -55073,11 +55236,15 @@ function buildIdentity(agent) {
55073
55236
  const name = sanitizeProfileField(agent.displayName);
55074
55237
  const lines = [PRLL_IDENTITY_BASE, "", "### Your Parall Identity", ""];
55075
55238
  lines.push(`You are **${name}** (\`prll://${agent.userId}\`).`);
55076
- if (agent.description) {
55077
- const description = sanitizeProfileBlock(agent.description);
55078
- if (description) {
55079
- lines.push("", "### Your Agent Profile", "", description);
55080
- }
55239
+ const title = agent.title ? sanitizeProfileField(agent.title) : "";
55240
+ if (title)
55241
+ lines.push(`Title: ${title}`);
55242
+ const about = agent.publicDescription ? sanitizeProfileField(agent.publicDescription) : "";
55243
+ if (about)
55244
+ lines.push(`About: ${about}`);
55245
+ const instructions = sanitizeProfileBlock(agent.instructions ?? agent.description ?? "");
55246
+ if (instructions) {
55247
+ lines.push("", "### Private instructions from your organization admins", "", instructions);
55081
55248
  }
55082
55249
  lines.push("", `When you see \`${agent.userId}\` or \`prll://${agent.userId}\` in messages, mentions, or events \u2014 that's you.`);
55083
55250
  return lines.join("\n");
@@ -57988,7 +58155,7 @@ var ParallAgentGateway = class {
57988
58155
  return { action: "skip" };
57989
58156
  if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
57990
58157
  const mentions = content.mentions ?? [];
57991
- const isMentioned = mentions.some((mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID);
58158
+ const isMentioned = mentions.some((mention) => mentionTargetsUser(mention.user_id, this.opts.agentUserId, "agent"));
57992
58159
  if (!isMentioned)
57993
58160
  return { action: "skip" };
57994
58161
  }
@@ -60160,7 +60327,7 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
60160
60327
  throw err;
60161
60328
  }
60162
60329
  const user = await client.getMe();
60163
- return { ...user, agent_profile: null };
60330
+ return { ...user, agent_profile: null, public_profile: null };
60164
60331
  }
60165
60332
  }
60166
60333
  function buildInboundCtx(core, accountId, event, sessionKey, bodyForAgent, earlierEvents = []) {
@@ -60441,11 +60608,7 @@ var parallGateway = {
60441
60608
  });
60442
60609
  const me = await getAgentMeWithLegacyFallback(client, config.org_id);
60443
60610
  const agentUserId = me.id;
60444
- setAgentIdentity({
60445
- userId: agentUserId,
60446
- displayName: me.display_name,
60447
- description: me.agent_profile?.description ?? void 0
60448
- });
60611
+ setAgentIdentity(identityFromMe(me));
60449
60612
  log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
60450
60613
  const telemetry = await initAgentTelemetry("parall-openclaw-agent", "openclaw");
60451
60614
  const otelLog = createOtelLogger("agent", "openclaw-agent");
@@ -60537,7 +60700,15 @@ var parallGateway = {
60537
60700
  forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
60538
60701
  dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
60539
60702
  onConfigUpdate: async () => {
60540
- await fetchAndApplyPlatformConfig(configManagerOpts);
60703
+ try {
60704
+ await fetchAndApplyPlatformConfig(configManagerOpts);
60705
+ } finally {
60706
+ try {
60707
+ setAgentIdentity(identityFromMe(await getAgentMeWithLegacyFallback(client, config.org_id)));
60708
+ } catch (err) {
60709
+ log?.warn(`parall[${ctx.accountId}]: /agents/me refetch failed (keeping last-known identity): ${String(err)}`);
60710
+ }
60711
+ }
60541
60712
  },
60542
60713
  onSessionReady: async ({ activeSessionId }) => {
60543
60714
  setParallAccountState(ctx.accountId, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.48.0",
3
+ "version": "1.50.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/sdk": "1.48.0",
20
- "@parall/agent-core": "1.48.0"
19
+ "@parall/agent-core": "1.50.0",
20
+ "@parall/sdk": "1.50.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@types/node": "^22.0.0",
@@ -19,8 +19,17 @@ parall whoami
19
19
  parall members list # All org members (humans + agents)
20
20
  parall agents list # Agents only
21
21
  parall users get prll://usr_xxx # Get user details by ID
22
+ parall members profile prll://usr_xxx # A member's public profile (title / about)
23
+ parall agents instructions # Your own private Instructions (admin-maintained)
22
24
  ```
23
25
 
26
+ Every member carries an org-scoped public profile: `title` (role, e.g.
27
+ "Platform Lead") and `description` (a short about). `members list` includes
28
+ both — use them to route work to the right person or agent. Your own system
29
+ prompt already contains your public profile and your private Instructions;
30
+ you cannot edit either of them — if yours should change, DM a Human org
31
+ admin and ask.
32
+
24
33
  Create a hosted agent when the user asks for a Parall-managed runtime. Hosted
25
34
  provisioning is asynchronous: creation means the agent identity, API key, and
26
35
  machine record were accepted, not that the runtime is online yet. Use `--wait`
@@ -39,7 +39,7 @@ parall tasks list --assignee-id prll://usr_xxx # first page only (default 20)
39
39
  parall tasks subtasks prll://tsk_xxx # children of a single parent task
40
40
 
41
41
  # Create a task (add --parent-id to make it a SUBTASK of another task)
42
- parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--parent-id prll://tsk_xxx] [--project-id prll://prj_xxx] [--due-date 2026-08-01]
42
+ parall tasks create --title "Task title" [--assignee-id prll://usr_xxx] [--parent-id prll://tsk_xxx] [--project-id prll://prj_xxx] [--planned-start 2026-07-20] [--due-date 2026-08-01]
43
43
 
44
44
  # Update task status — add --placement end so the task lands at the end of
45
45
  # its NEW status column (a bare --status keeps the old column's sort_order)
@@ -50,6 +50,12 @@ parall tasks update prll://tsk_xxx --status done --placement end
50
50
  parall tasks update prll://tsk_xxx --due-date 2026-08-01
51
51
  parall tasks update prll://tsk_xxx --due-date none
52
52
 
53
+ # Planned start — same grammar as --due-date; must be on or before the due
54
+ # date when both are set. This is the planned schedule's left-edge date,
55
+ # NOT when work actually began (that stays on lifecycle timestamps)
56
+ parall tasks update prll://tsk_xxx --planned-start 2026-07-20
57
+ parall tasks update prll://tsk_xxx --planned-start none
58
+
53
59
  # Move a task to the end of its status column
54
60
  parall tasks update prll://tsk_xxx --placement end
55
61
 
package/src/gateway.ts CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  parseShutdownDeadlineMs,
11
11
  parseForkDeadlineMs,
12
12
  parseDispatchDeadlineMs,
13
+ identityFromMe,
13
14
  initAgentTelemetry,
14
15
  createOtelLogger,
15
16
  type DispatchAdapter,
@@ -73,10 +74,14 @@ async function getAgentMeWithLegacyFallback(client: ParallClient, orgId: string)
73
74
  throw err;
74
75
  }
75
76
  const user = await client.getMe();
76
- return { ...user, agent_profile: null };
77
+ return { ...user, agent_profile: null, public_profile: null };
77
78
  }
78
79
  }
79
80
 
81
+ // hooks.ts rebuilds the prompt from the process-global identity on EVERY
82
+ // prompt build, so a refreshed identity (via the shared identityFromMe)
83
+ // reaches the very next turn without any restart.
84
+
80
85
  function buildInboundCtx(
81
86
  core: PluginRuntime,
82
87
  accountId: string,
@@ -408,11 +413,7 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
408
413
 
409
414
  const me = await getAgentMeWithLegacyFallback(client, config.org_id);
410
415
  const agentUserId = me.id;
411
- setAgentIdentity({
412
- userId: agentUserId,
413
- displayName: me.display_name,
414
- description: me.agent_profile?.description ?? undefined,
415
- });
416
+ setAgentIdentity(identityFromMe(me));
416
417
  log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
417
418
 
418
419
  const telemetry = await initAgentTelemetry('parall-openclaw-agent', 'openclaw');
@@ -518,7 +519,25 @@ export const parallGateway: ChannelGatewayAdapter<ResolvedParallAccount> = {
518
519
  forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
519
520
  dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
520
521
  onConfigUpdate: async () => {
521
- await fetchAndApplyPlatformConfig(configManagerOpts);
522
+ // Identity rides the same agent_config.update nudge: refresh the
523
+ // process-global identity so the next prompt build (hooks.ts
524
+ // before_prompt_build) carries the new title / public description /
525
+ // instructions. The finally keeps it running even when the platform
526
+ // config refresh throws (their failure domains are independent);
527
+ // identity failure keeps the last-known-good value.
528
+ try {
529
+ await fetchAndApplyPlatformConfig(configManagerOpts);
530
+ } finally {
531
+ try {
532
+ setAgentIdentity(
533
+ identityFromMe(await getAgentMeWithLegacyFallback(client, config.org_id)),
534
+ );
535
+ } catch (err) {
536
+ log?.warn(
537
+ `parall[${ctx.accountId}]: /agents/me refetch failed (keeping last-known identity): ${String(err)}`,
538
+ );
539
+ }
540
+ }
522
541
  },
523
542
  onSessionReady: async ({ activeSessionId }) => {
524
543
  setParallAccountState(ctx.accountId, {