@aituber-onair/manneri 0.1.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.
Files changed (48) hide show
  1. package/README.ja.md +609 -0
  2. package/README.md +600 -0
  3. package/dist/analyzers/KeywordExtractor.d.ts +48 -0
  4. package/dist/analyzers/KeywordExtractor.js +253 -0
  5. package/dist/analyzers/KeywordExtractor.js.map +1 -0
  6. package/dist/analyzers/PatternDetector.d.ts +38 -0
  7. package/dist/analyzers/PatternDetector.js +244 -0
  8. package/dist/analyzers/PatternDetector.js.map +1 -0
  9. package/dist/analyzers/SimilarityAnalyzer.d.ts +23 -0
  10. package/dist/analyzers/SimilarityAnalyzer.js +153 -0
  11. package/dist/analyzers/SimilarityAnalyzer.js.map +1 -0
  12. package/dist/config/defaultPrompts.d.ts +5 -0
  13. package/dist/config/defaultPrompts.js +22 -0
  14. package/dist/config/defaultPrompts.js.map +1 -0
  15. package/dist/core/ConversationAnalyzer.d.ts +51 -0
  16. package/dist/core/ConversationAnalyzer.js +213 -0
  17. package/dist/core/ConversationAnalyzer.js.map +1 -0
  18. package/dist/core/ManneriDetector.d.ts +64 -0
  19. package/dist/core/ManneriDetector.js +251 -0
  20. package/dist/core/ManneriDetector.js.map +1 -0
  21. package/dist/generators/PromptGenerator.d.ts +15 -0
  22. package/dist/generators/PromptGenerator.js +45 -0
  23. package/dist/generators/PromptGenerator.js.map +1 -0
  24. package/dist/index.d.ts +21 -0
  25. package/dist/index.js +27 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/persistence/LocalStoragePersistenceProvider.d.ts +45 -0
  28. package/dist/persistence/LocalStoragePersistenceProvider.js +102 -0
  29. package/dist/persistence/LocalStoragePersistenceProvider.js.map +1 -0
  30. package/dist/persistence/index.d.ts +5 -0
  31. package/dist/persistence/index.js +5 -0
  32. package/dist/persistence/index.js.map +1 -0
  33. package/dist/types/index.d.ts +114 -0
  34. package/dist/types/index.js +28 -0
  35. package/dist/types/index.js.map +1 -0
  36. package/dist/types/persistence.d.ts +78 -0
  37. package/dist/types/persistence.js +2 -0
  38. package/dist/types/persistence.js.map +1 -0
  39. package/dist/types/prompts.d.ts +22 -0
  40. package/dist/types/prompts.js +36 -0
  41. package/dist/types/prompts.js.map +1 -0
  42. package/dist/utils/browserUtils.d.ts +20 -0
  43. package/dist/utils/browserUtils.js +206 -0
  44. package/dist/utils/browserUtils.js.map +1 -0
  45. package/dist/utils/textUtils.d.ts +10 -0
  46. package/dist/utils/textUtils.js +269 -0
  47. package/dist/utils/textUtils.js.map +1 -0
  48. package/package.json +50 -0
