@oxvo/ai-live-assist 7.4.36 → 7.4.49
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/cjs/AiLiveAssist.d.ts +10 -1
- package/cjs/AiLiveAssist.js +797 -194
- package/cjs/context.d.ts +2 -0
- package/cjs/context.js +213 -22
- package/cjs/index.js +2 -2
- package/cjs/media.js +3 -2
- package/cjs/preview.d.ts +1 -1
- package/cjs/preview.js +2 -1
- package/cjs/types.d.ts +1 -0
- package/cjs/ui.d.ts +9 -0
- package/cjs/ui.js +478 -141
- package/cjs/version.d.ts +1 -1
- package/cjs/version.js +1 -1
- package/lib/AiLiveAssist.d.ts +10 -1
- package/lib/AiLiveAssist.js +797 -194
- package/lib/context.d.ts +2 -0
- package/lib/context.js +213 -22
- package/lib/index.js +2 -2
- package/lib/media.js +3 -2
- package/lib/preview.d.ts +1 -1
- package/lib/preview.js +2 -1
- package/lib/types.d.ts +1 -0
- package/lib/ui.d.ts +9 -0
- package/lib/ui.js +478 -141
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +2 -2
package/cjs/context.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare class PageContextCollector {
|
|
|
24
24
|
private captureTimer;
|
|
25
25
|
private mutationCaptureTimer;
|
|
26
26
|
private targetIds;
|
|
27
|
+
private navigationTargetBindings;
|
|
27
28
|
private textIds;
|
|
28
29
|
private optionIds;
|
|
29
30
|
private targets;
|
|
@@ -69,6 +70,7 @@ export declare class PageContextCollector {
|
|
|
69
70
|
private beginNavigationSettlement;
|
|
70
71
|
private observeCausalNavigationAfterMutation;
|
|
71
72
|
private reportCausalNavigationObservation;
|
|
73
|
+
private resetBoundTargetIds;
|
|
72
74
|
private installNavigationHooks;
|
|
73
75
|
private restoreNavigationHooks;
|
|
74
76
|
private reducedMotion;
|
package/cjs/context.js
CHANGED
|
@@ -10,6 +10,9 @@ const MAX_SELECTED_TEXT = 2000;
|
|
|
10
10
|
const SELECTION_RETENTION_MS = 120000;
|
|
11
11
|
const CAPTURE_SETTLE_MS = 250;
|
|
12
12
|
const MUTATION_CAPTURE_DEBOUNCE_MS = 350;
|
|
13
|
+
const FRAMER_TOGGLE_ROOT_SELECTOR = '[data-framer-name="Toggle"]';
|
|
14
|
+
const FRAMER_TOGGLE_CONTROL_SELECTOR = 'div[name="Toggle Switch"][data-highlight="true"][tabindex]';
|
|
15
|
+
const MAX_FRAMER_TOGGLE_LABEL = 120;
|
|
13
16
|
const PRIVATE_SELECTOR = [
|
|
14
17
|
'[data-oxvo-ai-live-assist-root]',
|
|
15
18
|
'[data-oxvo-private]',
|
|
@@ -40,6 +43,8 @@ const EXPLICIT_SENSITIVITIES = new Set([
|
|
|
40
43
|
'api_secret',
|
|
41
44
|
]);
|
|
42
45
|
const id = (prefix) => `${prefix}_${crypto.randomUUID()}`;
|
|
46
|
+
// The runtime may rebind only IDs whose navigation identity this collector rotates.
|
|
47
|
+
const BOUND_NAVIGATION_TARGET_PREFIX = 'target_bound';
|
|
43
48
|
const normalize = (value, maximum) => value
|
|
44
49
|
.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, '')
|
|
45
50
|
.replace(/\s+/g, ' ')
|
|
@@ -58,6 +63,31 @@ const canonicalJson = (value) => {
|
|
|
58
63
|
};
|
|
59
64
|
return JSON.stringify(sort(value));
|
|
60
65
|
};
|
|
66
|
+
const navigationTargetGeometry = (element) => {
|
|
67
|
+
const rect = element.getBoundingClientRect();
|
|
68
|
+
return {
|
|
69
|
+
x: Math.round(rect.left + window.scrollX),
|
|
70
|
+
y: Math.round(rect.top + window.scrollY),
|
|
71
|
+
width: Math.round(rect.width),
|
|
72
|
+
height: Math.round(rect.height),
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
const navigationTargetBinding = (element, target) => canonicalJson({
|
|
76
|
+
role: target.role,
|
|
77
|
+
name: target.name,
|
|
78
|
+
inputType: target.inputType ?? null,
|
|
79
|
+
autocomplete: target.autocomplete ?? null,
|
|
80
|
+
semanticRegion: target.semanticRegion ?? null,
|
|
81
|
+
destinationPath: target.destinationPath ?? null,
|
|
82
|
+
sensitivity: target.sensitivity,
|
|
83
|
+
protectedRegion: target.protectedRegion ?? null,
|
|
84
|
+
frameOrigin: target.frameOrigin ?? null,
|
|
85
|
+
consequence: target.consequence ?? null,
|
|
86
|
+
regionAssessment: target.regionAssessment ?? null,
|
|
87
|
+
state: target.state,
|
|
88
|
+
options: target.options ?? null,
|
|
89
|
+
geometry: navigationTargetGeometry(element),
|
|
90
|
+
});
|
|
61
91
|
const actionTargetFingerprint = async (target, subtle = globalThis.crypto?.subtle) => {
|
|
62
92
|
if (!subtle)
|
|
63
93
|
return null;
|
|
@@ -181,6 +211,8 @@ const sensitivityFor = (element, name) => {
|
|
|
181
211
|
return 'none';
|
|
182
212
|
};
|
|
183
213
|
const roleFor = (element) => {
|
|
214
|
+
if (framerToggleDescriptor(element))
|
|
215
|
+
return 'checkbox';
|
|
184
216
|
const explicit = normalize(element.getAttribute('role') ?? '', 64);
|
|
185
217
|
if (explicit)
|
|
186
218
|
return explicit;
|
|
@@ -209,6 +241,9 @@ const roleFor = (element) => {
|
|
|
209
241
|
return tag.slice(0, 64);
|
|
210
242
|
};
|
|
211
243
|
const nameFor = (element) => {
|
|
244
|
+
const framerToggle = framerToggleDescriptor(element);
|
|
245
|
+
if (framerToggle)
|
|
246
|
+
return framerToggle.name;
|
|
212
247
|
const input = element instanceof HTMLInputElement ? element : null;
|
|
213
248
|
const formControl = element instanceof HTMLInputElement ||
|
|
214
249
|
element instanceof HTMLSelectElement ||
|
|
@@ -320,6 +355,131 @@ const safeAccessibleNameText = (element, maximum) => {
|
|
|
320
355
|
const text = safeDescendantText(element, maximum, true);
|
|
321
356
|
return text && sensitivityFor(element, text) === 'none' ? text : '';
|
|
322
357
|
};
|
|
358
|
+
const safeFramerToggleLabel = (element) => {
|
|
359
|
+
if (!isVisible(element) ||
|
|
360
|
+
element.closest(PRIVATE_SELECTOR) ||
|
|
361
|
+
element.querySelector(PRIVATE_SELECTOR) ||
|
|
362
|
+
element.matches('a[href],button,input,select,textarea,summary,form,[contenteditable="true"],[role],[tabindex]') ||
|
|
363
|
+
element.querySelector('a[href],button,input,select,textarea,summary,form,[contenteditable="true"],[role],[tabindex]')) {
|
|
364
|
+
return '';
|
|
365
|
+
}
|
|
366
|
+
const label = safeDescendantText(element, MAX_FRAMER_TOGGLE_LABEL + 1);
|
|
367
|
+
if (!label ||
|
|
368
|
+
label.length > MAX_FRAMER_TOGGLE_LABEL ||
|
|
369
|
+
sensitivityFor(element, label) !== 'none') {
|
|
370
|
+
return '';
|
|
371
|
+
}
|
|
372
|
+
return label;
|
|
373
|
+
};
|
|
374
|
+
function framerToggleDescriptor(element) {
|
|
375
|
+
if (element.tagName !== 'DIV' ||
|
|
376
|
+
element.getAttribute('name') !== 'Toggle Switch' ||
|
|
377
|
+
element.getAttribute('data-highlight') !== 'true' ||
|
|
378
|
+
!element.hasAttribute('tabindex') ||
|
|
379
|
+
!(element instanceof HTMLElement) ||
|
|
380
|
+
element.tabIndex < 0) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
const state = element.getAttribute('data-framer-name');
|
|
384
|
+
if (state !== 'Off' && state !== 'On')
|
|
385
|
+
return null;
|
|
386
|
+
const root = element.closest(FRAMER_TOGGLE_ROOT_SELECTOR);
|
|
387
|
+
if (!root || root === element || root.closest(PRIVATE_SELECTOR))
|
|
388
|
+
return null;
|
|
389
|
+
const controls = Array.from(root.querySelectorAll(FRAMER_TOGGLE_CONTROL_SELECTOR));
|
|
390
|
+
if (controls.length !== 1 || controls[0] !== element)
|
|
391
|
+
return null;
|
|
392
|
+
let controlBranch = element;
|
|
393
|
+
while (controlBranch.parentElement && controlBranch.parentElement !== root) {
|
|
394
|
+
controlBranch = controlBranch.parentElement;
|
|
395
|
+
}
|
|
396
|
+
if (controlBranch.parentElement !== root)
|
|
397
|
+
return null;
|
|
398
|
+
const labels = [controlBranch.previousElementSibling, controlBranch.nextElementSibling]
|
|
399
|
+
.flatMap((candidate) => (candidate ? [safeFramerToggleLabel(candidate)] : []))
|
|
400
|
+
.filter(Boolean);
|
|
401
|
+
if (labels.length !== 1)
|
|
402
|
+
return null;
|
|
403
|
+
return { checked: state === 'On', name: labels[0] };
|
|
404
|
+
}
|
|
405
|
+
const checkedStateFor = (element) => {
|
|
406
|
+
if (element instanceof HTMLInputElement && ['checkbox', 'radio'].includes(element.type)) {
|
|
407
|
+
return element.checked;
|
|
408
|
+
}
|
|
409
|
+
return framerToggleDescriptor(element)?.checked;
|
|
410
|
+
};
|
|
411
|
+
const dispatchFramerTogglePrimaryPointer = (element) => {
|
|
412
|
+
if (!framerToggleDescriptor(element) || typeof window.PointerEvent !== 'function') {
|
|
413
|
+
throw new Error('Framer toggle pointer interaction is unavailable.');
|
|
414
|
+
}
|
|
415
|
+
const rect = element.getBoundingClientRect();
|
|
416
|
+
const clientX = rect.left + rect.width / 2;
|
|
417
|
+
const clientY = rect.top + rect.height / 2;
|
|
418
|
+
const shared = {
|
|
419
|
+
view: window,
|
|
420
|
+
bubbles: true,
|
|
421
|
+
cancelable: true,
|
|
422
|
+
composed: true,
|
|
423
|
+
clientX,
|
|
424
|
+
clientY,
|
|
425
|
+
};
|
|
426
|
+
const pointer = (type, init) => {
|
|
427
|
+
element.dispatchEvent(new window.PointerEvent(type, {
|
|
428
|
+
...shared,
|
|
429
|
+
pointerId: 1,
|
|
430
|
+
pointerType: 'mouse',
|
|
431
|
+
width: 1,
|
|
432
|
+
height: 1,
|
|
433
|
+
isPrimary: true,
|
|
434
|
+
...init,
|
|
435
|
+
}));
|
|
436
|
+
};
|
|
437
|
+
const mouse = (type, init) => {
|
|
438
|
+
element.dispatchEvent(new MouseEvent(type, { ...shared, ...init }));
|
|
439
|
+
};
|
|
440
|
+
pointer('pointerover', { button: -1, buttons: 0 });
|
|
441
|
+
element.dispatchEvent(new window.PointerEvent('pointerenter', {
|
|
442
|
+
...shared,
|
|
443
|
+
bubbles: false,
|
|
444
|
+
cancelable: false,
|
|
445
|
+
pointerId: 1,
|
|
446
|
+
pointerType: 'mouse',
|
|
447
|
+
width: 1,
|
|
448
|
+
height: 1,
|
|
449
|
+
isPrimary: true,
|
|
450
|
+
button: -1,
|
|
451
|
+
buttons: 0,
|
|
452
|
+
}));
|
|
453
|
+
mouse('mouseover', { button: 0, buttons: 0, detail: 0 });
|
|
454
|
+
element.dispatchEvent(new MouseEvent('mouseenter', {
|
|
455
|
+
...shared,
|
|
456
|
+
bubbles: false,
|
|
457
|
+
cancelable: false,
|
|
458
|
+
button: 0,
|
|
459
|
+
buttons: 0,
|
|
460
|
+
detail: 0,
|
|
461
|
+
}));
|
|
462
|
+
pointer('pointermove', { button: -1, buttons: 0 });
|
|
463
|
+
mouse('mousemove', { button: 0, buttons: 0, detail: 0 });
|
|
464
|
+
pointer('pointerdown', { button: 0, buttons: 1 });
|
|
465
|
+
mouse('mousedown', { button: 0, buttons: 1, detail: 1 });
|
|
466
|
+
element.focus({ preventScroll: true });
|
|
467
|
+
pointer('pointerup', { button: 0, buttons: 0 });
|
|
468
|
+
mouse('mouseup', { button: 0, buttons: 0, detail: 1 });
|
|
469
|
+
// Chromium's trusted mouse sequence keeps pointerId 1 on click but reports
|
|
470
|
+
// isPrimary false; these fields are trace-bound rather than normalized.
|
|
471
|
+
element.dispatchEvent(new window.PointerEvent('click', {
|
|
472
|
+
...shared,
|
|
473
|
+
pointerId: 1,
|
|
474
|
+
pointerType: 'mouse',
|
|
475
|
+
width: 1,
|
|
476
|
+
height: 1,
|
|
477
|
+
isPrimary: false,
|
|
478
|
+
button: 0,
|
|
479
|
+
buttons: 0,
|
|
480
|
+
detail: 1,
|
|
481
|
+
}));
|
|
482
|
+
};
|
|
323
483
|
const semanticSourceSensitivity = (source) => {
|
|
324
484
|
if (source.closest(PRIVATE_SELECTOR) || source.querySelector(PRIVATE_SELECTOR)) {
|
|
325
485
|
return 'private';
|
|
@@ -482,6 +642,7 @@ class PageContextCollector {
|
|
|
482
642
|
this.captureTimer = null;
|
|
483
643
|
this.mutationCaptureTimer = null;
|
|
484
644
|
this.targetIds = new WeakMap();
|
|
645
|
+
this.navigationTargetBindings = new WeakMap();
|
|
485
646
|
this.textIds = new WeakMap();
|
|
486
647
|
this.optionIds = new WeakMap();
|
|
487
648
|
this.targets = new Map();
|
|
@@ -565,6 +726,7 @@ class PageContextCollector {
|
|
|
565
726
|
this.pageId = id('page');
|
|
566
727
|
this.revision += 1;
|
|
567
728
|
this.targets.clear();
|
|
729
|
+
this.resetBoundTargetIds();
|
|
568
730
|
this.recentSelection = null;
|
|
569
731
|
if (this.executingActionId) {
|
|
570
732
|
this.pendingNavigation = {
|
|
@@ -640,6 +802,7 @@ class PageContextCollector {
|
|
|
640
802
|
'aria-pressed',
|
|
641
803
|
'aria-live',
|
|
642
804
|
'class',
|
|
805
|
+
'data-framer-name',
|
|
643
806
|
'disabled',
|
|
644
807
|
'href',
|
|
645
808
|
'hidden',
|
|
@@ -735,8 +898,6 @@ class PageContextCollector {
|
|
|
735
898
|
const name = nameFor(element);
|
|
736
899
|
if (!name && !['form', 'textbox'].includes(role))
|
|
737
900
|
continue;
|
|
738
|
-
const targetId = this.targetIds.get(element) ?? id('target');
|
|
739
|
-
this.targetIds.set(element, targetId);
|
|
740
901
|
const optionMap = new Map();
|
|
741
902
|
let options;
|
|
742
903
|
if (element instanceof HTMLSelectElement) {
|
|
@@ -781,9 +942,8 @@ class PageContextCollector {
|
|
|
781
942
|
const destinationPath = safeDestinationPath(element);
|
|
782
943
|
const expanded = literalBooleanAttribute(element, 'aria-expanded');
|
|
783
944
|
const pressed = literalBooleanAttribute(element, 'aria-pressed');
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
revision,
|
|
945
|
+
const checked = checkedStateFor(element);
|
|
946
|
+
const targetIdentity = {
|
|
787
947
|
role,
|
|
788
948
|
name,
|
|
789
949
|
...(element instanceof HTMLInputElement || element instanceof HTMLButtonElement
|
|
@@ -807,14 +967,38 @@ class PageContextCollector {
|
|
|
807
967
|
visible,
|
|
808
968
|
enabled: enabled(element),
|
|
809
969
|
covered: visible ? isCovered(element, this.trustedGuideRoot) : false,
|
|
810
|
-
...(
|
|
811
|
-
? { checked: element.checked }
|
|
812
|
-
: {}),
|
|
970
|
+
...(checked !== undefined ? { checked } : {}),
|
|
813
971
|
...(this.statefulButtonActionProof && expanded !== undefined ? { expanded } : {}),
|
|
814
972
|
...(this.statefulButtonActionProof && pressed !== undefined ? { pressed } : {}),
|
|
815
973
|
},
|
|
816
974
|
...(options ? { options } : {}),
|
|
817
975
|
};
|
|
976
|
+
const priorTargetId = this.targetIds.get(element);
|
|
977
|
+
const boundNavigation = targetIdentity.consequence === 'navigation' &&
|
|
978
|
+
typeof targetIdentity.destinationPath === 'string';
|
|
979
|
+
const binding = boundNavigation
|
|
980
|
+
? navigationTargetBinding(element, targetIdentity)
|
|
981
|
+
: null;
|
|
982
|
+
const priorBinding = this.navigationTargetBindings.get(element);
|
|
983
|
+
const targetId = binding
|
|
984
|
+
? priorTargetId?.startsWith(`${BOUND_NAVIGATION_TARGET_PREFIX}_`) &&
|
|
985
|
+
priorBinding === binding
|
|
986
|
+
? priorTargetId
|
|
987
|
+
: id(BOUND_NAVIGATION_TARGET_PREFIX)
|
|
988
|
+
: priorTargetId &&
|
|
989
|
+
!priorTargetId.startsWith(`${BOUND_NAVIGATION_TARGET_PREFIX}_`)
|
|
990
|
+
? priorTargetId
|
|
991
|
+
: id('target');
|
|
992
|
+
this.targetIds.set(element, targetId);
|
|
993
|
+
if (binding)
|
|
994
|
+
this.navigationTargetBindings.set(element, binding);
|
|
995
|
+
else
|
|
996
|
+
this.navigationTargetBindings.delete(element);
|
|
997
|
+
const target = {
|
|
998
|
+
targetId,
|
|
999
|
+
revision,
|
|
1000
|
+
...targetIdentity,
|
|
1001
|
+
};
|
|
818
1002
|
targetValues.push(target);
|
|
819
1003
|
nextTargets.set(targetId, { element, revision, options: optionMap, target });
|
|
820
1004
|
}
|
|
@@ -1019,8 +1203,7 @@ class PageContextCollector {
|
|
|
1019
1203
|
const sensitivity = sensitivityFor(element, nameFor(element));
|
|
1020
1204
|
const canRevealDesiredStateTarget = grant.action === 'click' &&
|
|
1021
1205
|
grant.desiredChecked !== undefined &&
|
|
1022
|
-
element
|
|
1023
|
-
['checkbox', 'radio'].includes(element.type);
|
|
1206
|
+
checkedStateFor(element) !== undefined;
|
|
1024
1207
|
if (sensitivity !== 'none' ||
|
|
1025
1208
|
handle.target.protectedRegion !== false ||
|
|
1026
1209
|
!isRendered(element) ||
|
|
@@ -1127,6 +1310,7 @@ class PageContextCollector {
|
|
|
1127
1310
|
const pressed = attached
|
|
1128
1311
|
? literalBooleanAttribute(element, 'aria-pressed')
|
|
1129
1312
|
: undefined;
|
|
1313
|
+
const checked = attached ? checkedStateFor(element) : undefined;
|
|
1130
1314
|
this.callbacks.onHighlight(attached ? element : null, 'success');
|
|
1131
1315
|
return {
|
|
1132
1316
|
...base,
|
|
@@ -1148,9 +1332,7 @@ class PageContextCollector {
|
|
|
1148
1332
|
: grant.desiredExpanded !== undefined || grant.desiredPressed !== undefined
|
|
1149
1333
|
? 'The requested button state was applied.'
|
|
1150
1334
|
: `${grant.action} executed on the approved ${roleFor(element)} target.`,
|
|
1151
|
-
...(
|
|
1152
|
-
? { checked: element.checked }
|
|
1153
|
-
: {}),
|
|
1335
|
+
...(checked !== undefined ? { checked } : {}),
|
|
1154
1336
|
...(this.statefulButtonActionProof && expanded !== undefined ? { expanded } : {}),
|
|
1155
1337
|
...(this.statefulButtonActionProof && pressed !== undefined ? { pressed } : {}),
|
|
1156
1338
|
},
|
|
@@ -1214,11 +1396,15 @@ class PageContextCollector {
|
|
|
1214
1396
|
}
|
|
1215
1397
|
const desiredStates = [];
|
|
1216
1398
|
if (desiredChecked !== undefined) {
|
|
1217
|
-
|
|
1399
|
+
const checked = checkedStateFor(element);
|
|
1400
|
+
if (checked === undefined) {
|
|
1218
1401
|
throw new Error('Desired checked state requires a checkbox or radio target.');
|
|
1219
1402
|
}
|
|
1220
|
-
desiredStates.push(
|
|
1221
|
-
if (element
|
|
1403
|
+
desiredStates.push(checked === desiredChecked);
|
|
1404
|
+
if (element instanceof HTMLInputElement &&
|
|
1405
|
+
element.type === 'radio' &&
|
|
1406
|
+
!desiredChecked &&
|
|
1407
|
+
element.checked !== desiredChecked) {
|
|
1222
1408
|
throw new Error('A radio target cannot be cleared by clicking it.');
|
|
1223
1409
|
}
|
|
1224
1410
|
}
|
|
@@ -1238,6 +1424,10 @@ class PageContextCollector {
|
|
|
1238
1424
|
}
|
|
1239
1425
|
if (desiredStates.length > 0 && desiredStates.every(Boolean))
|
|
1240
1426
|
return;
|
|
1427
|
+
if (desiredChecked !== undefined && framerToggleDescriptor(element)) {
|
|
1428
|
+
dispatchFramerTogglePrimaryPointer(element);
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1241
1431
|
if (element instanceof HTMLAnchorElement) {
|
|
1242
1432
|
const target = new URL(element.href, window.location.href);
|
|
1243
1433
|
if (expectedDestinationPath !== undefined &&
|
|
@@ -1356,18 +1546,14 @@ class PageContextCollector {
|
|
|
1356
1546
|
disabled: !enabled(element),
|
|
1357
1547
|
expanded: element.getAttribute('aria-expanded'),
|
|
1358
1548
|
pressed: element.getAttribute('aria-pressed'),
|
|
1359
|
-
checked:
|
|
1360
|
-
? element.checked
|
|
1361
|
-
: undefined,
|
|
1549
|
+
checked: checkedStateFor(element),
|
|
1362
1550
|
selectedIndex: element instanceof HTMLSelectElement ? element.selectedIndex : undefined,
|
|
1363
1551
|
path: window.location.pathname,
|
|
1364
1552
|
});
|
|
1365
1553
|
}
|
|
1366
1554
|
actionApplied(grant, element, handle) {
|
|
1367
1555
|
if (grant.desiredChecked !== undefined) {
|
|
1368
|
-
return (element
|
|
1369
|
-
['checkbox', 'radio'].includes(element.type) &&
|
|
1370
|
-
element.checked === grant.desiredChecked);
|
|
1556
|
+
return checkedStateFor(element) === grant.desiredChecked;
|
|
1371
1557
|
}
|
|
1372
1558
|
if (grant.desiredExpanded !== undefined &&
|
|
1373
1559
|
literalBooleanAttribute(element, 'aria-expanded') !== grant.desiredExpanded) {
|
|
@@ -1522,6 +1708,7 @@ class PageContextCollector {
|
|
|
1522
1708
|
this.pageId = id('page');
|
|
1523
1709
|
this.revision += 1;
|
|
1524
1710
|
this.targets.clear();
|
|
1711
|
+
this.resetBoundTargetIds();
|
|
1525
1712
|
this.recentSelection = null;
|
|
1526
1713
|
this.pendingNavigation = {
|
|
1527
1714
|
pageId: this.pageId,
|
|
@@ -1541,6 +1728,10 @@ class PageContextCollector {
|
|
|
1541
1728
|
navigation.causalObservationReported = true;
|
|
1542
1729
|
this.callbacks.onCausalNavigationObserved?.(navigation.pageId, navigation.revision, navigation.url, navigation.causalActionId);
|
|
1543
1730
|
}
|
|
1731
|
+
resetBoundTargetIds() {
|
|
1732
|
+
this.targetIds = new WeakMap();
|
|
1733
|
+
this.navigationTargetBindings = new WeakMap();
|
|
1734
|
+
}
|
|
1544
1735
|
installNavigationHooks() {
|
|
1545
1736
|
this.originalPushState = history.pushState;
|
|
1546
1737
|
this.originalReplaceState = history.replaceState;
|
package/cjs/index.js
CHANGED
|
@@ -18,8 +18,8 @@ function aiLiveAssist(options = {}) {
|
|
|
18
18
|
if (document.querySelector('[data-oxvo-ai-live-assist-root]')) {
|
|
19
19
|
return undefined;
|
|
20
20
|
}
|
|
21
|
-
if (!app.checkRequiredVersion?.('7.4.
|
|
22
|
-
console.warn('OXVO AI Guide requires @oxvo/browser version 7.4.
|
|
21
|
+
if (!app.checkRequiredVersion?.('7.4.49')) {
|
|
22
|
+
console.warn('OXVO AI Guide requires @oxvo/browser version 7.4.49 or newer.');
|
|
23
23
|
return undefined;
|
|
24
24
|
}
|
|
25
25
|
const instance = new AiLiveAssist_js_1.default(app, options);
|
package/cjs/media.js
CHANGED
|
@@ -157,8 +157,9 @@ class RealtimeMedia {
|
|
|
157
157
|
switchToTextOnly() {
|
|
158
158
|
this.revokeLocalAudioCapture();
|
|
159
159
|
for (const sender of this.connection?.getSenders() ?? []) {
|
|
160
|
-
if (sender.track?.kind === "audio")
|
|
161
|
-
void sender.replaceTrack(null);
|
|
160
|
+
if (sender.track?.kind === "audio") {
|
|
161
|
+
void sender.replaceTrack(null).catch(() => undefined);
|
|
162
|
+
}
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
close() {
|
package/cjs/preview.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AiGuidePreviewBridge, AiGuidePreviewController, AiGuidePreviewCont
|
|
|
2
2
|
export declare const AI_GUIDE_PREVIEW_PARENT_SOURCE = "oxvo-ai-guide-settings-preview";
|
|
3
3
|
export declare const AI_GUIDE_PREVIEW_WIDGET_SOURCE = "oxvo-ai-guide-widget-preview";
|
|
4
4
|
export declare const AI_GUIDE_PREVIEW_PROTOCOL_VERSION = 1;
|
|
5
|
-
export declare const AI_GUIDE_PREVIEW_RENDERER_VERSION = "1.0.
|
|
5
|
+
export declare const AI_GUIDE_PREVIEW_RENDERER_VERSION = "1.0.48";
|
|
6
6
|
export declare const buildAiGuidePreviewBootstrap: (draft: unknown, assetOrigin?: string | null) => BootstrapConfig;
|
|
7
7
|
export declare class AiGuidePreviewControllerImpl implements AiGuidePreviewController {
|
|
8
8
|
private readonly port;
|
package/cjs/preview.js
CHANGED
|
@@ -9,7 +9,7 @@ const voicePresenceUi_js_1 = require("./voicePresenceUi.js");
|
|
|
9
9
|
exports.AI_GUIDE_PREVIEW_PARENT_SOURCE = "oxvo-ai-guide-settings-preview";
|
|
10
10
|
exports.AI_GUIDE_PREVIEW_WIDGET_SOURCE = "oxvo-ai-guide-widget-preview";
|
|
11
11
|
exports.AI_GUIDE_PREVIEW_PROTOCOL_VERSION = 1;
|
|
12
|
-
exports.AI_GUIDE_PREVIEW_RENDERER_VERSION = "1.0.
|
|
12
|
+
exports.AI_GUIDE_PREVIEW_RENDERER_VERSION = "1.0.48";
|
|
13
13
|
const DEFAULT_COMPANION = {
|
|
14
14
|
enabled: true,
|
|
15
15
|
title: "AI Guide",
|
|
@@ -269,6 +269,7 @@ const buildAiGuidePreviewBootstrap = (draft, assetOrigin = typeof window === "un
|
|
|
269
269
|
customDisclosureEnabled,
|
|
270
270
|
welcomeMessage: boundedNullableString(source.welcomeMessage, 1000),
|
|
271
271
|
conversationStartersEnabled: booleanValue(appearance.conversationStartersEnabled, true),
|
|
272
|
+
compactEntryEnabled: booleanValue(appearance.compactEntryEnabled, false),
|
|
272
273
|
suggestedPrompts: boundedStringList(appearance.suggestedPrompts, 5),
|
|
273
274
|
proactiveEngagement: {
|
|
274
275
|
enabled: booleanValue(proactive.enabled, false),
|
package/cjs/types.d.ts
CHANGED
|
@@ -189,6 +189,7 @@ export type BootstrapConfig = {
|
|
|
189
189
|
customDisclosureEnabled?: boolean;
|
|
190
190
|
welcomeMessage: string | null;
|
|
191
191
|
conversationStartersEnabled?: boolean;
|
|
192
|
+
compactEntryEnabled?: boolean;
|
|
192
193
|
suggestedPrompts?: string[];
|
|
193
194
|
proactiveEngagement?: ProactiveEngagementConfig;
|
|
194
195
|
voicePresence?: VoicePresenceConfig;
|
package/cjs/ui.d.ts
CHANGED
|
@@ -96,6 +96,7 @@ export declare class WidgetView {
|
|
|
96
96
|
private currentHandoffContextRequest;
|
|
97
97
|
private handoffRequestPreparing;
|
|
98
98
|
private currentPageAssistanceRequest;
|
|
99
|
+
private pageAssistancePresentationSnapshot;
|
|
99
100
|
private safetyInteractionIdentity;
|
|
100
101
|
private introComposing;
|
|
101
102
|
private legalOpenedPanel;
|
|
@@ -110,6 +111,7 @@ export declare class WidgetView {
|
|
|
110
111
|
private tooltipTarget;
|
|
111
112
|
private tooltipTimer;
|
|
112
113
|
private ambientHideTimer;
|
|
114
|
+
private voiceCardEffectSettleTimer;
|
|
113
115
|
private attributionTimer;
|
|
114
116
|
private feedbackExitTimer;
|
|
115
117
|
private assistantReadyVisualTimer;
|
|
@@ -155,6 +157,7 @@ export declare class WidgetView {
|
|
|
155
157
|
setRemoteStream(stream: MediaStream): void;
|
|
156
158
|
private playRemoteAudio;
|
|
157
159
|
private invalidateRemotePlayback;
|
|
160
|
+
private pauseRemotePlayback;
|
|
158
161
|
private resetRemotePlayback;
|
|
159
162
|
private onPlaybackActivation;
|
|
160
163
|
private playbackEventIsCurrent;
|
|
@@ -167,6 +170,10 @@ export declare class WidgetView {
|
|
|
167
170
|
updatePreviewConfig(config: BootstrapConfig): boolean;
|
|
168
171
|
private disablePreviewNavigation;
|
|
169
172
|
private applyActivity;
|
|
173
|
+
private effectActivityIsBusy;
|
|
174
|
+
private beginVoiceCardEffectSettle;
|
|
175
|
+
private clearVoiceCardEffectSettle;
|
|
176
|
+
private voiceCardEffectElements;
|
|
170
177
|
private effectsCanRun;
|
|
171
178
|
private isReducedMotionRequested;
|
|
172
179
|
private syncEffectMotion;
|
|
@@ -228,6 +235,7 @@ export declare class WidgetView {
|
|
|
228
235
|
dismissHandoffContextRequest(): void;
|
|
229
236
|
showHandoffContextResult(status: HandoffContextStatus): void;
|
|
230
237
|
showPageAssistanceRequest(value: PageAssistanceRequest): void;
|
|
238
|
+
private syncPageAssistancePresentation;
|
|
231
239
|
private syncPageAssistanceFooter;
|
|
232
240
|
dismissPageAssistanceRequest(): void;
|
|
233
241
|
setPageAssistancePersistentAllowed(value: boolean): void;
|
|
@@ -356,6 +364,7 @@ export declare class WidgetView {
|
|
|
356
364
|
private removeStoredPanelVisibility;
|
|
357
365
|
private clearPanelSessionState;
|
|
358
366
|
private syncLauncherState;
|
|
367
|
+
private compactEntryEnabled;
|
|
359
368
|
cancelPendingConfirmation(): boolean;
|
|
360
369
|
resolvePendingConfirmation(approved: boolean, expected?: {
|
|
361
370
|
actionId: string;
|