aicm 0.14.4 → 0.14.5
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/commands/install.js +5 -5
- package/package.json +1 -1
- package/dist/api_v2.d.ts +0 -9
- package/dist/api_v2.js +0 -12
- package/dist/bin/aicm_v2.d.ts +0 -2
- package/dist/bin/aicm_v2.js +0 -8
- package/dist/cli_v2.d.ts +0 -2
- package/dist/cli_v2.js +0 -94
- package/dist/commands/install/install-package.d.ts +0 -53
- package/dist/commands/install/install-package.js +0 -122
- package/dist/commands/install/install-single-package.d.ts +0 -53
- package/dist/commands/install/install-single-package.js +0 -139
- package/dist/commands/install/install-workspaces.d.ts +0 -9
- package/dist/commands/install/install-workspaces.js +0 -172
- package/dist/commands/install_new.d.ts +0 -17
- package/dist/commands/install_new.js +0 -457
- package/dist/commands/install_v2.d.ts +0 -52
- package/dist/commands/install_v2.js +0 -505
- package/dist/commands/install_/327/2242.d.ts +0 -59
- package/dist/commands/install_/327/2242.js +0 -546
- package/dist/commands/workspaces/discovery.d.ts +0 -7
- package/dist/commands/workspaces/discovery.js +0 -50
- package/dist/commands/workspaces/workspaces-install.d.ts +0 -9
- package/dist/commands/workspaces/workspaces-install.js +0 -48
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -76
- package/dist/types/index.d.ts +0 -64
- package/dist/types/index.js +0 -2
- package/dist/utils/config_new.d.ts +0 -64
- package/dist/utils/config_new.js +0 -228
- package/dist/utils/config_v2.d.ts +0 -64
- package/dist/utils/config_v2.js +0 -250
- package/dist/utils/glob-handler.d.ts +0 -35
- package/dist/utils/glob-handler.js +0 -125
- package/dist/utils/mcp-writer.d.ts +0 -14
- package/dist/utils/mcp-writer.js +0 -69
- package/dist/utils/mdc-parser.d.ts +0 -9
- package/dist/utils/mdc-parser.js +0 -59
- package/dist/utils/rule-collector.d.ts +0 -33
- package/dist/utils/rule-collector.js +0 -169
- package/dist/utils/rule-detector.d.ts +0 -4
- package/dist/utils/rule-detector.js +0 -31
- package/dist/utils/rule-status.d.ts +0 -8
- package/dist/utils/rule-status.js +0 -53
- package/dist/utils/rule-writer.d.ts +0 -6
- package/dist/utils/rule-writer.js +0 -118
package/dist/utils/config_v2.js
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.SUPPORTED_TARGETS = void 0;
|
|
7
|
-
exports.applyDefaults = applyDefaults;
|
|
8
|
-
exports.validateConfig = validateConfig;
|
|
9
|
-
exports.loadRulesFromDirectory = loadRulesFromDirectory;
|
|
10
|
-
exports.resolvePresetPath = resolvePresetPath;
|
|
11
|
-
exports.loadPreset = loadPreset;
|
|
12
|
-
exports.loadAllRules = loadAllRules;
|
|
13
|
-
exports.applyOverrides = applyOverrides;
|
|
14
|
-
exports.loadConfigFile = loadConfigFile;
|
|
15
|
-
exports.loadConfig = loadConfig;
|
|
16
|
-
exports.saveConfig = saveConfig;
|
|
17
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
18
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
19
|
-
const cosmiconfig_1 = require("cosmiconfig");
|
|
20
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
21
|
-
exports.SUPPORTED_TARGETS = ["cursor", "windsurf", "codex"];
|
|
22
|
-
function applyDefaults(config) {
|
|
23
|
-
return {
|
|
24
|
-
rulesDir: config.rulesDir,
|
|
25
|
-
targets: config.targets || ["cursor"],
|
|
26
|
-
presets: config.presets || [],
|
|
27
|
-
overrides: config.overrides || {},
|
|
28
|
-
mcpServers: config.mcpServers || {},
|
|
29
|
-
workspaces: config.workspaces || false,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function validateConfig(config, configFilePath, cwd) {
|
|
33
|
-
if (typeof config !== "object" || config === null) {
|
|
34
|
-
throw new Error(`Config is not an object at ${configFilePath}`);
|
|
35
|
-
}
|
|
36
|
-
if (!("rulesDir" in config)) {
|
|
37
|
-
throw new Error(`rulesDir is not specified in config at ${configFilePath}`);
|
|
38
|
-
}
|
|
39
|
-
if (typeof config.rulesDir !== "string") {
|
|
40
|
-
throw new Error(`rulesDir is not a string in config at ${configFilePath}`);
|
|
41
|
-
}
|
|
42
|
-
const rulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
|
|
43
|
-
if (!fs_extra_1.default.existsSync(rulesPath)) {
|
|
44
|
-
throw new Error(`Rules directory does not exist: ${rulesPath}`);
|
|
45
|
-
}
|
|
46
|
-
if (!fs_extra_1.default.statSync(rulesPath).isDirectory()) {
|
|
47
|
-
throw new Error(`Rules path is not a directory: ${rulesPath}`);
|
|
48
|
-
}
|
|
49
|
-
if ("targets" in config) {
|
|
50
|
-
if (!Array.isArray(config.targets)) {
|
|
51
|
-
throw new Error(`targets must be an array in config at ${configFilePath}`);
|
|
52
|
-
}
|
|
53
|
-
if (config.targets.length === 0) {
|
|
54
|
-
throw new Error(`targets must not be empty in config at ${configFilePath}`);
|
|
55
|
-
}
|
|
56
|
-
for (const target of config.targets) {
|
|
57
|
-
if (!exports.SUPPORTED_TARGETS.includes(target)) {
|
|
58
|
-
throw new Error(`Unsupported target: ${target}. Supported targets: ${exports.SUPPORTED_TARGETS.join(", ")}`);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// Validate override rule names will be checked after rule resolution
|
|
63
|
-
}
|
|
64
|
-
async function loadRulesFromDirectory(rulesDir, source, presetName) {
|
|
65
|
-
const rules = [];
|
|
66
|
-
if (!fs_extra_1.default.existsSync(rulesDir)) {
|
|
67
|
-
return rules;
|
|
68
|
-
}
|
|
69
|
-
const pattern = node_path_1.default.join(rulesDir, "**/*.mdc").replace(/\\/g, "/");
|
|
70
|
-
const filePaths = await (0, fast_glob_1.default)(pattern, {
|
|
71
|
-
onlyFiles: true,
|
|
72
|
-
absolute: true,
|
|
73
|
-
});
|
|
74
|
-
for (const filePath of filePaths) {
|
|
75
|
-
const content = await fs_extra_1.default.readFile(filePath, "utf8");
|
|
76
|
-
// Preserve directory structure by using relative path from rulesDir
|
|
77
|
-
const relativePath = node_path_1.default.relative(rulesDir, filePath);
|
|
78
|
-
const ruleName = relativePath.replace(/\.mdc$/, "").replace(/\\/g, "/");
|
|
79
|
-
rules.push({
|
|
80
|
-
name: ruleName,
|
|
81
|
-
content,
|
|
82
|
-
sourcePath: filePath,
|
|
83
|
-
source,
|
|
84
|
-
presetName,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return rules;
|
|
88
|
-
}
|
|
89
|
-
function resolvePresetPath(presetPath, cwd) {
|
|
90
|
-
// Support specifying aicm.json directory and load the config from it
|
|
91
|
-
if (!presetPath.endsWith(".json")) {
|
|
92
|
-
presetPath = node_path_1.default.join(presetPath, "aicm.json");
|
|
93
|
-
}
|
|
94
|
-
// Support local or absolute paths
|
|
95
|
-
const absolutePath = node_path_1.default.isAbsolute(presetPath)
|
|
96
|
-
? presetPath
|
|
97
|
-
: node_path_1.default.resolve(cwd, presetPath);
|
|
98
|
-
if (fs_extra_1.default.existsSync(absolutePath)) {
|
|
99
|
-
return absolutePath;
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
// Support npm packages
|
|
103
|
-
const resolvedPath = require.resolve(presetPath, {
|
|
104
|
-
paths: [cwd, __dirname],
|
|
105
|
-
});
|
|
106
|
-
return fs_extra_1.default.existsSync(resolvedPath) ? resolvedPath : null;
|
|
107
|
-
}
|
|
108
|
-
catch (_a) {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
async function loadPreset(presetPath, cwd) {
|
|
113
|
-
const resolvedPresetPath = resolvePresetPath(presetPath, cwd);
|
|
114
|
-
if (!resolvedPresetPath) {
|
|
115
|
-
throw new Error(`Preset not found: "${presetPath}". Make sure the package is installed or the path is correct.`);
|
|
116
|
-
}
|
|
117
|
-
let presetConfig;
|
|
118
|
-
try {
|
|
119
|
-
const content = await fs_extra_1.default.readFile(resolvedPresetPath, "utf8");
|
|
120
|
-
presetConfig = JSON.parse(content);
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
throw new Error(`Failed to load preset "${presetPath}": ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
124
|
-
}
|
|
125
|
-
// Resolve preset's rules directory relative to the preset file
|
|
126
|
-
const presetDir = node_path_1.default.dirname(resolvedPresetPath);
|
|
127
|
-
const presetRulesDir = node_path_1.default.resolve(presetDir, presetConfig.rulesDir);
|
|
128
|
-
return {
|
|
129
|
-
config: presetConfig,
|
|
130
|
-
rulesDir: presetRulesDir,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
async function loadAllRules(config, cwd) {
|
|
134
|
-
const allRules = [];
|
|
135
|
-
let mergedMcpServers = { ...config.mcpServers };
|
|
136
|
-
// Load local rules
|
|
137
|
-
const localRulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
|
|
138
|
-
const localRules = await loadRulesFromDirectory(localRulesPath, "local");
|
|
139
|
-
allRules.push(...localRules);
|
|
140
|
-
if (config.presets) {
|
|
141
|
-
for (const presetPath of config.presets) {
|
|
142
|
-
const preset = await loadPreset(presetPath, cwd);
|
|
143
|
-
const presetRules = await loadRulesFromDirectory(preset.rulesDir, "preset", presetPath);
|
|
144
|
-
allRules.push(...presetRules);
|
|
145
|
-
// Merge MCP servers from preset
|
|
146
|
-
if (preset.config.mcpServers) {
|
|
147
|
-
mergedMcpServers = mergePresetMcpServers(mergedMcpServers, preset.config.mcpServers);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return {
|
|
152
|
-
rules: allRules,
|
|
153
|
-
mcpServers: mergedMcpServers,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
function applyOverrides(rules, overrides, cwd) {
|
|
157
|
-
// Validate that all override rule names exist in the resolved rules
|
|
158
|
-
for (const ruleName of Object.keys(overrides)) {
|
|
159
|
-
// TODO: support better error messages with edit distance, helping the user in case of a typo
|
|
160
|
-
// TODO: or shows a list of potential rules to override
|
|
161
|
-
if (!rules.some((rule) => rule.name === ruleName)) {
|
|
162
|
-
throw new Error(`Override rule "${ruleName}" does not exist in resolved rules`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const ruleMap = new Map();
|
|
166
|
-
for (const rule of rules) {
|
|
167
|
-
ruleMap.set(rule.name, rule);
|
|
168
|
-
}
|
|
169
|
-
for (const [ruleName, override] of Object.entries(overrides)) {
|
|
170
|
-
if (override === false) {
|
|
171
|
-
ruleMap.delete(ruleName);
|
|
172
|
-
}
|
|
173
|
-
else if (typeof override === "string") {
|
|
174
|
-
const overridePath = node_path_1.default.resolve(cwd, override);
|
|
175
|
-
if (!fs_extra_1.default.existsSync(overridePath)) {
|
|
176
|
-
throw new Error(`Override rule file not found: ${override} in ${cwd}`);
|
|
177
|
-
}
|
|
178
|
-
const content = fs_extra_1.default.readFileSync(overridePath, "utf8");
|
|
179
|
-
ruleMap.set(ruleName, {
|
|
180
|
-
name: ruleName,
|
|
181
|
-
content,
|
|
182
|
-
sourcePath: overridePath,
|
|
183
|
-
source: "local",
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return Array.from(ruleMap.values());
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Merge preset MCP servers with local config MCP servers
|
|
191
|
-
* Local config takes precedence over preset config
|
|
192
|
-
*/
|
|
193
|
-
function mergePresetMcpServers(configMcpServers, presetMcpServers) {
|
|
194
|
-
const newMcpServers = { ...configMcpServers };
|
|
195
|
-
for (const [serverName, serverConfig] of Object.entries(presetMcpServers)) {
|
|
196
|
-
// Cancel if set to false in config
|
|
197
|
-
if (Object.prototype.hasOwnProperty.call(newMcpServers, serverName) &&
|
|
198
|
-
newMcpServers[serverName] === false) {
|
|
199
|
-
delete newMcpServers[serverName];
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
// Only add if not already defined in config (override handled by config)
|
|
203
|
-
if (!Object.prototype.hasOwnProperty.call(newMcpServers, serverName)) {
|
|
204
|
-
newMcpServers[serverName] = serverConfig;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return newMcpServers;
|
|
208
|
-
}
|
|
209
|
-
async function loadConfigFile(searchFrom) {
|
|
210
|
-
const explorer = (0, cosmiconfig_1.cosmiconfig)("aicm", {
|
|
211
|
-
searchPlaces: ["aicm.json", "package.json"],
|
|
212
|
-
});
|
|
213
|
-
try {
|
|
214
|
-
const result = await explorer.search(searchFrom);
|
|
215
|
-
return result;
|
|
216
|
-
}
|
|
217
|
-
catch (error) {
|
|
218
|
-
throw new Error(`Failed to load configuration: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
async function loadConfig(cwd) {
|
|
222
|
-
const workingDir = cwd || process.cwd();
|
|
223
|
-
const configResult = await loadConfigFile(workingDir);
|
|
224
|
-
if (!(configResult === null || configResult === void 0 ? void 0 : configResult.config)) {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
validateConfig(configResult.config, configResult.filepath, workingDir);
|
|
228
|
-
const config = applyDefaults(configResult.config);
|
|
229
|
-
const { rules, mcpServers } = await loadAllRules(config, workingDir);
|
|
230
|
-
let rulesWithOverrides = rules;
|
|
231
|
-
if (config.overrides) {
|
|
232
|
-
rulesWithOverrides = applyOverrides(rules, config.overrides, workingDir);
|
|
233
|
-
}
|
|
234
|
-
return {
|
|
235
|
-
config,
|
|
236
|
-
rules: rulesWithOverrides,
|
|
237
|
-
mcpServers,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
function saveConfig(config, cwd) {
|
|
241
|
-
const workingDir = cwd || process.cwd();
|
|
242
|
-
const configPath = node_path_1.default.join(workingDir, "aicm.json");
|
|
243
|
-
try {
|
|
244
|
-
fs_extra_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
catch (_a) {
|
|
248
|
-
return false;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Check if a rule source string contains glob patterns
|
|
3
|
-
*/
|
|
4
|
-
export declare function isGlobPattern(source: string): boolean;
|
|
5
|
-
/**
|
|
6
|
-
* Expand a glob pattern to matching .mdc files
|
|
7
|
-
* @param pattern The glob pattern to expand
|
|
8
|
-
* @param basePath The base path to resolve relative patterns from
|
|
9
|
-
* @returns Array of file paths that match the pattern
|
|
10
|
-
*/
|
|
11
|
-
export declare function expandGlobPattern(pattern: string, basePath?: string): Promise<string[]>;
|
|
12
|
-
/**
|
|
13
|
-
* Generate a rule key from a file path and base key
|
|
14
|
-
* @param filePath The discovered file path
|
|
15
|
-
* @param baseKey The base key from the object notation
|
|
16
|
-
* @param patternBase The base directory of the glob pattern
|
|
17
|
-
* @returns Generated rule key with namespace
|
|
18
|
-
*/
|
|
19
|
-
export declare function generateGlobRuleKey(filePath: string, baseKey: string, patternBase: string): string;
|
|
20
|
-
/**
|
|
21
|
-
* Get the base directory from a glob pattern
|
|
22
|
-
* @param pattern The glob pattern
|
|
23
|
-
* @returns The base directory path without glob characters
|
|
24
|
-
*/
|
|
25
|
-
export declare function getGlobBase(pattern: string): string;
|
|
26
|
-
/**
|
|
27
|
-
* Expand glob patterns in rules object and return normalized rules
|
|
28
|
-
* @param rules The rules object that may contain glob patterns
|
|
29
|
-
* @param basePath The base path to resolve relative patterns from
|
|
30
|
-
* @returns Object with expanded rules and metadata about sources
|
|
31
|
-
*/
|
|
32
|
-
export declare function expandRulesGlobPatterns(rules: Record<string, string | false>, basePath?: string): Promise<{
|
|
33
|
-
expandedRules: Record<string, string>;
|
|
34
|
-
globSources: Record<string, string>;
|
|
35
|
-
}>;
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.isGlobPattern = isGlobPattern;
|
|
7
|
-
exports.expandGlobPattern = expandGlobPattern;
|
|
8
|
-
exports.generateGlobRuleKey = generateGlobRuleKey;
|
|
9
|
-
exports.getGlobBase = getGlobBase;
|
|
10
|
-
exports.expandRulesGlobPatterns = expandRulesGlobPatterns;
|
|
11
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
-
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
13
|
-
/**
|
|
14
|
-
* Check if a rule source string contains glob patterns
|
|
15
|
-
*/
|
|
16
|
-
function isGlobPattern(source) {
|
|
17
|
-
return /[*?{}[\]]/.test(source);
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Expand a glob pattern to matching .mdc files
|
|
21
|
-
* @param pattern The glob pattern to expand
|
|
22
|
-
* @param basePath The base path to resolve relative patterns from
|
|
23
|
-
* @returns Array of file paths that match the pattern
|
|
24
|
-
*/
|
|
25
|
-
async function expandGlobPattern(pattern, basePath) {
|
|
26
|
-
// Normalize the pattern to use forward slashes for consistent behavior
|
|
27
|
-
const normalizedPattern = pattern.replace(/\\/g, "/");
|
|
28
|
-
try {
|
|
29
|
-
const matches = await (0, fast_glob_1.default)(normalizedPattern, {
|
|
30
|
-
ignore: ["**/.*"], // Ignore hidden files
|
|
31
|
-
absolute: false,
|
|
32
|
-
onlyFiles: true,
|
|
33
|
-
// Set the working directory if basePath is provided
|
|
34
|
-
cwd: basePath,
|
|
35
|
-
});
|
|
36
|
-
// Filter to only .mdc files, normalize paths, and sort for deterministic behavior
|
|
37
|
-
return matches
|
|
38
|
-
.filter((file) => file.endsWith(".mdc"))
|
|
39
|
-
.map((file) => file.replace(/\\/g, "/")) // Normalize Windows backslashes to forward slashes
|
|
40
|
-
.sort((a, b) => a.localeCompare(b));
|
|
41
|
-
}
|
|
42
|
-
catch (error) {
|
|
43
|
-
throw new Error(`Error expanding glob pattern "${pattern}": ${error instanceof Error ? error.message : String(error)}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Generate a rule key from a file path and base key
|
|
48
|
-
* @param filePath The discovered file path
|
|
49
|
-
* @param baseKey The base key from the object notation
|
|
50
|
-
* @param patternBase The base directory of the glob pattern
|
|
51
|
-
* @returns Generated rule key with namespace
|
|
52
|
-
*/
|
|
53
|
-
function generateGlobRuleKey(filePath, baseKey, patternBase) {
|
|
54
|
-
// Normalize paths to use forward slashes for consistent behavior
|
|
55
|
-
const normalizedFilePath = filePath.replace(/\\/g, "/");
|
|
56
|
-
const normalizedPatternBase = patternBase.replace(/\\/g, "/");
|
|
57
|
-
// Get the relative path from the pattern base to the file
|
|
58
|
-
const relativePath = node_path_1.default.posix.relative(normalizedPatternBase, normalizedFilePath);
|
|
59
|
-
// Remove .mdc extension
|
|
60
|
-
const withoutExtension = relativePath.replace(/\.mdc$/, "");
|
|
61
|
-
// Return the combined key
|
|
62
|
-
return `${baseKey}/${withoutExtension}`;
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Get the base directory from a glob pattern
|
|
66
|
-
* @param pattern The glob pattern
|
|
67
|
-
* @returns The base directory path without glob characters
|
|
68
|
-
*/
|
|
69
|
-
function getGlobBase(pattern) {
|
|
70
|
-
// Normalize path separators to forward slashes for consistent behavior
|
|
71
|
-
const normalizedPattern = pattern.replace(/\\/g, "/");
|
|
72
|
-
// Find the first occurrence of glob characters
|
|
73
|
-
const globIndex = normalizedPattern.search(/[*?{}[\]]/);
|
|
74
|
-
if (globIndex === -1) {
|
|
75
|
-
// No glob characters, return the directory
|
|
76
|
-
return node_path_1.default.dirname(normalizedPattern);
|
|
77
|
-
}
|
|
78
|
-
// Get the path up to the first glob character
|
|
79
|
-
const basePath = normalizedPattern.substring(0, globIndex);
|
|
80
|
-
// Find the last path separator before the glob
|
|
81
|
-
const lastSeparator = basePath.lastIndexOf("/");
|
|
82
|
-
if (lastSeparator === -1) {
|
|
83
|
-
return ".";
|
|
84
|
-
}
|
|
85
|
-
return basePath.substring(0, lastSeparator);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Expand glob patterns in rules object and return normalized rules
|
|
89
|
-
* @param rules The rules object that may contain glob patterns
|
|
90
|
-
* @param basePath The base path to resolve relative patterns from
|
|
91
|
-
* @returns Object with expanded rules and metadata about sources
|
|
92
|
-
*/
|
|
93
|
-
async function expandRulesGlobPatterns(rules, basePath) {
|
|
94
|
-
const expandedRules = {};
|
|
95
|
-
const globSources = {};
|
|
96
|
-
for (const [key, source] of Object.entries(rules)) {
|
|
97
|
-
if (source === false) {
|
|
98
|
-
continue; // Skip canceled rules
|
|
99
|
-
}
|
|
100
|
-
if (isGlobPattern(source)) {
|
|
101
|
-
// Expand glob pattern
|
|
102
|
-
try {
|
|
103
|
-
const matchedFiles = await expandGlobPattern(source, basePath);
|
|
104
|
-
if (matchedFiles.length === 0) {
|
|
105
|
-
console.warn(`Warning: Glob pattern "${source}" matched no files`);
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
const patternBase = getGlobBase(source);
|
|
109
|
-
for (const filePath of matchedFiles) {
|
|
110
|
-
const generatedKey = generateGlobRuleKey(filePath, key, patternBase);
|
|
111
|
-
expandedRules[generatedKey] = filePath;
|
|
112
|
-
globSources[generatedKey] = source;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
throw new Error(`Error processing glob pattern for key "${key}": ${error instanceof Error ? error.message : String(error)}`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
// Regular file path
|
|
121
|
-
expandedRules[key] = source;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return { expandedRules, globSources };
|
|
125
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { NormalizedConfig } from "../types";
|
|
2
|
-
/**
|
|
3
|
-
* Write MCP servers configuration to IDE targets
|
|
4
|
-
* @param mcpServers The MCP servers configuration
|
|
5
|
-
* @param ides The IDEs to write to
|
|
6
|
-
* @param cwd The current working directory
|
|
7
|
-
*/
|
|
8
|
-
export declare function writeMcpServersToTargets(mcpServers: NormalizedConfig["mcpServers"], ides: string[], cwd: string): void;
|
|
9
|
-
/**
|
|
10
|
-
* Write MCP servers configuration to a specific file
|
|
11
|
-
* @param mcpServers The MCP servers configuration
|
|
12
|
-
* @param mcpPath The path to the mcp.json file
|
|
13
|
-
*/
|
|
14
|
-
export declare function writeMcpServersToFile(mcpServers: NormalizedConfig["mcpServers"], mcpPath: string): void;
|
package/dist/utils/mcp-writer.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.writeMcpServersToTargets = writeMcpServersToTargets;
|
|
7
|
-
exports.writeMcpServersToFile = writeMcpServersToFile;
|
|
8
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
-
/**
|
|
11
|
-
* Write MCP servers configuration to IDE targets
|
|
12
|
-
* @param mcpServers The MCP servers configuration
|
|
13
|
-
* @param ides The IDEs to write to
|
|
14
|
-
* @param cwd The current working directory
|
|
15
|
-
*/
|
|
16
|
-
function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
17
|
-
if (!mcpServers)
|
|
18
|
-
return;
|
|
19
|
-
for (const ide of ides) {
|
|
20
|
-
if (ide === "cursor") {
|
|
21
|
-
const mcpPath = node_path_1.default.join(cwd, ".cursor", "mcp.json");
|
|
22
|
-
writeMcpServersToFile(mcpServers, mcpPath);
|
|
23
|
-
}
|
|
24
|
-
// Windsurf does not support project mcpServers, so skip
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Write MCP servers configuration to a specific file
|
|
29
|
-
* @param mcpServers The MCP servers configuration
|
|
30
|
-
* @param mcpPath The path to the mcp.json file
|
|
31
|
-
*/
|
|
32
|
-
function writeMcpServersToFile(mcpServers, mcpPath) {
|
|
33
|
-
var _a;
|
|
34
|
-
if (!mcpServers)
|
|
35
|
-
return;
|
|
36
|
-
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(mcpPath));
|
|
37
|
-
const existingConfig = fs_extra_1.default.existsSync(mcpPath)
|
|
38
|
-
? fs_extra_1.default.readJsonSync(mcpPath)
|
|
39
|
-
: {};
|
|
40
|
-
const existingMcpServers = (_a = existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.mcpServers) !== null && _a !== void 0 ? _a : {};
|
|
41
|
-
// Filter out any existing aicm-managed servers (with aicm: true)
|
|
42
|
-
// This removes stale aicm servers that are no longer in the configuration
|
|
43
|
-
const userMcpServers = {};
|
|
44
|
-
for (const [key, value] of Object.entries(existingMcpServers)) {
|
|
45
|
-
if (typeof value === "object" && value !== null && value.aicm !== true) {
|
|
46
|
-
userMcpServers[key] = value;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// Mark new aicm servers as managed and filter out canceled servers
|
|
50
|
-
const aicmMcpServers = {};
|
|
51
|
-
for (const [key, value] of Object.entries(mcpServers)) {
|
|
52
|
-
if (value !== false) {
|
|
53
|
-
aicmMcpServers[key] = {
|
|
54
|
-
...value,
|
|
55
|
-
aicm: true,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// Merge user servers with aicm servers (aicm servers override user servers with same key)
|
|
60
|
-
const mergedMcpServers = {
|
|
61
|
-
...userMcpServers,
|
|
62
|
-
...aicmMcpServers,
|
|
63
|
-
};
|
|
64
|
-
const mergedConfig = {
|
|
65
|
-
...existingConfig,
|
|
66
|
-
mcpServers: mergedMcpServers,
|
|
67
|
-
};
|
|
68
|
-
fs_extra_1.default.writeJsonSync(mcpPath, mergedConfig, { spaces: 2 });
|
|
69
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse an MDC file and extract its content
|
|
3
|
-
* MDC files are Markdown files with metadata
|
|
4
|
-
* https://docs.cursor.com/context/rules
|
|
5
|
-
*/
|
|
6
|
-
export declare function parseMdcFile(filePath: string): {
|
|
7
|
-
metadata: Record<string, boolean | string | string[]>;
|
|
8
|
-
content: string;
|
|
9
|
-
};
|
package/dist/utils/mdc-parser.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.parseMdcFile = parseMdcFile;
|
|
7
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
-
/**
|
|
9
|
-
* Parse an MDC file and extract its content
|
|
10
|
-
* MDC files are Markdown files with metadata
|
|
11
|
-
* https://docs.cursor.com/context/rules
|
|
12
|
-
*/
|
|
13
|
-
function parseMdcFile(filePath) {
|
|
14
|
-
const fileContent = fs_extra_1.default.readFileSync(filePath, "utf8");
|
|
15
|
-
if (!fileContent.startsWith("---")) {
|
|
16
|
-
return {
|
|
17
|
-
metadata: {},
|
|
18
|
-
content: fileContent,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
const endOfMetadata = fileContent.indexOf("---", 3);
|
|
22
|
-
if (endOfMetadata === -1) {
|
|
23
|
-
return {
|
|
24
|
-
metadata: {},
|
|
25
|
-
content: fileContent,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const metadataStr = fileContent.substring(3, endOfMetadata).trim();
|
|
29
|
-
const content = fileContent.substring(endOfMetadata + 3).trim();
|
|
30
|
-
const metadata = {};
|
|
31
|
-
metadataStr.split("\n").forEach((line) => {
|
|
32
|
-
const colonIndex = line.indexOf(":");
|
|
33
|
-
if (colonIndex !== -1) {
|
|
34
|
-
const key = line.substring(0, colonIndex).trim();
|
|
35
|
-
const valueStr = line.substring(colonIndex + 1).trim();
|
|
36
|
-
// Handle different value types
|
|
37
|
-
let value = "";
|
|
38
|
-
if (valueStr === "true") {
|
|
39
|
-
value = true;
|
|
40
|
-
}
|
|
41
|
-
else if (valueStr === "false") {
|
|
42
|
-
value = false;
|
|
43
|
-
}
|
|
44
|
-
else if (valueStr.startsWith('"') && valueStr.endsWith('"')) {
|
|
45
|
-
// Remove quotes from string values
|
|
46
|
-
value = valueStr.substring(1, valueStr.length - 1);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
// Default to using the string value as is
|
|
50
|
-
value = valueStr;
|
|
51
|
-
}
|
|
52
|
-
metadata[key] = value;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
return {
|
|
56
|
-
metadata,
|
|
57
|
-
content,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { RuleCollection, RuleContent } from "../types";
|
|
2
|
-
/**
|
|
3
|
-
* Find the root directory of a package by name
|
|
4
|
-
* @param packageName The name of the package
|
|
5
|
-
* @returns The absolute path to the package's root directory
|
|
6
|
-
*/
|
|
7
|
-
export declare function findPackageRoot(packageName: string): string;
|
|
8
|
-
/**
|
|
9
|
-
* Initialize an empty rule collection
|
|
10
|
-
*/
|
|
11
|
-
export declare function initRuleCollection(): RuleCollection;
|
|
12
|
-
/**
|
|
13
|
-
* Add a rule to the collection
|
|
14
|
-
* @param collection The rule collection to add to
|
|
15
|
-
* @param rule The rule content to add
|
|
16
|
-
* @param ides The IDEs to add the rule for
|
|
17
|
-
*/
|
|
18
|
-
export declare function addRuleToCollection(collection: RuleCollection, rule: RuleContent, ides: string[]): void;
|
|
19
|
-
/**
|
|
20
|
-
* Collect a rule from a local file source
|
|
21
|
-
* @param ruleName The name of the rule
|
|
22
|
-
* @param source The source path (relative or absolute)
|
|
23
|
-
* @param ruleBasePath Optional base path for resolving relative paths
|
|
24
|
-
* @returns The rule content
|
|
25
|
-
*/
|
|
26
|
-
export declare function collectLocalRule(ruleName: string, source: string | false, ruleBasePath?: string): RuleContent;
|
|
27
|
-
/**
|
|
28
|
-
* Collect a rule from an npm package
|
|
29
|
-
* @param ruleName The name of the rule
|
|
30
|
-
* @param source The npm package source (can include path)
|
|
31
|
-
* @returns The rule content
|
|
32
|
-
*/
|
|
33
|
-
export declare function collectNpmRule(ruleName: string, source: string | false): RuleContent;
|