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,201 @@
1
+ /**
2
+ * Google Gemini LLM Provider
3
+ *
4
+ * @module llm/providers/gemini
5
+ */
6
+
7
+ import axios from 'axios';
8
+ import { BaseLLMProvider, type LLMMessage, type LLMRequestOptions, type LLMResponse, type LLMStreamChunk } from './base';
9
+ import { LLMError } from '../../core/errors';
10
+ import { logger } from '../../utils/logger';
11
+
12
+ /**
13
+ * Gemini provider configuration
14
+ */
15
+ export interface GeminiConfig {
16
+ apiKey: string;
17
+ model?: string;
18
+ baseUrl?: string;
19
+ timeoutMs?: number;
20
+ maxRetries?: number;
21
+ }
22
+
23
+ /**
24
+ * Gemini provider implementation
25
+ */
26
+ export class GeminiProvider extends BaseLLMProvider {
27
+ readonly name = 'gemini';
28
+ readonly availableModels = [
29
+ 'gemini-1.5-pro',
30
+ 'gemini-1.5-flash',
31
+ 'gemini-1.0-pro',
32
+ ];
33
+
34
+ constructor(config: GeminiConfig) {
35
+ super({
36
+ apiKey: config.apiKey,
37
+ baseUrl: config.baseUrl ?? 'https://generativelanguage.googleapis.com/v1beta',
38
+ defaultModel: config.model ?? 'gemini-1.5-pro',
39
+ timeoutMs: config.timeoutMs,
40
+ maxRetries: config.maxRetries,
41
+ });
42
+ }
43
+
44
+ async complete(
45
+ messages: LLMMessage[],
46
+ options: LLMRequestOptions = {}
47
+ ): Promise<LLMResponse> {
48
+ return this.withRetry(async () => {
49
+ const model = this.getModel(options);
50
+ const url = `${this.baseUrl}/models/${model}:generateContent?key=${this.apiKey}`;
51
+
52
+ const requestBody = this.buildRequestBody(messages, options);
53
+
54
+ try {
55
+ const response = await axios.post(url, requestBody, {
56
+ timeout: options.timeoutMs ?? this.timeoutMs,
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ },
60
+ });
61
+
62
+ return this.parseResponse(response.data, model);
63
+ } catch (error) {
64
+ if (axios.isAxiosError(error)) {
65
+ const statusCode = error.response?.status;
66
+ const errorMessage = error.response?.data?.error?.message ?? error.message;
67
+
68
+ logger.error('Gemini API error', { statusCode, errorMessage });
69
+ throw new LLMError(errorMessage, 'gemini', statusCode);
70
+ }
71
+ throw error;
72
+ }
73
+ });
74
+ }
75
+
76
+ async *stream(
77
+ messages: LLMMessage[],
78
+ options: LLMRequestOptions = {}
79
+ ): AsyncGenerator<LLMStreamChunk> {
80
+ const model = this.getModel(options);
81
+ const url = `${this.baseUrl}/models/${model}:streamGenerateContent?key=${this.apiKey}`;
82
+
83
+ const requestBody = this.buildRequestBody(messages, options);
84
+
85
+ try {
86
+ const response = await axios.post(url, requestBody, {
87
+ timeout: options.timeoutMs ?? this.timeoutMs,
88
+ headers: {
89
+ 'Content-Type': 'application/json',
90
+ },
91
+ responseType: 'stream',
92
+ });
93
+
94
+ const stream = response.data;
95
+
96
+ for await (const chunk of stream) {
97
+ const lines = chunk.toString().split('\n').filter((line: string) => line.trim());
98
+
99
+ for (const line of lines) {
100
+ try {
101
+ const data = JSON.parse(line);
102
+ const content = data.candidates?.[0]?.content?.parts?.[0]?.text ?? '';
103
+
104
+ if (content) {
105
+ yield {
106
+ content,
107
+ isComplete: false,
108
+ };
109
+ }
110
+ } catch {
111
+ // Ignore parse errors for non-JSON lines
112
+ }
113
+ }
114
+ }
115
+
116
+ yield {
117
+ content: '',
118
+ isComplete: true,
119
+ };
120
+ } catch (error) {
121
+ if (axios.isAxiosError(error)) {
122
+ const statusCode = error.response?.status;
123
+ const errorMessage = error.response?.data?.error?.message ?? error.message;
124
+ throw new LLMError(errorMessage, 'gemini', statusCode);
125
+ }
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ private buildRequestBody(messages: LLMMessage[], options: LLMRequestOptions): Record<string, unknown> {
131
+ const contents = messages.map(msg => ({
132
+ role: msg.role === 'user' ? 'user' : 'model',
133
+ parts: [{ text: msg.content }],
134
+ }));
135
+
136
+ const body: Record<string, unknown> = {
137
+ contents,
138
+ };
139
+
140
+ if (options.temperature !== undefined) {
141
+ body.generationConfig = {
142
+ ...(body.generationConfig as Record<string, unknown>),
143
+ temperature: options.temperature,
144
+ };
145
+ }
146
+
147
+ if (options.maxTokens !== undefined) {
148
+ body.generationConfig = {
149
+ ...(body.generationConfig as Record<string, unknown>),
150
+ maxOutputTokens: options.maxTokens,
151
+ };
152
+ }
153
+
154
+ if (options.topP !== undefined) {
155
+ body.generationConfig = {
156
+ ...(body.generationConfig as Record<string, unknown>),
157
+ topP: options.topP,
158
+ };
159
+ }
160
+
161
+ if (options.stopSequences !== undefined) {
162
+ body.generationConfig = {
163
+ ...(body.generationConfig as Record<string, unknown>),
164
+ stopSequences: options.stopSequences,
165
+ };
166
+ }
167
+
168
+ return body;
169
+ }
170
+
171
+ private parseResponse(data: Record<string, unknown>, model: string): LLMResponse {
172
+ const candidate = (data.candidates as unknown[])?.[0] as Record<string, unknown> | undefined;
173
+ const content = candidate?.content as Record<string, unknown> | undefined;
174
+ const parts = content?.parts as Array<{ text?: string }> | undefined;
175
+ const text = parts?.[0]?.text ?? '';
176
+
177
+ const usage = data.usageMetadata as Record<string, number> | undefined;
178
+
179
+ return {
180
+ content: text,
181
+ model,
182
+ usage: {
183
+ promptTokens: usage?.promptTokenCount ?? 0,
184
+ completionTokens: usage?.candidatesTokenCount ?? 0,
185
+ totalTokens: usage?.totalTokenCount ?? 0,
186
+ },
187
+ finishReason: (candidate?.finishReason as string) ?? 'stop',
188
+ };
189
+ }
190
+
191
+ protected override isNonRetryableError(error: unknown): boolean {
192
+ if (axios.isAxiosError(error)) {
193
+ const statusCode = error.response?.status;
194
+ // Don't retry on client errors (4xx except 429)
195
+ if (statusCode !== undefined && statusCode >= 400 && statusCode < 500 && statusCode !== 429) {
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Input Sanitization for LLM Service
3
+ *
4
+ * Provides security-focused sanitization to prevent prompt injection
5
+ * and other LLM-related security vulnerabilities.
6
+ *
7
+ * @module llm/sanitization
8
+ */
9
+
10
+ import { logger } from '../utils/logger';
11
+
12
+ /**
13
+ * Sanitization options
14
+ */
15
+ export interface SanitizationOptions {
16
+ maxLength?: number;
17
+ allowCode?: boolean;
18
+ allowHTML?: boolean;
19
+ allowedTags?: string[];
20
+ }
21
+
22
+ /**
23
+ * Default sanitization options
24
+ */
25
+ const DEFAULT_OPTIONS: SanitizationOptions = {
26
+ maxLength: 10000,
27
+ allowCode: false,
28
+ allowHTML: false,
29
+ allowedTags: [],
30
+ };
31
+
32
+ /**
33
+ * Dangerous patterns that could indicate prompt injection
34
+ */
35
+ const DANGEROUS_PATTERNS = [
36
+ // System prompt injection attempts
37
+ /ignore\s+(previous|prior|above)\s+instructions?/gi,
38
+ /disregard\s+(all\s+)?(previous|prior)\s+instructions?/gi,
39
+ /forget\s+(everything|all)\s+(you\s+)?(were\s+)?told/gi,
40
+ /system\s*:\s*/gi,
41
+ /user\s*:\s*/gi,
42
+ /assistant\s*:\s*/gi,
43
+ /\[system\s+prompt\]/gi,
44
+ /\[instructions\]/gi,
45
+
46
+ // Jailbreak attempts
47
+ /DAN\s*\(|do\s+anything\s+now/gi,
48
+ /jailbreak/gi,
49
+ /\bmode\s*:\s*\w+\s+unfiltered/gi,
50
+ /no\s+(restrictions?|limits?|filter)/gi,
51
+
52
+ // Delimiter manipulation
53
+ /```\s*system/gi,
54
+ /<\|system\|>/gi,
55
+ /<\|im_start\|>/gi,
56
+ /<\|im_end\|>/gi,
57
+ ];
58
+
59
+ /**
60
+ * Sanitize a prompt for LLM use
61
+ *
62
+ * @param input - Raw input string
63
+ * @param options - Sanitization options
64
+ * @returns Sanitized string
65
+ */
66
+ export function sanitizePrompt(input: string, options: SanitizationOptions = {}): string {
67
+ const opts = { ...DEFAULT_OPTIONS, ...options };
68
+
69
+ // Check for dangerous patterns
70
+ for (const pattern of DANGEROUS_PATTERNS) {
71
+ if (pattern.test(input)) {
72
+ logger.warn('Potentially dangerous pattern detected in prompt', { pattern: pattern.source });
73
+ }
74
+ }
75
+
76
+ let sanitized = input;
77
+
78
+ // Remove null bytes and control characters
79
+ sanitized = sanitized.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
80
+
81
+ // Remove potential prompt injection markers
82
+ sanitized = sanitized.replace(/^(system|user|assistant)\s*:\s*/gim, '');
83
+
84
+ // Remove system prompt markers
85
+ sanitized = sanitized.replace(/\[system\s+prompt\]/gi, '');
86
+ sanitized = sanitized.replace(/\[instructions?\]/gi, '');
87
+
88
+ // Handle code blocks
89
+ if (!opts.allowCode) {
90
+ // Escape code block markers
91
+ sanitized = sanitized.replace(/```/g, '` ` `');
92
+ }
93
+
94
+ // Handle HTML
95
+ if (!opts.allowHTML) {
96
+ // Remove or escape HTML tags
97
+ sanitized = sanitized.replace(/</g, '&lt;').replace(/>/g, '&gt;');
98
+ }
99
+
100
+ // Trim whitespace
101
+ sanitized = sanitized.trim();
102
+
103
+ // Enforce length limit
104
+ if (sanitized.length > opts.maxLength!) {
105
+ logger.warn('Prompt truncated due to length limit', {
106
+ originalLength: sanitized.length,
107
+ maxLength: opts.maxLength
108
+ });
109
+ sanitized = sanitized.substring(0, opts.maxLength);
110
+ }
111
+
112
+ return sanitized;
113
+ }
114
+
115
+ /**
116
+ * Validate that a prompt is safe to use
117
+ *
118
+ * @param input - Input to validate
119
+ * @returns Validation result
120
+ */
121
+ export function validatePrompt(input: string): { safe: boolean; issues: string[] } {
122
+ const issues: string[] = [];
123
+
124
+ // Check for dangerous patterns
125
+ for (const pattern of DANGEROUS_PATTERNS) {
126
+ if (pattern.test(input)) {
127
+ issues.push(`Suspicious pattern detected: ${pattern.source}`);
128
+ }
129
+ }
130
+
131
+ // Check length
132
+ if (input.length > 10000) {
133
+ issues.push('Input exceeds maximum length of 10000 characters');
134
+ }
135
+
136
+ // Check for null bytes
137
+ if (/\x00/.test(input)) {
138
+ issues.push('Input contains null bytes');
139
+ }
140
+
141
+ return {
142
+ safe: issues.length === 0,
143
+ issues,
144
+ };
145
+ }
146
+
147
+ /**
148
+ * Escape special characters for safe inclusion in prompts
149
+ *
150
+ * @param input - Input to escape
151
+ * @returns Escaped string
152
+ */
153
+ export function escapeSpecialChars(input: string): string {
154
+ return input
155
+ .replace(/\\/g, '\\\\')
156
+ .replace(/"/g, '\\"')
157
+ .replace(/\n/g, '\\n')
158
+ .replace(/\r/g, '\\r')
159
+ .replace(/\t/g, '\\t');
160
+ }
161
+
162
+ /**
163
+ * Sanitize LLM response to remove any system-like content
164
+ *
165
+ * @param response - LLM response
166
+ * @returns Sanitized response
167
+ */
168
+ export function sanitizeResponse(response: string): string {
169
+ let sanitized = response;
170
+
171
+ // Remove system-like prefixes
172
+ sanitized = sanitized.replace(/^(system|user|assistant)\s*:\s*/gim, '');
173
+
174
+ // Remove any embedded instructions
175
+ sanitized = sanitized.replace(/\[system\s+prompt\].*?\[\/system\s+prompt\]/gis, '');
176
+
177
+ return sanitized.trim();
178
+ }
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ } from "@modelcontextprotocol/sdk/types.js";
9
+ import { SequentialThinkingEngine } from "../core/engine";
10
+ import { Logger } from "../utils/logger";
11
+
12
+ const logger = new Logger('MCPServer');
13
+ const engine = new SequentialThinkingEngine();
14
+
15
+ const server = new Server(
16
+ {
17
+ name: "gthinking",
18
+ version: "2.0.0",
19
+ },
20
+ {
21
+ capabilities: {
22
+ tools: {},
23
+ },
24
+ }
25
+ );
26
+
27
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
28
+ return {
29
+ tools: [
30
+ {
31
+ name: "think",
32
+ description: "Execute full thinking pipeline",
33
+ inputSchema: {
34
+ type: "object",
35
+ properties: {
36
+ query: { type: "string" },
37
+ preferredStages: {
38
+ type: "array",
39
+ items: { type: "string" }
40
+ },
41
+ options: { type: "object" }
42
+ },
43
+ required: ["query"]
44
+ }
45
+ },
46
+ {
47
+ name: "quick_search",
48
+ description: "Execute quick search",
49
+ inputSchema: {
50
+ type: "object",
51
+ properties: {
52
+ query: { type: "string" }
53
+ },
54
+ required: ["query"]
55
+ }
56
+ },
57
+ {
58
+ name: "creative_solve",
59
+ description: "Solve problem creatively",
60
+ inputSchema: {
61
+ type: "object",
62
+ properties: {
63
+ challenge: { type: "string" },
64
+ techniques: {
65
+ type: "array",
66
+ items: { type: "string" }
67
+ }
68
+ },
69
+ required: ["challenge"]
70
+ }
71
+ }
72
+ ]
73
+ };
74
+ });
75
+
76
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
77
+ const { name, arguments: args } = request.params;
78
+
79
+ try {
80
+ if (name === "think") {
81
+ const result = await engine.think(args);
82
+ return {
83
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
84
+ };
85
+ } else if (name === "quick_search") {
86
+ const query = (args as any).query;
87
+ const result = await engine.quickSearch(query);
88
+ return {
89
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
90
+ };
91
+ } else if (name === "creative_solve") {
92
+ const challenge = (args as any).challenge;
93
+ const result = await engine.creativeSolve(challenge);
94
+ return {
95
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
96
+ };
97
+ }
98
+
99
+ throw new Error(`Unknown tool: ${name}`);
100
+ } catch (error) {
101
+ return {
102
+ content: [{ type: "text", text: `Error: ${(error as Error).message}` }],
103
+ isError: true
104
+ };
105
+ }
106
+ });
107
+
108
+ async function run() {
109
+ const transport = new StdioServerTransport();
110
+ await server.connect(transport);
111
+ logger.info("MCP Server running on stdio");
112
+ }
113
+
114
+ run().catch((error) => {
115
+ console.error("Fatal error running server:", error);
116
+ process.exit(1);
117
+ });
@@ -0,0 +1,14 @@
1
+ import { EventEmitter } from 'events';
2
+ import { Logger } from '../utils/logger';
3
+
4
+ const logger = new Logger('PlanningEngine');
5
+
6
+ export class PlanningEngine extends EventEmitter {
7
+ constructor() {
8
+ super();
9
+ }
10
+ }
11
+
12
+ export function createPlanningEngine(): PlanningEngine {
13
+ return new PlanningEngine();
14
+ }
@@ -0,0 +1,14 @@
1
+ import { EventEmitter } from 'events';
2
+ import { Logger } from '../utils/logger';
3
+
4
+ const logger = new Logger('ReasoningEngine');
5
+
6
+ export class ReasoningEngine extends EventEmitter {
7
+ constructor() {
8
+ super();
9
+ }
10
+ }
11
+
12
+ export function createReasoningEngine(): ReasoningEngine {
13
+ return new ReasoningEngine();
14
+ }