@tostudy-ai/mcp-setup 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.
Files changed (75) hide show
  1. package/README.md +149 -0
  2. package/bin/cli.js +6 -0
  3. package/dist/__tests__/e2e-diagnostic-repair-flow.test.d.ts +52 -0
  4. package/dist/__tests__/e2e-diagnostic-repair-flow.test.d.ts.map +1 -0
  5. package/dist/__tests__/e2e-diagnostic-repair-flow.test.js +720 -0
  6. package/dist/__tests__/e2e-diagnostic-repair-flow.test.js.map +1 -0
  7. package/dist/__tests__/e2e-wizard-flow.test.d.ts +43 -0
  8. package/dist/__tests__/e2e-wizard-flow.test.d.ts.map +1 -0
  9. package/dist/__tests__/e2e-wizard-flow.test.js +407 -0
  10. package/dist/__tests__/e2e-wizard-flow.test.js.map +1 -0
  11. package/dist/__tests__/ide-handlers.test.d.ts +10 -0
  12. package/dist/__tests__/ide-handlers.test.d.ts.map +1 -0
  13. package/dist/__tests__/ide-handlers.test.js +336 -0
  14. package/dist/__tests__/ide-handlers.test.js.map +1 -0
  15. package/dist/__tests__/install-command.test.d.ts +10 -0
  16. package/dist/__tests__/install-command.test.d.ts.map +1 -0
  17. package/dist/__tests__/install-command.test.js +237 -0
  18. package/dist/__tests__/install-command.test.js.map +1 -0
  19. package/dist/config.d.ts +51 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +117 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/detect.d.ts +42 -0
  24. package/dist/detect.d.ts.map +1 -0
  25. package/dist/detect.js +277 -0
  26. package/dist/detect.js.map +1 -0
  27. package/dist/diagnose.d.ts +36 -0
  28. package/dist/diagnose.d.ts.map +1 -0
  29. package/dist/diagnose.js +512 -0
  30. package/dist/diagnose.js.map +1 -0
  31. package/dist/ide-handlers/base.d.ts +36 -0
  32. package/dist/ide-handlers/base.d.ts.map +1 -0
  33. package/dist/ide-handlers/base.js +41 -0
  34. package/dist/ide-handlers/base.js.map +1 -0
  35. package/dist/ide-handlers/claude-code.d.ts +15 -0
  36. package/dist/ide-handlers/claude-code.d.ts.map +1 -0
  37. package/dist/ide-handlers/claude-code.js +50 -0
  38. package/dist/ide-handlers/claude-code.js.map +1 -0
  39. package/dist/ide-handlers/cursor.d.ts +15 -0
  40. package/dist/ide-handlers/cursor.d.ts.map +1 -0
  41. package/dist/ide-handlers/cursor.js +61 -0
  42. package/dist/ide-handlers/cursor.js.map +1 -0
  43. package/dist/ide-handlers/desktop.d.ts +16 -0
  44. package/dist/ide-handlers/desktop.d.ts.map +1 -0
  45. package/dist/ide-handlers/desktop.js +26 -0
  46. package/dist/ide-handlers/desktop.js.map +1 -0
  47. package/dist/ide-handlers/index.d.ts +21 -0
  48. package/dist/ide-handlers/index.d.ts.map +1 -0
  49. package/dist/ide-handlers/index.js +49 -0
  50. package/dist/ide-handlers/index.js.map +1 -0
  51. package/dist/ide-handlers/manual.d.ts +16 -0
  52. package/dist/ide-handlers/manual.d.ts.map +1 -0
  53. package/dist/ide-handlers/manual.js +34 -0
  54. package/dist/ide-handlers/manual.js.map +1 -0
  55. package/dist/ide-handlers/opencode.d.ts +15 -0
  56. package/dist/ide-handlers/opencode.d.ts.map +1 -0
  57. package/dist/ide-handlers/opencode.js +57 -0
  58. package/dist/ide-handlers/opencode.js.map +1 -0
  59. package/dist/ide-handlers/vscode.d.ts +16 -0
  60. package/dist/ide-handlers/vscode.d.ts.map +1 -0
  61. package/dist/ide-handlers/vscode.js +62 -0
  62. package/dist/ide-handlers/vscode.js.map +1 -0
  63. package/dist/index.d.ts +14 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +501 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/prompts.d.ts +23 -0
  68. package/dist/prompts.d.ts.map +1 -0
  69. package/dist/prompts.js +68 -0
  70. package/dist/prompts.js.map +1 -0
  71. package/dist/repair.d.ts +50 -0
  72. package/dist/repair.d.ts.map +1 -0
  73. package/dist/repair.js +588 -0
  74. package/dist/repair.js.map +1 -0
  75. package/package.json +54 -0
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Tests: IDE Handler Registry & Config Writers
3
+ *
4
+ * Tests the handler factory, base utilities, and config write/merge
5
+ * for Cursor, VS Code, OpenCode, and Manual handlers.
6
+ *
7
+ * Run with: npx tsx src/__tests__/ide-handlers.test.ts
8
+ */
9
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { tmpdir } from 'node:os';
12
+ // Import modules under test
13
+ import { buildMcpRemoteArgs, buildTostudyServerEntry, } from '../ide-handlers/base.js';
14
+ import { getIDEHandler, getAllIDEHandlers, } from '../ide-handlers/index.js';
15
+ // Test utilities
16
+ const TEST_API_KEY = 'test-handler-key-1234567890';
17
+ const TEST_MCP_URL = 'https://mcp.tostudy.ai';
18
+ const results = [];
19
+ function log(message) {
20
+ process.stdout.write(`${message}\n`);
21
+ }
22
+ function assert(condition, message) {
23
+ if (!condition) {
24
+ throw new Error(`Assertion failed: ${message}`);
25
+ }
26
+ }
27
+ async function runTest(name, testFn) {
28
+ try {
29
+ await testFn();
30
+ results.push({ name, passed: true, message: 'OK' });
31
+ log(` \x1b[32m✓\x1b[0m ${name}`);
32
+ }
33
+ catch (error) {
34
+ const message = error instanceof Error ? error.message : String(error);
35
+ results.push({ name, passed: false, message });
36
+ log(` \x1b[31m✗\x1b[0m ${name}: ${message}`);
37
+ }
38
+ }
39
+ /**
40
+ * Create a temp directory for file-based tests
41
+ */
42
+ function createTempDir(suffix) {
43
+ const dir = join(tmpdir(), `mcp-test-${suffix}-${Date.now()}`);
44
+ mkdirSync(dir, { recursive: true });
45
+ return dir;
46
+ }
47
+ /**
48
+ * Clean up temp directory
49
+ */
50
+ function cleanupTempDir(dir) {
51
+ try {
52
+ rmSync(dir, { recursive: true, force: true });
53
+ }
54
+ catch {
55
+ // Best-effort cleanup
56
+ }
57
+ }
58
+ // ───────────── Base Utilities ─────────────
59
+ async function testBaseUtilities() {
60
+ log('\n── Base Utilities ──');
61
+ await runTest('buildMcpRemoteArgs returns correct args', () => {
62
+ const args = buildMcpRemoteArgs(TEST_API_KEY, TEST_MCP_URL);
63
+ assert(Array.isArray(args), 'Should return an array');
64
+ assert(args[0] === '-y', 'First arg should be -y');
65
+ assert(args[1] === 'mcp-remote', 'Second arg should be mcp-remote');
66
+ assert(args[2] === `${TEST_MCP_URL}/mcp`, 'Third arg should be MCP URL + /mcp');
67
+ assert(args[3] === '--header', 'Fourth arg should be --header');
68
+ assert(args[4] === `Authorization:Bearer ${TEST_API_KEY}`, 'Fifth arg should be auth header');
69
+ });
70
+ await runTest('buildTostudyServerEntry returns command + args', () => {
71
+ const entry = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
72
+ assert(entry.command === 'npx', 'Command should be npx');
73
+ assert(Array.isArray(entry.args), 'Args should be an array');
74
+ assert(entry.args.length === 5, 'Should have 5 args');
75
+ assert(entry.args[1] === 'mcp-remote', 'Should include mcp-remote');
76
+ });
77
+ }
78
+ // ───────────── Handler Factory ─────────────
79
+ async function testHandlerFactory() {
80
+ log('\n── Handler Factory ──');
81
+ const validIDEs = ['claude-code', 'cursor', 'vscode', 'desktop', 'opencode', 'manual'];
82
+ await runTest('getIDEHandler returns handler for each valid IDE', () => {
83
+ for (const ide of validIDEs) {
84
+ const handler = getIDEHandler(ide);
85
+ assert(handler !== null && handler !== undefined, `Handler for ${ide} should exist`);
86
+ assert(handler.id === ide, `Handler id should match ${ide}`);
87
+ assert(typeof handler.name === 'string', `Handler ${ide} should have a name`);
88
+ assert(typeof handler.detect === 'function', `Handler ${ide} should have detect()`);
89
+ assert(typeof handler.getConfigPath === 'function', `Handler ${ide} should have getConfigPath()`);
90
+ assert(typeof handler.writeConfig === 'function', `Handler ${ide} should have writeConfig()`);
91
+ assert(typeof handler.verify === 'function', `Handler ${ide} should have verify()`);
92
+ }
93
+ });
94
+ await runTest('getIDEHandler throws for unknown IDE', () => {
95
+ let threw = false;
96
+ try {
97
+ getIDEHandler('unknown-ide');
98
+ }
99
+ catch (err) {
100
+ threw = true;
101
+ assert(err.message.includes('Unknown IDE'), 'Error should mention Unknown IDE');
102
+ }
103
+ assert(threw, 'Should throw for unknown IDE');
104
+ });
105
+ await runTest('getAllIDEHandlers returns all 6 handlers', () => {
106
+ const all = getAllIDEHandlers();
107
+ assert(all.length === 6, `Should return 6 handlers, got ${all.length}`);
108
+ const ids = all.map((h) => h.id).sort();
109
+ const expected = [...validIDEs].sort();
110
+ assert(JSON.stringify(ids) === JSON.stringify(expected), `IDs should match: ${JSON.stringify(ids)} vs ${JSON.stringify(expected)}`);
111
+ });
112
+ }
113
+ // ───────────── Handler Properties ─────────────
114
+ async function testHandlerProperties() {
115
+ log('\n── Handler Properties ──');
116
+ await runTest('Cursor handler has correct config path', () => {
117
+ const handler = getIDEHandler('cursor');
118
+ const path = handler.getConfigPath();
119
+ assert(path.includes('.cursor'), 'Path should contain .cursor');
120
+ assert(path.endsWith('mcp.json'), 'Path should end with mcp.json');
121
+ });
122
+ await runTest('VS Code handler has correct config path', () => {
123
+ const handler = getIDEHandler('vscode');
124
+ const path = handler.getConfigPath();
125
+ assert(path.includes('.vscode'), 'Path should contain .vscode');
126
+ assert(path.endsWith('mcp.json'), 'Path should end with mcp.json');
127
+ });
128
+ await runTest('OpenCode handler has correct config path', () => {
129
+ const handler = getIDEHandler('opencode');
130
+ const path = handler.getConfigPath();
131
+ assert(path.includes('.opencode'), 'Path should contain .opencode');
132
+ assert(path.endsWith('opencode.json'), 'Path should end with opencode.json');
133
+ });
134
+ await runTest('Manual handler config path is stdout', () => {
135
+ const handler = getIDEHandler('manual');
136
+ assert(handler.getConfigPath() === 'stdout', 'Manual handler config path should be stdout');
137
+ });
138
+ await runTest('Claude Code handler config path mentions terminal', () => {
139
+ const handler = getIDEHandler('claude-code');
140
+ assert(handler.getConfigPath().toLowerCase().includes('terminal') ||
141
+ handler.getConfigPath().includes('claude mcp add'), 'Claude Code handler should describe terminal usage');
142
+ });
143
+ await runTest('Desktop handler uses Claude Desktop config path', () => {
144
+ const handler = getIDEHandler('desktop');
145
+ const path = handler.getConfigPath();
146
+ assert(path.includes('claude_desktop_config.json'), 'Desktop handler should use Claude Desktop config');
147
+ });
148
+ await runTest('Manual handler always detects as available', async () => {
149
+ const handler = getIDEHandler('manual');
150
+ const detected = await handler.detect();
151
+ assert(detected === true, 'Manual handler should always detect');
152
+ });
153
+ }
154
+ // ───────────── Config Write/Merge (Cursor) ─────────────
155
+ async function testCursorConfigMerge() {
156
+ log('\n── Cursor Config Write/Merge ──');
157
+ // We can't easily override homedir() for CursorHandler, so we test
158
+ // the config merge logic by directly using the filesystem pattern.
159
+ const tempDir = createTempDir('cursor');
160
+ const configPath = join(tempDir, 'mcp.json');
161
+ try {
162
+ await runTest('Cursor: writes new config when none exists', () => {
163
+ // Simulate what CursorHandler.writeConfig does
164
+ const entry = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
165
+ const config = { mcpServers: { tostudy: entry } };
166
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
167
+ assert(existsSync(configPath), 'Config file should exist');
168
+ const written = JSON.parse(readFileSync(configPath, 'utf-8'));
169
+ assert(written.mcpServers !== undefined, 'mcpServers should exist');
170
+ assert(written.mcpServers.tostudy !== undefined, 'tostudy entry should exist');
171
+ assert(written.mcpServers.tostudy.command === 'npx', 'Command should be npx');
172
+ });
173
+ await runTest('Cursor: merges with existing config (preserves other servers)', () => {
174
+ // Write config with another server
175
+ const existing = {
176
+ mcpServers: {
177
+ other_server: { command: 'node', args: ['server.js'] },
178
+ },
179
+ };
180
+ writeFileSync(configPath, JSON.stringify(existing, null, 2), 'utf-8');
181
+ // Merge tostudy into existing
182
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
183
+ const mcpServers = config.mcpServers ?? {};
184
+ mcpServers['tostudy'] = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
185
+ config.mcpServers = mcpServers;
186
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
187
+ const merged = JSON.parse(readFileSync(configPath, 'utf-8'));
188
+ assert(merged.mcpServers.other_server !== undefined, 'Other server should be preserved');
189
+ assert(merged.mcpServers.tostudy !== undefined, 'tostudy should be added');
190
+ assert(merged.mcpServers.other_server.command === 'node', 'Other server command unchanged');
191
+ });
192
+ await runTest('Cursor: overwrites existing tostudy entry', () => {
193
+ // Write config with old tostudy
194
+ const existing = {
195
+ mcpServers: {
196
+ tostudy: { command: 'old', args: ['old'] },
197
+ keep_this: { command: 'keep', args: [] },
198
+ },
199
+ };
200
+ writeFileSync(configPath, JSON.stringify(existing, null, 2), 'utf-8');
201
+ // Update tostudy
202
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
203
+ const mcpServers = config.mcpServers;
204
+ mcpServers['tostudy'] = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
205
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
206
+ const updated = JSON.parse(readFileSync(configPath, 'utf-8'));
207
+ assert(updated.mcpServers.tostudy.command === 'npx', 'tostudy should be updated to npx');
208
+ assert(updated.mcpServers.keep_this.command === 'keep', 'keep_this should be unchanged');
209
+ });
210
+ await runTest('Cursor: handles corrupted config gracefully', () => {
211
+ // Write invalid JSON
212
+ writeFileSync(configPath, '{ invalid json !!!', 'utf-8');
213
+ // Should start fresh
214
+ let config = {};
215
+ try {
216
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
217
+ }
218
+ catch {
219
+ config = {};
220
+ }
221
+ const mcpServers = config.mcpServers ?? {};
222
+ mcpServers['tostudy'] = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
223
+ config.mcpServers = mcpServers;
224
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
225
+ const fixed = JSON.parse(readFileSync(configPath, 'utf-8'));
226
+ assert(fixed.mcpServers.tostudy.command === 'npx', 'Should write valid config after corruption');
227
+ });
228
+ }
229
+ finally {
230
+ cleanupTempDir(tempDir);
231
+ }
232
+ }
233
+ // ───────────── Config Write/Merge (VS Code) ─────────────
234
+ async function testVSCodeConfigMerge() {
235
+ log('\n── VS Code Config Write/Merge ──');
236
+ const tempDir = createTempDir('vscode');
237
+ const configPath = join(tempDir, 'mcp.json');
238
+ try {
239
+ await runTest('VSCode: uses "servers" key (not "mcpServers")', () => {
240
+ const entry = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
241
+ const config = { servers: { tostudy: entry } };
242
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
243
+ const written = JSON.parse(readFileSync(configPath, 'utf-8'));
244
+ assert(written.servers !== undefined, 'Should use "servers" key');
245
+ assert(written.mcpServers === undefined, 'Should NOT have "mcpServers" key');
246
+ assert(written.servers.tostudy.command === 'npx', 'Command should be npx');
247
+ });
248
+ await runTest('VSCode: merges with existing servers', () => {
249
+ const existing = { servers: { github: { command: 'gh', args: [] } } };
250
+ writeFileSync(configPath, JSON.stringify(existing, null, 2), 'utf-8');
251
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
252
+ const servers = config.servers ?? {};
253
+ servers['tostudy'] = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
254
+ config.servers = servers;
255
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
256
+ const merged = JSON.parse(readFileSync(configPath, 'utf-8'));
257
+ assert(merged.servers.github !== undefined, 'github server preserved');
258
+ assert(merged.servers.tostudy !== undefined, 'tostudy server added');
259
+ });
260
+ }
261
+ finally {
262
+ cleanupTempDir(tempDir);
263
+ }
264
+ }
265
+ // ───────────── Config Write/Merge (OpenCode) ─────────────
266
+ async function testOpenCodeConfigMerge() {
267
+ log('\n── OpenCode Config Write/Merge ──');
268
+ const tempDir = createTempDir('opencode');
269
+ const configPath = join(tempDir, 'opencode.json');
270
+ try {
271
+ await runTest('OpenCode: uses "mcp" key', () => {
272
+ const entry = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
273
+ const config = { mcp: { tostudy: entry } };
274
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
275
+ const written = JSON.parse(readFileSync(configPath, 'utf-8'));
276
+ assert(written.mcp !== undefined, 'Should use "mcp" key');
277
+ assert(written.mcp.tostudy.command === 'npx', 'Command should be npx');
278
+ });
279
+ await runTest('OpenCode: merges with existing mcp entries', () => {
280
+ const existing = {
281
+ mcp: { another: { command: 'node', args: ['other.js'] } },
282
+ otherConfig: 'preserved',
283
+ };
284
+ writeFileSync(configPath, JSON.stringify(existing, null, 2), 'utf-8');
285
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
286
+ const mcp = config.mcp ?? {};
287
+ mcp['tostudy'] = buildTostudyServerEntry(TEST_API_KEY, TEST_MCP_URL);
288
+ config.mcp = mcp;
289
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
290
+ const merged = JSON.parse(readFileSync(configPath, 'utf-8'));
291
+ assert(merged.mcp.another !== undefined, 'another entry preserved');
292
+ assert(merged.mcp.tostudy !== undefined, 'tostudy entry added');
293
+ assert(merged.otherConfig === 'preserved', 'Other config keys preserved');
294
+ });
295
+ }
296
+ finally {
297
+ cleanupTempDir(tempDir);
298
+ }
299
+ }
300
+ // ───────────── Summary ─────────────
301
+ function printSummary() {
302
+ log('\n' + '═'.repeat(50));
303
+ log('IDE HANDLERS TEST SUMMARY');
304
+ log('═'.repeat(50));
305
+ const passed = results.filter((r) => r.passed).length;
306
+ const failed = results.filter((r) => !r.passed).length;
307
+ log(`\nTotal: ${results.length} | Passed: ${passed} | Failed: ${failed}\n`);
308
+ if (failed > 0) {
309
+ log('FAILED:');
310
+ for (const r of results.filter((r) => !r.passed)) {
311
+ log(` \x1b[31m✗\x1b[0m ${r.name}: ${r.message}`);
312
+ }
313
+ }
314
+ if (failed === 0) {
315
+ log('\x1b[32m✓ All IDE handler tests passed!\x1b[0m\n');
316
+ }
317
+ else {
318
+ log(`\x1b[31m✗ ${failed} test(s) failed\x1b[0m\n`);
319
+ process.exitCode = 1;
320
+ }
321
+ }
322
+ // Main
323
+ async function main() {
324
+ log('═'.repeat(50));
325
+ log('TEST: IDE Handler Registry & Config Writers');
326
+ log('═'.repeat(50));
327
+ await testBaseUtilities();
328
+ await testHandlerFactory();
329
+ await testHandlerProperties();
330
+ await testCursorConfigMerge();
331
+ await testVSCodeConfigMerge();
332
+ await testOpenCodeConfigMerge();
333
+ printSummary();
334
+ }
335
+ main();
336
+ //# sourceMappingURL=ide-handlers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ide-handlers.test.js","sourceRoot":"","sources":["../../src/__tests__/ide-handlers.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,4BAA4B;AAC5B,OAAO,EACL,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,aAAa,EACb,iBAAiB,GAElB,MAAM,0BAA0B,CAAC;AAElC,iBAAiB;AACjB,MAAM,YAAY,GAAG,6BAA6B,CAAC;AACnD,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAQ9C,MAAM,OAAO,GAAiB,EAAE,CAAC;AAEjC,SAAS,GAAG,CAAC,OAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,MAAM,CAAC,SAAkB,EAAE,OAAe;IACjD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,MAAkC;IACrE,IAAI,CAAC;QACH,MAAM,MAAM,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC/C,GAAG,CAAC,sBAAsB,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,MAAc;IACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC/D,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;AACH,CAAC;AAED,6CAA6C;AAE7C,KAAK,UAAU,iBAAiB;IAC9B,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAE9B,MAAM,OAAO,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAC5D,MAAM,IAAI,GAAG,kBAAkB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,wBAAwB,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,wBAAwB,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,EAAE,iCAAiC,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,YAAY,MAAM,EAAE,oCAAoC,CAAC,CAAC;QAChF,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,+BAA+B,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,wBAAwB,YAAY,EAAE,EAAE,iCAAiC,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACnE,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAClE,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,KAAK,EAAE,uBAAuB,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,yBAAyB,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,oBAAoB,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,EAAE,2BAA2B,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8CAA8C;AAE9C,KAAK,UAAU,kBAAkB;IAC/B,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAE/B,MAAM,SAAS,GAAmB,CAAC,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAEvG,MAAM,OAAO,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACrE,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE,eAAe,GAAG,eAAe,CAAC,CAAC;YACrF,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,EAAE,2BAA2B,GAAG,EAAE,CAAC,CAAC;YAC7D,MAAM,CAAC,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,WAAW,GAAG,qBAAqB,CAAC,CAAC;YAC9E,MAAM,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,WAAW,GAAG,uBAAuB,CAAC,CAAC;YACpF,MAAM,CAAC,OAAO,OAAO,CAAC,aAAa,KAAK,UAAU,EAAE,WAAW,GAAG,8BAA8B,CAAC,CAAC;YAClG,MAAM,CAAC,OAAO,OAAO,CAAC,WAAW,KAAK,UAAU,EAAE,WAAW,GAAG,4BAA4B,CAAC,CAAC;YAC9F,MAAM,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,WAAW,GAAG,uBAAuB,CAAC,CAAC;QACtF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACzD,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC;YACH,aAAa,CAAC,aAA6B,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,GAAG,IAAI,CAAC;YACb,MAAM,CACH,GAAa,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAC9C,kCAAkC,CACnC,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAC7D,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,iCAAiC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;QACvC,MAAM,CACJ,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAChD,qBAAqB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAC1E,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,iDAAiD;AAEjD,KAAK,UAAU,qBAAqB;IAClC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAElC,MAAM,OAAO,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC3D,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAC5D,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,+BAA+B,CAAC,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,oCAAoC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACzD,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,QAAQ,EAAE,6CAA6C,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,mDAAmD,EAAE,GAAG,EAAE;QACtE,MAAM,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC,CAAC;QAC7C,MAAM,CACJ,OAAO,CAAC,aAAa,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC1D,OAAO,CAAC,aAAa,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAClD,oDAAoD,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACpE,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,4BAA4B,CAAC,EAAE,kDAAkD,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,qCAAqC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,0DAA0D;AAE1D,KAAK,UAAU,qBAAqB;IAClC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IAEzC,mEAAmE;IACnE,mEAAmE;IAEnE,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,4CAA4C,EAAE,GAAG,EAAE;YAC/D,+CAA+C;YAC/C,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,0BAA0B,CAAC,CAAC;YAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,yBAAyB,CAAC,CAAC;YACpE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,4BAA4B,CAAC,CAAC;YAC/E,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,+DAA+D,EAAE,GAAG,EAAE;YAClF,mCAAmC;YACnC,MAAM,QAAQ,GAAG;gBACf,UAAU,EAAE;oBACV,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,EAAE;iBACvD;aACF,CAAC;YACF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,8BAA8B;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAI,MAAM,CAAC,UAAsC,IAAI,EAAE,CAAC;YACxE,UAAU,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAC5E,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;YAC/B,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,kCAAkC,CAAC,CAAC;YACzF,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,KAAK,SAAS,EAAE,yBAAyB,CAAC,CAAC;YAC3E,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,OAAO,KAAK,MAAM,EAAE,gCAAgC,CAAC,CAAC;QAC9F,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,2CAA2C,EAAE,GAAG,EAAE;YAC9D,gCAAgC;YAChC,MAAM,QAAQ,GAAG;gBACf,UAAU,EAAE;oBACV,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE;oBAC1C,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE;iBACzC;aACF,CAAC;YACF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,iBAAiB;YACjB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAqC,CAAC;YAChE,UAAU,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAC5E,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,kCAAkC,CAAC,CAAC;YACzF,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,KAAK,MAAM,EAAE,+BAA+B,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,6CAA6C,EAAE,GAAG,EAAE;YAChE,qBAAqB;YACrB,aAAa,CAAC,UAAU,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAC;YAEzD,qBAAqB;YACrB,IAAI,MAAM,GAA4B,EAAE,CAAC;YACzC,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,GAAG,EAAE,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAI,MAAM,CAAC,UAAsC,IAAI,EAAE,CAAC;YACxE,UAAU,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAC5E,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;YAC/B,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC5D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,4CAA4C,CAAC,CAAC;QACnG,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,2DAA2D;AAE3D,KAAK,UAAU,qBAAqB;IAClC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,+CAA+C,EAAE,GAAG,EAAE;YAClE,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,0BAA0B,CAAC,CAAC;YAClE,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,kCAAkC,CAAC,CAAC;YAC7E,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,uBAAuB,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,sCAAsC,EAAE,GAAG,EAAE;YACzD,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;YACtE,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAI,MAAM,CAAC,OAAmC,IAAI,EAAE,CAAC;YAClE,OAAO,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YACzE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YACzB,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,yBAAyB,CAAC,CAAC;YACvE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,sBAAsB,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,4DAA4D;AAE5D,KAAK,UAAU,uBAAuB;IACpC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IAE3C,MAAM,OAAO,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAC7C,MAAM,KAAK,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YAClE,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;YAC3C,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,sBAAsB,CAAC,CAAC;YAC1D,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,uBAAuB,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,CAAC,4CAA4C,EAAE,GAAG,EAAE;YAC/D,MAAM,QAAQ,GAAG;gBACf,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE;gBACzD,WAAW,EAAE,WAAW;aACzB,CAAC;YACF,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEtE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAI,MAAM,CAAC,GAA+B,IAAI,EAAE,CAAC;YAC1D,GAAG,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YACrE,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;YACjB,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAEpE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,yBAAyB,CAAC,CAAC;YACpE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,qBAAqB,CAAC,CAAC;YAChE,MAAM,CAAC,MAAM,CAAC,WAAW,KAAK,WAAW,EAAE,6BAA6B,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACL,CAAC;YAAS,CAAC;QACT,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,sCAAsC;AAEtC,SAAS,YAAY;IACnB,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3B,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACjC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAEvD,GAAG,CAAC,YAAY,OAAO,CAAC,MAAM,cAAc,MAAM,cAAc,MAAM,IAAI,CAAC,CAAC;IAE5E,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QACf,GAAG,CAAC,SAAS,CAAC,CAAC;QACf,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;YACjD,GAAG,CAAC,sBAAsB,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACjB,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAC1D,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,aAAa,MAAM,0BAA0B,CAAC,CAAC;QACnD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC;AAED,OAAO;AACP,KAAK,UAAU,IAAI;IACjB,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACpB,GAAG,CAAC,6CAA6C,CAAC,CAAC;IACnD,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpB,MAAM,iBAAiB,EAAE,CAAC;IAC1B,MAAM,kBAAkB,EAAE,CAAC;IAC3B,MAAM,qBAAqB,EAAE,CAAC;IAC9B,MAAM,qBAAqB,EAAE,CAAC;IAC9B,MAAM,qBAAqB,EAAE,CAAC;IAC9B,MAAM,uBAAuB,EAAE,CAAC;IAEhC,YAAY,EAAE,CAAC;AACjB,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tests: CLI Install Command & URL Resolution
3
+ *
4
+ * Tests the `install` command logic, handler selection, and
5
+ * the resolveMcpServerUrl utility.
6
+ *
7
+ * Run with: npx tsx src/__tests__/install-command.test.ts
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=install-command.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-command.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/install-command.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Tests: CLI Install Command & URL Resolution
3
+ *
4
+ * Tests the `install` command logic, handler selection, and
5
+ * the resolveMcpServerUrl utility.
6
+ *
7
+ * Run with: npx tsx src/__tests__/install-command.test.ts
8
+ */
9
+ import { getIDEHandler, } from '../ide-handlers/index.js';
10
+ import { buildTostudyServerEntry, buildMcpRemoteArgs } from '../ide-handlers/base.js';
11
+ // We can't import resolveMcpServerUrl directly since it's a module-scoped function in index.ts.
12
+ // Replicate the logic here and test it.
13
+ function resolveMcpServerUrl(platformUrl) {
14
+ if (platformUrl.includes(':3700')) {
15
+ return platformUrl.replace(':3700', ':3701');
16
+ }
17
+ if (platformUrl.includes('localhost') && !platformUrl.includes(':')) {
18
+ return 'http://localhost:3701';
19
+ }
20
+ if (platformUrl.includes('tostudy')) {
21
+ return process.env.MCP_SERVER_URL || 'https://mcp.tostudy.ai';
22
+ }
23
+ return platformUrl;
24
+ }
25
+ const results = [];
26
+ function log(message) {
27
+ process.stdout.write(`${message}\n`);
28
+ }
29
+ function assert(condition, message) {
30
+ if (!condition) {
31
+ throw new Error(`Assertion failed: ${message}`);
32
+ }
33
+ }
34
+ async function runTest(name, testFn) {
35
+ try {
36
+ await testFn();
37
+ results.push({ name, passed: true, message: 'OK' });
38
+ log(` \x1b[32m✓\x1b[0m ${name}`);
39
+ }
40
+ catch (error) {
41
+ const message = error instanceof Error ? error.message : String(error);
42
+ results.push({ name, passed: false, message });
43
+ log(` \x1b[31m✗\x1b[0m ${name}: ${message}`);
44
+ }
45
+ }
46
+ // ───────────── resolveMcpServerUrl ─────────────
47
+ async function testUrlResolution() {
48
+ log('\n── resolveMcpServerUrl ──');
49
+ await runTest('Resolves localhost:3700 to localhost:3701', () => {
50
+ const result = resolveMcpServerUrl('http://localhost:3700');
51
+ assert(result === 'http://localhost:3701', `Expected http://localhost:3701, got ${result}`);
52
+ });
53
+ await runTest('Resolves https://localhost:3700 to https://localhost:3701', () => {
54
+ const result = resolveMcpServerUrl('https://localhost:3700');
55
+ assert(result === 'https://localhost:3701', `Expected https://localhost:3701, got ${result}`);
56
+ });
57
+ await runTest('Bare localhost with protocol is returned as-is (has colon in URL)', () => {
58
+ // "http://localhost" contains a colon (from http:), so the `!platformUrl.includes(':')` check fails.
59
+ // This is expected — the function targets the edge case of literally "localhost" with no protocol.
60
+ const result = resolveMcpServerUrl('http://localhost');
61
+ assert(result === 'http://localhost', `Expected http://localhost unchanged, got ${result}`);
62
+ });
63
+ await runTest('Resolves tostudy.com to mcp.tostudy.ai', () => {
64
+ // Clear env var to test default
65
+ const saved = process.env.MCP_SERVER_URL;
66
+ delete process.env.MCP_SERVER_URL;
67
+ const result = resolveMcpServerUrl('https://tostudy.com');
68
+ assert(result === 'https://mcp.tostudy.ai', `Expected https://mcp.tostudy.ai, got ${result}`);
69
+ // Restore
70
+ if (saved !== undefined)
71
+ process.env.MCP_SERVER_URL = saved;
72
+ });
73
+ await runTest('Respects MCP_SERVER_URL env var for tostudy URLs', () => {
74
+ const saved = process.env.MCP_SERVER_URL;
75
+ process.env.MCP_SERVER_URL = 'https://custom-mcp.example.com';
76
+ const result = resolveMcpServerUrl('https://tostudy.com');
77
+ assert(result === 'https://custom-mcp.example.com', `Expected custom URL, got ${result}`);
78
+ // Restore
79
+ if (saved !== undefined) {
80
+ process.env.MCP_SERVER_URL = saved;
81
+ }
82
+ else {
83
+ delete process.env.MCP_SERVER_URL;
84
+ }
85
+ });
86
+ await runTest('Returns unknown URLs unchanged', () => {
87
+ const result = resolveMcpServerUrl('https://example.com/api');
88
+ assert(result === 'https://example.com/api', `Expected unchanged URL, got ${result}`);
89
+ });
90
+ }
91
+ // ───────────── Install Command Logic ─────────────
92
+ async function testInstallCommandLogic() {
93
+ log('\n── Install Command Logic ──');
94
+ const SUPPORTED_IDES = ['claude-code', 'cursor', 'vscode', 'desktop', 'opencode', 'manual'];
95
+ await runTest('All supported IDEs can be resolved to a handler', () => {
96
+ for (const ide of SUPPORTED_IDES) {
97
+ const handler = getIDEHandler(ide);
98
+ assert(handler !== undefined, `Handler for ${ide} should be resolved`);
99
+ assert(handler.id === ide, `Handler id should match ${ide}`);
100
+ }
101
+ });
102
+ await runTest('Unsupported IDE throws error', () => {
103
+ let threw = false;
104
+ try {
105
+ getIDEHandler('vim');
106
+ }
107
+ catch {
108
+ threw = true;
109
+ }
110
+ assert(threw, 'Should throw for unsupported IDE');
111
+ });
112
+ await runTest('Handler writeConfig accepts key and URL', async () => {
113
+ // Manual handler doesn't write to filesystem, safe to call
114
+ const handler = getIDEHandler('manual');
115
+ // Capture stdout to prevent output during test
116
+ const originalWrite = process.stdout.write;
117
+ let output = '';
118
+ process.stdout.write = ((chunk) => {
119
+ output += chunk;
120
+ return true;
121
+ });
122
+ try {
123
+ await handler.writeConfig('test-key-123', 'https://mcp.tostudy.ai');
124
+ assert(output.includes('"command": "npx"'), 'Manual output should include npx command');
125
+ assert(output.includes('mcp-remote'), 'Manual output should include mcp-remote');
126
+ assert(output.includes('test-key-123'), 'Manual output should include the API key');
127
+ }
128
+ finally {
129
+ process.stdout.write = originalWrite;
130
+ }
131
+ });
132
+ await runTest('Handler verify returns boolean', async () => {
133
+ // Verify against a non-existent server should return false
134
+ const handler = getIDEHandler('manual');
135
+ const result = await handler.verify('fake-key', 'http://localhost:99999');
136
+ assert(typeof result === 'boolean', 'verify() should return boolean');
137
+ assert(result === false, 'verify() against non-existent server should return false');
138
+ });
139
+ }
140
+ // ───────────── Server Entry Structure ─────────────
141
+ async function testServerEntryStructure() {
142
+ log('\n── Server Entry Structure ──');
143
+ await runTest('Entry has correct shape for IDE configs', () => {
144
+ const entry = buildTostudyServerEntry('my-key', 'https://mcp.tostudy.ai');
145
+ assert(typeof entry === 'object', 'Entry should be an object');
146
+ assert(entry.command === 'npx', 'Command should be npx');
147
+ assert(Array.isArray(entry.args), 'Args should be an array');
148
+ // Verify args structure
149
+ const args = entry.args;
150
+ assert(args.includes('-y'), 'Should have -y flag');
151
+ assert(args.includes('mcp-remote'), 'Should have mcp-remote');
152
+ assert(args.includes('--header'), 'Should have --header flag');
153
+ assert(args.some((a) => a.includes('Authorization:Bearer my-key')), 'Should have authorization header with key');
154
+ assert(args.some((a) => a.includes('https://mcp.tostudy.ai/mcp')), 'Should have MCP URL with /mcp suffix');
155
+ });
156
+ await runTest('Args encode API key correctly', () => {
157
+ const specialKey = 'key-with-special-chars!@#';
158
+ const args = buildMcpRemoteArgs(specialKey, 'https://mcp.test.com');
159
+ const authArg = args.find((a) => a.includes('Authorization'));
160
+ assert(authArg !== undefined, 'Should have auth arg');
161
+ assert(authArg === `Authorization:Bearer ${specialKey}`, 'Auth arg should contain exact key without encoding');
162
+ });
163
+ await runTest('MCP URL gets /mcp suffix', () => {
164
+ const args = buildMcpRemoteArgs('key', 'https://mcp.tostudy.ai');
165
+ const urlArg = args[2];
166
+ assert(urlArg === 'https://mcp.tostudy.ai/mcp', `URL should have /mcp suffix, got ${urlArg}`);
167
+ });
168
+ }
169
+ // ───────────── IDE-specific Config Formats ─────────────
170
+ async function testIDEConfigFormats() {
171
+ log('\n── IDE Config Formats ──');
172
+ await runTest('Cursor uses mcpServers key', () => {
173
+ const entry = buildTostudyServerEntry('key', 'https://mcp.tostudy.ai');
174
+ // Simulate Cursor config shape
175
+ const config = { mcpServers: { tostudy: entry } };
176
+ const json = JSON.stringify(config);
177
+ assert(json.includes('"mcpServers"'), 'Cursor config should use mcpServers');
178
+ assert(!json.includes('"servers"'), 'Cursor config should NOT use bare servers');
179
+ });
180
+ await runTest('VS Code uses servers key', () => {
181
+ const entry = buildTostudyServerEntry('key', 'https://mcp.tostudy.ai');
182
+ // Simulate VS Code config shape
183
+ const config = { servers: { tostudy: entry } };
184
+ const json = JSON.stringify(config);
185
+ assert(json.includes('"servers"'), 'VSCode config should use servers');
186
+ });
187
+ await runTest('OpenCode uses mcp key', () => {
188
+ const entry = buildTostudyServerEntry('key', 'https://mcp.tostudy.ai');
189
+ // Simulate OpenCode config shape
190
+ const config = { mcp: { tostudy: entry } };
191
+ const json = JSON.stringify(config);
192
+ assert(json.includes('"mcp"'), 'OpenCode config should use mcp');
193
+ });
194
+ await runTest('Desktop uses SSE transport (different from other handlers)', () => {
195
+ // Desktop handler uses addTostudyMcpServer which writes SSE config,
196
+ // while other handlers use stdio (npx mcp-remote)
197
+ const handler = getIDEHandler('desktop');
198
+ assert(handler.name === 'Claude Desktop', 'Should be Claude Desktop handler');
199
+ // The desktop handler's config includes SSE transport via addTostudyMcpServer
200
+ // We can't easily test this without writing files, so just verify the handler exists
201
+ });
202
+ }
203
+ // ───────────── Summary ─────────────
204
+ function printSummary() {
205
+ log('\n' + '═'.repeat(50));
206
+ log('INSTALL COMMAND TEST SUMMARY');
207
+ log('═'.repeat(50));
208
+ const passed = results.filter((r) => r.passed).length;
209
+ const failed = results.filter((r) => !r.passed).length;
210
+ log(`\nTotal: ${results.length} | Passed: ${passed} | Failed: ${failed}\n`);
211
+ if (failed > 0) {
212
+ log('FAILED:');
213
+ for (const r of results.filter((r) => !r.passed)) {
214
+ log(` \x1b[31m✗\x1b[0m ${r.name}: ${r.message}`);
215
+ }
216
+ }
217
+ if (failed === 0) {
218
+ log('\x1b[32m✓ All install command tests passed!\x1b[0m\n');
219
+ }
220
+ else {
221
+ log(`\x1b[31m✗ ${failed} test(s) failed\x1b[0m\n`);
222
+ process.exitCode = 1;
223
+ }
224
+ }
225
+ // Main
226
+ async function main() {
227
+ log('═'.repeat(50));
228
+ log('TEST: CLI Install Command & URL Resolution');
229
+ log('═'.repeat(50));
230
+ await testUrlResolution();
231
+ await testInstallCommandLogic();
232
+ await testServerEntryStructure();
233
+ await testIDEConfigFormats();
234
+ printSummary();
235
+ }
236
+ main();
237
+ //# sourceMappingURL=install-command.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-command.test.js","sourceRoot":"","sources":["../../src/__tests__/install-command.test.ts"],"names":[],"mappings":"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"}