gthinking 1.3.0 → 2.1.1

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 (271) hide show
  1. package/.eslintrc.js +34 -0
  2. package/ANALYSIS_SUMMARY.md +363 -0
  3. package/README.md +230 -250
  4. package/dist/analysis/analysis-engine.d.ts +63 -0
  5. package/dist/analysis/analysis-engine.d.ts.map +1 -0
  6. package/dist/analysis/analysis-engine.js +322 -0
  7. package/dist/analysis/analysis-engine.js.map +1 -0
  8. package/dist/core/config.d.ts +1419 -0
  9. package/dist/core/config.d.ts.map +1 -0
  10. package/dist/core/config.js +361 -0
  11. package/dist/core/config.js.map +1 -0
  12. package/dist/core/engine.d.ts +176 -0
  13. package/dist/core/engine.d.ts.map +1 -0
  14. package/dist/core/engine.js +604 -0
  15. package/dist/core/engine.js.map +1 -0
  16. package/dist/core/errors.d.ts +153 -0
  17. package/dist/core/errors.d.ts.map +1 -0
  18. package/dist/core/errors.js +287 -0
  19. package/dist/core/errors.js.map +1 -0
  20. package/dist/core/index.d.ts +7 -0
  21. package/dist/core/index.d.ts.map +1 -0
  22. package/dist/{types.js → core/index.js} +8 -4
  23. package/dist/core/index.js.map +1 -0
  24. package/dist/core/pipeline.d.ts +121 -0
  25. package/dist/core/pipeline.d.ts.map +1 -0
  26. package/dist/core/pipeline.js +289 -0
  27. package/dist/core/pipeline.js.map +1 -0
  28. package/dist/core/rate-limiter.d.ts +58 -0
  29. package/dist/core/rate-limiter.d.ts.map +1 -0
  30. package/dist/core/rate-limiter.js +133 -0
  31. package/dist/core/rate-limiter.js.map +1 -0
  32. package/dist/core/session-manager.d.ts +96 -0
  33. package/dist/core/session-manager.d.ts.map +1 -0
  34. package/dist/core/session-manager.js +223 -0
  35. package/dist/core/session-manager.js.map +1 -0
  36. package/dist/creativity/creativity-engine.d.ts +6 -0
  37. package/dist/creativity/creativity-engine.d.ts.map +1 -0
  38. package/dist/creativity/creativity-engine.js +17 -0
  39. package/dist/creativity/creativity-engine.js.map +1 -0
  40. package/dist/index.d.ts +24 -32
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +130 -104
  43. package/dist/index.js.map +1 -1
  44. package/dist/learning/learning-engine.d.ts +6 -0
  45. package/dist/learning/learning-engine.d.ts.map +1 -0
  46. package/dist/learning/learning-engine.js +17 -0
  47. package/dist/learning/learning-engine.js.map +1 -0
  48. package/dist/llm/index.d.ts +10 -0
  49. package/dist/llm/index.d.ts.map +1 -0
  50. package/dist/llm/index.js +26 -0
  51. package/dist/llm/index.js.map +1 -0
  52. package/dist/llm/llm-service.d.ts +109 -0
  53. package/dist/llm/llm-service.d.ts.map +1 -0
  54. package/dist/llm/llm-service.js +224 -0
  55. package/dist/llm/llm-service.js.map +1 -0
  56. package/dist/llm/providers/base.d.ts +85 -0
  57. package/dist/llm/providers/base.d.ts.map +1 -0
  58. package/dist/llm/providers/base.js +57 -0
  59. package/dist/llm/providers/base.js.map +1 -0
  60. package/dist/llm/providers/cli.d.ts +23 -0
  61. package/dist/llm/providers/cli.d.ts.map +1 -0
  62. package/dist/llm/providers/cli.js +158 -0
  63. package/dist/llm/providers/cli.js.map +1 -0
  64. package/dist/llm/providers/gemini.d.ts +30 -0
  65. package/dist/llm/providers/gemini.d.ts.map +1 -0
  66. package/dist/llm/providers/gemini.js +168 -0
  67. package/dist/llm/providers/gemini.js.map +1 -0
  68. package/dist/llm/sanitization.d.ts +50 -0
  69. package/dist/llm/sanitization.d.ts.map +1 -0
  70. package/dist/llm/sanitization.js +149 -0
  71. package/dist/llm/sanitization.js.map +1 -0
  72. package/dist/{server.d.ts.map → mcp/server.d.ts.map} +1 -1
  73. package/dist/mcp/server.js +108 -0
  74. package/dist/mcp/server.js.map +1 -0
  75. package/dist/planning/planning-engine.d.ts +6 -0
  76. package/dist/planning/planning-engine.d.ts.map +1 -0
  77. package/dist/planning/planning-engine.js +17 -0
  78. package/dist/planning/planning-engine.js.map +1 -0
  79. package/dist/reasoning/reasoning-engine.d.ts +6 -0
  80. package/dist/reasoning/reasoning-engine.d.ts.map +1 -0
  81. package/dist/reasoning/reasoning-engine.js +17 -0
  82. package/dist/reasoning/reasoning-engine.js.map +1 -0
  83. package/dist/search/search-engine.d.ts +99 -0
  84. package/dist/search/search-engine.d.ts.map +1 -0
  85. package/dist/search/search-engine.js +271 -0
  86. package/dist/search/search-engine.js.map +1 -0
  87. package/dist/synthesis/synthesis-engine.d.ts +6 -0
  88. package/dist/synthesis/synthesis-engine.d.ts.map +1 -0
  89. package/dist/synthesis/synthesis-engine.js +17 -0
  90. package/dist/synthesis/synthesis-engine.js.map +1 -0
  91. package/dist/types/analysis.d.ts +1534 -49
  92. package/dist/types/analysis.d.ts.map +1 -1
  93. package/dist/types/analysis.js +250 -0
  94. package/dist/types/analysis.js.map +1 -1
  95. package/dist/types/core.d.ts +257 -30
  96. package/dist/types/core.d.ts.map +1 -1
  97. package/dist/types/core.js +148 -18
  98. package/dist/types/core.js.map +1 -1
  99. package/dist/types/creativity.d.ts +2871 -56
  100. package/dist/types/creativity.d.ts.map +1 -1
  101. package/dist/types/creativity.js +195 -0
  102. package/dist/types/creativity.js.map +1 -1
  103. package/dist/types/index.d.ts +6 -2
  104. package/dist/types/index.d.ts.map +1 -1
  105. package/dist/types/index.js +17 -2
  106. package/dist/types/index.js.map +1 -1
  107. package/dist/types/learning.d.ts +851 -61
  108. package/dist/types/learning.d.ts.map +1 -1
  109. package/dist/types/learning.js +155 -0
  110. package/dist/types/learning.js.map +1 -1
  111. package/dist/types/planning.d.ts +2223 -71
  112. package/dist/types/planning.d.ts.map +1 -1
  113. package/dist/types/planning.js +190 -0
  114. package/dist/types/planning.js.map +1 -1
  115. package/dist/types/reasoning.d.ts +2209 -72
  116. package/dist/types/reasoning.d.ts.map +1 -1
  117. package/dist/types/reasoning.js +200 -1
  118. package/dist/types/reasoning.js.map +1 -1
  119. package/dist/types/search.d.ts +981 -53
  120. package/dist/types/search.d.ts.map +1 -1
  121. package/dist/types/search.js +137 -0
  122. package/dist/types/search.js.map +1 -1
  123. package/dist/types/synthesis.d.ts +583 -38
  124. package/dist/types/synthesis.d.ts.map +1 -1
  125. package/dist/types/synthesis.js +138 -0
  126. package/dist/types/synthesis.js.map +1 -1
  127. package/dist/utils/cache.d.ts +144 -0
  128. package/dist/utils/cache.d.ts.map +1 -0
  129. package/dist/utils/cache.js +288 -0
  130. package/dist/utils/cache.js.map +1 -0
  131. package/dist/utils/id-generator.d.ts +89 -0
  132. package/dist/utils/id-generator.d.ts.map +1 -0
  133. package/dist/utils/id-generator.js +132 -0
  134. package/dist/utils/id-generator.js.map +1 -0
  135. package/dist/utils/index.d.ts +11 -0
  136. package/dist/utils/index.d.ts.map +1 -0
  137. package/dist/utils/index.js +33 -0
  138. package/dist/utils/index.js.map +1 -0
  139. package/dist/utils/logger.d.ts +142 -0
  140. package/dist/utils/logger.d.ts.map +1 -0
  141. package/dist/utils/logger.js +248 -0
  142. package/dist/utils/logger.js.map +1 -0
  143. package/dist/utils/metrics.d.ts +149 -0
  144. package/dist/utils/metrics.d.ts.map +1 -0
  145. package/dist/utils/metrics.js +296 -0
  146. package/dist/utils/metrics.js.map +1 -0
  147. package/dist/utils/timer.d.ts +7 -0
  148. package/dist/utils/timer.d.ts.map +1 -0
  149. package/dist/utils/timer.js +17 -0
  150. package/dist/utils/timer.js.map +1 -0
  151. package/dist/utils/validation.d.ts +147 -0
  152. package/dist/utils/validation.d.ts.map +1 -0
  153. package/dist/utils/validation.js +275 -0
  154. package/dist/utils/validation.js.map +1 -0
  155. package/docs/API.md +411 -0
  156. package/docs/ARCHITECTURE.md +271 -0
  157. package/docs/CHANGELOG.md +283 -0
  158. package/jest.config.js +28 -0
  159. package/package.json +43 -30
  160. package/src/analysis/analysis-engine.ts +383 -0
  161. package/src/core/config.ts +406 -0
  162. package/src/core/engine.ts +785 -0
  163. package/src/core/errors.ts +349 -0
  164. package/src/core/index.ts +12 -0
  165. package/src/core/pipeline.ts +424 -0
  166. package/src/core/rate-limiter.ts +155 -0
  167. package/src/core/session-manager.ts +269 -0
  168. package/src/creativity/creativity-engine.ts +14 -0
  169. package/src/index.ts +178 -0
  170. package/src/learning/learning-engine.ts +14 -0
  171. package/src/llm/index.ts +10 -0
  172. package/src/llm/llm-service.ts +285 -0
  173. package/src/llm/providers/base.ts +146 -0
  174. package/src/llm/providers/cli.ts +186 -0
  175. package/src/llm/providers/gemini.ts +201 -0
  176. package/src/llm/sanitization.ts +178 -0
  177. package/src/mcp/server.ts +117 -0
  178. package/src/planning/planning-engine.ts +14 -0
  179. package/src/reasoning/reasoning-engine.ts +14 -0
  180. package/src/search/search-engine.ts +333 -0
  181. package/src/synthesis/synthesis-engine.ts +14 -0
  182. package/src/types/analysis.ts +337 -0
  183. package/src/types/core.ts +342 -0
  184. package/src/types/creativity.ts +268 -0
  185. package/src/types/index.ts +31 -0
  186. package/src/types/learning.ts +215 -0
  187. package/src/types/planning.ts +251 -0
  188. package/src/types/reasoning.ts +288 -0
  189. package/src/types/search.ts +192 -0
  190. package/src/types/synthesis.ts +187 -0
  191. package/src/utils/cache.ts +363 -0
  192. package/src/utils/id-generator.ts +135 -0
  193. package/src/utils/index.ts +22 -0
  194. package/src/utils/logger.ts +290 -0
  195. package/src/utils/metrics.ts +380 -0
  196. package/src/utils/timer.ts +15 -0
  197. package/src/utils/validation.ts +297 -0
  198. package/tests/setup.ts +22 -0
  199. package/tests/unit/cache.test.ts +189 -0
  200. package/tests/unit/engine.test.ts +179 -0
  201. package/tests/unit/validation.test.ts +218 -0
  202. package/tsconfig.json +17 -12
  203. package/GEMINI.md +0 -68
  204. package/analysis.ts +0 -1063
  205. package/creativity.ts +0 -1055
  206. package/dist/analysis.d.ts +0 -54
  207. package/dist/analysis.d.ts.map +0 -1
  208. package/dist/analysis.js +0 -866
  209. package/dist/analysis.js.map +0 -1
  210. package/dist/creativity.d.ts +0 -81
  211. package/dist/creativity.d.ts.map +0 -1
  212. package/dist/creativity.js +0 -828
  213. package/dist/creativity.js.map +0 -1
  214. package/dist/engine.d.ts +0 -90
  215. package/dist/engine.d.ts.map +0 -1
  216. package/dist/engine.js +0 -720
  217. package/dist/engine.js.map +0 -1
  218. package/dist/examples.d.ts +0 -7
  219. package/dist/examples.d.ts.map +0 -1
  220. package/dist/examples.js +0 -506
  221. package/dist/examples.js.map +0 -1
  222. package/dist/learning.d.ts +0 -72
  223. package/dist/learning.d.ts.map +0 -1
  224. package/dist/learning.js +0 -615
  225. package/dist/learning.js.map +0 -1
  226. package/dist/llm-service.d.ts +0 -21
  227. package/dist/llm-service.d.ts.map +0 -1
  228. package/dist/llm-service.js +0 -100
  229. package/dist/llm-service.js.map +0 -1
  230. package/dist/planning.d.ts +0 -62
  231. package/dist/planning.d.ts.map +0 -1
  232. package/dist/planning.js +0 -886
  233. package/dist/planning.js.map +0 -1
  234. package/dist/reasoning.d.ts +0 -73
  235. package/dist/reasoning.d.ts.map +0 -1
  236. package/dist/reasoning.js +0 -845
  237. package/dist/reasoning.js.map +0 -1
  238. package/dist/search-discovery.d.ts +0 -73
  239. package/dist/search-discovery.d.ts.map +0 -1
  240. package/dist/search-discovery.js +0 -548
  241. package/dist/search-discovery.js.map +0 -1
  242. package/dist/server.js +0 -113
  243. package/dist/server.js.map +0 -1
  244. package/dist/types/engine.d.ts +0 -55
  245. package/dist/types/engine.d.ts.map +0 -1
  246. package/dist/types/engine.js +0 -3
  247. package/dist/types/engine.js.map +0 -1
  248. package/dist/types.d.ts +0 -6
  249. package/dist/types.d.ts.map +0 -1
  250. package/dist/types.js.map +0 -1
  251. package/engine.ts +0 -1009
  252. package/examples.ts +0 -717
  253. package/index.ts +0 -106
  254. package/learning.ts +0 -779
  255. package/llm-service.ts +0 -120
  256. package/planning.ts +0 -1101
  257. package/reasoning.ts +0 -1079
  258. package/search-discovery.ts +0 -700
  259. package/server.ts +0 -115
  260. package/types/analysis.ts +0 -69
  261. package/types/core.ts +0 -90
  262. package/types/creativity.ts +0 -72
  263. package/types/engine.ts +0 -60
  264. package/types/index.ts +0 -9
  265. package/types/learning.ts +0 -69
  266. package/types/planning.ts +0 -85
  267. package/types/reasoning.ts +0 -92
  268. package/types/search.ts +0 -58
  269. package/types/synthesis.ts +0 -43
  270. package/types.ts +0 -6
  271. /package/dist/{server.d.ts → mcp/server.d.ts} +0 -0
