@pendo/agent 2.330.1 → 2.331.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/dist/dom.esm.js CHANGED
@@ -7505,7 +7505,7 @@ function applyMatrix2dRect(matrix2d, rect) {
7505
7505
  return transformedRect;
7506
7506
  }
7507
7507
 
7508
- var VERSION = '2.330.1_';
7508
+ var VERSION = '2.331.0_';
7509
7509
 
7510
7510
  var decodeURIComponent = _.isFunction(window.decodeURIComponent) ? window.decodeURIComponent : _.identity;
7511
7511
 
@@ -7629,8 +7629,12 @@ function clearCookie(name) {
7629
7629
  // domain-scoped cookie can't be matched for deletion -- omitting it (or
7630
7630
  // writing a blank value) leaves a permanent empty cookie that still costs
7631
7631
  // request-header space via its name.
7632
- var cookie = name + '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
7633
- document.cookie = cookie;
7632
+ var expiry = '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
7633
+ // Also expire the host-only variant (no domain attribute). A domain-scoped
7634
+ // cookie and a host-only cookie with the same name are distinct, so if
7635
+ // cookieDomain was set/changed after the cookie was first written, the
7636
+ // other scope would otherwise be orphaned on the current host.
7637
+ document.cookie = name + expiry;
7634
7638
  }
