@astermind/cybernetic-chatbot-client 2.2.30 → 2.2.34
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/CyberneticSessionStorage.d.ts +117 -0
- package/dist/CyberneticSessionStorage.d.ts.map +1 -0
- package/dist/agentic/CyberneticIntentClassifier.d.ts.map +1 -1
- package/dist/agentic/SiteMapDiscovery.d.ts +42 -0
- package/dist/agentic/SiteMapDiscovery.d.ts.map +1 -1
- package/dist/cybernetic-chatbot-client-full.esm.js +268 -19
- package/dist/cybernetic-chatbot-client-full.esm.js.map +1 -1
- package/dist/cybernetic-chatbot-client-full.min.js +1 -1
- package/dist/cybernetic-chatbot-client-full.min.js.map +1 -1
- package/dist/cybernetic-chatbot-client-full.umd.js +268 -19
- package/dist/cybernetic-chatbot-client-full.umd.js.map +1 -1
- package/dist/cybernetic-chatbot-client.esm.js +268 -19
- package/dist/cybernetic-chatbot-client.esm.js.map +1 -1
- package/dist/cybernetic-chatbot-client.min.js +1 -1
- package/dist/cybernetic-chatbot-client.min.js.map +1 -1
- package/dist/cybernetic-chatbot-client.umd.js +268 -19
- package/dist/cybernetic-chatbot-client.umd.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -2670,6 +2670,68 @@ const configLoaders = {
|
|
|
2670
2670
|
|
|
2671
2671
|
// src/agentic/SiteMapDiscovery.ts
|
|
2672
2672
|
// Multi-source sitemap discovery and merging for agentic navigation
|
|
2673
|
+
// Zero-config mode: automatically discovers routes on any site
|
|
2674
|
+
// ==================== SMART DEFAULTS ====================
|
|
2675
|
+
/**
|
|
2676
|
+
* Comprehensive default selectors that work on most sites
|
|
2677
|
+
* Covers semantic HTML, common CSS patterns, and framework conventions
|
|
2678
|
+
*/
|
|
2679
|
+
const DEFAULT_NAV_SELECTORS = [
|
|
2680
|
+
// Semantic HTML5 navigation
|
|
2681
|
+
'nav a[href]',
|
|
2682
|
+
'[role="navigation"] a[href]',
|
|
2683
|
+
'header a[href]',
|
|
2684
|
+
// Common CSS class patterns
|
|
2685
|
+
'.nav a[href]',
|
|
2686
|
+
'.navbar a[href]',
|
|
2687
|
+
'.navigation a[href]',
|
|
2688
|
+
'.sidebar a[href]',
|
|
2689
|
+
'.side-nav a[href]',
|
|
2690
|
+
'.sidenav a[href]',
|
|
2691
|
+
'.menu a[href]',
|
|
2692
|
+
'.main-menu a[href]',
|
|
2693
|
+
'.top-menu a[href]',
|
|
2694
|
+
// Data attributes
|
|
2695
|
+
'[data-nav] a[href]',
|
|
2696
|
+
'[data-menu] a[href]',
|
|
2697
|
+
'[data-navigation] a[href]',
|
|
2698
|
+
// ARIA patterns
|
|
2699
|
+
'[aria-label*="navigation" i] a[href]',
|
|
2700
|
+
'[aria-label*="menu" i] a[href]',
|
|
2701
|
+
// Breadcrumbs
|
|
2702
|
+
'[aria-label*="breadcrumb" i] a[href]',
|
|
2703
|
+
'.breadcrumb a[href]',
|
|
2704
|
+
'.breadcrumbs a[href]',
|
|
2705
|
+
// Generic internal links (fallback - caught last)
|
|
2706
|
+
'a[href^="/"]',
|
|
2707
|
+
];
|
|
2708
|
+
/**
|
|
2709
|
+
* Default paths to exclude from discovery
|
|
2710
|
+
* Covers common auth, API, and framework-internal routes
|
|
2711
|
+
*/
|
|
2712
|
+
const DEFAULT_EXCLUDE_PATTERNS = [
|
|
2713
|
+
// Authentication routes
|
|
2714
|
+
'/login', '/logout', '/signin', '/signout', '/sign-in', '/sign-out',
|
|
2715
|
+
'/register', '/signup', '/sign-up', '/forgot-password', '/reset-password',
|
|
2716
|
+
'/auth/*', '/oauth/*', '/callback/*', '/sso/*',
|
|
2717
|
+
// API and framework internals
|
|
2718
|
+
'/api/*', '/_next/*', '/_nuxt/*', '/__*',
|
|
2719
|
+
// Special links
|
|
2720
|
+
'javascript:*', 'mailto:*', 'tel:*', '#*',
|
|
2721
|
+
];
|
|
2722
|
+
/**
|
|
2723
|
+
* Default maximum number of links to scan from DOM
|
|
2724
|
+
* Prevents performance issues on sites with many links
|
|
2725
|
+
*/
|
|
2726
|
+
const DEFAULT_MAX_DOM_LINKS = 200;
|
|
2727
|
+
/**
|
|
2728
|
+
* Default cache TTL for localStorage (5 minutes)
|
|
2729
|
+
*/
|
|
2730
|
+
const DEFAULT_CACHE_TTL = 5 * 60 * 1000;
|
|
2731
|
+
/**
|
|
2732
|
+
* Cache version - increment when cache format changes
|
|
2733
|
+
*/
|
|
2734
|
+
const CACHE_VERSION = '1';
|
|
2673
2735
|
/**
|
|
2674
2736
|
* Multi-source sitemap discovery and management
|
|
2675
2737
|
*
|
|
@@ -2677,6 +2739,9 @@ const configLoaders = {
|
|
|
2677
2739
|
* 1. Static props (explicit configuration)
|
|
2678
2740
|
* 2. Framework auto-discovery (React Router, Vue Router, etc.)
|
|
2679
2741
|
* 3. Backend API (tenant-specific sitemaps)
|
|
2742
|
+
*
|
|
2743
|
+
* Zero-config mode: When agentic is enabled but no siteMapConfig provided,
|
|
2744
|
+
* automatically discovers routes using smart defaults.
|
|
2680
2745
|
*/
|
|
2681
2746
|
class SiteMapDiscovery {
|
|
2682
2747
|
constructor(config, apiUrl, apiKey) {
|
|
@@ -2686,6 +2751,8 @@ class SiteMapDiscovery {
|
|
|
2686
2751
|
this.backendCache = null;
|
|
2687
2752
|
this.isInitialized = false;
|
|
2688
2753
|
this.initPromise = null;
|
|
2754
|
+
this.detectedFramework = 'generic';
|
|
2755
|
+
this.popstateHandler = null;
|
|
2689
2756
|
this.config = config;
|
|
2690
2757
|
this.apiUrl = apiUrl;
|
|
2691
2758
|
this.apiKey = apiKey;
|
|
@@ -2694,6 +2761,7 @@ class SiteMapDiscovery {
|
|
|
2694
2761
|
this.staticEntries = this.enhanceEntries(config.static, 'props');
|
|
2695
2762
|
}
|
|
2696
2763
|
}
|
|
2764
|
+
// ==================== INITIALIZATION ====================
|
|
2697
2765
|
/**
|
|
2698
2766
|
* Initialize all sitemap sources
|
|
2699
2767
|
* Call this during widget initialization or first query based on loadStrategy
|
|
@@ -2708,8 +2776,19 @@ class SiteMapDiscovery {
|
|
|
2708
2776
|
this.isInitialized = true;
|
|
2709
2777
|
}
|
|
2710
2778
|
async performInitialization() {
|
|
2779
|
+
// Wait for DOM to be ready before discovery
|
|
2780
|
+
await this.waitForDOMReady();
|
|
2781
|
+
// Try to load from localStorage cache first
|
|
2782
|
+
const cachedEntries = this.loadFromLocalStorage();
|
|
2783
|
+
if (cachedEntries) {
|
|
2784
|
+
this.discoveredEntries = cachedEntries;
|
|
2785
|
+
console.log(`[SiteMapDiscovery] Loaded ${cachedEntries.length} entries from cache`);
|
|
2786
|
+
// Still run discovery in background to refresh cache
|
|
2787
|
+
this.refreshInBackground();
|
|
2788
|
+
return;
|
|
2789
|
+
}
|
|
2711
2790
|
const tasks = [];
|
|
2712
|
-
// Source 2: Framework auto-discovery
|
|
2791
|
+
// Source 2: Framework auto-discovery (enabled by default)
|
|
2713
2792
|
if (this.config.discovery?.enabled !== false) {
|
|
2714
2793
|
tasks.push(this.discoverFromFramework());
|
|
2715
2794
|
}
|
|
@@ -2723,6 +2802,8 @@ class SiteMapDiscovery {
|
|
|
2723
2802
|
const { entries, source } = result.value;
|
|
2724
2803
|
if (source === 'discovery') {
|
|
2725
2804
|
this.discoveredEntries = entries;
|
|
2805
|
+
// Save to localStorage
|
|
2806
|
+
this.saveToLocalStorage(entries);
|
|
2726
2807
|
}
|
|
2727
2808
|
else if (source === 'backend') {
|
|
2728
2809
|
this.backendEntries = entries;
|
|
@@ -2732,9 +2813,144 @@ class SiteMapDiscovery {
|
|
|
2732
2813
|
console.warn('[SiteMapDiscovery] Source failed:', result.reason);
|
|
2733
2814
|
}
|
|
2734
2815
|
}
|
|
2816
|
+
// Set up popstate listener for SPA navigation
|
|
2817
|
+
this.setupPopstateListener();
|
|
2735
2818
|
const total = this.staticEntries.length + this.discoveredEntries.length + this.backendEntries.length;
|
|
2736
2819
|
console.log(`[SiteMapDiscovery] Initialized with ${total} total entries (${this.staticEntries.length} static, ${this.discoveredEntries.length} discovered, ${this.backendEntries.length} backend)`);
|
|
2737
2820
|
}
|
|
2821
|
+
/**
|
|
2822
|
+
* Wait for DOM to be ready before scanning
|
|
2823
|
+
*/
|
|
2824
|
+
async waitForDOMReady() {
|
|
2825
|
+
if (typeof document === 'undefined')
|
|
2826
|
+
return;
|
|
2827
|
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
2828
|
+
// DOM is ready, but give frameworks a microtask to mount
|
|
2829
|
+
await new Promise(resolve => setTimeout(resolve, 0));
|
|
2830
|
+
return;
|
|
2831
|
+
}
|
|
2832
|
+
return new Promise((resolve) => {
|
|
2833
|
+
document.addEventListener('DOMContentLoaded', () => resolve(), { once: true });
|
|
2834
|
+
});
|
|
2835
|
+
}
|
|
2836
|
+
/**
|
|
2837
|
+
* Set up popstate listener to re-discover on SPA navigation
|
|
2838
|
+
*/
|
|
2839
|
+
setupPopstateListener() {
|
|
2840
|
+
if (typeof window === 'undefined')
|
|
2841
|
+
return;
|
|
2842
|
+
this.popstateHandler = () => {
|
|
2843
|
+
// Debounce re-discovery
|
|
2844
|
+
setTimeout(() => {
|
|
2845
|
+
this.refreshInBackground();
|
|
2846
|
+
}, 100);
|
|
2847
|
+
};
|
|
2848
|
+
window.addEventListener('popstate', this.popstateHandler);
|
|
2849
|
+
}
|
|
2850
|
+
/**
|
|
2851
|
+
* Refresh discovery in background without blocking
|
|
2852
|
+
*/
|
|
2853
|
+
async refreshInBackground() {
|
|
2854
|
+
try {
|
|
2855
|
+
const result = await this.discoverFromFramework();
|
|
2856
|
+
if (result.entries.length > 0) {
|
|
2857
|
+
this.discoveredEntries = result.entries;
|
|
2858
|
+
this.saveToLocalStorage(result.entries);
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
catch (error) {
|
|
2862
|
+
// Silent fail for background refresh
|
|
2863
|
+
console.debug('[SiteMapDiscovery] Background refresh failed:', error);
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
// ==================== LOCALSTORAGE CACHING ====================
|
|
2867
|
+
/**
|
|
2868
|
+
* Get localStorage cache key for current origin
|
|
2869
|
+
*/
|
|
2870
|
+
getCacheKey() {
|
|
2871
|
+
if (typeof window === 'undefined')
|
|
2872
|
+
return 'astermind-sitemap';
|
|
2873
|
+
return `astermind-sitemap-${window.location.origin}`;
|
|
2874
|
+
}
|
|
2875
|
+
/**
|
|
2876
|
+
* Load discovered entries from localStorage cache
|
|
2877
|
+
*/
|
|
2878
|
+
loadFromLocalStorage() {
|
|
2879
|
+
if (typeof localStorage === 'undefined')
|
|
2880
|
+
return null;
|
|
2881
|
+
try {
|
|
2882
|
+
const key = this.getCacheKey();
|
|
2883
|
+
const cached = localStorage.getItem(key);
|
|
2884
|
+
if (!cached)
|
|
2885
|
+
return null;
|
|
2886
|
+
const data = JSON.parse(cached);
|
|
2887
|
+
// Check version
|
|
2888
|
+
if (data.version !== CACHE_VERSION) {
|
|
2889
|
+
localStorage.removeItem(key);
|
|
2890
|
+
return null;
|
|
2891
|
+
}
|
|
2892
|
+
// Check TTL
|
|
2893
|
+
const ttl = this.config.discovery?.cacheTtl ?? DEFAULT_CACHE_TTL;
|
|
2894
|
+
if (Date.now() - data.timestamp > ttl) {
|
|
2895
|
+
localStorage.removeItem(key);
|
|
2896
|
+
return null;
|
|
2897
|
+
}
|
|
2898
|
+
this.detectedFramework = data.framework;
|
|
2899
|
+
return data.entries;
|
|
2900
|
+
}
|
|
2901
|
+
catch (error) {
|
|
2902
|
+
console.debug('[SiteMapDiscovery] Failed to load from cache:', error);
|
|
2903
|
+
return null;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
/**
|
|
2907
|
+
* Save discovered entries to localStorage cache
|
|
2908
|
+
*/
|
|
2909
|
+
saveToLocalStorage(entries) {
|
|
2910
|
+
if (typeof localStorage === 'undefined')
|
|
2911
|
+
return;
|
|
2912
|
+
if (this.config.discovery?.cacheRoutes === false)
|
|
2913
|
+
return;
|
|
2914
|
+
try {
|
|
2915
|
+
const key = this.getCacheKey();
|
|
2916
|
+
const data = {
|
|
2917
|
+
entries,
|
|
2918
|
+
url: typeof window !== 'undefined' ? window.location.href : '',
|
|
2919
|
+
timestamp: Date.now(),
|
|
2920
|
+
framework: this.detectedFramework,
|
|
2921
|
+
version: CACHE_VERSION
|
|
2922
|
+
};
|
|
2923
|
+
localStorage.setItem(key, JSON.stringify(data));
|
|
2924
|
+
}
|
|
2925
|
+
catch (error) {
|
|
2926
|
+
// localStorage might be full or disabled
|
|
2927
|
+
console.debug('[SiteMapDiscovery] Failed to save to cache:', error);
|
|
2928
|
+
}
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* Clear localStorage cache
|
|
2932
|
+
*/
|
|
2933
|
+
clearCache() {
|
|
2934
|
+
if (typeof localStorage === 'undefined')
|
|
2935
|
+
return;
|
|
2936
|
+
localStorage.removeItem(this.getCacheKey());
|
|
2937
|
+
}
|
|
2938
|
+
// ==================== CLEANUP ====================
|
|
2939
|
+
/**
|
|
2940
|
+
* Dispose of resources (event listeners, etc.)
|
|
2941
|
+
*/
|
|
2942
|
+
dispose() {
|
|
2943
|
+
if (this.popstateHandler && typeof window !== 'undefined') {
|
|
2944
|
+
window.removeEventListener('popstate', this.popstateHandler);
|
|
2945
|
+
this.popstateHandler = null;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
/**
|
|
2949
|
+
* Get detected framework name
|
|
2950
|
+
*/
|
|
2951
|
+
getDetectedFramework() {
|
|
2952
|
+
return this.detectedFramework;
|
|
2953
|
+
}
|
|
2738
2954
|
/**
|
|
2739
2955
|
* Get merged sitemap entries with deduplication
|
|
2740
2956
|
*/
|
|
@@ -2761,6 +2977,7 @@ class SiteMapDiscovery {
|
|
|
2761
2977
|
try {
|
|
2762
2978
|
// Detect framework if not specified
|
|
2763
2979
|
const framework = config.framework || this.detectFramework();
|
|
2980
|
+
this.detectedFramework = framework;
|
|
2764
2981
|
let routes = [];
|
|
2765
2982
|
switch (framework) {
|
|
2766
2983
|
case 'react-router':
|
|
@@ -2944,26 +3161,31 @@ class SiteMapDiscovery {
|
|
|
2944
3161
|
}
|
|
2945
3162
|
/**
|
|
2946
3163
|
* Discover routes by scanning DOM navigation elements
|
|
3164
|
+
* Uses smart defaults when no selectors provided
|
|
2947
3165
|
*/
|
|
2948
3166
|
discoverFromDOM(selectors) {
|
|
2949
3167
|
const routes = [];
|
|
2950
3168
|
if (typeof document === 'undefined')
|
|
2951
3169
|
return routes;
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
'header a[href]'
|
|
2960
|
-
];
|
|
2961
|
-
const allSelectors = selectors || defaultSelectors;
|
|
3170
|
+
// Use provided selectors or smart defaults
|
|
3171
|
+
const allSelectors = selectors || DEFAULT_NAV_SELECTORS;
|
|
3172
|
+
// Get max links limit from config or use default
|
|
3173
|
+
const maxLinks = this.config.discovery?.maxDomLinks ?? DEFAULT_MAX_DOM_LINKS;
|
|
3174
|
+
// Get exclude patterns (merge user-provided with defaults)
|
|
3175
|
+
const userExcludes = this.config.discovery?.excludePaths || [];
|
|
3176
|
+
const allExcludes = [...DEFAULT_EXCLUDE_PATTERNS, ...userExcludes];
|
|
2962
3177
|
const seen = new Set();
|
|
3178
|
+
let linkCount = 0;
|
|
2963
3179
|
for (const selector of allSelectors) {
|
|
3180
|
+
// Stop if we've hit the limit
|
|
3181
|
+
if (linkCount >= maxLinks)
|
|
3182
|
+
break;
|
|
2964
3183
|
try {
|
|
2965
3184
|
const links = document.querySelectorAll(selector);
|
|
2966
3185
|
for (const link of links) {
|
|
3186
|
+
// Stop if we've hit the limit
|
|
3187
|
+
if (linkCount >= maxLinks)
|
|
3188
|
+
break;
|
|
2967
3189
|
const href = link.getAttribute('href');
|
|
2968
3190
|
if (!href)
|
|
2969
3191
|
continue;
|
|
@@ -2972,14 +3194,31 @@ class SiteMapDiscovery {
|
|
|
2972
3194
|
continue;
|
|
2973
3195
|
}
|
|
2974
3196
|
// Normalize path
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3197
|
+
let path = href;
|
|
3198
|
+
if (href.startsWith('http')) {
|
|
3199
|
+
try {
|
|
3200
|
+
path = new URL(href).pathname;
|
|
3201
|
+
}
|
|
3202
|
+
catch {
|
|
3203
|
+
continue;
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
else if (!href.startsWith('/')) {
|
|
3207
|
+
path = `/${href}`;
|
|
2979
3208
|
}
|
|
2980
|
-
seen.add(path);
|
|
2981
3209
|
// Clean path (remove query string and hash)
|
|
2982
3210
|
const cleanPath = path.split('?')[0].split('#')[0];
|
|
3211
|
+
// Skip duplicates
|
|
3212
|
+
if (seen.has(cleanPath))
|
|
3213
|
+
continue;
|
|
3214
|
+
// Skip root path
|
|
3215
|
+
if (cleanPath === '/')
|
|
3216
|
+
continue;
|
|
3217
|
+
// Skip paths matching exclude patterns
|
|
3218
|
+
if (this.shouldExcludeRoute(cleanPath, allExcludes))
|
|
3219
|
+
continue;
|
|
3220
|
+
seen.add(cleanPath);
|
|
3221
|
+
linkCount++;
|
|
2983
3222
|
routes.push({
|
|
2984
3223
|
path: cleanPath,
|
|
2985
3224
|
name: link.textContent?.trim() || this.pathToName(cleanPath)
|
|
@@ -2990,6 +3229,7 @@ class SiteMapDiscovery {
|
|
|
2990
3229
|
// Invalid selector - skip
|
|
2991
3230
|
}
|
|
2992
3231
|
}
|
|
3232
|
+
console.log(`[SiteMapDiscovery] DOM scan found ${routes.length} routes (limit: ${maxLinks})`);
|
|
2993
3233
|
return routes;
|
|
2994
3234
|
}
|
|
2995
3235
|
// ==================== SOURCE 3: BACKEND API ====================
|
|
@@ -3277,9 +3517,18 @@ class CyberneticIntentClassifier {
|
|
|
3277
3517
|
this.modalIndex = new Map();
|
|
3278
3518
|
// Build indexes for fast lookup
|
|
3279
3519
|
this.buildIndexes();
|
|
3280
|
-
//
|
|
3281
|
-
|
|
3282
|
-
|
|
3520
|
+
// Auto-enable sitemap discovery when agentic is enabled but no explicit config provided
|
|
3521
|
+
// This enables zero-config mode: just set enabled: true and discovery works automatically
|
|
3522
|
+
const siteMapConfig = config.siteMapConfig ?? (config.enabled && !config.siteMap?.length
|
|
3523
|
+
? { discovery: { enabled: true } }
|
|
3524
|
+
: undefined);
|
|
3525
|
+
// Initialize multi-source sitemap discovery
|
|
3526
|
+
if (siteMapConfig) {
|
|
3527
|
+
this.siteMapDiscovery = new SiteMapDiscovery(siteMapConfig, apiUrl, apiKey);
|
|
3528
|
+
// Log zero-config mode activation
|
|
3529
|
+
if (!config.siteMapConfig && config.enabled) {
|
|
3530
|
+
console.log('[CyberneticIntentClassifier] Zero-config mode: auto-discovery enabled');
|
|
3531
|
+
}
|
|
3283
3532
|
}
|
|
3284
3533
|
}
|
|
3285
3534
|
/**
|