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
@@ -0,0 +1,384 @@
1
+ /**
2
+ * Analysis Engine for gthinking v2.0.0
3
+ * AI-powered content analysis including sentiment, entities, topics, and more.
4
+ */
5
+
6
+ import { EventEmitter } from 'events';
7
+ import { generateUUID } from '../utils/id-generator';
8
+ import { Logger } from '../utils/logger';
9
+ import { LLMService } from '../llm/llm-service';
10
+ import {
11
+ AnalysisRequest,
12
+ AnalysisRequestSchema,
13
+ AnalysisType,
14
+ CompleteAnalysisResult,
15
+ SentimentResult,
16
+ EntityExtractionResult,
17
+ TopicExtractionResult,
18
+ KeywordExtractionResult,
19
+ SummaryResult,
20
+ ReadabilityResult,
21
+ ThinkingStage,
22
+ ValidationError,
23
+ } from '../types';
24
+ import { validateSchema, safeJsonParse } from '../utils/validation';
25
+ import { withRetry, StageError } from '../core/errors';
26
+
27
+ const logger = new Logger('AnalysisEngine');
28
+
29
+ /**
30
+ * Analysis Engine
31
+ */
32
+ export class AnalysisEngine extends EventEmitter {
33
+ private llmService: LLMService | null = null;
34
+
35
+ constructor(llmService?: LLMService) {
36
+ super();
37
+ this.llmService = llmService || null;
38
+ }
39
+
40
+ /**
41
+ * Set the LLM service
42
+ * @param llmService - The LLM service instance
43
+ */
44
+ public setLLMService(llmService: LLMService): void {
45
+ this.llmService = llmService;
46
+ }
47
+
48
+ /**
49
+ * Analyze content based on request
50
+ * @param request - The analysis request
51
+ * @returns Complete analysis result
52
+ */
53
+ public async analyze(request: unknown): Promise<CompleteAnalysisResult> {
54
+ const startTime = Date.now();
55
+
56
+ // Validate request
57
+ const validatedRequest = validateSchema(AnalysisRequestSchema, request);
58
+
59
+ logger.info('Starting analysis', {
60
+ types: validatedRequest.types,
61
+ contentLength: validatedRequest.content.length
62
+ });
63
+
64
+ this.emit('analysis:start', { request: validatedRequest });
65
+
66
+ try {
67
+ // Execute requested analysis types in parallel
68
+ const tasks: Promise<void>[] = [];
69
+ const result: Partial<CompleteAnalysisResult> = {
70
+ success: true,
71
+ timestamp: new Date(),
72
+ request: validatedRequest,
73
+ rawContent: validatedRequest.options.includeRaw ? validatedRequest.content : undefined,
74
+ };
75
+
76
+ if (validatedRequest.types.includes(AnalysisType.SENTIMENT)) {
77
+ tasks.push(this.analyzeSentiment(validatedRequest).then(res => { result.sentiment = res; }));
78
+ }
79
+
80
+ if (validatedRequest.types.includes(AnalysisType.ENTITY)) {
81
+ tasks.push(this.extractEntities(validatedRequest).then(res => { result.entities = res; }));
82
+ }
83
+
84
+ if (validatedRequest.types.includes(AnalysisType.TOPIC)) {
85
+ tasks.push(this.extractTopics(validatedRequest).then(res => { result.topics = res; }));
86
+ }
87
+
88
+ if (validatedRequest.types.includes(AnalysisType.KEYWORD)) {
89
+ tasks.push(this.extractKeywords(validatedRequest).then(res => { result.keywords = res; }));
90
+ }
91
+
92
+ if (validatedRequest.types.includes(AnalysisType.SUMMARY)) {
93
+ tasks.push(this.generateSummary(validatedRequest).then(res => { result.summary = res; }));
94
+ }
95
+
96
+ if (validatedRequest.types.includes(AnalysisType.READABILITY)) {
97
+ // Readability is calculated locally, no LLM needed
98
+ tasks.push(Promise.resolve(this.analyzeReadability(validatedRequest.content)).then(res => { result.readability = res; }));
99
+ }
100
+
101
+ // Wait for all tasks to complete
102
+ await Promise.all(tasks);
103
+
104
+ const duration = Date.now() - startTime;
105
+ const finalResult = {
106
+ ...result,
107
+ duration,
108
+ confidence: this.calculateOverallConfidence(result),
109
+ errors: [],
110
+ } as CompleteAnalysisResult;
111
+
112
+ logger.info('Analysis completed', { duration });
113
+ this.emit('analysis:complete', { result: finalResult });
114
+
115
+ return finalResult;
116
+ } catch (error) {
117
+ logger.error('Analysis failed', { error });
118
+ this.emit('analysis:error', { error });
119
+
120
+ throw new StageError(
121
+ `Analysis failed: ${(error as Error).message}`,
122
+ ThinkingStage.ANALYSIS,
123
+ false,
124
+ { originalError: error }
125
+ );
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Analyze sentiment
131
+ */
132
+ private async analyzeSentiment(request: AnalysisRequest): Promise<SentimentResult> {
133
+ this.ensureLLM();
134
+
135
+ const prompt = `
136
+ Analyze the sentiment of the following text.
137
+ Return a JSON object with:
138
+ - overall: "positive", "negative", "neutral", or "mixed"
139
+ - score: number between -1 (negative) and 1 (positive)
140
+ - confidence: number between 0 and 1
141
+ - emotions: object with scores (0-1) for joy, sadness, anger, fear, surprise, disgust
142
+
143
+ Text: "${request.content.slice(0, 5000)}"
144
+ `;
145
+
146
+ return this.executeLLMAnalysis<SentimentResult>(prompt);
147
+ }
148
+
149
+ /**
150
+ * Extract entities
151
+ */
152
+ private async extractEntities(request: AnalysisRequest): Promise<EntityExtractionResult> {
153
+ this.ensureLLM();
154
+
155
+ const prompt = `
156
+ Extract entities from the following text.
157
+ Return a JSON object with:
158
+ - entities: array of objects with { text, type, confidence }
159
+ - totalCount: total number of entities
160
+
161
+ Entity types: person, organization, location, product, event, concept, date, money, percent
162
+ Max entities: ${request.options.maxEntities}
163
+
164
+ Text: "${request.content.slice(0, 5000)}"
165
+ `;
166
+
167
+ const result = await this.executeLLMAnalysis<any>(prompt);
168
+
169
+ // Post-process to ensure correct structure
170
+ const entities = (result.entities || []).map((e: any) => ({
171
+ id: generateUUID(),
172
+ text: e.text,
173
+ type: e.type,
174
+ startIndex: 0, // Placeholder
175
+ endIndex: 0, // Placeholder
176
+ confidence: e.confidence || 0.8,
177
+ metadata: {}
178
+ }));
179
+
180
+ return {
181
+ entities,
182
+ totalCount: entities.length,
183
+ byType: {} // Needs aggregation logic if needed
184
+ };
185
+ }
186
+
187
+ /**
188
+ * Extract topics
189
+ */
190
+ private async extractTopics(request: AnalysisRequest): Promise<TopicExtractionResult> {
191
+ this.ensureLLM();
192
+
193
+ const prompt = `
194
+ Extract main topics from the following text.
195
+ Return a JSON object with:
196
+ - topics: array of objects with { name, confidence, relevance, keywords (array of strings) }
197
+ - mainTopic: string
198
+
199
+ Max topics: ${request.options.maxTopics}
200
+
201
+ Text: "${request.content.slice(0, 5000)}"
202
+ `;
203
+
204
+ const result = await this.executeLLMAnalysis<any>(prompt);
205
+
206
+ const topics = (result.topics || []).map((t: any) => ({
207
+ id: generateUUID(),
208
+ name: t.name,
209
+ confidence: t.confidence || 0.8,
210
+ relevance: t.relevance || 0.5,
211
+ keywords: t.keywords || []
212
+ }));
213
+
214
+ return {
215
+ topics,
216
+ mainTopic: result.mainTopic,
217
+ topicHierarchy: []
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Extract keywords
223
+ */
224
+ private async extractKeywords(request: AnalysisRequest): Promise<KeywordExtractionResult> {
225
+ this.ensureLLM();
226
+
227
+ const prompt = `
228
+ Extract keywords and key phrases from the following text.
229
+ Return a JSON object with:
230
+ - keywords: array of objects with { text, score, frequency }
231
+ - keyPhrases: array of strings
232
+
233
+ Max keywords: ${request.options.maxKeywords}
234
+
235
+ Text: "${request.content.slice(0, 5000)}"
236
+ `;
237
+
238
+ const result = await this.executeLLMAnalysis<any>(prompt);
239
+
240
+ const keywords = (result.keywords || []).map((k: any) => ({
241
+ text: k.text,
242
+ score: k.score || 0.5,
243
+ frequency: k.frequency || 1,
244
+ tfidf: 0,
245
+ isKeyPhrase: false
246
+ }));
247
+
248
+ return {
249
+ keywords,
250
+ keyPhrases: result.keyPhrases || [],
251
+ totalWords: request.content.split(/\s+/).length,
252
+ uniqueWords: 0 // Placeholder
253
+ };
254
+ }
255
+
256
+ /**
257
+ * Generate summary
258
+ */
259
+ private async generateSummary(request: AnalysisRequest): Promise<SummaryResult> {
260
+ this.ensureLLM();
261
+
262
+ const prompt = `
263
+ Summarize the following text.
264
+ Return a JSON object with:
265
+ - summary: string
266
+ - keyPoints: array of strings
267
+
268
+ Length: ${request.options.summaryLength}
269
+
270
+ Text: "${request.content.slice(0, 10000)}"
271
+ `;
272
+
273
+ const result = await this.executeLLMAnalysis<any>(prompt);
274
+
275
+ return {
276
+ summary: result.summary,
277
+ keyPoints: result.keyPoints || [],
278
+ originalLength: request.content.length,
279
+ summaryLength: result.summary?.length || 0,
280
+ compressionRatio: result.summary ? result.summary.length / request.content.length : 0,
281
+ method: 'abstractive'
282
+ };
283
+ }
284
+
285
+ /**
286
+ * Calculate readability metrics (Locally)
287
+ */
288
+ private analyzeReadability(text: string): ReadabilityResult {
289
+ const words = text.trim().split(/\s+/).length;
290
+ const sentences = text.split(/[.!?]+/).length - 1 || 1;
291
+ const syllables = this.countSyllables(text);
292
+ const complexWords = this.countComplexWords(text);
293
+
294
+ // Flesch-Kincaid Grade Level
295
+ const fkGrade = 0.39 * (words / sentences) + 11.8 * (syllables / words) - 15.59;
296
+
297
+ // Flesch Reading Ease
298
+ const fReadingEase = 206.835 - 1.015 * (words / sentences) - 84.6 * (syllables / words);
299
+
300
+ return {
301
+ score: Math.max(0, Math.min(100, fReadingEase)),
302
+ grade: this.getGradeLevel(fkGrade),
303
+ metrics: {
304
+ fleschKincaid: fkGrade,
305
+ fleschReadingEase: fReadingEase,
306
+ gunningFog: 0, // Placeholder
307
+ smogIndex: 0, // Placeholder
308
+ colemanLiau: 0, // Placeholder
309
+ automatedReadability: 0 // Placeholder
310
+ },
311
+ statistics: {
312
+ wordCount: words,
313
+ sentenceCount: sentences,
314
+ syllableCount: syllables,
315
+ avgWordsPerSentence: words / sentences,
316
+ avgSyllablesPerWord: syllables / words,
317
+ complexWordCount: complexWords,
318
+ complexWordPercentage: (complexWords / words) * 100
319
+ }
320
+ };
321
+ }
322
+
323
+ private countSyllables(text: string): number {
324
+ // Very basic syllable counter
325
+ return text.length / 3;
326
+ }
327
+
328
+ private countComplexWords(text: string): number {
329
+ // Placeholder
330
+ return text.split(/\s+/).filter(w => w.length > 6).length;
331
+ }
332
+
333
+ private getGradeLevel(score: number): any {
334
+ if (score < 5) return 'elementary';
335
+ if (score < 8) return 'middle_school';
336
+ if (score < 12) return 'high_school';
337
+ if (score < 16) return 'college';
338
+ return 'graduate';
339
+ }
340
+
341
+ /**
342
+ * Execute LLM analysis with retries and parsing
343
+ */
344
+ private async executeLLMAnalysis<T>(prompt: string): Promise<T> {
345
+ if (!this.llmService) throw new Error('LLM Service not initialized');
346
+
347
+ const response = await withRetry(async () => {
348
+ return this.llmService!.complete(prompt, 'You are a precise text analysis engine. Output valid JSON only.');
349
+ });
350
+
351
+ // Clean up potential markdown code blocks
352
+ const cleanResponse = response.replace(/```json/g, '').replace(/```/g, '').trim();
353
+
354
+ const parsed = safeJsonParse<T>(cleanResponse);
355
+ if (!parsed) {
356
+ throw new Error('Failed to parse LLM response as JSON');
357
+ }
358
+ return parsed;
359
+ }
360
+
361
+ private ensureLLM(): void {
362
+ if (!this.llmService) {
363
+ throw new Error('LLM Service is required for this analysis type');
364
+ }
365
+ }
366
+
367
+ private calculateOverallConfidence(result: Partial<CompleteAnalysisResult>): number {
368
+ // Simple average of available confidences
369
+ const confidences: number[] = [];
370
+ if (result.sentiment) confidences.push(result.sentiment.confidence);
371
+ if (result.entities) confidences.push(0.8); // Entities usually high
372
+ if (result.topics) confidences.push(0.8);
373
+
374
+ if (confidences.length === 0) return 0.8;
375
+ return confidences.reduce((a, b) => a + b, 0) / confidences.length;
376
+ }
377
+ }
378
+
379
+ /**
380
+ * Factory function
381
+ */
382
+ export function createAnalysisEngine(llmService?: LLMService): AnalysisEngine {
383
+ return new AnalysisEngine(llmService);
384
+ }