aicm 0.16.1 → 0.17.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 -0
- package/dist/commands/install.d.ts +4 -0
- package/dist/commands/install.js +77 -13
- package/dist/utils/config.d.ts +10 -0
- package/dist/utils/config.js +38 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,32 @@ For project-specific rules, you can specify `rulesDir` in your `aicm.json` confi
|
|
|
95
95
|
}
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
+
**Referencing Auxiliary Files**
|
|
99
|
+
|
|
100
|
+
You can place any file (e.g., `example.ts`, `schema.json`, `guide.md`) in your `rulesDir` alongside your `.mdc` files. These assets are automatically copied to the target location. You can reference them in your rules using relative paths, and aicm will automatically rewrite the links to point to the correct location for each target IDE.
|
|
101
|
+
|
|
102
|
+
Example `rules/my-rule.mdc`:
|
|
103
|
+
|
|
104
|
+
```markdown
|
|
105
|
+
# My Rule
|
|
106
|
+
|
|
107
|
+
See [Example](./example.ts) for details.
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Commands referencing files**
|
|
111
|
+
|
|
112
|
+
You can also use this feature to create commands that reference auxiliary files in your `rulesDir`. Since assets in `rulesDir` are copied to the target directory, your commands can link to them.
|
|
113
|
+
|
|
114
|
+
For example, if you have a schema file at `rules/schema.json` and a command at `commands/generate-schema.md`:
|
|
115
|
+
|
|
116
|
+
```markdown
|
|
117
|
+
# Generate Schema
|
|
118
|
+
|
|
119
|
+
Use the schema defined in [Schema Template](../rules/schema.json) to generate the response.
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
When installed, `aicm` will automatically rewrite the link to point to the correct location of `schema.json` in the target environment (e.g., `../../rules/aicm/schema.json` for Cursor).
|
|
123
|
+
|
|
98
124
|
### Using Commands
|
|
99
125
|
|
|
100
126
|
Cursor supports custom commands that can be invoked directly in the chat interface. aicm can manage these command files
|
package/dist/commands/install.js
CHANGED
|
@@ -18,9 +18,7 @@ function getTargetPaths() {
|
|
|
18
18
|
const projectDir = process.cwd();
|
|
19
19
|
return {
|
|
20
20
|
cursor: node_path_1.default.join(projectDir, ".cursor", "rules", "aicm"),
|
|
21
|
-
|
|
22
|
-
codex: node_path_1.default.join(projectDir, ".aicm"),
|
|
23
|
-
claude: node_path_1.default.join(projectDir, ".aicm"),
|
|
21
|
+
aicm: node_path_1.default.join(projectDir, ".aicm"),
|
|
24
22
|
};
|
|
25
23
|
}
|
|
26
24
|
function writeCursorRules(rules, cursorRulesDir) {
|
|
@@ -53,9 +51,29 @@ function writeCursorCommands(commands, cursorCommandsDir) {
|
|
|
53
51
|
const commandPath = node_path_1.default.join(cursorCommandsDir, ...commandNameParts);
|
|
54
52
|
const commandFile = commandPath + ".md";
|
|
55
53
|
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(commandFile));
|
|
56
|
-
|
|
54
|
+
// If the command file references assets in the rules directory, we need to rewrite the links.
|
|
55
|
+
// Commands are installed in .cursor/commands/aicm/
|
|
56
|
+
// Rules/assets are installed in .cursor/rules/aicm/
|
|
57
|
+
// So a link like "../rules/asset.json" in source (from commands/ to rules/)
|
|
58
|
+
// needs to become "../../rules/aicm/asset.json" in target (from .cursor/commands/aicm/ to .cursor/rules/aicm/)
|
|
59
|
+
const content = rewriteCommandRelativeLinks(command.content);
|
|
60
|
+
fs_extra_1.default.writeFileSync(commandFile, content);
|
|
57
61
|
}
|
|
58
62
|
}
|
|
63
|
+
function rewriteCommandRelativeLinks(content) {
|
|
64
|
+
return content.replace(/\[([^\]]*)\]\(([^)]+)\)/g, (match, text, url) => {
|
|
65
|
+
if (url.startsWith("http") || url.startsWith("#") || url.startsWith("/")) {
|
|
66
|
+
return match;
|
|
67
|
+
}
|
|
68
|
+
// Check if it's a link to the rules directory
|
|
69
|
+
if (url.includes("rules/")) {
|
|
70
|
+
const parts = url.split("/");
|
|
71
|
+
const filename = parts[parts.length - 1];
|
|
72
|
+
return `[${text}](../../rules/aicm/${filename})`;
|
|
73
|
+
}
|
|
74
|
+
return match;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
59
77
|
function extractNamespaceFromPresetPath(presetPath) {
|
|
60
78
|
// Special case: npm package names always use forward slashes, regardless of platform
|
|
61
79
|
if (presetPath.startsWith("@")) {
|
|
@@ -68,7 +86,7 @@ function extractNamespaceFromPresetPath(presetPath) {
|
|
|
68
86
|
/**
|
|
69
87
|
* Write rules to a shared directory and update the given rules file
|
|
70
88
|
*/
|
|
71
|
-
function writeRulesForFile(rules, ruleDir, rulesFile) {
|
|
89
|
+
function writeRulesForFile(rules, assets, ruleDir, rulesFile) {
|
|
72
90
|
fs_extra_1.default.emptyDirSync(ruleDir);
|
|
73
91
|
const ruleFiles = rules.map((rule) => {
|
|
74
92
|
let rulePath;
|
|
@@ -83,9 +101,10 @@ function writeRulesForFile(rules, ruleDir, rulesFile) {
|
|
|
83
101
|
// For local rules, maintain the original flat structure
|
|
84
102
|
rulePath = node_path_1.default.join(ruleDir, ...ruleNameParts);
|
|
85
103
|
}
|
|
104
|
+
const content = rule.content;
|
|
86
105
|
const physicalRulePath = rulePath + ".md";
|
|
87
106
|
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(physicalRulePath));
|
|
88
|
-
fs_extra_1.default.writeFileSync(physicalRulePath,
|
|
107
|
+
fs_extra_1.default.writeFileSync(physicalRulePath, content);
|
|
89
108
|
const relativeRuleDir = node_path_1.default.basename(ruleDir);
|
|
90
109
|
// For the rules file, maintain the same structure
|
|
91
110
|
let windsurfPath;
|
|
@@ -102,16 +121,46 @@ function writeRulesForFile(rules, ruleDir, rulesFile) {
|
|
|
102
121
|
return {
|
|
103
122
|
name: rule.name,
|
|
104
123
|
path: windsurfPathPosix,
|
|
105
|
-
metadata: (0, rules_file_writer_1.parseRuleFrontmatter)(
|
|
124
|
+
metadata: (0, rules_file_writer_1.parseRuleFrontmatter)(content),
|
|
106
125
|
};
|
|
107
126
|
});
|
|
108
127
|
const rulesContent = (0, rules_file_writer_1.generateRulesFileContent)(ruleFiles);
|
|
109
128
|
(0, rules_file_writer_1.writeRulesFile)(rulesContent, node_path_1.default.join(process.cwd(), rulesFile));
|
|
110
129
|
}
|
|
130
|
+
function writeAssetsToTargets(assets, targets) {
|
|
131
|
+
const targetPaths = getTargetPaths();
|
|
132
|
+
for (const target of targets) {
|
|
133
|
+
let targetDir;
|
|
134
|
+
switch (target) {
|
|
135
|
+
case "cursor":
|
|
136
|
+
targetDir = targetPaths.cursor;
|
|
137
|
+
break;
|
|
138
|
+
case "windsurf":
|
|
139
|
+
case "codex":
|
|
140
|
+
case "claude":
|
|
141
|
+
targetDir = targetPaths.aicm;
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
for (const asset of assets) {
|
|
147
|
+
let assetPath;
|
|
148
|
+
if (asset.presetName) {
|
|
149
|
+
const namespace = extractNamespaceFromPresetPath(asset.presetName);
|
|
150
|
+
assetPath = node_path_1.default.join(targetDir, ...namespace, asset.name);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
assetPath = node_path_1.default.join(targetDir, asset.name);
|
|
154
|
+
}
|
|
155
|
+
fs_extra_1.default.ensureDirSync(node_path_1.default.dirname(assetPath));
|
|
156
|
+
fs_extra_1.default.writeFileSync(assetPath, asset.content);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
111
160
|
/**
|
|
112
161
|
* Write all collected rules to their respective IDE targets
|
|
113
162
|
*/
|
|
114
|
-
function writeRulesToTargets(rules, targets) {
|
|
163
|
+
function writeRulesToTargets(rules, assets, targets) {
|
|
115
164
|
const targetPaths = getTargetPaths();
|
|
116
165
|
for (const target of targets) {
|
|
117
166
|
switch (target) {
|
|
@@ -122,21 +171,23 @@ function writeRulesToTargets(rules, targets) {
|
|
|
122
171
|
break;
|
|
123
172
|
case "windsurf":
|
|
124
173
|
if (rules.length > 0) {
|
|
125
|
-
writeRulesForFile(rules, targetPaths.
|
|
174
|
+
writeRulesForFile(rules, assets, targetPaths.aicm, ".windsurfrules");
|
|
126
175
|
}
|
|
127
176
|
break;
|
|
128
177
|
case "codex":
|
|
129
178
|
if (rules.length > 0) {
|
|
130
|
-
writeRulesForFile(rules, targetPaths.
|
|
179
|
+
writeRulesForFile(rules, assets, targetPaths.aicm, "AGENTS.md");
|
|
131
180
|
}
|
|
132
181
|
break;
|
|
133
182
|
case "claude":
|
|
134
183
|
if (rules.length > 0) {
|
|
135
|
-
writeRulesForFile(rules, targetPaths.
|
|
184
|
+
writeRulesForFile(rules, assets, targetPaths.aicm, "CLAUDE.md");
|
|
136
185
|
}
|
|
137
186
|
break;
|
|
138
187
|
}
|
|
139
188
|
}
|
|
189
|
+
// Write assets after rules so they don't get wiped by emptyDirSync
|
|
190
|
+
writeAssetsToTargets(assets, targets);
|
|
140
191
|
}
|
|
141
192
|
function writeCommandsToTargets(commands, targets) {
|
|
142
193
|
const projectDir = process.cwd();
|
|
@@ -357,15 +408,17 @@ async function installPackage(options = {}) {
|
|
|
357
408
|
error: new Error("Configuration file not found"),
|
|
358
409
|
installedRuleCount: 0,
|
|
359
410
|
installedCommandCount: 0,
|
|
411
|
+
installedAssetCount: 0,
|
|
360
412
|
packagesCount: 0,
|
|
361
413
|
};
|
|
362
414
|
}
|
|
363
|
-
const { config, rules, commands, mcpServers } = resolvedConfig;
|
|
415
|
+
const { config, rules, commands, assets, mcpServers } = resolvedConfig;
|
|
364
416
|
if (config.skipInstall === true) {
|
|
365
417
|
return {
|
|
366
418
|
success: true,
|
|
367
419
|
installedRuleCount: 0,
|
|
368
420
|
installedCommandCount: 0,
|
|
421
|
+
installedAssetCount: 0,
|
|
369
422
|
packagesCount: 0,
|
|
370
423
|
};
|
|
371
424
|
}
|
|
@@ -373,7 +426,7 @@ async function installPackage(options = {}) {
|
|
|
373
426
|
const commandsToInstall = dedupeCommandsForInstall(commands);
|
|
374
427
|
try {
|
|
375
428
|
if (!options.dryRun) {
|
|
376
|
-
writeRulesToTargets(rules, config.targets);
|
|
429
|
+
writeRulesToTargets(rules, assets, config.targets);
|
|
377
430
|
writeCommandsToTargets(commandsToInstall, config.targets);
|
|
378
431
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
379
432
|
writeMcpServersToTargets(mcpServers, config.targets, cwd);
|
|
@@ -385,6 +438,7 @@ async function installPackage(options = {}) {
|
|
|
385
438
|
success: true,
|
|
386
439
|
installedRuleCount: uniqueRuleCount,
|
|
387
440
|
installedCommandCount: uniqueCommandCount,
|
|
441
|
+
installedAssetCount: assets.length,
|
|
388
442
|
packagesCount: 1,
|
|
389
443
|
};
|
|
390
444
|
}
|
|
@@ -394,6 +448,7 @@ async function installPackage(options = {}) {
|
|
|
394
448
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
395
449
|
installedRuleCount: 0,
|
|
396
450
|
installedCommandCount: 0,
|
|
451
|
+
installedAssetCount: 0,
|
|
397
452
|
packagesCount: 0,
|
|
398
453
|
};
|
|
399
454
|
}
|
|
@@ -406,6 +461,7 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
406
461
|
const results = [];
|
|
407
462
|
let totalRuleCount = 0;
|
|
408
463
|
let totalCommandCount = 0;
|
|
464
|
+
let totalAssetCount = 0;
|
|
409
465
|
// Install packages sequentially for now (can be parallelized later)
|
|
410
466
|
for (const pkg of packages) {
|
|
411
467
|
const packagePath = pkg.absolutePath;
|
|
@@ -417,12 +473,14 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
417
473
|
});
|
|
418
474
|
totalRuleCount += result.installedRuleCount;
|
|
419
475
|
totalCommandCount += result.installedCommandCount;
|
|
476
|
+
totalAssetCount += result.installedAssetCount;
|
|
420
477
|
results.push({
|
|
421
478
|
path: pkg.relativePath,
|
|
422
479
|
success: result.success,
|
|
423
480
|
error: result.error,
|
|
424
481
|
installedRuleCount: result.installedRuleCount,
|
|
425
482
|
installedCommandCount: result.installedCommandCount,
|
|
483
|
+
installedAssetCount: result.installedAssetCount,
|
|
426
484
|
});
|
|
427
485
|
}
|
|
428
486
|
catch (error) {
|
|
@@ -432,6 +490,7 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
432
490
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
433
491
|
installedRuleCount: 0,
|
|
434
492
|
installedCommandCount: 0,
|
|
493
|
+
installedAssetCount: 0,
|
|
435
494
|
});
|
|
436
495
|
}
|
|
437
496
|
}
|
|
@@ -441,6 +500,7 @@ async function installWorkspacesPackages(packages, options = {}) {
|
|
|
441
500
|
packages: results,
|
|
442
501
|
totalRuleCount,
|
|
443
502
|
totalCommandCount,
|
|
503
|
+
totalAssetCount,
|
|
444
504
|
};
|
|
445
505
|
}
|
|
446
506
|
/**
|
|
@@ -471,6 +531,7 @@ async function installWorkspaces(cwd, installOnCI, verbose = false, dryRun = fal
|
|
|
471
531
|
error: new Error("No packages with aicm configurations found"),
|
|
472
532
|
installedRuleCount: 0,
|
|
473
533
|
installedCommandCount: 0,
|
|
534
|
+
installedAssetCount: 0,
|
|
474
535
|
packagesCount: 0,
|
|
475
536
|
};
|
|
476
537
|
}
|
|
@@ -538,6 +599,7 @@ async function installWorkspaces(cwd, installOnCI, verbose = false, dryRun = fal
|
|
|
538
599
|
error: new Error(`Package installation failed for ${failedPackages.length} package(s): ${errorDetails}`),
|
|
539
600
|
installedRuleCount: result.totalRuleCount,
|
|
540
601
|
installedCommandCount: result.totalCommandCount,
|
|
602
|
+
installedAssetCount: result.totalAssetCount,
|
|
541
603
|
packagesCount: result.packages.length,
|
|
542
604
|
};
|
|
543
605
|
}
|
|
@@ -545,6 +607,7 @@ async function installWorkspaces(cwd, installOnCI, verbose = false, dryRun = fal
|
|
|
545
607
|
success: true,
|
|
546
608
|
installedRuleCount: result.totalRuleCount,
|
|
547
609
|
installedCommandCount: result.totalCommandCount,
|
|
610
|
+
installedAssetCount: result.totalAssetCount,
|
|
548
611
|
packagesCount: result.packages.length,
|
|
549
612
|
};
|
|
550
613
|
});
|
|
@@ -562,6 +625,7 @@ async function install(options = {}) {
|
|
|
562
625
|
success: true,
|
|
563
626
|
installedRuleCount: 0,
|
|
564
627
|
installedCommandCount: 0,
|
|
628
|
+
installedAssetCount: 0,
|
|
565
629
|
packagesCount: 0,
|
|
566
630
|
};
|
|
567
631
|
}
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -40,6 +40,13 @@ export interface ManagedFile {
|
|
|
40
40
|
source: "local" | "preset";
|
|
41
41
|
presetName?: string;
|
|
42
42
|
}
|
|
43
|
+
export interface AssetFile {
|
|
44
|
+
name: string;
|
|
45
|
+
content: Buffer;
|
|
46
|
+
sourcePath: string;
|
|
47
|
+
source: "local" | "preset";
|
|
48
|
+
presetName?: string;
|
|
49
|
+
}
|
|
43
50
|
export type RuleFile = ManagedFile;
|
|
44
51
|
export type CommandFile = ManagedFile;
|
|
45
52
|
export interface RuleCollection {
|
|
@@ -49,6 +56,7 @@ export interface ResolvedConfig {
|
|
|
49
56
|
config: Config;
|
|
50
57
|
rules: RuleFile[];
|
|
51
58
|
commands: CommandFile[];
|
|
59
|
+
assets: AssetFile[];
|
|
52
60
|
mcpServers: MCPServers;
|
|
53
61
|
}
|
|
54
62
|
export declare const ALLOWED_CONFIG_KEYS: readonly ["rulesDir", "commandsDir", "targets", "presets", "overrides", "mcpServers", "workspaces", "skipInstall"];
|
|
@@ -60,6 +68,7 @@ export declare function applyDefaults(config: RawConfig, workspaces: boolean): C
|
|
|
60
68
|
export declare function validateConfig(config: unknown, configFilePath: string, cwd: string, isWorkspaceMode?: boolean): asserts config is Config;
|
|
61
69
|
export declare function loadRulesFromDirectory(rulesDir: string, source: "local" | "preset", presetName?: string): Promise<RuleFile[]>;
|
|
62
70
|
export declare function loadCommandsFromDirectory(commandsDir: string, source: "local" | "preset", presetName?: string): Promise<CommandFile[]>;
|
|
71
|
+
export declare function loadAssetsFromDirectory(rulesDir: string, source: "local" | "preset", presetName?: string): Promise<AssetFile[]>;
|
|
63
72
|
export declare function resolvePresetPath(presetPath: string, cwd: string): string | null;
|
|
64
73
|
export declare function loadPreset(presetPath: string, cwd: string): Promise<{
|
|
65
74
|
config: Config;
|
|
@@ -69,6 +78,7 @@ export declare function loadPreset(presetPath: string, cwd: string): Promise<{
|
|
|
69
78
|
export declare function loadAllRules(config: Config, cwd: string): Promise<{
|
|
70
79
|
rules: RuleFile[];
|
|
71
80
|
commands: CommandFile[];
|
|
81
|
+
assets: AssetFile[];
|
|
72
82
|
mcpServers: MCPServers;
|
|
73
83
|
}>;
|
|
74
84
|
export declare function applyOverrides<T extends ManagedFile>(files: T[], overrides: Record<string, string | false>, cwd: string): T[];
|
package/dist/utils/config.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.applyDefaults = applyDefaults;
|
|
|
10
10
|
exports.validateConfig = validateConfig;
|
|
11
11
|
exports.loadRulesFromDirectory = loadRulesFromDirectory;
|
|
12
12
|
exports.loadCommandsFromDirectory = loadCommandsFromDirectory;
|
|
13
|
+
exports.loadAssetsFromDirectory = loadAssetsFromDirectory;
|
|
13
14
|
exports.resolvePresetPath = resolvePresetPath;
|
|
14
15
|
exports.loadPreset = loadPreset;
|
|
15
16
|
exports.loadAllRules = loadAllRules;
|
|
@@ -175,6 +176,34 @@ async function loadCommandsFromDirectory(commandsDir, source, presetName) {
|
|
|
175
176
|
}
|
|
176
177
|
return commands;
|
|
177
178
|
}
|
|
179
|
+
async function loadAssetsFromDirectory(rulesDir, source, presetName) {
|
|
180
|
+
const assets = [];
|
|
181
|
+
if (!fs_extra_1.default.existsSync(rulesDir)) {
|
|
182
|
+
return assets;
|
|
183
|
+
}
|
|
184
|
+
// Find all files except .mdc files and hidden files
|
|
185
|
+
const pattern = node_path_1.default.join(rulesDir, "**/*").replace(/\\/g, "/");
|
|
186
|
+
const filePaths = await (0, fast_glob_1.default)(pattern, {
|
|
187
|
+
onlyFiles: true,
|
|
188
|
+
absolute: true,
|
|
189
|
+
ignore: ["**/*.mdc", "**/.*"],
|
|
190
|
+
});
|
|
191
|
+
for (const filePath of filePaths) {
|
|
192
|
+
const content = await fs_extra_1.default.readFile(filePath);
|
|
193
|
+
// Preserve directory structure by using relative path from rulesDir
|
|
194
|
+
const relativePath = node_path_1.default.relative(rulesDir, filePath);
|
|
195
|
+
// Keep extension for assets
|
|
196
|
+
const assetName = relativePath.replace(/\\/g, "/");
|
|
197
|
+
assets.push({
|
|
198
|
+
name: assetName,
|
|
199
|
+
content,
|
|
200
|
+
sourcePath: filePath,
|
|
201
|
+
source,
|
|
202
|
+
presetName,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return assets;
|
|
206
|
+
}
|
|
178
207
|
function resolvePresetPath(presetPath, cwd) {
|
|
179
208
|
// Support specifying aicm.json directory and load the config from it
|
|
180
209
|
if (!presetPath.endsWith(".json")) {
|
|
@@ -230,12 +259,15 @@ async function loadPreset(presetPath, cwd) {
|
|
|
230
259
|
async function loadAllRules(config, cwd) {
|
|
231
260
|
const allRules = [];
|
|
232
261
|
const allCommands = [];
|
|
262
|
+
const allAssets = [];
|
|
233
263
|
let mergedMcpServers = { ...config.mcpServers };
|
|
234
264
|
// Load local rules only if rulesDir is provided
|
|
235
265
|
if (config.rulesDir) {
|
|
236
266
|
const localRulesPath = node_path_1.default.resolve(cwd, config.rulesDir);
|
|
237
267
|
const localRules = await loadRulesFromDirectory(localRulesPath, "local");
|
|
268
|
+
const localAssets = await loadAssetsFromDirectory(localRulesPath, "local");
|
|
238
269
|
allRules.push(...localRules);
|
|
270
|
+
allAssets.push(...localAssets);
|
|
239
271
|
}
|
|
240
272
|
if (config.commandsDir) {
|
|
241
273
|
const localCommandsPath = node_path_1.default.resolve(cwd, config.commandsDir);
|
|
@@ -247,7 +279,9 @@ async function loadAllRules(config, cwd) {
|
|
|
247
279
|
const preset = await loadPreset(presetPath, cwd);
|
|
248
280
|
if (preset.rulesDir) {
|
|
249
281
|
const presetRules = await loadRulesFromDirectory(preset.rulesDir, "preset", presetPath);
|
|
282
|
+
const presetAssets = await loadAssetsFromDirectory(preset.rulesDir, "preset", presetPath);
|
|
250
283
|
allRules.push(...presetRules);
|
|
284
|
+
allAssets.push(...presetAssets);
|
|
251
285
|
}
|
|
252
286
|
if (preset.commandsDir) {
|
|
253
287
|
const presetCommands = await loadCommandsFromDirectory(preset.commandsDir, "preset", presetPath);
|
|
@@ -262,6 +296,7 @@ async function loadAllRules(config, cwd) {
|
|
|
262
296
|
return {
|
|
263
297
|
rules: allRules,
|
|
264
298
|
commands: allCommands,
|
|
299
|
+
assets: allAssets,
|
|
265
300
|
mcpServers: mergedMcpServers,
|
|
266
301
|
};
|
|
267
302
|
}
|
|
@@ -341,9 +376,10 @@ async function loadConfig(cwd) {
|
|
|
341
376
|
const isWorkspaces = resolveWorkspaces(config, configResult.filepath, workingDir);
|
|
342
377
|
validateConfig(config, configResult.filepath, workingDir, isWorkspaces);
|
|
343
378
|
const configWithDefaults = applyDefaults(config, isWorkspaces);
|
|
344
|
-
const { rules, commands, mcpServers } = await loadAllRules(configWithDefaults, workingDir);
|
|
379
|
+
const { rules, commands, assets, mcpServers } = await loadAllRules(configWithDefaults, workingDir);
|
|
345
380
|
let rulesWithOverrides = rules;
|
|
346
381
|
let commandsWithOverrides = commands;
|
|
382
|
+
// Note: Assets are not currently supported in overrides as they are binary/varied files
|
|
347
383
|
if (configWithDefaults.overrides) {
|
|
348
384
|
const overrides = configWithDefaults.overrides;
|
|
349
385
|
const ruleNames = new Set(rules.map((rule) => rule.name));
|
|
@@ -366,6 +402,7 @@ async function loadConfig(cwd) {
|
|
|
366
402
|
config: configWithDefaults,
|
|
367
403
|
rules: rulesWithOverrides,
|
|
368
404
|
commands: commandsWithOverrides,
|
|
405
|
+
assets,
|
|
369
406
|
mcpServers,
|
|
370
407
|
};
|
|
371
408
|
}
|