7635
7639
  var getPendoCookieKey = function (name, cookieSuffix) {
7636
7640
  return "_pendo_".concat(name, ".").concat(cookieSuffix || pendo.apiKey);
@@ -4010,8 +4010,8 @@ let SERVER = '';
4010
4010
  let ASSET_HOST = '';
4011
4011
  let ASSET_PATH = '';
4012
4012
  let DESIGNER_SERVER = '';
4013
- let VERSION = '2.330.1_';
4014
- let PACKAGE_VERSION = '2.330.1';
4013
+ let VERSION = '2.331.0_';
4014
+ let PACKAGE_VERSION = '2.331.0';
4015
4015
  let LOADER = 'xhr';
4016
4016
  /* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
4017
4017
  /**
@@ -4592,11 +4592,15 @@ function clearCookie(name) {
4592
4592
  // domain-scoped cookie can't be matched for deletion -- omitting it (or
4593
4593
  // writing a blank value) leaves a permanent empty cookie that still costs
4594
4594
  // request-header space via its name.
4595
- var cookie = name + '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
4595
+ var expiry = '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
4596
4596
  if (cookieDomain) {
4597
- cookie += ';domain=' + cookieDomain;
4597
+ document.cookie = name + expiry + ';domain=' + cookieDomain;
4598
4598
  }
4599
- document.cookie = cookie;
4599
+ // Also expire the host-only variant (no domain attribute). A domain-scoped
4600
+ // cookie and a host-only cookie with the same name are distinct, so if
4601
+ // cookieDomain was set/changed after the cookie was first written, the
4602
+ // other scope would otherwise be orphaned on the current host.
4603
+ document.cookie = name + expiry;
4600
4604
  }
4601
4605
  var getPendoCookieKey = function (name, cookieSuffix) {
4602
4606
  return `_pendo_${name}.${cookieSuffix || pendo$1.apiKey}`;
@@ -28014,7 +28018,7 @@ var EventRouter = function () {
28014
28018
  if (!currentGuideTerms)
28015
28019
  return false;
28016
28020
  return currentGuideTerms.some(function (term) {
28017
- return _.contains(haystack, (term)) && term === text;
28021
+ return _.contains(haystack, (term)) && term.toLowerCase() === text.toLowerCase();
28018
28022
  });
28019
28023
  }
28020
28024
  function searchGuides(evt) {
@@ -28454,15 +28458,28 @@ var GuideActivity = (function () {
28454
28458
  return _.isString(appData.id) && appData.id.indexOf('pendo-guide-container') === 0;
28455
28459
  }
28456
28460
  function getGuideForEvent(appData) {
28457
- const stepId = getStepIdFromAppData(appData);
28458
- if (stepId) {
28461
+ // A `pendo-g-<id>` container id can be either a stepId or a guideId
28462
+ // (see building-block-guides.js / fetchAndMigrateGuide), so resolve
28463
+ // against both before falling back to the active guide. Without the
28464
+ // guideId match, a click in a guide whose container carries the guideId
28465
+ // drops into the element-blind getActiveGuide() fallback, which can
28466
+ // resolve to a different, higher-priority co-displayed guide.
28467
+ const containerId = getStepIdFromAppData(appData);
28468
+ if (containerId) {
28459
28469
  let step;
28460
- const guide = _.find(getLocalActiveGuides(), function (guide) {
28461
- step = _.find(guide.steps, (step) => step.id === stepId);
28470
+ const guideByStep = _.find(getLocalActiveGuides(), function (guide) {
28471
+ step = _.find(guide.steps, (step) => step.id === containerId);
28462
28472
  return !!step;
28463
28473
  });
28464
- if (guide && step) {
28465
- return { guide, step };
28474
+ if (guideByStep && step) {
28475
+ return { guide: guideByStep, step };
28476
+ }
28477
+ const guideById = _.find(getLocalActiveGuides(), (guide) => guide.id === containerId);
28478
+ if (guideById) {
28479
+ const shownStep = _.find(guideById.steps, (step) => step.isShown());
28480
+ if (shownStep) {
28481
+ return { guide: guideById, step: shownStep };
28482
+ }
28466
28483
  }
28467
28484
  }
28468
28485
  return getActiveGuide();
@@ -52964,16 +52981,16 @@ const THUMB_UP = 'thumbUp';
52964
52981
  const TURN_CONTAINER = 'turnContainer';
52965
52982
  const USER_MESSAGE = 'userMessage';
52966
52983
  const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
52984
+ const CUSTOM_AGENT_ID = 'customAgentId';
52967
52985
  const CUSTOM_AGENT_NAME = 'customAgentName';
52968
52986
  const REQUIRED_SELECTORS = [
52969
52987
  ASSISTANT_MESSAGE,
52970
52988
  CONVERSATION_ID_URL_PATTERN,
52971
- MESSAGE_ID_ATTR,
52972
52989
  STREAMING_ACTIVE,
52973
52990
  TURN_CONTAINER,
52974
52991
  USER_MESSAGE
52975
52992
  ];
52976
- const SUPPORTED_PRESETS = ['chatgpt-full', 'gemini-full'];
52993
+ const SUPPORTED_PRESETS = ['chatgpt-full', 'gemini-full', 'claude-full'];
52977
52994
  const STREAMING_END_SETTLE_MS = 500;
52978
52995
  const SUBMISSION_START_RETRY_MS = 1000;
52979
52996
  const SUBMISSION_START_MAX_ATTEMPTS = 4;
@@ -53163,18 +53180,53 @@ class DOMConversation {
53163
53180
  }
53164
53181
  }
53165
53182
  extractContent(node) {
53166
- return { content: node.text().trim() };
53183
+ // .text() reads innerText, which is empty for content-visibility:auto / off-screen subtrees
53184
+ // (e.g. claude.ai's scrolled-up messages). Keep innerText as the primary source so agents
53185
+ // whose content already works are unchanged, and fall back to textContent only when it's empty.
53186
+ const primary = node.text().trim();
53187
+ if (primary)
53188
+ return primary;
53189
+ return node[0].textContent.trim();
53167
53190
  }
53168
53191
  getMessageId(node) {
53169
- return node.attr(this.findSelector(MESSAGE_ID_ATTR));
53192
+ const attr = this.findSelector(MESSAGE_ID_ATTR);
53193
+ if (!attr) {
53194
+ return this.syntheticMessageId(node[0]);
53195
+ }
53196
+ return node.attr(attr);
53197
+ }
53198
+ // Agents with no DOM message id (e.g. claude.ai) get a synthetic id based on the role and
53199
+ // position in document order.
53200
+ syntheticMessageId(el) {
53201
+ if (!el)
53202
+ return undefined;
53203
+ const userSelector = this.findSelector(USER_MESSAGE);
53204
+ const isUser = userSelector && this.Sizzle.matchesSelector(el, userSelector);
53205
+ const role = isUser ? 'u' : 'a';
53206
+ const siblings = this.select(isUser ? USER_MESSAGE : ASSISTANT_MESSAGE);
53207
+ for (let i = 0; i < siblings.length; i++) {
53208
+ if (siblings[i] === el) {
53209
+ return `${role}-${i}`;
53210
+ }
53211
+ }
53212
+ return undefined; // el isn't among the rendered messages — no meaningful index
53170
53213
  }
53171
53214
  handleUserMessage(node) {
53172
- this.emit('prompt', Object.assign({ agentId: this.id, messageId: this.getMessageId(node) }, this.extractContent(node)));
53215
+ this.emit('prompt', {
53216
+ agentId: this.id,
53217
+ messageId: this.getMessageId(node),
53218
+ content: this.extractContent(node)
53219
+ });
53173
53220
  }
53174
53221
  handleAssistantMessage(node) {
53175
53222
  const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
53176
53223
  const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
53177
- this.emit('agent_response', Object.assign({ agentId: this.id, messageId: this.getMessageId(node), agentModelsUsed: modelUsed ? [modelUsed] : [] }, this.extractContent(node)));
53224
+ this.emit('agent_response', {
53225
+ agentId: this.id,
53226
+ messageId: this.getMessageId(node),
53227
+ agentModelsUsed: modelUsed ? [modelUsed] : [],
53228
+ content: this.extractContent(node)
53229
+ });
53178
53230
  }
53179
53231
  findLastRequestNode() {
53180
53232
  if (!this.getConversationId())
@@ -53211,7 +53263,16 @@ class DOMConversation {
53211
53263
  getCustomAgentId() {
53212
53264
  if (!this.customAgentIdRegex)
53213
53265
  return undefined;
53214
- const m = location.href.match(this.customAgentIdRegex);
53266
+ // The id may live in the page URL (e.g. gemini /gem/<id>) or,
53267
+ // when customAgentId is set, in the href of a DOM element
53268
+ let source = location.href;
53269
+ if (this.findSelector(CUSTOM_AGENT_ID)) {
53270
+ const node = this.select(CUSTOM_AGENT_ID);
53271
+ if (!node.length)
53272
+ return undefined;
53273
+ source = node.attr('href') || '';
53274
+ }
53275
+ const m = source.match(this.customAgentIdRegex);
53215
53276
  if (!m)
53216
53277
  return undefined;
53217
53278
  return m[1] !== undefined ? m[1] : m[0];