@@ -0,0 +1,114 @@
1
+ export interface Message {
2
+ role: 'system' | 'user' | 'assistant' | 'tool';
3
+ content: string;
4
+ timestamp?: number;
5
+ }
6
+ import type { LocalizedPrompts } from './prompts.js';
7
+ export interface ManneriConfig {
8
+ similarityThreshold: number;
9
+ repetitionLimit: number;
10
+ lookbackWindow: number;
11
+ interventionCooldown: number;
12
+ minMessageLength: number;
13
+ excludeKeywords: string[];
14
+ enableTopicTracking: boolean;
15
+ enableKeywordAnalysis: boolean;
16
+ debugMode: boolean;
17
+ enableAiPromptGeneration: boolean;
18
+ aiPromptGenerationProvider: 'openai' | 'gemini' | 'default';
19
+ aiPromptGenerationModel?: string;
20
+ language?: string;
21
+ customPrompts?: Partial<LocalizedPrompts>;
22
+ }
23
+ export interface SimilarityResult {
24
+ score: number;
25
+ isRepeated: boolean;
26
+ matchedMessages: Message[];
27
+ }
28
+ export interface ConversationPattern {
29
+ id: string;
30
+ pattern: string;
31
+ frequency: number;
32
+ firstSeen: number;
33
+ lastSeen: number;
34
+ messages: Message[];
35
+ }
36
+ export interface TopicInfo {
37
+ keywords: string[];
38
+ score: number;
39
+ category: string;
40
+ confidence: number;
41
+ }
42
+ export interface AnalysisResult {
43
+ similarity: SimilarityResult;
44
+ topics: TopicInfo[];
45
+ patterns: ConversationPattern[];
46
+ shouldIntervene: boolean;
47
+ interventionReason: string;
48
+ lastIntervention: number;
49
+ }
50
+ export interface DiversificationPrompt {
51
+ content: string;
52
+ type: 'topic_change' | 'pattern_break' | 'keyword_shift';
53
+ priority: 'low' | 'medium' | 'high';
54
+ context: string;
55
+ }
56
+ export interface AiProviderConfig {
57
+ provider: 'openai' | 'gemini';
58
+ model: string;
59
+ apiKey: string;
60
+ }
61
+ export interface TextAnalysisOptions {
62
+ minWordLength: number;
63
+ maxNgrams: number;
64
+ includeStopWords: boolean;
65
+ caseSensitive: boolean;
66
+ language: 'ja' | 'en' | 'auto';
67
+ }
68
+ export interface StorageData {
69
+ patterns: ConversationPattern[];
70
+ interventions: number[];
71
+ settings: Partial<ManneriConfig>;
72
+ lastCleanup: number;
73
+ }
74
+ export interface ManneriEvent {
75
+ pattern_detected: AnalysisResult;
76
+ intervention_triggered: DiversificationPrompt;
77
+ topic_changed: {
78
+ oldTopics: string[];
79
+ newTopics: string[];
80
+ };
81
+ similarity_calculated: {
82
+ score: number;
83
+ threshold: number;
84
+ };
85
+ config_updated: Partial<ManneriConfig>;
86
+ storage_cleaned: {
87
+ removedItems: number;
88
+ };
89
+ save_success: {
90
+ timestamp: number;
91
+ };
92
+ save_error: {
93
+ error: Error;
94
+ };
95
+ load_success: {
96
+ data: StorageData;
97
+ timestamp: number;
98
+ };
99
+ load_error: {
100
+ error: Error;
101
+ };
102
+ cleanup_completed: {
103
+ removedItems: number;
104
+ timestamp: number;
105
+ };
106
+ cleanup_error: {
107
+ error: Error;
108
+ };
109
+ }
110
+ export type ManneriEventHandler<T = unknown> = (data: T) => void;
111
+ export declare const DEFAULT_MANNERI_CONFIG: ManneriConfig;
112
+ export type { PromptTemplates, LocalizedPrompts, } from './prompts.js';
113
+ export type { PersistenceProvider, PersistenceConfig, PersistenceEvents, } from './persistence.js';
114
+ export { getPromptTemplate, overridePrompts } from './prompts.js';
@@ -0,0 +1,28 @@
1
+ export const DEFAULT_MANNERI_CONFIG = {
2
+ similarityThreshold: 0.75,
3
+ repetitionLimit: 3,
4
+ lookbackWindow: 10,
5
+ interventionCooldown: 300000,
6
+ minMessageLength: 10,
7
+ excludeKeywords: [
8
+ 'はい',
9
+ 'そうですね',
10
+ 'そうです',
11
+ 'いいえ',
12
+ 'yes',
13
+ 'no',
14
+ 'ok',
15
+ 'okay',
16
+ ],
17
+ enableTopicTracking: true,
18
+ enableKeywordAnalysis: true,
19
+ debugMode: false,
20
+ enableAiPromptGeneration: false,
21
+ aiPromptGenerationProvider: 'default',
22
+ aiPromptGenerationModel: undefined,
23
+ language: 'ja',
24
+ customPrompts: undefined,
25
+ };
26
+ // Re-export utility functions
27
+ export { getPromptTemplate, overridePrompts } from './prompts.js';
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAuGA,MAAM,CAAC,MAAM,sBAAsB,GAAkB;IACnD,mBAAmB,EAAE,IAAI;IACzB,eAAe,EAAE,CAAC;IAClB,cAAc,EAAE,EAAE;IAClB,oBAAoB,EAAE,MAAM;IAC5B,gBAAgB,EAAE,EAAE;IACpB,eAAe,EAAE;QACf,IAAI;QACJ,OAAO;QACP,MAAM;QACN,KAAK;QACL,KAAK;QACL,IAAI;QACJ,IAAI;QACJ,MAAM;KACP;IACD,mBAAmB,EAAE,IAAI;IACzB,qBAAqB,EAAE,IAAI;IAC3B,SAAS,EAAE,KAAK;IAChB,wBAAwB,EAAE,KAAK;IAC/B,0BAA0B,EAAE,SAAS;IACrC,uBAAuB,EAAE,SAAS;IAClC,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,SAAS;CACzB,CAAC;AAeF,8BAA8B;AAC9B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,78 @@
1
+ import type { StorageData } from './index.js';
2
+ /**
3
+ * Interface for persistence providers
4
+ * Allows custom storage implementations (localStorage, IndexedDB, databases, etc.)
5
+ */
6
+ export interface PersistenceProvider {
7
+ /**
8
+ * Save data to storage
9
+ * @param data Data to save
10
+ * @returns Promise<boolean> or boolean indicating success
11
+ */
12
+ save(data: StorageData): Promise<boolean> | boolean;
13
+ /**
14
+ * Load data from storage
15
+ * @returns Promise<StorageData | null> or StorageData | null
16
+ */
17
+ load(): Promise<StorageData | null> | StorageData | null;
18
+ /**
19
+ * Clear all data from storage
20
+ * @returns Promise<boolean> or boolean indicating success
21
+ */
22
+ clear(): Promise<boolean> | boolean;
23
+ /**
24
+ * Clean up old data (optional)
25
+ * @param maxAge Maximum age in milliseconds
26
+ * @returns Promise<number> or number of items removed
27
+ */
28
+ cleanup?(maxAge: number): Promise<number> | number;
29
+ }
30
+ /**
31
+ * Configuration for persistence
32
+ */
33
+ export interface PersistenceConfig {
34
+ /**
35
+ * Persistence provider instance
36
+ */
37
+ provider: PersistenceProvider;
38
+ /**
39
+ * Auto-save interval in milliseconds (0 = disabled)
40
+ * @default 0
41
+ */
42
+ autoSaveInterval?: number;
43
+ /**
44
+ * Auto-cleanup interval in milliseconds (0 = disabled)
45
+ * @default 0
46
+ */
47
+ autoCleanupInterval?: number;
48
+ /**
49
+ * Maximum age for cleanup in milliseconds
50
+ * @default 7 * 24 * 60 * 60 * 1000 (7 days)
51
+ */
52
+ maxAge?: number;
53
+ }
54
+ /**
55
+ * Storage event types
56
+ */
57
+ export interface PersistenceEvents {
58
+ save_success: {
59
+ timestamp: number;
60
+ };
61
+ save_error: {
62
+ error: Error;
63
+ };
64
+ load_success: {
65
+ data: StorageData;
66
+ timestamp: number;
67
+ };
68
+ load_error: {
69
+ error: Error;
70
+ };
71
+ cleanup_completed: {
72
+ removedItems: number;
73
+ timestamp: number;
74
+ };
75
+ cleanup_error: {
76
+ error: Error;
77
+ };
78
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["../../src/types/persistence.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Prompt template types for intervention
3
+ */
4
+ export interface PromptTemplates {
5
+ intervention: string[];
6
+ }
7
+ export interface LocalizedPrompts {
8
+ [language: string]: PromptTemplates;
9
+ }
10
+ export interface PromptConfig {
11
+ language?: string;
12
+ customPrompts?: Partial<LocalizedPrompts>;
13
+ }
14
+ export type SupportedLanguage = 'ja' | 'en' | string;
15
+ /**
16
+ * Get prompt template for specific language and path
17
+ */
18
+ export declare function getPromptTemplate(prompts: LocalizedPrompts, language: string, index?: number): string;
19
+ /**
20
+ * Override default prompts with custom prompts where provided
21
+ */
22
+ export declare function overridePrompts(defaultPrompts: LocalizedPrompts, customPrompts?: Partial<LocalizedPrompts>): LocalizedPrompts;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Prompt template types for intervention
3
+ */
4
+ /**
5
+ * Get prompt template for specific language and path
6
+ */
7
+ export function getPromptTemplate(prompts, language, index) {
8
+ const langPrompts = prompts[language] || prompts.en;
9
+ if (!langPrompts || !langPrompts.intervention) {
10
+ return 'Please change the topic and talk about something new.';
11
+ }
12
+ if (index !== undefined && langPrompts.intervention[index]) {
13
+ return langPrompts.intervention[index];
14
+ }
15
+ // Return random intervention prompt
16
+ const randomIndex = Math.floor(Math.random() * langPrompts.intervention.length);
17
+ return langPrompts.intervention[randomIndex];
18
+ }
19
+ /**
20
+ * Override default prompts with custom prompts where provided
21
+ */
22
+ export function overridePrompts(defaultPrompts, customPrompts) {
23
+ if (!customPrompts)
24
+ return defaultPrompts;
25
+ const merged = { ...defaultPrompts };
26
+ for (const [lang, templates] of Object.entries(customPrompts)) {
27
+ if (templates?.intervention) {
28
+ merged[lang] = {
29
+ ...merged[lang], // Preserve default prompts
30
+ ...templates, // Override with custom prompts
31
+ };
32
+ }
33
+ }
34
+ return merged;
35
+ }
36
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/types/prompts.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAyB,EACzB,QAAgB,EAChB,KAAc;IAEd,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;IACpD,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QAC9C,OAAO,uDAAuD,CAAC;IACjE,CAAC;IAED,IAAI,KAAK,KAAK,SAAS,IAAI,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,oCAAoC;IACpC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC,YAAY,CAAC,MAAM,CAChD,CAAC;IACF,OAAO,WAAW,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,cAAgC,EAChC,aAAyC;IAEzC,IAAI,CAAC,aAAa;QAAE,OAAO,cAAc,CAAC;IAE1C,MAAM,MAAM,GAAqB,EAAE,GAAG,cAAc,EAAE,CAAC;IAEvD,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9D,IAAI,SAAS,EAAE,YAAY,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC,GAAG;gBACb,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,2BAA2B;gBAC5C,GAAG,SAAS,EAAE,+BAA+B;aAC9C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { StorageData, ManneriConfig } from '../types/index.js';
2
+ export declare function isBrowserEnvironment(): boolean;
3
+ export declare function saveToLocalStorage(data: StorageData, storageKey?: string): boolean;
4
+ export declare function loadFromLocalStorage(storageKey?: string): StorageData | null;
5
+ export declare function clearLocalStorage(storageKey?: string): boolean;
6
+ export declare function getStorageSize(storageKey?: string): number;
7
+ export declare function cleanupOldData(storageKey?: string, maxAge?: number): boolean;
8
+ export declare function debounce<T extends (...args: unknown[]) => void>(func: T, wait: number, immediate?: boolean): T;
9
+ export declare function throttle<T extends (...args: unknown[]) => void>(func: T, limit: number): T;
10
+ export declare function createWorkerFunction(fn: () => void): Worker | null;
11
+ export declare function measurePerformance<T>(name: string, fn: () => T, enableLogging?: boolean): T;
12
+ export declare function asyncMeasurePerformance<T>(name: string, fn: () => Promise<T>, enableLogging?: boolean): Promise<T>;
13
+ export declare function createEventEmitter<EventMap extends Record<string, unknown>>(): {
14
+ on<K extends keyof EventMap>(event: K, listener: (data: EventMap[K]) => void): void;
15
+ off<K extends keyof EventMap>(event: K, listener: (data: EventMap[K]) => void): void;
16
+ emit<K extends keyof EventMap>(event: K, data: EventMap[K]): void;
17
+ removeAllListeners(): void;
18
+ };
19
+ export declare function generateId(): string;
20
+ export declare function isValidConfig(config: unknown): config is ManneriConfig;
@@ -0,0 +1,206 @@
1
+ const STORAGE_KEY = 'manneri_data';
2
+ const STORAGE_VERSION = '1.0.0';
3
+ export function isBrowserEnvironment() {
4
+ return typeof window !== 'undefined' && typeof localStorage !== 'undefined';
5
+ }
6
+ export function saveToLocalStorage(data, storageKey) {
7
+ if (!isBrowserEnvironment())
8
+ return false;
9
+ try {
10
+ const storageData = {
11
+ version: STORAGE_VERSION,
12
+ timestamp: Date.now(),
13
+ data,
14
+ };
15
+ localStorage.setItem(storageKey || STORAGE_KEY, JSON.stringify(storageData));
16
+ return true;
17
+ }
18
+ catch (error) {
19
+ console.warn('Failed to save manneri data to localStorage:', error);
20
+ return false;
21
+ }
22
+ }
23
+ export function loadFromLocalStorage(storageKey) {
24
+ if (!isBrowserEnvironment())
25
+ return null;
26
+ try {
27
+ const item = localStorage.getItem(storageKey || STORAGE_KEY);
28
+ if (!item)
29
+ return null;
30
+ const storageData = JSON.parse(item);
31
+ if (storageData.version !== STORAGE_VERSION) {
32
+ console.warn('Manneri storage version mismatch, clearing data');
33
+ clearLocalStorage(storageKey);
34
+ return null;
35
+ }
36
+ return storageData.data;
37
+ }
38
+ catch (error) {
39
+ console.warn('Failed to load manneri data from localStorage:', error);
40
+ return null;
41
+ }
42
+ }
43
+ export function clearLocalStorage(storageKey) {
44
+ if (!isBrowserEnvironment())
45
+ return false;
46
+ try {
47
+ localStorage.removeItem(storageKey || STORAGE_KEY);
48
+ return true;
49
+ }
50
+ catch (error) {
51
+ console.warn('Failed to clear manneri data from localStorage:', error);
52
+ return false;
53
+ }
54
+ }
55
+ export function getStorageSize(storageKey) {
56
+ if (!isBrowserEnvironment())
57
+ return 0;
58
+ try {
59
+ const item = localStorage.getItem(storageKey || STORAGE_KEY);
60
+ return item ? new Blob([item]).size : 0;
61
+ }
62
+ catch (error) {
63
+ return 0;
64
+ }
65
+ }
66
+ export function cleanupOldData(storageKey, maxAge = 24 * 60 * 60 * 1000) {
67
+ const data = loadFromLocalStorage(storageKey);
68
+ if (!data)
69
+ return false;
70
+ const now = Date.now();
71
+ const cutoff = now - maxAge;
72
+ const cleanedPatterns = data.patterns.filter((pattern) => pattern.lastSeen > cutoff);
73
+ const cleanedInterventions = data.interventions.filter((timestamp) => timestamp > cutoff);
74
+ const cleanedData = {
75
+ ...data,
76
+ patterns: cleanedPatterns,
77
+ interventions: cleanedInterventions,
78
+ lastCleanup: now,
79
+ };
80
+ return saveToLocalStorage(cleanedData, storageKey);
81
+ }
82
+ export function debounce(func, wait, immediate = false) {
83
+ let timeout = null;
84
+ return ((...args) => {
85
+ const later = () => {
86
+ timeout = null;
87
+ if (!immediate)
88
+ func(...args);
89
+ };
90
+ const callNow = immediate && !timeout;
91
+ if (timeout)
92
+ clearTimeout(timeout);
93
+ timeout = setTimeout(later, wait);
94
+ if (callNow)
95
+ func(...args);
96
+ });
97
+ }
98
+ export function throttle(func, limit) {
99
+ let inThrottle = false;
100
+ return ((...args) => {
101
+ if (!inThrottle) {
102
+ func(...args);
103
+ inThrottle = true;
104
+ setTimeout(() => {
105
+ inThrottle = false;
106
+ }, limit);
107
+ }
108
+ });
109
+ }
110
+ export function createWorkerFunction(fn) {
111
+ if (!isBrowserEnvironment() || typeof Worker === 'undefined')
112
+ return null;
113
+ try {
114
+ const functionString = fn.toString();
115
+ const blob = new Blob([`(${functionString})()`], {
116
+ type: 'application/javascript',
117
+ });
118
+ const url = URL.createObjectURL(blob);
119
+ const worker = new Worker(url);
120
+ worker.addEventListener('error', () => {
121
+ URL.revokeObjectURL(url);
122
+ });
123
+ return worker;
124
+ }
125
+ catch (error) {
126
+ console.warn('Failed to create worker:', error);
127
+ return null;
128
+ }
129
+ }
130
+ export function measurePerformance(name, fn, enableLogging = false) {
131
+ const start = performance.now();
132
+ const result = fn();
133
+ const end = performance.now();
134
+ if (enableLogging) {
135
+ console.log(`[Manneri] ${name}: ${(end - start).toFixed(2)}ms`);
136
+ }
137
+ return result;
138
+ }
139
+ export function asyncMeasurePerformance(name, fn, enableLogging = false) {
140
+ const start = performance.now();
141
+ return fn().then((result) => {
142
+ const end = performance.now();
143
+ if (enableLogging) {
144
+ console.log(`[Manneri] ${name}: ${(end - start).toFixed(2)}ms`);
145
+ }
146
+ return result;
147
+ });
148
+ }
149
+ export function createEventEmitter() {
150
+ const listeners = new Map();
151
+ return {
152
+ on(event, listener) {
153
+ const eventKey = String(event);
154
+ if (!listeners.has(eventKey)) {
155
+ listeners.set(eventKey, new Set());
156
+ }
157
+ listeners.get(eventKey)?.add(listener);
158
+ },
159
+ off(event, listener) {
160
+ const eventKey = String(event);
161
+ const eventListeners = listeners.get(eventKey);
162
+ if (eventListeners) {
163
+ eventListeners.delete(listener);
164
+ if (eventListeners.size === 0) {
165
+ listeners.delete(eventKey);
166
+ }
167
+ }
168
+ },
169
+ emit(event, data) {
170
+ const eventKey = String(event);
171
+ const eventListeners = listeners.get(eventKey);
172
+ if (eventListeners) {
173
+ for (const listener of eventListeners) {
174
+ try {
175
+ listener(data);
176
+ }
177
+ catch (error) {
178
+ console.error(`Error in event listener for ${String(event)}:`, error);
179
+ }
180
+ }
181
+ }
182
+ },
183
+ removeAllListeners() {
184
+ listeners.clear();
185
+ },
186
+ };
187
+ }
188
+ export function generateId() {
189
+ return Math.random().toString(36).substr(2, 9) + Date.now().toString(36);
190
+ }
191
+ export function isValidConfig(config) {
192
+ if (typeof config !== 'object' || config === null) {
193
+ return false;
194
+ }
195
+ const c = config;
196
+ return (typeof c.similarityThreshold === 'number' &&
197
+ typeof c.repetitionLimit === 'number' &&
198
+ typeof c.lookbackWindow === 'number' &&
199
+ typeof c.interventionCooldown === 'number' &&
200
+ typeof c.minMessageLength === 'number' &&
201
+ Array.isArray(c.excludeKeywords) &&
202
+ typeof c.enableTopicTracking === 'boolean' &&
203
+ typeof c.enableKeywordAnalysis === 'boolean' &&
204
+ typeof c.debugMode === 'boolean');
205
+ }
206
+ //# sourceMappingURL=browserUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browserUtils.js","sourceRoot":"","sources":["../../src/utils/browserUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { TextAnalysisOptions } from '../types/index.js';
2
+ export declare function normalizeText(text: string, options?: Partial<TextAnalysisOptions>): string;
3
+ export declare function containsJapanese(text: string): boolean;
4
+ export declare function tokenize(text: string, options?: Partial<TextAnalysisOptions>): string[];
5
+ export declare function generateNgrams(tokens: string[], n: number): string[];
6
+ export declare function calculateJaccardSimilarity(set1: Set<string>, set2: Set<string>): number;
7
+ export declare function calculateCosineSimilarity(vector1: number[], vector2: number[]): number;
8
+ export declare function createTfIdfVector(tokens: string[], vocabulary: string[], documentFrequencies: Map<string, number>, totalDocuments: number): number[];
9
+ export declare function extractKeywords(text: string, options?: Partial<TextAnalysisOptions>): string[];
10
+ export declare function calculateTextSimilarity(text1: string, text2: string, options?: Partial<TextAnalysisOptions>): number;