@atlaskit/collab-provider 39.0.6 → 39.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,40 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 39.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`88f6eda39f497`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/88f6eda39f497) -
8
+ Resolve agent telepointer colours from supplied display names and stable named IDs instead of
9
+ machine types. Under `confluence_ncs_step_diffing_version_history`, collab-provider carries
10
+ `agentId`, `agentName` and `agentNamedId` from received steps into local agent presence, retaining
11
+ known metadata when later steps omit it. This path uses no profile lookups. Missing presentation
12
+ metadata uses the generic agent palette; human participants keep their existing colours.
13
+
14
+ Telepointers identify agent participants from these explicit identity fields rather than
15
+ `agentType` or a human participant's display name.
16
+
17
+ `getParticipantColor(id, agentName?, agentNamedId?)` and
18
+ `collabEdit.actions.getAvatarColor(id, agentName?, agentNamedId?)` now accept a resolved display
19
+ name in the second argument. Callers previously passing a machine type should supply the agent's
20
+ name instead, and pass stable named IDs in the third argument. With
21
+ `confluence_ncs_step_diffing_version_history` enabled, named brand metadata takes precedence over
22
+ the display name. With the gate off, brand lookup is disabled. Human callers should continue to
23
+ omit agent metadata.
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies
28
+
29
+ ## 39.0.7
30
+
31
+ ### Patch Changes
32
+
33
+ - [`0f850e01177aa`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0f850e01177aa) -
34
+ Remove the abandoned collab_edit_via_websocket_only_for_gcp feature gate and its WebSocket-only
35
+ transport path.
36
+ - Updated dependencies
37
+
3
38
  ## 39.0.6
4
39
 
5
40
  ### Patch Changes
@@ -971,7 +971,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
971
971
  }
972
972
  try {
973
973
  var _this$analyticsHelper34;
974
- var agentTypeByProviderId = new Map();
974
+ var agentsByProviderId = new Map();
975
975
  var agentIds = new Set();
976
976
  var agentTypes = new Set();
977
977
  var agentStepCount = 0;
@@ -985,11 +985,19 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
985
985
  continue;
986
986
  }
987
987
  agentStepCount++;
988
- var _ref10 = step,
989
- agentId = _ref10.agentId,
990
- agentType = _ref10.agentType;
988
+ var _ref11 = step,
989
+ agentId = _ref11.agentId,
990
+ agentType = _ref11.agentType,
991
+ agentName = _ref11.agentName,
992
+ agentNamedId = _ref11.agentNamedId;
991
993
  if (agentType) {
992
- agentTypeByProviderId.set(providerId, agentType);
994
+ var previous = agentsByProviderId.get(providerId);
995
+ agentsByProviderId.set(providerId, {
996
+ agentType: agentType,
997
+ agentId: (agentId ? (0, _utils.normalizeAgentId)(agentId.trim()) : undefined) || (previous === null || previous === void 0 ? void 0 : previous.agentId),
998
+ agentName: (agentName === null || agentName === void 0 ? void 0 : agentName.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentName),
999
+ agentNamedId: (agentNamedId === null || agentNamedId === void 0 ? void 0 : agentNamedId.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentNamedId)
1000
+ });
993
1001
  agentTypes.add(agentType);
994
1002
  }
995
1003
  if (agentId) {
@@ -1002,7 +1010,7 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
1002
1010
  } finally {
1003
1011
  _iterator.f();
1004
1012
  }
