aicm 0.7.0 → 0.9.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 +9 -2
- package/dist/api.d.ts +1 -1
- package/dist/api.js +1 -1
- package/dist/commands/init.js +1 -0
- package/dist/commands/install.d.ts +5 -1
- package/dist/commands/install.js +34 -2
- package/dist/index.js +3 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/utils/config.d.ts +10 -1
- package/dist/utils/config.js +24 -10
- package/dist/utils/rule-writer.js +53 -3
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -37,12 +37,12 @@ In your project's `aicm.json`, reference the package and the specific rule:
|
|
|
37
37
|
}
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
2. **Add a
|
|
40
|
+
2. **Add a prepare script** to your `package.json`:
|
|
41
41
|
|
|
42
42
|
```json
|
|
43
43
|
{
|
|
44
44
|
"scripts": {
|
|
45
|
-
"
|
|
45
|
+
"prepare": "npx -y aicm install"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
```
|
|
@@ -192,6 +192,8 @@ Example `aicm.json`:
|
|
|
192
192
|
|
|
193
193
|
- Preset files should contain a `rules` and `mcpServers` objects with the same structure as the main configuration.
|
|
194
194
|
|
|
195
|
+
- **installOnCI**: Boolean flag (default: `false`) that controls whether installation should proceed in CI environments. When set to `true`, rules will be installed even in CI environments.
|
|
196
|
+
|
|
195
197
|
### MCP Server Installation
|
|
196
198
|
|
|
197
199
|
- **Cursor**: MCP server configs are written to `.cursor/mcp.json` (see Cursor docs for latest path).
|
|
@@ -247,6 +249,10 @@ Installs all rules and MCPs configured in your `aicm.json`.
|
|
|
247
249
|
npx aicm install
|
|
248
250
|
```
|
|
249
251
|
|
|
252
|
+
Options:
|
|
253
|
+
|
|
254
|
+
- `--ci`: run in CI environments (default: `false`)
|
|
255
|
+
|
|
250
256
|
## Node.js API
|
|
251
257
|
|
|
252
258
|
In addition to the CLI, aicm can be used programmatically in Node.js applications:
|
|
@@ -289,6 +295,7 @@ Installs rules and MCP servers based on configuration.
|
|
|
289
295
|
|
|
290
296
|
- `cwd`: Base directory to use instead of `process.cwd()`
|
|
291
297
|
- `config`: Custom config object to use instead of loading from file
|
|
298
|
+
- `installOnCI`: Run installation on CI environments (default: `false`)
|
|
292
299
|
|
|
293
300
|
**Returns:**
|
|
294
301
|
|
package/dist/api.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { InstallOptions, InstallResult } from "./commands/install";
|
|
2
2
|
/**
|
|
3
3
|
* Install AICM rules based on configuration
|
|
4
|
-
* @param options
|
|
4
|
+
* @param options Installation options
|
|
5
5
|
* @returns Result of the install operation
|
|
6
6
|
*/
|
|
7
7
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
package/dist/api.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.install = install;
|
|
|
4
4
|
const install_1 = require("./commands/install");
|
|
5
5
|
/**
|
|
6
6
|
* Install AICM rules based on configuration
|
|
7
|
-
* @param options
|
|
7
|
+
* @param options Installation options
|
|
8
8
|
* @returns Result of the install operation
|
|
9
9
|
*/
|
|
10
10
|
async function install(options = {}) {
|
package/dist/commands/init.js
CHANGED
|
@@ -11,6 +11,10 @@ export interface InstallOptions {
|
|
|
11
11
|
* Custom config object to use instead of loading from file
|
|
12
12
|
*/
|
|
13
13
|
config?: Config;
|
|
14
|
+
/**
|
|
15
|
+
* allow installation on CI environments
|
|
16
|
+
*/
|
|
17
|
+
installOnCI?: boolean;
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
20
|
* Result of the install operation
|
|
@@ -35,4 +39,4 @@ export interface InstallResult {
|
|
|
35
39
|
* @returns Result of the install operation
|
|
36
40
|
*/
|
|
37
41
|
export declare function install(options?: InstallOptions): Promise<InstallResult>;
|
|
38
|
-
export declare function installCommand(): Promise<void>;
|
|
42
|
+
export declare function installCommand(installOnCI?: boolean): Promise<void>;
|
package/dist/commands/install.js
CHANGED
|
@@ -12,6 +12,7 @@ const rule_collector_1 = require("../utils/rule-collector");
|
|
|
12
12
|
const rule_writer_1 = require("../utils/rule-writer");
|
|
13
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const ci_info_1 = require("ci-info");
|
|
15
16
|
/**
|
|
16
17
|
* Write MCP servers configuration to IDE targets
|
|
17
18
|
* @param mcpServers The MCP servers configuration
|
|
@@ -33,6 +34,19 @@ function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the current environment is a CI environment
|
|
39
|
+
* This function respects any explicit settings in process.env.CI
|
|
40
|
+
*/
|
|
41
|
+
function isInCIEnvironment() {
|
|
42
|
+
// Explicit environment variable settings take precedence
|
|
43
|
+
if (process.env.CI === "true")
|
|
44
|
+
return true;
|
|
45
|
+
if (process.env.CI === "false")
|
|
46
|
+
return false;
|
|
47
|
+
// Fall back to ci-info's detection
|
|
48
|
+
return ci_info_1.isCI;
|
|
49
|
+
}
|
|
36
50
|
/**
|
|
37
51
|
* Core implementation of the rule installation logic
|
|
38
52
|
* @param options Install options
|
|
@@ -40,6 +54,7 @@ function writeMcpServersToTargets(mcpServers, ides, cwd) {
|
|
|
40
54
|
*/
|
|
41
55
|
async function install(options = {}) {
|
|
42
56
|
const cwd = options.cwd || process.cwd();
|
|
57
|
+
const installOnCI = options.installOnCI === true; // Default to false if not specified
|
|
43
58
|
try {
|
|
44
59
|
const originalCwd = process.cwd();
|
|
45
60
|
if (cwd !== originalCwd) {
|
|
@@ -57,6 +72,17 @@ async function install(options = {}) {
|
|
|
57
72
|
installedRuleCount: 0,
|
|
58
73
|
};
|
|
59
74
|
}
|
|
75
|
+
const inCI = isInCIEnvironment();
|
|
76
|
+
if (inCI && !installOnCI && !config.installOnCI) {
|
|
77
|
+
if (cwd !== originalCwd) {
|
|
78
|
+
process.chdir(originalCwd);
|
|
79
|
+
}
|
|
80
|
+
console.log(chalk_1.default.yellow("Detected CI environment, skipping install."));
|
|
81
|
+
return {
|
|
82
|
+
success: true,
|
|
83
|
+
installedRuleCount: 0,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
60
86
|
// Check if rules are defined (either directly or through presets)
|
|
61
87
|
if (!config.rules || Object.keys(config.rules).length === 0) {
|
|
62
88
|
// If there are no presets defined either, show a message
|
|
@@ -82,6 +108,8 @@ async function install(options = {}) {
|
|
|
82
108
|
const ruleType = (0, rule_detector_1.detectRuleType)(source);
|
|
83
109
|
// Get the base path of the preset file if this rule came from a preset
|
|
84
110
|
const ruleBasePath = (0, config_1.getRuleSource)(config, name);
|
|
111
|
+
// Get the original preset path for namespacing
|
|
112
|
+
const originalPresetPath = (0, config_1.getOriginalPresetPath)(config, name);
|
|
85
113
|
// Collect the rule based on its type
|
|
86
114
|
try {
|
|
87
115
|
let ruleContent;
|
|
@@ -96,6 +124,10 @@ async function install(options = {}) {
|
|
|
96
124
|
errorMessages.push(`Unknown rule type: ${ruleType}`);
|
|
97
125
|
continue;
|
|
98
126
|
}
|
|
127
|
+
// Add the preset path to the rule content for namespacing
|
|
128
|
+
if (originalPresetPath) {
|
|
129
|
+
ruleContent.presetPath = originalPresetPath;
|
|
130
|
+
}
|
|
99
131
|
(0, rule_collector_1.addRuleToCollection)(ruleCollection, ruleContent, config.ides);
|
|
100
132
|
installedRuleCount++;
|
|
101
133
|
}
|
|
@@ -146,9 +178,9 @@ async function install(options = {}) {
|
|
|
146
178
|
};
|
|
147
179
|
}
|
|
148
180
|
}
|
|
149
|
-
async function installCommand() {
|
|
181
|
+
async function installCommand(installOnCI) {
|
|
150
182
|
try {
|
|
151
|
-
const result = await install();
|
|
183
|
+
const result = await install({ installOnCI });
|
|
152
184
|
if (!result.success) {
|
|
153
185
|
console.error(chalk_1.default.red(result.error));
|
|
154
186
|
process.exit(1);
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const pkg = require("../package.json");
|
|
|
16
16
|
const args = (0, arg_1.default)({
|
|
17
17
|
"--help": Boolean,
|
|
18
18
|
"--version": Boolean,
|
|
19
|
+
"--ci": Boolean,
|
|
19
20
|
"-h": "--help",
|
|
20
21
|
"-v": "--version",
|
|
21
22
|
}, {
|
|
@@ -35,7 +36,7 @@ switch (command) {
|
|
|
35
36
|
(0, init_1.initCommand)();
|
|
36
37
|
break;
|
|
37
38
|
case "install":
|
|
38
|
-
(0, install_1.installCommand)();
|
|
39
|
+
(0, install_1.installCommand)(args["--ci"]);
|
|
39
40
|
break;
|
|
40
41
|
case "list":
|
|
41
42
|
(0, list_1.listCommand)();
|
|
@@ -60,6 +61,7 @@ ${chalk_1.default.bold("COMMANDS")}
|
|
|
60
61
|
${chalk_1.default.bold("OPTIONS")}
|
|
61
62
|
-h, --help Show this help message
|
|
62
63
|
-v, --version Show version number
|
|
64
|
+
--ci Run in CI environments (default: \`false\`)
|
|
63
65
|
|
|
64
66
|
${chalk_1.default.bold("EXAMPLES")}
|
|
65
67
|
$ aicm init
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export interface Config {
|
|
|
21
21
|
rules: Rules;
|
|
22
22
|
presets?: string[];
|
|
23
23
|
mcpServers?: MCPServers;
|
|
24
|
+
installOnCI?: boolean;
|
|
24
25
|
}
|
|
25
26
|
export interface RuleMetadata {
|
|
26
27
|
type?: string;
|
|
@@ -34,6 +35,7 @@ export interface RuleContent {
|
|
|
34
35
|
content: string;
|
|
35
36
|
metadata: RuleMetadata;
|
|
36
37
|
sourcePath: string;
|
|
38
|
+
presetPath?: string;
|
|
37
39
|
}
|
|
38
40
|
export interface RuleCollection {
|
|
39
41
|
cursor: RuleContent[];
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { Config, Rules } from "../types";
|
|
2
2
|
interface ConfigWithMeta extends Config {
|
|
3
3
|
__ruleSources?: Record<string, string>;
|
|
4
|
+
__originalPresetPaths?: Record<string, string>;
|
|
4
5
|
}
|
|
5
|
-
export
|
|
6
|
+
export interface PresetPathInfo {
|
|
7
|
+
fullPath: string;
|
|
8
|
+
originalPath: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function getFullPresetPath(presetPath: string): PresetPathInfo | null;
|
|
6
11
|
/**
|
|
7
12
|
* Load a preset file and return its rules and mcpServers
|
|
8
13
|
*/
|
|
@@ -23,6 +28,10 @@ export declare function getConfig(): Config | null;
|
|
|
23
28
|
* Get the source preset path for a rule if it came from a preset
|
|
24
29
|
*/
|
|
25
30
|
export declare function getRuleSource(config: Config, ruleName: string): string | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get the original preset path for a rule if it came from a preset
|
|
33
|
+
*/
|
|
34
|
+
export declare function getOriginalPresetPath(config: Config, ruleName: string): string | undefined;
|
|
26
35
|
/**
|
|
27
36
|
* Save the configuration to the aicm.json file
|
|
28
37
|
*/
|
package/dist/utils/config.js
CHANGED
|
@@ -8,6 +8,7 @@ exports.loadPreset = loadPreset;
|
|
|
8
8
|
exports.loadAicmConfigCosmiconfig = loadAicmConfigCosmiconfig;
|
|
9
9
|
exports.getConfig = getConfig;
|
|
10
10
|
exports.getRuleSource = getRuleSource;
|
|
11
|
+
exports.getOriginalPresetPath = getOriginalPresetPath;
|
|
11
12
|
exports.saveConfig = saveConfig;
|
|
12
13
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
13
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -15,7 +16,7 @@ const cosmiconfig_1 = require("cosmiconfig");
|
|
|
15
16
|
const CONFIG_FILE = "aicm.json";
|
|
16
17
|
function getFullPresetPath(presetPath) {
|
|
17
18
|
if (presetPath.endsWith(".json") && fs_extra_1.default.pathExistsSync(presetPath)) {
|
|
18
|
-
return presetPath;
|
|
19
|
+
return { fullPath: presetPath, originalPath: presetPath };
|
|
19
20
|
}
|
|
20
21
|
try {
|
|
21
22
|
let absolutePresetPath;
|
|
@@ -30,7 +31,9 @@ function getFullPresetPath(presetPath) {
|
|
|
30
31
|
paths: [__dirname, process.cwd()],
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
return fs_extra_1.default.existsSync(absolutePresetPath)
|
|
34
|
+
return fs_extra_1.default.existsSync(absolutePresetPath)
|
|
35
|
+
? { fullPath: absolutePresetPath, originalPath: presetPath }
|
|
36
|
+
: null;
|
|
34
37
|
}
|
|
35
38
|
catch (_a) {
|
|
36
39
|
return null;
|
|
@@ -40,11 +43,11 @@ function getFullPresetPath(presetPath) {
|
|
|
40
43
|
* Load a preset file and return its rules and mcpServers
|
|
41
44
|
*/
|
|
42
45
|
function loadPreset(presetPath) {
|
|
43
|
-
const
|
|
44
|
-
if (!
|
|
46
|
+
const pathInfo = getFullPresetPath(presetPath);
|
|
47
|
+
if (!pathInfo) {
|
|
45
48
|
throw new Error(`Error loading preset: "${presetPath}". Make sure the package is installed in your project.`);
|
|
46
49
|
}
|
|
47
|
-
const presetContent = fs_extra_1.default.readFileSync(
|
|
50
|
+
const presetContent = fs_extra_1.default.readFileSync(pathInfo.fullPath, "utf8");
|
|
48
51
|
let preset;
|
|
49
52
|
try {
|
|
50
53
|
preset = JSON.parse(presetContent);
|
|
@@ -69,10 +72,10 @@ function processPresets(config) {
|
|
|
69
72
|
const preset = loadPreset(presetPath);
|
|
70
73
|
if (!preset)
|
|
71
74
|
continue;
|
|
72
|
-
const
|
|
73
|
-
if (!
|
|
75
|
+
const pathInfo = getFullPresetPath(presetPath);
|
|
76
|
+
if (!pathInfo)
|
|
74
77
|
continue;
|
|
75
|
-
mergePresetRules(config, preset.rules,
|
|
78
|
+
mergePresetRules(config, preset.rules, pathInfo);
|
|
76
79
|
if (preset.mcpServers) {
|
|
77
80
|
mergePresetMcpServers(config, preset.mcpServers);
|
|
78
81
|
}
|
|
@@ -81,7 +84,7 @@ function processPresets(config) {
|
|
|
81
84
|
/**
|
|
82
85
|
* Merge preset rules into the config
|
|
83
86
|
*/
|
|
84
|
-
function mergePresetRules(config, presetRules,
|
|
87
|
+
function mergePresetRules(config, presetRules, pathInfo) {
|
|
85
88
|
for (const [ruleName, rulePath] of Object.entries(presetRules)) {
|
|
86
89
|
// Cancel if set to false in config
|
|
87
90
|
if (Object.prototype.hasOwnProperty.call(config.rules, ruleName) &&
|
|
@@ -89,13 +92,17 @@ function mergePresetRules(config, presetRules, presetPath) {
|
|
|
89
92
|
delete config.rules[ruleName];
|
|
90
93
|
if (config.__ruleSources)
|
|
91
94
|
delete config.__ruleSources[ruleName];
|
|
95
|
+
if (config.__originalPresetPaths)
|
|
96
|
+
delete config.__originalPresetPaths[ruleName];
|
|
92
97
|
continue;
|
|
93
98
|
}
|
|
94
99
|
// Only add if not already defined in config (override handled by config)
|
|
95
100
|
if (!Object.prototype.hasOwnProperty.call(config.rules, ruleName)) {
|
|
96
101
|
config.rules[ruleName] = rulePath;
|
|
97
102
|
config.__ruleSources = config.__ruleSources || {};
|
|
98
|
-
config.__ruleSources[ruleName] =
|
|
103
|
+
config.__ruleSources[ruleName] = pathInfo.fullPath;
|
|
104
|
+
config.__originalPresetPaths = config.__originalPresetPaths || {};
|
|
105
|
+
config.__originalPresetPaths[ruleName] = pathInfo.originalPath;
|
|
99
106
|
}
|
|
100
107
|
}
|
|
101
108
|
}
|
|
@@ -159,6 +166,13 @@ function getRuleSource(config, ruleName) {
|
|
|
159
166
|
var _a;
|
|
160
167
|
return (_a = config.__ruleSources) === null || _a === void 0 ? void 0 : _a[ruleName];
|
|
161
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* Get the original preset path for a rule if it came from a preset
|
|
171
|
+
*/
|
|
172
|
+
function getOriginalPresetPath(config, ruleName) {
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = config.__originalPresetPaths) === null || _a === void 0 ? void 0 : _a[ruleName];
|
|
175
|
+
}
|
|
162
176
|
/**
|
|
163
177
|
* Save the configuration to the aicm.json file
|
|
164
178
|
*/
|
|
@@ -23,6 +23,21 @@ function writeRulesToTargets(collection) {
|
|
|
23
23
|
writeWindsurfRulesFromCollection(collection.windsurf, idePaths.windsurf);
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Extract a normalized namespace from a preset path
|
|
28
|
+
* @param presetPath The original preset path
|
|
29
|
+
* @returns An array of path segments to use for namespacing
|
|
30
|
+
*/
|
|
31
|
+
function extractNamespaceFromPresetPath(presetPath) {
|
|
32
|
+
// Special case: npm package names always use forward slashes, regardless of platform
|
|
33
|
+
if (presetPath.startsWith("@")) {
|
|
34
|
+
// For scoped packages like @scope/package/subdir, create nested directories
|
|
35
|
+
return presetPath.split("/");
|
|
36
|
+
}
|
|
37
|
+
// Handle both Unix and Windows style path separators
|
|
38
|
+
const parts = presetPath.split(/[/\\]/);
|
|
39
|
+
return parts.filter((part) => part.length > 0); // Filter out empty segments
|
|
40
|
+
}
|
|
26
41
|
/**
|
|
27
42
|
* Write rules to Cursor's rules directory
|
|
28
43
|
* @param rules The rules to write
|
|
@@ -31,7 +46,20 @@ function writeRulesToTargets(collection) {
|
|
|
31
46
|
function writeCursorRules(rules, cursorRulesDir) {
|
|
32
47
|
fs_extra_1.default.emptyDirSync(cursorRulesDir);
|
|
33
48
|
for (const rule of rules) {
|
|
34
|
-
|
|
49
|
+
let rulePath;
|
|
50
|
+
// Parse rule name into path segments using platform-specific path separator
|
|
51
|
+
const ruleNameParts = rule.name.split(/[/\\]/).filter(Boolean);
|
|
52
|
+
if (rule.presetPath) {
|
|
53
|
+
// For rules from presets, create a namespaced directory structure
|
|
54
|
+
const namespace = extractNamespaceFromPresetPath(rule.presetPath);
|
|
55
|
+
// Path will be: cursorRulesDir/namespace/rule-name.mdc
|
|
56
|
+
rulePath = node_path_1.default.join(cursorRulesDir, ...namespace, ...ruleNameParts);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// For local rules, maintain the original flat structure
|
|
60
|
+
rulePath = node_path_1.default.join(cursorRulesDir, ...ruleNameParts);
|
|
61
|
+
}
|
|
62
|
+
const ruleFile = rulePath + ".mdc";
|
|
35
63
|
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(ruleFile));
|
|
36
64
|
if (fs_extra_1.default.existsSync(rule.sourcePath)) {
|
|
37
65
|
fs_extra_1.default.copyFileSync(rule.sourcePath, ruleFile);
|
|
@@ -49,11 +77,33 @@ function writeCursorRules(rules, cursorRulesDir) {
|
|
|
49
77
|
function writeWindsurfRulesFromCollection(rules, ruleDir) {
|
|
50
78
|
fs_extra_1.default.emptyDirSync(ruleDir);
|
|
51
79
|
const ruleFiles = rules.map((rule) => {
|
|
52
|
-
|
|
80
|
+
let rulePath;
|
|
81
|
+
// Parse rule name into path segments using platform-specific path separator
|
|
82
|
+
const ruleNameParts = rule.name.split(/[/\\]/).filter(Boolean);
|
|
83
|
+
if (rule.presetPath) {
|
|
84
|
+
// For rules from presets, create a namespaced directory structure
|
|
85
|
+
const namespace = extractNamespaceFromPresetPath(rule.presetPath);
|
|
86
|
+
// Path will be: ruleDir/namespace/rule-name.md
|
|
87
|
+
rulePath = node_path_1.default.join(ruleDir, ...namespace, ...ruleNameParts);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// For local rules, maintain the original flat structure
|
|
91
|
+
rulePath = node_path_1.default.join(ruleDir, ...ruleNameParts);
|
|
92
|
+
}
|
|
93
|
+
const physicalRulePath = rulePath + ".md";
|
|
53
94
|
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(physicalRulePath));
|
|
54
95
|
fs_extra_1.default.writeFileSync(physicalRulePath, rule.content);
|
|
55
96
|
const relativeRuleDir = node_path_1.default.basename(ruleDir); // Gets '.rules'
|
|
56
|
-
|
|
97
|
+
// For the Windsurf rules file, we need to maintain the same structure
|
|
98
|
+
let windsurfPath;
|
|
99
|
+
if (rule.presetPath) {
|
|
100
|
+
const namespace = extractNamespaceFromPresetPath(rule.presetPath);
|
|
101
|
+
windsurfPath =
|
|
102
|
+
node_path_1.default.join(relativeRuleDir, ...namespace, ...ruleNameParts) + ".md";
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
windsurfPath = node_path_1.default.join(relativeRuleDir, ...ruleNameParts) + ".md";
|
|
106
|
+
}
|
|
57
107
|
// Normalize to POSIX style for cross-platform compatibility in .windsurfrules
|
|
58
108
|
const windsurfPathPosix = windsurfPath.replace(/\\/g, "/");
|
|
59
109
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "A TypeScript CLI tool for managing AI IDE rules across different projects and teams",
|
|
5
5
|
"main": "dist/api.js",
|
|
6
6
|
"types": "dist/api.d.ts",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"arg": "^5.0.2",
|
|
42
42
|
"args": "^5.0.3",
|
|
43
43
|
"chalk": "^4.1.2",
|
|
44
|
+
"ci-info": "^4.2.0",
|
|
44
45
|
"cosmiconfig": "^9.0.0",
|
|
45
46
|
"fs-extra": "^11.1.1"
|
|
46
47
|
},
|