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