gthinking 1.3.0 → 2.1.2

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 +248 -246
  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 +323 -0
  7. package/dist/analysis/analysis-engine.js.map +1 -0
  8. package/dist/core/config.d.ts +1423 -0
  9. package/dist/core/config.d.ts.map +1 -0
  10. package/dist/core/config.js +445 -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 +384 -0
  161. package/src/core/config.ts +462 -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
package/dist/analysis.js DELETED
@@ -1,866 +0,0 @@
1
- "use strict";
2
- /**
3
- * Analysis Module
4
- * Deep content analysis with multi-dimensional insights extraction
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.analysisEngine = exports.AnalysisEngine = void 0;
8
- const types_1 = require("./types");
9
- const events_1 = require("events");
10
- const llm_service_1 = require("./llm-service");
11
- class SentimentAnalyzer {
12
- constructor() {
13
- this.positiveWords = new Set([
14
- 'excellent', 'great', 'amazing', 'wonderful', 'fantastic', 'good', 'best',
15
- 'love', 'like', 'happy', 'success', 'benefit', 'advantage', 'improve',
16
- 'progress', 'achieve', 'win', 'positive', 'effective', 'efficient'
17
- ]);
18
- this.negativeWords = new Set([
19
- 'bad', 'terrible', 'awful', 'worst', 'hate', 'dislike', 'sad', 'fail',
20
- 'problem', 'issue', 'disadvantage', 'worse', 'decline', 'lose', 'negative',
21
- 'ineffective', 'inefficient', 'difficult', 'challenging', 'concern'
22
- ]);
23
- }
24
- analyze(text) {
25
- const words = text.toLowerCase().match(/\b\w+\b/g) || [];
26
- let positive = 0;
27
- let negative = 0;
28
- let neutral = 0;
29
- words.forEach(word => {
30
- if (this.positiveWords.has(word))
31
- positive++;
32
- else if (this.negativeWords.has(word))
33
- negative++;
34
- else
35
- neutral++;
36
- });
37
- const total = words.length || 1;
38
- const compound = (positive - negative) / total;
39
- return {
40
- positive: positive / total,
41
- negative: negative / total,
42
- neutral: neutral / total,
43
- compound
44
- };
45
- }
46
- getSentimentLabel(score) {
47
- if (score.compound > 0.5)
48
- return 'very_positive';
49
- if (score.compound > 0.1)
50
- return 'positive';
51
- if (score.compound < -0.5)
52
- return 'very_negative';
53
- if (score.compound < -0.1)
54
- return 'negative';
55
- return 'neutral';
56
- }
57
- }
58
- class EntityExtractor {
59
- constructor() {
60
- this.entityPatterns = new Map([
61
- ['person', [/\b[A-Z][a-z]+ [A-Z][a-z]+\b/g, /\b(Mr|Mrs|Ms|Dr|Prof)\.? [A-Z][a-z]+\b/g]],
62
- ['organization', [/\b[A-Z][a-z]* (Inc|Corp|Ltd|LLC|Company|Organization)\b/g]],
63
- ['location', [/\b(in|at|from) ([A-Z][a-z]+( [A-Z][a-z]+)?)\b/g]],
64
- ['product', [/\b[A-Z][a-z]*[0-9]+\b/g, /\b(the|a|an) ([A-Z][a-z]+ (Pro|Max|Ultra|Plus))\b/gi]]
65
- ]);
66
- }
67
- extract(text) {
68
- const entities = new Map();
69
- const words = text.split(/\s+/);
70
- // Simple entity extraction based on patterns and capitalization
71
- words.forEach((word, index) => {
72
- // Check for capitalized words (potential proper nouns)
73
- if (/^[A-Z][a-z]+$/.test(word) && word.length > 2) {
74
- const context = words.slice(Math.max(0, index - 3), index + 4).join(' ');
75
- const type = this.classifyEntity(word, context);
76
- if (entities.has(word)) {
77
- const existing = entities.get(word);
78
- existing.mentions++;
79
- existing.confidence = Math.min(0.95, existing.confidence + 0.1);
80
- }
81
- else {
82
- entities.set(word, {
83
- name: word,
84
- type,
85
- confidence: 0.6,
86
- mentions: 1
87
- });
88
- }
89
- }
90
- });
91
- return Array.from(entities.values()).sort((a, b) => b.mentions - a.mentions);
92
- }
93
- classifyEntity(word, context) {
94
- const contextLower = context.toLowerCase();
95
- if (/\b(said|stated|announced|CEO|founder|president)\b/i.test(contextLower)) {
96
- return 'person';
97
- }
98
- if (/\b(company|organization|firm|corporation)\b/i.test(contextLower)) {
99
- return 'organization';
100
- }
101
- if (/\b(in|at|from|located|city|country|region)\b/i.test(contextLower)) {
102
- return 'location';
103
- }
104
- if (/\b(product|launched|released|device|software)\b/i.test(contextLower)) {
105
- return 'product';
106
- }
107
- if (/\b(event|conference|meeting|summit|festival)\b/i.test(contextLower)) {
108
- return 'event';
109
- }
110
- return 'concept';
111
- }
112
- }
113
- class TopicExtractor {
114
- constructor() {
115
- this.stopWords = new Set([
116
- 'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been', 'being',
117
- 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could',
118
- 'should', 'may', 'might', 'must', 'can', 'this', 'that', 'these', 'those'
119
- ]);
120
- }
121
- extract(text) {
122
- const words = text.toLowerCase().match(/\b\w{4,}\b/g) || [];
123
- const wordFreq = new Map();
124
- // Calculate word frequencies
125
- words.forEach(word => {
126
- if (!this.stopWords.has(word)) {
127
- wordFreq.set(word, (wordFreq.get(word) || 0) + 1);
128
- }
129
- });
130
- // Group related words into topics
131
- const topics = [];
132
- const sortedWords = Array.from(wordFreq.entries())
133
- .sort((a, b) => b[1] - a[1])
134
- .slice(0, 20);
135
- // Simple topic clustering
136
- const usedWords = new Set();
137
- sortedWords.forEach(([word, freq]) => {
138
- if (!usedWords.has(word)) {
139
- const relatedWords = this.findRelatedWords(word, sortedWords, usedWords);
140
- topics.push({
141
- name: word,
142
- relevance: freq / words.length,
143
- keywords: [word, ...relatedWords],
144
- subtopics: relatedWords.slice(0, 3)
145
- });
146
- usedWords.add(word);
147
- relatedWords.forEach(w => usedWords.add(w));
148
- }
149
- });
150
- return topics.slice(0, 5);
151
- }
152
- findRelatedWords(mainWord, allWords, usedWords) {
153
- const related = [];
154
- const mainPrefix = mainWord.substring(0, 3);
155
- allWords.forEach(([word, _]) => {
156
- if (word !== mainWord && !usedWords.has(word)) {
157
- // Check for semantic similarity (simplified)
158
- if (word.startsWith(mainPrefix) || mainWord.startsWith(word.substring(0, 3))) {
159
- related.push(word);
160
- }
161
- }
162
- });
163
- return related.slice(0, 5);
164
- }
165
- }
166
- class KeywordExtractor {
167
- constructor() {
168
- this.documentFrequency = new Map();
169
- this.totalDocuments = 0;
170
- }
171
- extract(text, corpus) {
172
- const words = text.toLowerCase().match(/\b\w{3,}\b/g) || [];
173
- const wordFreq = new Map();
174
- words.forEach(word => {
175
- wordFreq.set(word, (wordFreq.get(word) || 0) + 1);
176
- });
177
- // Calculate TF-IDF if corpus is provided
178
- const keywords = [];
179
- wordFreq.forEach((freq, word) => {
180
- const tf = freq / words.length;
181
- const idf = corpus ? this.calculateIDF(word, corpus) : 1;
182
- keywords.push({
183
- term: word,
184
- frequency: freq,
185
- importance: tf * (1 + Math.log(1 + freq)),
186
- tfidf: tf * idf
187
- });
188
- });
189
- return keywords
190
- .sort((a, b) => b.importance - a.importance)
191
- .slice(0, 15);
192
- }
193
- calculateIDF(word, corpus) {
194
- const docsWithWord = corpus.filter(doc => doc.toLowerCase().includes(word)).length;
195
- return Math.log(corpus.length / (1 + docsWithWord));
196
- }
197
- }
198
- // ============================================================================
199
- // SUMMARIZER
200
- // ============================================================================
201
- class Summarizer {
202
- summarize(text, maxLength = 200) {
203
- const sentences = this.splitIntoSentences(text);
204
- if (sentences.length <= 3) {
205
- return text;
206
- }
207
- // Score sentences based on importance
208
- const sentenceScores = sentences.map((sentence, index) => ({
209
- sentence,
210
- index,
211
- score: this.scoreSentence(sentence, text, index, sentences.length)
212
- }));
213
- // Select top sentences
214
- const topSentences = sentenceScores
215
- .sort((a, b) => b.score - a.score)
216
- .slice(0, Math.ceil(sentences.length * 0.3))
217
- .sort((a, b) => a.index - b.index);
218
- const summary = topSentences.map(s => s.sentence).join(' ');
219
- return summary.length > maxLength
220
- ? summary.substring(0, maxLength - 3) + '...'
221
- : summary;
222
- }
223
- splitIntoSentences(text) {
224
- return text
225
- .replace(/([.!?])\s+/g, "$1|")
226
- .split("|")
227
- .filter(s => s.trim().length > 10);
228
- }
229
- scoreSentence(sentence, fullText, index, total) {
230
- let score = 0;
231
- // Position score (first and last sentences are often important)
232
- if (index === 0 || index === total - 1)
233
- score += 2;
234
- if (index === 1 || index === total - 2)
235
- score += 1;
236
- // Length score (avoid very short or very long sentences)
237
- const wordCount = sentence.split(/\s+/).length;
238
- if (wordCount >= 8 && wordCount <= 25)
239
- score += 1;
240
- // Keyword density score
241
- const words = sentence.toLowerCase().match(/\b\w+\b/g) || [];
242
- const importantWords = words.filter(w => w.length > 5);
243
- score += importantWords.length / words.length;
244
- // Presence of numerical data
245
- if (/\d+/.test(sentence))
246
- score += 0.5;
247
- return score;
248
- }
249
- }
250
- // ============================================================================
251
- // FACT CHECKER
252
- // ============================================================================
253
- class FactChecker {
254
- constructor() {
255
- this.knownFacts = new Map();
256
- }
257
- async checkClaim(claim, sources) {
258
- // Normalize the claim
259
- const normalizedClaim = claim.toLowerCase().trim();
260
- // Check against known facts
261
- if (this.knownFacts.has(normalizedClaim)) {
262
- const fact = this.knownFacts.get(normalizedClaim);
263
- return {
264
- claim,
265
- verdict: fact.value ? 'true' : 'false',
266
- confidence: fact.confidence,
267
- sources: [],
268
- explanation: 'Based on verified knowledge base'
269
- };
270
- }
271
- // Analyze sources for verification
272
- const sourceAnalysis = this.analyzeSources(sources, claim);
273
- // Determine verdict based on source analysis
274
- let verdict;
275
- let confidence = sourceAnalysis.agreement;
276
- if (sourceAnalysis.supporting > sourceAnalysis.contradicting * 2) {
277
- verdict = 'true';
278
- }
279
- else if (sourceAnalysis.contradicting > sourceAnalysis.supporting * 2) {
280
- verdict = 'false';
281
- }
282
- else if (sourceAnalysis.supporting > 0 || sourceAnalysis.contradicting > 0) {
283
- verdict = 'partially_true';
284
- confidence *= 0.7;
285
- }
286
- else {
287
- verdict = 'unverifiable';
288
- confidence = 0.3;
289
- }
290
- return {
291
- claim,
292
- verdict,
293
- confidence,
294
- sources: sourceAnalysis.relevantSources,
295
- explanation: this.generateExplanation(verdict, sourceAnalysis),
296
- corrections: sourceAnalysis.corrections
297
- };
298
- }
299
- analyzeSources(sources, claim) {
300
- const claimWords = claim.toLowerCase().split(/\s+/);
301
- let supporting = 0;
302
- let contradicting = 0;
303
- let neutral = 0;
304
- const relevantSources = [];
305
- const corrections = [];
306
- sources.forEach(source => {
307
- const content = (source.title + ' ' + source.snippet).toLowerCase();
308
- const relevance = claimWords.filter(w => content.includes(w)).length / claimWords.length;
309
- if (relevance > 0.5) {
310
- relevantSources.push(source);
311
- // Check for supporting/contradicting indicators
312
- if (this.isSupporting(content, claim)) {
313
- supporting++;
314
- }
315
- else if (this.isContradicting(content, claim)) {
316
- contradicting++;
317
- const correction = this.extractCorrection(content, claim);
318
- if (correction)
319
- corrections.push(correction);
320
- }
321
- else {
322
- neutral++;
323
- }
324
- }
325
- });
326
- const total = supporting + contradicting + neutral || 1;
327
- const agreement = Math.max(supporting, contradicting) / total;
328
- return { supporting, contradicting, neutral, agreement, relevantSources, corrections };
329
- }
330
- isSupporting(content, _claim) {
331
- const positiveIndicators = ['confirmed', 'true', 'correct', 'yes', 'indeed', 'verified'];
332
- return positiveIndicators.some(ind => content.includes(ind));
333
- }
334
- isContradicting(content, _claim) {
335
- const negativeIndicators = ['false', 'incorrect', 'not true', 'myth', 'misleading', 'wrong'];
336
- return negativeIndicators.some(ind => content.includes(ind));
337
- }
338
- extractCorrection(content, _claim) {
339
- // Extract potential correction from content
340
- const correctionMatch = content.match(/(?:actually|in fact|correctly|the truth is)[^.]+/i);
341
- return correctionMatch ? correctionMatch[0].trim() : undefined;
342
- }
343
- generateExplanation(verdict, analysis) {
344
- switch (verdict) {
345
- case 'true':
346
- return `Supported by ${analysis.supporting} reliable sources with high agreement.`;
347
- case 'false':
348
- return `Contradicted by ${analysis.contradicting} sources. ${analysis.corrections.length > 0 ? 'Corrections found.' : ''}`;
349
- case 'partially_true':
350
- return `Mixed evidence: ${analysis.supporting} supporting, ${analysis.contradicting} contradicting sources.`;
351
- case 'unverifiable':
352
- return 'Insufficient reliable sources to verify this claim.';
353
- default:
354
- return 'Unable to determine veracity.';
355
- }
356
- }
357
- addFact(claim, value, confidence) {
358
- this.knownFacts.set(claim.toLowerCase().trim(), { value, confidence });
359
- }
360
- }
361
- // ============================================================================
362
- // COMPARISON ENGINE
363
- // ============================================================================
364
- class ComparisonEngine {
365
- compare(subjects, contents) {
366
- const similarities = [];
367
- const differences = [];
368
- // Extract features from each subject
369
- const features = subjects.map((subject, index) => ({
370
- subject,
371
- content: contents[index],
372
- entities: this.extractEntities(contents[index]),
373
- topics: this.extractTopics(contents[index]),
374
- keywords: this.extractKeywords(contents[index]),
375
- sentiment: this.analyzeSentiment(contents[index])
376
- }));
377
- // Compare features
378
- const aspects = ['entities', 'topics', 'keywords', 'sentiment'];
379
- aspects.forEach(aspect => {
380
- const values = {};
381
- features.forEach(f => {
382
- values[f.subject] = f[aspect];
383
- });
384
- const similarity = this.calculateSimilarity(values);
385
- if (similarity > 0.6) {
386
- similarities.push({
387
- aspect,
388
- values,
389
- significance: similarity
390
- });
391
- }
392
- else {
393
- differences.push({
394
- aspect,
395
- values,
396
- significance: 1 - similarity
397
- });
398
- }
399
- });
400
- // Generate conclusion
401
- const conclusion = this.generateComparisonConclusion(subjects, similarities, differences);
402
- const confidence = similarities.length / (similarities.length + differences.length);
403
- return {
404
- id: `comparison_${Date.now()}`,
405
- subjects,
406
- similarities,
407
- differences,
408
- conclusion,
409
- confidence
410
- };
411
- }
412
- extractEntities(text) {
413
- const words = text.match(/\b[A-Z][a-z]+\b/g) || [];
414
- return [...new Set(words)];
415
- }
416
- extractTopics(text) {
417
- const words = text.toLowerCase().match(/\b\w{5,}\b/g) || [];
418
- const freq = new Map();
419
- words.forEach(w => freq.set(w, (freq.get(w) || 0) + 1));
420
- return Array.from(freq.entries())
421
- .sort((a, b) => b[1] - a[1])
422
- .slice(0, 5)
423
- .map(([w]) => w);
424
- }
425
- extractKeywords(text) {
426
- return this.extractTopics(text).slice(0, 10);
427
- }
428
- analyzeSentiment(text) {
429
- const positive = /\b(good|great|excellent|positive|benefit|advantage)\b/gi;
430
- const negative = /\b(bad|poor|negative|problem|issue|disadvantage)\b/gi;
431
- const posCount = (text.match(positive) || []).length;
432
- const negCount = (text.match(negative) || []).length;
433
- if (posCount > negCount)
434
- return 'positive';
435
- if (negCount > posCount)
436
- return 'negative';
437
- return 'neutral';
438
- }
439
- calculateSimilarity(values) {
440
- const subjects = Object.keys(values);
441
- if (subjects.length < 2)
442
- return 1;
443
- let totalSimilarity = 0;
444
- let comparisons = 0;
445
- for (let i = 0; i < subjects.length; i++) {
446
- for (let j = i + 1; j < subjects.length; j++) {
447
- const val1 = values[subjects[i]];
448
- const val2 = values[subjects[j]];
449
- if (Array.isArray(val1) && Array.isArray(val2)) {
450
- const intersection = val1.filter(v => val2.includes(v));
451
- const union = [...new Set([...val1, ...val2])];
452
- totalSimilarity += intersection.length / union.length;
453
- }
454
- else if (typeof val1 === 'string' && typeof val2 === 'string') {
455
- totalSimilarity += val1 === val2 ? 1 : 0;
456
- }
457
- comparisons++;
458
- }
459
- }
460
- return comparisons > 0 ? totalSimilarity / comparisons : 0;
461
- }
462
- generateComparisonConclusion(subjects, similarities, differences) {
463
- const similarityRatio = similarities.length / (similarities.length + differences.length);
464
- if (similarityRatio > 0.7) {
465
- return `${subjects.join(' and ')} share significant similarities, particularly in ${similarities.map(s => s.aspect).join(', ')}.`;
466
- }
467
- else if (similarityRatio < 0.3) {
468
- return `${subjects.join(' and ')} are notably different across ${differences.map(d => d.aspect).join(', ')}.`;
469
- }
470
- else {
471
- return `${subjects.join(' and ')} show both similarities and differences, with overlap in ${similarities.map(s => s.aspect).join(', ')} but divergence in ${differences.map(d => d.aspect).join(', ')}.`;
472
- }
473
- }
474
- }
475
- // ============================================================================
476
- // MAIN ANALYSIS ENGINE
477
- // ============================================================================
478
- class AnalysisEngine extends events_1.EventEmitter {
479
- constructor() {
480
- super();
481
- this.sentimentAnalyzer = new SentimentAnalyzer();
482
- this.entityExtractor = new EntityExtractor();
483
- this.topicExtractor = new TopicExtractor();
484
- this.keywordExtractor = new KeywordExtractor();
485
- this.summarizer = new Summarizer();
486
- this.factChecker = new FactChecker();
487
- this.comparisonEngine = new ComparisonEngine();
488
- }
489
- /**
490
- * Perform comprehensive analysis on content
491
- */
492
- async analyze(content, options = {}) {
493
- const { types = ['sentiment', 'entity', 'topic', 'keyword', 'summary'], depth = 'moderate', context } = options;
494
- const requestId = this.generateId();
495
- const startTime = Date.now();
496
- this.emit('analysis_start', {
497
- id: requestId,
498
- stage: types_1.ThinkingStage.ANALYSIS,
499
- timestamp: new Date(),
500
- data: { content: content.substring(0, 100) + '...', types }
501
- });
502
- const results = [];
503
- // Try to get bulk analysis from LLM first
504
- let llmResults = {};
505
- try {
506
- llmResults = await this.performLLMAnalysis(content, types, context);
507
- }
508
- catch (error) {
509
- console.warn('LLM analysis failed, falling back to local engines', error);
510
- }
511
- try {
512
- for (const type of types) {
513
- let result;
514
- if (llmResults[type]) {
515
- result = this.convertLLMResult(type, llmResults[type]);
516
- }
517
- else {
518
- result = await this.analyzeByType(type, content, context, depth);
519
- }
520
- results.push(result);
521
- }
522
- const processingTime = Date.now() - startTime;
523
- this.emit('analysis_complete', {
524
- id: requestId,
525
- stage: types_1.ThinkingStage.ANALYSIS,
526
- timestamp: new Date(),
527
- data: { results, processingTime }
528
- });
529
- return results;
530
- }
531
- catch (error) {
532
- this.emit('analysis_error', {
533
- id: requestId,
534
- stage: types_1.ThinkingStage.ANALYSIS,
535
- timestamp: new Date(),
536
- data: { error }
537
- });
538
- throw new types_1.ThinkingError(`Analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`, types_1.ThinkingStage.ANALYSIS, true, error instanceof Error ? error : undefined);
539
- }
540
- }
541
- async performLLMAnalysis(content, types, context) {
542
- const prompt = `
543
- Analyze this text: "${content.substring(0, 3000)}..."
544
- ${context ? `Context: ${context}` : ''}
545
-
546
- Provide analysis for: ${types.join(', ')}.
547
-
548
- Return strictly JSON with keys: ${types.map(t => `"${t}"`).join(', ')}.
549
- Structure requirements:
550
- - sentiment: { score: { positive: 0-1, negative: 0-1, neutral: 0-1, compound: -1 to 1 }, label: string }
551
- - entity: array of { name, type, confidence: 0-1, mentions: number }
552
- - topic: array of { name, relevance: 0-1, keywords: [] }
553
- - keyword: array of { term, frequency, importance: 0-1 }
554
- - summary: { summary: string }
555
- - fact_check: array of { claim, verdict: true/false/mixed, confidence }
556
- - trend: array of { trend: string, count }
557
- `;
558
- const response = await llm_service_1.llmService.generateText({ prompt });
559
- const jsonMatch = response.match(/\{[\s\S]*\}/);
560
- return jsonMatch ? JSON.parse(jsonMatch[0]) : {};
561
- }
562
- convertLLMResult(type, data) {
563
- const id = this.generateId();
564
- let findings = [];
565
- // Map raw JSON data to Finding[] structure
566
- if (type === 'sentiment') {
567
- findings = [{
568
- id: this.generateId(), type: 'sentiment_analysis',
569
- value: data, confidence: 0.9, evidence: [], relatedFindings: []
570
- }];
571
- }
572
- else if (Array.isArray(data)) {
573
- // Handle array results (entity, topic, keyword, fact_check)
574
- findings = data.map((item) => ({
575
- id: this.generateId(),
576
- type,
577
- value: item,
578
- confidence: item.confidence || item.relevance || item.importance || 0.8,
579
- evidence: [],
580
- relatedFindings: []
581
- }));
582
- }
583
- else {
584
- // Handle object results (summary)
585
- findings = [{
586
- id: this.generateId(), type,
587
- value: data, confidence: 0.9, evidence: [], relatedFindings: []
588
- }];
589
- }
590
- return {
591
- id,
592
- requestId: this.generateId(),
593
- type,
594
- findings,
595
- confidence: 0.9,
596
- processingTime: 0,
597
- timestamp: new Date()
598
- };
599
- }
600
- /**
601
- * Analyze by specific type
602
- */
603
- async analyzeByType(type, content, context, depth = 'moderate') {
604
- const startTime = Date.now();
605
- let findings = [];
606
- switch (type) {
607
- case 'sentiment':
608
- findings = this.analyzeSentiment(content);
609
- break;
610
- case 'entity':
611
- findings = this.analyzeEntities(content);
612
- break;
613
- case 'topic':
614
- findings = this.analyzeTopics(content);
615
- break;
616
- case 'keyword':
617
- findings = this.analyzeKeywords(content);
618
- break;
619
- case 'summary':
620
- findings = this.generateSummary(content, depth);
621
- break;
622
- case 'fact_check':
623
- findings = await this.factCheck(content);
624
- break;
625
- case 'comparison':
626
- findings = this.compareContent(content, context);
627
- break;
628
- case 'trend':
629
- findings = this.analyzeTrends(content);
630
- break;
631
- }
632
- return {
633
- id: this.generateId(),
634
- requestId: this.generateId(),
635
- type,
636
- findings,
637
- confidence: this.calculateConfidence(findings),
638
- processingTime: Date.now() - startTime,
639
- timestamp: new Date()
640
- };
641
- }
642
- analyzeSentiment(content) {
643
- const score = this.sentimentAnalyzer.analyze(content);
644
- const label = this.sentimentAnalyzer.getSentimentLabel(score);
645
- return [{
646
- id: this.generateId(),
647
- type: 'sentiment_analysis',
648
- value: { score, label },
649
- confidence: 0.85,
650
- evidence: [{
651
- source: 'sentiment_analyzer',
652
- excerpt: content.substring(0, 100),
653
- location: 'full_text',
654
- strength: 0.8
655
- }],
656
- relatedFindings: []
657
- }];
658
- }
659
- analyzeEntities(content) {
660
- const entities = this.entityExtractor.extract(content);
661
- return entities.slice(0, 10).map(entity => ({
662
- id: this.generateId(),
663
- type: 'entity',
664
- value: entity,
665
- confidence: entity.confidence,
666
- evidence: [{
667
- source: 'entity_extractor',
668
- excerpt: `Found ${entity.name} (${entity.type}) mentioned ${entity.mentions} times`,
669
- location: 'content',
670
- strength: entity.confidence
671
- }],
672
- relatedFindings: []
673
- }));
674
- }
675
- analyzeTopics(content) {
676
- const topics = this.topicExtractor.extract(content);
677
- return topics.map(topic => ({
678
- id: this.generateId(),
679
- type: 'topic',
680
- value: topic,
681
- confidence: topic.relevance,
682
- evidence: [{
683
- source: 'topic_extractor',
684
- excerpt: `Topic: ${topic.name} with keywords: ${topic.keywords.join(', ')}`,
685
- location: 'content',
686
- strength: topic.relevance
687
- }],
688
- relatedFindings: []
689
- }));
690
- }
691
- analyzeKeywords(content) {
692
- const keywords = this.keywordExtractor.extract(content);
693
- return keywords.map(kw => ({
694
- id: this.generateId(),
695
- type: 'keyword',
696
- value: kw,
697
- confidence: kw.importance,
698
- evidence: [{
699
- source: 'keyword_extractor',
700
- excerpt: `Keyword "${kw.term}" appears ${kw.frequency} times`,
701
- location: 'content',
702
- strength: kw.importance
703
- }],
704
- relatedFindings: []
705
- }));
706
- }
707
- generateSummary(content, depth) {
708
- const maxLength = depth === 'surface' ? 100 : depth === 'deep' ? 500 : 250;
709
- const summary = this.summarizer.summarize(content, maxLength);
710
- return [{
711
- id: this.generateId(),
712
- type: 'summary',
713
- value: { summary, originalLength: content.length, compressionRatio: summary.length / content.length },
714
- confidence: 0.8,
715
- evidence: [{
716
- source: 'summarizer',
717
- excerpt: summary.substring(0, 100),
718
- location: 'generated_summary',
719
- strength: 0.75
720
- }],
721
- relatedFindings: []
722
- }];
723
- }
724
- async factCheck(content) {
725
- // Extract claims from content (simplified)
726
- const sentences = content.match(/[^.!?]+[.!?]+/g) || [];
727
- const claims = sentences.filter(s => s.length > 20 &&
728
- !s.toLowerCase().includes('i think') &&
729
- !s.toLowerCase().includes('maybe')).slice(0, 3);
730
- const findings = [];
731
- for (const claim of claims) {
732
- const factCheck = await this.factChecker.checkClaim(claim, []);
733
- findings.push({
734
- id: this.generateId(),
735
- type: 'fact_check',
736
- value: factCheck,
737
- confidence: factCheck.confidence,
738
- evidence: factCheck.sources.map(s => ({
739
- source: s.url,
740
- excerpt: s.snippet,
741
- location: s.url,
742
- strength: s.credibility
743
- })),
744
- relatedFindings: []
745
- });
746
- }
747
- return findings;
748
- }
749
- compareContent(content, context) {
750
- if (!context) {
751
- return [{
752
- id: this.generateId(),
753
- type: 'comparison',
754
- value: { error: 'No comparison context provided' },
755
- confidence: 0,
756
- evidence: [],
757
- relatedFindings: []
758
- }];
759
- }
760
- const comparison = this.comparisonEngine.compare(['Current Content', 'Context'], [content, context]);
761
- return [{
762
- id: this.generateId(),
763
- type: 'comparison',
764
- value: comparison,
765
- confidence: comparison.confidence,
766
- evidence: [{
767
- source: 'comparison_engine',
768
- excerpt: comparison.conclusion,
769
- location: 'comparison_result',
770
- strength: comparison.confidence
771
- }],
772
- relatedFindings: []
773
- }];
774
- }
775
- analyzeTrends(content) {
776
- // Simple trend analysis based on temporal references
777
- const temporalPatterns = [
778
- { pattern: /\b(increasing|growing|rising|upward)\b/gi, trend: 'upward' },
779
- { pattern: /\b(decreasing|declining|falling|downward)\b/gi, trend: 'downward' },
780
- { pattern: /\b(stable|constant|steady|unchanged)\b/gi, trend: 'stable' }
781
- ];
782
- const trends = [];
783
- temporalPatterns.forEach(({ pattern, trend }) => {
784
- const matches = content.match(pattern) || [];
785
- if (matches.length > 0) {
786
- trends.push({ trend, count: matches.length });
787
- }
788
- });
789
- return [{
790
- id: this.generateId(),
791
- type: 'trend',
792
- value: trends,
793
- confidence: trends.length > 0 ? 0.7 : 0.3,
794
- evidence: [{
795
- source: 'trend_analyzer',
796
- excerpt: `Detected trends: ${trends.map(t => t.trend).join(', ')}`,
797
- location: 'content',
798
- strength: 0.65
799
- }],
800
- relatedFindings: []
801
- }];
802
- }
803
- calculateConfidence(findings) {
804
- if (findings.length === 0)
805
- return 0;
806
- const avgConfidence = findings.reduce((sum, f) => sum + f.confidence, 0) / findings.length;
807
- return Math.min(0.95, avgConfidence);
808
- }
809
- /**
810
- * Compare multiple contents
811
- */
812
- compare(subjects, contents) {
813
- return this.comparisonEngine.compare(subjects, contents);
814
- }
815
- /**
816
- * Fact check a claim
817
- */
818
- async factCheckClaim(claim, sources) {
819
- return this.factChecker.checkClaim(claim, sources);
820
- }
821
- /**
822
- * Add known fact for fact checking
823
- */
824
- addKnownFact(claim, value, confidence) {
825
- this.factChecker.addFact(claim, value, confidence);
826
- }
827
- generateId() {
828
- return `analysis_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
829
- }
830
- }
831
- exports.AnalysisEngine = AnalysisEngine;
832
- // ============================================================================
833
- // EXPORT SINGLETON INSTANCE
834
- // ============================================================================
835
- exports.analysisEngine = new AnalysisEngine();
836
- // ============================================================================
837
- // EXAMPLE USAGE
838
- // ============================================================================
839
- /*
840
- // Comprehensive analysis
841
- const results = await analysisEngine.analyze(
842
- "Artificial Intelligence is revolutionizing healthcare. Machine learning algorithms can now detect diseases with 95% accuracy. " +
843
- "However, there are concerns about privacy and data security. The future looks promising but challenges remain.",
844
- {
845
- types: ['sentiment', 'entity', 'topic', 'keyword', 'summary'],
846
- depth: 'deep'
847
- }
848
- );
849
-
850
- // Compare multiple texts
851
- const comparison = analysisEngine.compare(
852
- ['Article A', 'Article B', 'Article C'],
853
- [
854
- "AI is transforming industries with automation and efficiency gains.",
855
- "Machine learning brings both opportunities and challenges to various sectors.",
856
- "Automation through AI technology is reshaping the workplace landscape."
857
- ]
858
- );
859
-
860
- // Fact check
861
- const factCheck = await analysisEngine.factCheckClaim(
862
- "AI can detect diseases with 95% accuracy",
863
- searchResults
864
- );
865
- */
866
- //# sourceMappingURL=analysis.js.map