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.
- package/.eslintrc.js +34 -0
- package/ANALYSIS_SUMMARY.md +363 -0
- package/README.md +230 -250
- package/dist/analysis/analysis-engine.d.ts +63 -0
- package/dist/analysis/analysis-engine.d.ts.map +1 -0
- package/dist/analysis/analysis-engine.js +322 -0
- package/dist/analysis/analysis-engine.js.map +1 -0
- package/dist/core/config.d.ts +1419 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +361 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/engine.d.ts +176 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +604 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/errors.d.ts +153 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +287 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/{types.js → core/index.js} +8 -4
- package/dist/core/index.js.map +1 -0
- package/dist/core/pipeline.d.ts +121 -0
- package/dist/core/pipeline.d.ts.map +1 -0
- package/dist/core/pipeline.js +289 -0
- package/dist/core/pipeline.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +58 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +133 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/session-manager.d.ts +96 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +223 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/creativity/creativity-engine.d.ts +6 -0
- package/dist/creativity/creativity-engine.d.ts.map +1 -0
- package/dist/creativity/creativity-engine.js +17 -0
- package/dist/creativity/creativity-engine.js.map +1 -0
- package/dist/index.d.ts +24 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +130 -104
- package/dist/index.js.map +1 -1
- package/dist/learning/learning-engine.d.ts +6 -0
- package/dist/learning/learning-engine.d.ts.map +1 -0
- package/dist/learning/learning-engine.js +17 -0
- package/dist/learning/learning-engine.js.map +1 -0
- package/dist/llm/index.d.ts +10 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +26 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/llm-service.d.ts +109 -0
- package/dist/llm/llm-service.d.ts.map +1 -0
- package/dist/llm/llm-service.js +224 -0
- package/dist/llm/llm-service.js.map +1 -0
- package/dist/llm/providers/base.d.ts +85 -0
- package/dist/llm/providers/base.d.ts.map +1 -0
- package/dist/llm/providers/base.js +57 -0
- package/dist/llm/providers/base.js.map +1 -0
- package/dist/llm/providers/cli.d.ts +23 -0
- package/dist/llm/providers/cli.d.ts.map +1 -0
- package/dist/llm/providers/cli.js +158 -0
- package/dist/llm/providers/cli.js.map +1 -0
- package/dist/llm/providers/gemini.d.ts +30 -0
- package/dist/llm/providers/gemini.d.ts.map +1 -0
- package/dist/llm/providers/gemini.js +168 -0
- package/dist/llm/providers/gemini.js.map +1 -0
- package/dist/llm/sanitization.d.ts +50 -0
- package/dist/llm/sanitization.d.ts.map +1 -0
- package/dist/llm/sanitization.js +149 -0
- package/dist/llm/sanitization.js.map +1 -0
- package/dist/{server.d.ts.map → mcp/server.d.ts.map} +1 -1
- package/dist/mcp/server.js +108 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/planning/planning-engine.d.ts +6 -0
- package/dist/planning/planning-engine.d.ts.map +1 -0
- package/dist/planning/planning-engine.js +17 -0
- package/dist/planning/planning-engine.js.map +1 -0
- package/dist/reasoning/reasoning-engine.d.ts +6 -0
- package/dist/reasoning/reasoning-engine.d.ts.map +1 -0
- package/dist/reasoning/reasoning-engine.js +17 -0
- package/dist/reasoning/reasoning-engine.js.map +1 -0
- package/dist/search/search-engine.d.ts +99 -0
- package/dist/search/search-engine.d.ts.map +1 -0
- package/dist/search/search-engine.js +271 -0
- package/dist/search/search-engine.js.map +1 -0
- package/dist/synthesis/synthesis-engine.d.ts +6 -0
- package/dist/synthesis/synthesis-engine.d.ts.map +1 -0
- package/dist/synthesis/synthesis-engine.js +17 -0
- package/dist/synthesis/synthesis-engine.js.map +1 -0
- package/dist/types/analysis.d.ts +1534 -49
- package/dist/types/analysis.d.ts.map +1 -1
- package/dist/types/analysis.js +250 -0
- package/dist/types/analysis.js.map +1 -1
- package/dist/types/core.d.ts +257 -30
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js +148 -18
- package/dist/types/core.js.map +1 -1
- package/dist/types/creativity.d.ts +2871 -56
- package/dist/types/creativity.d.ts.map +1 -1
- package/dist/types/creativity.js +195 -0
- package/dist/types/creativity.js.map +1 -1
- package/dist/types/index.d.ts +6 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +17 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/learning.d.ts +851 -61
- package/dist/types/learning.d.ts.map +1 -1
- package/dist/types/learning.js +155 -0
- package/dist/types/learning.js.map +1 -1
- package/dist/types/planning.d.ts +2223 -71
- package/dist/types/planning.d.ts.map +1 -1
- package/dist/types/planning.js +190 -0
- package/dist/types/planning.js.map +1 -1
- package/dist/types/reasoning.d.ts +2209 -72
- package/dist/types/reasoning.d.ts.map +1 -1
- package/dist/types/reasoning.js +200 -1
- package/dist/types/reasoning.js.map +1 -1
- package/dist/types/search.d.ts +981 -53
- package/dist/types/search.d.ts.map +1 -1
- package/dist/types/search.js +137 -0
- package/dist/types/search.js.map +1 -1
- package/dist/types/synthesis.d.ts +583 -38
- package/dist/types/synthesis.d.ts.map +1 -1
- package/dist/types/synthesis.js +138 -0
- package/dist/types/synthesis.js.map +1 -1
- package/dist/utils/cache.d.ts +144 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +288 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/id-generator.d.ts +89 -0
- package/dist/utils/id-generator.d.ts.map +1 -0
- package/dist/utils/id-generator.js +132 -0
- package/dist/utils/id-generator.js.map +1 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +33 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +142 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +248 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/metrics.d.ts +149 -0
- package/dist/utils/metrics.d.ts.map +1 -0
- package/dist/utils/metrics.js +296 -0
- package/dist/utils/metrics.js.map +1 -0
- package/dist/utils/timer.d.ts +7 -0
- package/dist/utils/timer.d.ts.map +1 -0
- package/dist/utils/timer.js +17 -0
- package/dist/utils/timer.js.map +1 -0
- package/dist/utils/validation.d.ts +147 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +275 -0
- package/dist/utils/validation.js.map +1 -0
- package/docs/API.md +411 -0
- package/docs/ARCHITECTURE.md +271 -0
- package/docs/CHANGELOG.md +283 -0
- package/jest.config.js +28 -0
- package/package.json +43 -30
- package/src/analysis/analysis-engine.ts +383 -0
- package/src/core/config.ts +406 -0
- package/src/core/engine.ts +785 -0
- package/src/core/errors.ts +349 -0
- package/src/core/index.ts +12 -0
- package/src/core/pipeline.ts +424 -0
- package/src/core/rate-limiter.ts +155 -0
- package/src/core/session-manager.ts +269 -0
- package/src/creativity/creativity-engine.ts +14 -0
- package/src/index.ts +178 -0
- package/src/learning/learning-engine.ts +14 -0
- package/src/llm/index.ts +10 -0
- package/src/llm/llm-service.ts +285 -0
- package/src/llm/providers/base.ts +146 -0
- package/src/llm/providers/cli.ts +186 -0
- package/src/llm/providers/gemini.ts +201 -0
- package/src/llm/sanitization.ts +178 -0
- package/src/mcp/server.ts +117 -0
- package/src/planning/planning-engine.ts +14 -0
- package/src/reasoning/reasoning-engine.ts +14 -0
- package/src/search/search-engine.ts +333 -0
- package/src/synthesis/synthesis-engine.ts +14 -0
- package/src/types/analysis.ts +337 -0
- package/src/types/core.ts +342 -0
- package/src/types/creativity.ts +268 -0
- package/src/types/index.ts +31 -0
- package/src/types/learning.ts +215 -0
- package/src/types/planning.ts +251 -0
- package/src/types/reasoning.ts +288 -0
- package/src/types/search.ts +192 -0
- package/src/types/synthesis.ts +187 -0
- package/src/utils/cache.ts +363 -0
- package/src/utils/id-generator.ts +135 -0
- package/src/utils/index.ts +22 -0
- package/src/utils/logger.ts +290 -0
- package/src/utils/metrics.ts +380 -0
- package/src/utils/timer.ts +15 -0
- package/src/utils/validation.ts +297 -0
- package/tests/setup.ts +22 -0
- package/tests/unit/cache.test.ts +189 -0
- package/tests/unit/engine.test.ts +179 -0
- package/tests/unit/validation.test.ts +218 -0
- package/tsconfig.json +17 -12
- package/GEMINI.md +0 -68
- package/analysis.ts +0 -1063
- package/creativity.ts +0 -1055
- package/dist/analysis.d.ts +0 -54
- package/dist/analysis.d.ts.map +0 -1
- package/dist/analysis.js +0 -866
- package/dist/analysis.js.map +0 -1
- package/dist/creativity.d.ts +0 -81
- package/dist/creativity.d.ts.map +0 -1
- package/dist/creativity.js +0 -828
- package/dist/creativity.js.map +0 -1
- package/dist/engine.d.ts +0 -90
- package/dist/engine.d.ts.map +0 -1
- package/dist/engine.js +0 -720
- package/dist/engine.js.map +0 -1
- package/dist/examples.d.ts +0 -7
- package/dist/examples.d.ts.map +0 -1
- package/dist/examples.js +0 -506
- package/dist/examples.js.map +0 -1
- package/dist/learning.d.ts +0 -72
- package/dist/learning.d.ts.map +0 -1
- package/dist/learning.js +0 -615
- package/dist/learning.js.map +0 -1
- package/dist/llm-service.d.ts +0 -21
- package/dist/llm-service.d.ts.map +0 -1
- package/dist/llm-service.js +0 -100
- package/dist/llm-service.js.map +0 -1
- package/dist/planning.d.ts +0 -62
- package/dist/planning.d.ts.map +0 -1
- package/dist/planning.js +0 -886
- package/dist/planning.js.map +0 -1
- package/dist/reasoning.d.ts +0 -73
- package/dist/reasoning.d.ts.map +0 -1
- package/dist/reasoning.js +0 -845
- package/dist/reasoning.js.map +0 -1
- package/dist/search-discovery.d.ts +0 -73
- package/dist/search-discovery.d.ts.map +0 -1
- package/dist/search-discovery.js +0 -548
- package/dist/search-discovery.js.map +0 -1
- package/dist/server.js +0 -113
- package/dist/server.js.map +0 -1
- package/dist/types/engine.d.ts +0 -55
- package/dist/types/engine.d.ts.map +0 -1
- package/dist/types/engine.js +0 -3
- package/dist/types/engine.js.map +0 -1
- package/dist/types.d.ts +0 -6
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/engine.ts +0 -1009
- package/examples.ts +0 -717
- package/index.ts +0 -106
- package/learning.ts +0 -779
- package/llm-service.ts +0 -120
- package/planning.ts +0 -1101
- package/reasoning.ts +0 -1079
- package/search-discovery.ts +0 -700
- package/server.ts +0 -115
- package/types/analysis.ts +0 -69
- package/types/core.ts +0 -90
- package/types/creativity.ts +0 -72
- package/types/engine.ts +0 -60
- package/types/index.ts +0 -9
- package/types/learning.ts +0 -69
- package/types/planning.ts +0 -85
- package/types/reasoning.ts +0 -92
- package/types/search.ts +0 -58
- package/types/synthesis.ts +0 -43
- package/types.ts +0 -6
- /package/dist/{server.d.ts → mcp/server.d.ts} +0 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Discovery Engine for gthinking v2.0.0
|
|
3
|
+
* Multi-provider search with aggregation and ranking
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import {
|
|
8
|
+
SearchQuery,
|
|
9
|
+
SearchResult,
|
|
10
|
+
SearchResultItem,
|
|
11
|
+
AggregatedResult,
|
|
12
|
+
SearchProvider,
|
|
13
|
+
SourceType,
|
|
14
|
+
ThinkingStage,
|
|
15
|
+
BaseResult,
|
|
16
|
+
} from '../types';
|
|
17
|
+
import { Logger } from '../utils/logger';
|
|
18
|
+
import { Cache } from '../utils/cache';
|
|
19
|
+
import { generateUUID } from '../utils/id-generator';
|
|
20
|
+
import { withRetry, SearchError } from '../core/errors';
|
|
21
|
+
import axios from 'axios';
|
|
22
|
+
|
|
23
|
+
const logger = new Logger('SearchDiscoveryEngine');
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Search Provider Interface
|
|
27
|
+
*/
|
|
28
|
+
interface ISearchProvider {
|
|
29
|
+
name: string;
|
|
30
|
+
search(query: SearchQuery): Promise<SearchResultItem[]>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Google Search Provider
|
|
35
|
+
*/
|
|
36
|
+
class GoogleSearchProvider implements ISearchProvider {
|
|
37
|
+
name = 'google';
|
|
38
|
+
private apiKey: string;
|
|
39
|
+
private baseUrl = 'https://www.googleapis.com/customsearch/v1';
|
|
40
|
+
|
|
41
|
+
constructor(apiKey: string) {
|
|
42
|
+
this.apiKey = apiKey;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async search(query: SearchQuery): Promise<SearchResultItem[]> {
|
|
46
|
+
// Implementation would go here
|
|
47
|
+
logger.info(`Searching Google: ${query.query}`);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Bing Search Provider
|
|
54
|
+
*/
|
|
55
|
+
class BingSearchProvider implements ISearchProvider {
|
|
56
|
+
name = 'bing';
|
|
57
|
+
private apiKey: string;
|
|
58
|
+
private baseUrl = 'https://api.bing.microsoft.com/v7.0/search';
|
|
59
|
+
|
|
60
|
+
constructor(apiKey: string) {
|
|
61
|
+
this.apiKey = apiKey;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async search(query: SearchQuery): Promise<SearchResultItem[]> {
|
|
65
|
+
logger.info(`Searching Bing: ${query.query}`);
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Search Discovery Engine
|
|
72
|
+
*/
|
|
73
|
+
export class SearchDiscoveryEngine extends EventEmitter {
|
|
74
|
+
private providers: Map<string, ISearchProvider> = new Map();
|
|
75
|
+
private cache: Cache<SearchResult>;
|
|
76
|
+
|
|
77
|
+
constructor() {
|
|
78
|
+
super();
|
|
79
|
+
this.cache = new Cache({ maxSize: 500, defaultTTL: 3600000 });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Register a search provider
|
|
84
|
+
* @param provider - The search provider
|
|
85
|
+
*/
|
|
86
|
+
public registerProvider(provider: ISearchProvider): void {
|
|
87
|
+
this.providers.set(provider.name, provider);
|
|
88
|
+
logger.info(`Registered search provider: ${provider.name}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Search using registered providers
|
|
93
|
+
* @param query - The search query
|
|
94
|
+
* @returns Search result
|
|
95
|
+
*/
|
|
96
|
+
public async search(query: SearchQuery): Promise<SearchResult> {
|
|
97
|
+
const startTime = Date.now();
|
|
98
|
+
const cacheKey = `search:${JSON.stringify(query)}`;
|
|
99
|
+
|
|
100
|
+
// Check cache
|
|
101
|
+
const cached = this.cache.get(cacheKey);
|
|
102
|
+
if (cached) {
|
|
103
|
+
logger.info(`Cache hit for search: ${query.query}`);
|
|
104
|
+
return cached;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
logger.info(`Starting search: ${query.query}`);
|
|
108
|
+
this.emit('search:start', { query });
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const allResults: SearchResultItem[] = [];
|
|
112
|
+
|
|
113
|
+
// Search with each provider
|
|
114
|
+
for (const providerName of query.sources) {
|
|
115
|
+
const provider = this.providers.get(providerName);
|
|
116
|
+
if (!provider) {
|
|
117
|
+
logger.warn(`Provider not found: ${providerName}`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const results = await withRetry(
|
|
123
|
+
() => provider.search(query),
|
|
124
|
+
{ maxRetries: 2 }
|
|
125
|
+
);
|
|
126
|
+
allResults.push(...results);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
logger.error(`Provider ${providerName} failed:`, error as Record<string, unknown>);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Rank and deduplicate results
|
|
133
|
+
const rankedResults = this.rankResults(allResults, query);
|
|
134
|
+
|
|
135
|
+
const result: SearchResult = {
|
|
136
|
+
success: true,
|
|
137
|
+
confidence: 0.8,
|
|
138
|
+
timestamp: new Date(),
|
|
139
|
+
duration: Date.now() - startTime,
|
|
140
|
+
errors: [],
|
|
141
|
+
query,
|
|
142
|
+
items: rankedResults.slice(0, query.maxResults),
|
|
143
|
+
totalResults: rankedResults.length,
|
|
144
|
+
searchTime: Date.now() - startTime,
|
|
145
|
+
provider: query.sources[0] || SearchProvider.GOOGLE,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// Cache result
|
|
149
|
+
this.cache.set(cacheKey, result);
|
|
150
|
+
|
|
151
|
+
this.emit('search:complete', { query, result });
|
|
152
|
+
logger.info(`Search completed: ${query.query}`);
|
|
153
|
+
|
|
154
|
+
return result;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
logger.error(`Search failed: ${query.query}`, error as Record<string, unknown>);
|
|
157
|
+
this.emit('search:error', { query, error });
|
|
158
|
+
|
|
159
|
+
throw new SearchError(
|
|
160
|
+
`Search failed: ${(error as Error).message}`,
|
|
161
|
+
query.sources[0] || 'unknown'
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Rank search results
|
|
168
|
+
* @param results - Raw search results
|
|
169
|
+
* @param query - Search query for context
|
|
170
|
+
* @returns Ranked results
|
|
171
|
+
*/
|
|
172
|
+
private rankResults(
|
|
173
|
+
results: SearchResultItem[],
|
|
174
|
+
query: SearchQuery
|
|
175
|
+
): SearchResultItem[] {
|
|
176
|
+
// Calculate composite score for each result
|
|
177
|
+
const scored = results.map(item => ({
|
|
178
|
+
item,
|
|
179
|
+
score: this.calculateScore(item),
|
|
180
|
+
}));
|
|
181
|
+
|
|
182
|
+
// Sort by score descending
|
|
183
|
+
scored.sort((a, b) => b.score - a.score);
|
|
184
|
+
|
|
185
|
+
// Deduplicate by URL
|
|
186
|
+
const seen = new Set<string>();
|
|
187
|
+
return scored
|
|
188
|
+
.map(s => s.item)
|
|
189
|
+
.filter(item => {
|
|
190
|
+
if (seen.has(item.url)) return false;
|
|
191
|
+
seen.add(item.url);
|
|
192
|
+
return true;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Calculate relevance score for a result
|
|
198
|
+
* @param item - Search result item
|
|
199
|
+
* @returns Score (0-1)
|
|
200
|
+
*/
|
|
201
|
+
private calculateScore(item: SearchResultItem): number {
|
|
202
|
+
const relevanceWeight = 0.4;
|
|
203
|
+
const credibilityWeight = 0.3;
|
|
204
|
+
const freshnessWeight = 0.15;
|
|
205
|
+
const engagementWeight = 0.15;
|
|
206
|
+
|
|
207
|
+
const freshness = item.publishedDate
|
|
208
|
+
? Math.max(0, 1 - (Date.now() - item.publishedDate.getTime()) / (30 * 24 * 60 * 60 * 1000))
|
|
209
|
+
: 0.5;
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
item.relevance * relevanceWeight +
|
|
213
|
+
item.credibility * credibilityWeight +
|
|
214
|
+
freshness * freshnessWeight +
|
|
215
|
+
item.engagement * engagementWeight
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Aggregate results by topic
|
|
221
|
+
* @param results - Search results
|
|
222
|
+
* @returns Aggregated results
|
|
223
|
+
*/
|
|
224
|
+
public aggregateResults(results: SearchResultItem[]): AggregatedResult[] {
|
|
225
|
+
// Group by topic
|
|
226
|
+
const topicMap = new Map<string, SearchResultItem[]>();
|
|
227
|
+
|
|
228
|
+
for (const item of results) {
|
|
229
|
+
// Extract topic from title/snippet
|
|
230
|
+
const topic = this.extractTopic(item.title);
|
|
231
|
+
if (!topicMap.has(topic)) {
|
|
232
|
+
topicMap.set(topic, []);
|
|
233
|
+
}
|
|
234
|
+
topicMap.get(topic)!.push(item);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Create aggregated results
|
|
238
|
+
return Array.from(topicMap.entries()).map(([topic, items]) => ({
|
|
239
|
+
id: generateUUID(),
|
|
240
|
+
topic,
|
|
241
|
+
summary: this.generateSummary(items),
|
|
242
|
+
sources: items,
|
|
243
|
+
consensusScore: this.calculateConsensus(items),
|
|
244
|
+
conflicts: this.detectConflicts(items),
|
|
245
|
+
keyInsights: this.extractInsights(items),
|
|
246
|
+
confidence: items.reduce((sum, item) => sum + item.credibility, 0) / items.length,
|
|
247
|
+
timestamp: new Date(),
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Extract topic from text
|
|
253
|
+
* @param text - Text to extract topic from
|
|
254
|
+
* @returns Topic string
|
|
255
|
+
*/
|
|
256
|
+
private extractTopic(text: string): string {
|
|
257
|
+
// Simple topic extraction - would use NLP in production
|
|
258
|
+
const words = text.toLowerCase().split(/\s+/);
|
|
259
|
+
const stopWords = new Set(['the', 'a', 'an', 'in', 'on', 'at', 'to', 'for', 'of', 'and']);
|
|
260
|
+
const keywords = words.filter(w => w.length > 3 && !stopWords.has(w));
|
|
261
|
+
return keywords.slice(0, 3).join(' ');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Generate summary from search results
|
|
266
|
+
* @param items - Search result items
|
|
267
|
+
* @returns Summary string
|
|
268
|
+
*/
|
|
269
|
+
private generateSummary(items: SearchResultItem[]): string {
|
|
270
|
+
return items.map(i => i.snippet).join(' ').slice(0, 500);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Calculate consensus score
|
|
275
|
+
* @param items - Search result items
|
|
276
|
+
* @returns Consensus score (0-1)
|
|
277
|
+
*/
|
|
278
|
+
private calculateConsensus(items: SearchResultItem[]): number {
|
|
279
|
+
if (items.length < 2) return 1;
|
|
280
|
+
// Simple consensus calculation
|
|
281
|
+
return items.reduce((sum, item) => sum + item.credibility, 0) / items.length;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Detect conflicts between sources
|
|
286
|
+
* @param items - Search result items
|
|
287
|
+
* @returns Array of conflicts
|
|
288
|
+
*/
|
|
289
|
+
private detectConflicts(
|
|
290
|
+
items: SearchResultItem[]
|
|
291
|
+
): Array<{ claim1: string; claim2: string; sources: string[] }> {
|
|
292
|
+
// Simplified conflict detection
|
|
293
|
+
const conflicts: Array<{ claim1: string; claim2: string; sources: string[] }> = [];
|
|
294
|
+
// Would implement actual conflict detection in production
|
|
295
|
+
return conflicts;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Extract key insights from search results
|
|
300
|
+
* @param items - Search result items
|
|
301
|
+
* @returns Array of insights
|
|
302
|
+
*/
|
|
303
|
+
private extractInsights(items: SearchResultItem[]): string[] {
|
|
304
|
+
return items.slice(0, 3).map(i => i.snippet.slice(0, 100));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Get cache statistics
|
|
309
|
+
* @returns Cache stats
|
|
310
|
+
*/
|
|
311
|
+
public getCacheStats(): ReturnType<Cache<SearchResult>['getStats']> {
|
|
312
|
+
return this.cache.getStats();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Clear search cache
|
|
317
|
+
*/
|
|
318
|
+
public clearCache(): void {
|
|
319
|
+
this.cache.clear();
|
|
320
|
+
logger.info('Search cache cleared');
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Create a new SearchDiscoveryEngine instance
|
|
326
|
+
* @returns New engine instance
|
|
327
|
+
*/
|
|
328
|
+
export function createSearchEngine(): SearchDiscoveryEngine {
|
|
329
|
+
return new SearchDiscoveryEngine();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Export singleton instance
|
|
333
|
+
export const searchEngine = new SearchDiscoveryEngine();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { Logger } from '../utils/logger';
|
|
3
|
+
|
|
4
|
+
const logger = new Logger('SynthesisEngine');
|
|
5
|
+
|
|
6
|
+
export class SynthesisEngine extends EventEmitter {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createSynthesisEngine(): SynthesisEngine {
|
|
13
|
+
return new SynthesisEngine();
|
|
14
|
+
}
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analysis Types for gthinking v2.0.0
|
|
3
|
+
* Types for content analysis functionality
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { BaseResultSchema, ConfidenceLevel } from './core';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Analysis Type Enum
|
|
11
|
+
*/
|
|
12
|
+
export enum AnalysisType {
|
|
13
|
+
SENTIMENT = 'sentiment',
|
|
14
|
+
ENTITY = 'entity',
|
|
15
|
+
TOPIC = 'topic',
|
|
16
|
+
KEYWORD = 'keyword',
|
|
17
|
+
SUMMARY = 'summary',
|
|
18
|
+
FACT_CHECK = 'fact_check',
|
|
19
|
+
COMPARISON = 'comparison',
|
|
20
|
+
TREND = 'trend',
|
|
21
|
+
LANGUAGE = 'language',
|
|
22
|
+
READABILITY = 'readability',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Analysis Type Schema
|
|
27
|
+
*/
|
|
28
|
+
export const AnalysisTypeSchema = z.nativeEnum(AnalysisType);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Sentiment Type Enum
|
|
32
|
+
*/
|
|
33
|
+
export enum SentimentType {
|
|
34
|
+
POSITIVE = 'positive',
|
|
35
|
+
NEGATIVE = 'negative',
|
|
36
|
+
NEUTRAL = 'neutral',
|
|
37
|
+
MIXED = 'mixed',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Sentiment Type Schema
|
|
42
|
+
*/
|
|
43
|
+
export const SentimentTypeSchema = z.nativeEnum(SentimentType);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Entity Type Enum
|
|
47
|
+
*/
|
|
48
|
+
export enum EntityType {
|
|
49
|
+
PERSON = 'person',
|
|
50
|
+
ORGANIZATION = 'organization',
|
|
51
|
+
LOCATION = 'location',
|
|
52
|
+
PRODUCT = 'product',
|
|
53
|
+
EVENT = 'event',
|
|
54
|
+
CONCEPT = 'concept',
|
|
55
|
+
DATE = 'date',
|
|
56
|
+
MONEY = 'money',
|
|
57
|
+
PERCENT = 'percent',
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Entity Type Schema
|
|
62
|
+
*/
|
|
63
|
+
export const EntityTypeSchema = z.nativeEnum(EntityType);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Analysis Request Schema
|
|
67
|
+
*/
|
|
68
|
+
export const AnalysisRequestSchema = z.object({
|
|
69
|
+
content: z.string().min(1).max(100000),
|
|
70
|
+
types: z.array(AnalysisTypeSchema).min(1),
|
|
71
|
+
options: z.object({
|
|
72
|
+
language: z.string().default('auto'),
|
|
73
|
+
depth: z.enum(['shallow', 'medium', 'deep']).default('medium'),
|
|
74
|
+
includeRaw: z.boolean().default(false),
|
|
75
|
+
maxEntities: z.number().positive().default(50),
|
|
76
|
+
maxKeywords: z.number().positive().default(20),
|
|
77
|
+
maxTopics: z.number().positive().default(10),
|
|
78
|
+
summaryLength: z.enum(['short', 'medium', 'long']).default('medium'),
|
|
79
|
+
}).default({}),
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Analysis Request Type
|
|
84
|
+
*/
|
|
85
|
+
export type AnalysisRequest = z.infer<typeof AnalysisRequestSchema>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Sentiment Result Schema
|
|
89
|
+
*/
|
|
90
|
+
export const SentimentResultSchema = z.object({
|
|
91
|
+
overall: SentimentTypeSchema,
|
|
92
|
+
score: z.number().min(-1).max(1),
|
|
93
|
+
confidence: z.number().min(0).max(1),
|
|
94
|
+
aspects: z.array(z.object({
|
|
95
|
+
aspect: z.string(),
|
|
96
|
+
sentiment: SentimentTypeSchema,
|
|
97
|
+
score: z.number().min(-1).max(1),
|
|
98
|
+
})).default([]),
|
|
99
|
+
emotions: z.object({
|
|
100
|
+
joy: z.number().min(0).max(1).default(0),
|
|
101
|
+
sadness: z.number().min(0).max(1).default(0),
|
|
102
|
+
anger: z.number().min(0).max(1).default(0),
|
|
103
|
+
fear: z.number().min(0).max(1).default(0),
|
|
104
|
+
surprise: z.number().min(0).max(1).default(0),
|
|
105
|
+
disgust: z.number().min(0).max(1).default(0),
|
|
106
|
+
}).default({}),
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Sentiment Result Type
|
|
111
|
+
*/
|
|
112
|
+
export type SentimentResult = z.infer<typeof SentimentResultSchema>;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Entity Schema
|
|
116
|
+
*/
|
|
117
|
+
export const EntitySchema = z.object({
|
|
118
|
+
id: z.string().uuid(),
|
|
119
|
+
text: z.string(),
|
|
120
|
+
type: EntityTypeSchema,
|
|
121
|
+
startIndex: z.number().nonnegative(),
|
|
122
|
+
endIndex: z.number().nonnegative(),
|
|
123
|
+
confidence: z.number().min(0).max(1),
|
|
124
|
+
normalized: z.string().optional(),
|
|
125
|
+
metadata: z.record(z.unknown()).default({}),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Entity Type
|
|
130
|
+
*/
|
|
131
|
+
export type Entity = z.infer<typeof EntitySchema>;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Entity Extraction Result Schema
|
|
135
|
+
*/
|
|
136
|
+
export const EntityExtractionResultSchema = z.object({
|
|
137
|
+
entities: z.array(EntitySchema),
|
|
138
|
+
totalCount: z.number().nonnegative(),
|
|
139
|
+
byType: z.record(z.number().nonnegative()).default({}),
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Entity Extraction Result Type
|
|
144
|
+
*/
|
|
145
|
+
export type EntityExtractionResult = z.infer<typeof EntityExtractionResultSchema>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Topic Schema
|
|
149
|
+
*/
|
|
150
|
+
export const TopicSchema = z.object({
|
|
151
|
+
id: z.string().uuid(),
|
|
152
|
+
name: z.string(),
|
|
153
|
+
confidence: z.number().min(0).max(1),
|
|
154
|
+
keywords: z.array(z.string()),
|
|
155
|
+
relevance: z.number().min(0).max(1),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Topic Type
|
|
160
|
+
*/
|
|
161
|
+
export type Topic = z.infer<typeof TopicSchema>;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Topic Extraction Result Schema
|
|
165
|
+
*/
|
|
166
|
+
export const TopicExtractionResultSchema = z.object({
|
|
167
|
+
topics: z.array(TopicSchema),
|
|
168
|
+
mainTopic: z.string().optional(),
|
|
169
|
+
topicHierarchy: z.array(z.object({
|
|
170
|
+
parent: z.string(),
|
|
171
|
+
children: z.array(z.string()),
|
|
172
|
+
})).default([]),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Topic Extraction Result Type
|
|
177
|
+
*/
|
|
178
|
+
export type TopicExtractionResult = z.infer<typeof TopicExtractionResultSchema>;
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Keyword Schema
|
|
182
|
+
*/
|
|
183
|
+
export const KeywordSchema = z.object({
|
|
184
|
+
text: z.string(),
|
|
185
|
+
score: z.number().min(0),
|
|
186
|
+
frequency: z.number().nonnegative(),
|
|
187
|
+
tfidf: z.number().min(0),
|
|
188
|
+
isKeyPhrase: z.boolean().default(false),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Keyword Type
|
|
193
|
+
*/
|
|
194
|
+
export type Keyword = z.infer<typeof KeywordSchema>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Keyword Extraction Result Schema
|
|
198
|
+
*/
|
|
199
|
+
export const KeywordExtractionResultSchema = z.object({
|
|
200
|
+
keywords: z.array(KeywordSchema),
|
|
201
|
+
keyPhrases: z.array(z.string()),
|
|
202
|
+
totalWords: z.number().nonnegative(),
|
|
203
|
+
uniqueWords: z.number().nonnegative(),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Keyword Extraction Result Type
|
|
208
|
+
*/
|
|
209
|
+
export type KeywordExtractionResult = z.infer<typeof KeywordExtractionResultSchema>;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Summary Result Schema
|
|
213
|
+
*/
|
|
214
|
+
export const SummaryResultSchema = z.object({
|
|
215
|
+
summary: z.string(),
|
|
216
|
+
keyPoints: z.array(z.string()),
|
|
217
|
+
originalLength: z.number().nonnegative(),
|
|
218
|
+
summaryLength: z.number().nonnegative(),
|
|
219
|
+
compressionRatio: z.number().min(0).max(1),
|
|
220
|
+
method: z.enum(['extractive', 'abstractive', 'hybrid']).default('extractive'),
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Summary Result Type
|
|
225
|
+
*/
|
|
226
|
+
export type SummaryResult = z.infer<typeof SummaryResultSchema>;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Fact Check Result Schema
|
|
230
|
+
*/
|
|
231
|
+
export const FactCheckResultSchema = z.object({
|
|
232
|
+
claim: z.string(),
|
|
233
|
+
verdict: z.enum(['true', 'false', 'partially_true', 'unverifiable', 'misleading']),
|
|
234
|
+
confidence: z.number().min(0).max(1),
|
|
235
|
+
explanation: z.string(),
|
|
236
|
+
sources: z.array(z.object({
|
|
237
|
+
url: z.string().url(),
|
|
238
|
+
title: z.string(),
|
|
239
|
+
credibility: z.number().min(0).max(1),
|
|
240
|
+
})),
|
|
241
|
+
corrections: z.array(z.string()).default([]),
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Fact Check Result Type
|
|
246
|
+
*/
|
|
247
|
+
export type FactCheckResult = z.infer<typeof FactCheckResultSchema>;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Comparison Result Schema
|
|
251
|
+
*/
|
|
252
|
+
export const ComparisonResultSchema = z.object({
|
|
253
|
+
subjects: z.array(z.string()).length(2),
|
|
254
|
+
similarities: z.array(z.string()),
|
|
255
|
+
differences: z.array(z.string()),
|
|
256
|
+
similarityScore: z.number().min(0).max(1),
|
|
257
|
+
aspects: z.array(z.object({
|
|
258
|
+
aspect: z.string(),
|
|
259
|
+
subject1Value: z.string(),
|
|
260
|
+
subject2Value: z.string(),
|
|
261
|
+
comparison: z.enum(['better', 'worse', 'equal', 'different']),
|
|
262
|
+
})),
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Comparison Result Type
|
|
267
|
+
*/
|
|
268
|
+
export type ComparisonResult = z.infer<typeof ComparisonResultSchema>;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Language Detection Result Schema
|
|
272
|
+
*/
|
|
273
|
+
export const LanguageDetectionResultSchema = z.object({
|
|
274
|
+
language: z.string(),
|
|
275
|
+
confidence: z.number().min(0).max(1),
|
|
276
|
+
alternatives: z.array(z.object({
|
|
277
|
+
language: z.string(),
|
|
278
|
+
confidence: z.number().min(0).max(1),
|
|
279
|
+
})).default([]),
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Language Detection Result Type
|
|
284
|
+
*/
|
|
285
|
+
export type LanguageDetectionResult = z.infer<typeof LanguageDetectionResultSchema>;
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Readability Result Schema
|
|
289
|
+
*/
|
|
290
|
+
export const ReadabilityResultSchema = z.object({
|
|
291
|
+
score: z.number().min(0).max(100),
|
|
292
|
+
grade: z.enum(['elementary', 'middle_school', 'high_school', 'college', 'graduate']),
|
|
293
|
+
metrics: z.object({
|
|
294
|
+
fleschKincaid: z.number(),
|
|
295
|
+
fleschReadingEase: z.number(),
|
|
296
|
+
gunningFog: z.number(),
|
|
297
|
+
smogIndex: z.number(),
|
|
298
|
+
colemanLiau: z.number(),
|
|
299
|
+
automatedReadability: z.number(),
|
|
300
|
+
}),
|
|
301
|
+
statistics: z.object({
|
|
302
|
+
wordCount: z.number().nonnegative(),
|
|
303
|
+
sentenceCount: z.number().nonnegative(),
|
|
304
|
+
syllableCount: z.number().nonnegative(),
|
|
305
|
+
avgWordsPerSentence: z.number(),
|
|
306
|
+
avgSyllablesPerWord: z.number(),
|
|
307
|
+
complexWordCount: z.number().nonnegative(),
|
|
308
|
+
complexWordPercentage: z.number().min(0).max(100),
|
|
309
|
+
}),
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Readability Result Type
|
|
314
|
+
*/
|
|
315
|
+
export type ReadabilityResult = z.infer<typeof ReadabilityResultSchema>;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Complete Analysis Result Schema
|
|
319
|
+
*/
|
|
320
|
+
export const CompleteAnalysisResultSchema = BaseResultSchema.extend({
|
|
321
|
+
request: AnalysisRequestSchema,
|
|
322
|
+
sentiment: SentimentResultSchema.optional(),
|
|
323
|
+
entities: EntityExtractionResultSchema.optional(),
|
|
324
|
+
topics: TopicExtractionResultSchema.optional(),
|
|
325
|
+
keywords: KeywordExtractionResultSchema.optional(),
|
|
326
|
+
summary: SummaryResultSchema.optional(),
|
|
327
|
+
factChecks: z.array(FactCheckResultSchema).optional(),
|
|
328
|
+
comparison: ComparisonResultSchema.optional(),
|
|
329
|
+
language: LanguageDetectionResultSchema.optional(),
|
|
330
|
+
readability: ReadabilityResultSchema.optional(),
|
|
331
|
+
rawContent: z.string().optional(),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Complete Analysis Result Type
|
|
336
|
+
*/
|
|
337
|
+
export type CompleteAnalysisResult = z.infer<typeof CompleteAnalysisResultSchema>;
|