@oxvo/ai-live-assist 7.5.6 → 7.5.8

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.
@@ -34,7 +34,7 @@ export declare const normalizeAiGuideOpenInput: (input?: AiGuideOpenInput) => Re
34
34
  export declare const resolveAiGuideProtocolVersion: (bootstrap: Pick<BootstrapConfig, "experienceMode" | "minimumProtocolVersion" | "protocol">) => 1 | 2;
35
35
  export default class AiLiveAssist {
36
36
  private readonly options;
37
- readonly version = "7.5.6";
37
+ readonly version = "7.5.8";
38
38
  private readonly host;
39
39
  private readonly guideAdmission;
40
40
  private readonly standaloneAdmissionPending;
package/cjs/context.js CHANGED
@@ -640,6 +640,18 @@ const safeOptionLabel = (option) => {
640
640
  return sensitivityFor(option, label) === 'none' ? label : '';
641
641
  };
642
642
  const isActionTarget = (element) => element.matches('a[href],button,input,select,textarea,summary,form,[contenteditable="true"],[role="button"],[role="link"],[role="checkbox"],[role="radio"],[role="combobox"],[role="textbox"],[tabindex]');
643
+ const belongsToInteractiveControl = (element) => {
644
+ for (let current = element; current; current = current.parentElement) {
645
+ // Form copy can carry useful public instructions. Only controls and links
646
+ // already represented in targets are omitted from visible page text.
647
+ if (current.matches('form'))
648
+ continue;
649
+ // A bare tabindex is often a focusable Framer content card, not an action.
650
+ if (current.matches('a[href],button,input,select,textarea,summary,[contenteditable="true"],[role="button"],[role="link"],[role="checkbox"],[role="radio"],[role="combobox"],[role="textbox"]'))
651
+ return true;
652
+ }
653
+ return false;
654
+ };
643
655
  const READONLY_INPUT_TYPES = new Set([
644
656
  'date',
645
657
  'datetime-local',
@@ -1185,23 +1197,33 @@ class PageContextCollector {
1185
1197
  });
1186
1198
  }
1187
1199
  const visibleText = [];
1200
+ const capturedSemanticText = new Set();
1188
1201
  let totalText = 0;
1189
1202
  const walker = document.createTreeWalker(document.body ?? document.documentElement, NodeFilter.SHOW_TEXT);
1190
1203
  let node = walker.nextNode();
1191
1204
  while (node && visibleText.length < MAX_TEXT_ITEMS && totalText < MAX_TOTAL_TEXT) {
1192
1205
  const parent = node.parentElement;
1193
- const text = normalize(node.textContent ?? '', 500);
1206
+ const semanticTextElement = parent?.closest('[role="img"][aria-label]') ?? null;
1207
+ const textElement = semanticTextElement && isRendered(semanticTextElement)
1208
+ ? semanticTextElement
1209
+ : parent;
1210
+ const text = normalize(semanticTextElement?.getAttribute('aria-label') ?? node.textContent ?? '', 500);
1194
1211
  if (parent &&
1212
+ textElement &&
1195
1213
  text &&
1196
1214
  !parent.closest(PRIVATE_SELECTOR) &&
1197
1215
  !parent.closest('script,style,noscript,template,svg') &&
1198
1216
  !parent.closest('input,select,textarea,option') &&
1199
- isVisible(parent) &&
1200
- sensitivityFor(parent, nameFor(parent)) === 'none') {
1217
+ (!semanticTextElement || !capturedSemanticText.has(semanticTextElement)) &&
1218
+ !belongsToInteractiveControl(textElement) &&
1219
+ isRendered(textElement) &&
1220
+ sensitivityFor(textElement, nameFor(textElement)) === 'none') {
1201
1221
  const textId = this.textIds.get(node) ?? id('text');
1202
1222
  this.textIds.set(node, textId);
1203
1223
  visibleText.push({ id: textId, text, provenance: 'page' });
1204
1224
  totalText += text.length;
1225
+ if (semanticTextElement)
1226
+ capturedSemanticText.add(semanticTextElement);
1205
1227
  }
1206
1228
  node = walker.nextNode();
1207
1229
  }
@@ -1,5 +1,5 @@
1
1
  import { type LiveDuplexMediaOptions, type LiveDuplexMediaDependencies } from './liveDuplexMedia.js';
2
- export declare const LIVE_CONTROL_CLIENT_VERSION = "7.5.6";
2
+ export declare const LIVE_CONTROL_CLIENT_VERSION = "7.5.8";
3
3
  export declare const LIVE_CONTROL_CLIENT_CAPABILITIES: readonly ["live_duplex_v1", "live_local_wake_v1", "live_fragment_captions_v1"];
4
4
  declare const phases: readonly ["voice_off", "local_listening", "wake_buffering", "starting", "active", "tentative_idle", "closing", "uncertain", "muted", "suspended", "budget_blocked", "ended"];
5
5
  export type LiveControlState = {
package/cjs/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "7.5.6";
1
+ export declare const VERSION = "7.5.8";
package/cjs/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '7.5.6';
4
+ exports.VERSION = '7.5.8';
@@ -34,7 +34,7 @@ export declare const normalizeAiGuideOpenInput: (input?: AiGuideOpenInput) => Re
34
34
  export declare const resolveAiGuideProtocolVersion: (bootstrap: Pick<BootstrapConfig, "experienceMode" | "minimumProtocolVersion" | "protocol">) => 1 | 2;
35
35
  export default class AiLiveAssist {
36
36
  private readonly options;
37
- readonly version = "7.5.6";
37
+ readonly version = "7.5.8";
38
38
  private readonly host;
39
39
  private readonly guideAdmission;
40
40
  private readonly standaloneAdmissionPending;
package/lib/context.js CHANGED
@@ -636,6 +636,18 @@ const safeOptionLabel = (option) => {
636
636
  return sensitivityFor(option, label) === 'none' ? label : '';
637
637
  };
638
638
  const isActionTarget = (element) => element.matches('a[href],button,input,select,textarea,summary,form,[contenteditable="true"],[role="button"],[role="link"],[role="checkbox"],[role="radio"],[role="combobox"],[role="textbox"],[tabindex]');
639
+ const belongsToInteractiveControl = (element) => {
640
+ for (let current = element; current; current = current.parentElement) {
641
+ // Form copy can carry useful public instructions. Only controls and links
642
+ // already represented in targets are omitted from visible page text.
643
+ if (current.matches('form'))
644
+ continue;
645
+ // A bare tabindex is often a focusable Framer content card, not an action.
646
+ if (current.matches('a[href],button,input,select,textarea,summary,[contenteditable="true"],[role="button"],[role="link"],[role="checkbox"],[role="radio"],[role="combobox"],[role="textbox"]'))
647
+ return true;
648
+ }
649
+ return false;
650
+ };
639
651
  const READONLY_INPUT_TYPES = new Set([
640
652
  'date',
641
653
  'datetime-local',
@@ -1181,23 +1193,33 @@ export class PageContextCollector {
1181
1193
  });
1182
1194
  }
1183
1195
  const visibleText = [];
1196
+ const capturedSemanticText = new Set();
1184
1197
  let totalText = 0;
1185
1198
  const walker = document.createTreeWalker(document.body ?? document.documentElement, NodeFilter.SHOW_TEXT);
1186
1199
  let node = walker.nextNode();
1187
1200
  while (node && visibleText.length < MAX_TEXT_ITEMS && totalText < MAX_TOTAL_TEXT) {
1188
1201
  const parent = node.parentElement;
1189
- const text = normalize(node.textContent ?? '', 500);
1202
+ const semanticTextElement = parent?.closest('[role="img"][aria-label]') ?? null;
1203
+ const textElement = semanticTextElement && isRendered(semanticTextElement)
1204
+ ? semanticTextElement
1205
+ : parent;
1206
+ const text = normalize(semanticTextElement?.getAttribute('aria-label') ?? node.textContent ?? '', 500);
1190
1207
  if (parent &&
1208
+ textElement &&
1191
1209
  text &&
1192
1210
  !parent.closest(PRIVATE_SELECTOR) &&
1193
1211
  !parent.closest('script,style,noscript,template,svg') &&
1194
1212
  !parent.closest('input,select,textarea,option') &&
1195
- isVisible(parent) &&
1196
- sensitivityFor(parent, nameFor(parent)) === 'none') {
1213
+ (!semanticTextElement || !capturedSemanticText.has(semanticTextElement)) &&
1214
+ !belongsToInteractiveControl(textElement) &&
1215
+ isRendered(textElement) &&
1216
+ sensitivityFor(textElement, nameFor(textElement)) === 'none') {
1197
1217
  const textId = this.textIds.get(node) ?? id('text');
1198
1218
  this.textIds.set(node, textId);
1199
1219
  visibleText.push({ id: textId, text, provenance: 'page' });
1200
1220
  totalText += text.length;
1221
+ if (semanticTextElement)
1222
+ capturedSemanticText.add(semanticTextElement);
1201
1223
  }
1202
1224
  node = walker.nextNode();
1203
1225
  }
@@ -1,5 +1,5 @@
1
1
  import { type LiveDuplexMediaOptions, type LiveDuplexMediaDependencies } from './liveDuplexMedia.js';
2
- export declare const LIVE_CONTROL_CLIENT_VERSION = "7.5.6";
2
+ export declare const LIVE_CONTROL_CLIENT_VERSION = "7.5.8";
3
3
  export declare const LIVE_CONTROL_CLIENT_CAPABILITIES: readonly ["live_duplex_v1", "live_local_wake_v1", "live_fragment_captions_v1"];
4
4
  declare const phases: readonly ["voice_off", "local_listening", "wake_buffering", "starting", "active", "tentative_idle", "closing", "uncertain", "muted", "suspended", "budget_blocked", "ended"];
5
5
  export type LiveControlState = {
package/lib/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "7.5.6";
1
+ export declare const VERSION = "7.5.8";
package/lib/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '7.5.6';
1
+ export const VERSION = '7.5.8';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oxvo/ai-live-assist",
3
3
  "description": "Secure AI Guide browser plugin for OXVO Sessions.",
4
- "version": "7.5.6",
4
+ "version": "7.5.8",
5
5
  "keywords": [
6
6
  "ai-live-assist",
7
7
  "webrtc",