@@ -1,700 +0,0 @@
1
- /**
2
- * Search & Discovery Module
3
- * Real-time web search with multi-source aggregation and intelligent filtering
4
- */
5
-
6
- import {
7
- SearchQuery,
8
- SearchResult,
9
- SearchSession,
10
- SearchFilters,
11
- AggregatedResult,
12
- SourceType,
13
- ResultMetadata,
14
- ConfidenceLevel,
15
- ThinkingEvent,
16
- ThinkingError,
17
- ThinkingStage
18
- } from './types';
19
- import { EventEmitter } from 'events';
20
- import { llmService } from './llm-service';
21
-
22
- // ============================================================================
23
- // SEARCH PROVIDER INTERFACES
24
- // ============================================================================
25
-
26
- interface SearchProvider {
27
- name: string;
28
- search(query: string, filters: SearchFilters, maxResults: number): Promise<SearchResult[]>;
29
- getCredibilityScore(url: string): number;
30
- }
31
-
32
- // ============================================================================
33
- // WEB SEARCH PROVIDER IMPLEMENTATION
34
- // ============================================================================
35
-
36
- class WebSearchProvider implements SearchProvider {
37
- name = 'web_search';
38
-
39
- async search(
40
- query: string,
41
- filters: SearchFilters,
42
- maxResults: number
43
- ): Promise<SearchResult[]> {
44
- try {
45
- const results = await this.searchWithLLM(query, maxResults);
46
- if (results.length > 0) {
47
- return this.applyFilters(results, filters);
48
- }
49
- } catch (error) {
50
- console.warn('LLM search failed, falling back to simulation', error);
51
- }
52
-
53
- // In real implementation, this would call actual search APIs
54
- // For demonstration, we simulate search results
55
- const simulatedResults: SearchResult[] = [];
56
-
57
- // Generate diverse simulated results based on query
58
- const topics = this.extractTopics(query);
59
-
60
- for (let i = 0; i < maxResults; i++) {
61
- const topic = topics[i % topics.length];
62
- const result: SearchResult = {
63
- id: `web_${Date.now()}_${i}`,
64
- title: this.generateTitle(topic, i),
65
- url: `https://example.com/article/${topic.replace(/\s+/g, '-')}-${i}`,
66
- snippet: this.generateSnippet(topic, query),
67
- source: SourceType.WEB,
68
- credibility: this.calculateCredibility(i),
69
- relevance: this.calculateRelevance(query, topic, i),
70
- timestamp: new Date(),
71
- metadata: this.generateMetadata(topic)
72
- };
73
- simulatedResults.push(result);
74
- }
75
-
76
- return this.applyFilters(simulatedResults, filters);
77
- }
78
-
79
- private async searchWithLLM(query: string, maxResults: number): Promise<SearchResult[]> {
80
- const prompt = `
81
- Act as a search engine. Query: "${query}"
82
- Generate ${maxResults} relevant search results based on your knowledge.
83
-
84
- Return strictly JSON with an array of objects:
85
- [
86
- {
87
- "title": "string",
88
- "url": "https://... (invent a plausible URL)",
89
- "snippet": "string (1-2 sentences summarizing the content)",
90
- "credibility": number (0-1)
91
- }
92
- ]
93
- `;
94
-
95
- const response = await llmService.generateText({ prompt });
96
- const jsonMatch = response.match(/\[[\s\S]*\]/); // Match array
97
-
98
- if (jsonMatch) {
99
- const data = JSON.parse(jsonMatch[0]);
100
- return data.map((item: any, i: number) => ({
101
- id: `web_llm_${Date.now()}_${i}`,
102
- title: item.title,
103
- url: item.url,
104
- snippet: item.snippet,
105
- source: SourceType.WEB,
106
- credibility: item.credibility || 0.7,
107
- relevance: 0.9, // Assumed relevant
108
- timestamp: new Date(),
109
- metadata: { wordCount: 1000, citations: 10 }
110
- }));
111
- }
112
- return [];
113
- }
114
-
115
- getCredibilityScore(url: string): number {
116
- const credibleDomains = [
117
- 'edu', 'gov', 'ac.uk', 'ac.jp', 'arxiv.org',
118
- 'nature.com', 'science.org', 'ieee.org', 'acm.org'
119
- ];
120
-
121
- const lowCredibilityDomains = [
122
- 'blogspot', 'wordpress', 'medium', 'wix', 'weebly'
123
- ];
124
-
125
- if (credibleDomains.some(d => url.includes(d))) return 0.9;
126
- if (lowCredibilityDomains.some(d => url.includes(d))) return 0.4;
127
- return 0.6;
128
- }
129
-
130
- private extractTopics(query: string): string[] {
131
- // Simple topic extraction - in real implementation, use NLP
132
- const commonWords = ['what', 'how', 'why', 'when', 'where', 'who', 'is', 'are', 'the', 'a', 'an'];
133
- return query
134
- .toLowerCase()
135
- .split(/\s+/)
136
- .filter(word => !commonWords.includes(word) && word.length > 3);
137
- }
138
-
139
- private generateTitle(topic: string, index: number): string {
140
- const templates = [
141
- `Complete Guide to ${topic}`,
142
- `${topic}: Everything You Need to Know`,
143
- `Understanding ${topic} in Depth`,
144
- `The Future of ${topic}`,
145
- `${topic} Best Practices and Strategies`,
146
- `Advanced ${topic} Techniques`,
147
- `${topic} Case Studies and Examples`,
148
- `Breaking Down ${topic}: A Comprehensive Analysis`
149
- ];
150
- return templates[index % templates.length];
151
- }
152
-
153
- private generateSnippet(topic: string, query: string): string {
154
- return `This comprehensive resource about ${topic} provides detailed insights related to "${query}". ` +
155
- `It covers key concepts, practical applications, and expert perspectives on the subject matter.`;
156
- }
157
-
158
- private calculateCredibility(index: number): number {
159
- // Higher ranked results typically have higher credibility
160
- return Math.max(0.3, 0.95 - (index * 0.05));
161
- }
162
-
163
- private calculateRelevance(query: string, topic: string, index: number): number {
164
- const queryWords = query.toLowerCase().split(/\s+/);
165
- const topicWords = topic.toLowerCase().split(/\s+/);
166
- const matchCount = topicWords.filter(w => queryWords.includes(w)).length;
167
- const baseRelevance = matchCount / Math.max(queryWords.length, topicWords.length);
168
- return Math.min(0.95, baseRelevance + (0.9 - index * 0.1));
169
- }
170
-
171
- private generateMetadata(topic: string): ResultMetadata {
172
- return {
173
- author: `Expert on ${topic}`,
174
- publishDate: new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000),
175
- wordCount: Math.floor(1000 + Math.random() * 4000),
176
- readingTime: Math.floor(5 + Math.random() * 20),
177
- relatedTopics: [topic, 'related-concept-1', 'related-concept-2'],
178
- citations: Math.floor(Math.random() * 50)
179
- };
180
- }
181
-
182
- private applyFilters(results: SearchResult[], filters: SearchFilters): SearchResult[] {
183
- return results.filter(result => {
184
- if (filters.minCredibility && result.credibility < filters.minCredibility) {
185
- return false;
186
- }
187
- if (filters.domains && filters.domains.length > 0) {
188
- const domainMatch = filters.domains.some(d => result.url.includes(d));
189
- if (!domainMatch) return false;
190
- }
191
- if (filters.excludeDomains) {
192
- const excluded = filters.excludeDomains.some(d => result.url.includes(d));
193
- if (excluded) return false;
194
- }
195
- return true;
196
- });
197
- }
198
- }
199
-
200
- // ============================================================================
201
- // KNOWLEDGE BASE SEARCH PROVIDER
202
- // ============================================================================
203
-
204
- class KnowledgeBaseProvider implements SearchProvider {
205
- name = 'knowledge_base';
206
- private knowledgeStore: Map<string, unknown> = new Map();
207
-
208
- async search(
209
- query: string,
210
- filters: SearchFilters,
211
- maxResults: number
212
- ): Promise<SearchResult[]> {
213
- const results: SearchResult[] = [];
214
- const queryLower = query.toLowerCase();
215
-
216
- // Search through stored knowledge
217
- for (const [key, value] of this.knowledgeStore.entries()) {
218
- if (key.toLowerCase().includes(queryLower)) {
219
- results.push({
220
- id: `kb_${key}`,
221
- title: key,
222
- url: `knowledge://${key}`,
223
- snippet: JSON.stringify(value).substring(0, 200),
224
- source: SourceType.KNOWLEDGE_BASE,
225
- credibility: 0.95,
226
- relevance: 0.9,
227
- timestamp: new Date(),
228
- metadata: { wordCount: JSON.stringify(value).length }
229
- });
230
- }
231
- if (results.length >= maxResults) break;
232
- }
233
-
234
- return results;
235
- }
236
-
237
- getCredibilityScore(): number {
238
- return 0.95; // Knowledge base has high credibility
239
- }
240
-
241
- addKnowledge(key: string, value: unknown): void {
242
- this.knowledgeStore.set(key, value);
243
- }
244
-
245
- getKnowledge(key: string): unknown {
246
- return this.knowledgeStore.get(key);
247
- }
248
- }
249
-
250
- // ============================================================================
251
- // CACHE SEARCH PROVIDER
252
- // ============================================================================
253
-
254
- class CacheProvider implements SearchProvider {
255
- name = 'cache';
256
- private cache: Map<string, { result: SearchResult; timestamp: number; ttl: number }> = new Map();
257
- private defaultTTL = 3600000; // 1 hour
258
-
259
- async search(
260
- query: string,
261
- _filters: SearchFilters,
262
- maxResults: number
263
- ): Promise<SearchResult[]> {
264
- const results: SearchResult[] = [];
265
- const now = Date.now();
266
-
267
- for (const [key, cached] of this.cache.entries()) {
268
- if (key.includes(query) && now - cached.timestamp < cached.ttl) {
269
- results.push(cached.result);
270
- }
271
- if (results.length >= maxResults) break;
272
- }
273
-
274
- return results;
275
- }
276
-
277
- getCredibilityScore(): number {
278
- return 0.8;
279
- }
280
-
281
- cacheResult(query: string, result: SearchResult, ttl?: number): void {
282
- this.cache.set(query, {
283
- result,
284
- timestamp: Date.now(),
285
- ttl: ttl || this.defaultTTL
286
- });
287
- }
288
-
289
- invalidate(query: string): void {
290
- this.cache.delete(query);
291
- }
292
-
293
- clear(): void {
294
- this.cache.clear();
295
- }
296
- }
297
-
298
- // ============================================================================
299
- // MAIN SEARCH & DISCOVERY ENGINE
300
- // ============================================================================
301
-
302
- export class SearchDiscoveryEngine extends EventEmitter {
303
- private providers: Map<SourceType, SearchProvider> = new Map();
304
- private sessions: Map<string, SearchSession> = new Map();
305
- private knowledgeBase: KnowledgeBaseProvider;
306
- private cache: CacheProvider;
307
-
308
- constructor() {
309
- super();
310
- this.knowledgeBase = new KnowledgeBaseProvider();
311
- this.cache = new CacheProvider();
312
- this.registerDefaultProviders();
313
- }
314
-
315
- private registerDefaultProviders(): void {
316
- this.providers.set(SourceType.WEB, new WebSearchProvider());
317
- this.providers.set(SourceType.KNOWLEDGE_BASE, this.knowledgeBase);
318
- this.providers.set(SourceType.CACHE, this.cache);
319
- }
320
-
321
- /**
322
- * Execute a search query across multiple sources
323
- */
324
- async search(
325
- query: string,
326
- options: {
327
- sources?: SourceType[];
328
- filters?: SearchFilters;
329
- maxResults?: number;
330
- timeout?: number;
331
- } = {}
332
- ): Promise<SearchResult[]> {
333
- const {
334
- sources = [SourceType.WEB, SourceType.KNOWLEDGE_BASE, SourceType.CACHE],
335
- filters = {},
336
- maxResults = 10,
337
- timeout = 30000
338
- } = options;
339
-
340
- const searchId = this.generateId();
341
- const startTime = Date.now();
342
-
343
- this.emit('search_start', {
344
- id: searchId,
345
- type: 'stage_start',
346
- stage: ThinkingStage.SEARCH,
347
- timestamp: new Date(),
348
- data: { query, sources },
349
- sessionId: searchId
350
- } as ThinkingEvent);
351
-
352
- try {
353
- // Check cache first
354
- const cachedResults = await this.searchWithProvider(
355
- SourceType.CACHE,
356
- query,
357
- filters,
358
- maxResults
359
- );
360
-
361
- if (cachedResults.length > 0) {
362
- this.emit('search_complete', {
363
- id: searchId,
364
- type: 'search_result',
365
- stage: ThinkingStage.SEARCH,
366
- timestamp: new Date(),
367
- data: { results: cachedResults, fromCache: true },
368
- sessionId: searchId
369
- } as ThinkingEvent);
370
- return cachedResults;
371
- }
372
-
373
- // Execute searches across all specified sources in parallel
374
- const searchPromises = sources
375
- .filter(s => s !== SourceType.CACHE) // Already checked cache
376
- .map(source => this.searchWithProvider(source, query, filters, maxResults));
377
-
378
- const resultsArrays = await Promise.allSettled(searchPromises);
379
-
380
- let allResults: SearchResult[] = [];
381
- resultsArrays.forEach((result, index) => {
382
- if (result.status === 'fulfilled') {
383
- allResults = allResults.concat(result.value);
384
- } else {
385
- console.warn(`Search from ${sources[index]} failed:`, result.reason);
386
- }
387
- });
388
-
389
- // Rank and filter results
390
- const rankedResults = this.rankResults(allResults, query).slice(0, maxResults);
391
-
392
- // Cache top results
393
- rankedResults.forEach(result => {
394
- this.cache.cacheResult(query, result);
395
- });
396
-
397
- const processingTime = Date.now() - startTime;
398
-
399
- this.emit('search_complete', {
400
- id: searchId,
401
- type: 'search_result',
402
- stage: ThinkingStage.SEARCH,
403
- timestamp: new Date(),
404
- data: {
405
- results: rankedResults,
406
- fromCache: false,
407
- processingTime,
408
- sourcesQueried: sources.length
409
- },
410
- sessionId: searchId
411
- } as ThinkingEvent);
412
-
413
- return rankedResults;
414
-
415
- } catch (error) {
416
- this.emit('search_error', {
417
- id: searchId,
418
- type: 'stage_error',
419
- stage: ThinkingStage.SEARCH,
420
- timestamp: new Date(),
421
- data: { error },
422
- sessionId: searchId
423
- } as ThinkingEvent);
424
-
425
- throw new ThinkingError(
426
- `Search failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
427
- ThinkingStage.SEARCH,
428
- true,
429
- error instanceof Error ? error : undefined
430
- );
431
- }
432
- }
433
-
434
- /**
435
- * Multi-query search for comprehensive coverage
436
- */
437
- async multiSearch(
438
- queries: string[],
439
- options: {
440
- sources?: SourceType[];
441
- filters?: SearchFilters;
442
- maxResultsPerQuery?: number;
443
- aggregate?: boolean;
444
- } = {}
445
- ): Promise<SearchResult[] | AggregatedResult[]> {
446
- const { aggregate = true, maxResultsPerQuery = 5 } = options;
447
-
448
- const sessionId = this.generateId();
449
- const session: SearchSession = {
450
- id: sessionId,
451
- queries: [],
452
- results: [],
453
- aggregatedResults: [],
454
- startTime: new Date()
455
- };
456
-
457
- this.sessions.set(sessionId, session);
458
-
459
- // Execute all queries
460
- const searchPromises = queries.map(async (query) => {
461
- const results = await this.search(query, {
462
- ...options,
463
- maxResults: maxResultsPerQuery
464
- });
465
- return { query, results };
466
- });
467
-
468
- const searchResults = await Promise.all(searchPromises);
469
-
470
- // Collect all results
471
- searchResults.forEach(({ query, results }) => {
472
- session.queries.push({
473
- id: this.generateId(),
474
- query,
475
- sources: options.sources || [SourceType.WEB],
476
- filters: options.filters || {},
477
- maxResults: maxResultsPerQuery,
478
- timeout: 30000,
479
- timestamp: new Date()
480
- });
481
- session.results.push(...results);
482
- });
483
-
484
- if (aggregate) {
485
- session.aggregatedResults = this.aggregateResults(session.results);
486
- return session.aggregatedResults;
487
- }
488
-
489
- return session.results;
490
- }
491
-
492
- /**
493
- * Aggregate results by topic and identify consensus/conflicts
494
- */
495
- aggregateResults(results: SearchResult[]): AggregatedResult[] {
496
- const topicMap = new Map<string, SearchResult[]>();
497
-
498
- // Group by topic (simplified - in real implementation use NLP clustering)
499
- results.forEach(result => {
500
- const topic = this.extractMainTopic(result.title);
501
- if (!topicMap.has(topic)) {
502
- topicMap.set(topic, []);
503
- }
504
- topicMap.get(topic)!.push(result);
505
- });
506
-
507
- const aggregated: AggregatedResult[] = [];
508
-
509
- topicMap.forEach((topicResults, topic) => {
510
- // Calculate consensus score
511
- const avgCredibility = topicResults.reduce((sum, r) => sum + r.credibility, 0) / topicResults.length;
512
- const avgRelevance = topicResults.reduce((sum, r) => sum + r.relevance, 0) / topicResults.length;
513
- const consensusScore = (avgCredibility + avgRelevance) / 2;
514
-
515
- // Check for conflicting information
516
- const conflictingInfo = this.detectConflicts(topicResults);
517
-
518
- // Extract key insights
519
- const keyInsights = this.extractKeyInsights(topicResults);
520
-
521
- aggregated.push({
522
- topic,
523
- results: topicResults,
524
- consensusScore,
525
- conflictingInfo,
526
- keyInsights
527
- });
528
- });
529
-
530
- // Sort by consensus score
531
- return aggregated.sort((a, b) => b.consensusScore - a.consensusScore);
532
- }
533
-
534
- /**
535
- * Rank results based on multiple factors
536
- */
537
- private rankResults(results: SearchResult[], query: string): SearchResult[] {
538
- return results
539
- .map(result => ({
540
- ...result,
541
- // Calculate composite score
542
- compositeScore: this.calculateCompositeScore(result, query)
543
- }))
544
- .sort((a, b) => (b as any).compositeScore - (a as any).compositeScore);
545
- }
546
-
547
- private calculateCompositeScore(result: SearchResult, query: string): number {
548
- const relevanceWeight = 0.4;
549
- const credibilityWeight = 0.3;
550
- const freshnessWeight = 0.15;
551
- const engagementWeight = 0.15;
552
-
553
- // Relevance score
554
- const relevanceScore = result.relevance;
555
-
556
- // Credibility score
557
- const credibilityScore = result.credibility;
558
-
559
- // Freshness score (newer is better)
560
- const ageInDays = (Date.now() - result.timestamp.getTime()) / (1000 * 60 * 60 * 24);
561
- const freshnessScore = Math.max(0, 1 - ageInDays / 365);
562
-
563
- // Engagement score (based on citations, reading time)
564
- const engagementScore = Math.min(1, (result.metadata.citations || 0) / 100);
565
-
566
- return (
567
- relevanceScore * relevanceWeight +
568
- credibilityScore * credibilityWeight +
569
- freshnessScore * freshnessWeight +
570
- engagementScore * engagementWeight
571
- );
572
- }
573
-
574
- /**
575
- * Search with a specific provider
576
- */
577
- private async searchWithProvider(
578
- source: SourceType,
579
- query: string,
580
- filters: SearchFilters,
581
- maxResults: number
582
- ): Promise<SearchResult[]> {
583
- const provider = this.providers.get(source);
584
- if (!provider) {
585
- throw new Error(`No provider registered for source: ${source}`);
586
- }
587
- return provider.search(query, filters, maxResults);
588
- }
589
-
590
- /**
591
- * Add custom search provider
592
- */
593
- registerProvider(source: SourceType, provider: SearchProvider): void {
594
- this.providers.set(source, provider);
595
- }
596
-
597
- /**
598
- * Add knowledge to knowledge base
599
- */
600
- addKnowledge(key: string, value: unknown): void {
601
- this.knowledgeBase.addKnowledge(key, value);
602
- }
603
-
604
- /**
605
- * Get search session by ID
606
- */
607
- getSession(sessionId: string): SearchSession | undefined {
608
- return this.sessions.get(sessionId);
609
- }
610
-
611
- /**
612
- * Clear all sessions
613
- */
614
- clearSessions(): void {
615
- this.sessions.clear();
616
- }
617
-
618
- // Helper methods
619
- private generateId(): string {
620
- return `search_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
621
- }
622
-
623
- private extractMainTopic(title: string): string {
624
- // Simplified topic extraction
625
- const words = title.toLowerCase().split(/\s+/);
626
- const significantWords = words.filter(w => w.length > 4);
627
- return significantWords.slice(0, 3).join(' ') || 'general';
628
- }
629
-
630
- private detectConflicts(results: SearchResult[]): boolean {
631
- // Simplified conflict detection
632
- // In real implementation, use NLP to compare content
633
- const snippets = results.map(r => r.snippet.toLowerCase());
634
- const contradictoryTerms = ['not', 'never', 'false', 'incorrect', 'myth'];
635
-
636
- return snippets.some(snippet =>
637
- contradictoryTerms.some(term => snippet.includes(term))
638
- );
639
- }
640
-
641
- private extractKeyInsights(results: SearchResult[]): string[] {
642
- // Simplified insight extraction
643
- const insights: string[] = [];
644
- const seenTopics = new Set<string>();
645
-
646
- results.forEach(result => {
647
- const topic = this.extractMainTopic(result.title);
648
- if (!seenTopics.has(topic)) {
649
- seenTopics.add(topic);
650
- insights.push(`${topic}: ${result.snippet.substring(0, 100)}...`);
651
- }
652
- });
653
-
654
- return insights.slice(0, 5);
655
- }
656
- }
657
-
658
- // ============================================================================
659
- // EXPORT SINGLETON INSTANCE
660
- // ============================================================================
661
-
662
- export const searchEngine = new SearchDiscoveryEngine();
663
-
664
- // ============================================================================
665
- // EXAMPLE USAGE
666
- // ============================================================================
667
-
668
- /*
669
- // Basic search
670
- const results = await searchEngine.search('artificial intelligence trends 2024', {
671
- sources: [SourceType.WEB, SourceType.KNOWLEDGE_BASE],
672
- maxResults: 10,
673
- filters: {
674
- minCredibility: 0.7,
675
- language: 'en'
676
- }
677
- });
678
-
679
- // Multi-query search with aggregation
680
- const aggregatedResults = await searchEngine.multiSearch([
681
- 'AI in healthcare',
682
- 'machine learning medical applications',
683
- 'healthcare automation technology'
684
- ], {
685
- aggregate: true,
686
- maxResultsPerQuery: 5
687
- }) as AggregatedResult[];
688
-
689
- // Add custom knowledge
690
- searchEngine.addKnowledge('AI Definition', {
691
- term: 'Artificial Intelligence',
692
- definition: 'The simulation of human intelligence by machines',
693
- categories: ['technology', 'computer science']
694
- });
695
-
696
- // Listen to events
697
- searchEngine.on('search_complete', (event) => {
698
- console.log(`Search completed in ${event.data.processingTime}ms`);
699
- });
700
- */