@recapt/mcp 0.0.19-beta → 0.0.20-beta
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/dist/cli/index.d.ts +0 -11
- package/dist/cli/index.js +1059 -21
- package/dist/index.d.ts +0 -19
- package/dist/index.js +3210 -89
- package/package.json +5 -3
- package/dist/api/client.d.ts +0 -6
- package/dist/api/client.js +0 -6
- package/dist/cli/commands/setup-self-improvement-gh.d.ts +0 -7
- package/dist/cli/commands/setup-self-improvement-gh.js +0 -310
- package/dist/cli/commands/setup.d.ts +0 -7
- package/dist/cli/commands/setup.js +0 -178
- package/dist/cli/commands/skill.d.ts +0 -24
- package/dist/cli/commands/skill.js +0 -264
- package/dist/cli/utils/ide-config.d.ts +0 -31
- package/dist/cli/utils/ide-config.js +0 -294
- package/dist/cli/utils/prompts.d.ts +0 -22
- package/dist/cli/utils/prompts.js +0 -71
- package/dist/tools/analyzeFlow.d.ts +0 -7
- package/dist/tools/analyzeFlow.js +0 -68
- package/dist/tools/analyzeFunnel.d.ts +0 -7
- package/dist/tools/analyzeFunnel.js +0 -63
- package/dist/tools/catalog/callTool.d.ts +0 -22
- package/dist/tools/catalog/callTool.js +0 -92
- package/dist/tools/catalog/index.d.ts +0 -11
- package/dist/tools/catalog/index.js +0 -11
- package/dist/tools/catalog/searchTools.d.ts +0 -22
- package/dist/tools/catalog/searchTools.js +0 -194
- package/dist/tools/compareCohorts.d.ts +0 -6
- package/dist/tools/compareCohorts.js +0 -84
- package/dist/tools/comparePeriods.d.ts +0 -6
- package/dist/tools/comparePeriods.js +0 -54
- package/dist/tools/detectDrift.d.ts +0 -6
- package/dist/tools/detectDrift.js +0 -55
- package/dist/tools/detectRegressions.d.ts +0 -6
- package/dist/tools/detectRegressions.js +0 -63
- package/dist/tools/diagnostic.d.ts +0 -6
- package/dist/tools/diagnostic.js +0 -109
- package/dist/tools/discoverPersonas.d.ts +0 -6
- package/dist/tools/discoverPersonas.js +0 -50
- package/dist/tools/getActionableIssues.d.ts +0 -7
- package/dist/tools/getActionableIssues.js +0 -55
- package/dist/tools/getAnomalies.d.ts +0 -6
- package/dist/tools/getAnomalies.js +0 -53
- package/dist/tools/getConsoleErrors.d.ts +0 -6
- package/dist/tools/getConsoleErrors.js +0 -61
- package/dist/tools/getDeadClicks.d.ts +0 -6
- package/dist/tools/getDeadClicks.js +0 -42
- package/dist/tools/getDomains.d.ts +0 -6
- package/dist/tools/getDomains.js +0 -34
- package/dist/tools/getElementFriction.d.ts +0 -6
- package/dist/tools/getElementFriction.js +0 -45
- package/dist/tools/getFlowFriction.d.ts +0 -7
- package/dist/tools/getFlowFriction.js +0 -57
- package/dist/tools/getFormFriction.d.ts +0 -6
- package/dist/tools/getFormFriction.js +0 -42
- package/dist/tools/getIssues.d.ts +0 -6
- package/dist/tools/getIssues.js +0 -82
- package/dist/tools/getJourneyPatterns.d.ts +0 -7
- package/dist/tools/getJourneyPatterns.js +0 -50
- package/dist/tools/getPageMetrics.d.ts +0 -6
- package/dist/tools/getPageMetrics.js +0 -47
- package/dist/tools/getPageTrends.d.ts +0 -6
- package/dist/tools/getPageTrends.js +0 -46
- package/dist/tools/getSessionDetails.d.ts +0 -6
- package/dist/tools/getSessionDetails.js +0 -70
- package/dist/tools/getSessionPages.d.ts +0 -7
- package/dist/tools/getSessionPages.js +0 -74
- package/dist/tools/getUxHealthReport.d.ts +0 -7
- package/dist/tools/getUxHealthReport.js +0 -50
- package/dist/tools/improvementRun.d.ts +0 -6
- package/dist/tools/improvementRun.js +0 -386
- package/dist/tools/knowledge.d.ts +0 -6
- package/dist/tools/knowledge.js +0 -186
- package/dist/tools/listPages.d.ts +0 -6
- package/dist/tools/listPages.js +0 -50
- package/dist/tools/listSessions.d.ts +0 -7
- package/dist/tools/listSessions.js +0 -67
- package/dist/tools/memory.d.ts +0 -7
- package/dist/tools/memory.js +0 -119
- package/dist/tools/predictOutcomes.d.ts +0 -6
- package/dist/tools/predictOutcomes.js +0 -66
- package/dist/tools/remediation.d.ts +0 -6
- package/dist/tools/remediation.js +0 -335
- package/dist/tools/scanSite.d.ts +0 -6
- package/dist/tools/scanSite.js +0 -51
- package/dist/tools/searchSessions.d.ts +0 -6
- package/dist/tools/searchSessions.js +0 -51
- package/dist/tools/triage.d.ts +0 -6
- package/dist/tools/triage.js +0 -114
- package/dist/tools/triageSessions.d.ts +0 -8
- package/dist/tools/triageSessions.js +0 -197
- package/dist/tools/upgradeOptions.d.ts +0 -7
- package/dist/tools/upgradeOptions.js +0 -67
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skill Command
|
|
3
|
-
*
|
|
4
|
-
* Manages recapt workflow skills installation to .agents/recapt/.
|
|
5
|
-
* Works across all AI IDEs that support the AGENTS.md standard.
|
|
6
|
-
*/
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
import fs from "fs";
|
|
9
|
-
import path from "path";
|
|
10
|
-
import { fileURLToPath } from "url";
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = path.dirname(__filename);
|
|
13
|
-
const SKILLS_DIR = path.resolve(__dirname, "../../../skills");
|
|
14
|
-
const AGENTS_DIR = ".agents/recapt";
|
|
15
|
-
const AGENTS_MD = "AGENTS.md";
|
|
16
|
-
const MARKER_START = "<!-- recapt:skills -->";
|
|
17
|
-
const MARKER_END = "<!-- /recapt:skills -->";
|
|
18
|
-
export function getAvailableSkills() {
|
|
19
|
-
if (!fs.existsSync(SKILLS_DIR)) {
|
|
20
|
-
throw new Error(`Skills directory not found: ${SKILLS_DIR}`);
|
|
21
|
-
}
|
|
22
|
-
const files = fs.readdirSync(SKILLS_DIR).filter((f) => f.endsWith(".md"));
|
|
23
|
-
if (files.length === 0) {
|
|
24
|
-
throw new Error(`No skill files found in: ${SKILLS_DIR}`);
|
|
25
|
-
}
|
|
26
|
-
return files.map((file) => {
|
|
27
|
-
const content = fs.readFileSync(path.join(SKILLS_DIR, file), "utf-8");
|
|
28
|
-
const firstLine = content.split("\n")[0];
|
|
29
|
-
const description = firstLine.startsWith("# ")
|
|
30
|
-
? firstLine.slice(2).trim()
|
|
31
|
-
: file.replace(".md", "");
|
|
32
|
-
return {
|
|
33
|
-
name: file.replace(".md", ""),
|
|
34
|
-
file,
|
|
35
|
-
description,
|
|
36
|
-
};
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
function getInstalledSkills(cwd) {
|
|
40
|
-
const agentsDir = path.join(cwd, AGENTS_DIR);
|
|
41
|
-
if (!fs.existsSync(agentsDir)) {
|
|
42
|
-
return [];
|
|
43
|
-
}
|
|
44
|
-
return fs
|
|
45
|
-
.readdirSync(agentsDir)
|
|
46
|
-
.filter((f) => f.endsWith(".md"))
|
|
47
|
-
.map((f) => f.replace(".md", ""));
|
|
48
|
-
}
|
|
49
|
-
function ensureAgentsDir(cwd) {
|
|
50
|
-
const agentsDir = path.join(cwd, AGENTS_DIR);
|
|
51
|
-
if (!fs.existsSync(agentsDir)) {
|
|
52
|
-
fs.mkdirSync(agentsDir, { recursive: true });
|
|
53
|
-
console.log(`Created ${AGENTS_DIR}/`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function readAgentsMd(cwd) {
|
|
57
|
-
const agentsMdPath = path.join(cwd, AGENTS_MD);
|
|
58
|
-
if (!fs.existsSync(agentsMdPath)) {
|
|
59
|
-
return "";
|
|
60
|
-
}
|
|
61
|
-
return fs.readFileSync(agentsMdPath, "utf-8");
|
|
62
|
-
}
|
|
63
|
-
function writeAgentsMd(cwd, content) {
|
|
64
|
-
const agentsMdPath = path.join(cwd, AGENTS_MD);
|
|
65
|
-
fs.writeFileSync(agentsMdPath, content);
|
|
66
|
-
}
|
|
67
|
-
function getSkillDisplayName(skillName) {
|
|
68
|
-
try {
|
|
69
|
-
const skills = getAvailableSkills();
|
|
70
|
-
const skill = skills.find((s) => s.name === skillName);
|
|
71
|
-
return skill?.description ?? skillName;
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return skillName;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
function updateAgentsMdReferences(cwd) {
|
|
78
|
-
const installed = getInstalledSkills(cwd);
|
|
79
|
-
let content = readAgentsMd(cwd);
|
|
80
|
-
if (installed.length === 0) {
|
|
81
|
-
if (content.includes(MARKER_START)) {
|
|
82
|
-
const regex = new RegExp(`\\n?${MARKER_START}[\\s\\S]*?${MARKER_END}\\n?`, "g");
|
|
83
|
-
content = content.replace(regex, "").trim();
|
|
84
|
-
if (content) {
|
|
85
|
-
writeAgentsMd(cwd, content + "\n");
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
const agentsMdPath = path.join(cwd, AGENTS_MD);
|
|
89
|
-
if (fs.existsSync(agentsMdPath)) {
|
|
90
|
-
fs.unlinkSync(agentsMdPath);
|
|
91
|
-
console.log(`Removed empty ${AGENTS_MD}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
const skillLinks = installed
|
|
98
|
-
.map((name) => `- [${getSkillDisplayName(name)}](${AGENTS_DIR}/${name}.md)`)
|
|
99
|
-
.join("\n");
|
|
100
|
-
const newBlock = `${MARKER_START}
|
|
101
|
-
For recapt behavioral intelligence workflows, see:
|
|
102
|
-
${skillLinks}
|
|
103
|
-
${MARKER_END}`;
|
|
104
|
-
if (content.includes(MARKER_START)) {
|
|
105
|
-
const regex = new RegExp(`${MARKER_START}[\\s\\S]*?${MARKER_END}`, "g");
|
|
106
|
-
content = content.replace(regex, newBlock);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
if (content.trim()) {
|
|
110
|
-
content = content.trim() + "\n\n" + newBlock;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
content = `# Project Agent Instructions\n\n${newBlock}`;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
writeAgentsMd(cwd, content + "\n");
|
|
117
|
-
}
|
|
118
|
-
export function installSkill(cwd, skillName, force = false) {
|
|
119
|
-
let skills;
|
|
120
|
-
try {
|
|
121
|
-
skills = getAvailableSkills();
|
|
122
|
-
}
|
|
123
|
-
catch (err) {
|
|
124
|
-
console.error(`Failed to load skills: ${err instanceof Error ? err.message : err}`);
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
const skill = skills.find((s) => s.name === skillName);
|
|
128
|
-
if (!skill) {
|
|
129
|
-
console.error(`Unknown skill: ${skillName}`);
|
|
130
|
-
console.error(`Available skills: ${skills.map((s) => s.name).join(", ")}`);
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
ensureAgentsDir(cwd);
|
|
134
|
-
const sourcePath = path.join(SKILLS_DIR, skill.file);
|
|
135
|
-
const destPath = path.join(cwd, AGENTS_DIR, skill.file);
|
|
136
|
-
if (fs.existsSync(destPath)) {
|
|
137
|
-
const sourceContent = fs.readFileSync(sourcePath, "utf-8");
|
|
138
|
-
const destContent = fs.readFileSync(destPath, "utf-8");
|
|
139
|
-
if (sourceContent === destContent) {
|
|
140
|
-
console.log(`Skill already up to date: ${skillName}`);
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
if (!force) {
|
|
144
|
-
console.log(`Skill outdated: ${skillName} (use --force to update)`);
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
fs.copyFileSync(sourcePath, destPath);
|
|
148
|
-
console.log(`Updated: ${skillName} → ${AGENTS_DIR}/${skill.file}`);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
fs.copyFileSync(sourcePath, destPath);
|
|
152
|
-
console.log(`Installed: ${skillName} → ${AGENTS_DIR}/${skill.file}`);
|
|
153
|
-
}
|
|
154
|
-
updateAgentsMdReferences(cwd);
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
function uninstallSkill(cwd, skillName) {
|
|
158
|
-
const skillPath = path.join(cwd, AGENTS_DIR, `${skillName}.md`);
|
|
159
|
-
if (!fs.existsSync(skillPath)) {
|
|
160
|
-
console.error(`Skill not installed: ${skillName}`);
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
fs.unlinkSync(skillPath);
|
|
164
|
-
console.log(`Uninstalled: ${skillName}`);
|
|
165
|
-
updateAgentsMdReferences(cwd);
|
|
166
|
-
const agentsDir = path.join(cwd, AGENTS_DIR);
|
|
167
|
-
const remaining = fs.readdirSync(agentsDir);
|
|
168
|
-
if (remaining.length === 0) {
|
|
169
|
-
fs.rmdirSync(agentsDir);
|
|
170
|
-
const parentDir = path.dirname(agentsDir);
|
|
171
|
-
if (fs.existsSync(parentDir) && fs.readdirSync(parentDir).length === 0) {
|
|
172
|
-
fs.rmdirSync(parentDir);
|
|
173
|
-
}
|
|
174
|
-
console.log(`Removed empty ${AGENTS_DIR}/`);
|
|
175
|
-
}
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
function listSkills(cwd) {
|
|
179
|
-
let available;
|
|
180
|
-
try {
|
|
181
|
-
available = getAvailableSkills();
|
|
182
|
-
}
|
|
183
|
-
catch (err) {
|
|
184
|
-
console.error(`Failed to load skills: ${err instanceof Error ? err.message : err}`);
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
const installed = new Set(getInstalledSkills(cwd));
|
|
188
|
-
console.log("\nAvailable recapt skills:\n");
|
|
189
|
-
for (const skill of available) {
|
|
190
|
-
const status = installed.has(skill.name) ? "[installed]" : "";
|
|
191
|
-
console.log(` ${skill.name.padEnd(20)} ${skill.description} ${status}`);
|
|
192
|
-
}
|
|
193
|
-
console.log();
|
|
194
|
-
}
|
|
195
|
-
export function installAllSkills(cwd, force = false) {
|
|
196
|
-
let skills;
|
|
197
|
-
try {
|
|
198
|
-
skills = getAvailableSkills();
|
|
199
|
-
}
|
|
200
|
-
catch (err) {
|
|
201
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
202
|
-
console.error(`Failed to load skills: ${message}`);
|
|
203
|
-
return { success: false, installed: [], failed: [], error: message };
|
|
204
|
-
}
|
|
205
|
-
return installSelectedSkills(cwd, skills.map((s) => s.name), force);
|
|
206
|
-
}
|
|
207
|
-
export function installSelectedSkills(cwd, skillNames, force = false) {
|
|
208
|
-
const installed = [];
|
|
209
|
-
const failed = [];
|
|
210
|
-
for (const skillName of skillNames) {
|
|
211
|
-
try {
|
|
212
|
-
if (installSkill(cwd, skillName, force)) {
|
|
213
|
-
installed.push(skillName);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
failed.push(skillName);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
catch (err) {
|
|
220
|
-
console.error(`Failed to install ${skillName}: ${err}`);
|
|
221
|
-
failed.push(skillName);
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const success = failed.length === 0 && installed.length > 0;
|
|
225
|
-
if (success && installed.length > 1) {
|
|
226
|
-
console.log(`\nAll skills installed. See ${AGENTS_MD} for references.`);
|
|
227
|
-
}
|
|
228
|
-
return { success, installed, failed };
|
|
229
|
-
}
|
|
230
|
-
const listCommand = new Command("list")
|
|
231
|
-
.description("Show available skills")
|
|
232
|
-
.action(() => {
|
|
233
|
-
listSkills(process.cwd());
|
|
234
|
-
});
|
|
235
|
-
const installCommand = new Command("install")
|
|
236
|
-
.description("Install a skill")
|
|
237
|
-
.argument("[name]", "Skill name to install")
|
|
238
|
-
.option("-a, --all", "Install all skills")
|
|
239
|
-
.option("-f, --force", "Force update if skill already exists")
|
|
240
|
-
.action((name, options) => {
|
|
241
|
-
const cwd = process.cwd();
|
|
242
|
-
if (options.all) {
|
|
243
|
-
installAllSkills(cwd, options.force);
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
if (!name) {
|
|
247
|
-
console.error("Usage: recapt skill install <name> or recapt skill install --all");
|
|
248
|
-
process.exit(1);
|
|
249
|
-
}
|
|
250
|
-
if (installSkill(cwd, name, options.force)) {
|
|
251
|
-
console.log(`\nSkill reference added to ${AGENTS_MD}`);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
const uninstallCommand = new Command("uninstall")
|
|
255
|
-
.description("Remove a skill")
|
|
256
|
-
.argument("<name>", "Skill name to uninstall")
|
|
257
|
-
.action((name) => {
|
|
258
|
-
uninstallSkill(process.cwd(), name);
|
|
259
|
-
});
|
|
260
|
-
export const skillCommand = new Command("skill")
|
|
261
|
-
.description("Manage recapt workflow skills")
|
|
262
|
-
.addCommand(listCommand)
|
|
263
|
-
.addCommand(installCommand)
|
|
264
|
-
.addCommand(uninstallCommand);
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDE Configuration Utilities
|
|
3
|
-
*
|
|
4
|
-
* Handles detection and configuration of MCP servers across different AI IDEs.
|
|
5
|
-
*/
|
|
6
|
-
export type ConfigFormat = "json" | "toml";
|
|
7
|
-
export interface IdeConfig {
|
|
8
|
-
name: string;
|
|
9
|
-
globalPath: string | null;
|
|
10
|
-
projectPath: string;
|
|
11
|
-
rootKey: string;
|
|
12
|
-
format: ConfigFormat;
|
|
13
|
-
}
|
|
14
|
-
export declare const IDE_CONFIGS: IdeConfig[];
|
|
15
|
-
export interface DetectedIde {
|
|
16
|
-
config: IdeConfig;
|
|
17
|
-
detected: boolean;
|
|
18
|
-
globalPathResolved: string | null;
|
|
19
|
-
}
|
|
20
|
-
export declare function detectInstalledIdes(): DetectedIde[];
|
|
21
|
-
export interface McpServerConfig {
|
|
22
|
-
type?: string;
|
|
23
|
-
command: string;
|
|
24
|
-
args: string[];
|
|
25
|
-
env: Record<string, string>;
|
|
26
|
-
}
|
|
27
|
-
export declare function readIdeConfig(configPath: string, format?: ConfigFormat): Record<string, unknown>;
|
|
28
|
-
export declare function writeIdeConfig(configPath: string, config: Record<string, unknown>, format?: ConfigFormat): void;
|
|
29
|
-
export declare function addRecaptToIdeConfig(ide: IdeConfig, secretKey: string, useGlobal?: boolean): string;
|
|
30
|
-
export declare function removeRecaptFromIdeConfig(ide: IdeConfig, useGlobal?: boolean): boolean;
|
|
31
|
-
export declare function isRecaptConfigured(ide: IdeConfig): boolean;
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* IDE Configuration Utilities
|
|
3
|
-
*
|
|
4
|
-
* Handles detection and configuration of MCP servers across different AI IDEs.
|
|
5
|
-
*/
|
|
6
|
-
import fs from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import os from "os";
|
|
9
|
-
export const IDE_CONFIGS = [
|
|
10
|
-
{
|
|
11
|
-
name: "Cursor",
|
|
12
|
-
globalPath: "~/.cursor/mcp.json",
|
|
13
|
-
projectPath: ".cursor/mcp.json",
|
|
14
|
-
rootKey: "mcpServers",
|
|
15
|
-
format: "json",
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
name: "Claude Code",
|
|
19
|
-
globalPath: "~/.claude.json",
|
|
20
|
-
projectPath: ".mcp.json",
|
|
21
|
-
rootKey: "mcpServers",
|
|
22
|
-
format: "json",
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: "Windsurf",
|
|
26
|
-
globalPath: "~/.windsurf/mcp.json",
|
|
27
|
-
projectPath: ".windsurf/mcp.json",
|
|
28
|
-
rootKey: "mcpServers",
|
|
29
|
-
format: "json",
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: "VS Code",
|
|
33
|
-
globalPath: null,
|
|
34
|
-
projectPath: ".vscode/mcp.json",
|
|
35
|
-
rootKey: "servers",
|
|
36
|
-
format: "json",
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: "Codex CLI",
|
|
40
|
-
globalPath: "~/.codex/config.toml",
|
|
41
|
-
projectPath: ".codex/config.toml",
|
|
42
|
-
rootKey: "mcp_servers",
|
|
43
|
-
format: "toml",
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: "Zed",
|
|
47
|
-
globalPath: "~/.config/zed/settings.json",
|
|
48
|
-
projectPath: ".zed/settings.json",
|
|
49
|
-
rootKey: "context_servers",
|
|
50
|
-
format: "json",
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: "GitHub Copilot",
|
|
54
|
-
globalPath: null,
|
|
55
|
-
projectPath: ".github/mcp.json",
|
|
56
|
-
rootKey: "servers",
|
|
57
|
-
format: "json",
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
function expandPath(p) {
|
|
61
|
-
if (p.startsWith("~/")) {
|
|
62
|
-
return path.join(os.homedir(), p.slice(2));
|
|
63
|
-
}
|
|
64
|
-
return p;
|
|
65
|
-
}
|
|
66
|
-
function ideExists(config) {
|
|
67
|
-
if (!config.globalPath) {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
const resolved = expandPath(config.globalPath);
|
|
71
|
-
const dir = path.dirname(resolved);
|
|
72
|
-
if (config.name === "Claude Code") {
|
|
73
|
-
return (fs.existsSync(resolved) ||
|
|
74
|
-
fs.existsSync(path.join(os.homedir(), ".claude")));
|
|
75
|
-
}
|
|
76
|
-
if (config.name === "Zed") {
|
|
77
|
-
return fs.existsSync(path.join(os.homedir(), ".config", "zed"));
|
|
78
|
-
}
|
|
79
|
-
if (config.name === "Codex CLI") {
|
|
80
|
-
return fs.existsSync(path.join(os.homedir(), ".codex"));
|
|
81
|
-
}
|
|
82
|
-
return fs.existsSync(dir);
|
|
83
|
-
}
|
|
84
|
-
export function detectInstalledIdes() {
|
|
85
|
-
return IDE_CONFIGS.map((config) => ({
|
|
86
|
-
config,
|
|
87
|
-
detected: ideExists(config),
|
|
88
|
-
globalPathResolved: config.globalPath
|
|
89
|
-
? expandPath(config.globalPath)
|
|
90
|
-
: null,
|
|
91
|
-
}));
|
|
92
|
-
}
|
|
93
|
-
function getRecaptServerConfig(secretKey) {
|
|
94
|
-
return {
|
|
95
|
-
type: "stdio",
|
|
96
|
-
command: "npx",
|
|
97
|
-
args: ["-y", "@recapt/mcp@latest"],
|
|
98
|
-
env: {
|
|
99
|
-
RECAPT_SECRET_KEY: secretKey,
|
|
100
|
-
},
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function readIdeConfig(configPath, format = "json") {
|
|
104
|
-
const resolved = expandPath(configPath);
|
|
105
|
-
if (!fs.existsSync(resolved)) {
|
|
106
|
-
return {};
|
|
107
|
-
}
|
|
108
|
-
try {
|
|
109
|
-
const content = fs.readFileSync(resolved, "utf-8");
|
|
110
|
-
if (format === "toml") {
|
|
111
|
-
return parseToml(content);
|
|
112
|
-
}
|
|
113
|
-
return JSON.parse(content);
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
return {};
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function parseToml(content) {
|
|
120
|
-
const result = {};
|
|
121
|
-
let currentSection = "";
|
|
122
|
-
let currentSubSection = "";
|
|
123
|
-
for (const line of content.split("\n")) {
|
|
124
|
-
const trimmed = line.trim();
|
|
125
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
|
|
129
|
-
if (sectionMatch) {
|
|
130
|
-
const section = sectionMatch[1];
|
|
131
|
-
const parts = section.split(".");
|
|
132
|
-
if (parts.length === 1) {
|
|
133
|
-
currentSection = parts[0];
|
|
134
|
-
currentSubSection = "";
|
|
135
|
-
if (!result[currentSection]) {
|
|
136
|
-
result[currentSection] = {};
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else if (parts.length === 2) {
|
|
140
|
-
currentSection = parts[0];
|
|
141
|
-
currentSubSection = parts[1];
|
|
142
|
-
if (!result[currentSection]) {
|
|
143
|
-
result[currentSection] = {};
|
|
144
|
-
}
|
|
145
|
-
const sectionObj = result[currentSection];
|
|
146
|
-
if (!sectionObj[currentSubSection]) {
|
|
147
|
-
sectionObj[currentSubSection] = {};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
const kvMatch = trimmed.match(/^(\w+)\s*=\s*(.+)$/);
|
|
153
|
-
if (kvMatch) {
|
|
154
|
-
const [, key, rawValue] = kvMatch;
|
|
155
|
-
const value = parseTomlValue(rawValue);
|
|
156
|
-
if (currentSubSection) {
|
|
157
|
-
const sectionObj = result[currentSection];
|
|
158
|
-
const subSectionObj = sectionObj[currentSubSection];
|
|
159
|
-
subSectionObj[key] = value;
|
|
160
|
-
}
|
|
161
|
-
else if (currentSection) {
|
|
162
|
-
const sectionObj = result[currentSection];
|
|
163
|
-
sectionObj[key] = value;
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
result[key] = value;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return result;
|
|
171
|
-
}
|
|
172
|
-
function parseTomlValue(raw) {
|
|
173
|
-
const trimmed = raw.trim();
|
|
174
|
-
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
175
|
-
return trimmed.slice(1, -1);
|
|
176
|
-
}
|
|
177
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
178
|
-
return trimmed.slice(1, -1);
|
|
179
|
-
}
|
|
180
|
-
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
181
|
-
const inner = trimmed.slice(1, -1);
|
|
182
|
-
if (!inner.trim())
|
|
183
|
-
return [];
|
|
184
|
-
return inner.split(",").map((item) => {
|
|
185
|
-
const t = item.trim();
|
|
186
|
-
if ((t.startsWith('"') && t.endsWith('"')) ||
|
|
187
|
-
(t.startsWith("'") && t.endsWith("'"))) {
|
|
188
|
-
return t.slice(1, -1);
|
|
189
|
-
}
|
|
190
|
-
return t;
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
if (trimmed === "true")
|
|
194
|
-
return true;
|
|
195
|
-
if (trimmed === "false")
|
|
196
|
-
return false;
|
|
197
|
-
const num = Number(trimmed);
|
|
198
|
-
if (!isNaN(num))
|
|
199
|
-
return num;
|
|
200
|
-
return trimmed;
|
|
201
|
-
}
|
|
202
|
-
function stringifyToml(obj, prefix = "") {
|
|
203
|
-
const lines = [];
|
|
204
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
205
|
-
if (value === null || value === undefined)
|
|
206
|
-
continue;
|
|
207
|
-
if (typeof value === "object" && !Array.isArray(value)) {
|
|
208
|
-
const sectionKey = prefix ? `${prefix}.${key}` : key;
|
|
209
|
-
const nested = value;
|
|
210
|
-
const hasNestedObjects = Object.values(nested).some((v) => typeof v === "object" && !Array.isArray(v));
|
|
211
|
-
if (hasNestedObjects) {
|
|
212
|
-
for (const [subKey, subValue] of Object.entries(nested)) {
|
|
213
|
-
if (typeof subValue === "object" && !Array.isArray(subValue)) {
|
|
214
|
-
lines.push(`[${sectionKey}.${subKey}]`);
|
|
215
|
-
for (const [k, v] of Object.entries(subValue)) {
|
|
216
|
-
lines.push(`${k} = ${tomlValue(v)}`);
|
|
217
|
-
}
|
|
218
|
-
lines.push("");
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
lines.push(`[${sectionKey}]`);
|
|
224
|
-
for (const [k, v] of Object.entries(nested)) {
|
|
225
|
-
lines.push(`${k} = ${tomlValue(v)}`);
|
|
226
|
-
}
|
|
227
|
-
lines.push("");
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return lines.join("\n");
|
|
232
|
-
}
|
|
233
|
-
function tomlValue(value) {
|
|
234
|
-
if (typeof value === "string") {
|
|
235
|
-
return `"${value}"`;
|
|
236
|
-
}
|
|
237
|
-
if (Array.isArray(value)) {
|
|
238
|
-
return `[${value.map((v) => (typeof v === "string" ? `"${v}"` : String(v))).join(", ")}]`;
|
|
239
|
-
}
|
|
240
|
-
return String(value);
|
|
241
|
-
}
|
|
242
|
-
export function writeIdeConfig(configPath, config, format = "json") {
|
|
243
|
-
const resolved = expandPath(configPath);
|
|
244
|
-
const dir = path.dirname(resolved);
|
|
245
|
-
if (!fs.existsSync(dir)) {
|
|
246
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
247
|
-
}
|
|
248
|
-
if (format === "toml") {
|
|
249
|
-
fs.writeFileSync(resolved, stringifyToml(config));
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
fs.writeFileSync(resolved, JSON.stringify(config, null, 2) + "\n");
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
export function addRecaptToIdeConfig(ide, secretKey, useGlobal = true) {
|
|
256
|
-
const configPath = useGlobal && ide.globalPath ? ide.globalPath : ide.projectPath;
|
|
257
|
-
const resolved = expandPath(configPath);
|
|
258
|
-
const existing = readIdeConfig(configPath, ide.format);
|
|
259
|
-
const rootKey = ide.rootKey;
|
|
260
|
-
const servers = existing[rootKey] || {};
|
|
261
|
-
servers["recapt"] = getRecaptServerConfig(secretKey);
|
|
262
|
-
existing[rootKey] = servers;
|
|
263
|
-
writeIdeConfig(configPath, existing, ide.format);
|
|
264
|
-
return resolved;
|
|
265
|
-
}
|
|
266
|
-
export function removeRecaptFromIdeConfig(ide, useGlobal = true) {
|
|
267
|
-
const configPath = useGlobal && ide.globalPath ? ide.globalPath : ide.projectPath;
|
|
268
|
-
const resolved = expandPath(configPath);
|
|
269
|
-
if (!fs.existsSync(resolved)) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
const existing = readIdeConfig(configPath, ide.format);
|
|
273
|
-
const rootKey = ide.rootKey;
|
|
274
|
-
const servers = existing[rootKey] || {};
|
|
275
|
-
if (!("recapt" in servers)) {
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
delete servers["recapt"];
|
|
279
|
-
existing[rootKey] = servers;
|
|
280
|
-
writeIdeConfig(configPath, existing, ide.format);
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
export function isRecaptConfigured(ide) {
|
|
284
|
-
if (ide.globalPath) {
|
|
285
|
-
const globalConfig = readIdeConfig(ide.globalPath, ide.format);
|
|
286
|
-
const servers = globalConfig[ide.rootKey] || {};
|
|
287
|
-
if ("recapt" in servers) {
|
|
288
|
-
return true;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
const projectConfig = readIdeConfig(ide.projectPath, ide.format);
|
|
292
|
-
const servers = projectConfig[ide.rootKey] || {};
|
|
293
|
-
return "recapt" in servers;
|
|
294
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive Prompts
|
|
3
|
-
*
|
|
4
|
-
* Arrow-key navigable prompts for CLI interactions using @inquirer/prompts.
|
|
5
|
-
*/
|
|
6
|
-
export declare function confirm(message: string, defaultYes?: boolean): Promise<boolean>;
|
|
7
|
-
export declare function input(message: string, defaultValue?: string): Promise<string>;
|
|
8
|
-
export declare function secret(message: string): Promise<string>;
|
|
9
|
-
export interface SelectOption<T = string> {
|
|
10
|
-
label: string;
|
|
11
|
-
value: T;
|
|
12
|
-
selected?: boolean;
|
|
13
|
-
}
|
|
14
|
-
export declare function multiSelect<T = string>(message: string, options: SelectOption<T>[]): Promise<T[]>;
|
|
15
|
-
export declare function select<T = string>(message: string, options: SelectOption<T>[]): Promise<T | null>;
|
|
16
|
-
export declare function print(message: string): void;
|
|
17
|
-
export declare function success(message: string): void;
|
|
18
|
-
export declare function error(message: string): void;
|
|
19
|
-
export declare function info(message: string): void;
|
|
20
|
-
export declare function warn(message: string): void;
|
|
21
|
-
export declare function newline(): void;
|
|
22
|
-
export declare function header(title: string): void;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interactive Prompts
|
|
3
|
-
*
|
|
4
|
-
* Arrow-key navigable prompts for CLI interactions using @inquirer/prompts.
|
|
5
|
-
*/
|
|
6
|
-
import { confirm as inquirerConfirm, input as inquirerInput, password as inquirerPassword, select as inquirerSelect, checkbox as inquirerCheckbox, } from "@inquirer/prompts";
|
|
7
|
-
export async function confirm(message, defaultYes = true) {
|
|
8
|
-
return inquirerConfirm({
|
|
9
|
-
message,
|
|
10
|
-
default: defaultYes,
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
export async function input(message, defaultValue) {
|
|
14
|
-
return inquirerInput({
|
|
15
|
-
message,
|
|
16
|
-
default: defaultValue,
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
export async function secret(message) {
|
|
20
|
-
const value = await inquirerPassword({
|
|
21
|
-
message,
|
|
22
|
-
mask: "*",
|
|
23
|
-
});
|
|
24
|
-
return value.trim();
|
|
25
|
-
}
|
|
26
|
-
export async function multiSelect(message, options) {
|
|
27
|
-
return inquirerCheckbox({
|
|
28
|
-
message,
|
|
29
|
-
choices: options.map((opt) => ({
|
|
30
|
-
name: opt.label,
|
|
31
|
-
value: opt.value,
|
|
32
|
-
checked: opt.selected ?? false,
|
|
33
|
-
})),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
export async function select(message, options) {
|
|
37
|
-
if (options.length === 0) {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
return inquirerSelect({
|
|
41
|
-
message,
|
|
42
|
-
choices: options.map((opt) => ({
|
|
43
|
-
name: opt.label,
|
|
44
|
-
value: opt.value,
|
|
45
|
-
})),
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
export function print(message) {
|
|
49
|
-
console.log(message);
|
|
50
|
-
}
|
|
51
|
-
export function success(message) {
|
|
52
|
-
console.log(`✓ ${message}`);
|
|
53
|
-
}
|
|
54
|
-
export function error(message) {
|
|
55
|
-
console.error(`✗ ${message}`);
|
|
56
|
-
}
|
|
57
|
-
export function info(message) {
|
|
58
|
-
console.log(`ℹ ${message}`);
|
|
59
|
-
}
|
|
60
|
-
export function warn(message) {
|
|
61
|
-
console.log(`⚠ ${message}`);
|
|
62
|
-
}
|
|
63
|
-
export function newline() {
|
|
64
|
-
console.log();
|
|
65
|
-
}
|
|
66
|
-
export function header(title) {
|
|
67
|
-
console.log();
|
|
68
|
-
console.log(title);
|
|
69
|
-
console.log("=".repeat(title.length));
|
|
70
|
-
console.log();
|
|
71
|
-
}
|