gthinking 1.0.0
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/README.md +283 -0
- package/analysis.ts +986 -0
- package/creativity.ts +1002 -0
- package/dist/analysis.d.ts +52 -0
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +792 -0
- package/dist/analysis.js.map +1 -0
- package/dist/creativity.d.ts +80 -0
- package/dist/creativity.d.ts.map +1 -0
- package/dist/creativity.js +778 -0
- package/dist/creativity.js.map +1 -0
- package/dist/engine.d.ts +76 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +675 -0
- package/dist/engine.js.map +1 -0
- package/dist/examples.d.ts +7 -0
- package/dist/examples.d.ts.map +1 -0
- package/dist/examples.js +506 -0
- package/dist/examples.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +126 -0
- package/dist/index.js.map +1 -0
- package/dist/learning.d.ts +72 -0
- package/dist/learning.d.ts.map +1 -0
- package/dist/learning.js +615 -0
- package/dist/learning.js.map +1 -0
- package/dist/planning.d.ts +58 -0
- package/dist/planning.d.ts.map +1 -0
- package/dist/planning.js +824 -0
- package/dist/planning.js.map +1 -0
- package/dist/reasoning.d.ts +72 -0
- package/dist/reasoning.d.ts.map +1 -0
- package/dist/reasoning.js +792 -0
- package/dist/reasoning.js.map +1 -0
- package/dist/search-discovery.d.ts +73 -0
- package/dist/search-discovery.d.ts.map +1 -0
- package/dist/search-discovery.js +505 -0
- package/dist/search-discovery.js.map +1 -0
- package/dist/types.d.ts +535 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +77 -0
- package/dist/types.js.map +1 -0
- package/engine.ts +928 -0
- package/examples.ts +717 -0
- package/index.ts +106 -0
- package/learning.ts +779 -0
- package/package.json +51 -0
- package/planning.ts +1028 -0
- package/reasoning.ts +1019 -0
- package/search-discovery.ts +654 -0
- package/tsconfig.json +25 -0
- package/types.ts +674 -0
package/engine.ts
ADDED
|
@@ -0,0 +1,928 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sequential Thinking Engine
|
|
3
|
+
* Main orchestrator that integrates all thinking modules
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
// Core types
|
|
8
|
+
SequentialThinkingConfig,
|
|
9
|
+
ThinkingRequest,
|
|
10
|
+
ThinkingResponse,
|
|
11
|
+
ThinkingSession,
|
|
12
|
+
ThinkingStage,
|
|
13
|
+
StageResult,
|
|
14
|
+
ResponseMetadata,
|
|
15
|
+
TaskStatus,
|
|
16
|
+
ThinkingEvent,
|
|
17
|
+
ThinkingError,
|
|
18
|
+
|
|
19
|
+
// Search types
|
|
20
|
+
SearchResult,
|
|
21
|
+
AggregatedResult,
|
|
22
|
+
SourceType,
|
|
23
|
+
|
|
24
|
+
// Analysis types
|
|
25
|
+
AnalysisResult,
|
|
26
|
+
AnalysisType,
|
|
27
|
+
|
|
28
|
+
// Reasoning types
|
|
29
|
+
ReasoningSession,
|
|
30
|
+
ReasoningType,
|
|
31
|
+
ChainOfThought,
|
|
32
|
+
|
|
33
|
+
// Learning types
|
|
34
|
+
LearningContext,
|
|
35
|
+
Interaction,
|
|
36
|
+
KnowledgeNode,
|
|
37
|
+
|
|
38
|
+
// Planning types
|
|
39
|
+
Plan,
|
|
40
|
+
Task,
|
|
41
|
+
Resource,
|
|
42
|
+
ProgressReport,
|
|
43
|
+
|
|
44
|
+
// Creativity types
|
|
45
|
+
CreativeSession,
|
|
46
|
+
CreativityTechnique,
|
|
47
|
+
OutOfBoxThinking,
|
|
48
|
+
|
|
49
|
+
// Synthesis types
|
|
50
|
+
SynthesisResult,
|
|
51
|
+
Recommendation
|
|
52
|
+
} from './types';
|
|
53
|
+
|
|
54
|
+
import { EventEmitter } from 'events';
|
|
55
|
+
|
|
56
|
+
// Import all engines
|
|
57
|
+
import { SearchDiscoveryEngine } from './search-discovery';
|
|
58
|
+
import { AnalysisEngine } from './analysis';
|
|
59
|
+
import { ReasoningEngine } from './reasoning';
|
|
60
|
+
import { LearningEngine } from './learning';
|
|
61
|
+
import { PlanningEngine } from './planning';
|
|
62
|
+
import { CreativityEngine } from './creativity';
|
|
63
|
+
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// SYNTHESIS ENGINE
|
|
66
|
+
// ============================================================================
|
|
67
|
+
|
|
68
|
+
class SynthesisEngine {
|
|
69
|
+
synthesize(
|
|
70
|
+
query: string,
|
|
71
|
+
searchResults: SearchResult[],
|
|
72
|
+
analysisResults: AnalysisResult[],
|
|
73
|
+
reasoningSession: ReasoningSession,
|
|
74
|
+
creativeSession?: CreativeSession
|
|
75
|
+
): SynthesisResult {
|
|
76
|
+
// Extract key insights from each component
|
|
77
|
+
const insights = this.extractInsights(
|
|
78
|
+
searchResults,
|
|
79
|
+
analysisResults,
|
|
80
|
+
reasoningSession,
|
|
81
|
+
creativeSession
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Generate summary
|
|
85
|
+
const summary = this.generateSummary(query, insights);
|
|
86
|
+
|
|
87
|
+
// Generate recommendations
|
|
88
|
+
const recommendations = this.generateRecommendations(
|
|
89
|
+
query,
|
|
90
|
+
insights,
|
|
91
|
+
reasoningSession
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Identify gaps and uncertainties
|
|
95
|
+
const gaps = this.identifyGaps(searchResults, analysisResults);
|
|
96
|
+
const uncertainties = this.identifyUncertainties(reasoningSession);
|
|
97
|
+
|
|
98
|
+
// Calculate confidence
|
|
99
|
+
const confidence = this.calculateSynthesisConfidence(
|
|
100
|
+
searchResults,
|
|
101
|
+
analysisResults,
|
|
102
|
+
reasoningSession
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
id: `synthesis_${Date.now()}`,
|
|
107
|
+
sources: [
|
|
108
|
+
...searchResults.map(r => r.url),
|
|
109
|
+
`reasoning_${reasoningSession.id}`
|
|
110
|
+
],
|
|
111
|
+
summary,
|
|
112
|
+
keyInsights: insights,
|
|
113
|
+
recommendations,
|
|
114
|
+
confidence,
|
|
115
|
+
gaps,
|
|
116
|
+
uncertainties
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private extractInsights(
|
|
121
|
+
searchResults: SearchResult[],
|
|
122
|
+
analysisResults: AnalysisResult[],
|
|
123
|
+
reasoningSession: ReasoningSession,
|
|
124
|
+
creativeSession?: CreativeSession
|
|
125
|
+
): string[] {
|
|
126
|
+
const insights: string[] = [];
|
|
127
|
+
|
|
128
|
+
// From search
|
|
129
|
+
if (searchResults.length > 0) {
|
|
130
|
+
const topResult = searchResults[0];
|
|
131
|
+
insights.push(`Key finding from research: ${topResult.snippet.substring(0, 100)}...`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// From analysis
|
|
135
|
+
analysisResults.forEach(result => {
|
|
136
|
+
result.findings.forEach(finding => {
|
|
137
|
+
if (finding.confidence > 0.7) {
|
|
138
|
+
insights.push(`${result.type}: ${JSON.stringify(finding.value).substring(0, 100)}`);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// From reasoning
|
|
144
|
+
if (reasoningSession.steps.length > 0) {
|
|
145
|
+
const lastStep = reasoningSession.steps[reasoningSession.steps.length - 1];
|
|
146
|
+
insights.push(`Reasoning conclusion: ${lastStep.inference}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// From creativity
|
|
150
|
+
if (creativeSession) {
|
|
151
|
+
const topIdeas = creativeSession.ideas
|
|
152
|
+
.sort((a, b) => (b.novelty + b.feasibility + b.impact) - (a.novelty + a.feasibility + a.impact))
|
|
153
|
+
.slice(0, 2);
|
|
154
|
+
|
|
155
|
+
topIdeas.forEach(idea => {
|
|
156
|
+
insights.push(`Creative insight: ${idea.content.substring(0, 80)}...`);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return insights;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private generateSummary(query: string, insights: string[]): string {
|
|
164
|
+
return `Analysis of "${query}" reveals ${insights.length} key insights. ` +
|
|
165
|
+
`The synthesis combines research findings, logical reasoning, and creative exploration ` +
|
|
166
|
+
`to provide a comprehensive understanding of the topic.`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private generateRecommendations(
|
|
170
|
+
query: string,
|
|
171
|
+
insights: string[],
|
|
172
|
+
reasoningSession: ReasoningSession
|
|
173
|
+
): Recommendation[] {
|
|
174
|
+
const recommendations: Recommendation[] = [];
|
|
175
|
+
|
|
176
|
+
// Based on reasoning
|
|
177
|
+
if (reasoningSession.conclusion) {
|
|
178
|
+
recommendations.push({
|
|
179
|
+
id: `rec_${Date.now()}_1`,
|
|
180
|
+
action: `Proceed with approach suggested by ${reasoningSession.type} reasoning`,
|
|
181
|
+
rationale: reasoningSession.conclusion,
|
|
182
|
+
priority: reasoningSession.confidence > 0.7 ? 1 : 2,
|
|
183
|
+
expectedOutcome: 'Resolution based on logical analysis',
|
|
184
|
+
risks: ['Reasoning assumptions may not hold'],
|
|
185
|
+
confidence: reasoningSession.confidence
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// General recommendations
|
|
190
|
+
recommendations.push({
|
|
191
|
+
id: `rec_${Date.now()}_2`,
|
|
192
|
+
action: 'Gather additional data to validate findings',
|
|
193
|
+
rationale: 'More information increases confidence',
|
|
194
|
+
priority: 3,
|
|
195
|
+
expectedOutcome: 'Improved decision quality',
|
|
196
|
+
risks: ['Time delay'],
|
|
197
|
+
confidence: 0.8
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return recommendations;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private identifyGaps(
|
|
204
|
+
searchResults: SearchResult[],
|
|
205
|
+
analysisResults: AnalysisResult[]
|
|
206
|
+
): string[] {
|
|
207
|
+
const gaps: string[] = [];
|
|
208
|
+
|
|
209
|
+
if (searchResults.length < 5) {
|
|
210
|
+
gaps.push('Limited research coverage');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const lowConfidenceAnalysis = analysisResults.filter(r => r.confidence < 0.5);
|
|
214
|
+
if (lowConfidenceAnalysis.length > 0) {
|
|
215
|
+
gaps.push('Some analyses have low confidence');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return gaps;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
private identifyUncertainties(reasoningSession: ReasoningSession): string[] {
|
|
222
|
+
const uncertainties: string[] = [];
|
|
223
|
+
|
|
224
|
+
reasoningSession.steps.forEach(step => {
|
|
225
|
+
if (step.confidence < 0.7) {
|
|
226
|
+
uncertainties.push(`Step ${step.stepNumber}: ${step.inference}`);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
return uncertainties;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private calculateSynthesisConfidence(
|
|
234
|
+
searchResults: SearchResult[],
|
|
235
|
+
analysisResults: AnalysisResult[],
|
|
236
|
+
reasoningSession: ReasoningSession
|
|
237
|
+
): number {
|
|
238
|
+
const factors = [
|
|
239
|
+
searchResults.length > 0 ? searchResults[0].credibility : 0,
|
|
240
|
+
analysisResults.length > 0 ?
|
|
241
|
+
analysisResults.reduce((sum, r) => sum + r.confidence, 0) / analysisResults.length : 0,
|
|
242
|
+
reasoningSession.confidence
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
return factors.reduce((sum, f) => sum + f, 0) / factors.length;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ============================================================================
|
|
250
|
+
// MAIN SEQUENTIAL THINKING ENGINE
|
|
251
|
+
// ============================================================================
|
|
252
|
+
|
|
253
|
+
export class SequentialThinkingEngine extends EventEmitter {
|
|
254
|
+
private searchEngine: SearchDiscoveryEngine;
|
|
255
|
+
private analysisEngine: AnalysisEngine;
|
|
256
|
+
private reasoningEngine: ReasoningEngine;
|
|
257
|
+
private learningEngine: LearningEngine;
|
|
258
|
+
private planningEngine: PlanningEngine;
|
|
259
|
+
private creativityEngine: CreativityEngine;
|
|
260
|
+
private synthesisEngine: SynthesisEngine;
|
|
261
|
+
|
|
262
|
+
private config: SequentialThinkingConfig;
|
|
263
|
+
private sessions: Map<string, ThinkingSession> = new Map();
|
|
264
|
+
|
|
265
|
+
constructor(config: Partial<SequentialThinkingConfig> = {}) {
|
|
266
|
+
super();
|
|
267
|
+
|
|
268
|
+
this.config = {
|
|
269
|
+
maxSearchResults: 10,
|
|
270
|
+
analysisDepth: 'moderate',
|
|
271
|
+
reasoningComplexity: 'moderate',
|
|
272
|
+
learningEnabled: true,
|
|
273
|
+
creativityLevel: 'balanced',
|
|
274
|
+
planningDetail: 'detailed',
|
|
275
|
+
timeout: 60000,
|
|
276
|
+
retryAttempts: 3,
|
|
277
|
+
...config
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Initialize all engines
|
|
281
|
+
this.searchEngine = new SearchDiscoveryEngine();
|
|
282
|
+
this.analysisEngine = new AnalysisEngine();
|
|
283
|
+
this.reasoningEngine = new ReasoningEngine();
|
|
284
|
+
this.learningEngine = new LearningEngine();
|
|
285
|
+
this.planningEngine = new PlanningEngine();
|
|
286
|
+
this.creativityEngine = new CreativityEngine();
|
|
287
|
+
this.synthesisEngine = new SynthesisEngine();
|
|
288
|
+
|
|
289
|
+
// Set up event forwarding
|
|
290
|
+
this.setupEventForwarding();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private setupEventForwarding(): void {
|
|
294
|
+
// Forward events from all engines
|
|
295
|
+
const engines = [
|
|
296
|
+
this.searchEngine,
|
|
297
|
+
this.analysisEngine,
|
|
298
|
+
this.reasoningEngine,
|
|
299
|
+
this.learningEngine,
|
|
300
|
+
this.planningEngine,
|
|
301
|
+
this.creativityEngine
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
engines.forEach(engine => {
|
|
305
|
+
engine.on('*', (event: ThinkingEvent) => {
|
|
306
|
+
this.emit(event.type, event);
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Process a thinking request through all stages
|
|
313
|
+
*/
|
|
314
|
+
async think(request: ThinkingRequest): Promise<ThinkingResponse> {
|
|
315
|
+
const startTime = Date.now();
|
|
316
|
+
const stageResults: StageResult[] = [];
|
|
317
|
+
|
|
318
|
+
// Create or get session
|
|
319
|
+
const session = this.getOrCreateSession(request);
|
|
320
|
+
|
|
321
|
+
// Merge config
|
|
322
|
+
const config = { ...this.config, ...request.config };
|
|
323
|
+
|
|
324
|
+
this.emit('thinking_start', {
|
|
325
|
+
id: request.id,
|
|
326
|
+
stage: ThinkingStage.SEARCH,
|
|
327
|
+
timestamp: new Date(),
|
|
328
|
+
data: { query: request.query }
|
|
329
|
+
} as ThinkingEvent);
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
// Stage 1: Search & Discovery
|
|
333
|
+
if (this.shouldExecuteStage(request, ThinkingStage.SEARCH)) {
|
|
334
|
+
const searchResult = await this.executeSearch(request, config);
|
|
335
|
+
stageResults.push(searchResult);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Stage 2: Analysis
|
|
339
|
+
if (this.shouldExecuteStage(request, ThinkingStage.ANALYSIS)) {
|
|
340
|
+
const analysisResult = await this.executeAnalysis(request, stageResults, config);
|
|
341
|
+
stageResults.push(analysisResult);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Stage 3: Reasoning
|
|
345
|
+
if (this.shouldExecuteStage(request, ThinkingStage.REASONING)) {
|
|
346
|
+
const reasoningResult = await this.executeReasoning(request, stageResults, config);
|
|
347
|
+
stageResults.push(reasoningResult);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Stage 4: Learning (context enrichment)
|
|
351
|
+
if (config.learningEnabled && this.shouldExecuteStage(request, ThinkingStage.LEARNING)) {
|
|
352
|
+
const learningResult = await this.executeLearning(request, stageResults, config);
|
|
353
|
+
stageResults.push(learningResult);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Stage 5: Planning (if applicable)
|
|
357
|
+
if (this.shouldExecuteStage(request, ThinkingStage.PLANNING) && this.isPlanningRequest(request)) {
|
|
358
|
+
const planningResult = await this.executePlanning(request, stageResults, config);
|
|
359
|
+
stageResults.push(planningResult);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Stage 6: Creativity
|
|
363
|
+
if (this.shouldExecuteStage(request, ThinkingStage.CREATIVITY)) {
|
|
364
|
+
const creativityResult = await this.executeCreativity(request, stageResults, config);
|
|
365
|
+
stageResults.push(creativityResult);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Stage 7: Synthesis
|
|
369
|
+
const synthesisResult = await this.executeSynthesis(request, stageResults, config);
|
|
370
|
+
stageResults.push(synthesisResult);
|
|
371
|
+
|
|
372
|
+
// Generate final response
|
|
373
|
+
const response = this.generateResponse(request, stageResults, startTime);
|
|
374
|
+
|
|
375
|
+
// Record interaction for learning
|
|
376
|
+
if (config.learningEnabled) {
|
|
377
|
+
this.learningEngine.recordInteraction(
|
|
378
|
+
session.id,
|
|
379
|
+
request.query,
|
|
380
|
+
response.finalAnswer
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
this.emit('thinking_complete', {
|
|
385
|
+
id: request.id,
|
|
386
|
+
stage: ThinkingStage.EVALUATION,
|
|
387
|
+
timestamp: new Date(),
|
|
388
|
+
data: {
|
|
389
|
+
response,
|
|
390
|
+
stagesExecuted: stageResults.length,
|
|
391
|
+
processingTime: Date.now() - startTime
|
|
392
|
+
}
|
|
393
|
+
} as ThinkingEvent);
|
|
394
|
+
|
|
395
|
+
return response;
|
|
396
|
+
|
|
397
|
+
} catch (error) {
|
|
398
|
+
this.emit('thinking_error', {
|
|
399
|
+
id: request.id,
|
|
400
|
+
stage: ThinkingStage.EVALUATION,
|
|
401
|
+
timestamp: new Date(),
|
|
402
|
+
data: { error }
|
|
403
|
+
} as ThinkingEvent);
|
|
404
|
+
|
|
405
|
+
throw new ThinkingError(
|
|
406
|
+
`Thinking process failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
407
|
+
ThinkingStage.EVALUATION,
|
|
408
|
+
false,
|
|
409
|
+
error instanceof Error ? error : undefined
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ============================================================================
|
|
415
|
+
// STAGE EXECUTORS
|
|
416
|
+
// ============================================================================
|
|
417
|
+
|
|
418
|
+
private async executeSearch(
|
|
419
|
+
request: ThinkingRequest,
|
|
420
|
+
config: SequentialThinkingConfig
|
|
421
|
+
): Promise<StageResult> {
|
|
422
|
+
const startTime = Date.now();
|
|
423
|
+
|
|
424
|
+
const searchResults = await this.searchEngine.search(request.query, {
|
|
425
|
+
maxResults: config.maxSearchResults,
|
|
426
|
+
sources: [SourceType.WEB, SourceType.KNOWLEDGE_BASE]
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
return {
|
|
430
|
+
stage: ThinkingStage.SEARCH,
|
|
431
|
+
status: TaskStatus.COMPLETED,
|
|
432
|
+
input: { query: request.query },
|
|
433
|
+
output: { results: searchResults, count: searchResults.length },
|
|
434
|
+
processingTime: Date.now() - startTime,
|
|
435
|
+
confidence: searchResults.length > 0 ? searchResults[0].credibility : 0
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
private async executeAnalysis(
|
|
440
|
+
request: ThinkingRequest,
|
|
441
|
+
previousResults: StageResult[],
|
|
442
|
+
config: SequentialThinkingConfig
|
|
443
|
+
): Promise<StageResult> {
|
|
444
|
+
const startTime = Date.now();
|
|
445
|
+
|
|
446
|
+
const searchResult = previousResults.find(r => r.stage === ThinkingStage.SEARCH);
|
|
447
|
+
const content = searchResult ?
|
|
448
|
+
(searchResult.output as any).results.map((r: SearchResult) => r.snippet).join(' ') :
|
|
449
|
+
request.query;
|
|
450
|
+
|
|
451
|
+
const analysisTypes: AnalysisType[] = config.analysisDepth === 'deep' ?
|
|
452
|
+
['sentiment', 'entity', 'topic', 'keyword', 'summary', 'fact_check'] :
|
|
453
|
+
config.analysisDepth === 'surface' ?
|
|
454
|
+
['summary', 'keyword'] :
|
|
455
|
+
['sentiment', 'topic', 'summary'];
|
|
456
|
+
|
|
457
|
+
const analysisResults = await this.analysisEngine.analyze(content, {
|
|
458
|
+
types: analysisTypes,
|
|
459
|
+
depth: config.analysisDepth,
|
|
460
|
+
context: request.context
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
const avgConfidence = analysisResults.reduce((sum, r) => sum + r.confidence, 0) /
|
|
464
|
+
analysisResults.length;
|
|
465
|
+
|
|
466
|
+
return {
|
|
467
|
+
stage: ThinkingStage.ANALYSIS,
|
|
468
|
+
status: TaskStatus.COMPLETED,
|
|
469
|
+
input: { content: content.substring(0, 200) },
|
|
470
|
+
output: { results: analysisResults },
|
|
471
|
+
processingTime: Date.now() - startTime,
|
|
472
|
+
confidence: avgConfidence
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
private async executeReasoning(
|
|
477
|
+
request: ThinkingRequest,
|
|
478
|
+
previousResults: StageResult[],
|
|
479
|
+
config: SequentialThinkingConfig
|
|
480
|
+
): Promise<StageResult> {
|
|
481
|
+
const startTime = Date.now();
|
|
482
|
+
|
|
483
|
+
const reasoningType = this.inferReasoningType(request.query);
|
|
484
|
+
const maxSteps = config.reasoningComplexity === 'complex' ? 7 :
|
|
485
|
+
config.reasoningComplexity === 'simple' ? 3 : 5;
|
|
486
|
+
|
|
487
|
+
const reasoningSession = await this.reasoningEngine.reason(request.query, {
|
|
488
|
+
type: reasoningType,
|
|
489
|
+
maxSteps,
|
|
490
|
+
generateCOT: true
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
return {
|
|
494
|
+
stage: ThinkingStage.REASONING,
|
|
495
|
+
status: TaskStatus.COMPLETED,
|
|
496
|
+
input: { problem: request.query },
|
|
497
|
+
output: {
|
|
498
|
+
session: reasoningSession,
|
|
499
|
+
conclusion: reasoningSession.conclusion,
|
|
500
|
+
steps: reasoningSession.steps.length
|
|
501
|
+
},
|
|
502
|
+
processingTime: Date.now() - startTime,
|
|
503
|
+
confidence: reasoningSession.confidence
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
private async executeLearning(
|
|
508
|
+
request: ThinkingRequest,
|
|
509
|
+
previousResults: StageResult[],
|
|
510
|
+
config: SequentialThinkingConfig
|
|
511
|
+
): Promise<StageResult> {
|
|
512
|
+
const startTime = Date.now();
|
|
513
|
+
|
|
514
|
+
// Get relevant context
|
|
515
|
+
const context = this.learningEngine.getOrCreateContext(request.id);
|
|
516
|
+
const relevantContext = this.learningEngine.getRelevantContext(request.id, request.query);
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
stage: ThinkingStage.LEARNING,
|
|
520
|
+
status: TaskStatus.COMPLETED,
|
|
521
|
+
input: { query: request.query },
|
|
522
|
+
output: {
|
|
523
|
+
context,
|
|
524
|
+
relevantInteractions: relevantContext.interactions.length,
|
|
525
|
+
relevantPatterns: relevantContext.patterns.length,
|
|
526
|
+
relevantKnowledge: relevantContext.knowledge.length
|
|
527
|
+
},
|
|
528
|
+
processingTime: Date.now() - startTime,
|
|
529
|
+
confidence: relevantContext.patterns.length > 0 ? 0.8 : 0.5
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
private async executePlanning(
|
|
534
|
+
request: ThinkingRequest,
|
|
535
|
+
previousResults: StageResult[],
|
|
536
|
+
config: SequentialThinkingConfig
|
|
537
|
+
): Promise<StageResult> {
|
|
538
|
+
const startTime = Date.now();
|
|
539
|
+
|
|
540
|
+
const plan = this.planningEngine.createPlan(request.query, {
|
|
541
|
+
resources: [],
|
|
542
|
+
deadline: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) // 30 days
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
return {
|
|
546
|
+
stage: ThinkingStage.PLANNING,
|
|
547
|
+
status: TaskStatus.COMPLETED,
|
|
548
|
+
input: { goal: request.query },
|
|
549
|
+
output: {
|
|
550
|
+
plan,
|
|
551
|
+
taskCount: plan.tasks.length,
|
|
552
|
+
estimatedDuration: plan.tasks.reduce((sum, t) => sum + t.estimatedDuration, 0)
|
|
553
|
+
},
|
|
554
|
+
processingTime: Date.now() - startTime,
|
|
555
|
+
confidence: 0.75
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
private async executeCreativity(
|
|
560
|
+
request: ThinkingRequest,
|
|
561
|
+
previousResults: StageResult[],
|
|
562
|
+
config: SequentialThinkingConfig
|
|
563
|
+
): Promise<StageResult> {
|
|
564
|
+
const startTime = Date.now();
|
|
565
|
+
|
|
566
|
+
const techniques: CreativityTechnique[] = config.creativityLevel === 'adventurous' ?
|
|
567
|
+
['brainstorming', 'scamper', 'six_thinking_hats', 'lateral_thinking', 'analogy'] :
|
|
568
|
+
config.creativityLevel === 'conservative' ?
|
|
569
|
+
['brainstorming'] :
|
|
570
|
+
['brainstorming', 'scamper', 'analogy'];
|
|
571
|
+
|
|
572
|
+
const creativeSession = this.creativityEngine.startSession(request.query, {
|
|
573
|
+
techniques,
|
|
574
|
+
ideaCount: 15
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
return {
|
|
578
|
+
stage: ThinkingStage.CREATIVITY,
|
|
579
|
+
status: TaskStatus.COMPLETED,
|
|
580
|
+
input: { prompt: request.query },
|
|
581
|
+
output: {
|
|
582
|
+
session: creativeSession,
|
|
583
|
+
ideaCount: creativeSession.ideas.length,
|
|
584
|
+
connectionCount: creativeSession.connections.length,
|
|
585
|
+
topIdeas: creativeSession.convergentPhase.selectedIdeas
|
|
586
|
+
},
|
|
587
|
+
processingTime: Date.now() - startTime,
|
|
588
|
+
confidence: creativeSession.ideas.length > 5 ? 0.8 : 0.5
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
private async executeSynthesis(
|
|
593
|
+
request: ThinkingRequest,
|
|
594
|
+
stageResults: StageResult[],
|
|
595
|
+
config: SequentialThinkingConfig
|
|
596
|
+
): Promise<StageResult> {
|
|
597
|
+
const startTime = Date.now();
|
|
598
|
+
|
|
599
|
+
const searchResults = (stageResults.find(r => r.stage === ThinkingStage.SEARCH)?.output as any)?.results || [];
|
|
600
|
+
const analysisResults = (stageResults.find(r => r.stage === ThinkingStage.ANALYSIS)?.output as any)?.results || [];
|
|
601
|
+
const reasoningSession = (stageResults.find(r => r.stage === ThinkingStage.REASONING)?.output as any)?.session;
|
|
602
|
+
const creativeSession = (stageResults.find(r => r.stage === ThinkingStage.CREATIVITY)?.output as any)?.session;
|
|
603
|
+
|
|
604
|
+
const synthesis = this.synthesisEngine.synthesize(
|
|
605
|
+
request.query,
|
|
606
|
+
searchResults,
|
|
607
|
+
analysisResults,
|
|
608
|
+
reasoningSession,
|
|
609
|
+
creativeSession
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
stage: ThinkingStage.SYNTHESIS,
|
|
614
|
+
status: TaskStatus.COMPLETED,
|
|
615
|
+
input: { query: request.query },
|
|
616
|
+
output: { synthesis },
|
|
617
|
+
processingTime: Date.now() - startTime,
|
|
618
|
+
confidence: synthesis.confidence
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// ============================================================================
|
|
623
|
+
// RESPONSE GENERATION
|
|
624
|
+
// ============================================================================
|
|
625
|
+
|
|
626
|
+
private generateResponse(
|
|
627
|
+
request: ThinkingRequest,
|
|
628
|
+
stageResults: StageResult[],
|
|
629
|
+
startTime: number
|
|
630
|
+
): ThinkingResponse {
|
|
631
|
+
const synthesisResult = stageResults.find(r => r.stage === ThinkingStage.SYNTHESIS);
|
|
632
|
+
const synthesis = (synthesisResult?.output as any)?.synthesis as SynthesisResult;
|
|
633
|
+
|
|
634
|
+
const reasoningResult = stageResults.find(r => r.stage === ThinkingStage.REASONING);
|
|
635
|
+
const reasoning = (reasoningResult?.output as any)?.session as ReasoningSession;
|
|
636
|
+
|
|
637
|
+
const creativeResult = stageResults.find(r => r.stage === ThinkingStage.CREATIVITY);
|
|
638
|
+
const creative = (creativeResult?.output as any)?.session as CreativeSession;
|
|
639
|
+
|
|
640
|
+
// Build final answer
|
|
641
|
+
const parts: string[] = [];
|
|
642
|
+
|
|
643
|
+
// Add synthesis summary
|
|
644
|
+
if (synthesis) {
|
|
645
|
+
parts.push(synthesis.summary);
|
|
646
|
+
parts.push('');
|
|
647
|
+
parts.push('Key Insights:');
|
|
648
|
+
synthesis.keyInsights.forEach((insight, i) => {
|
|
649
|
+
parts.push(`${i + 1}. ${insight}`);
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Add reasoning conclusion
|
|
654
|
+
if (reasoning?.conclusion) {
|
|
655
|
+
parts.push('');
|
|
656
|
+
parts.push('Reasoning:');
|
|
657
|
+
parts.push(reasoning.conclusion);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// Add creative insights
|
|
661
|
+
if (creative) {
|
|
662
|
+
parts.push('');
|
|
663
|
+
parts.push('Creative Perspectives:');
|
|
664
|
+
const topIdeas = creative.ideas
|
|
665
|
+
.sort((a, b) => (b.novelty + b.feasibility + b.impact) - (a.novelty + a.feasibility + a.impact))
|
|
666
|
+
.slice(0, 3);
|
|
667
|
+
|
|
668
|
+
topIdeas.forEach((idea, i) => {
|
|
669
|
+
parts.push(`${i + 1}. ${idea.content.substring(0, 100)}...`);
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Add recommendations
|
|
674
|
+
if (synthesis?.recommendations) {
|
|
675
|
+
parts.push('');
|
|
676
|
+
parts.push('Recommendations:');
|
|
677
|
+
synthesis.recommendations.forEach((rec, i) => {
|
|
678
|
+
parts.push(`${i + 1}. ${rec.action} (Confidence: ${Math.round(rec.confidence * 100)}%)`);
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const finalAnswer = parts.join('\n');
|
|
683
|
+
|
|
684
|
+
// Calculate metadata
|
|
685
|
+
const searchResult = stageResults.find(r => r.stage === ThinkingStage.SEARCH);
|
|
686
|
+
const sourcesUsed = ((searchResult?.output as any)?.results as SearchResult[] || []).length;
|
|
687
|
+
|
|
688
|
+
const reasoningSteps = reasoning?.steps.length || 0;
|
|
689
|
+
const ideasGenerated = creative?.ideas.length || 0;
|
|
690
|
+
|
|
691
|
+
const planningResult = stageResults.find(r => r.stage === ThinkingStage.PLANNING);
|
|
692
|
+
const tasksCreated = ((planningResult?.output as any)?.plan as Plan)?.tasks.length || 0;
|
|
693
|
+
|
|
694
|
+
const metadata: ResponseMetadata = {
|
|
695
|
+
sourcesUsed,
|
|
696
|
+
reasoningSteps,
|
|
697
|
+
ideasGenerated,
|
|
698
|
+
tasksCreated,
|
|
699
|
+
knowledgeNodesAccessed: 0
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// Calculate overall confidence
|
|
703
|
+
const confidenceScores = stageResults.map(r => r.confidence).filter(c => c > 0);
|
|
704
|
+
const overallConfidence = confidenceScores.length > 0 ?
|
|
705
|
+
confidenceScores.reduce((sum, c) => sum + c, 0) / confidenceScores.length :
|
|
706
|
+
0.5;
|
|
707
|
+
|
|
708
|
+
return {
|
|
709
|
+
id: `response_${Date.now()}`,
|
|
710
|
+
requestId: request.id,
|
|
711
|
+
stages: stageResults,
|
|
712
|
+
finalAnswer,
|
|
713
|
+
confidence: overallConfidence,
|
|
714
|
+
processingTime: Date.now() - startTime,
|
|
715
|
+
metadata,
|
|
716
|
+
timestamp: new Date()
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// ============================================================================
|
|
721
|
+
// UTILITY METHODS
|
|
722
|
+
// ============================================================================
|
|
723
|
+
|
|
724
|
+
private getOrCreateSession(request: ThinkingRequest): ThinkingSession {
|
|
725
|
+
if (this.sessions.has(request.id)) {
|
|
726
|
+
return this.sessions.get(request.id)!;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
const session: ThinkingSession = {
|
|
730
|
+
id: request.id,
|
|
731
|
+
requests: [request],
|
|
732
|
+
responses: [],
|
|
733
|
+
context: this.learningEngine.getOrCreateContext(request.id),
|
|
734
|
+
startTime: new Date(),
|
|
735
|
+
lastActivity: new Date()
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
this.sessions.set(request.id, session);
|
|
739
|
+
return session;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
private shouldExecuteStage(request: ThinkingRequest, stage: ThinkingStage): boolean {
|
|
743
|
+
if (!request.preferredStages) return true;
|
|
744
|
+
return request.preferredStages.length === 0 || request.preferredStages.includes(stage);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
private isPlanningRequest(request: ThinkingRequest): boolean {
|
|
748
|
+
const planningKeywords = ['plan', 'build', 'create', 'develop', 'implement', 'project', 'strategy'];
|
|
749
|
+
return planningKeywords.some(kw => request.query.toLowerCase().includes(kw));
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
private inferReasoningType(query: string): ReasoningType {
|
|
753
|
+
const queryLower = query.toLowerCase();
|
|
754
|
+
|
|
755
|
+
if (queryLower.includes('why') || queryLower.includes('because')) {
|
|
756
|
+
return ReasoningType.CAUSAL;
|
|
757
|
+
}
|
|
758
|
+
if (queryLower.includes('what if') || queryLower.includes('suppose')) {
|
|
759
|
+
return ReasoningType.COUNTERFACTUAL;
|
|
760
|
+
}
|
|
761
|
+
if (queryLower.includes('similar') || queryLower.includes('like')) {
|
|
762
|
+
return ReasoningType.ANALOGICAL;
|
|
763
|
+
}
|
|
764
|
+
if (queryLower.includes('pattern') || queryLower.includes('trend')) {
|
|
765
|
+
return ReasoningType.INDUCTIVE;
|
|
766
|
+
}
|
|
767
|
+
if (queryLower.includes('best explanation') || queryLower.includes('probably')) {
|
|
768
|
+
return ReasoningType.ABDUCTIVE;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return ReasoningType.DEDUCTIVE;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// ============================================================================
|
|
775
|
+
// PUBLIC API METHODS
|
|
776
|
+
// ============================================================================
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* Quick search and answer
|
|
780
|
+
*/
|
|
781
|
+
async quickSearch(query: string): Promise<ThinkingResponse> {
|
|
782
|
+
return this.think({
|
|
783
|
+
id: `quick_${Date.now()}`,
|
|
784
|
+
query,
|
|
785
|
+
preferredStages: [ThinkingStage.SEARCH, ThinkingStage.ANALYSIS, ThinkingStage.SYNTHESIS],
|
|
786
|
+
config: {
|
|
787
|
+
analysisDepth: 'surface',
|
|
788
|
+
reasoningComplexity: 'simple',
|
|
789
|
+
learningEnabled: false,
|
|
790
|
+
creativityLevel: 'conservative'
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Deep analysis with all stages
|
|
797
|
+
*/
|
|
798
|
+
async deepAnalysis(query: string, context?: string): Promise<ThinkingResponse> {
|
|
799
|
+
return this.think({
|
|
800
|
+
id: `deep_${Date.now()}`,
|
|
801
|
+
query,
|
|
802
|
+
context,
|
|
803
|
+
config: {
|
|
804
|
+
analysisDepth: 'deep',
|
|
805
|
+
reasoningComplexity: 'complex',
|
|
806
|
+
learningEnabled: true,
|
|
807
|
+
creativityLevel: 'adventurous',
|
|
808
|
+
planningDetail: 'granular'
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Creative problem solving
|
|
815
|
+
*/
|
|
816
|
+
async creativeSolve(problem: string): Promise<ThinkingResponse> {
|
|
817
|
+
return this.think({
|
|
818
|
+
id: `creative_${Date.now()}`,
|
|
819
|
+
query: problem,
|
|
820
|
+
preferredStages: [
|
|
821
|
+
ThinkingStage.SEARCH,
|
|
822
|
+
ThinkingStage.ANALYSIS,
|
|
823
|
+
ThinkingStage.REASONING,
|
|
824
|
+
ThinkingStage.CREATIVITY,
|
|
825
|
+
ThinkingStage.SYNTHESIS
|
|
826
|
+
],
|
|
827
|
+
config: {
|
|
828
|
+
creativityLevel: 'adventurous',
|
|
829
|
+
analysisDepth: 'moderate'
|
|
830
|
+
}
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/**
|
|
835
|
+
* Create a plan for a goal
|
|
836
|
+
*/
|
|
837
|
+
async createPlan(goal: string, options?: { resources?: Resource[]; deadline?: Date }): Promise<Plan> {
|
|
838
|
+
return this.planningEngine.createPlan(goal, options);
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Update config
|
|
843
|
+
*/
|
|
844
|
+
updateConfig(config: Partial<SequentialThinkingConfig>): void {
|
|
845
|
+
this.config = { ...this.config, ...config };
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Get session history
|
|
850
|
+
*/
|
|
851
|
+
getSession(sessionId: string): ThinkingSession | undefined {
|
|
852
|
+
return this.sessions.get(sessionId);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Get all sessions
|
|
857
|
+
*/
|
|
858
|
+
getAllSessions(): ThinkingSession[] {
|
|
859
|
+
return Array.from(this.sessions.values());
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* Export knowledge graph
|
|
864
|
+
*/
|
|
865
|
+
exportKnowledgeGraph(): string {
|
|
866
|
+
return this.learningEngine.exportKnowledgeGraph();
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* Import knowledge graph
|
|
871
|
+
*/
|
|
872
|
+
importKnowledgeGraph(json: string): void {
|
|
873
|
+
this.learningEngine.importKnowledgeGraph(json);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// ============================================================================
|
|
878
|
+
// EXPORT SINGLETON INSTANCE
|
|
879
|
+
// ============================================================================
|
|
880
|
+
|
|
881
|
+
export const thinkingEngine = new SequentialThinkingEngine();
|
|
882
|
+
|
|
883
|
+
// ============================================================================
|
|
884
|
+
// EXAMPLE USAGE
|
|
885
|
+
// ============================================================================
|
|
886
|
+
|
|
887
|
+
/*
|
|
888
|
+
// Basic usage
|
|
889
|
+
const response = await thinkingEngine.think({
|
|
890
|
+
id: 'request_1',
|
|
891
|
+
query: 'What are the implications of quantum computing for cybersecurity?',
|
|
892
|
+
config: {
|
|
893
|
+
analysisDepth: 'deep',
|
|
894
|
+
reasoningComplexity: 'complex'
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
console.log(response.finalAnswer);
|
|
899
|
+
console.log(`Confidence: ${response.confidence}`);
|
|
900
|
+
console.log(`Processing time: ${response.processingTime}ms`);
|
|
901
|
+
|
|
902
|
+
// Quick search
|
|
903
|
+
const quick = await thinkingEngine.quickSearch('Latest AI trends 2024');
|
|
904
|
+
|
|
905
|
+
// Deep analysis
|
|
906
|
+
const deep = await thinkingEngine.deepAnalysis(
|
|
907
|
+
'How will climate change affect global food security?',
|
|
908
|
+
'Focus on agricultural impacts'
|
|
909
|
+
);
|
|
910
|
+
|
|
911
|
+
// Creative problem solving
|
|
912
|
+
const creative = await thinkingEngine.creativeSolve(
|
|
913
|
+
'How can we make public transportation more appealing?'
|
|
914
|
+
);
|
|
915
|
+
|
|
916
|
+
// Create a plan
|
|
917
|
+
const plan = await thinkingEngine.createPlan(
|
|
918
|
+
'Launch a sustainable fashion brand',
|
|
919
|
+
{
|
|
920
|
+
deadline: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000) // 6 months
|
|
921
|
+
}
|
|
922
|
+
);
|
|
923
|
+
|
|
924
|
+
// Listen to events
|
|
925
|
+
thinkingEngine.on('thinking_complete', (event) => {
|
|
926
|
+
console.log(`Thinking completed: ${event.data.processingTime}ms`);
|
|
927
|
+
});
|
|
928
|
+
*/
|