@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 +7 -3
- package/dist/pendo.module.js +80 -19
- package/dist/pendo.module.min.js +7 -7
- package/dist/servers.json +7 -7
- package/package.json +1 -1
- package/setup.js +6 -2
- package/setup.test.js +65 -0
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.
|
|
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
|
|
7633
|
-
|
|
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);
|
package/dist/pendo.module.js
CHANGED
|
@@ -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.
|
|
4014
|
-
let PACKAGE_VERSION = '2.
|
|
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
|
|
4595
|
+
var expiry = '=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
|
4596
4596
|
if (cookieDomain) {
|
|
4597
|
-
cookie
|
|
4597
|
+
document.cookie = name + expiry + ';domain=' + cookieDomain;
|
|
4598
4598
|
}
|
|
4599
|
-
|
|
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
|
-
|
|
28458
|
-
|
|
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
|
|
28461
|
-
step = _.find(guide.steps, (step) => step.id ===
|
|
28470
|
+
const guideByStep = _.find(getLocalActiveGuides(), function (guide) {
|
|
28471
|
+
step = _.find(guide.steps, (step) => step.id === containerId);
|
|
28462
28472
|
return !!step;
|
|
28463
28473
|
});
|
|
28464
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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',
|
|
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',
|
|
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
|
-
|
|
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];
|