@tostudy-ai/mcp-setup 1.2.2 → 1.4.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 +26 -25
- package/dist/index.d.ts +2 -14
- package/dist/index.js +2989 -562
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/dist/__tests__/e2e-diagnostic-repair-flow.test.d.ts +0 -52
- package/dist/__tests__/e2e-diagnostic-repair-flow.test.d.ts.map +0 -1
- package/dist/__tests__/e2e-diagnostic-repair-flow.test.js +0 -720
- package/dist/__tests__/e2e-diagnostic-repair-flow.test.js.map +0 -1
- package/dist/__tests__/e2e-wizard-flow.test.d.ts +0 -43
- package/dist/__tests__/e2e-wizard-flow.test.d.ts.map +0 -1
- package/dist/__tests__/e2e-wizard-flow.test.js +0 -418
- package/dist/__tests__/e2e-wizard-flow.test.js.map +0 -1
- package/dist/__tests__/ide-handlers.test.d.ts +0 -10
- package/dist/__tests__/ide-handlers.test.d.ts.map +0 -1
- package/dist/__tests__/ide-handlers.test.js +0 -358
- package/dist/__tests__/ide-handlers.test.js.map +0 -1
- package/dist/__tests__/install-command.test.d.ts +0 -10
- package/dist/__tests__/install-command.test.d.ts.map +0 -1
- package/dist/__tests__/install-command.test.js +0 -248
- package/dist/__tests__/install-command.test.js.map +0 -1
- package/dist/callback-page.d.ts +0 -6
- package/dist/callback-page.d.ts.map +0 -1
- package/dist/callback-page.js +0 -96
- package/dist/callback-page.js.map +0 -1
- package/dist/config.d.ts +0 -62
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -167
- package/dist/config.js.map +0 -1
- package/dist/detect.d.ts +0 -42
- package/dist/detect.d.ts.map +0 -1
- package/dist/detect.js +0 -277
- package/dist/detect.js.map +0 -1
- package/dist/diagnose.d.ts +0 -36
- package/dist/diagnose.d.ts.map +0 -1
- package/dist/diagnose.js +0 -502
- package/dist/diagnose.js.map +0 -1
- package/dist/ide-handlers/antigravity.d.ts +0 -16
- package/dist/ide-handlers/antigravity.d.ts.map +0 -1
- package/dist/ide-handlers/antigravity.js +0 -46
- package/dist/ide-handlers/antigravity.js.map +0 -1
- package/dist/ide-handlers/base.d.ts +0 -36
- package/dist/ide-handlers/base.d.ts.map +0 -1
- package/dist/ide-handlers/base.js +0 -66
- package/dist/ide-handlers/base.js.map +0 -1
- package/dist/ide-handlers/claude-code.d.ts +0 -15
- package/dist/ide-handlers/claude-code.d.ts.map +0 -1
- package/dist/ide-handlers/claude-code.js +0 -50
- package/dist/ide-handlers/claude-code.js.map +0 -1
- package/dist/ide-handlers/codex.d.ts +0 -15
- package/dist/ide-handlers/codex.d.ts.map +0 -1
- package/dist/ide-handlers/codex.js +0 -53
- package/dist/ide-handlers/codex.js.map +0 -1
- package/dist/ide-handlers/cursor.d.ts +0 -15
- package/dist/ide-handlers/cursor.d.ts.map +0 -1
- package/dist/ide-handlers/cursor.js +0 -61
- package/dist/ide-handlers/cursor.js.map +0 -1
- package/dist/ide-handlers/desktop.d.ts +0 -16
- package/dist/ide-handlers/desktop.d.ts.map +0 -1
- package/dist/ide-handlers/desktop.js +0 -50
- package/dist/ide-handlers/desktop.js.map +0 -1
- package/dist/ide-handlers/index.d.ts +0 -21
- package/dist/ide-handlers/index.d.ts.map +0 -1
- package/dist/ide-handlers/index.js +0 -55
- package/dist/ide-handlers/index.js.map +0 -1
- package/dist/ide-handlers/manual.d.ts +0 -16
- package/dist/ide-handlers/manual.d.ts.map +0 -1
- package/dist/ide-handlers/manual.js +0 -34
- package/dist/ide-handlers/manual.js.map +0 -1
- package/dist/ide-handlers/opencode.d.ts +0 -15
- package/dist/ide-handlers/opencode.d.ts.map +0 -1
- package/dist/ide-handlers/opencode.js +0 -57
- package/dist/ide-handlers/opencode.js.map +0 -1
- package/dist/ide-handlers/vscode.d.ts +0 -16
- package/dist/ide-handlers/vscode.d.ts.map +0 -1
- package/dist/ide-handlers/vscode.js +0 -62
- package/dist/ide-handlers/vscode.js.map +0 -1
- package/dist/ide-handlers/windsurf.d.ts +0 -16
- package/dist/ide-handlers/windsurf.d.ts.map +0 -1
- package/dist/ide-handlers/windsurf.js +0 -46
- package/dist/ide-handlers/windsurf.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/oauth-server.d.ts +0 -4
- package/dist/oauth-server.d.ts.map +0 -1
- package/dist/oauth-server.js +0 -49
- package/dist/oauth-server.js.map +0 -1
- package/dist/prompts.d.ts +0 -23
- package/dist/prompts.d.ts.map +0 -1
- package/dist/prompts.js +0 -68
- package/dist/prompts.js.map +0 -1
- package/dist/repair.d.ts +0 -50
- package/dist/repair.d.ts.map +0 -1
- package/dist/repair.js +0 -633
- package/dist/repair.js.map +0 -1
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDE Handler Interface
|
|
3
|
-
*
|
|
4
|
-
* Each IDE has a handler that knows how to write MCP config
|
|
5
|
-
* to the correct location in the correct format.
|
|
6
|
-
*/
|
|
7
|
-
import { platform } from 'node:os';
|
|
8
|
-
/**
|
|
9
|
-
* Build the mcp-remote args array used by most IDE handlers.
|
|
10
|
-
*/
|
|
11
|
-
export function buildMcpRemoteArgs(apiKey, mcpUrl, ide) {
|
|
12
|
-
const osHeader = getClientOsHeaderValue();
|
|
13
|
-
return [
|
|
14
|
-
'-y',
|
|
15
|
-
'mcp-remote',
|
|
16
|
-
`${mcpUrl}/mcp`,
|
|
17
|
-
'--header',
|
|
18
|
-
`Authorization:Bearer ${apiKey}`,
|
|
19
|
-
'--header',
|
|
20
|
-
`X-Tostudy-Client-IDE:${ide}`,
|
|
21
|
-
'--header',
|
|
22
|
-
`X-Tostudy-Client-OS:${osHeader}`,
|
|
23
|
-
];
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Build the tostudy MCP server entry for stdio-based configs.
|
|
27
|
-
*/
|
|
28
|
-
export function buildTostudyServerEntry(apiKey, mcpUrl, ide) {
|
|
29
|
-
return {
|
|
30
|
-
command: 'npx',
|
|
31
|
-
args: buildMcpRemoteArgs(apiKey, mcpUrl, ide),
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Normalize current OS to the MCP metadata header format.
|
|
36
|
-
*/
|
|
37
|
-
export function getClientOsHeaderValue() {
|
|
38
|
-
switch (platform()) {
|
|
39
|
-
case 'darwin':
|
|
40
|
-
return 'macos';
|
|
41
|
-
case 'win32':
|
|
42
|
-
return 'windows';
|
|
43
|
-
default:
|
|
44
|
-
return 'linux';
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Verify connection by hitting the platform heartbeat endpoint.
|
|
49
|
-
*/
|
|
50
|
-
export async function verifyHeartbeat(apiKey, platformUrl) {
|
|
51
|
-
try {
|
|
52
|
-
const response = await fetch(`${platformUrl}/api/mcp/heartbeat`, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers: {
|
|
55
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
56
|
-
'Content-Type': 'application/json',
|
|
57
|
-
},
|
|
58
|
-
body: JSON.stringify({ timestamp: new Date().toISOString() }),
|
|
59
|
-
});
|
|
60
|
-
return response.ok || response.status === 204;
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
//# sourceMappingURL=base.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/ide-handlers/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAmBnC;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAc,EAAE,GAAW;IAC5E,MAAM,QAAQ,GAAG,sBAAsB,EAAE,CAAC;IAE1C,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,GAAG,MAAM,MAAM;QACf,UAAU;QACV,wBAAwB,MAAM,EAAE;QAChC,UAAU;QACV,wBAAwB,GAAG,EAAE;QAC7B,UAAU;QACV,uBAAuB,QAAQ,EAAE;KAClC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc,EAAE,MAAc,EAAE,GAAW;IACjF,OAAO;QACL,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC;KAC9C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IACpC,QAAQ,QAAQ,EAAE,EAAE,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,SAAS,CAAC;QACnB;YACE,OAAO,OAAO,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,WAAmB;IACvE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,oBAAoB,EAAE;YAC/D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,eAAe,EAAE,UAAU,MAAM,EAAE;gBACnC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Code IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Uses `claude mcp add` CLI command to register the MCP server.
|
|
5
|
-
*/
|
|
6
|
-
import { type IDEHandler } from './base.js';
|
|
7
|
-
export declare class ClaudeCodeHandler implements IDEHandler {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
detect(): Promise<boolean>;
|
|
11
|
-
getConfigPath(): string;
|
|
12
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
13
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=claude-code.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/claude-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,WAAW,CAAC;AAEjF,qBAAa,iBAAkB,YAAW,UAAU;IAClD,EAAE,SAAiB;IACnB,IAAI,SAAiB;IAEf,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAchC,aAAa,IAAI,MAAM;IAIjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Code IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Uses `claude mcp add` CLI command to register the MCP server.
|
|
5
|
-
*/
|
|
6
|
-
import { execFileSync } from 'node:child_process';
|
|
7
|
-
import { buildMcpRemoteArgs, verifyHeartbeat } from './base.js';
|
|
8
|
-
export class ClaudeCodeHandler {
|
|
9
|
-
id = 'claude-code';
|
|
10
|
-
name = 'Claude Code';
|
|
11
|
-
async detect() {
|
|
12
|
-
try {
|
|
13
|
-
execFileSync('which', ['claude'], { stdio: 'ignore' });
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
try {
|
|
18
|
-
execFileSync('where', ['claude'], { stdio: 'ignore' });
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
getConfigPath() {
|
|
27
|
-
return 'Terminal (claude mcp add)';
|
|
28
|
-
}
|
|
29
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
30
|
-
const args = buildMcpRemoteArgs(apiKey, mcpUrl, this.id);
|
|
31
|
-
try {
|
|
32
|
-
// First try to remove existing entry (ignore errors if it doesn't exist)
|
|
33
|
-
try {
|
|
34
|
-
execFileSync('claude', ['mcp', 'remove', 'tostudy'], { stdio: 'ignore' });
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
// Ignore - entry may not exist
|
|
38
|
-
}
|
|
39
|
-
execFileSync('claude', ['mcp', 'add', 'tostudy', '--', 'npx', ...args], { stdio: 'inherit' });
|
|
40
|
-
}
|
|
41
|
-
catch (error) {
|
|
42
|
-
throw new Error(`Failed to run 'claude mcp add'. Is Claude Code installed?\n` +
|
|
43
|
-
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async verify(apiKey, mcpUrl) {
|
|
47
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
//# sourceMappingURL=claude-code.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/ide-handlers/claude-code.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAmB,kBAAkB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjF,MAAM,OAAO,iBAAiB;IAC5B,EAAE,GAAG,aAAa,CAAC;IACnB,IAAI,GAAG,aAAa,CAAC;IAErB,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,YAAY,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACvD,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,2BAA2B,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,yEAAyE;YACzE,IAAI,CAAC;gBACH,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC5E,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;YAED,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAChG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,6DAA6D;gBAC7D,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codex IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Uses `codex mcp add` CLI command to register the MCP server.
|
|
5
|
-
*/
|
|
6
|
-
import { type IDEHandler } from './base.js';
|
|
7
|
-
export declare class CodexHandler implements IDEHandler {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
detect(): Promise<boolean>;
|
|
11
|
-
getConfigPath(): string;
|
|
12
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
13
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=codex.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/codex.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,KAAK,UAAU,EAAuC,MAAM,WAAW,CAAC;AAEjF,qBAAa,YAAa,YAAW,UAAU;IAC7C,EAAE,SAAW;IACb,IAAI,SAAW;IAET,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAchC,aAAa,IAAI,MAAM;IAIjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codex IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Uses `codex mcp add` CLI command to register the MCP server.
|
|
5
|
-
*/
|
|
6
|
-
import { execFileSync } from 'node:child_process';
|
|
7
|
-
import { existsSync } from 'node:fs';
|
|
8
|
-
import { join } from 'node:path';
|
|
9
|
-
import { homedir } from 'node:os';
|
|
10
|
-
import { buildMcpRemoteArgs, verifyHeartbeat } from './base.js';
|
|
11
|
-
export class CodexHandler {
|
|
12
|
-
id = 'codex';
|
|
13
|
-
name = 'Codex';
|
|
14
|
-
async detect() {
|
|
15
|
-
try {
|
|
16
|
-
execFileSync('which', ['codex'], { stdio: 'ignore' });
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
try {
|
|
21
|
-
execFileSync('where', ['codex'], { stdio: 'ignore' });
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return existsSync(join(homedir(), '.codex'));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
getConfigPath() {
|
|
30
|
-
return join(homedir(), '.codex', 'config.toml');
|
|
31
|
-
}
|
|
32
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
33
|
-
const args = buildMcpRemoteArgs(apiKey, mcpUrl, this.id);
|
|
34
|
-
try {
|
|
35
|
-
// First try to remove existing entry (ignore errors if it doesn't exist)
|
|
36
|
-
try {
|
|
37
|
-
execFileSync('codex', ['mcp', 'remove', 'tostudy'], { stdio: 'ignore' });
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
// Ignore - entry may not exist
|
|
41
|
-
}
|
|
42
|
-
execFileSync('codex', ['mcp', 'add', 'tostudy', '--', 'npx', ...args], { stdio: 'inherit' });
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
throw new Error(`Failed to run 'codex mcp add'. Is Codex installed?\n` +
|
|
46
|
-
`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
async verify(apiKey, mcpUrl) {
|
|
50
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//# sourceMappingURL=codex.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/ide-handlers/codex.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAmB,kBAAkB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjF,MAAM,OAAO,YAAY;IACvB,EAAE,GAAG,OAAO,CAAC;IACb,IAAI,GAAG,OAAO,CAAC;IAEf,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,YAAY,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACtD,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,IAAI,GAAG,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC;YACH,yEAAyE;YACzE,IAAI,CAAC;gBACH,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAC3E,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;YAED,YAAY,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,sDAAsD;gBACtD,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cursor IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/.cursor/mcp.json with { mcpServers: { tostudy: ... } }
|
|
5
|
-
*/
|
|
6
|
-
import { type IDEHandler } from './base.js';
|
|
7
|
-
export declare class CursorHandler implements IDEHandler {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
detect(): Promise<boolean>;
|
|
11
|
-
getConfigPath(): string;
|
|
12
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
13
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/cursor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,WAAW,CAAC;AAEtF,qBAAa,aAAc,YAAW,UAAU;IAC9C,EAAE,SAAY;IACd,IAAI,SAAY;IAEV,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAmBhC,aAAa,IAAI,MAAM;IAKjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cursor IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/.cursor/mcp.json with { mcpServers: { tostudy: ... } }
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
7
|
-
import { join, dirname } from 'node:path';
|
|
8
|
-
import { homedir, platform } from 'node:os';
|
|
9
|
-
import { buildTostudyServerEntry, verifyHeartbeat } from './base.js';
|
|
10
|
-
export class CursorHandler {
|
|
11
|
-
id = 'cursor';
|
|
12
|
-
name = 'Cursor';
|
|
13
|
-
async detect() {
|
|
14
|
-
const home = homedir();
|
|
15
|
-
const os = platform();
|
|
16
|
-
switch (os) {
|
|
17
|
-
case 'darwin':
|
|
18
|
-
return existsSync(join('/Applications', 'Cursor.app')) ||
|
|
19
|
-
existsSync(join(home, 'Applications', 'Cursor.app'));
|
|
20
|
-
case 'win32': {
|
|
21
|
-
const localAppData = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local');
|
|
22
|
-
return existsSync(join(localAppData, 'Programs', 'cursor', 'Cursor.exe'));
|
|
23
|
-
}
|
|
24
|
-
case 'linux':
|
|
25
|
-
return existsSync(join(home, '.cursor'));
|
|
26
|
-
default:
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
getConfigPath() {
|
|
31
|
-
const home = homedir();
|
|
32
|
-
return join(home, '.cursor', 'mcp.json');
|
|
33
|
-
}
|
|
34
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
35
|
-
const configPath = this.getConfigPath();
|
|
36
|
-
const configDir = dirname(configPath);
|
|
37
|
-
// Ensure directory exists
|
|
38
|
-
if (!existsSync(configDir)) {
|
|
39
|
-
mkdirSync(configDir, { recursive: true });
|
|
40
|
-
}
|
|
41
|
-
// Read existing config to preserve other servers
|
|
42
|
-
let config = {};
|
|
43
|
-
if (existsSync(configPath)) {
|
|
44
|
-
try {
|
|
45
|
-
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
// Start fresh if config is corrupted
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
// Merge - only update tostudy entry
|
|
52
|
-
const mcpServers = config.mcpServers ?? {};
|
|
53
|
-
mcpServers['tostudy'] = buildTostudyServerEntry(apiKey, mcpUrl, this.id);
|
|
54
|
-
config.mcpServers = mcpServers;
|
|
55
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
56
|
-
}
|
|
57
|
-
async verify(apiKey, mcpUrl) {
|
|
58
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=cursor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/ide-handlers/cursor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAmB,uBAAuB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEtF,MAAM,OAAO,aAAa;IACxB,EAAE,GAAG,QAAQ,CAAC;IACd,IAAI,GAAG,QAAQ,CAAC;IAEhB,KAAK,CAAC,MAAM;QACV,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;QAEtB,QAAQ,EAAE,EAAE,CAAC;YACX,KAAK,QAAQ;gBACX,OAAO,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;oBACpD,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC,CAAC;YACzD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;gBAChF,OAAO,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC;YAC5E,CAAC;YACD,KAAK,OAAO;gBACV,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;YAC3C;gBACE,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,aAAa;QACX,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAEtC,0BAA0B;QAC1B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,iDAAiD;QACjD,IAAI,MAAM,GAA4B,EAAE,CAAC;QACzC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,qCAAqC;YACvC,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,UAAU,GAAI,MAAM,CAAC,UAAsC,IAAI,EAAE,CAAC;QACxE,UAAU,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAE/B,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Desktop IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
5
|
-
* using stdio transport (command + args) via mcp-remote.
|
|
6
|
-
*/
|
|
7
|
-
import { type IDEHandler } from "./base.js";
|
|
8
|
-
export declare class DesktopHandler implements IDEHandler {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
detect(): Promise<boolean>;
|
|
12
|
-
getConfigPath(): string;
|
|
13
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
14
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=desktop.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"desktop.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/desktop.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,WAAW,CAAC;AAGtF,qBAAa,cAAe,YAAW,UAAU;IAC/C,EAAE,SAAa;IACf,IAAI,SAAoB;IAElB,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC,aAAa,IAAI,MAAM;IAIjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+B1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Desktop IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
5
|
-
* using stdio transport (command + args) via mcp-remote.
|
|
6
|
-
*/
|
|
7
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from "node:fs";
|
|
8
|
-
import { dirname } from "node:path";
|
|
9
|
-
import { buildTostudyServerEntry, verifyHeartbeat } from "./base.js";
|
|
10
|
-
import { isClaudeInstalled, getClaudeConfigPath } from "../config.js";
|
|
11
|
-
export class DesktopHandler {
|
|
12
|
-
id = "desktop";
|
|
13
|
-
name = "Claude Desktop";
|
|
14
|
-
async detect() {
|
|
15
|
-
return isClaudeInstalled();
|
|
16
|
-
}
|
|
17
|
-
getConfigPath() {
|
|
18
|
-
return getClaudeConfigPath();
|
|
19
|
-
}
|
|
20
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
21
|
-
const configPath = this.getConfigPath();
|
|
22
|
-
const configDir = dirname(configPath);
|
|
23
|
-
// Ensure directory exists
|
|
24
|
-
if (!existsSync(configDir)) {
|
|
25
|
-
mkdirSync(configDir, { recursive: true });
|
|
26
|
-
}
|
|
27
|
-
// Read existing config to preserve other servers and preferences
|
|
28
|
-
let config = {};
|
|
29
|
-
if (existsSync(configPath)) {
|
|
30
|
-
try {
|
|
31
|
-
config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
// Start fresh if config is corrupted
|
|
35
|
-
}
|
|
36
|
-
// Backup existing config
|
|
37
|
-
const backupPath = `${configPath}.backup`;
|
|
38
|
-
copyFileSync(configPath, backupPath);
|
|
39
|
-
}
|
|
40
|
-
// Merge - only update tostudy entry using stdio transport (command + args)
|
|
41
|
-
const mcpServers = config.mcpServers ?? {};
|
|
42
|
-
mcpServers["tostudy"] = buildTostudyServerEntry(apiKey, mcpUrl, this.id);
|
|
43
|
-
config.mcpServers = mcpServers;
|
|
44
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
45
|
-
}
|
|
46
|
-
async verify(apiKey, mcpUrl) {
|
|
47
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
//# sourceMappingURL=desktop.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"desktop.js","sourceRoot":"","sources":["../../src/ide-handlers/desktop.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC3F,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAmB,uBAAuB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,OAAO,cAAc;IACzB,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,gBAAgB,CAAC;IAExB,KAAK,CAAC,MAAM;QACV,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAED,aAAa;QACX,OAAO,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAEtC,0BAA0B;QAC1B,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,iEAAiE;QACjE,IAAI,MAAM,GAA4B,EAAE,CAAC;QACzC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,qCAAqC;YACvC,CAAC;YAED,yBAAyB;YACzB,MAAM,UAAU,GAAG,GAAG,UAAU,SAAS,CAAC;YAC1C,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QACvC,CAAC;QAED,2EAA2E;QAC3E,MAAM,UAAU,GAAI,MAAM,CAAC,UAAsC,IAAI,EAAE,CAAC;QACxE,UAAU,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAE/B,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDE Handler Factory
|
|
3
|
-
*
|
|
4
|
-
* Registry of all supported IDE handlers.
|
|
5
|
-
*/
|
|
6
|
-
import { type IDEHandler } from './base.js';
|
|
7
|
-
export type SupportedIDE = 'claude-code' | 'cursor' | 'vscode' | 'desktop' | 'windsurf' | 'opencode' | 'codex' | 'antigravity' | 'manual';
|
|
8
|
-
/**
|
|
9
|
-
* Get an IDE handler by type.
|
|
10
|
-
*/
|
|
11
|
-
export declare function getIDEHandler(ide: SupportedIDE): IDEHandler;
|
|
12
|
-
/**
|
|
13
|
-
* Get all available IDE handlers.
|
|
14
|
-
*/
|
|
15
|
-
export declare function getAllIDEHandlers(): IDEHandler[];
|
|
16
|
-
/**
|
|
17
|
-
* Detect which IDEs are installed.
|
|
18
|
-
*/
|
|
19
|
-
export declare function detectInstalledIDEs(): Promise<IDEHandler[]>;
|
|
20
|
-
export { type IDEHandler } from './base.js';
|
|
21
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAW5C,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,UAAU,GACV,UAAU,GACV,OAAO,GACP,aAAa,GACb,QAAQ,CAAC;AAcb;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,YAAY,GAAG,UAAU,CAM3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,EAAE,CAEhD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAWjE;AAED,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDE Handler Factory
|
|
3
|
-
*
|
|
4
|
-
* Registry of all supported IDE handlers.
|
|
5
|
-
*/
|
|
6
|
-
import { ClaudeCodeHandler } from './claude-code.js';
|
|
7
|
-
import { CursorHandler } from './cursor.js';
|
|
8
|
-
import { VSCodeHandler } from './vscode.js';
|
|
9
|
-
import { DesktopHandler } from './desktop.js';
|
|
10
|
-
import { WindsurfHandler } from './windsurf.js';
|
|
11
|
-
import { OpenCodeHandler } from './opencode.js';
|
|
12
|
-
import { CodexHandler } from './codex.js';
|
|
13
|
-
import { AntigravityHandler } from './antigravity.js';
|
|
14
|
-
import { ManualHandler } from './manual.js';
|
|
15
|
-
const handlers = {
|
|
16
|
-
'claude-code': () => new ClaudeCodeHandler(),
|
|
17
|
-
'cursor': () => new CursorHandler(),
|
|
18
|
-
'vscode': () => new VSCodeHandler(),
|
|
19
|
-
'desktop': () => new DesktopHandler(),
|
|
20
|
-
'windsurf': () => new WindsurfHandler(),
|
|
21
|
-
'opencode': () => new OpenCodeHandler(),
|
|
22
|
-
'codex': () => new CodexHandler(),
|
|
23
|
-
'antigravity': () => new AntigravityHandler(),
|
|
24
|
-
'manual': () => new ManualHandler(),
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Get an IDE handler by type.
|
|
28
|
-
*/
|
|
29
|
-
export function getIDEHandler(ide) {
|
|
30
|
-
const factory = handlers[ide];
|
|
31
|
-
if (!factory) {
|
|
32
|
-
throw new Error(`Unknown IDE: ${ide}. Supported: ${Object.keys(handlers).join(', ')}`);
|
|
33
|
-
}
|
|
34
|
-
return factory();
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Get all available IDE handlers.
|
|
38
|
-
*/
|
|
39
|
-
export function getAllIDEHandlers() {
|
|
40
|
-
return Object.values(handlers).map((factory) => factory());
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Detect which IDEs are installed.
|
|
44
|
-
*/
|
|
45
|
-
export async function detectInstalledIDEs() {
|
|
46
|
-
const all = getAllIDEHandlers();
|
|
47
|
-
const results = [];
|
|
48
|
-
for (const handler of all) {
|
|
49
|
-
if (await handler.detect()) {
|
|
50
|
-
results.push(handler);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return results;
|
|
54
|
-
}
|
|
55
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ide-handlers/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAa5C,MAAM,QAAQ,GAA2C;IACvD,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;IAC5C,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,aAAa,EAAE;IACnC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,aAAa,EAAE;IACnC,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,cAAc,EAAE;IACrC,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,EAAE;IACvC,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,EAAE;IACvC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,YAAY,EAAE;IACjC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,kBAAkB,EAAE;IAC7C,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,aAAa,EAAE;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAiB;IAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,GAAG,gBAAgB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;AAC7D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,OAAO,IAAI,GAAG,EAAE,CAAC;QAC1B,IAAI,MAAM,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Manual Handler
|
|
3
|
-
*
|
|
4
|
-
* Prints the config to stdout for the user to copy-paste.
|
|
5
|
-
* Does not write to any file.
|
|
6
|
-
*/
|
|
7
|
-
import { type IDEHandler } from './base.js';
|
|
8
|
-
export declare class ManualHandler implements IDEHandler {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
detect(): Promise<boolean>;
|
|
12
|
-
getConfigPath(): string;
|
|
13
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
14
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=manual.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manual.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/manual.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,WAAW,CAAC;AAEtF,qBAAa,aAAc,YAAW,UAAU;IAC9C,EAAE,SAAY;IACd,IAAI,SAAY;IAEV,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAIhC,aAAa,IAAI,MAAM;IAIjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Manual Handler
|
|
3
|
-
*
|
|
4
|
-
* Prints the config to stdout for the user to copy-paste.
|
|
5
|
-
* Does not write to any file.
|
|
6
|
-
*/
|
|
7
|
-
import chalk from 'chalk';
|
|
8
|
-
import { buildTostudyServerEntry, verifyHeartbeat } from './base.js';
|
|
9
|
-
export class ManualHandler {
|
|
10
|
-
id = 'manual';
|
|
11
|
-
name = 'Manual';
|
|
12
|
-
async detect() {
|
|
13
|
-
return true; // Always available
|
|
14
|
-
}
|
|
15
|
-
getConfigPath() {
|
|
16
|
-
return 'stdout';
|
|
17
|
-
}
|
|
18
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
19
|
-
const config = {
|
|
20
|
-
mcpServers: {
|
|
21
|
-
tostudy: buildTostudyServerEntry(apiKey, mcpUrl, this.id),
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
process.stdout.write('\n');
|
|
25
|
-
process.stdout.write(chalk.cyan('Add the following to your MCP config:\n'));
|
|
26
|
-
process.stdout.write('\n');
|
|
27
|
-
process.stdout.write(JSON.stringify(config, null, 2));
|
|
28
|
-
process.stdout.write('\n\n');
|
|
29
|
-
}
|
|
30
|
-
async verify(apiKey, mcpUrl) {
|
|
31
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=manual.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"manual.js","sourceRoot":"","sources":["../../src/ide-handlers/manual.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAmB,uBAAuB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEtF,MAAM,OAAO,aAAa;IACxB,EAAE,GAAG,QAAQ,CAAC;IACd,IAAI,GAAG,QAAQ,CAAC;IAEhB,KAAK,CAAC,MAAM;QACV,OAAO,IAAI,CAAC,CAAC,mBAAmB;IAClC,CAAC;IAED,aAAa;QACX,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,MAAM,GAAG;YACb,UAAU,EAAE;gBACV,OAAO,EAAE,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;aAC1D;SACF,CAAC;QAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenCode IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/.opencode/opencode.json with { mcp: { tostudy: ... } }
|
|
5
|
-
*/
|
|
6
|
-
import { type IDEHandler } from './base.js';
|
|
7
|
-
export declare class OpenCodeHandler implements IDEHandler {
|
|
8
|
-
id: string;
|
|
9
|
-
name: string;
|
|
10
|
-
detect(): Promise<boolean>;
|
|
11
|
-
getConfigPath(): string;
|
|
12
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
13
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,WAAW,CAAC;AAEtF,qBAAa,eAAgB,YAAW,UAAU;IAChD,EAAE,SAAc;IAChB,IAAI,SAAc;IAEZ,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAchC,aAAa,IAAI,MAAM;IAIjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenCode IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to ~/.opencode/opencode.json with { mcp: { tostudy: ... } }
|
|
5
|
-
*/
|
|
6
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
7
|
-
import { execFileSync } from 'node:child_process';
|
|
8
|
-
import { join, dirname } from 'node:path';
|
|
9
|
-
import { homedir } from 'node:os';
|
|
10
|
-
import { buildTostudyServerEntry, verifyHeartbeat } from './base.js';
|
|
11
|
-
export class OpenCodeHandler {
|
|
12
|
-
id = 'opencode';
|
|
13
|
-
name = 'OpenCode';
|
|
14
|
-
async detect() {
|
|
15
|
-
try {
|
|
16
|
-
execFileSync('which', ['opencode'], { stdio: 'ignore' });
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
try {
|
|
21
|
-
execFileSync('where', ['opencode'], { stdio: 'ignore' });
|
|
22
|
-
return true;
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return existsSync(join(homedir(), '.opencode'));
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
getConfigPath() {
|
|
30
|
-
return join(homedir(), '.opencode', 'opencode.json');
|
|
31
|
-
}
|
|
32
|
-
async writeConfig(apiKey, mcpUrl) {
|
|
33
|
-
const configPath = this.getConfigPath();
|
|
34
|
-
const configDir = dirname(configPath);
|
|
35
|
-
if (!existsSync(configDir)) {
|
|
36
|
-
mkdirSync(configDir, { recursive: true });
|
|
37
|
-
}
|
|
38
|
-
let config = {};
|
|
39
|
-
if (existsSync(configPath)) {
|
|
40
|
-
try {
|
|
41
|
-
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// Start fresh
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
// OpenCode uses "mcp" key
|
|
48
|
-
const mcp = config.mcp ?? {};
|
|
49
|
-
mcp['tostudy'] = buildTostudyServerEntry(apiKey, mcpUrl, this.id);
|
|
50
|
-
config.mcp = mcp;
|
|
51
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
52
|
-
}
|
|
53
|
-
async verify(apiKey, mcpUrl) {
|
|
54
|
-
return verifyHeartbeat(apiKey, mcpUrl);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=opencode.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/ide-handlers/opencode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAmB,uBAAuB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEtF,MAAM,OAAO,eAAe;IAC1B,EAAE,GAAG,UAAU,CAAC;IAChB,IAAI,GAAG,UAAU,CAAC;IAElB,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,YAAY,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACzD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC;gBACH,YAAY,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACzD,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,MAAc;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QAEtC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,MAAM,GAA4B,EAAE,CAAC;QACzC,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,cAAc;YAChB,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,MAAM,GAAG,GAAI,MAAM,CAAC,GAA+B,IAAI,EAAE,CAAC;QAC1D,GAAG,CAAC,SAAS,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;QAEjB,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,MAAc;QACzC,OAAO,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VS Code IDE Handler
|
|
3
|
-
*
|
|
4
|
-
* Writes to .vscode/mcp.json with { servers: { tostudy: ... } }
|
|
5
|
-
* Note: VS Code uses "servers" (not "mcpServers") in its config format.
|
|
6
|
-
*/
|
|
7
|
-
import { type IDEHandler } from './base.js';
|
|
8
|
-
export declare class VSCodeHandler implements IDEHandler {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
detect(): Promise<boolean>;
|
|
12
|
-
getConfigPath(): string;
|
|
13
|
-
writeConfig(apiKey: string, mcpUrl: string): Promise<void>;
|
|
14
|
-
verify(apiKey: string, mcpUrl: string): Promise<boolean>;
|
|
15
|
-
}
|
|
16
|
-
//# sourceMappingURL=vscode.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vscode.d.ts","sourceRoot":"","sources":["../../src/ide-handlers/vscode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,KAAK,UAAU,EAA4C,MAAM,WAAW,CAAC;AAEtF,qBAAa,aAAc,YAAW,UAAU;IAC9C,EAAE,SAAY;IACd,IAAI,SAAa;IAEX,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAqBhC,aAAa,IAAI,MAAM;IAKjB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB1D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG/D"}
|