@pendo/agent 2.329.0 → 2.330.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 +2 -2
- package/dist/pendo.module.js +56 -160
- package/dist/pendo.module.min.js +10 -10
- package/dist/servers.json +7 -7
- package/package.json +1 -1
package/dist/dom.esm.js
CHANGED
|
@@ -6790,7 +6790,7 @@ var ConfigReader = (function () {
|
|
|
6790
6790
|
* cookies, localStorage, click tracking, and metadata. Only displays guides
|
|
6791
6791
|
* that have been configured explicitly to show to this visitor.
|
|
6792
6792
|
*
|
|
6793
|
-
* @access
|
|
6793
|
+
* @access public
|
|
6794
6794
|
* @category Config/Guides
|
|
6795
6795
|
* @name doNotTrackGuides
|
|
6796
6796
|
* @default false
|
|
@@ -7505,7 +7505,7 @@ function applyMatrix2dRect(matrix2d, rect) {
|
|
|
7505
7505
|
return transformedRect;
|
|
7506
7506
|
}
|
|
7507
7507
|
|
|
7508
|
-
var VERSION = '2.
|
|
7508
|
+
var VERSION = '2.330.0_';
|
|
7509
7509
|
|
|
7510
7510
|
var decodeURIComponent = _.isFunction(window.decodeURIComponent) ? window.decodeURIComponent : _.identity;
|
|
7511
7511
|
|
package/dist/pendo.module.js
CHANGED
|
@@ -3403,7 +3403,7 @@ var ConfigReader = (function () {
|
|
|
3403
3403
|
* cookies, localStorage, click tracking, and metadata. Only displays guides
|
|
3404
3404
|
* that have been configured explicitly to show to this visitor.
|
|
3405
3405
|
*
|
|
3406
|
-
* @access
|
|
3406
|
+
* @access public
|
|
3407
3407
|
* @category Config/Guides
|
|
3408
3408
|
* @name doNotTrackGuides
|
|
3409
3409
|
* @default false
|
|
@@ -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.330.0_';
|
|
4014
|
+
let PACKAGE_VERSION = '2.330.0';
|
|
4015
4015
|
let LOADER = 'xhr';
|
|
4016
4016
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
4017
4017
|
/**
|
|
@@ -9750,7 +9750,11 @@ function exportDataHost(pendo) {
|
|
|
9750
9750
|
pendo.HOST = HOST;
|
|
9751
9751
|
}
|
|
9752
9752
|
function getAssetHost() {
|
|
9753
|
-
|
|
9753
|
+
var assetHost = ConfigReader.get('assetHost');
|
|
9754
|
+
if (assetHost) {
|
|
9755
|
+
return assetHost.indexOf('://') === -1 ? 'https://' + assetHost : assetHost;
|
|
9756
|
+
}
|
|
9757
|
+
return getContentHost();
|
|
9754
9758
|
}
|
|
9755
9759
|
function getContentHost() {
|
|
9756
9760
|
var protocol = 'https://';
|
|
@@ -11752,13 +11756,13 @@ function isTrustedOrigin(host) {
|
|
|
11752
11756
|
// Domains that Pendo owns, will be swapped in by build patches
|
|
11753
11757
|
const patterns = [
|
|
11754
11758
|
/^https:\/\/(adopt\.)?((us1)\.)?(app|via|adopt|cdn|oem|novus-api|novus)(\.(au|eu|gov|hsbc|jpn))?\.pendo\.io$/,
|
|
11755
|
-
/^https:\/\/([0-9]{8}t[0-9]{4}-dot-)pendo-
|
|
11756
|
-
/^https:\/\/hotfix-(ops|app)-([0-9]+-dot-)pendo-
|
|
11757
|
-
/^https:\/\/pendo-
|
|
11759
|
+
/^https:\/\/([0-9]{8}t[0-9]{4}-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11760
|
+
/^https:\/\/hotfix-(ops|app)-([0-9]+-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11761
|
+
/^https:\/\/(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)-static\.storage\.googleapis\.com$/,
|
|
11758
11762
|
/^https:\/\/([a-zA-Z0-9-]+\.)*pendo-dev\.com$/,
|
|
11759
|
-
/^https:\/\/([a-zA-Z0-9-]+-dot-)?pendo-
|
|
11763
|
+
/^https:\/\/([a-zA-Z0-9-]+-dot-)?(pendo-apollo|pendo-armada|pendo-atlas|pendo-batman|pendo-calypso|pendo-dap|pendo-dev|pendo-dr-us-east1|pendo-eu-dev|pendo-freeze|pendo-helix|pendo-link|pendo-magic|pendo-mango|pendo-mcfly|pendo-ml|pendo-mobile-fbi|pendo-mobile-guides|pendo-mobile-hummus|pendo-mobile-plat|pendo-perfserf|pendo-voc|pendo-wildlings|pendo-ionchef|pendo-scrum-ops|pendo-security|pendo-test|pendo-uat|pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11760
11764
|
/^https:\/\/(via|adopt|local)\.pendo\.(local|io):\d{4}$/,
|
|
11761
|
-
/^https:\/\/pendo-
|
|
11765
|
+
/^https:\/\/(pendo-apollo|pendo-armada|pendo-atlas|pendo-batman|pendo-calypso|pendo-dap|pendo-dev|pendo-dr-us-east1|pendo-eu-dev|pendo-freeze|pendo-helix|pendo-link|pendo-magic|pendo-mango|pendo-mcfly|pendo-ml|pendo-mobile-fbi|pendo-mobile-guides|pendo-mobile-hummus|pendo-mobile-plat|pendo-perfserf|pendo-voc|pendo-wildlings|pendo-ionchef|pendo-scrum-ops|pendo-security|pendo-test|pendo-uat)-static\.storage\.googleapis\.com$/
|
|
11762
11766
|
]; // eslint-disable-line web-sdk-eslint-rules/no-gulp-env-references
|
|
11763
11767
|
var adoptHost = ConfigReader.get('adoptHost');
|
|
11764
11768
|
if (adoptHost) {
|
|
@@ -11846,7 +11850,9 @@ var trustedOriginForLoadResource = function (origin) {
|
|
|
11846
11850
|
return isTrustedOrigin(origin);
|
|
11847
11851
|
};
|
|
11848
11852
|
var parseUrlOrigin = function (url) {
|
|
11849
|
-
|
|
11853
|
+
// Resolve against the document URL so relative asset urls (used when self-hosting
|
|
11854
|
+
// with an empty asset host) parse to the current page origin instead of throwing.
|
|
11855
|
+
return new URL(url, window.location.href).origin;
|
|
11850
11856
|
};
|
|
11851
11857
|
var loadResource = function (options, callback, sendErrorToCallback = false) {
|
|
11852
11858
|
try {
|
|
@@ -30367,10 +30373,8 @@ function track(name, props, eventProperties) {
|
|
|
30367
30373
|
collectEventHelper({ type: 'track', name, props, eventProperties });
|
|
30368
30374
|
}
|
|
30369
30375
|
|
|
30370
|
-
const privacyFilterCache = new Map();
|
|
30371
30376
|
/**
|
|
30372
30377
|
* Method to manually track agentic events. Uses agent functions for IDs and context.
|
|
30373
|
-
* Automatically applies privacy filters if agentId is provided and agent configuration exists.
|
|
30374
30378
|
*
|
|
30375
30379
|
* @access public
|
|
30376
30380
|
* @category Events
|
|
@@ -30390,64 +30394,8 @@ const privacyFilterCache = new Map();
|
|
|
30390
30394
|
* }, { experiment: 'variant_a' })
|
|
30391
30395
|
*/
|
|
30392
30396
|
function trackAgent(type, props, eventProperties) {
|
|
30393
|
-
const filteredTypes = ['prompt', 'agent_response'];
|
|
30394
|
-
if (_.contains(filteredTypes, type)) {
|
|
30395
|
-
props = applyPrivacyFilters(props);
|
|
30396
|
-
}
|
|
30397
30397
|
collectEventHelper({ type, name: 'agentic', props, eventProperties });
|
|
30398
30398
|
}
|
|
30399
|
-
/**
|
|
30400
|
-
* Apply privacy filters to event properties based on agent configuration
|
|
30401
|
-
* Optimized for maximum performance with caching
|
|
30402
|
-
* @param {Object} props - Event properties to filter
|
|
30403
|
-
* @returns {Object} - Filtered properties
|
|
30404
|
-
*/
|
|
30405
|
-
function applyPrivacyFilters(props) {
|
|
30406
|
-
if (!(props === null || props === void 0 ? void 0 : props.agentId)) {
|
|
30407
|
-
return props;
|
|
30408
|
-
}
|
|
30409
|
-
try {
|
|
30410
|
-
const agents = ConfigReader.get('aiAgents', []);
|
|
30411
|
-
const agent = (agents === null || agents === void 0 ? void 0 : agents.find(agent => agent.id === props.agentId)) || null;
|
|
30412
|
-
const content = props.content;
|
|
30413
|
-
if (!content) {
|
|
30414
|
-
return props;
|
|
30415
|
-
}
|
|
30416
|
-
if (!(agent === null || agent === void 0 ? void 0 : agent.privacyFilters)) {
|
|
30417
|
-
return props;
|
|
30418
|
-
}
|
|
30419
|
-
const privacyFilter = getCachedRegex(agent.privacyFilters);
|
|
30420
|
-
if (!privacyFilter) {
|
|
30421
|
-
return props;
|
|
30422
|
-
}
|
|
30423
|
-
const filteredContent = content.replace(privacyFilter, '<redacted>');
|
|
30424
|
-
if (filteredContent === content) {
|
|
30425
|
-
return props;
|
|
30426
|
-
}
|
|
30427
|
-
return Object.assign(Object.assign({}, props), { content: filteredContent });
|
|
30428
|
-
}
|
|
30429
|
-
catch (error) {
|
|
30430
|
-
console.error('Error applying privacy filters', error);
|
|
30431
|
-
return props;
|
|
30432
|
-
}
|
|
30433
|
-
}
|
|
30434
|
-
/**
|
|
30435
|
-
* Get cached regex or compile and cache new one
|
|
30436
|
-
*/
|
|
30437
|
-
function getCachedRegex(filterPattern) {
|
|
30438
|
-
let regex = privacyFilterCache.get(filterPattern);
|
|
30439
|
-
if (!regex) {
|
|
30440
|
-
try {
|
|
30441
|
-
regex = new RegExp(filterPattern, 'gmi');
|
|
30442
|
-
privacyFilterCache.set(filterPattern, regex);
|
|
30443
|
-
}
|
|
30444
|
-
catch (e) {
|
|
30445
|
-
privacyFilterCache.set(filterPattern, null);
|
|
30446
|
-
return null;
|
|
30447
|
-
}
|
|
30448
|
-
}
|
|
30449
|
-
return regex;
|
|
30450
|
-
}
|
|
30451
30399
|
|
|
30452
30400
|
/**
|
|
30453
30401
|
* Checks visitor and account metadata in the current Pendo installation. Either logs to the console
|
|
@@ -37640,7 +37588,7 @@ const GuideCachePlugin = {
|
|
|
37640
37588
|
if (!capturedEvent || capturedEvent.type !== 'guideSeen') {
|
|
37641
37589
|
return;
|
|
37642
37590
|
}
|
|
37643
|
-
if (capturedEvent.props.reason
|
|
37591
|
+
if (!_.contains(['auto', 'continue'], capturedEvent.props.reason)) {
|
|
37644
37592
|
return;
|
|
37645
37593
|
}
|
|
37646
37594
|
const snap = getSnapshot(capturedEvent.props.guide_id, capturedEvent.props.guide_step_id);
|
|
@@ -40047,7 +39995,7 @@ function SegmentFlags() {
|
|
|
40047
39995
|
}
|
|
40048
39996
|
|
|
40049
39997
|
class DOMPrompt {
|
|
40050
|
-
constructor(pendo, PluginAPI, id,
|
|
39998
|
+
constructor(pendo, PluginAPI, id, inputCssSelectors, submitCssSelectors) {
|
|
40051
39999
|
this.listeners = [];
|
|
40052
40000
|
this.latestPromptValue = '';
|
|
40053
40001
|
this.isActive = true;
|
|
@@ -40058,7 +40006,6 @@ class DOMPrompt {
|
|
|
40058
40006
|
this.api = PluginAPI;
|
|
40059
40007
|
this.q = PluginAPI.q;
|
|
40060
40008
|
this.id = id;
|
|
40061
|
-
this.setFilters(privacyFilters);
|
|
40062
40009
|
if (!this._.isArray(inputCssSelectors)) {
|
|
40063
40010
|
this.api.log.error('inputCssSelectors must be an array, received:', typeof inputCssSelectors);
|
|
40064
40011
|
inputCssSelectors = [];
|
|
@@ -40161,26 +40108,6 @@ class DOMPrompt {
|
|
|
40161
40108
|
const validSubmitEls = this._.filter(this.submitEls, el => el);
|
|
40162
40109
|
this.promptContainer.addObservers(...validInputEls, ...validSubmitEls);
|
|
40163
40110
|
}
|
|
40164
|
-
setFilters(candidateFilter) {
|
|
40165
|
-
if (!candidateFilter) {
|
|
40166
|
-
this.privacyFilters = null;
|
|
40167
|
-
return null;
|
|
40168
|
-
}
|
|
40169
|
-
try {
|
|
40170
|
-
this.privacyFilters = new RegExp(candidateFilter, 'gmi');
|
|
40171
|
-
}
|
|
40172
|
-
catch (e) {
|
|
40173
|
-
this.privacyFilters = null;
|
|
40174
|
-
this.api.log.error(e);
|
|
40175
|
-
}
|
|
40176
|
-
return this.privacyFilters;
|
|
40177
|
-
}
|
|
40178
|
-
applyPrivacyFilter(candidateValue, filters = null) {
|
|
40179
|
-
const filtersToUse = filters || this.privacyFilters;
|
|
40180
|
-
if (!filtersToUse || !this._.isRegExp(filtersToUse))
|
|
40181
|
-
return candidateValue;
|
|
40182
|
-
return candidateValue.replace(filtersToUse, 'redacted');
|
|
40183
|
-
}
|
|
40184
40111
|
submit(origVal) {
|
|
40185
40112
|
if (!origVal || !this.isActive) {
|
|
40186
40113
|
return;
|
|
@@ -40191,11 +40118,9 @@ class DOMPrompt {
|
|
|
40191
40118
|
return;
|
|
40192
40119
|
}
|
|
40193
40120
|
this.lastSubmitTime = now;
|
|
40194
|
-
const val = this.applyPrivacyFilter(origVal);
|
|
40195
40121
|
const payload = {
|
|
40196
40122
|
agentId: this.id,
|
|
40197
|
-
prompt:
|
|
40198
|
-
privacyFilterApplied: val !== origVal
|
|
40123
|
+
prompt: origVal
|
|
40199
40124
|
};
|
|
40200
40125
|
this._.each(this.listeners, (cb) => cb(payload));
|
|
40201
40126
|
}
|
|
@@ -40369,11 +40294,6 @@ class PromptPlugin {
|
|
|
40369
40294
|
}
|
|
40370
40295
|
return this.agentsCache.get(agentId);
|
|
40371
40296
|
}
|
|
40372
|
-
applyPrivacyFilter(candidateValue, filters = null) {
|
|
40373
|
-
if (!filters || !this._.isRegExp(filters))
|
|
40374
|
-
return candidateValue;
|
|
40375
|
-
return candidateValue.replace(filters, 'redacted');
|
|
40376
|
-
}
|
|
40377
40297
|
// conversation agents, owned by the ConversationAnalytics plugin.
|
|
40378
40298
|
isConversationAgent(agent) {
|
|
40379
40299
|
return agent.preset && agent.preset != 'chatgpt';
|
|
@@ -40424,13 +40344,11 @@ class PromptPlugin {
|
|
|
40424
40344
|
return;
|
|
40425
40345
|
}
|
|
40426
40346
|
const originalBody = body || '';
|
|
40427
|
-
const filteredPrompt = this.applyPrivacyFilter(originalBody, aiAgent.privacyFilters);
|
|
40428
40347
|
this.api.analytics.collectEvent('prompt', {
|
|
40429
|
-
prompt:
|
|
40348
|
+
prompt: originalBody,
|
|
40430
40349
|
agentId: aiAgent.id,
|
|
40431
40350
|
promptType: method,
|
|
40432
|
-
url
|
|
40433
|
-
privacyFilterApplied: filteredPrompt !== originalBody
|
|
40351
|
+
url
|
|
40434
40352
|
}, undefined, 'agentic');
|
|
40435
40353
|
});
|
|
40436
40354
|
}
|
|
@@ -40443,7 +40361,7 @@ class PromptPlugin {
|
|
|
40443
40361
|
}
|
|
40444
40362
|
}
|
|
40445
40363
|
observePrompt(config) {
|
|
40446
|
-
const { id, cssSelectors
|
|
40364
|
+
const { id, cssSelectors } = config;
|
|
40447
40365
|
// Check if agent already exists
|
|
40448
40366
|
const existingPrompt = this._.find(this.prompts, prompt => prompt.id === id);
|
|
40449
40367
|
if (existingPrompt) {
|
|
@@ -40452,7 +40370,7 @@ class PromptPlugin {
|
|
|
40452
40370
|
let inputCssSelectors, submitCssSelectors;
|
|
40453
40371
|
inputCssSelectors = this.parseCssSelector('input', cssSelectors);
|
|
40454
40372
|
submitCssSelectors = this.parseCssSelector('submit', cssSelectors);
|
|
40455
|
-
const prompt = new DOMPrompt(this.pendo, this.api, id,
|
|
40373
|
+
const prompt = new DOMPrompt(this.pendo, this.api, id, inputCssSelectors, submitCssSelectors);
|
|
40456
40374
|
prompt.onSubmit((promptPayload) => {
|
|
40457
40375
|
this.sendPromptEvent(promptPayload);
|
|
40458
40376
|
});
|
|
@@ -53055,6 +52973,7 @@ const PredictGuides = () => {
|
|
|
53055
52973
|
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
53056
52974
|
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
53057
52975
|
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
52976
|
+
const MESSAGE_ID_PATTERN = 'messageIdPattern';
|
|
53058
52977
|
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
53059
52978
|
const REACTION_ACTIVE = 'reactionActive';
|
|
53060
52979
|
const STREAMING_ACTIVE = 'streamingActive';
|
|
@@ -53062,7 +52981,6 @@ const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
|
53062
52981
|
const THUMB_DOWN = 'thumbDown';
|
|
53063
52982
|
const THUMB_UP = 'thumbUp';
|
|
53064
52983
|
const TURN_CONTAINER = 'turnContainer';
|
|
53065
|
-
const TURN_ATTR = 'turnAttr';
|
|
53066
52984
|
const USER_MESSAGE = 'userMessage';
|
|
53067
52985
|
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
53068
52986
|
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
@@ -53072,9 +52990,9 @@ const REQUIRED_SELECTORS = [
|
|
|
53072
52990
|
MESSAGE_ID_ATTR,
|
|
53073
52991
|
STREAMING_ACTIVE,
|
|
53074
52992
|
TURN_CONTAINER,
|
|
53075
|
-
TURN_ATTR,
|
|
53076
52993
|
USER_MESSAGE
|
|
53077
52994
|
];
|
|
52995
|
+
const SUPPORTED_PRESETS = ['chatgpt-full', 'gemini-full'];
|
|
53078
52996
|
const STREAMING_END_SETTLE_MS = 500;
|
|
53079
52997
|
const SUBMISSION_START_RETRY_MS = 1000;
|
|
53080
52998
|
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
@@ -53103,9 +53021,9 @@ class DOMConversation {
|
|
|
53103
53021
|
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
53104
53022
|
}
|
|
53105
53023
|
static supportedPreset(preset) {
|
|
53106
|
-
return preset
|
|
53024
|
+
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
53107
53025
|
}
|
|
53108
|
-
constructor(pendo, PluginAPI, id,
|
|
53026
|
+
constructor(pendo, PluginAPI, id, cssSelectors) {
|
|
53109
53027
|
this.selectors = {};
|
|
53110
53028
|
this.listeners = [];
|
|
53111
53029
|
this.isActive = true;
|
|
@@ -53116,13 +53034,13 @@ class DOMConversation {
|
|
|
53116
53034
|
this.requestNode = null;
|
|
53117
53035
|
this.conversationIdRegex = null;
|
|
53118
53036
|
this.customAgentIdRegex = null;
|
|
53037
|
+
this.messageIdRegex = null;
|
|
53119
53038
|
this.lastReturnedMessageId = null;
|
|
53120
53039
|
this.dom = pendo.dom;
|
|
53121
53040
|
this._ = pendo._;
|
|
53122
53041
|
this.api = PluginAPI;
|
|
53123
53042
|
this.Sizzle = pendo.Sizzle;
|
|
53124
53043
|
this.id = id;
|
|
53125
|
-
this.setFilters(privacyFilters);
|
|
53126
53044
|
if (!this._.isArray(cssSelectors)) {
|
|
53127
53045
|
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
53128
53046
|
cssSelectors = [];
|
|
@@ -53142,6 +53060,15 @@ class DOMConversation {
|
|
|
53142
53060
|
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
53143
53061
|
}
|
|
53144
53062
|
}
|
|
53063
|
+
const messageIdPattern = this.selectors[MESSAGE_ID_PATTERN];
|
|
53064
|
+
if (messageIdPattern) { // optional: gates the request node until its id is fully rendered
|
|
53065
|
+
try {
|
|
53066
|
+
this.messageIdRegex = new RegExp(messageIdPattern);
|
|
53067
|
+
}
|
|
53068
|
+
catch (error) {
|
|
53069
|
+
this.api.log.error(`bad messageIdPattern ${messageIdPattern}`, { error });
|
|
53070
|
+
}
|
|
53071
|
+
}
|
|
53145
53072
|
this.root = document.body;
|
|
53146
53073
|
this.setupReactionListener();
|
|
53147
53074
|
this.setupStreamingObserver();
|
|
@@ -53171,8 +53098,7 @@ class DOMConversation {
|
|
|
53171
53098
|
this.emit('user_reaction', {
|
|
53172
53099
|
agentId: this.id,
|
|
53173
53100
|
messageId: this.getMessageId(assistantNode),
|
|
53174
|
-
content
|
|
53175
|
-
privacyFilterApplied: false
|
|
53101
|
+
content
|
|
53176
53102
|
});
|
|
53177
53103
|
}
|
|
53178
53104
|
// observe the streaming indicator
|
|
@@ -53241,28 +53167,22 @@ class DOMConversation {
|
|
|
53241
53167
|
return;
|
|
53242
53168
|
this.handleUserMessage(requestNode);
|
|
53243
53169
|
}
|
|
53244
|
-
const
|
|
53245
|
-
if (
|
|
53170
|
+
const requestEl = requestNode[0];
|
|
53171
|
+
if (!requestEl)
|
|
53246
53172
|
return;
|
|
53173
|
+
// the request is the latest user message, so any assistant message that
|
|
53174
|
+
// follows it in the DOM is a response to it. document order is already
|
|
53175
|
+
// chronological, so we emit as we go
|
|
53247
53176
|
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
53248
|
-
|
|
53249
|
-
|
|
53250
|
-
|
|
53251
|
-
|
|
53252
|
-
|
|
53253
|
-
if (n <= requestTurn)
|
|
53254
|
-
break;
|
|
53255
|
-
toEmit.push(assistantNodes[i]);
|
|
53256
|
-
}
|
|
53257
|
-
// emit in chronological order (reverse of collection order)
|
|
53258
|
-
for (let i = toEmit.length - 1; i >= 0; i--) {
|
|
53259
|
-
this.handleAssistantMessage(this.dom(toEmit[i]));
|
|
53177
|
+
for (let i = 0; i < assistantNodes.length; i++) {
|
|
53178
|
+
const el = assistantNodes[i];
|
|
53179
|
+
if (requestEl.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
53180
|
+
this.handleAssistantMessage(this.dom(el));
|
|
53181
|
+
}
|
|
53260
53182
|
}
|
|
53261
53183
|
}
|
|
53262
53184
|
extractContent(node) {
|
|
53263
|
-
|
|
53264
|
-
const content = this.applyPrivacyFilter(rawContent);
|
|
53265
|
-
return { content, privacyFilterApplied: content !== rawContent };
|
|
53185
|
+
return { content: node.text().trim() };
|
|
53266
53186
|
}
|
|
53267
53187
|
getMessageId(node) {
|
|
53268
53188
|
return node.attr(this.findSelector(MESSAGE_ID_ATTR));
|
|
@@ -53285,20 +53205,16 @@ class DOMConversation {
|
|
|
53285
53205
|
const messageId = this.getMessageId($node);
|
|
53286
53206
|
if (!messageId)
|
|
53287
53207
|
return null;
|
|
53208
|
+
// the node may still be rendering (e.g. a framework interpolating an
|
|
53209
|
+
// unresolved id); treat it as not-ready so the retry waits for the
|
|
53210
|
+
// finalized node rather than caching a placeholder that gets replaced
|
|
53211
|
+
if (this.messageIdRegex && !this.messageIdRegex.test(messageId))
|
|
53212
|
+
return null;
|
|
53288
53213
|
if (messageId === this.lastReturnedMessageId)
|
|
53289
53214
|
return null;
|
|
53290
53215
|
this.lastReturnedMessageId = messageId;
|
|
53291
53216
|
return $node;
|
|
53292
53217
|
}
|
|
53293
|
-
findTurnNumber(node) {
|
|
53294
|
-
const turnSelector = this.findSelector(TURN_CONTAINER);
|
|
53295
|
-
const turnAttr = this.findSelector(TURN_ATTR);
|
|
53296
|
-
const turn = node.closest(turnSelector).attr(turnAttr);
|
|
53297
|
-
if (!turn)
|
|
53298
|
-
return null;
|
|
53299
|
-
const seqMatch = String(turn).match(/\d+/);
|
|
53300
|
-
return seqMatch ? parseInt(seqMatch[0], 10) : null;
|
|
53301
|
-
}
|
|
53302
53218
|
findSelector(type) {
|
|
53303
53219
|
return this.selectors[type];
|
|
53304
53220
|
}
|
|
@@ -53337,26 +53253,6 @@ class DOMConversation {
|
|
|
53337
53253
|
eventPayload.customAgentName = customAgentName;
|
|
53338
53254
|
}
|
|
53339
53255
|
}
|
|
53340
|
-
setFilters(candidateFilter) {
|
|
53341
|
-
if (!candidateFilter) {
|
|
53342
|
-
this.privacyFilters = null;
|
|
53343
|
-
return null;
|
|
53344
|
-
}
|
|
53345
|
-
try {
|
|
53346
|
-
this.privacyFilters = new RegExp(candidateFilter, 'gmi');
|
|
53347
|
-
}
|
|
53348
|
-
catch (e) {
|
|
53349
|
-
this.privacyFilters = null;
|
|
53350
|
-
this.api.log.error(e);
|
|
53351
|
-
}
|
|
53352
|
-
return this.privacyFilters;
|
|
53353
|
-
}
|
|
53354
|
-
applyPrivacyFilter(candidateValue, filters = null) {
|
|
53355
|
-
const filtersToUse = filters || this.privacyFilters;
|
|
53356
|
-
if (!filtersToUse || !this._.isRegExp(filtersToUse))
|
|
53357
|
-
return candidateValue;
|
|
53358
|
-
return candidateValue.replace(filtersToUse, 'redacted');
|
|
53359
|
-
}
|
|
53360
53256
|
onSubmit(callback) {
|
|
53361
53257
|
this.listeners.push(callback);
|
|
53362
53258
|
}
|
|
@@ -53517,7 +53413,7 @@ function ConversationAnalytics() {
|
|
|
53517
53413
|
});
|
|
53518
53414
|
}
|
|
53519
53415
|
function observeConversation(config) {
|
|
53520
|
-
const { id, cssSelectors
|
|
53416
|
+
const { id, cssSelectors } = config;
|
|
53521
53417
|
// Check if this agent is already being tracked
|
|
53522
53418
|
const existing = _.find(conversations, conversation => conversation.id === id);
|
|
53523
53419
|
if (existing) {
|
|
@@ -53528,7 +53424,7 @@ function ConversationAnalytics() {
|
|
|
53528
53424
|
log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
53529
53425
|
return;
|
|
53530
53426
|
}
|
|
53531
|
-
const conversation = new DOMConversation(pendo, api, id,
|
|
53427
|
+
const conversation = new DOMConversation(pendo, api, id, cssSelectors);
|
|
53532
53428
|
conversation.onSubmit(sendConversationEvent);
|
|
53533
53429
|
conversations.push(conversation);
|
|
53534
53430
|
}
|