1005
- if (agentTypeByProviderId.size === 0) {
1013
+ if (agentsByProviderId.size === 0) {
1006
1014
  return;
1007
1015
  }
1008
1016
  // Anchor signal that the agent-presence logic kicked off for a received transaction. Fires
@@ -1010,13 +1018,21 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
1010
1018
  // non-PII: agent kinds, actor ids, and counts — never document content.
1011
1019
  (_this$analyticsHelper34 = this.analyticsHelper) === null || _this$analyticsHelper34 === void 0 || _this$analyticsHelper34.sendActionEvent(_const.EVENT_ACTION.AGENT_EDIT_RECEIVED, _const.EVENT_STATUS.SUCCESS, {
1012
1020
  agentIds: (0, _toConsumableArray2.default)(agentIds),
1013
- agentCount: agentTypeByProviderId.size,
1021
+ agentCount: agentsByProviderId.size,
1014
1022
  agentTypes: (0, _toConsumableArray2.default)(agentTypes),
1015
1023
  agentStepCount: agentStepCount,
1016
1024
  totalStepCount: steps.length
1017
1025
  });
1018
- agentTypeByProviderId.forEach(function (agentType, providerId) {
1019
- return _this3.participantsService.upsertAIProviderParticipantLocally(providerId, agentType);
1026
+ agentsByProviderId.forEach(function (_ref10, providerId) {
1027
+ var agentType = _ref10.agentType,
1028
+ agentId = _ref10.agentId,
1029
+ agentName = _ref10.agentName,
1030
+ agentNamedId = _ref10.agentNamedId;
1031
+ return _this3.participantsService.upsertAIProviderParticipantLocally(providerId, agentType, (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? {
1032
+ agentId: agentId,
1033
+ agentName: agentName,
1034
+ agentNamedId: agentNamedId
1035
+ } : undefined);
1020
1036
  });
1021
1037
  } catch (error) {
1022
1038
  var _this$analyticsHelper35;
@@ -1044,10 +1060,10 @@ var DocumentService = exports.DocumentService = /*#__PURE__*/function () {
1044
1060
  * @param root0.clientId
1045
1061
  * @example
1046
1062
  */
1047
- function setup(_ref11) {
1048
- var getState = _ref11.getState,
1049
- onSyncUpError = _ref11.onSyncUpError,
1050
- clientId = _ref11.clientId;
1063
+ function setup(_ref12) {
1064
+ var getState = _ref12.getState,
1065
+ onSyncUpError = _ref12.onSyncUpError,
1066
+ clientId = _ref12.clientId;
1051
1067
  this.getState = getState;
1052
1068
  this.onSyncUpError = onSyncUpError || noop;
1053
1069
  this.clientId = clientId;
@@ -138,32 +138,41 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
138
138
  *
139
139
  * Deliberately does NOT go through the `getUser` hydration path: agents have no human profile,
140
140
  * so `getUser('agent:<id>')` would 404/throw (and could drop the participant) or add latency;
141
- * the agent's display identity is resolved downstream in the facepile.
141
+ * supplied step presentation can be used directly; avatars are resolved downstream.
142
142
  *
143
- * `presence` is emitted only on the FIRST add for an agent. Subsequent steps for the same agent
144
- * refresh `lastActive` and reset the sliding inactivity timer silently, to avoid churning every
145
- * presence consumer on each streamed step.
143
+ * Unchanged active agents refresh `lastActive` and the inactivity timer silently. Emit presence
144
+ * when an agent is added or its supplied identity changes, so consumers get the latest metadata.
146
145
  *
147
146
  * @param providerId `agent:<aaid|type>` id of the agent
148
147
  * @param agentType kind of the agent that authored the step
148
+ * @param identity optional display metadata already supplied by the agent's steps
149
149
  */
150
- (0, _defineProperty2.default)(this, "upsertAIProviderParticipantLocally", function (providerId, agentType) {
150
+ (0, _defineProperty2.default)(this, "upsertAIProviderParticipantLocally", function (providerId, agentType, identity) {
151
+ var _identity$agentId, _identity$agentName, _identity$agentNamedI;
151
152
  var payload = _this.buildAIProviderPresencePayload(providerId, agentType);
152
153
  var sessionId = payload.sessionId;
153
154
  var existing = _this.participantsState.getBySessionId(sessionId);
154
155
  var hasAgentTypeChanged = (existing === null || existing === void 0 ? void 0 : existing.agentType) !== agentType;
156
+ var agentId = (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentId = identity.agentId) === null || _identity$agentId === void 0 ? void 0 : _identity$agentId.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentId) : undefined;
157
+ var name = (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentName = identity.agentName) === null || _identity$agentName === void 0 ? void 0 : _identity$agentName.trim()) || (existing === null || existing === void 0 ? void 0 : existing.name) || '' : '';
158
+ var agentNamedId = (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentNamedI = identity.agentNamedId) === null || _identity$agentNamedI === void 0 ? void 0 : _identity$agentNamedI.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentNamedId) : undefined;
155
159
  var wasInactive = existing ? Date.now() - existing.lastActive >= AGENT_PRESENCE_INACTIVE_MS : false;
156
- var participant = _objectSpread(_objectSpread(_objectSpread({}, payload), (0, _fg.fg)('platform_move_presence_agents') ? {
160
+ var participant = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, payload), (0, _fg.fg)('platform_move_presence_agents') ? {
157
161
  presenceActivity: 'editor'
158
162
  } : {}), {}, {
159
163
  // `payload.userId` is typed `string | undefined`; here it is always the (string)
160
164
  // providerId, so pin it to satisfy ProviderParticipant.userId (string).
161
165
  userId: providerId,
162
166
  lastActive: payload.timestamp,
163
- // name/avatar/email are intentionally empty: an agent has no human profile here. Its display
164
- // identity (name + avatar) is resolved downstream in the facepile from the agent id, so the
165
- // provider stays identity-free (no getUser/assistance lookup on this hot path).
166
- name: '',
167
+ // Use presentation already supplied on the step; never fetch a human profile on this path.
168
+ name: name
169
+ }, agentId ? {
170
+ agentId: agentId
171
+ } : {}), name ? {
172
+ agentName: name
173
+ } : {}), agentNamedId ? {
174
+ agentNamedId: agentNamedId
175
+ } : {}), {}, {
167
176
  avatar: '',
168
177
  email: ''
169
178
  });
@@ -171,7 +180,7 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
171
180
 
172
181
  // Active refreshes stay silent. Re-emit when an inactive agent becomes active so consumers
173
182
  // can update its presentation immediately.
174
- if (!existing || hasAgentTypeChanged || (0, _fg.fg)('platform_move_presence_agents') && wasInactive) {
183
+ if (!existing || hasAgentTypeChanged || existing.name !== name || existing.agentId !== agentId || existing.agentName !== (name || undefined) || existing.agentNamedId !== agentNamedId || (0, _fg.fg)('platform_move_presence_agents') && wasInactive) {
175
184
  _this.emitPresence({
176
185
  joined: [participant]
177
186
  }, 'adding agent participant from remote step');
@@ -56,8 +56,6 @@ function createSocketIOSocket(url, auth, productInfo, isPresenceOnly, analyticsH
56
56
  if ((0, _fg.fg)('platform_editor_gcp_collab_ws_first')) {
57
57
  transports = ['websocket', 'polling'];
58
58
  webSocketFirst = true;
59
- } else if ((0, _fg.fg)('collab_edit_via_websocket_only_for_gcp')) {
60
- transports = ['websocket'];
61
59
  }
62
60
  break;
63
61
  default:
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/collab-provider";
8
- var version = exports.version = "39.0.5";
8
+ var version = exports.version = "39.0.7";
9
9
  var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
10
10
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
11
11
  };
@@ -847,7 +847,7 @@ export class DocumentService {
847
847
  }
848
848
  try {
849
849
  var _this$analyticsHelper34;
850
- const agentTypeByProviderId = new Map();
850
+ const agentsByProviderId = new Map();
851
851
  const agentIds = new Set();
852
852
  const agentTypes = new Set();
853
853
  let agentStepCount = 0;
@@ -859,10 +859,18 @@ export class DocumentService {
859
859
  agentStepCount++;
860
860
  const {
861
861
  agentId,
862
- agentType
862
+ agentType,
863
+ agentName,
864
+ agentNamedId
863
865
  } = step;
864
866
  if (agentType) {
865
- agentTypeByProviderId.set(providerId, agentType);
867
+ const previous = agentsByProviderId.get(providerId);
868
+ agentsByProviderId.set(providerId, {
869
+ agentType,
870
+ agentId: (agentId ? normalizeAgentId(agentId.trim()) : undefined) || (previous === null || previous === void 0 ? void 0 : previous.agentId),
871
+ agentName: (agentName === null || agentName === void 0 ? void 0 : agentName.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentName),
872
+ agentNamedId: (agentNamedId === null || agentNamedId === void 0 ? void 0 : agentNamedId.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentNamedId)
873
+ });
866
874
  agentTypes.add(agentType);
867
875
  }
868
876
  if (agentId) {
@@ -870,7 +878,7 @@ export class DocumentService {
870
878
  }
871
879
  }
872
880
  // No agent-authored steps in this batch — nothing to register or report.
873
- if (agentTypeByProviderId.size === 0) {
881
+ if (agentsByProviderId.size === 0) {
874
882
  return;
875
883
  }
876
884
  // Anchor signal that the agent-presence logic kicked off for a received transaction. Fires
@@ -878,12 +886,21 @@ export class DocumentService {
878
886
  // non-PII: agent kinds, actor ids, and counts — never document content.
879
887
  (_this$analyticsHelper34 = this.analyticsHelper) === null || _this$analyticsHelper34 === void 0 ? void 0 : _this$analyticsHelper34.sendActionEvent(EVENT_ACTION.AGENT_EDIT_RECEIVED, EVENT_STATUS.SUCCESS, {
880
888
  agentIds: [...agentIds],
881
- agentCount: agentTypeByProviderId.size,
889
+ agentCount: agentsByProviderId.size,
882
890
  agentTypes: [...agentTypes],
883
891
  agentStepCount,
884
892
  totalStepCount: steps.length
885
893
  });
886
- agentTypeByProviderId.forEach((agentType, providerId) => this.participantsService.upsertAIProviderParticipantLocally(providerId, agentType));
894
+ agentsByProviderId.forEach(({
895
+ agentType,
896
+ agentId,
897
+ agentName,
898
+ agentNamedId
899
+ }, providerId) => this.participantsService.upsertAIProviderParticipantLocally(providerId, agentType, fg('confluence_ncs_step_diffing_version_history') ? {
900
+ agentId,
901
+ agentName,
902
+ agentNamedId
903
+ } : undefined));
887
904
  } catch (error) {
888
905
  var _this$analyticsHelper35;
889
906
  (_this$analyticsHelper35 = this.analyticsHelper) === null || _this$analyticsHelper35 === void 0 ? void 0 : _this$analyticsHelper35.sendErrorEvent(error, 'Error while adding agent presence from steps');
@@ -123,22 +123,26 @@ export class ParticipantsService {
123
123
  *
124
124
  * Deliberately does NOT go through the `getUser` hydration path: agents have no human profile,
125
125
  * so `getUser('agent:<id>')` would 404/throw (and could drop the participant) or add latency;
126
- * the agent's display identity is resolved downstream in the facepile.
126
+ * supplied step presentation can be used directly; avatars are resolved downstream.
127
127
  *
128
- * `presence` is emitted only on the FIRST add for an agent. Subsequent steps for the same agent
129
- * refresh `lastActive` and reset the sliding inactivity timer silently, to avoid churning every
130
- * presence consumer on each streamed step.
128
+ * Unchanged active agents refresh `lastActive` and the inactivity timer silently. Emit presence
129
+ * when an agent is added or its supplied identity changes, so consumers get the latest metadata.
131
130
  *
132
131
  * @param providerId `agent:<aaid|type>` id of the agent
133
132
  * @param agentType kind of the agent that authored the step
133
+ * @param identity optional display metadata already supplied by the agent's steps
134
134
  */
135
- _defineProperty(this, "upsertAIProviderParticipantLocally", (providerId, agentType) => {
135
+ _defineProperty(this, "upsertAIProviderParticipantLocally", (providerId, agentType, identity) => {
136
+ var _identity$agentId, _identity$agentName, _identity$agentNamedI;
136
137
  const payload = this.buildAIProviderPresencePayload(providerId, agentType);
137
138
  const {
138
139
  sessionId
139
140
  } = payload;
140
141
  const existing = this.participantsState.getBySessionId(sessionId);
141
142
  const hasAgentTypeChanged = (existing === null || existing === void 0 ? void 0 : existing.agentType) !== agentType;
143
+ const agentId = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 ? void 0 : (_identity$agentId = identity.agentId) === null || _identity$agentId === void 0 ? void 0 : _identity$agentId.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentId) : undefined;
144
+ const name = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 ? void 0 : (_identity$agentName = identity.agentName) === null || _identity$agentName === void 0 ? void 0 : _identity$agentName.trim()) || (existing === null || existing === void 0 ? void 0 : existing.name) || '' : '';
145
+ const agentNamedId = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 ? void 0 : (_identity$agentNamedI = identity.agentNamedId) === null || _identity$agentNamedI === void 0 ? void 0 : _identity$agentNamedI.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentNamedId) : undefined;
142
146
  const wasInactive = existing ? Date.now() - existing.lastActive >= AGENT_PRESENCE_INACTIVE_MS : false;
143
147
  const participant = {
144
148
  ...payload,
@@ -149,10 +153,17 @@ export class ParticipantsService {
149
153
  // providerId, so pin it to satisfy ProviderParticipant.userId (string).
150
154
  userId: providerId,
151
155
  lastActive: payload.timestamp,
152
- // name/avatar/email are intentionally empty: an agent has no human profile here. Its display
153
- // identity (name + avatar) is resolved downstream in the facepile from the agent id, so the
154
- // provider stays identity-free (no getUser/assistance lookup on this hot path).
155
- name: '',
156
+ // Use presentation already supplied on the step; never fetch a human profile on this path.
157
+ name,
158
+ ...(agentId ? {
159
+ agentId
160
+ } : {}),
161
+ ...(name ? {
162
+ agentName: name
163
+ } : {}),
164
+ ...(agentNamedId ? {
165
+ agentNamedId
166
+ } : {}),
156
167
  avatar: '',
157
168
  email: ''
158
169
  };
@@ -160,7 +171,7 @@ export class ParticipantsService {
160
171
 
161
172
  // Active refreshes stay silent. Re-emit when an inactive agent becomes active so consumers
162
173
  // can update its presentation immediately.
163
- if (!existing || hasAgentTypeChanged || fg('platform_move_presence_agents') && wasInactive) {
174
+ if (!existing || hasAgentTypeChanged || existing.name !== name || existing.agentId !== agentId || existing.agentName !== (name || undefined) || existing.agentNamedId !== agentNamedId || fg('platform_move_presence_agents') && wasInactive) {
164
175
  this.emitPresence({
165
176
  joined: [participant]
166
177
  }, 'adding agent participant from remote step');
@@ -45,8 +45,6 @@ export function createSocketIOSocket(url, auth, productInfo, isPresenceOnly, ana
45
45
  if (fg('platform_editor_gcp_collab_ws_first')) {
46
46
  transports = ['websocket', 'polling'];
47
47
  webSocketFirst = true;
48
- } else if (fg('collab_edit_via_websocket_only_for_gcp')) {
49
- transports = ['websocket'];
50
48
  }
51
49
  break;
52
50
  default:
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "39.0.5";
2
+ export const version = "39.0.7";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -966,7 +966,7 @@ export var DocumentService = /*#__PURE__*/function () {
966
966
  }
967
967
  try {
968
968
  var _this$analyticsHelper34;
969
- var agentTypeByProviderId = new Map();
969
+ var agentsByProviderId = new Map();
970
970
  var agentIds = new Set();
971
971
  var agentTypes = new Set();
972
972
  var agentStepCount = 0;
@@ -980,11 +980,19 @@ export var DocumentService = /*#__PURE__*/function () {
980
980
  continue;
981
981
  }
982
982
  agentStepCount++;
983
- var _ref10 = step,
984
- agentId = _ref10.agentId,
985
- agentType = _ref10.agentType;
983
+ var _ref11 = step,
984
+ agentId = _ref11.agentId,
985
+ agentType = _ref11.agentType,
986
+ agentName = _ref11.agentName,
987
+ agentNamedId = _ref11.agentNamedId;
986
988
  if (agentType) {
987
- agentTypeByProviderId.set(providerId, agentType);
989
+ var previous = agentsByProviderId.get(providerId);
990
+ agentsByProviderId.set(providerId, {
991
+ agentType: agentType,
992
+ agentId: (agentId ? normalizeAgentId(agentId.trim()) : undefined) || (previous === null || previous === void 0 ? void 0 : previous.agentId),
993
+ agentName: (agentName === null || agentName === void 0 ? void 0 : agentName.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentName),
994
+ agentNamedId: (agentNamedId === null || agentNamedId === void 0 ? void 0 : agentNamedId.trim()) || (previous === null || previous === void 0 ? void 0 : previous.agentNamedId)
995
+ });
988
996
  agentTypes.add(agentType);
989
997
  }
990
998
  if (agentId) {
@@ -997,7 +1005,7 @@ export var DocumentService = /*#__PURE__*/function () {
997
1005
  } finally {
998
1006
  _iterator.f();
999
1007
  }
1000
- if (agentTypeByProviderId.size === 0) {
1008
+ if (agentsByProviderId.size === 0) {
1001
1009
  return;
1002
1010
  }
1003
1011
  // Anchor signal that the agent-presence logic kicked off for a received transaction. Fires
@@ -1005,13 +1013,21 @@ export var DocumentService = /*#__PURE__*/function () {
1005
1013
  // non-PII: agent kinds, actor ids, and counts — never document content.
1006
1014
  (_this$analyticsHelper34 = this.analyticsHelper) === null || _this$analyticsHelper34 === void 0 || _this$analyticsHelper34.sendActionEvent(EVENT_ACTION.AGENT_EDIT_RECEIVED, EVENT_STATUS.SUCCESS, {
1007
1015
  agentIds: _toConsumableArray(agentIds),
1008
- agentCount: agentTypeByProviderId.size,
1016
+ agentCount: agentsByProviderId.size,
1009
1017
  agentTypes: _toConsumableArray(agentTypes),
1010
1018
  agentStepCount: agentStepCount,
1011
1019
  totalStepCount: steps.length
1012
1020
  });
1013
- agentTypeByProviderId.forEach(function (agentType, providerId) {
1014
- return _this3.participantsService.upsertAIProviderParticipantLocally(providerId, agentType);
1021
+ agentsByProviderId.forEach(function (_ref10, providerId) {
1022
+ var agentType = _ref10.agentType,
1023
+ agentId = _ref10.agentId,
1024
+ agentName = _ref10.agentName,
1025
+ agentNamedId = _ref10.agentNamedId;
1026
+ return _this3.participantsService.upsertAIProviderParticipantLocally(providerId, agentType, fg('confluence_ncs_step_diffing_version_history') ? {
1027
+ agentId: agentId,
1028
+ agentName: agentName,
1029
+ agentNamedId: agentNamedId
1030
+ } : undefined);
1015
1031
  });
1016
1032
  } catch (error) {
1017
1033
  var _this$analyticsHelper35;
@@ -1039,10 +1055,10 @@ export var DocumentService = /*#__PURE__*/function () {
1039
1055
  * @param root0.clientId
1040
1056
  * @example
1041
1057
  */
1042
- function setup(_ref11) {
1043
- var getState = _ref11.getState,
1044
- onSyncUpError = _ref11.onSyncUpError,
1045
- clientId = _ref11.clientId;
1058
+ function setup(_ref12) {
1059
+ var getState = _ref12.getState,
1060
+ onSyncUpError = _ref12.onSyncUpError,
1061
+ clientId = _ref12.clientId;
1046
1062
  this.getState = getState;
1047
1063
  this.onSyncUpError = onSyncUpError || noop;
1048
1064
  this.clientId = clientId;
@@ -131,32 +131,41 @@ export var ParticipantsService = /*#__PURE__*/function () {
131
131
  *
132
132
  * Deliberately does NOT go through the `getUser` hydration path: agents have no human profile,
133
133
  * so `getUser('agent:<id>')` would 404/throw (and could drop the participant) or add latency;
134
- * the agent's display identity is resolved downstream in the facepile.
134
+ * supplied step presentation can be used directly; avatars are resolved downstream.
135
135
  *
136
- * `presence` is emitted only on the FIRST add for an agent. Subsequent steps for the same agent
137
- * refresh `lastActive` and reset the sliding inactivity timer silently, to avoid churning every
138
- * presence consumer on each streamed step.
136
+ * Unchanged active agents refresh `lastActive` and the inactivity timer silently. Emit presence
137
+ * when an agent is added or its supplied identity changes, so consumers get the latest metadata.
139
138
  *
140
139
  * @param providerId `agent:<aaid|type>` id of the agent
141
140
  * @param agentType kind of the agent that authored the step
141
+ * @param identity optional display metadata already supplied by the agent's steps
142
142
  */
143
- _defineProperty(this, "upsertAIProviderParticipantLocally", function (providerId, agentType) {
143
+ _defineProperty(this, "upsertAIProviderParticipantLocally", function (providerId, agentType, identity) {
144
+ var _identity$agentId, _identity$agentName, _identity$agentNamedI;
144
145
  var payload = _this.buildAIProviderPresencePayload(providerId, agentType);
145
146
  var sessionId = payload.sessionId;
146
147
  var existing = _this.participantsState.getBySessionId(sessionId);
147
148
  var hasAgentTypeChanged = (existing === null || existing === void 0 ? void 0 : existing.agentType) !== agentType;
149
+ var agentId = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentId = identity.agentId) === null || _identity$agentId === void 0 ? void 0 : _identity$agentId.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentId) : undefined;
150
+ var name = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentName = identity.agentName) === null || _identity$agentName === void 0 ? void 0 : _identity$agentName.trim()) || (existing === null || existing === void 0 ? void 0 : existing.name) || '' : '';
151
+ var agentNamedId = fg('confluence_ncs_step_diffing_version_history') ? (identity === null || identity === void 0 || (_identity$agentNamedI = identity.agentNamedId) === null || _identity$agentNamedI === void 0 ? void 0 : _identity$agentNamedI.trim()) || (existing === null || existing === void 0 ? void 0 : existing.agentNamedId) : undefined;
148
152
  var wasInactive = existing ? Date.now() - existing.lastActive >= AGENT_PRESENCE_INACTIVE_MS : false;
149
- var participant = _objectSpread(_objectSpread(_objectSpread({}, payload), fg('platform_move_presence_agents') ? {
153
+ var participant = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({}, payload), fg('platform_move_presence_agents') ? {
150
154
  presenceActivity: 'editor'
151
155
  } : {}), {}, {
152
156
  // `payload.userId` is typed `string | undefined`; here it is always the (string)
153
157
  // providerId, so pin it to satisfy ProviderParticipant.userId (string).
154
158
  userId: providerId,
155
159
  lastActive: payload.timestamp,
156
- // name/avatar/email are intentionally empty: an agent has no human profile here. Its display
157
- // identity (name + avatar) is resolved downstream in the facepile from the agent id, so the
158
- // provider stays identity-free (no getUser/assistance lookup on this hot path).
159
- name: '',
160
+ // Use presentation already supplied on the step; never fetch a human profile on this path.
161
+ name: name
162
+ }, agentId ? {
163
+ agentId: agentId
164
+ } : {}), name ? {
165
+ agentName: name
166
+ } : {}), agentNamedId ? {
167
+ agentNamedId: agentNamedId
168
+ } : {}), {}, {
160
169
  avatar: '',
161
170
  email: ''
162
171
  });
@@ -164,7 +173,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
164
173
 
165
174
  // Active refreshes stay silent. Re-emit when an inactive agent becomes active so consumers
166
175
  // can update its presentation immediately.
167
- if (!existing || hasAgentTypeChanged || fg('platform_move_presence_agents') && wasInactive) {
176
+ if (!existing || hasAgentTypeChanged || existing.name !== name || existing.agentId !== agentId || existing.agentName !== (name || undefined) || existing.agentNamedId !== agentNamedId || fg('platform_move_presence_agents') && wasInactive) {
168
177
  _this.emitPresence({
169
178
  joined: [participant]
170
179
  }, 'adding agent participant from remote step');
@@ -47,8 +47,6 @@ export function createSocketIOSocket(url, auth, productInfo, isPresenceOnly, ana
47
47
  if (fg('platform_editor_gcp_collab_ws_first')) {
48
48
  transports = ['websocket', 'polling'];
49
49
  webSocketFirst = true;
50
- } else if (fg('collab_edit_via_websocket_only_for_gcp')) {
51
- transports = ['websocket'];
52
50
  }
53
51
  break;
54
52
  default:
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "39.0.5";
2
+ export var version = "39.0.7";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -1,4 +1,4 @@
1
- import type { CollabEventPresenceData, CollabTelepointerPayload, CollabPresenceActivityChangePayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
1
+ import type { BaseStepPM, CollabEventPresenceData, CollabTelepointerPayload, CollabPresenceActivityChangePayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
2
2
  import type AnalyticsHelper from '../analytics/analytics-helper';
3
3
  import type { CollabEventDisconnectedData, ChannelEvent, PresenceData, PresencePayload, TelepointerPayload, FetchAnonymousAsset } from '../types';
4
4
  import type { BatchProps, GetUserType } from './participants-helper';
@@ -76,16 +76,16 @@ export declare class ParticipantsService {
76
76
  *
77
77
  * Deliberately does NOT go through the `getUser` hydration path: agents have no human profile,
78
78
  * so `getUser('agent:<id>')` would 404/throw (and could drop the participant) or add latency;
79
- * the agent's display identity is resolved downstream in the facepile.
79
+ * supplied step presentation can be used directly; avatars are resolved downstream.
80
80
  *
81
- * `presence` is emitted only on the FIRST add for an agent. Subsequent steps for the same agent
82
- * refresh `lastActive` and reset the sliding inactivity timer silently, to avoid churning every
83
- * presence consumer on each streamed step.
81
+ * Unchanged active agents refresh `lastActive` and the inactivity timer silently. Emit presence
82
+ * when an agent is added or its supplied identity changes, so consumers get the latest metadata.
84
83
  *
85
84
  * @param providerId `agent:<aaid|type>` id of the agent
86
85
  * @param agentType kind of the agent that authored the step
86
+ * @param identity optional display metadata already supplied by the agent's steps
87
87
  */
88
- upsertAIProviderParticipantLocally: (providerId: string, agentType?: string) => void;
88
+ upsertAIProviderParticipantLocally: (providerId: string, agentType?: string, identity?: Pick<BaseStepPM, 'agentId' | 'agentName' | 'agentNamedId'>) => void;
89
89
  /**
90
90
  * (Re)starts the sliding expiry timer for an agent participant. The enriched lifecycle retains
91
91
  * agents for 30 seconds active plus five minutes inactive; the legacy lifecycle removes at 30 seconds.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "39.0.6",
3
+ "version": "39.1.0",
4
4
  "description": "A provider for collaborative editing.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -25,7 +25,7 @@
25
25
  "@atlaskit/atlassian-context": "^2.0.0",
26
26
  "@atlaskit/editor-json-transformer": "^10.0.0",
27
27
  "@atlaskit/editor-prosemirror": "^9.0.0",
28
- "@atlaskit/feature-gate-js-client": "^7.1.0",
28
+ "@atlaskit/feature-gate-js-client": "^8.0.0",
29
29
  "@atlaskit/platform-feature-experiments": "^0.3.0",
30
30
  "@atlaskit/platform-feature-flags": "^2.2.0",
31
31
  "@atlaskit/prosemirror-collab": "^1.1.0",
@@ -69,12 +69,9 @@
69
69
  },
70
70
  "platform_editor_presence_ws_restore_after_upgrade": {
71
71
  "type": "boolean"
72
- },
73
- "collab_edit_via_websocket_only_for_gcp": {
74
- "type": "boolean"
75
72
  }
76
73
  },
77
74
  "peerDependencies": {
78
- "@atlaskit/editor-common": "^134.3.0"
75
+ "@atlaskit/editor-common": "^134.4.0"
79
76
  }
80
77
  }