@j0hanz/thinkseq-mcp 1.0.4 → 1.1.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 +238 -111
- package/dist/app.d.ts +2 -35
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +13 -91
- package/dist/app.js.map +1 -1
- package/dist/appConfig/runDependencies.d.ts +36 -0
- package/dist/appConfig/runDependencies.d.ts.map +1 -0
- package/dist/appConfig/runDependencies.js +65 -0
- package/dist/appConfig/runDependencies.js.map +1 -0
- package/dist/appConfig/shutdown.d.ts +19 -0
- package/dist/appConfig/shutdown.d.ts.map +1 -0
- package/dist/appConfig/shutdown.js +65 -0
- package/dist/appConfig/shutdown.js.map +1 -0
- package/dist/appConfig/types.d.ts +10 -0
- package/dist/appConfig/types.d.ts.map +1 -0
- package/dist/appConfig/types.js +2 -0
- package/dist/appConfig/types.js.map +1 -0
- package/dist/appConfig.d.ts +5 -0
- package/dist/appConfig.d.ts.map +1 -0
- package/dist/appConfig.js +3 -0
- package/dist/appConfig.js.map +1 -0
- package/dist/engine/pruning.d.ts +3 -0
- package/dist/engine/pruning.d.ts.map +1 -0
- package/dist/engine/pruning.js +11 -0
- package/dist/engine/pruning.js.map +1 -0
- package/dist/engine/revision.d.ts +9 -0
- package/dist/engine/revision.d.ts.map +1 -0
- package/dist/engine/revision.js +38 -0
- package/dist/engine/revision.js.map +1 -0
- package/dist/engine/thoughtQueries.d.ts +3 -0
- package/dist/engine/thoughtQueries.d.ts.map +1 -0
- package/dist/engine/thoughtQueries.js +18 -0
- package/dist/engine/thoughtQueries.js.map +1 -0
- package/dist/engine/thoughtStore.d.ts +22 -0
- package/dist/engine/thoughtStore.d.ts.map +1 -0
- package/dist/engine/thoughtStore.js +151 -0
- package/dist/engine/thoughtStore.js.map +1 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +65 -147
- package/dist/engine.js.map +1 -1
- package/dist/engineConfig.d.ts +11 -0
- package/dist/engineConfig.d.ts.map +1 -0
- package/dist/engineConfig.js +12 -0
- package/dist/engineConfig.js.map +1 -0
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/cli.d.ts +14 -0
- package/dist/lib/cli.d.ts.map +1 -0
- package/dist/lib/cli.js +71 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/context.d.ts +7 -0
- package/dist/lib/context.d.ts.map +1 -0
- package/dist/lib/context.js +15 -0
- package/dist/lib/context.js.map +1 -0
- package/dist/lib/diagnostics.d.ts +9 -8
- package/dist/lib/diagnostics.d.ts.map +1 -1
- package/dist/lib/diagnostics.js +18 -8
- package/dist/lib/diagnostics.js.map +1 -1
- package/dist/lib/engineWorkerHandler.d.ts +12 -0
- package/dist/lib/engineWorkerHandler.d.ts.map +1 -0
- package/dist/lib/engineWorkerHandler.js +44 -0
- package/dist/lib/engineWorkerHandler.js.map +1 -0
- package/dist/lib/package.d.ts.map +1 -1
- package/dist/lib/package.js +17 -7
- package/dist/lib/package.js.map +1 -1
- package/dist/lib/protocolGuards.d.ts.map +1 -1
- package/dist/lib/protocolGuards.js +8 -5
- package/dist/lib/protocolGuards.js.map +1 -1
- package/dist/lib/stdioGuards.d.ts.map +1 -1
- package/dist/lib/stdioGuards.js +23 -12
- package/dist/lib/stdioGuards.js.map +1 -1
- package/dist/lib/types.d.ts +15 -13
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/workerEngineClient.d.ts +23 -0
- package/dist/lib/workerEngineClient.d.ts.map +1 -0
- package/dist/lib/workerEngineClient.js +144 -0
- package/dist/lib/workerEngineClient.js.map +1 -0
- package/dist/lib/workerProtocol.d.ts +21 -0
- package/dist/lib/workerProtocol.d.ts.map +1 -0
- package/dist/lib/workerProtocol.js +22 -0
- package/dist/lib/workerProtocol.js.map +1 -0
- package/dist/schemas/inputs.d.ts +1 -13
- package/dist/schemas/inputs.d.ts.map +1 -1
- package/dist/schemas/inputs.js +5 -27
- package/dist/schemas/inputs.js.map +1 -1
- package/dist/schemas/outputs.d.ts +14 -16
- package/dist/schemas/outputs.d.ts.map +1 -1
- package/dist/schemas/outputs.js +48 -61
- package/dist/schemas/outputs.js.map +1 -1
- package/dist/tools/thinkseq.d.ts +7 -2
- package/dist/tools/thinkseq.d.ts.map +1 -1
- package/dist/tools/thinkseq.js +71 -59
- package/dist/tools/thinkseq.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workers/engineWorker.d.ts +2 -0
- package/dist/workers/engineWorker.d.ts.map +1 -0
- package/dist/workers/engineWorker.js +15 -0
- package/dist/workers/engineWorker.js.map +1 -0
- package/package.json +8 -6
package/README.md
CHANGED
|
@@ -1,130 +1,67 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ThinkSeq MCP Server
|
|
2
2
|
|
|
3
|
-
<img src="docs/logo.png" alt="
|
|
3
|
+
<img src="docs/logo.png" alt="ThinkSeq MCP Server Logo" width="175" />
|
|
4
4
|
|
|
5
|
-
An MCP
|
|
5
|
+
An MCP server for structured, sequential thinking with revision support.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@j0hanz/thinkseq-mcp)
|
|
8
8
|
|
|
9
|
-
## One-
|
|
9
|
+
## One-click install
|
|
10
10
|
|
|
11
11
|
[](https://insiders.vscode.dev/redirect/mcp/install?name=thinkseq&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fthinkseq-mcp%40latest%22%5D%7D) [](https://insiders.vscode.dev/redirect/mcp/install?name=thinkseq&inputs=%5B%5D&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40j0hanz%2Fthinkseq-mcp%40latest%22%5D%7D&quality=insiders)
|
|
12
12
|
|
|
13
13
|
[](https://cursor.com/install-mcp?name=thinkseq&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBqMGhhbnovdGhpbmtzZXEtbWNwQGxhdGVzdCJdfQ==)
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Overview
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
ThinkSeq exposes a single MCP tool, `thinkseq`, for structured, sequential thinking. The server runs over stdio and stores an in-memory thought history so it can return progress, active-path context, and revision metadata on each call.
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
| :------------------------- | :-------------------------------------------------------------------------------------- |
|
|
21
|
-
| 🧠 **Sequential Thinking** | Break down complex problems into manageable steps with maintained context. |
|
|
22
|
-
| 🌿 **Branching** | Explore multiple solution paths simultaneously without losing track of the main thread. |
|
|
23
|
-
| 🔄 **Revision Support** | Dynamically revise previous thoughts and conclusions based on new insights. |
|
|
24
|
-
| 🏗️ **Structured Output** | Returns structured data for better agent-reasoning loops. |
|
|
25
|
-
|
|
26
|
-
## 🎯 When to Use
|
|
27
|
-
|
|
28
|
-
Use `thinkseq` when the AI agent needs to:
|
|
29
|
-
|
|
30
|
-
- **Plan complex architectures** before writing code.
|
|
31
|
-
- **Analyze interdependent parameters** or conflicting information.
|
|
32
|
-
- **Debug tricky issues** where initial assumptions might need correction.
|
|
33
|
-
- **Determine feature prioritization** based on multiple constraints.
|
|
34
|
-
- **Structure a "Chain of Thought"** that is visible and reviewable.
|
|
35
|
-
|
|
36
|
-
## 🚀 Quick Start
|
|
37
|
-
|
|
38
|
-
The easiest way to use the server is via `npx`:
|
|
19
|
+
## Quick start
|
|
39
20
|
|
|
40
21
|
```bash
|
|
41
22
|
npx -y @j0hanz/thinkseq-mcp@latest
|
|
42
23
|
```
|
|
43
24
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
### NPX (Recommended)
|
|
25
|
+
## CLI options
|
|
47
26
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"thinkseq": {
|
|
53
|
-
"command": "npx",
|
|
54
|
-
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
55
|
-
}
|
|
56
|
-
}
|
|
27
|
+
```bash
|
|
28
|
+
thinkseq --max-thoughts 500 --max-memory-mb 100
|
|
57
29
|
```
|
|
58
30
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
1. Clone the repository:
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
git clone https://github.com/j0hanz/thinkseq-mcp-server.git
|
|
65
|
-
cd thinkseq-mcp
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
2. Install dependencies:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
npm install
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
3. Build the server:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
npm run build
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
4. Start the server:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
npm start
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## ⚙️ Configuration
|
|
87
|
-
|
|
88
|
-
The server currently does not require environment variables or command-line arguments for basic operation. It runs over stdio by default.
|
|
31
|
+
Available flags:
|
|
89
32
|
|
|
90
|
-
|
|
33
|
+
- `--max-thoughts <number>`: Max thoughts to keep in memory.
|
|
34
|
+
- `--max-memory-mb <number>`: Max memory (MB) for stored thoughts.
|
|
35
|
+
- `--shutdown-timeout-ms <number>`: Graceful shutdown timeout.
|
|
36
|
+
- `--package-read-timeout-ms <number>`: Package.json read timeout.
|
|
37
|
+
- `-h, --help`: Show help.
|
|
91
38
|
|
|
92
|
-
|
|
39
|
+
Defaults and limits:
|
|
93
40
|
|
|
94
|
-
|
|
41
|
+
- `maxThoughts` default: 500 (cap 10000).
|
|
42
|
+
- `maxMemoryBytes` default: 100 MB (derived from `--max-memory-mb`).
|
|
43
|
+
- `packageReadTimeoutMs` default: 2000 ms.
|
|
44
|
+
- `shutdownTimeoutMs` default: 5000 ms.
|
|
95
45
|
|
|
96
|
-
|
|
97
|
-
| :------------------ | :------ | :------- | :------ | :------------------------------------------------------------------------ |
|
|
98
|
-
| `thought` | string | ✅ | - | Your current thinking step. |
|
|
99
|
-
| `thoughtNumber` | number | ✅ | - | Current thought number in sequence (starts at 1). |
|
|
100
|
-
| `totalThoughts` | number | ✅ | - | Estimated total thoughts needed (can adjust). |
|
|
101
|
-
| `nextThoughtNeeded` | boolean | ✅ | - | Whether another thought step is needed. |
|
|
102
|
-
| `isRevision` | boolean | ❌ | - | Whether this revises previous thinking. |
|
|
103
|
-
| `revisesThought` | number | ❌ | - | Which thought number is being reconsidered. |
|
|
104
|
-
| `branchFromThought` | number | ❌ | - | Branching point thought number. |
|
|
105
|
-
| `branchId` | string | ❌ | - | Branch identifier. |
|
|
106
|
-
| `thoughtType` | string | ❌ | - | Type: `analysis`, `hypothesis`, `verification`, `revision`, `conclusion`. |
|
|
46
|
+
## MCP client configuration
|
|
107
47
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
**Example Input:**
|
|
48
|
+
Add this to your MCP client settings:
|
|
111
49
|
|
|
112
50
|
```json
|
|
113
51
|
{
|
|
114
|
-
"
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"thinkseq": {
|
|
54
|
+
"command": "npx",
|
|
55
|
+
"args": ["-y", "@j0hanz/thinkseq-mcp@latest"]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
119
58
|
}
|
|
120
59
|
```
|
|
121
60
|
|
|
122
|
-
## 🔌 Client Configuration
|
|
123
|
-
|
|
124
61
|
<details>
|
|
125
62
|
<summary><b>VS Code</b></summary>
|
|
126
63
|
|
|
127
|
-
Add to your `mcp.json` (
|
|
64
|
+
Add to your `mcp.json` (command palette: "MCP: Open Settings"):
|
|
128
65
|
|
|
129
66
|
```json
|
|
130
67
|
{
|
|
@@ -187,7 +124,168 @@ Add to your `~/.codeium/windsurf/mcp_config.json`:
|
|
|
187
124
|
|
|
188
125
|
</details>
|
|
189
126
|
|
|
190
|
-
##
|
|
127
|
+
## Tool: `thinkseq`
|
|
128
|
+
|
|
129
|
+
Record a concise thinking step. Be brief: capture only the essential insight, calculation, or decision-like a minimal draft, not a verbose explanation.
|
|
130
|
+
|
|
131
|
+
### Input
|
|
132
|
+
|
|
133
|
+
| Field | Type | Required | Description |
|
|
134
|
+
| :--------------- | :----- | :------: | :----------------------------------------------------------------- |
|
|
135
|
+
| `thought` | string | yes | Current thinking step (1-2000 chars). |
|
|
136
|
+
| `totalThoughts` | number | no | Estimated total thoughts (1-25, default: 3). |
|
|
137
|
+
| `revisesThought` | number | no | Revise a previous thought by number. Original preserved for audit. |
|
|
138
|
+
|
|
139
|
+
### Output
|
|
140
|
+
|
|
141
|
+
The tool returns `structuredContent` with an `ok` flag. On success, `result` is populated; on error, `error` is populated.
|
|
142
|
+
|
|
143
|
+
Envelope fields:
|
|
144
|
+
|
|
145
|
+
| Field | Type | Description |
|
|
146
|
+
| :------- | :------ | :----------------------------------- |
|
|
147
|
+
| `ok` | boolean | `true` on success, `false` on error. |
|
|
148
|
+
| `result` | object | Present when `ok` is true. |
|
|
149
|
+
| `error` | object | Present when `ok` is false. |
|
|
150
|
+
|
|
151
|
+
Result fields:
|
|
152
|
+
|
|
153
|
+
| Field | Type | Description |
|
|
154
|
+
| :--------------------- | :------- | :--------------------------------------------------- |
|
|
155
|
+
| `thoughtNumber` | number | Auto-incremented thought number. |
|
|
156
|
+
| `totalThoughts` | number | Effective total thoughts (at least `thoughtNumber`). |
|
|
157
|
+
| `progress` | number | `thoughtNumber / totalThoughts` (0 to 1). |
|
|
158
|
+
| `isComplete` | boolean | `true` when `thoughtNumber >= totalThoughts`. |
|
|
159
|
+
| `thoughtHistoryLength` | number | Stored thought count after pruning. |
|
|
160
|
+
| `hasRevisions` | boolean | `true` if any thought has been revised. |
|
|
161
|
+
| `activePathLength` | number | Count of non-superseded thoughts. |
|
|
162
|
+
| `revisableThoughts` | number[] | Thought numbers available for revision. |
|
|
163
|
+
| `context` | object | Recent context summary (see below). |
|
|
164
|
+
|
|
165
|
+
Context fields:
|
|
166
|
+
|
|
167
|
+
| Field | Type | Description |
|
|
168
|
+
| :--------------- | :----- | :--------------------------------------------------------------------- |
|
|
169
|
+
| `recentThoughts` | array | Up to the last 5 active thoughts with `number` and `preview`. |
|
|
170
|
+
| `revisionInfo` | object | Present when revising: `revises` (number) and `supersedes` (number[]). |
|
|
171
|
+
|
|
172
|
+
Notes:
|
|
173
|
+
|
|
174
|
+
- `recentThoughts` previews are truncated to 100 characters.
|
|
175
|
+
- Revisions supersede the target thought and any later active thoughts.
|
|
176
|
+
|
|
177
|
+
Error fields:
|
|
178
|
+
|
|
179
|
+
| Code | Description |
|
|
180
|
+
| :----------------------------- | :---------------------------------------------- |
|
|
181
|
+
| `E_REVISION_TARGET_NOT_FOUND` | The requested thought number does not exist. |
|
|
182
|
+
| `E_REVISION_TARGET_SUPERSEDED` | The requested thought was already superseded. |
|
|
183
|
+
| `E_THINK` | Unexpected tool failure while processing input. |
|
|
184
|
+
|
|
185
|
+
### Example
|
|
186
|
+
|
|
187
|
+
**Basic usage:**
|
|
188
|
+
|
|
189
|
+
Input:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"thought": "3 steps: parse -> validate -> transform"
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Output (success):
|
|
198
|
+
|
|
199
|
+
```json
|
|
200
|
+
{
|
|
201
|
+
"ok": true,
|
|
202
|
+
"result": {
|
|
203
|
+
"thoughtNumber": 1,
|
|
204
|
+
"totalThoughts": 3,
|
|
205
|
+
"progress": 0.3333333333333333,
|
|
206
|
+
"isComplete": false,
|
|
207
|
+
"thoughtHistoryLength": 1,
|
|
208
|
+
"hasRevisions": false,
|
|
209
|
+
"activePathLength": 1,
|
|
210
|
+
"revisableThoughts": [1],
|
|
211
|
+
"context": {
|
|
212
|
+
"recentThoughts": [
|
|
213
|
+
{
|
|
214
|
+
"number": 1,
|
|
215
|
+
"preview": "3 steps: parse -> validate -> transform"
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Revising a thought:**
|
|
224
|
+
|
|
225
|
+
If you realize an earlier step was wrong, use `revisesThought` to correct it:
|
|
226
|
+
|
|
227
|
+
Input:
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"thought": "Better approach: validate first, then parse",
|
|
232
|
+
"revisesThought": 1
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Output:
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"ok": true,
|
|
241
|
+
"result": {
|
|
242
|
+
"thoughtNumber": 2,
|
|
243
|
+
"totalThoughts": 3,
|
|
244
|
+
"progress": 0.6666666666666666,
|
|
245
|
+
"isComplete": false,
|
|
246
|
+
"thoughtHistoryLength": 2,
|
|
247
|
+
"hasRevisions": true,
|
|
248
|
+
"activePathLength": 1,
|
|
249
|
+
"revisableThoughts": [2],
|
|
250
|
+
"context": {
|
|
251
|
+
"recentThoughts": [
|
|
252
|
+
{
|
|
253
|
+
"number": 2,
|
|
254
|
+
"preview": "Better approach: validate first, then parse"
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
"revisionInfo": {
|
|
258
|
+
"revises": 1,
|
|
259
|
+
"supersedes": [1]
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Behavior and validation
|
|
267
|
+
|
|
268
|
+
- Inputs are validated with Zod and unknown keys are rejected.
|
|
269
|
+
- `thoughtNumber` is auto-incremented (1, 2, 3...).
|
|
270
|
+
- `totalThoughts` defaults to 3, must be in 1-25, and is adjusted up to at least `thoughtNumber`.
|
|
271
|
+
- The engine stores thoughts in memory and prunes when limits are exceeded:
|
|
272
|
+
- `maxThoughts` default: 500 (cap 10000). When exceeded, prunes the oldest 10% (minimum excess).
|
|
273
|
+
- `maxMemoryBytes` default: 100 MB. When exceeded and history is large, prunes roughly 20% of history.
|
|
274
|
+
- `estimatedThoughtOverheadBytes` default: 200.
|
|
275
|
+
|
|
276
|
+
## Diagnostics
|
|
277
|
+
|
|
278
|
+
This server publishes events via `node:diagnostics_channel`:
|
|
279
|
+
|
|
280
|
+
- `thinkseq:tool` for `tool.start` and `tool.end` (includes duration, errors, and request context).
|
|
281
|
+
- `thinkseq:lifecycle` for `lifecycle.started` and `lifecycle.shutdown`.
|
|
282
|
+
- `thinkseq:engine` for internal engine events such as `engine.sequence_gap`.
|
|
283
|
+
|
|
284
|
+
## Configuration
|
|
285
|
+
|
|
286
|
+
No environment variables or CLI flags are required for basic operation. The server runs over stdio, enforces MCP initialization order, and validates protocol versions. Invalid JSON-RPC message shapes and parse errors are surfaced as JSON-RPC errors on stdio.
|
|
287
|
+
|
|
288
|
+
## Development
|
|
191
289
|
|
|
192
290
|
### Prerequisites
|
|
193
291
|
|
|
@@ -195,26 +293,55 @@ Add to your `~/.codeium/windsurf/mcp_config.json`:
|
|
|
195
293
|
|
|
196
294
|
### Scripts
|
|
197
295
|
|
|
198
|
-
| Command
|
|
199
|
-
|
|
|
200
|
-
| `npm run build`
|
|
201
|
-
| `npm run dev`
|
|
202
|
-
| `npm
|
|
203
|
-
| `npm run
|
|
204
|
-
| `npm run
|
|
205
|
-
|
|
206
|
-
|
|
296
|
+
| Command | Description |
|
|
297
|
+
| :----------------------- | :------------------------------- |
|
|
298
|
+
| `npm run build` | Compile TypeScript to `dist/`. |
|
|
299
|
+
| `npm run dev` | Run the server in watch mode. |
|
|
300
|
+
| `npm start` | Run `dist/index.js`. |
|
|
301
|
+
| `npm run test` | Run the test suite. |
|
|
302
|
+
| `npm run test:ci` | Build, then run the test suite. |
|
|
303
|
+
| `npm run test:coverage` | Run tests with coverage output. |
|
|
304
|
+
| `npm run lint` | Lint with ESLint. |
|
|
305
|
+
| `npm run format` | Format with Prettier. |
|
|
306
|
+
| `npm run format:check` | Check formatting with Prettier. |
|
|
307
|
+
| `npm run type-check` | Type-check without emitting. |
|
|
308
|
+
| `npm run inspector` | Launch the MCP inspector. |
|
|
309
|
+
| `npm run clean` | Remove `dist/`. |
|
|
310
|
+
| `npm run prepublishOnly` | Lint, type-check, and build. |
|
|
311
|
+
| `npm run benchmark` | Run `benchmark/engine.bench.ts`. |
|
|
312
|
+
|
|
313
|
+
Benchmark environment variables:
|
|
314
|
+
|
|
315
|
+
- `THINKSEQ_BENCH_SAMPLES` (default: 1)
|
|
316
|
+
- `THINKSEQ_BENCH_NEW_ITERATIONS` (default: 10000)
|
|
317
|
+
- `THINKSEQ_BENCH_REV_ITERATIONS` (default: 1000)
|
|
318
|
+
- `THINKSEQ_BENCH_WARMUP` (default: 1000)
|
|
319
|
+
- `THINKSEQ_BENCH_PIN` (optional CPU affinity mask)
|
|
320
|
+
|
|
321
|
+
### Project structure
|
|
207
322
|
|
|
208
323
|
```text
|
|
209
324
|
src/
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
325
|
+
app.ts # Application setup and MCP wiring
|
|
326
|
+
appConfig.ts # Dependency wiring and shutdown handling
|
|
327
|
+
engine.ts # Core thinking engine
|
|
328
|
+
engineConfig.ts # Defaults and limits
|
|
329
|
+
engine/ # Revision and query helpers
|
|
330
|
+
lib/ # CLI, diagnostics, errors, protocol, stdio utilities
|
|
331
|
+
schemas/ # Zod input/output schemas
|
|
332
|
+
tools/ # MCP tool definitions (thinkseq)
|
|
333
|
+
tests/ # Node.js tests
|
|
334
|
+
benchmark/ # Benchmark targets
|
|
335
|
+
docs/ # Assets (logo)
|
|
336
|
+
dist/ # Build output
|
|
337
|
+
scripts/ # Quality gates and metrics helpers
|
|
338
|
+
metrics/ # Generated metrics outputs
|
|
216
339
|
```
|
|
217
340
|
|
|
218
|
-
##
|
|
341
|
+
## Troubleshooting
|
|
342
|
+
|
|
343
|
+
- CI workflow references `npm run maintainability` and `npm run duplication`, but these scripts are not defined in `package.json`.
|
|
344
|
+
|
|
345
|
+
## Contributing
|
|
219
346
|
|
|
220
|
-
Contributions are welcome
|
|
347
|
+
Contributions are welcome. Please open a pull request with a clear description and include relevant tests.
|
package/dist/app.d.ts
CHANGED
|
@@ -1,42 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { ThinkingEngine } from './engine.js';
|
|
4
|
-
import type { LifecycleEvent } from './lib/diagnostics.js';
|
|
5
|
-
import type { PackageInfo } from './lib/package.js';
|
|
6
|
-
interface Closeable extends Record<string, unknown> {
|
|
7
|
-
close?: () => Promise<void> | void;
|
|
8
|
-
}
|
|
9
|
-
interface ProcessLike {
|
|
10
|
-
on: (event: string, listener: (...args: unknown[]) => void) => void;
|
|
11
|
-
exit: (code: number) => void;
|
|
12
|
-
}
|
|
13
|
-
type ServerLike = Pick<McpServer, 'connect' | 'registerTool'>;
|
|
14
|
-
type TransportLike = Pick<StdioServerTransport, 'close'>;
|
|
15
|
-
type EngineLike = Pick<ThinkingEngine, 'processThought'>;
|
|
16
|
-
export interface ProcessErrorHandlerDeps {
|
|
1
|
+
import { type ProcessLike, type RunDependencies } from './appConfig.js';
|
|
2
|
+
interface ProcessErrorHandlerDeps {
|
|
17
3
|
processLike?: ProcessLike;
|
|
18
4
|
logError?: (message: string) => void;
|
|
19
5
|
exit?: (code: number) => void;
|
|
20
6
|
}
|
|
21
|
-
interface ShutdownDependencies {
|
|
22
|
-
processLike?: ProcessLike;
|
|
23
|
-
server: Closeable;
|
|
24
|
-
transport: Closeable;
|
|
25
|
-
publishLifecycleEvent?: (event: LifecycleEvent) => void;
|
|
26
|
-
now?: () => number;
|
|
27
|
-
}
|
|
28
|
-
export interface RunDependencies {
|
|
29
|
-
processLike?: ProcessLike;
|
|
30
|
-
packageReadTimeoutMs?: number;
|
|
31
|
-
readPackageJson?: (signal?: AbortSignal) => Promise<PackageInfo>;
|
|
32
|
-
publishLifecycleEvent?: (event: LifecycleEvent) => void;
|
|
33
|
-
createServer?: (name: string, version: string) => ServerLike;
|
|
34
|
-
connectServer?: (server: ServerLike) => Promise<TransportLike>;
|
|
35
|
-
registerTool?: (server: ServerLike, engine: EngineLike) => void;
|
|
36
|
-
engineFactory?: () => EngineLike;
|
|
37
|
-
installShutdownHandlers?: (deps: ShutdownDependencies) => void;
|
|
38
|
-
now?: () => number;
|
|
39
|
-
}
|
|
40
7
|
export declare function installProcessErrorHandlers(deps?: ProcessErrorHandlerDeps): void;
|
|
41
8
|
export declare function run(deps?: RunDependencies): Promise<void>;
|
|
42
9
|
export {};
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAGhB,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAGxB,UAAU,uBAAuB;IAC/B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC/B;AAqBD,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,uBAA4B,GACjC,IAAI,CAQN;AAED,wBAAsB,GAAG,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBnE"}
|
package/dist/app.js
CHANGED
|
@@ -1,96 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import { ThinkingEngine } from './engine.js';
|
|
4
|
-
import { publishLifecycleEvent } from './lib/diagnostics.js';
|
|
5
|
-
import { readSelfPackageJson } from './lib/package.js';
|
|
1
|
+
import { buildShutdownDependencies, resolvePackageIdentity, resolveRunDependencies, } from './appConfig.js';
|
|
6
2
|
import { installInitializationGuards } from './lib/protocolGuards.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
3
|
+
const toError = (value) => value instanceof Error ? value : new Error(String(value));
|
|
4
|
+
const createExit = (proc, exit) => exit ?? ((code) => proc.exit(code));
|
|
5
|
+
const createHandlerFor = (logError, exit) => (label) => (value) => {
|
|
6
|
+
const error = toError(value);
|
|
7
|
+
logError(`thinkseq: ${label}: ${error.message}`);
|
|
8
|
+
exit(1);
|
|
9
|
+
};
|
|
11
10
|
export function installProcessErrorHandlers(deps = {}) {
|
|
12
11
|
const proc = deps.processLike ?? process;
|
|
13
12
|
const logError = deps.logError ?? console.error;
|
|
14
|
-
const exit = deps.exit
|
|
15
|
-
|
|
16
|
-
proc.exit(code);
|
|
17
|
-
});
|
|
18
|
-
const handlerFor = (label) => (value) => {
|
|
19
|
-
const error = value instanceof Error ? value : new Error(String(value));
|
|
20
|
-
logError(`thinkseq: ${label}: ${error.message}`);
|
|
21
|
-
exit(1);
|
|
22
|
-
};
|
|
13
|
+
const exit = createExit(proc, deps.exit);
|
|
14
|
+
const handlerFor = createHandlerFor(logError, exit);
|
|
23
15
|
proc.on('unhandledRejection', handlerFor('unhandledRejection'));
|
|
24
16
|
proc.on('uncaughtException', handlerFor('uncaughtException'));
|
|
25
17
|
}
|
|
26
|
-
function createServer(name, version) {
|
|
27
|
-
return new McpServer({ name, version }, {
|
|
28
|
-
instructions: SERVER_INSTRUCTIONS,
|
|
29
|
-
capabilities: { logging: {} },
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
async function connectServer(server) {
|
|
33
|
-
const transport = new StdioServerTransport();
|
|
34
|
-
await server.connect(transport);
|
|
35
|
-
installStdioInvalidMessageGuards(transport);
|
|
36
|
-
installStdioParseErrorResponder(transport);
|
|
37
|
-
return transport;
|
|
38
|
-
}
|
|
39
|
-
const DEFAULT_RUN_DEPENDENCIES = {
|
|
40
|
-
processLike: process,
|
|
41
|
-
packageReadTimeoutMs: DEFAULT_PACKAGE_READ_TIMEOUT_MS,
|
|
42
|
-
readPackageJson: readSelfPackageJson,
|
|
43
|
-
publishLifecycleEvent,
|
|
44
|
-
createServer,
|
|
45
|
-
connectServer,
|
|
46
|
-
registerTool: registerThinkSeq,
|
|
47
|
-
engineFactory: () => new ThinkingEngine(),
|
|
48
|
-
installShutdownHandlers,
|
|
49
|
-
now: Date.now,
|
|
50
|
-
};
|
|
51
|
-
async function closeSafely(value) {
|
|
52
|
-
try {
|
|
53
|
-
if (typeof value.close === 'function') {
|
|
54
|
-
await value.close();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function installShutdownHandlers({ processLike, server, transport, publishLifecycleEvent: publishLifecycle, now, }) {
|
|
62
|
-
const proc = processLike ?? process;
|
|
63
|
-
const emit = publishLifecycle ?? publishLifecycleEvent;
|
|
64
|
-
const timestamp = now ?? Date.now;
|
|
65
|
-
let shuttingDown = false;
|
|
66
|
-
const shutdown = async (signal) => {
|
|
67
|
-
if (shuttingDown)
|
|
68
|
-
return;
|
|
69
|
-
shuttingDown = true;
|
|
70
|
-
emit({
|
|
71
|
-
type: 'lifecycle.shutdown',
|
|
72
|
-
ts: timestamp(),
|
|
73
|
-
signal,
|
|
74
|
-
});
|
|
75
|
-
await closeSafely(server);
|
|
76
|
-
await closeSafely(transport);
|
|
77
|
-
proc.exit(0);
|
|
78
|
-
};
|
|
79
|
-
proc.on('SIGTERM', () => {
|
|
80
|
-
void shutdown('SIGTERM');
|
|
81
|
-
});
|
|
82
|
-
proc.on('SIGINT', () => {
|
|
83
|
-
void shutdown('SIGINT');
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
18
|
export async function run(deps = {}) {
|
|
87
|
-
const resolved =
|
|
88
|
-
...DEFAULT_RUN_DEPENDENCIES,
|
|
89
|
-
...deps,
|
|
90
|
-
};
|
|
19
|
+
const resolved = resolveRunDependencies(deps);
|
|
91
20
|
const pkg = await resolved.readPackageJson(AbortSignal.timeout(resolved.packageReadTimeoutMs));
|
|
92
|
-
const name = pkg
|
|
93
|
-
const version = pkg.version ?? '0.0.0';
|
|
21
|
+
const { name, version } = resolvePackageIdentity(pkg);
|
|
94
22
|
resolved.publishLifecycleEvent({
|
|
95
23
|
type: 'lifecycle.started',
|
|
96
24
|
ts: resolved.now(),
|
|
@@ -100,12 +28,6 @@ export async function run(deps = {}) {
|
|
|
100
28
|
resolved.registerTool(server, engine);
|
|
101
29
|
installInitializationGuards(server);
|
|
102
30
|
const transport = await resolved.connectServer(server);
|
|
103
|
-
resolved.installShutdownHandlers({
|
|
104
|
-
processLike: resolved.processLike,
|
|
105
|
-
server,
|
|
106
|
-
transport,
|
|
107
|
-
publishLifecycleEvent: resolved.publishLifecycleEvent,
|
|
108
|
-
now: resolved.now,
|
|
109
|
-
});
|
|
31
|
+
resolved.installShutdownHandlers(buildShutdownDependencies(resolved, { server, engine, transport }));
|
|
110
32
|
}
|
|
111
33
|
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EAEzB,sBAAsB,EACtB,sBAAsB,GAEvB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAUtE,MAAM,OAAO,GAAG,CAAC,KAAc,EAAS,EAAE,CACxC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAE5D,MAAM,UAAU,GAAG,CACjB,IAAiB,EACjB,IAA6B,EACH,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAE3E,MAAM,gBAAgB,GACpB,CAAC,QAAmC,EAAE,IAA4B,EAAE,EAAE,CACtE,CAAC,KAAiB,EAAE,EAAE,CACtB,CAAC,KAAc,EAAQ,EAAE;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC7B,QAAQ,CAAC,aAAa,KAAK,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjD,IAAI,CAAC,CAAC,CAAC,CAAC;AACV,CAAC,CAAC;AAEJ,MAAM,UAAU,2BAA2B,CACzC,OAAgC,EAAE;IAElC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,IAAI,OAAO,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;IAChD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAEpD,IAAI,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAU,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE,CAAC,mBAAmB,EAAE,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAwB,EAAE;IAClD,MAAM,QAAQ,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,eAAe,CACxC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CACnD,CAAC;IACF,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAEtD,QAAQ,CAAC,qBAAqB,CAAC;QAC7B,IAAI,EAAE,mBAAmB;QACzB,EAAE,EAAE,QAAQ,CAAC,GAAG,EAAE;KACnB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACvD,QAAQ,CAAC,uBAAuB,CAC9B,yBAAyB,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACnE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { LifecycleEvent } from '../lib/diagnostics.js';
|
|
2
|
+
import type { PackageInfo } from '../lib/package.js';
|
|
3
|
+
import type { ShutdownDependencies } from './shutdown.js';
|
|
4
|
+
import type { EngineLike, ProcessLike, ServerLike, TransportLike } from './types.js';
|
|
5
|
+
export interface RunDependencies {
|
|
6
|
+
processLike?: ProcessLike;
|
|
7
|
+
packageReadTimeoutMs?: number;
|
|
8
|
+
shutdownTimeoutMs?: number;
|
|
9
|
+
readPackageJson?: (signal?: AbortSignal) => Promise<PackageInfo>;
|
|
10
|
+
publishLifecycleEvent?: (event: LifecycleEvent) => void;
|
|
11
|
+
createServer?: (name: string, version: string) => ServerLike;
|
|
12
|
+
connectServer?: (server: ServerLike, createTransport?: () => TransportLike) => Promise<TransportLike>;
|
|
13
|
+
registerTool?: (server: ServerLike, engine: EngineLike) => void;
|
|
14
|
+
engineFactory?: () => EngineLike;
|
|
15
|
+
installShutdownHandlers?: (deps: ShutdownDependencies) => void;
|
|
16
|
+
now?: () => number;
|
|
17
|
+
}
|
|
18
|
+
export interface ResolvedRunDependencies {
|
|
19
|
+
processLike: ProcessLike;
|
|
20
|
+
packageReadTimeoutMs: number;
|
|
21
|
+
shutdownTimeoutMs?: number;
|
|
22
|
+
readPackageJson: (signal?: AbortSignal) => Promise<PackageInfo>;
|
|
23
|
+
publishLifecycleEvent: (event: LifecycleEvent) => void;
|
|
24
|
+
createServer: (name: string, version: string) => ServerLike;
|
|
25
|
+
connectServer: (server: ServerLike, createTransport?: () => TransportLike) => Promise<TransportLike>;
|
|
26
|
+
registerTool: (server: ServerLike, engine: EngineLike) => void;
|
|
27
|
+
engineFactory: () => EngineLike;
|
|
28
|
+
installShutdownHandlers: (deps: ShutdownDependencies) => void;
|
|
29
|
+
now: () => number;
|
|
30
|
+
}
|
|
31
|
+
export declare function resolveRunDependencies(deps: RunDependencies): ResolvedRunDependencies;
|
|
32
|
+
export declare function resolvePackageIdentity(pkg: PackageInfo): {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=runDependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runDependencies.d.ts","sourceRoot":"","sources":["../../src/appConfig/runDependencies.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOrD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1D,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AAMpB,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IACjE,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACxD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC;IAC7D,aAAa,CAAC,EAAE,CACd,MAAM,EAAE,UAAU,EAClB,eAAe,CAAC,EAAE,MAAM,aAAa,KAClC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,UAAU,CAAC;IACjC,uBAAuB,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,WAAW,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAChE,qBAAqB,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACvD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC;IAC5D,aAAa,EAAE,CACb,MAAM,EAAE,UAAU,EAClB,eAAe,CAAC,EAAE,MAAM,aAAa,KAClC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B,YAAY,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,MAAM,UAAU,CAAC;IAChC,uBAAuB,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC9D,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB;AAyED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,eAAe,GACpB,uBAAuB,CAOzB;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAKA"}
|