@parall/parall 1.49.0 → 1.50.1

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, {
@@ -51289,8 +51289,16 @@ function laneContextFilePath(contextDir, targetUri, threadRootId) {
51289
51289
  return path.join(contextDir, `${laneKeyForTarget(targetUri, threadRootId)}.json`);
51290
51290
  }
51291
51291
 
51292
- // ../sdk/dist/types.js
51293
- var MENTION_ALL_USER_ID = "all";
51292
+ // ../sdk/dist/browser-viewer.js
51293
+ var BROWSER_VIEWER_READINESS_TIMEOUT_MS = 6e4;
51294
+ function browserViewerRequestOptions(command, opts) {
51295
+ if (command !== "stream.answer" && command !== "stream.switch")
51296
+ return opts;
51297
+ return {
51298
+ ...opts,
51299
+ timeoutMs: Math.max(opts?.timeoutMs ?? 0, BROWSER_VIEWER_READINESS_TIMEOUT_MS)
51300
+ };
51301
+ }
51294
51302
 
51295
51303
  // ../sdk/dist/constants.js
51296
51304
  var API_BASE = "/api/v1";
@@ -51326,6 +51334,12 @@ var ENDPOINTS = {
51326
51334
  ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
51327
51335
  ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
51328
51336
  ORG_MEMBER_TASKS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/tasks`,
51337
+ // Org-scoped public profile (title / description). GET readable by every
51338
+ // active member; PATCH is CAS-guarded (expected_version).
51339
+ ORG_MEMBER_PROFILE: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}/profile`,
51340
+ // Private agent Instructions — visibility gated server-side
51341
+ // (agent self + Human org admin/owner). Never cached.
51342
+ AGENT_INSTRUCTIONS: (orgId, agentId) => `${API_BASE}/orgs/${orgId}/agents/${agentId}/instructions`,
51329
51343
  REF_SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/search`,
51330
51344
  // Direct messages (org-scoped, atomic find-or-create + send)
51331
51345
  DM: (orgId) => `${API_BASE}/orgs/${orgId}/dm`,
@@ -51609,6 +51623,11 @@ var ENDPOINTS = {
51609
51623
  SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/search`,
51610
51624
  // Feature flags (org-scoped, server-evaluated)
51611
51625
  FEATURE_FLAGS: (orgId) => `${API_BASE}/orgs/${orgId}/feature-flags`,
51626
+ // Team templates (org-scoped, owner/admin only)
51627
+ TEMPLATES: (orgId) => `${API_BASE}/orgs/${orgId}/templates`,
51628
+ TEMPLATE: (orgId, templateId) => `${API_BASE}/orgs/${orgId}/templates/${templateId}`,
51629
+ TEMPLATE_DEPLOYMENTS: (orgId) => `${API_BASE}/orgs/${orgId}/template-deployments`,
51630
+ TEMPLATE_DEPLOYMENT: (orgId, deploymentId) => `${API_BASE}/orgs/${orgId}/template-deployments/${deploymentId}`,
51612
51631
  // Billing & Credits (org-scoped)
51613
51632
  BILLING: (orgId) => `${API_BASE}/orgs/${orgId}/billing`,
51614
51633
  BILLING_TRANSACTIONS: (orgId) => `${API_BASE}/orgs/${orgId}/billing/transactions`,
@@ -52129,6 +52148,30 @@ var ParallClient = class _ParallClient {
52129
52148
  async updateOrgMember(orgId, userId, role) {
52130
52149
  return this.request("PATCH", ENDPOINTS.ORG_MEMBER(orgId, userId), { role });
52131
52150
  }
52151
+ /** Org-scoped public profile (title / description) of any active member. */
52152
+ async getMemberProfile(orgId, userId) {
52153
+ return this.request("GET", ENDPOINTS.ORG_MEMBER_PROFILE(orgId, userId));
52154
+ }
52155
+ /**
52156
+ * CAS full-replacement of a member's public profile. Humans edit their
52157
+ * own; Human org admins/owners edit agents'. A stale expected_version
52158
+ * gets 409 PROFILE_VERSION_CONFLICT with error.details.current_version.
52159
+ */
52160
+ async updateMemberProfile(orgId, userId, req) {
52161
+ return this.request("PATCH", ENDPOINTS.ORG_MEMBER_PROFILE(orgId, userId), req);
52162
+ }
52163
+ /** Private agent Instructions — agent self or Human org admin/owner only. */
52164
+ async getAgentInstructions(orgId, agentId) {
52165
+ return this.request("GET", ENDPOINTS.AGENT_INSTRUCTIONS(orgId, agentId));
52166
+ }
52167
+ /**
52168
+ * CAS update of the private Instructions (Human org admin/owner only).
52169
+ * A stale expected_version gets 409 INSTRUCTIONS_VERSION_CONFLICT with
52170
+ * error.details.current_version.
52171
+ */
52172
+ async updateAgentInstructions(orgId, agentId, req) {
52173
+ return this.request("PATCH", ENDPOINTS.AGENT_INSTRUCTIONS(orgId, agentId), req);
52174
+ }
52132
52175
  // Member activity surfaces — chats the member participates in within this org,
52133
52176
  // ordered by most recent activity. Powers the member profile Activity tab.
52134
52177
  async getMemberChats(orgId, memberId, params) {
@@ -52686,11 +52729,7 @@ var ParallClient = class _ParallClient {
52686
52729
  async postBrowseResponse(requestId, response) {
52687
52730
  return this.request("POST", ENDPOINTS.MACHINES_ME_BROWSE_RESPONSE(requestId), response);
52688
52731
  }
52689
- /**
52690
- * `POST /machines/me/browser-profiles/viewer-response/{requestId}` — daemon
52691
- * reply to a `machine.browser_profile.viewer` control command. Wakes the
52692
- * api-server request/reply bridge (mirrors {@link postBrowseResponse}).
52693
- */
52732
+ /** Reply to `machine.browser_profile.viewer` and wake its request/reply bridge. */
52694
52733
  async postBrowserProfileViewerResponse(requestId, response) {
52695
52734
  return this.request("POST", ENDPOINTS.MACHINES_ME_BROWSER_PROFILE_VIEWER_RESPONSE(requestId), response);
52696
52735
  }
@@ -52700,7 +52739,7 @@ var ParallClient = class _ParallClient {
52700
52739
  * owner or org admin. api-server brokers the command to the host daemon.
52701
52740
  */
52702
52741
  async browserViewerCommand(orgId, profileId, req, opts) {
52703
- return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, opts);
52742
+ return this.request("POST", ENDPOINTS.BROWSER_PROFILE_VIEWER_COMMAND(orgId, profileId), req, void 0, false, browserViewerRequestOptions(req.command, opts));
52704
52743
  }
52705
52744
  /**
52706
52745
  * Drive the Cloud Edge live viewer (V1b, design §6): WebRTC signaling + input +
@@ -53472,6 +53511,22 @@ var ParallClient = class _ParallClient {
53472
53511
  async getFeatureFlags(orgId) {
53473
53512
  return this.request("GET", ENDPOINTS.FEATURE_FLAGS(orgId));
53474
53513
  }
53514
+ // ---- Official Template catalog (org-contextual owner/admin reads + Hire) ----
53515
+ async listOfficialTemplates(orgId) {
53516
+ const response = await this.request("GET", ENDPOINTS.TEMPLATES(orgId));
53517
+ return response.templates ?? [];
53518
+ }
53519
+ async getOfficialTemplate(orgId, templateId) {
53520
+ return this.request("GET", ENDPOINTS.TEMPLATE(orgId, templateId));
53521
+ }
53522
+ async deployTemplate(orgId, request3) {
53523
+ return this.request("POST", ENDPOINTS.TEMPLATE_DEPLOYMENTS(orgId), request3, void 0, false, {
53524
+ timeoutMs: 185e3
53525
+ });
53526
+ }
53527
+ async getTemplateDeployment(orgId, deploymentId) {
53528
+ return this.request("GET", ENDPOINTS.TEMPLATE_DEPLOYMENT(orgId, deploymentId));
53529
+ }
53475
53530
  // ---- Billing & Credits (org-scoped) ----
53476
53531
  async getBilling(orgId) {
53477
53532
  return this.request("GET", ENDPOINTS.BILLING(orgId));
@@ -53868,6 +53923,20 @@ function buildApiError(res, rawErrorBody) {
53868
53923
  return apiError;
53869
53924
  }
53870
53925
 
53926
+ // ../sdk/dist/types.js
53927
+ var MENTION_ALL_USER_ID = "all";
53928
+ var MENTION_ALL_HUMANS_USER_ID = "allhuman";
53929
+ var MENTION_ALL_AGENTS_USER_ID = "allagent";
53930
+ function mentionTargetsUser(mentionUserId, userId, userType) {
53931
+ if (mentionUserId === userId || mentionUserId === MENTION_ALL_USER_ID)
53932
+ return true;
53933
+ if (mentionUserId === MENTION_ALL_HUMANS_USER_ID)
53934
+ return userType === "human";
53935
+ if (mentionUserId === MENTION_ALL_AGENTS_USER_ID)
53936
+ return userType === "agent";
53937
+ return false;
53938
+ }
53939
+
53871
53940
  // ../sdk/dist/ws.js
53872
53941
  function isRetryableNetworkError(err) {
53873
53942
  return err instanceof Error && err.name === "ApiError" && "status" in err && err.status === 0;
@@ -55142,6 +55211,17 @@ function buildForkResultPrefix(results) {
55142
55211
  }
55143
55212
 
55144
55213
  // ../agent-core/dist/prompt-fragments.js
55214
+ function identityFromMe(me) {
55215
+ return {
55216
+ userId: me.id,
55217
+ displayName: me.display_name,
55218
+ title: me.public_profile?.title || void 0,
55219
+ publicDescription: me.public_profile?.description || void 0,
55220
+ // `||` on purpose: an empty-string instructions must also fall back to
55221
+ // the deprecated description alias (empty means "unset" on this wire).
55222
+ instructions: me.agent_profile?.instructions || me.agent_profile?.description || void 0
55223
+ };
55224
+ }
55145
55225
  var PRLL_IDENTITY_BASE = `## You on Parall
55146
55226
 
55147
55227
  Parall is a shared workspace where humans and agents work side by side as equals.
@@ -55163,11 +55243,15 @@ function buildIdentity(agent) {
55163
55243
  const name = sanitizeProfileField(agent.displayName);
55164
55244
  const lines = [PRLL_IDENTITY_BASE, "", "### Your Parall Identity", ""];
55165
55245
  lines.push(`You are **${name}** (\`prll://${agent.userId}\`).`);
55166
- if (agent.description) {
55167
- const description = sanitizeProfileBlock(agent.description);
55168
- if (description) {
55169
- lines.push("", "### Your Agent Profile", "", description);
55170
- }
55246
+ const title = agent.title ? sanitizeProfileField(agent.title) : "";
55247
+ if (title)
55248
+ lines.push(`Title: ${title}`);
55249
+ const about = agent.publicDescription ? sanitizeProfileField(agent.publicDescription) : "";
55250
+ if (about)
55251
+ lines.push(`About: ${about}`);
55252
+ const instructions = sanitizeProfileBlock(agent.instructions ?? agent.description ?? "");
55253
+ if (instructions) {
55254
+ lines.push("", "### Private instructions from your organization admins", "", instructions);
55171
55255
  }
55172
55256
  lines.push("", `When you see \`${agent.userId}\` or \`prll://${agent.userId}\` in messages, mentions, or events \u2014 that's you.`);
55173
55257
  return lines.join("\n");
@@ -58078,7 +58162,7 @@ var ParallAgentGateway = class {
58078
58162
  return { action: "skip" };
58079
58163
  if (chatInfo.type === "group" && chatInfo.agentRoutingMode !== "active") {
58080
58164
  const mentions = content.mentions ?? [];
58081
- const isMentioned = mentions.some((mention) => mention.user_id === this.opts.agentUserId || mention.user_id === MENTION_ALL_USER_ID);
58165
+ const isMentioned = mentions.some((mention) => mentionTargetsUser(mention.user_id, this.opts.agentUserId, "agent"));
58082
58166
  if (!isMentioned)
58083
58167
  return { action: "skip" };
58084
58168
  }
@@ -60250,7 +60334,7 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
60250
60334
  throw err;
60251
60335
  }
60252
60336
  const user = await client.getMe();
60253
- return { ...user, agent_profile: null };
60337
+ return { ...user, agent_profile: null, public_profile: null };
60254
60338
  }
60255
60339
  }
60256
60340
  function buildInboundCtx(core, accountId, event, sessionKey, bodyForAgent, earlierEvents = []) {
@@ -60531,11 +60615,7 @@ var parallGateway = {
60531
60615
  });
60532
60616
  const me = await getAgentMeWithLegacyFallback(client, config.org_id);
60533
60617
  const agentUserId = me.id;
60534
- setAgentIdentity({
60535
- userId: agentUserId,
60536
- displayName: me.display_name,
60537
- description: me.agent_profile?.description ?? void 0
60538
- });
60618
+ setAgentIdentity(identityFromMe(me));
60539
60619
  log?.info(`parall[${ctx.accountId}]: authenticated as ${me.display_name} (${agentUserId})`);
60540
60620
  const telemetry = await initAgentTelemetry("parall-openclaw-agent", "openclaw");
60541
60621
  const otelLog = createOtelLogger("agent", "openclaw-agent");
@@ -60627,7 +60707,15 @@ var parallGateway = {
60627
60707
  forkDeadlineMs: parseForkDeadlineMs(process.env.PRLL_FORK_DEADLINE_MS),
60628
60708
  dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
60629
60709
  onConfigUpdate: async () => {
60630
- await fetchAndApplyPlatformConfig(configManagerOpts);
60710
+ try {
60711
+ await fetchAndApplyPlatformConfig(configManagerOpts);
60712
+ } finally {
60713
+ try {
60714
+ setAgentIdentity(identityFromMe(await getAgentMeWithLegacyFallback(client, config.org_id)));
60715
+ } catch (err) {
60716
+ log?.warn(`parall[${ctx.accountId}]: /agents/me refetch failed (keeping last-known identity): ${String(err)}`);
60717
+ }
60718
+ }
60631
60719
  },
60632
60720
  onSessionReady: async ({ activeSessionId }) => {
60633
60721
  setParallAccountState(ctx.accountId, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parall/parall",
3
- "version": "1.49.0",
3
+ "version": "1.50.1",
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.49.0",
20
- "@parall/sdk": "1.49.0"
19
+ "@parall/agent-core": "1.50.1",
20
+ "@parall/sdk": "1.50.1"
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`
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, {