rulesync 7.0.0 → 7.1.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 +155 -2
- package/dist/index.cjs +1280 -671
- package/dist/index.js +1276 -667
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -106,7 +106,7 @@ var logger = new Logger();
|
|
|
106
106
|
|
|
107
107
|
// src/lib/fetch.ts
|
|
108
108
|
import { Semaphore } from "es-toolkit/promise";
|
|
109
|
-
import { join as
|
|
109
|
+
import { join as join108 } from "path";
|
|
110
110
|
|
|
111
111
|
// src/constants/rulesync-paths.ts
|
|
112
112
|
import { join } from "path";
|
|
@@ -123,9 +123,15 @@ var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join(RULESYNC_RELATIVE_DIR_PATH, ".ai
|
|
|
123
123
|
var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
124
124
|
var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
125
125
|
var RULESYNC_SKILLS_RELATIVE_DIR_PATH = join(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
126
|
+
var RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = join(
|
|
127
|
+
RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
128
|
+
".curated"
|
|
129
|
+
);
|
|
130
|
+
var RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH = "rulesync.lock";
|
|
126
131
|
var RULESYNC_MCP_FILE_NAME = "mcp.json";
|
|
127
132
|
var RULESYNC_HOOKS_FILE_NAME = "hooks.json";
|
|
128
133
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
134
|
+
var FETCH_CONCURRENCY_LIMIT = 10;
|
|
129
135
|
|
|
130
136
|
// src/features/commands/commands-processor.ts
|
|
131
137
|
import { basename as basename16, join as join18 } from "path";
|
|
@@ -298,10 +304,11 @@ var FeatureProcessor = class {
|
|
|
298
304
|
}
|
|
299
305
|
/**
|
|
300
306
|
* Once converted to rulesync/tool files, write them to the filesystem.
|
|
301
|
-
* Returns the
|
|
307
|
+
* Returns the count and paths of files written.
|
|
302
308
|
*/
|
|
303
309
|
async writeAiFiles(aiFiles) {
|
|
304
310
|
let changedCount = 0;
|
|
311
|
+
const changedPaths = [];
|
|
305
312
|
for (const aiFile of aiFiles) {
|
|
306
313
|
const filePath = aiFile.getFilePath();
|
|
307
314
|
const contentWithNewline = addTrailingNewline(aiFile.getFileContent());
|
|
@@ -315,8 +322,9 @@ var FeatureProcessor = class {
|
|
|
315
322
|
await writeFileContent(filePath, contentWithNewline);
|
|
316
323
|
}
|
|
317
324
|
changedCount++;
|
|
325
|
+
changedPaths.push(aiFile.getRelativePathFromCwd());
|
|
318
326
|
}
|
|
319
|
-
return changedCount;
|
|
327
|
+
return { count: changedCount, paths: changedPaths };
|
|
320
328
|
}
|
|
321
329
|
async removeAiFiles(aiFiles) {
|
|
322
330
|
for (const aiFile of aiFiles) {
|
|
@@ -1656,7 +1664,7 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
|
|
|
1656
1664
|
const result = GeminiCliCommandFrontmatterSchema.safeParse(parsed);
|
|
1657
1665
|
if (!result.success) {
|
|
1658
1666
|
throw new Error(
|
|
1659
|
-
`Invalid frontmatter in
|
|
1667
|
+
`Invalid frontmatter in ${join13(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
1660
1668
|
);
|
|
1661
1669
|
}
|
|
1662
1670
|
return {
|
|
@@ -1664,7 +1672,10 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
|
|
|
1664
1672
|
description: result.data.description || ""
|
|
1665
1673
|
};
|
|
1666
1674
|
} catch (error) {
|
|
1667
|
-
throw new Error(
|
|
1675
|
+
throw new Error(
|
|
1676
|
+
`Failed to parse TOML command file (${join13(this.relativeDirPath, this.relativeFilePath)}): ${error}`,
|
|
1677
|
+
{ cause: error }
|
|
1678
|
+
);
|
|
1668
1679
|
}
|
|
1669
1680
|
}
|
|
1670
1681
|
getBody() {
|
|
@@ -2419,7 +2430,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2419
2430
|
(path4) => RulesyncCommand.fromFile({ relativeFilePath: basename16(path4) })
|
|
2420
2431
|
)
|
|
2421
2432
|
);
|
|
2422
|
-
logger.
|
|
2433
|
+
logger.debug(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
|
|
2423
2434
|
return rulesyncCommands;
|
|
2424
2435
|
}
|
|
2425
2436
|
/**
|
|
@@ -2443,7 +2454,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2443
2454
|
global: this.global
|
|
2444
2455
|
})
|
|
2445
2456
|
).filter((cmd) => cmd.isDeletable());
|
|
2446
|
-
logger.
|
|
2457
|
+
logger.debug(`Successfully loaded ${toolCommands2.length} ${paths.relativeDirPath} commands`);
|
|
2447
2458
|
return toolCommands2;
|
|
2448
2459
|
}
|
|
2449
2460
|
const toolCommands = await Promise.all(
|
|
@@ -2455,7 +2466,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2455
2466
|
})
|
|
2456
2467
|
)
|
|
2457
2468
|
);
|
|
2458
|
-
logger.
|
|
2469
|
+
logger.debug(`Successfully loaded ${toolCommands.length} ${paths.relativeDirPath} commands`);
|
|
2459
2470
|
return toolCommands;
|
|
2460
2471
|
}
|
|
2461
2472
|
/**
|
|
@@ -2792,10 +2803,7 @@ var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
|
2792
2803
|
}) {
|
|
2793
2804
|
const paths = _ClaudecodeHooks.getSettablePaths({ global });
|
|
2794
2805
|
const filePath = join20(baseDir, paths.relativeDirPath, paths.relativeFilePath);
|
|
2795
|
-
const fileContent = await
|
|
2796
|
-
filePath,
|
|
2797
|
-
JSON.stringify({ hooks: {} }, null, 2)
|
|
2798
|
-
);
|
|
2806
|
+
const fileContent = await readFileContentOrNull(filePath) ?? '{"hooks":{}}';
|
|
2799
2807
|
return new _ClaudecodeHooks({
|
|
2800
2808
|
baseDir,
|
|
2801
2809
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -2842,9 +2850,12 @@ var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
|
2842
2850
|
try {
|
|
2843
2851
|
settings = JSON.parse(this.getFileContent());
|
|
2844
2852
|
} catch (error) {
|
|
2845
|
-
throw new Error(
|
|
2846
|
-
|
|
2847
|
-
|
|
2853
|
+
throw new Error(
|
|
2854
|
+
`Failed to parse Claude hooks content in ${join20(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`,
|
|
2855
|
+
{
|
|
2856
|
+
cause: error
|
|
2857
|
+
}
|
|
2858
|
+
);
|
|
2848
2859
|
}
|
|
2849
2860
|
const hooks = claudeHooksToCanonical(settings.hooks);
|
|
2850
2861
|
return this.toRulesyncHooksDefault({
|
|
@@ -3067,10 +3078,7 @@ var FactorydroidHooks = class _FactorydroidHooks extends ToolHooks {
|
|
|
3067
3078
|
}) {
|
|
3068
3079
|
const paths = _FactorydroidHooks.getSettablePaths({ global });
|
|
3069
3080
|
const filePath = join22(baseDir, paths.relativeDirPath, paths.relativeFilePath);
|
|
3070
|
-
const fileContent = await
|
|
3071
|
-
filePath,
|
|
3072
|
-
JSON.stringify({ hooks: {} }, null, 2)
|
|
3073
|
-
);
|
|
3081
|
+
const fileContent = await readFileContentOrNull(filePath) ?? '{"hooks":{}}';
|
|
3074
3082
|
return new _FactorydroidHooks({
|
|
3075
3083
|
baseDir,
|
|
3076
3084
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -3117,9 +3125,12 @@ var FactorydroidHooks = class _FactorydroidHooks extends ToolHooks {
|
|
|
3117
3125
|
try {
|
|
3118
3126
|
settings = JSON.parse(this.getFileContent());
|
|
3119
3127
|
} catch (error) {
|
|
3120
|
-
throw new Error(
|
|
3121
|
-
|
|
3122
|
-
|
|
3128
|
+
throw new Error(
|
|
3129
|
+
`Failed to parse Factory Droid hooks content in ${join22(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`,
|
|
3130
|
+
{
|
|
3131
|
+
cause: error
|
|
3132
|
+
}
|
|
3133
|
+
);
|
|
3123
3134
|
}
|
|
3124
3135
|
const hooks = factorydroidHooksToCanonical(settings.hooks);
|
|
3125
3136
|
return this.toRulesyncHooksDefault({
|
|
@@ -3372,7 +3383,9 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3372
3383
|
})
|
|
3373
3384
|
];
|
|
3374
3385
|
} catch (error) {
|
|
3375
|
-
logger.error(
|
|
3386
|
+
logger.error(
|
|
3387
|
+
`Failed to load Rulesync hooks file (${RULESYNC_HOOKS_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
3388
|
+
);
|
|
3376
3389
|
return [];
|
|
3377
3390
|
}
|
|
3378
3391
|
}
|
|
@@ -3389,7 +3402,7 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3389
3402
|
global: this.global
|
|
3390
3403
|
});
|
|
3391
3404
|
const list = toolHooks2.isDeletable?.() !== false ? [toolHooks2] : [];
|
|
3392
|
-
logger.
|
|
3405
|
+
logger.debug(
|
|
3393
3406
|
`Successfully loaded ${list.length} ${this.toolTarget} hooks files for deletion`
|
|
3394
3407
|
);
|
|
3395
3408
|
return list;
|
|
@@ -3399,7 +3412,7 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3399
3412
|
validate: true,
|
|
3400
3413
|
global: this.global
|
|
3401
3414
|
});
|
|
3402
|
-
logger.
|
|
3415
|
+
logger.debug(`Successfully loaded 1 ${this.toolTarget} hooks file`);
|
|
3403
3416
|
return [toolHooks];
|
|
3404
3417
|
} catch (error) {
|
|
3405
3418
|
const msg = `Failed to load hooks files for tool target: ${this.toolTarget}: ${formatError(error)}`;
|
|
@@ -4463,7 +4476,9 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
4463
4476
|
try {
|
|
4464
4477
|
return [await RulesyncIgnore.fromFile()];
|
|
4465
4478
|
} catch (error) {
|
|
4466
|
-
logger.error(
|
|
4479
|
+
logger.error(
|
|
4480
|
+
`Failed to load rulesync ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
4481
|
+
);
|
|
4467
4482
|
return [];
|
|
4468
4483
|
}
|
|
4469
4484
|
}
|
|
@@ -4489,7 +4504,7 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
4489
4504
|
const toolIgnores = await this.loadToolIgnores();
|
|
4490
4505
|
return toolIgnores;
|
|
4491
4506
|
} catch (error) {
|
|
4492
|
-
const errorMessage = `Failed to load tool files: ${formatError(error)}`;
|
|
4507
|
+
const errorMessage = `Failed to load tool files for ${this.toolTarget}: ${formatError(error)}`;
|
|
4493
4508
|
if (error instanceof Error && error.message.includes("no such file or directory")) {
|
|
4494
4509
|
logger.debug(errorMessage);
|
|
4495
4510
|
} else {
|
|
@@ -4754,10 +4769,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
|
|
|
4754
4769
|
global = false
|
|
4755
4770
|
}) {
|
|
4756
4771
|
const paths = this.getSettablePaths({ global });
|
|
4757
|
-
const fileContent = await
|
|
4758
|
-
join38(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
4759
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
4760
|
-
);
|
|
4772
|
+
const fileContent = await readFileContentOrNull(join38(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
4761
4773
|
const json = JSON.parse(fileContent);
|
|
4762
4774
|
const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
|
|
4763
4775
|
return new _ClaudecodeMcp({
|
|
@@ -5310,10 +5322,7 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
|
|
|
5310
5322
|
global = false
|
|
5311
5323
|
}) {
|
|
5312
5324
|
const paths = this.getSettablePaths({ global });
|
|
5313
|
-
const fileContent = await
|
|
5314
|
-
join44(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5315
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5316
|
-
);
|
|
5325
|
+
const fileContent = await readFileContentOrNull(join44(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5317
5326
|
const json = JSON.parse(fileContent);
|
|
5318
5327
|
const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
|
|
5319
5328
|
return new _GeminiCliMcp({
|
|
@@ -5468,10 +5477,7 @@ var KiloMcp = class _KiloMcp extends ToolMcp {
|
|
|
5468
5477
|
validate = true
|
|
5469
5478
|
}) {
|
|
5470
5479
|
const paths = this.getSettablePaths();
|
|
5471
|
-
const fileContent = await
|
|
5472
|
-
join46(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5473
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5474
|
-
);
|
|
5480
|
+
const fileContent = await readFileContentOrNull(join46(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5475
5481
|
return new _KiloMcp({
|
|
5476
5482
|
baseDir,
|
|
5477
5483
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -5540,10 +5546,7 @@ var KiroMcp = class _KiroMcp extends ToolMcp {
|
|
|
5540
5546
|
validate = true
|
|
5541
5547
|
}) {
|
|
5542
5548
|
const paths = this.getSettablePaths();
|
|
5543
|
-
const fileContent = await
|
|
5544
|
-
join47(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5545
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5546
|
-
);
|
|
5549
|
+
const fileContent = await readFileContentOrNull(join47(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5547
5550
|
return new _KiroMcp({
|
|
5548
5551
|
baseDir,
|
|
5549
5552
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -5714,10 +5717,7 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
|
|
|
5714
5717
|
global = false
|
|
5715
5718
|
}) {
|
|
5716
5719
|
const paths = this.getSettablePaths({ global });
|
|
5717
|
-
const fileContent = await
|
|
5718
|
-
join48(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5719
|
-
JSON.stringify({ mcp: {} }, null, 2)
|
|
5720
|
-
);
|
|
5720
|
+
const fileContent = await readFileContentOrNull(join48(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcp":{}}';
|
|
5721
5721
|
const json = JSON.parse(fileContent);
|
|
5722
5722
|
const newJson = { ...json, mcp: json.mcp ?? {} };
|
|
5723
5723
|
return new _OpencodeMcp({
|
|
@@ -6045,7 +6045,9 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6045
6045
|
try {
|
|
6046
6046
|
return [await RulesyncMcp.fromFile({})];
|
|
6047
6047
|
} catch (error) {
|
|
6048
|
-
logger.error(
|
|
6048
|
+
logger.error(
|
|
6049
|
+
`Failed to load a Rulesync MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
6050
|
+
);
|
|
6049
6051
|
return [];
|
|
6050
6052
|
}
|
|
6051
6053
|
}
|
|
@@ -6067,7 +6069,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6067
6069
|
global: this.global
|
|
6068
6070
|
});
|
|
6069
6071
|
const toolMcps2 = toolMcp.isDeletable() ? [toolMcp] : [];
|
|
6070
|
-
logger.
|
|
6072
|
+
logger.debug(`Successfully loaded ${toolMcps2.length} ${this.toolTarget} MCP files`);
|
|
6071
6073
|
return toolMcps2;
|
|
6072
6074
|
}
|
|
6073
6075
|
const toolMcps = [
|
|
@@ -6077,7 +6079,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6077
6079
|
global: this.global
|
|
6078
6080
|
})
|
|
6079
6081
|
];
|
|
6080
|
-
logger.
|
|
6082
|
+
logger.debug(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
|
|
6081
6083
|
return toolMcps;
|
|
6082
6084
|
} catch (error) {
|
|
6083
6085
|
const errorMessage = `Failed to load MCP files for tool target: ${this.toolTarget}: ${formatError(error)}`;
|
|
@@ -6137,7 +6139,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6137
6139
|
|
|
6138
6140
|
// src/features/rules/rules-processor.ts
|
|
6139
6141
|
import { encode } from "@toon-format/toon";
|
|
6140
|
-
import { basename as
|
|
6142
|
+
import { basename as basename24, join as join107, relative as relative4 } from "path";
|
|
6141
6143
|
import { z as z48 } from "zod/mini";
|
|
6142
6144
|
|
|
6143
6145
|
// src/constants/general.ts
|
|
@@ -6600,7 +6602,7 @@ var FactorydroidSkill = class _FactorydroidSkill extends SimulatedSkill {
|
|
|
6600
6602
|
};
|
|
6601
6603
|
|
|
6602
6604
|
// src/features/skills/skills-processor.ts
|
|
6603
|
-
import { basename as
|
|
6605
|
+
import { basename as basename19, join as join70 } from "path";
|
|
6604
6606
|
import { z as z33 } from "zod/mini";
|
|
6605
6607
|
|
|
6606
6608
|
// src/types/dir-feature-processor.ts
|
|
@@ -6628,6 +6630,7 @@ var DirFeatureProcessor = class {
|
|
|
6628
6630
|
*/
|
|
6629
6631
|
async writeAiDirs(aiDirs) {
|
|
6630
6632
|
let changedCount = 0;
|
|
6633
|
+
const changedPaths = [];
|
|
6631
6634
|
for (const aiDir of aiDirs) {
|
|
6632
6635
|
const dirPath = aiDir.getDirPath();
|
|
6633
6636
|
let dirHasChanges = false;
|
|
@@ -6658,19 +6661,23 @@ var DirFeatureProcessor = class {
|
|
|
6658
6661
|
if (!dirHasChanges) {
|
|
6659
6662
|
continue;
|
|
6660
6663
|
}
|
|
6664
|
+
const relativeDir = aiDir.getRelativePathFromCwd();
|
|
6661
6665
|
if (this.dryRun) {
|
|
6662
6666
|
logger.info(`[DRY RUN] Would create directory: ${dirPath}`);
|
|
6663
6667
|
if (mainFile) {
|
|
6664
6668
|
logger.info(`[DRY RUN] Would write: ${join55(dirPath, mainFile.name)}`);
|
|
6669
|
+
changedPaths.push(join55(relativeDir, mainFile.name));
|
|
6665
6670
|
}
|
|
6666
6671
|
for (const file of otherFiles) {
|
|
6667
6672
|
logger.info(`[DRY RUN] Would write: ${join55(dirPath, file.relativeFilePathToDirPath)}`);
|
|
6673
|
+
changedPaths.push(join55(relativeDir, file.relativeFilePathToDirPath));
|
|
6668
6674
|
}
|
|
6669
6675
|
} else {
|
|
6670
6676
|
await ensureDir(dirPath);
|
|
6671
6677
|
if (mainFile && mainFileContent) {
|
|
6672
6678
|
const mainFilePath = join55(dirPath, mainFile.name);
|
|
6673
6679
|
await writeFileContent(mainFilePath, mainFileContent);
|
|
6680
|
+
changedPaths.push(join55(relativeDir, mainFile.name));
|
|
6674
6681
|
}
|
|
6675
6682
|
for (const [i, file] of otherFiles.entries()) {
|
|
6676
6683
|
const filePath = join55(dirPath, file.relativeFilePathToDirPath);
|
|
@@ -6681,11 +6688,12 @@ var DirFeatureProcessor = class {
|
|
|
6681
6688
|
);
|
|
6682
6689
|
}
|
|
6683
6690
|
await writeFileContent(filePath, content);
|
|
6691
|
+
changedPaths.push(join55(relativeDir, file.relativeFilePathToDirPath));
|
|
6684
6692
|
}
|
|
6685
6693
|
}
|
|
6686
6694
|
changedCount++;
|
|
6687
6695
|
}
|
|
6688
|
-
return changedCount;
|
|
6696
|
+
return { count: changedCount, paths: changedPaths };
|
|
6689
6697
|
}
|
|
6690
6698
|
async removeAiDirs(aiDirs) {
|
|
6691
6699
|
for (const aiDir of aiDirs) {
|
|
@@ -6782,7 +6790,7 @@ var RulesyncSkill = class _RulesyncSkill extends AiDir {
|
|
|
6782
6790
|
}
|
|
6783
6791
|
getFrontmatter() {
|
|
6784
6792
|
if (!this.mainFile?.frontmatter) {
|
|
6785
|
-
throw new Error(
|
|
6793
|
+
throw new Error(`Frontmatter is not defined in ${join56(this.relativeDirPath, this.dirName)}`);
|
|
6786
6794
|
}
|
|
6787
6795
|
const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
6788
6796
|
return result;
|
|
@@ -6883,7 +6891,7 @@ var AgentsSkillsSkill = class _AgentsSkillsSkill extends ToolSkill {
|
|
|
6883
6891
|
}
|
|
6884
6892
|
getFrontmatter() {
|
|
6885
6893
|
if (!this.mainFile?.frontmatter) {
|
|
6886
|
-
throw new Error(
|
|
6894
|
+
throw new Error(`Frontmatter is not defined in ${join57(this.relativeDirPath, this.dirName)}`);
|
|
6887
6895
|
}
|
|
6888
6896
|
const result = AgentsSkillsSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
6889
6897
|
return result;
|
|
@@ -7047,7 +7055,7 @@ var AntigravitySkill = class _AntigravitySkill extends ToolSkill {
|
|
|
7047
7055
|
}
|
|
7048
7056
|
getFrontmatter() {
|
|
7049
7057
|
if (!this.mainFile?.frontmatter) {
|
|
7050
|
-
throw new Error(
|
|
7058
|
+
throw new Error(`Frontmatter is not defined in ${join58(this.relativeDirPath, this.dirName)}`);
|
|
7051
7059
|
}
|
|
7052
7060
|
const result = AntigravitySkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7053
7061
|
return result;
|
|
@@ -7206,7 +7214,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
|
|
|
7206
7214
|
}
|
|
7207
7215
|
getFrontmatter() {
|
|
7208
7216
|
if (!this.mainFile?.frontmatter) {
|
|
7209
|
-
throw new Error(
|
|
7217
|
+
throw new Error(`Frontmatter is not defined in ${join59(this.relativeDirPath, this.dirName)}`);
|
|
7210
7218
|
}
|
|
7211
7219
|
const result = ClaudecodeSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7212
7220
|
return result;
|
|
@@ -7375,7 +7383,7 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
|
|
|
7375
7383
|
}
|
|
7376
7384
|
getFrontmatter() {
|
|
7377
7385
|
if (!this.mainFile?.frontmatter) {
|
|
7378
|
-
throw new Error(
|
|
7386
|
+
throw new Error(`Frontmatter is not defined in ${join60(this.relativeDirPath, this.dirName)}`);
|
|
7379
7387
|
}
|
|
7380
7388
|
const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7381
7389
|
return result;
|
|
@@ -7545,7 +7553,7 @@ var CopilotSkill = class _CopilotSkill extends ToolSkill {
|
|
|
7545
7553
|
}
|
|
7546
7554
|
getFrontmatter() {
|
|
7547
7555
|
if (!this.mainFile?.frontmatter) {
|
|
7548
|
-
throw new Error(
|
|
7556
|
+
throw new Error(`Frontmatter is not defined in ${join61(this.relativeDirPath, this.dirName)}`);
|
|
7549
7557
|
}
|
|
7550
7558
|
const result = CopilotSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7551
7559
|
return result;
|
|
@@ -7708,7 +7716,7 @@ var CursorSkill = class _CursorSkill extends ToolSkill {
|
|
|
7708
7716
|
}
|
|
7709
7717
|
getFrontmatter() {
|
|
7710
7718
|
if (!this.mainFile?.frontmatter) {
|
|
7711
|
-
throw new Error(
|
|
7719
|
+
throw new Error(`Frontmatter is not defined in ${join62(this.relativeDirPath, this.dirName)}`);
|
|
7712
7720
|
}
|
|
7713
7721
|
const result = CursorSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7714
7722
|
return result;
|
|
@@ -7867,7 +7875,7 @@ var GeminiCliSkill = class _GeminiCliSkill extends ToolSkill {
|
|
|
7867
7875
|
}
|
|
7868
7876
|
getFrontmatter() {
|
|
7869
7877
|
if (!this.mainFile?.frontmatter) {
|
|
7870
|
-
throw new Error(
|
|
7878
|
+
throw new Error(`Frontmatter is not defined in ${join63(this.relativeDirPath, this.dirName)}`);
|
|
7871
7879
|
}
|
|
7872
7880
|
const result = GeminiCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7873
7881
|
return result;
|
|
@@ -8026,7 +8034,7 @@ var KiloSkill = class _KiloSkill extends ToolSkill {
|
|
|
8026
8034
|
}
|
|
8027
8035
|
getFrontmatter() {
|
|
8028
8036
|
if (!this.mainFile?.frontmatter) {
|
|
8029
|
-
throw new Error(
|
|
8037
|
+
throw new Error(`Frontmatter is not defined in ${join64(this.relativeDirPath, this.dirName)}`);
|
|
8030
8038
|
}
|
|
8031
8039
|
const result = KiloSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8032
8040
|
return result;
|
|
@@ -8204,7 +8212,7 @@ var KiroSkill = class _KiroSkill extends ToolSkill {
|
|
|
8204
8212
|
}
|
|
8205
8213
|
getFrontmatter() {
|
|
8206
8214
|
if (!this.mainFile?.frontmatter) {
|
|
8207
|
-
throw new Error(
|
|
8215
|
+
throw new Error(`Frontmatter is not defined in ${join65(this.relativeDirPath, this.dirName)}`);
|
|
8208
8216
|
}
|
|
8209
8217
|
const result = KiroSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8210
8218
|
return result;
|
|
@@ -8381,7 +8389,7 @@ var OpenCodeSkill = class _OpenCodeSkill extends ToolSkill {
|
|
|
8381
8389
|
}
|
|
8382
8390
|
getFrontmatter() {
|
|
8383
8391
|
if (!this.mainFile?.frontmatter) {
|
|
8384
|
-
throw new Error(
|
|
8392
|
+
throw new Error(`Frontmatter is not defined in ${join66(this.relativeDirPath, this.dirName)}`);
|
|
8385
8393
|
}
|
|
8386
8394
|
const result = OpenCodeSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8387
8395
|
return result;
|
|
@@ -8546,7 +8554,7 @@ var ReplitSkill = class _ReplitSkill extends ToolSkill {
|
|
|
8546
8554
|
}
|
|
8547
8555
|
getFrontmatter() {
|
|
8548
8556
|
if (!this.mainFile?.frontmatter) {
|
|
8549
|
-
throw new Error(
|
|
8557
|
+
throw new Error(`Frontmatter is not defined in ${join67(this.relativeDirPath, this.dirName)}`);
|
|
8550
8558
|
}
|
|
8551
8559
|
const result = ReplitSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8552
8560
|
return result;
|
|
@@ -8705,7 +8713,7 @@ var RooSkill = class _RooSkill extends ToolSkill {
|
|
|
8705
8713
|
}
|
|
8706
8714
|
getFrontmatter() {
|
|
8707
8715
|
if (!this.mainFile?.frontmatter) {
|
|
8708
|
-
throw new Error(
|
|
8716
|
+
throw new Error(`Frontmatter is not defined in ${join68(this.relativeDirPath, this.dirName)}`);
|
|
8709
8717
|
}
|
|
8710
8718
|
const result = RooSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8711
8719
|
return result;
|
|
@@ -8836,6 +8844,23 @@ var RooSkill = class _RooSkill extends ToolSkill {
|
|
|
8836
8844
|
}
|
|
8837
8845
|
};
|
|
8838
8846
|
|
|
8847
|
+
// src/features/skills/skills-utils.ts
|
|
8848
|
+
import { basename as basename18, join as join69 } from "path";
|
|
8849
|
+
async function getLocalSkillDirNames(baseDir) {
|
|
8850
|
+
const skillsDir = join69(baseDir, RULESYNC_SKILLS_RELATIVE_DIR_PATH);
|
|
8851
|
+
const names = /* @__PURE__ */ new Set();
|
|
8852
|
+
if (!await directoryExists(skillsDir)) {
|
|
8853
|
+
return names;
|
|
8854
|
+
}
|
|
8855
|
+
const dirPaths = await findFilesByGlobs(join69(skillsDir, "*"), { type: "dir" });
|
|
8856
|
+
for (const dirPath of dirPaths) {
|
|
8857
|
+
const name = basename18(dirPath);
|
|
8858
|
+
if (name === basename18(RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH)) continue;
|
|
8859
|
+
names.add(name);
|
|
8860
|
+
}
|
|
8861
|
+
return names;
|
|
8862
|
+
}
|
|
8863
|
+
|
|
8839
8864
|
// src/features/skills/skills-processor.ts
|
|
8840
8865
|
var skillsProcessorToolTargetTuple = [
|
|
8841
8866
|
"agentsmd",
|
|
@@ -9037,19 +9062,46 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9037
9062
|
/**
|
|
9038
9063
|
* Implementation of abstract method from DirFeatureProcessor
|
|
9039
9064
|
* Load and parse rulesync skill directories from .rulesync/skills/ directory
|
|
9065
|
+
* and also from .rulesync/skills/.curated/ for remote skills.
|
|
9066
|
+
* Local skills take precedence over curated skills with the same name.
|
|
9040
9067
|
*/
|
|
9041
9068
|
async loadRulesyncDirs() {
|
|
9042
|
-
const
|
|
9043
|
-
const
|
|
9044
|
-
|
|
9045
|
-
const dirNames = dirPaths.map((path4) => basename18(path4));
|
|
9046
|
-
const rulesyncSkills = await Promise.all(
|
|
9047
|
-
dirNames.map(
|
|
9069
|
+
const localDirNames = [...await getLocalSkillDirNames(this.baseDir)];
|
|
9070
|
+
const localSkills = await Promise.all(
|
|
9071
|
+
localDirNames.map(
|
|
9048
9072
|
(dirName) => RulesyncSkill.fromDir({ baseDir: this.baseDir, dirName, global: this.global })
|
|
9049
9073
|
)
|
|
9050
9074
|
);
|
|
9051
|
-
|
|
9052
|
-
|
|
9075
|
+
const localSkillNames = new Set(localDirNames);
|
|
9076
|
+
const curatedDirPath = join70(this.baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
9077
|
+
let curatedSkills = [];
|
|
9078
|
+
if (await directoryExists(curatedDirPath)) {
|
|
9079
|
+
const curatedDirPaths = await findFilesByGlobs(join70(curatedDirPath, "*"), { type: "dir" });
|
|
9080
|
+
const curatedDirNames = curatedDirPaths.map((path4) => basename19(path4));
|
|
9081
|
+
const nonConflicting = curatedDirNames.filter((name) => {
|
|
9082
|
+
if (localSkillNames.has(name)) {
|
|
9083
|
+
logger.debug(`Skipping curated skill "${name}": local skill takes precedence.`);
|
|
9084
|
+
return false;
|
|
9085
|
+
}
|
|
9086
|
+
return true;
|
|
9087
|
+
});
|
|
9088
|
+
const curatedRelativeDirPath = RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH;
|
|
9089
|
+
curatedSkills = await Promise.all(
|
|
9090
|
+
nonConflicting.map(
|
|
9091
|
+
(dirName) => RulesyncSkill.fromDir({
|
|
9092
|
+
baseDir: this.baseDir,
|
|
9093
|
+
relativeDirPath: curatedRelativeDirPath,
|
|
9094
|
+
dirName,
|
|
9095
|
+
global: this.global
|
|
9096
|
+
})
|
|
9097
|
+
)
|
|
9098
|
+
);
|
|
9099
|
+
}
|
|
9100
|
+
const allSkills = [...localSkills, ...curatedSkills];
|
|
9101
|
+
logger.debug(
|
|
9102
|
+
`Successfully loaded ${allSkills.length} rulesync skills (${localSkills.length} local, ${curatedSkills.length} curated)`
|
|
9103
|
+
);
|
|
9104
|
+
return allSkills;
|
|
9053
9105
|
}
|
|
9054
9106
|
/**
|
|
9055
9107
|
* Implementation of abstract method from DirFeatureProcessor
|
|
@@ -9058,9 +9110,9 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9058
9110
|
async loadToolDirs() {
|
|
9059
9111
|
const factory = this.getFactory(this.toolTarget);
|
|
9060
9112
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
9061
|
-
const skillsDirPath =
|
|
9062
|
-
const dirPaths = await findFilesByGlobs(
|
|
9063
|
-
const dirNames = dirPaths.map((path4) =>
|
|
9113
|
+
const skillsDirPath = join70(this.baseDir, paths.relativeDirPath);
|
|
9114
|
+
const dirPaths = await findFilesByGlobs(join70(skillsDirPath, "*"), { type: "dir" });
|
|
9115
|
+
const dirNames = dirPaths.map((path4) => basename19(path4));
|
|
9064
9116
|
const toolSkills = await Promise.all(
|
|
9065
9117
|
dirNames.map(
|
|
9066
9118
|
(dirName) => factory.class.fromDir({
|
|
@@ -9070,15 +9122,15 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9070
9122
|
})
|
|
9071
9123
|
)
|
|
9072
9124
|
);
|
|
9073
|
-
logger.
|
|
9125
|
+
logger.debug(`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills`);
|
|
9074
9126
|
return toolSkills;
|
|
9075
9127
|
}
|
|
9076
9128
|
async loadToolDirsToDelete() {
|
|
9077
9129
|
const factory = this.getFactory(this.toolTarget);
|
|
9078
9130
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
9079
|
-
const skillsDirPath =
|
|
9080
|
-
const dirPaths = await findFilesByGlobs(
|
|
9081
|
-
const dirNames = dirPaths.map((path4) =>
|
|
9131
|
+
const skillsDirPath = join70(this.baseDir, paths.relativeDirPath);
|
|
9132
|
+
const dirPaths = await findFilesByGlobs(join70(skillsDirPath, "*"), { type: "dir" });
|
|
9133
|
+
const dirNames = dirPaths.map((path4) => basename19(path4));
|
|
9082
9134
|
const toolSkills = dirNames.map(
|
|
9083
9135
|
(dirName) => factory.class.forDeletion({
|
|
9084
9136
|
baseDir: this.baseDir,
|
|
@@ -9087,7 +9139,7 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9087
9139
|
global: this.global
|
|
9088
9140
|
})
|
|
9089
9141
|
);
|
|
9090
|
-
logger.
|
|
9142
|
+
logger.debug(
|
|
9091
9143
|
`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills for deletion`
|
|
9092
9144
|
);
|
|
9093
9145
|
return toolSkills;
|
|
@@ -9139,10 +9191,10 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9139
9191
|
};
|
|
9140
9192
|
|
|
9141
9193
|
// src/features/subagents/agentsmd-subagent.ts
|
|
9142
|
-
import { join as
|
|
9194
|
+
import { join as join72 } from "path";
|
|
9143
9195
|
|
|
9144
9196
|
// src/features/subagents/simulated-subagent.ts
|
|
9145
|
-
import { basename as
|
|
9197
|
+
import { basename as basename20, join as join71 } from "path";
|
|
9146
9198
|
import { z as z34 } from "zod/mini";
|
|
9147
9199
|
|
|
9148
9200
|
// src/features/subagents/tool-subagent.ts
|
|
@@ -9198,7 +9250,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9198
9250
|
const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9199
9251
|
if (!result.success) {
|
|
9200
9252
|
throw new Error(
|
|
9201
|
-
`Invalid frontmatter in ${
|
|
9253
|
+
`Invalid frontmatter in ${join71(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9202
9254
|
);
|
|
9203
9255
|
}
|
|
9204
9256
|
}
|
|
@@ -9249,7 +9301,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9249
9301
|
return {
|
|
9250
9302
|
success: false,
|
|
9251
9303
|
error: new Error(
|
|
9252
|
-
`Invalid frontmatter in ${
|
|
9304
|
+
`Invalid frontmatter in ${join71(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9253
9305
|
)
|
|
9254
9306
|
};
|
|
9255
9307
|
}
|
|
@@ -9259,7 +9311,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9259
9311
|
relativeFilePath,
|
|
9260
9312
|
validate = true
|
|
9261
9313
|
}) {
|
|
9262
|
-
const filePath =
|
|
9314
|
+
const filePath = join71(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
|
|
9263
9315
|
const fileContent = await readFileContent(filePath);
|
|
9264
9316
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9265
9317
|
const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9269,7 +9321,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9269
9321
|
return {
|
|
9270
9322
|
baseDir,
|
|
9271
9323
|
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
9272
|
-
relativeFilePath:
|
|
9324
|
+
relativeFilePath: basename20(relativeFilePath),
|
|
9273
9325
|
frontmatter: result.data,
|
|
9274
9326
|
body: content.trim(),
|
|
9275
9327
|
validate
|
|
@@ -9295,7 +9347,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9295
9347
|
var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
|
|
9296
9348
|
static getSettablePaths() {
|
|
9297
9349
|
return {
|
|
9298
|
-
relativeDirPath:
|
|
9350
|
+
relativeDirPath: join72(".agents", "subagents")
|
|
9299
9351
|
};
|
|
9300
9352
|
}
|
|
9301
9353
|
static async fromFile(params) {
|
|
@@ -9318,11 +9370,11 @@ var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
|
|
|
9318
9370
|
};
|
|
9319
9371
|
|
|
9320
9372
|
// src/features/subagents/codexcli-subagent.ts
|
|
9321
|
-
import { join as
|
|
9373
|
+
import { join as join73 } from "path";
|
|
9322
9374
|
var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
|
|
9323
9375
|
static getSettablePaths() {
|
|
9324
9376
|
return {
|
|
9325
|
-
relativeDirPath:
|
|
9377
|
+
relativeDirPath: join73(".codex", "subagents")
|
|
9326
9378
|
};
|
|
9327
9379
|
}
|
|
9328
9380
|
static async fromFile(params) {
|
|
@@ -9345,11 +9397,11 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
|
|
|
9345
9397
|
};
|
|
9346
9398
|
|
|
9347
9399
|
// src/features/subagents/factorydroid-subagent.ts
|
|
9348
|
-
import { join as
|
|
9400
|
+
import { join as join74 } from "path";
|
|
9349
9401
|
var FactorydroidSubagent = class _FactorydroidSubagent extends SimulatedSubagent {
|
|
9350
9402
|
static getSettablePaths(_options) {
|
|
9351
9403
|
return {
|
|
9352
|
-
relativeDirPath:
|
|
9404
|
+
relativeDirPath: join74(".factory", "droids")
|
|
9353
9405
|
};
|
|
9354
9406
|
}
|
|
9355
9407
|
static async fromFile(params) {
|
|
@@ -9372,11 +9424,11 @@ var FactorydroidSubagent = class _FactorydroidSubagent extends SimulatedSubagent
|
|
|
9372
9424
|
};
|
|
9373
9425
|
|
|
9374
9426
|
// src/features/subagents/geminicli-subagent.ts
|
|
9375
|
-
import { join as
|
|
9427
|
+
import { join as join75 } from "path";
|
|
9376
9428
|
var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
|
|
9377
9429
|
static getSettablePaths() {
|
|
9378
9430
|
return {
|
|
9379
|
-
relativeDirPath:
|
|
9431
|
+
relativeDirPath: join75(".gemini", "subagents")
|
|
9380
9432
|
};
|
|
9381
9433
|
}
|
|
9382
9434
|
static async fromFile(params) {
|
|
@@ -9399,11 +9451,11 @@ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
|
|
|
9399
9451
|
};
|
|
9400
9452
|
|
|
9401
9453
|
// src/features/subagents/roo-subagent.ts
|
|
9402
|
-
import { join as
|
|
9454
|
+
import { join as join76 } from "path";
|
|
9403
9455
|
var RooSubagent = class _RooSubagent extends SimulatedSubagent {
|
|
9404
9456
|
static getSettablePaths() {
|
|
9405
9457
|
return {
|
|
9406
|
-
relativeDirPath:
|
|
9458
|
+
relativeDirPath: join76(".roo", "subagents")
|
|
9407
9459
|
};
|
|
9408
9460
|
}
|
|
9409
9461
|
static async fromFile(params) {
|
|
@@ -9426,15 +9478,15 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
|
|
|
9426
9478
|
};
|
|
9427
9479
|
|
|
9428
9480
|
// src/features/subagents/subagents-processor.ts
|
|
9429
|
-
import { basename as
|
|
9481
|
+
import { basename as basename23, join as join83 } from "path";
|
|
9430
9482
|
import { z as z41 } from "zod/mini";
|
|
9431
9483
|
|
|
9432
9484
|
// src/features/subagents/claudecode-subagent.ts
|
|
9433
|
-
import { join as
|
|
9485
|
+
import { join as join78 } from "path";
|
|
9434
9486
|
import { z as z36 } from "zod/mini";
|
|
9435
9487
|
|
|
9436
9488
|
// src/features/subagents/rulesync-subagent.ts
|
|
9437
|
-
import { basename as
|
|
9489
|
+
import { basename as basename21, join as join77 } from "path";
|
|
9438
9490
|
import { z as z35 } from "zod/mini";
|
|
9439
9491
|
var RulesyncSubagentFrontmatterSchema = z35.looseObject({
|
|
9440
9492
|
targets: z35._default(RulesyncTargetsSchema, ["*"]),
|
|
@@ -9448,7 +9500,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9448
9500
|
const parseResult = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9449
9501
|
if (!parseResult.success && rest.validate !== false) {
|
|
9450
9502
|
throw new Error(
|
|
9451
|
-
`Invalid frontmatter in ${
|
|
9503
|
+
`Invalid frontmatter in ${join77(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`
|
|
9452
9504
|
);
|
|
9453
9505
|
}
|
|
9454
9506
|
const parsedFrontmatter = parseResult.success ? { ...frontmatter, ...parseResult.data } : { ...frontmatter, targets: frontmatter?.targets ?? ["*"] };
|
|
@@ -9481,7 +9533,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9481
9533
|
return {
|
|
9482
9534
|
success: false,
|
|
9483
9535
|
error: new Error(
|
|
9484
|
-
`Invalid frontmatter in ${
|
|
9536
|
+
`Invalid frontmatter in ${join77(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9485
9537
|
)
|
|
9486
9538
|
};
|
|
9487
9539
|
}
|
|
@@ -9490,14 +9542,14 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9490
9542
|
relativeFilePath
|
|
9491
9543
|
}) {
|
|
9492
9544
|
const fileContent = await readFileContent(
|
|
9493
|
-
|
|
9545
|
+
join77(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, relativeFilePath)
|
|
9494
9546
|
);
|
|
9495
9547
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9496
9548
|
const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9497
9549
|
if (!result.success) {
|
|
9498
9550
|
throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
9499
9551
|
}
|
|
9500
|
-
const filename =
|
|
9552
|
+
const filename = basename21(relativeFilePath);
|
|
9501
9553
|
return new _RulesyncSubagent({
|
|
9502
9554
|
baseDir: process.cwd(),
|
|
9503
9555
|
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
@@ -9525,7 +9577,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9525
9577
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9526
9578
|
if (!result.success) {
|
|
9527
9579
|
throw new Error(
|
|
9528
|
-
`Invalid frontmatter in ${
|
|
9580
|
+
`Invalid frontmatter in ${join78(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9529
9581
|
);
|
|
9530
9582
|
}
|
|
9531
9583
|
}
|
|
@@ -9537,7 +9589,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9537
9589
|
}
|
|
9538
9590
|
static getSettablePaths(_options = {}) {
|
|
9539
9591
|
return {
|
|
9540
|
-
relativeDirPath:
|
|
9592
|
+
relativeDirPath: join78(".claude", "agents")
|
|
9541
9593
|
};
|
|
9542
9594
|
}
|
|
9543
9595
|
getFrontmatter() {
|
|
@@ -9584,7 +9636,9 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9584
9636
|
};
|
|
9585
9637
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(rawClaudecodeFrontmatter);
|
|
9586
9638
|
if (!result.success) {
|
|
9587
|
-
throw new Error(
|
|
9639
|
+
throw new Error(
|
|
9640
|
+
`Invalid claudecode subagent frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(result.error)}`
|
|
9641
|
+
);
|
|
9588
9642
|
}
|
|
9589
9643
|
const claudecodeFrontmatter = result.data;
|
|
9590
9644
|
const body = rulesyncSubagent.getBody();
|
|
@@ -9611,7 +9665,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9611
9665
|
return {
|
|
9612
9666
|
success: false,
|
|
9613
9667
|
error: new Error(
|
|
9614
|
-
`Invalid frontmatter in ${
|
|
9668
|
+
`Invalid frontmatter in ${join78(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9615
9669
|
)
|
|
9616
9670
|
};
|
|
9617
9671
|
}
|
|
@@ -9629,7 +9683,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9629
9683
|
global = false
|
|
9630
9684
|
}) {
|
|
9631
9685
|
const paths = this.getSettablePaths({ global });
|
|
9632
|
-
const filePath =
|
|
9686
|
+
const filePath = join78(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9633
9687
|
const fileContent = await readFileContent(filePath);
|
|
9634
9688
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9635
9689
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9664,7 +9718,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9664
9718
|
};
|
|
9665
9719
|
|
|
9666
9720
|
// src/features/subagents/copilot-subagent.ts
|
|
9667
|
-
import { join as
|
|
9721
|
+
import { join as join79 } from "path";
|
|
9668
9722
|
import { z as z37 } from "zod/mini";
|
|
9669
9723
|
var REQUIRED_TOOL = "agent/runSubagent";
|
|
9670
9724
|
var CopilotSubagentFrontmatterSchema = z37.looseObject({
|
|
@@ -9690,7 +9744,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9690
9744
|
const result = CopilotSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9691
9745
|
if (!result.success) {
|
|
9692
9746
|
throw new Error(
|
|
9693
|
-
`Invalid frontmatter in ${
|
|
9747
|
+
`Invalid frontmatter in ${join79(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9694
9748
|
);
|
|
9695
9749
|
}
|
|
9696
9750
|
}
|
|
@@ -9702,7 +9756,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9702
9756
|
}
|
|
9703
9757
|
static getSettablePaths(_options = {}) {
|
|
9704
9758
|
return {
|
|
9705
|
-
relativeDirPath:
|
|
9759
|
+
relativeDirPath: join79(".github", "agents")
|
|
9706
9760
|
};
|
|
9707
9761
|
}
|
|
9708
9762
|
getFrontmatter() {
|
|
@@ -9776,7 +9830,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9776
9830
|
return {
|
|
9777
9831
|
success: false,
|
|
9778
9832
|
error: new Error(
|
|
9779
|
-
`Invalid frontmatter in ${
|
|
9833
|
+
`Invalid frontmatter in ${join79(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9780
9834
|
)
|
|
9781
9835
|
};
|
|
9782
9836
|
}
|
|
@@ -9794,7 +9848,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9794
9848
|
global = false
|
|
9795
9849
|
}) {
|
|
9796
9850
|
const paths = this.getSettablePaths({ global });
|
|
9797
|
-
const filePath =
|
|
9851
|
+
const filePath = join79(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9798
9852
|
const fileContent = await readFileContent(filePath);
|
|
9799
9853
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9800
9854
|
const result = CopilotSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9830,7 +9884,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9830
9884
|
};
|
|
9831
9885
|
|
|
9832
9886
|
// src/features/subagents/cursor-subagent.ts
|
|
9833
|
-
import { join as
|
|
9887
|
+
import { join as join80 } from "path";
|
|
9834
9888
|
import { z as z38 } from "zod/mini";
|
|
9835
9889
|
var CursorSubagentFrontmatterSchema = z38.looseObject({
|
|
9836
9890
|
name: z38.string(),
|
|
@@ -9844,7 +9898,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9844
9898
|
const result = CursorSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9845
9899
|
if (!result.success) {
|
|
9846
9900
|
throw new Error(
|
|
9847
|
-
`Invalid frontmatter in ${
|
|
9901
|
+
`Invalid frontmatter in ${join80(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9848
9902
|
);
|
|
9849
9903
|
}
|
|
9850
9904
|
}
|
|
@@ -9856,7 +9910,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9856
9910
|
}
|
|
9857
9911
|
static getSettablePaths(_options = {}) {
|
|
9858
9912
|
return {
|
|
9859
|
-
relativeDirPath:
|
|
9913
|
+
relativeDirPath: join80(".cursor", "agents")
|
|
9860
9914
|
};
|
|
9861
9915
|
}
|
|
9862
9916
|
getFrontmatter() {
|
|
@@ -9923,7 +9977,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9923
9977
|
return {
|
|
9924
9978
|
success: false,
|
|
9925
9979
|
error: new Error(
|
|
9926
|
-
`Invalid frontmatter in ${
|
|
9980
|
+
`Invalid frontmatter in ${join80(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9927
9981
|
)
|
|
9928
9982
|
};
|
|
9929
9983
|
}
|
|
@@ -9941,7 +9995,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9941
9995
|
global = false
|
|
9942
9996
|
}) {
|
|
9943
9997
|
const paths = this.getSettablePaths({ global });
|
|
9944
|
-
const filePath =
|
|
9998
|
+
const filePath = join80(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9945
9999
|
const fileContent = await readFileContent(filePath);
|
|
9946
10000
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9947
10001
|
const result = CursorSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9977,7 +10031,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9977
10031
|
};
|
|
9978
10032
|
|
|
9979
10033
|
// src/features/subagents/kiro-subagent.ts
|
|
9980
|
-
import { join as
|
|
10034
|
+
import { join as join81 } from "path";
|
|
9981
10035
|
import { z as z39 } from "zod/mini";
|
|
9982
10036
|
var KiroCliSubagentJsonSchema = z39.looseObject({
|
|
9983
10037
|
name: z39.string(),
|
|
@@ -10005,7 +10059,7 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10005
10059
|
}
|
|
10006
10060
|
static getSettablePaths(_options = {}) {
|
|
10007
10061
|
return {
|
|
10008
|
-
relativeDirPath:
|
|
10062
|
+
relativeDirPath: join81(".kiro", "agents")
|
|
10009
10063
|
};
|
|
10010
10064
|
}
|
|
10011
10065
|
getBody() {
|
|
@@ -10085,7 +10139,7 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10085
10139
|
global = false
|
|
10086
10140
|
}) {
|
|
10087
10141
|
const paths = this.getSettablePaths({ global });
|
|
10088
|
-
const filePath =
|
|
10142
|
+
const filePath = join81(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
10089
10143
|
const fileContent = await readFileContent(filePath);
|
|
10090
10144
|
return new _KiroSubagent({
|
|
10091
10145
|
baseDir,
|
|
@@ -10114,11 +10168,11 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10114
10168
|
};
|
|
10115
10169
|
|
|
10116
10170
|
// src/features/subagents/opencode-subagent.ts
|
|
10117
|
-
import { basename as
|
|
10171
|
+
import { basename as basename22, join as join82 } from "path";
|
|
10118
10172
|
import { z as z40 } from "zod/mini";
|
|
10119
10173
|
var OpenCodeSubagentFrontmatterSchema = z40.looseObject({
|
|
10120
10174
|
description: z40.string(),
|
|
10121
|
-
mode: z40.
|
|
10175
|
+
mode: z40.optional(z40._default(z40.string(), "subagent")),
|
|
10122
10176
|
name: z40.optional(z40.string())
|
|
10123
10177
|
});
|
|
10124
10178
|
var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
@@ -10129,7 +10183,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10129
10183
|
const result = OpenCodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
10130
10184
|
if (!result.success) {
|
|
10131
10185
|
throw new Error(
|
|
10132
|
-
`Invalid frontmatter in ${
|
|
10186
|
+
`Invalid frontmatter in ${join82(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
10133
10187
|
);
|
|
10134
10188
|
}
|
|
10135
10189
|
}
|
|
@@ -10143,7 +10197,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10143
10197
|
global = false
|
|
10144
10198
|
} = {}) {
|
|
10145
10199
|
return {
|
|
10146
|
-
relativeDirPath: global ?
|
|
10200
|
+
relativeDirPath: global ? join82(".config", "opencode", "agent") : join82(".opencode", "agent")
|
|
10147
10201
|
};
|
|
10148
10202
|
}
|
|
10149
10203
|
getFrontmatter() {
|
|
@@ -10156,7 +10210,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10156
10210
|
const { description, mode, name, ...opencodeSection } = this.frontmatter;
|
|
10157
10211
|
const rulesyncFrontmatter = {
|
|
10158
10212
|
targets: ["*"],
|
|
10159
|
-
name: name ??
|
|
10213
|
+
name: name ?? basename22(this.getRelativeFilePath(), ".md"),
|
|
10160
10214
|
description,
|
|
10161
10215
|
opencode: { mode, ...opencodeSection }
|
|
10162
10216
|
};
|
|
@@ -10209,7 +10263,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10209
10263
|
return {
|
|
10210
10264
|
success: false,
|
|
10211
10265
|
error: new Error(
|
|
10212
|
-
`Invalid frontmatter in ${
|
|
10266
|
+
`Invalid frontmatter in ${join82(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
10213
10267
|
)
|
|
10214
10268
|
};
|
|
10215
10269
|
}
|
|
@@ -10226,7 +10280,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10226
10280
|
global = false
|
|
10227
10281
|
}) {
|
|
10228
10282
|
const paths = this.getSettablePaths({ global });
|
|
10229
|
-
const filePath =
|
|
10283
|
+
const filePath = join82(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
10230
10284
|
const fileContent = await readFileContent(filePath);
|
|
10231
10285
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
10232
10286
|
const result = OpenCodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -10437,7 +10491,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10437
10491
|
* Load and parse rulesync subagent files from .rulesync/subagents/ directory
|
|
10438
10492
|
*/
|
|
10439
10493
|
async loadRulesyncFiles() {
|
|
10440
|
-
const subagentsDir =
|
|
10494
|
+
const subagentsDir = join83(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
|
|
10441
10495
|
const dirExists = await directoryExists(subagentsDir);
|
|
10442
10496
|
if (!dirExists) {
|
|
10443
10497
|
logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
|
|
@@ -10449,10 +10503,10 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10449
10503
|
logger.debug(`No markdown files found in rulesync subagents directory: ${subagentsDir}`);
|
|
10450
10504
|
return [];
|
|
10451
10505
|
}
|
|
10452
|
-
logger.
|
|
10506
|
+
logger.debug(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
|
|
10453
10507
|
const rulesyncSubagents = [];
|
|
10454
10508
|
for (const mdFile of mdFiles) {
|
|
10455
|
-
const filepath =
|
|
10509
|
+
const filepath = join83(subagentsDir, mdFile);
|
|
10456
10510
|
try {
|
|
10457
10511
|
const rulesyncSubagent = await RulesyncSubagent.fromFile({
|
|
10458
10512
|
relativeFilePath: mdFile,
|
|
@@ -10461,7 +10515,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10461
10515
|
rulesyncSubagents.push(rulesyncSubagent);
|
|
10462
10516
|
logger.debug(`Successfully loaded subagent: ${mdFile}`);
|
|
10463
10517
|
} catch (error) {
|
|
10464
|
-
logger.warn(`Failed to load subagent file ${filepath}
|
|
10518
|
+
logger.warn(`Failed to load subagent file ${filepath}: ${formatError(error)}`);
|
|
10465
10519
|
continue;
|
|
10466
10520
|
}
|
|
10467
10521
|
}
|
|
@@ -10469,7 +10523,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10469
10523
|
logger.debug(`No valid subagents found in ${subagentsDir}`);
|
|
10470
10524
|
return [];
|
|
10471
10525
|
}
|
|
10472
|
-
logger.
|
|
10526
|
+
logger.debug(`Successfully loaded ${rulesyncSubagents.length} rulesync subagents`);
|
|
10473
10527
|
return rulesyncSubagents;
|
|
10474
10528
|
}
|
|
10475
10529
|
/**
|
|
@@ -10482,30 +10536,32 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10482
10536
|
const factory = this.getFactory(this.toolTarget);
|
|
10483
10537
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
10484
10538
|
const subagentFilePaths = await findFilesByGlobs(
|
|
10485
|
-
|
|
10539
|
+
join83(this.baseDir, paths.relativeDirPath, factory.meta.filePattern)
|
|
10486
10540
|
);
|
|
10487
10541
|
if (forDeletion) {
|
|
10488
10542
|
const toolSubagents2 = subagentFilePaths.map(
|
|
10489
10543
|
(path4) => factory.class.forDeletion({
|
|
10490
10544
|
baseDir: this.baseDir,
|
|
10491
10545
|
relativeDirPath: paths.relativeDirPath,
|
|
10492
|
-
relativeFilePath:
|
|
10546
|
+
relativeFilePath: basename23(path4),
|
|
10493
10547
|
global: this.global
|
|
10494
10548
|
})
|
|
10495
10549
|
).filter((subagent) => subagent.isDeletable());
|
|
10496
|
-
logger.
|
|
10550
|
+
logger.debug(
|
|
10551
|
+
`Successfully loaded ${toolSubagents2.length} ${paths.relativeDirPath} subagents`
|
|
10552
|
+
);
|
|
10497
10553
|
return toolSubagents2;
|
|
10498
10554
|
}
|
|
10499
10555
|
const toolSubagents = await Promise.all(
|
|
10500
10556
|
subagentFilePaths.map(
|
|
10501
10557
|
(path4) => factory.class.fromFile({
|
|
10502
10558
|
baseDir: this.baseDir,
|
|
10503
|
-
relativeFilePath:
|
|
10559
|
+
relativeFilePath: basename23(path4),
|
|
10504
10560
|
global: this.global
|
|
10505
10561
|
})
|
|
10506
10562
|
)
|
|
10507
10563
|
);
|
|
10508
|
-
logger.
|
|
10564
|
+
logger.debug(`Successfully loaded ${toolSubagents.length} ${paths.relativeDirPath} subagents`);
|
|
10509
10565
|
return toolSubagents;
|
|
10510
10566
|
}
|
|
10511
10567
|
/**
|
|
@@ -10545,13 +10601,13 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10545
10601
|
};
|
|
10546
10602
|
|
|
10547
10603
|
// src/features/rules/agentsmd-rule.ts
|
|
10548
|
-
import { join as
|
|
10604
|
+
import { join as join86 } from "path";
|
|
10549
10605
|
|
|
10550
10606
|
// src/features/rules/tool-rule.ts
|
|
10551
|
-
import { join as
|
|
10607
|
+
import { join as join85 } from "path";
|
|
10552
10608
|
|
|
10553
10609
|
// src/features/rules/rulesync-rule.ts
|
|
10554
|
-
import { join as
|
|
10610
|
+
import { join as join84 } from "path";
|
|
10555
10611
|
import { z as z42 } from "zod/mini";
|
|
10556
10612
|
var RulesyncRuleFrontmatterSchema = z42.object({
|
|
10557
10613
|
root: z42.optional(z42.boolean()),
|
|
@@ -10598,7 +10654,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10598
10654
|
const parseResult = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
|
|
10599
10655
|
if (!parseResult.success && rest.validate !== false) {
|
|
10600
10656
|
throw new Error(
|
|
10601
|
-
`Invalid frontmatter in ${
|
|
10657
|
+
`Invalid frontmatter in ${join84(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`
|
|
10602
10658
|
);
|
|
10603
10659
|
}
|
|
10604
10660
|
const parsedFrontmatter = parseResult.success ? parseResult.data : { ...frontmatter, targets: frontmatter.targets ?? ["*"] };
|
|
@@ -10633,7 +10689,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10633
10689
|
return {
|
|
10634
10690
|
success: false,
|
|
10635
10691
|
error: new Error(
|
|
10636
|
-
`Invalid frontmatter in ${
|
|
10692
|
+
`Invalid frontmatter in ${join84(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
10637
10693
|
)
|
|
10638
10694
|
};
|
|
10639
10695
|
}
|
|
@@ -10642,7 +10698,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10642
10698
|
relativeFilePath,
|
|
10643
10699
|
validate = true
|
|
10644
10700
|
}) {
|
|
10645
|
-
const filePath =
|
|
10701
|
+
const filePath = join84(
|
|
10646
10702
|
process.cwd(),
|
|
10647
10703
|
this.getSettablePaths().recommended.relativeDirPath,
|
|
10648
10704
|
relativeFilePath
|
|
@@ -10726,7 +10782,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10726
10782
|
};
|
|
10727
10783
|
}
|
|
10728
10784
|
if (!nonRootPath) {
|
|
10729
|
-
throw new Error(
|
|
10785
|
+
throw new Error(`nonRootPath is not set for ${rulesyncRule.getRelativeFilePath()}`);
|
|
10730
10786
|
}
|
|
10731
10787
|
return {
|
|
10732
10788
|
baseDir,
|
|
@@ -10744,7 +10800,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10744
10800
|
rulesyncRule,
|
|
10745
10801
|
validate = true,
|
|
10746
10802
|
rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
|
|
10747
|
-
nonRootPath = { relativeDirPath:
|
|
10803
|
+
nonRootPath = { relativeDirPath: join85(".agents", "memories") }
|
|
10748
10804
|
}) {
|
|
10749
10805
|
const params = this.buildToolRuleParamsDefault({
|
|
10750
10806
|
baseDir,
|
|
@@ -10755,7 +10811,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10755
10811
|
});
|
|
10756
10812
|
const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
|
|
10757
10813
|
if (!rulesyncFrontmatter.root && rulesyncFrontmatter.agentsmd?.subprojectPath) {
|
|
10758
|
-
params.relativeDirPath =
|
|
10814
|
+
params.relativeDirPath = join85(rulesyncFrontmatter.agentsmd.subprojectPath);
|
|
10759
10815
|
params.relativeFilePath = "AGENTS.md";
|
|
10760
10816
|
}
|
|
10761
10817
|
return params;
|
|
@@ -10804,7 +10860,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10804
10860
|
}
|
|
10805
10861
|
};
|
|
10806
10862
|
function buildToolPath(toolDir, subDir, excludeToolDir) {
|
|
10807
|
-
return excludeToolDir ? subDir :
|
|
10863
|
+
return excludeToolDir ? subDir : join85(toolDir, subDir);
|
|
10808
10864
|
}
|
|
10809
10865
|
|
|
10810
10866
|
// src/features/rules/agentsmd-rule.ts
|
|
@@ -10833,8 +10889,8 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
|
|
|
10833
10889
|
validate = true
|
|
10834
10890
|
}) {
|
|
10835
10891
|
const isRoot = relativeFilePath === "AGENTS.md";
|
|
10836
|
-
const relativePath = isRoot ? "AGENTS.md" :
|
|
10837
|
-
const fileContent = await readFileContent(
|
|
10892
|
+
const relativePath = isRoot ? "AGENTS.md" : join86(".agents", "memories", relativeFilePath);
|
|
10893
|
+
const fileContent = await readFileContent(join86(baseDir, relativePath));
|
|
10838
10894
|
return new _AgentsMdRule({
|
|
10839
10895
|
baseDir,
|
|
10840
10896
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -10889,7 +10945,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
|
|
|
10889
10945
|
};
|
|
10890
10946
|
|
|
10891
10947
|
// src/features/rules/antigravity-rule.ts
|
|
10892
|
-
import { join as
|
|
10948
|
+
import { join as join87 } from "path";
|
|
10893
10949
|
import { z as z43 } from "zod/mini";
|
|
10894
10950
|
var AntigravityRuleFrontmatterSchema = z43.looseObject({
|
|
10895
10951
|
trigger: z43.optional(
|
|
@@ -11048,7 +11104,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11048
11104
|
const result = AntigravityRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11049
11105
|
if (!result.success) {
|
|
11050
11106
|
throw new Error(
|
|
11051
|
-
`Invalid frontmatter in ${
|
|
11107
|
+
`Invalid frontmatter in ${join87(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11052
11108
|
);
|
|
11053
11109
|
}
|
|
11054
11110
|
}
|
|
@@ -11072,7 +11128,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11072
11128
|
relativeFilePath,
|
|
11073
11129
|
validate = true
|
|
11074
11130
|
}) {
|
|
11075
|
-
const filePath =
|
|
11131
|
+
const filePath = join87(
|
|
11076
11132
|
baseDir,
|
|
11077
11133
|
this.getSettablePaths().nonRoot.relativeDirPath,
|
|
11078
11134
|
relativeFilePath
|
|
@@ -11213,7 +11269,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11213
11269
|
};
|
|
11214
11270
|
|
|
11215
11271
|
// src/features/rules/augmentcode-legacy-rule.ts
|
|
11216
|
-
import { join as
|
|
11272
|
+
import { join as join88 } from "path";
|
|
11217
11273
|
var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
11218
11274
|
toRulesyncRule() {
|
|
11219
11275
|
const rulesyncFrontmatter = {
|
|
@@ -11274,8 +11330,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
|
11274
11330
|
}) {
|
|
11275
11331
|
const settablePaths = this.getSettablePaths();
|
|
11276
11332
|
const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
|
|
11277
|
-
const relativePath = isRoot ? settablePaths.root.relativeFilePath :
|
|
11278
|
-
const fileContent = await readFileContent(
|
|
11333
|
+
const relativePath = isRoot ? settablePaths.root.relativeFilePath : join88(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11334
|
+
const fileContent = await readFileContent(join88(baseDir, relativePath));
|
|
11279
11335
|
return new _AugmentcodeLegacyRule({
|
|
11280
11336
|
baseDir,
|
|
11281
11337
|
relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
|
|
@@ -11304,7 +11360,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
|
11304
11360
|
};
|
|
11305
11361
|
|
|
11306
11362
|
// src/features/rules/augmentcode-rule.ts
|
|
11307
|
-
import { join as
|
|
11363
|
+
import { join as join89 } from "path";
|
|
11308
11364
|
var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
11309
11365
|
toRulesyncRule() {
|
|
11310
11366
|
return this.toRulesyncRuleDefault();
|
|
@@ -11336,7 +11392,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
|
11336
11392
|
validate = true
|
|
11337
11393
|
}) {
|
|
11338
11394
|
const fileContent = await readFileContent(
|
|
11339
|
-
|
|
11395
|
+
join89(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
11340
11396
|
);
|
|
11341
11397
|
const { body: content } = parseFrontmatter(fileContent);
|
|
11342
11398
|
return new _AugmentcodeRule({
|
|
@@ -11372,7 +11428,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
|
11372
11428
|
};
|
|
11373
11429
|
|
|
11374
11430
|
// src/features/rules/claudecode-legacy-rule.ts
|
|
11375
|
-
import { join as
|
|
11431
|
+
import { join as join90 } from "path";
|
|
11376
11432
|
var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
11377
11433
|
static getSettablePaths({
|
|
11378
11434
|
global,
|
|
@@ -11407,7 +11463,7 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11407
11463
|
if (isRoot) {
|
|
11408
11464
|
const relativePath2 = paths.root.relativeFilePath;
|
|
11409
11465
|
const fileContent2 = await readFileContent(
|
|
11410
|
-
|
|
11466
|
+
join90(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
11411
11467
|
);
|
|
11412
11468
|
return new _ClaudecodeLegacyRule({
|
|
11413
11469
|
baseDir,
|
|
@@ -11419,10 +11475,10 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11419
11475
|
});
|
|
11420
11476
|
}
|
|
11421
11477
|
if (!paths.nonRoot) {
|
|
11422
|
-
throw new Error(
|
|
11478
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11423
11479
|
}
|
|
11424
|
-
const relativePath =
|
|
11425
|
-
const fileContent = await readFileContent(
|
|
11480
|
+
const relativePath = join90(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11481
|
+
const fileContent = await readFileContent(join90(baseDir, relativePath));
|
|
11426
11482
|
return new _ClaudecodeLegacyRule({
|
|
11427
11483
|
baseDir,
|
|
11428
11484
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -11481,7 +11537,7 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11481
11537
|
};
|
|
11482
11538
|
|
|
11483
11539
|
// src/features/rules/claudecode-rule.ts
|
|
11484
|
-
import { join as
|
|
11540
|
+
import { join as join91 } from "path";
|
|
11485
11541
|
import { z as z44 } from "zod/mini";
|
|
11486
11542
|
var ClaudecodeRuleFrontmatterSchema = z44.object({
|
|
11487
11543
|
paths: z44.optional(z44.array(z44.string()))
|
|
@@ -11516,7 +11572,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11516
11572
|
const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11517
11573
|
if (!result.success) {
|
|
11518
11574
|
throw new Error(
|
|
11519
|
-
`Invalid frontmatter in ${
|
|
11575
|
+
`Invalid frontmatter in ${join91(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11520
11576
|
);
|
|
11521
11577
|
}
|
|
11522
11578
|
}
|
|
@@ -11544,7 +11600,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11544
11600
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
11545
11601
|
if (isRoot) {
|
|
11546
11602
|
const fileContent2 = await readFileContent(
|
|
11547
|
-
|
|
11603
|
+
join91(baseDir, paths.root.relativeDirPath, paths.root.relativeFilePath)
|
|
11548
11604
|
);
|
|
11549
11605
|
return new _ClaudecodeRule({
|
|
11550
11606
|
baseDir,
|
|
@@ -11557,15 +11613,15 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11557
11613
|
});
|
|
11558
11614
|
}
|
|
11559
11615
|
if (!paths.nonRoot) {
|
|
11560
|
-
throw new Error(
|
|
11616
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11561
11617
|
}
|
|
11562
|
-
const relativePath =
|
|
11563
|
-
const fileContent = await readFileContent(
|
|
11618
|
+
const relativePath = join91(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11619
|
+
const fileContent = await readFileContent(join91(baseDir, relativePath));
|
|
11564
11620
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
11565
11621
|
const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11566
11622
|
if (!result.success) {
|
|
11567
11623
|
throw new Error(
|
|
11568
|
-
`Invalid frontmatter in ${
|
|
11624
|
+
`Invalid frontmatter in ${join91(baseDir, relativePath)}: ${formatError(result.error)}`
|
|
11569
11625
|
);
|
|
11570
11626
|
}
|
|
11571
11627
|
return new _ClaudecodeRule({
|
|
@@ -11624,7 +11680,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11624
11680
|
});
|
|
11625
11681
|
}
|
|
11626
11682
|
if (!paths.nonRoot) {
|
|
11627
|
-
throw new Error(
|
|
11683
|
+
throw new Error(`nonRoot path is not set for ${rulesyncRule.getRelativeFilePath()}`);
|
|
11628
11684
|
}
|
|
11629
11685
|
return new _ClaudecodeRule({
|
|
11630
11686
|
baseDir,
|
|
@@ -11672,7 +11728,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11672
11728
|
return {
|
|
11673
11729
|
success: false,
|
|
11674
11730
|
error: new Error(
|
|
11675
|
-
`Invalid frontmatter in ${
|
|
11731
|
+
`Invalid frontmatter in ${join91(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
11676
11732
|
)
|
|
11677
11733
|
};
|
|
11678
11734
|
}
|
|
@@ -11692,7 +11748,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11692
11748
|
};
|
|
11693
11749
|
|
|
11694
11750
|
// src/features/rules/cline-rule.ts
|
|
11695
|
-
import { join as
|
|
11751
|
+
import { join as join92 } from "path";
|
|
11696
11752
|
import { z as z45 } from "zod/mini";
|
|
11697
11753
|
var ClineRuleFrontmatterSchema = z45.object({
|
|
11698
11754
|
description: z45.string()
|
|
@@ -11738,7 +11794,7 @@ var ClineRule = class _ClineRule extends ToolRule {
|
|
|
11738
11794
|
validate = true
|
|
11739
11795
|
}) {
|
|
11740
11796
|
const fileContent = await readFileContent(
|
|
11741
|
-
|
|
11797
|
+
join92(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
11742
11798
|
);
|
|
11743
11799
|
return new _ClineRule({
|
|
11744
11800
|
baseDir,
|
|
@@ -11764,7 +11820,7 @@ var ClineRule = class _ClineRule extends ToolRule {
|
|
|
11764
11820
|
};
|
|
11765
11821
|
|
|
11766
11822
|
// src/features/rules/codexcli-rule.ts
|
|
11767
|
-
import { join as
|
|
11823
|
+
import { join as join93 } from "path";
|
|
11768
11824
|
var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
11769
11825
|
static getSettablePaths({
|
|
11770
11826
|
global,
|
|
@@ -11799,7 +11855,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11799
11855
|
if (isRoot) {
|
|
11800
11856
|
const relativePath2 = paths.root.relativeFilePath;
|
|
11801
11857
|
const fileContent2 = await readFileContent(
|
|
11802
|
-
|
|
11858
|
+
join93(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
11803
11859
|
);
|
|
11804
11860
|
return new _CodexcliRule({
|
|
11805
11861
|
baseDir,
|
|
@@ -11811,10 +11867,10 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11811
11867
|
});
|
|
11812
11868
|
}
|
|
11813
11869
|
if (!paths.nonRoot) {
|
|
11814
|
-
throw new Error(
|
|
11870
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11815
11871
|
}
|
|
11816
|
-
const relativePath =
|
|
11817
|
-
const fileContent = await readFileContent(
|
|
11872
|
+
const relativePath = join93(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11873
|
+
const fileContent = await readFileContent(join93(baseDir, relativePath));
|
|
11818
11874
|
return new _CodexcliRule({
|
|
11819
11875
|
baseDir,
|
|
11820
11876
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -11873,7 +11929,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11873
11929
|
};
|
|
11874
11930
|
|
|
11875
11931
|
// src/features/rules/copilot-rule.ts
|
|
11876
|
-
import { join as
|
|
11932
|
+
import { join as join94 } from "path";
|
|
11877
11933
|
import { z as z46 } from "zod/mini";
|
|
11878
11934
|
var CopilotRuleFrontmatterSchema = z46.object({
|
|
11879
11935
|
description: z46.optional(z46.string()),
|
|
@@ -11899,7 +11955,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
11899
11955
|
const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11900
11956
|
if (!result.success) {
|
|
11901
11957
|
throw new Error(
|
|
11902
|
-
`Invalid frontmatter in ${
|
|
11958
|
+
`Invalid frontmatter in ${join94(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11903
11959
|
);
|
|
11904
11960
|
}
|
|
11905
11961
|
}
|
|
@@ -11981,11 +12037,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
11981
12037
|
validate = true
|
|
11982
12038
|
}) {
|
|
11983
12039
|
const isRoot = relativeFilePath === "copilot-instructions.md";
|
|
11984
|
-
const relativePath = isRoot ?
|
|
12040
|
+
const relativePath = isRoot ? join94(
|
|
11985
12041
|
this.getSettablePaths().root.relativeDirPath,
|
|
11986
12042
|
this.getSettablePaths().root.relativeFilePath
|
|
11987
|
-
) :
|
|
11988
|
-
const fileContent = await readFileContent(
|
|
12043
|
+
) : join94(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
|
|
12044
|
+
const fileContent = await readFileContent(join94(baseDir, relativePath));
|
|
11989
12045
|
if (isRoot) {
|
|
11990
12046
|
return new _CopilotRule({
|
|
11991
12047
|
baseDir,
|
|
@@ -12001,7 +12057,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12001
12057
|
const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12002
12058
|
if (!result.success) {
|
|
12003
12059
|
throw new Error(
|
|
12004
|
-
`Invalid frontmatter in ${
|
|
12060
|
+
`Invalid frontmatter in ${join94(baseDir, relativeFilePath)}: ${formatError(result.error)}`
|
|
12005
12061
|
);
|
|
12006
12062
|
}
|
|
12007
12063
|
return new _CopilotRule({
|
|
@@ -12041,7 +12097,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12041
12097
|
return {
|
|
12042
12098
|
success: false,
|
|
12043
12099
|
error: new Error(
|
|
12044
|
-
`Invalid frontmatter in ${
|
|
12100
|
+
`Invalid frontmatter in ${join94(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
12045
12101
|
)
|
|
12046
12102
|
};
|
|
12047
12103
|
}
|
|
@@ -12061,7 +12117,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12061
12117
|
};
|
|
12062
12118
|
|
|
12063
12119
|
// src/features/rules/cursor-rule.ts
|
|
12064
|
-
import { join as
|
|
12120
|
+
import { join as join95 } from "path";
|
|
12065
12121
|
import { z as z47 } from "zod/mini";
|
|
12066
12122
|
var CursorRuleFrontmatterSchema = z47.object({
|
|
12067
12123
|
description: z47.optional(z47.string()),
|
|
@@ -12083,7 +12139,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12083
12139
|
const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12084
12140
|
if (!result.success) {
|
|
12085
12141
|
throw new Error(
|
|
12086
|
-
`Invalid frontmatter in ${
|
|
12142
|
+
`Invalid frontmatter in ${join95(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
12087
12143
|
);
|
|
12088
12144
|
}
|
|
12089
12145
|
}
|
|
@@ -12200,13 +12256,13 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12200
12256
|
validate = true
|
|
12201
12257
|
}) {
|
|
12202
12258
|
const fileContent = await readFileContent(
|
|
12203
|
-
|
|
12259
|
+
join95(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12204
12260
|
);
|
|
12205
12261
|
const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
|
|
12206
12262
|
const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12207
12263
|
if (!result.success) {
|
|
12208
12264
|
throw new Error(
|
|
12209
|
-
`Invalid frontmatter in ${
|
|
12265
|
+
`Invalid frontmatter in ${join95(baseDir, relativeFilePath)}: ${formatError(result.error)}`
|
|
12210
12266
|
);
|
|
12211
12267
|
}
|
|
12212
12268
|
return new _CursorRule({
|
|
@@ -12243,7 +12299,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12243
12299
|
return {
|
|
12244
12300
|
success: false,
|
|
12245
12301
|
error: new Error(
|
|
12246
|
-
`Invalid frontmatter in ${
|
|
12302
|
+
`Invalid frontmatter in ${join95(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
12247
12303
|
)
|
|
12248
12304
|
};
|
|
12249
12305
|
}
|
|
@@ -12263,7 +12319,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12263
12319
|
};
|
|
12264
12320
|
|
|
12265
12321
|
// src/features/rules/factorydroid-rule.ts
|
|
12266
|
-
import { join as
|
|
12322
|
+
import { join as join96 } from "path";
|
|
12267
12323
|
var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
12268
12324
|
constructor({ fileContent, root, ...rest }) {
|
|
12269
12325
|
super({
|
|
@@ -12303,8 +12359,8 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12303
12359
|
const paths = this.getSettablePaths({ global });
|
|
12304
12360
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
12305
12361
|
if (isRoot) {
|
|
12306
|
-
const relativePath2 =
|
|
12307
|
-
const fileContent2 = await readFileContent(
|
|
12362
|
+
const relativePath2 = join96(paths.root.relativeDirPath, paths.root.relativeFilePath);
|
|
12363
|
+
const fileContent2 = await readFileContent(join96(baseDir, relativePath2));
|
|
12308
12364
|
return new _FactorydroidRule({
|
|
12309
12365
|
baseDir,
|
|
12310
12366
|
relativeDirPath: paths.root.relativeDirPath,
|
|
@@ -12315,10 +12371,10 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12315
12371
|
});
|
|
12316
12372
|
}
|
|
12317
12373
|
if (!paths.nonRoot) {
|
|
12318
|
-
throw new Error(
|
|
12374
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
12319
12375
|
}
|
|
12320
|
-
const relativePath =
|
|
12321
|
-
const fileContent = await readFileContent(
|
|
12376
|
+
const relativePath = join96(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
12377
|
+
const fileContent = await readFileContent(join96(baseDir, relativePath));
|
|
12322
12378
|
return new _FactorydroidRule({
|
|
12323
12379
|
baseDir,
|
|
12324
12380
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -12377,7 +12433,7 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12377
12433
|
};
|
|
12378
12434
|
|
|
12379
12435
|
// src/features/rules/geminicli-rule.ts
|
|
12380
|
-
import { join as
|
|
12436
|
+
import { join as join97 } from "path";
|
|
12381
12437
|
var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
12382
12438
|
static getSettablePaths({
|
|
12383
12439
|
global,
|
|
@@ -12412,7 +12468,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12412
12468
|
if (isRoot) {
|
|
12413
12469
|
const relativePath2 = paths.root.relativeFilePath;
|
|
12414
12470
|
const fileContent2 = await readFileContent(
|
|
12415
|
-
|
|
12471
|
+
join97(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
12416
12472
|
);
|
|
12417
12473
|
return new _GeminiCliRule({
|
|
12418
12474
|
baseDir,
|
|
@@ -12424,10 +12480,10 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12424
12480
|
});
|
|
12425
12481
|
}
|
|
12426
12482
|
if (!paths.nonRoot) {
|
|
12427
|
-
throw new Error(
|
|
12483
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
12428
12484
|
}
|
|
12429
|
-
const relativePath =
|
|
12430
|
-
const fileContent = await readFileContent(
|
|
12485
|
+
const relativePath = join97(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
12486
|
+
const fileContent = await readFileContent(join97(baseDir, relativePath));
|
|
12431
12487
|
return new _GeminiCliRule({
|
|
12432
12488
|
baseDir,
|
|
12433
12489
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -12486,7 +12542,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12486
12542
|
};
|
|
12487
12543
|
|
|
12488
12544
|
// src/features/rules/junie-rule.ts
|
|
12489
|
-
import { join as
|
|
12545
|
+
import { join as join98 } from "path";
|
|
12490
12546
|
var JunieRule = class _JunieRule extends ToolRule {
|
|
12491
12547
|
static getSettablePaths(_options = {}) {
|
|
12492
12548
|
return {
|
|
@@ -12505,8 +12561,8 @@ var JunieRule = class _JunieRule extends ToolRule {
|
|
|
12505
12561
|
validate = true
|
|
12506
12562
|
}) {
|
|
12507
12563
|
const isRoot = relativeFilePath === "guidelines.md";
|
|
12508
|
-
const relativePath = isRoot ? "guidelines.md" :
|
|
12509
|
-
const fileContent = await readFileContent(
|
|
12564
|
+
const relativePath = isRoot ? "guidelines.md" : join98(".junie", "memories", relativeFilePath);
|
|
12565
|
+
const fileContent = await readFileContent(join98(baseDir, relativePath));
|
|
12510
12566
|
return new _JunieRule({
|
|
12511
12567
|
baseDir,
|
|
12512
12568
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12561,7 +12617,7 @@ var JunieRule = class _JunieRule extends ToolRule {
|
|
|
12561
12617
|
};
|
|
12562
12618
|
|
|
12563
12619
|
// src/features/rules/kilo-rule.ts
|
|
12564
|
-
import { join as
|
|
12620
|
+
import { join as join99 } from "path";
|
|
12565
12621
|
var KiloRule = class _KiloRule extends ToolRule {
|
|
12566
12622
|
static getSettablePaths(_options = {}) {
|
|
12567
12623
|
return {
|
|
@@ -12576,7 +12632,7 @@ var KiloRule = class _KiloRule extends ToolRule {
|
|
|
12576
12632
|
validate = true
|
|
12577
12633
|
}) {
|
|
12578
12634
|
const fileContent = await readFileContent(
|
|
12579
|
-
|
|
12635
|
+
join99(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12580
12636
|
);
|
|
12581
12637
|
return new _KiloRule({
|
|
12582
12638
|
baseDir,
|
|
@@ -12628,7 +12684,7 @@ var KiloRule = class _KiloRule extends ToolRule {
|
|
|
12628
12684
|
};
|
|
12629
12685
|
|
|
12630
12686
|
// src/features/rules/kiro-rule.ts
|
|
12631
|
-
import { join as
|
|
12687
|
+
import { join as join100 } from "path";
|
|
12632
12688
|
var KiroRule = class _KiroRule extends ToolRule {
|
|
12633
12689
|
static getSettablePaths(_options = {}) {
|
|
12634
12690
|
return {
|
|
@@ -12643,7 +12699,7 @@ var KiroRule = class _KiroRule extends ToolRule {
|
|
|
12643
12699
|
validate = true
|
|
12644
12700
|
}) {
|
|
12645
12701
|
const fileContent = await readFileContent(
|
|
12646
|
-
|
|
12702
|
+
join100(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12647
12703
|
);
|
|
12648
12704
|
return new _KiroRule({
|
|
12649
12705
|
baseDir,
|
|
@@ -12697,7 +12753,7 @@ var KiroRule = class _KiroRule extends ToolRule {
|
|
|
12697
12753
|
};
|
|
12698
12754
|
|
|
12699
12755
|
// src/features/rules/opencode-rule.ts
|
|
12700
|
-
import { join as
|
|
12756
|
+
import { join as join101 } from "path";
|
|
12701
12757
|
var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
12702
12758
|
static getSettablePaths(_options = {}) {
|
|
12703
12759
|
return {
|
|
@@ -12716,8 +12772,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
|
12716
12772
|
validate = true
|
|
12717
12773
|
}) {
|
|
12718
12774
|
const isRoot = relativeFilePath === "AGENTS.md";
|
|
12719
|
-
const relativePath = isRoot ? "AGENTS.md" :
|
|
12720
|
-
const fileContent = await readFileContent(
|
|
12775
|
+
const relativePath = isRoot ? "AGENTS.md" : join101(".opencode", "memories", relativeFilePath);
|
|
12776
|
+
const fileContent = await readFileContent(join101(baseDir, relativePath));
|
|
12721
12777
|
return new _OpenCodeRule({
|
|
12722
12778
|
baseDir,
|
|
12723
12779
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12772,7 +12828,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
|
12772
12828
|
};
|
|
12773
12829
|
|
|
12774
12830
|
// src/features/rules/qwencode-rule.ts
|
|
12775
|
-
import { join as
|
|
12831
|
+
import { join as join102 } from "path";
|
|
12776
12832
|
var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
12777
12833
|
static getSettablePaths(_options = {}) {
|
|
12778
12834
|
return {
|
|
@@ -12791,8 +12847,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
|
12791
12847
|
validate = true
|
|
12792
12848
|
}) {
|
|
12793
12849
|
const isRoot = relativeFilePath === "QWEN.md";
|
|
12794
|
-
const relativePath = isRoot ? "QWEN.md" :
|
|
12795
|
-
const fileContent = await readFileContent(
|
|
12850
|
+
const relativePath = isRoot ? "QWEN.md" : join102(".qwen", "memories", relativeFilePath);
|
|
12851
|
+
const fileContent = await readFileContent(join102(baseDir, relativePath));
|
|
12796
12852
|
return new _QwencodeRule({
|
|
12797
12853
|
baseDir,
|
|
12798
12854
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12844,7 +12900,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
|
12844
12900
|
};
|
|
12845
12901
|
|
|
12846
12902
|
// src/features/rules/replit-rule.ts
|
|
12847
|
-
import { join as
|
|
12903
|
+
import { join as join103 } from "path";
|
|
12848
12904
|
var ReplitRule = class _ReplitRule extends ToolRule {
|
|
12849
12905
|
static getSettablePaths(_options = {}) {
|
|
12850
12906
|
return {
|
|
@@ -12862,11 +12918,11 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12862
12918
|
const paths = this.getSettablePaths();
|
|
12863
12919
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
12864
12920
|
if (!isRoot) {
|
|
12865
|
-
throw new Error(
|
|
12921
|
+
throw new Error(`ReplitRule only supports root rules: ${relativeFilePath}`);
|
|
12866
12922
|
}
|
|
12867
12923
|
const relativePath = paths.root.relativeFilePath;
|
|
12868
12924
|
const fileContent = await readFileContent(
|
|
12869
|
-
|
|
12925
|
+
join103(baseDir, paths.root.relativeDirPath, relativePath)
|
|
12870
12926
|
);
|
|
12871
12927
|
return new _ReplitRule({
|
|
12872
12928
|
baseDir,
|
|
@@ -12885,7 +12941,7 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12885
12941
|
const paths = this.getSettablePaths();
|
|
12886
12942
|
const isRoot = rulesyncRule.getFrontmatter().root ?? false;
|
|
12887
12943
|
if (!isRoot) {
|
|
12888
|
-
throw new Error(
|
|
12944
|
+
throw new Error(`ReplitRule only supports root rules: ${rulesyncRule.getRelativeFilePath()}`);
|
|
12889
12945
|
}
|
|
12890
12946
|
return new _ReplitRule(
|
|
12891
12947
|
this.buildToolRuleParamsDefault({
|
|
@@ -12932,7 +12988,7 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12932
12988
|
};
|
|
12933
12989
|
|
|
12934
12990
|
// src/features/rules/roo-rule.ts
|
|
12935
|
-
import { join as
|
|
12991
|
+
import { join as join104 } from "path";
|
|
12936
12992
|
var RooRule = class _RooRule extends ToolRule {
|
|
12937
12993
|
static getSettablePaths(_options = {}) {
|
|
12938
12994
|
return {
|
|
@@ -12947,7 +13003,7 @@ var RooRule = class _RooRule extends ToolRule {
|
|
|
12947
13003
|
validate = true
|
|
12948
13004
|
}) {
|
|
12949
13005
|
const fileContent = await readFileContent(
|
|
12950
|
-
|
|
13006
|
+
join104(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12951
13007
|
);
|
|
12952
13008
|
return new _RooRule({
|
|
12953
13009
|
baseDir,
|
|
@@ -13016,7 +13072,7 @@ var RooRule = class _RooRule extends ToolRule {
|
|
|
13016
13072
|
};
|
|
13017
13073
|
|
|
13018
13074
|
// src/features/rules/warp-rule.ts
|
|
13019
|
-
import { join as
|
|
13075
|
+
import { join as join105 } from "path";
|
|
13020
13076
|
var WarpRule = class _WarpRule extends ToolRule {
|
|
13021
13077
|
constructor({ fileContent, root, ...rest }) {
|
|
13022
13078
|
super({
|
|
@@ -13042,8 +13098,8 @@ var WarpRule = class _WarpRule extends ToolRule {
|
|
|
13042
13098
|
validate = true
|
|
13043
13099
|
}) {
|
|
13044
13100
|
const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
|
|
13045
|
-
const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath :
|
|
13046
|
-
const fileContent = await readFileContent(
|
|
13101
|
+
const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : join105(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
|
|
13102
|
+
const fileContent = await readFileContent(join105(baseDir, relativePath));
|
|
13047
13103
|
return new _WarpRule({
|
|
13048
13104
|
baseDir,
|
|
13049
13105
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
|
|
@@ -13098,7 +13154,7 @@ var WarpRule = class _WarpRule extends ToolRule {
|
|
|
13098
13154
|
};
|
|
13099
13155
|
|
|
13100
13156
|
// src/features/rules/windsurf-rule.ts
|
|
13101
|
-
import { join as
|
|
13157
|
+
import { join as join106 } from "path";
|
|
13102
13158
|
var WindsurfRule = class _WindsurfRule extends ToolRule {
|
|
13103
13159
|
static getSettablePaths(_options = {}) {
|
|
13104
13160
|
return {
|
|
@@ -13113,7 +13169,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
|
|
|
13113
13169
|
validate = true
|
|
13114
13170
|
}) {
|
|
13115
13171
|
const fileContent = await readFileContent(
|
|
13116
|
-
|
|
13172
|
+
join106(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
13117
13173
|
);
|
|
13118
13174
|
return new _WindsurfRule({
|
|
13119
13175
|
baseDir,
|
|
@@ -13499,7 +13555,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13499
13555
|
}).relativeDirPath;
|
|
13500
13556
|
return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
|
|
13501
13557
|
const frontmatter = skill.getFrontmatter();
|
|
13502
|
-
const relativePath =
|
|
13558
|
+
const relativePath = join107(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
|
|
13503
13559
|
return {
|
|
13504
13560
|
name: frontmatter.name,
|
|
13505
13561
|
description: frontmatter.description,
|
|
@@ -13610,8 +13666,8 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13610
13666
|
* Load and parse rulesync rule files from .rulesync/rules/ directory
|
|
13611
13667
|
*/
|
|
13612
13668
|
async loadRulesyncFiles() {
|
|
13613
|
-
const rulesyncBaseDir =
|
|
13614
|
-
const files = await findFilesByGlobs(
|
|
13669
|
+
const rulesyncBaseDir = join107(this.baseDir, RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
13670
|
+
const files = await findFilesByGlobs(join107(rulesyncBaseDir, "**", "*.md"));
|
|
13615
13671
|
logger.debug(`Found ${files.length} rulesync files`);
|
|
13616
13672
|
const rulesyncRules = await Promise.all(
|
|
13617
13673
|
files.map((file) => {
|
|
@@ -13624,7 +13680,9 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13624
13680
|
);
|
|
13625
13681
|
const rootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().root);
|
|
13626
13682
|
if (rootRules.length > 1) {
|
|
13627
|
-
throw new Error(
|
|
13683
|
+
throw new Error(
|
|
13684
|
+
`Multiple root rulesync rules found: ${rootRules.map((r) => join107(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13685
|
+
);
|
|
13628
13686
|
}
|
|
13629
13687
|
if (rootRules.length === 0 && rulesyncRules.length > 0) {
|
|
13630
13688
|
logger.warn(
|
|
@@ -13633,21 +13691,25 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13633
13691
|
}
|
|
13634
13692
|
const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
|
|
13635
13693
|
if (localRootRules.length > 1) {
|
|
13636
|
-
throw new Error(
|
|
13694
|
+
throw new Error(
|
|
13695
|
+
`Multiple localRoot rules found: ${localRootRules.map((r) => join107(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}. Only one rule can have localRoot: true`
|
|
13696
|
+
);
|
|
13637
13697
|
}
|
|
13638
13698
|
if (localRootRules.length > 0 && rootRules.length === 0) {
|
|
13639
|
-
throw new Error(
|
|
13699
|
+
throw new Error(
|
|
13700
|
+
`localRoot: true requires a root: true rule to exist (found in ${localRootRules.map((r) => join107(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")})`
|
|
13701
|
+
);
|
|
13640
13702
|
}
|
|
13641
13703
|
if (this.global) {
|
|
13642
13704
|
const nonRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().root);
|
|
13643
13705
|
if (nonRootRules.length > 0) {
|
|
13644
13706
|
logger.warn(
|
|
13645
|
-
`${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them`
|
|
13707
|
+
`${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them: ${nonRootRules.map((r) => join107(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13646
13708
|
);
|
|
13647
13709
|
}
|
|
13648
13710
|
if (localRootRules.length > 0) {
|
|
13649
13711
|
logger.warn(
|
|
13650
|
-
`${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them`
|
|
13712
|
+
`${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them: ${localRootRules.map((r) => join107(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13651
13713
|
);
|
|
13652
13714
|
}
|
|
13653
13715
|
return rootRules;
|
|
@@ -13669,7 +13731,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13669
13731
|
return [];
|
|
13670
13732
|
}
|
|
13671
13733
|
const rootFilePaths = await findFilesByGlobs(
|
|
13672
|
-
|
|
13734
|
+
join107(
|
|
13673
13735
|
this.baseDir,
|
|
13674
13736
|
settablePaths.root.relativeDirPath ?? ".",
|
|
13675
13737
|
settablePaths.root.relativeFilePath
|
|
@@ -13680,7 +13742,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13680
13742
|
(filePath) => factory.class.forDeletion({
|
|
13681
13743
|
baseDir: this.baseDir,
|
|
13682
13744
|
relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
|
|
13683
|
-
relativeFilePath:
|
|
13745
|
+
relativeFilePath: basename24(filePath),
|
|
13684
13746
|
global: this.global
|
|
13685
13747
|
})
|
|
13686
13748
|
).filter((rule) => rule.isDeletable());
|
|
@@ -13689,7 +13751,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13689
13751
|
rootFilePaths.map(
|
|
13690
13752
|
(filePath) => factory.class.fromFile({
|
|
13691
13753
|
baseDir: this.baseDir,
|
|
13692
|
-
relativeFilePath:
|
|
13754
|
+
relativeFilePath: basename24(filePath),
|
|
13693
13755
|
global: this.global
|
|
13694
13756
|
})
|
|
13695
13757
|
)
|
|
@@ -13707,13 +13769,13 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13707
13769
|
return [];
|
|
13708
13770
|
}
|
|
13709
13771
|
const localRootFilePaths = await findFilesByGlobs(
|
|
13710
|
-
|
|
13772
|
+
join107(this.baseDir, settablePaths.root.relativeDirPath ?? ".", "CLAUDE.local.md")
|
|
13711
13773
|
);
|
|
13712
13774
|
return localRootFilePaths.map(
|
|
13713
13775
|
(filePath) => factory.class.forDeletion({
|
|
13714
13776
|
baseDir: this.baseDir,
|
|
13715
13777
|
relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
|
|
13716
|
-
relativeFilePath:
|
|
13778
|
+
relativeFilePath: basename24(filePath),
|
|
13717
13779
|
global: this.global
|
|
13718
13780
|
})
|
|
13719
13781
|
).filter((rule) => rule.isDeletable());
|
|
@@ -13723,9 +13785,9 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13723
13785
|
if (!settablePaths.nonRoot) {
|
|
13724
13786
|
return [];
|
|
13725
13787
|
}
|
|
13726
|
-
const nonRootBaseDir =
|
|
13788
|
+
const nonRootBaseDir = join107(this.baseDir, settablePaths.nonRoot.relativeDirPath);
|
|
13727
13789
|
const nonRootFilePaths = await findFilesByGlobs(
|
|
13728
|
-
|
|
13790
|
+
join107(nonRootBaseDir, "**", `*.${factory.meta.extension}`)
|
|
13729
13791
|
);
|
|
13730
13792
|
if (forDeletion) {
|
|
13731
13793
|
return nonRootFilePaths.map((filePath) => {
|
|
@@ -13757,7 +13819,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13757
13819
|
logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
|
|
13758
13820
|
return [...rootToolRules, ...localRootToolRules, ...nonRootToolRules];
|
|
13759
13821
|
} catch (error) {
|
|
13760
|
-
logger.error(`Failed to load tool files: ${formatError(error)}`);
|
|
13822
|
+
logger.error(`Failed to load tool files for ${this.toolTarget}: ${formatError(error)}`);
|
|
13761
13823
|
return [];
|
|
13762
13824
|
}
|
|
13763
13825
|
}
|
|
@@ -13854,14 +13916,14 @@ s/<command> [arguments]
|
|
|
13854
13916
|
This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
|
|
13855
13917
|
The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
|
|
13856
13918
|
|
|
13857
|
-
When users call a custom slash command, you have to look for the markdown file, \`${
|
|
13919
|
+
When users call a custom slash command, you have to look for the markdown file, \`${join107(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
|
|
13858
13920
|
const subagentsSection = subagents ? `## Simulated Subagents
|
|
13859
13921
|
|
|
13860
13922
|
Simulated subagents are specialized AI assistants that can be invoked to handle specific types of tasks. In this case, it can be appear something like custom slash commands simply. Simulated subagents can be called by custom slash commands.
|
|
13861
13923
|
|
|
13862
|
-
When users call a simulated subagent, it will look for the corresponding markdown file, \`${
|
|
13924
|
+
When users call a simulated subagent, it will look for the corresponding markdown file, \`${join107(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
|
|
13863
13925
|
|
|
13864
|
-
For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${
|
|
13926
|
+
For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${join107(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
|
|
13865
13927
|
const skillsSection = skills ? this.generateSkillsSection(skills) : "";
|
|
13866
13928
|
const result = [
|
|
13867
13929
|
overview,
|
|
@@ -13888,61 +13950,56 @@ ${toonContent}`;
|
|
|
13888
13950
|
}
|
|
13889
13951
|
};
|
|
13890
13952
|
|
|
13891
|
-
// src/types/git-provider.ts
|
|
13892
|
-
import { z as z49 } from "zod/mini";
|
|
13893
|
-
var ALL_GIT_PROVIDERS = ["github", "gitlab"];
|
|
13894
|
-
var GitProviderSchema = z49.enum(ALL_GIT_PROVIDERS);
|
|
13895
|
-
|
|
13896
13953
|
// src/lib/github-client.ts
|
|
13897
13954
|
import { RequestError } from "@octokit/request-error";
|
|
13898
13955
|
import { Octokit } from "@octokit/rest";
|
|
13899
13956
|
|
|
13900
13957
|
// src/types/fetch.ts
|
|
13901
|
-
import { z as
|
|
13958
|
+
import { z as z50 } from "zod/mini";
|
|
13902
13959
|
|
|
13903
13960
|
// src/types/fetch-targets.ts
|
|
13904
|
-
import { z as
|
|
13961
|
+
import { z as z49 } from "zod/mini";
|
|
13905
13962
|
var ALL_FETCH_TARGETS = ["rulesync", ...ALL_TOOL_TARGETS];
|
|
13906
|
-
var FetchTargetSchema =
|
|
13963
|
+
var FetchTargetSchema = z49.enum(ALL_FETCH_TARGETS);
|
|
13907
13964
|
|
|
13908
13965
|
// src/types/fetch.ts
|
|
13909
|
-
var ConflictStrategySchema =
|
|
13910
|
-
var GitHubFileTypeSchema =
|
|
13911
|
-
var GitHubFileEntrySchema =
|
|
13912
|
-
name:
|
|
13913
|
-
path:
|
|
13914
|
-
sha:
|
|
13915
|
-
size:
|
|
13966
|
+
var ConflictStrategySchema = z50.enum(["skip", "overwrite"]);
|
|
13967
|
+
var GitHubFileTypeSchema = z50.enum(["file", "dir", "symlink", "submodule"]);
|
|
13968
|
+
var GitHubFileEntrySchema = z50.looseObject({
|
|
13969
|
+
name: z50.string(),
|
|
13970
|
+
path: z50.string(),
|
|
13971
|
+
sha: z50.string(),
|
|
13972
|
+
size: z50.number(),
|
|
13916
13973
|
type: GitHubFileTypeSchema,
|
|
13917
|
-
download_url:
|
|
13974
|
+
download_url: z50.nullable(z50.string())
|
|
13918
13975
|
});
|
|
13919
|
-
var FetchOptionsSchema =
|
|
13920
|
-
target:
|
|
13921
|
-
features:
|
|
13922
|
-
ref:
|
|
13923
|
-
path:
|
|
13924
|
-
output:
|
|
13925
|
-
conflict:
|
|
13926
|
-
token:
|
|
13927
|
-
verbose:
|
|
13928
|
-
silent:
|
|
13976
|
+
var FetchOptionsSchema = z50.looseObject({
|
|
13977
|
+
target: z50.optional(FetchTargetSchema),
|
|
13978
|
+
features: z50.optional(z50.array(z50.enum(ALL_FEATURES_WITH_WILDCARD))),
|
|
13979
|
+
ref: z50.optional(z50.string()),
|
|
13980
|
+
path: z50.optional(z50.string()),
|
|
13981
|
+
output: z50.optional(z50.string()),
|
|
13982
|
+
conflict: z50.optional(ConflictStrategySchema),
|
|
13983
|
+
token: z50.optional(z50.string()),
|
|
13984
|
+
verbose: z50.optional(z50.boolean()),
|
|
13985
|
+
silent: z50.optional(z50.boolean())
|
|
13929
13986
|
});
|
|
13930
|
-
var FetchFileStatusSchema =
|
|
13931
|
-
var GitHubRepoInfoSchema =
|
|
13932
|
-
default_branch:
|
|
13933
|
-
private:
|
|
13987
|
+
var FetchFileStatusSchema = z50.enum(["created", "overwritten", "skipped"]);
|
|
13988
|
+
var GitHubRepoInfoSchema = z50.looseObject({
|
|
13989
|
+
default_branch: z50.string(),
|
|
13990
|
+
private: z50.boolean()
|
|
13934
13991
|
});
|
|
13935
|
-
var GitHubReleaseAssetSchema =
|
|
13936
|
-
name:
|
|
13937
|
-
browser_download_url:
|
|
13938
|
-
size:
|
|
13992
|
+
var GitHubReleaseAssetSchema = z50.looseObject({
|
|
13993
|
+
name: z50.string(),
|
|
13994
|
+
browser_download_url: z50.string(),
|
|
13995
|
+
size: z50.number()
|
|
13939
13996
|
});
|
|
13940
|
-
var GitHubReleaseSchema =
|
|
13941
|
-
tag_name:
|
|
13942
|
-
name:
|
|
13943
|
-
prerelease:
|
|
13944
|
-
draft:
|
|
13945
|
-
assets:
|
|
13997
|
+
var GitHubReleaseSchema = z50.looseObject({
|
|
13998
|
+
tag_name: z50.string(),
|
|
13999
|
+
name: z50.nullable(z50.string()),
|
|
14000
|
+
prerelease: z50.boolean(),
|
|
14001
|
+
draft: z50.boolean(),
|
|
14002
|
+
assets: z50.array(GitHubReleaseAssetSchema)
|
|
13946
14003
|
});
|
|
13947
14004
|
|
|
13948
14005
|
// src/lib/github-client.ts
|
|
@@ -14110,6 +14167,21 @@ var GitHubClient = class {
|
|
|
14110
14167
|
throw error;
|
|
14111
14168
|
}
|
|
14112
14169
|
}
|
|
14170
|
+
/**
|
|
14171
|
+
* Resolve a ref (branch, tag, or SHA) to a full commit SHA.
|
|
14172
|
+
*/
|
|
14173
|
+
async resolveRefToSha(owner, repo, ref) {
|
|
14174
|
+
try {
|
|
14175
|
+
const { data } = await this.octokit.repos.getCommit({
|
|
14176
|
+
owner,
|
|
14177
|
+
repo,
|
|
14178
|
+
ref
|
|
14179
|
+
});
|
|
14180
|
+
return data.sha;
|
|
14181
|
+
} catch (error) {
|
|
14182
|
+
throw this.handleError(error);
|
|
14183
|
+
}
|
|
14184
|
+
}
|
|
14113
14185
|
/**
|
|
14114
14186
|
* Get the latest release from a repository
|
|
14115
14187
|
*/
|
|
@@ -14180,96 +14252,60 @@ var GitHubClient = class {
|
|
|
14180
14252
|
}
|
|
14181
14253
|
};
|
|
14182
14254
|
|
|
14183
|
-
// src/lib/
|
|
14184
|
-
var
|
|
14185
|
-
|
|
14186
|
-
|
|
14187
|
-
|
|
14188
|
-
|
|
14189
|
-
|
|
14190
|
-
|
|
14191
|
-
hooks: [RULESYNC_HOOKS_FILE_NAME]
|
|
14192
|
-
};
|
|
14193
|
-
function isToolTarget(target) {
|
|
14194
|
-
return target !== "rulesync";
|
|
14195
|
-
}
|
|
14196
|
-
function validateFileSize(relativePath, size) {
|
|
14197
|
-
if (size > MAX_FILE_SIZE) {
|
|
14198
|
-
throw new GitHubClientError(
|
|
14199
|
-
`File "${relativePath}" exceeds maximum size limit (${(size / 1024 / 1024).toFixed(2)}MB > ${MAX_FILE_SIZE / 1024 / 1024}MB)`
|
|
14200
|
-
);
|
|
14255
|
+
// src/lib/github-utils.ts
|
|
14256
|
+
var MAX_RECURSION_DEPTH = 15;
|
|
14257
|
+
async function withSemaphore(semaphore, fn) {
|
|
14258
|
+
await semaphore.acquire();
|
|
14259
|
+
try {
|
|
14260
|
+
return await fn();
|
|
14261
|
+
} finally {
|
|
14262
|
+
semaphore.release();
|
|
14201
14263
|
}
|
|
14202
14264
|
}
|
|
14203
|
-
async function
|
|
14204
|
-
const {
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14265
|
+
async function listDirectoryRecursive(params) {
|
|
14266
|
+
const { client, owner, repo, path: path4, ref, depth = 0, semaphore } = params;
|
|
14267
|
+
if (depth > MAX_RECURSION_DEPTH) {
|
|
14268
|
+
throw new Error(
|
|
14269
|
+
`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while listing directory: ${path4}`
|
|
14270
|
+
);
|
|
14209
14271
|
}
|
|
14210
|
-
const
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
|
|
14272
|
+
const entries = await withSemaphore(
|
|
14273
|
+
semaphore,
|
|
14274
|
+
() => client.listDirectory(owner, repo, path4, ref)
|
|
14275
|
+
);
|
|
14276
|
+
const files = [];
|
|
14277
|
+
const directories = [];
|
|
14278
|
+
for (const entry of entries) {
|
|
14279
|
+
if (entry.type === "file") {
|
|
14280
|
+
files.push(entry);
|
|
14281
|
+
} else if (entry.type === "dir") {
|
|
14282
|
+
directories.push(entry);
|
|
14283
|
+
}
|
|
14216
14284
|
}
|
|
14217
|
-
|
|
14218
|
-
|
|
14219
|
-
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14223
|
-
|
|
14224
|
-
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
createProcessor: () => new CommandsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14232
|
-
},
|
|
14233
|
-
{
|
|
14234
|
-
feature: "subagents",
|
|
14235
|
-
getTargets: () => SubagentsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14236
|
-
createProcessor: () => new SubagentsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14237
|
-
},
|
|
14238
|
-
{
|
|
14239
|
-
feature: "ignore",
|
|
14240
|
-
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
14241
|
-
createProcessor: () => new IgnoreProcessor({ baseDir: tempDir, toolTarget: target })
|
|
14242
|
-
},
|
|
14243
|
-
{
|
|
14244
|
-
feature: "mcp",
|
|
14245
|
-
getTargets: () => McpProcessor.getToolTargets({ global: false }),
|
|
14246
|
-
createProcessor: () => new McpProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14247
|
-
},
|
|
14248
|
-
{
|
|
14249
|
-
feature: "hooks",
|
|
14250
|
-
getTargets: () => HooksProcessor.getToolTargets({ global: false }),
|
|
14251
|
-
createProcessor: () => new HooksProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14252
|
-
}
|
|
14253
|
-
];
|
|
14254
|
-
for (const config of featureConfigs) {
|
|
14255
|
-
if (!features.includes(config.feature)) {
|
|
14256
|
-
continue;
|
|
14257
|
-
}
|
|
14258
|
-
const supportedTargets = config.getTargets();
|
|
14259
|
-
if (!supportedTargets.includes(target)) {
|
|
14260
|
-
continue;
|
|
14261
|
-
}
|
|
14262
|
-
const processor = config.createProcessor();
|
|
14263
|
-
const result = await processFeatureConversion({ processor, outputDir });
|
|
14264
|
-
convertedPaths.push(...result.paths);
|
|
14265
|
-
}
|
|
14266
|
-
if (features.includes("skills")) {
|
|
14267
|
-
logger.debug(
|
|
14268
|
-
"Skills conversion is not yet supported in fetch command. Use import command instead."
|
|
14269
|
-
);
|
|
14270
|
-
}
|
|
14271
|
-
return { converted: convertedPaths.length, convertedPaths };
|
|
14285
|
+
const subResults = await Promise.all(
|
|
14286
|
+
directories.map(
|
|
14287
|
+
(dir) => listDirectoryRecursive({
|
|
14288
|
+
client,
|
|
14289
|
+
owner,
|
|
14290
|
+
repo,
|
|
14291
|
+
path: dir.path,
|
|
14292
|
+
ref,
|
|
14293
|
+
depth: depth + 1,
|
|
14294
|
+
semaphore
|
|
14295
|
+
})
|
|
14296
|
+
)
|
|
14297
|
+
);
|
|
14298
|
+
return [...files, ...subResults.flat()];
|
|
14272
14299
|
}
|
|
14300
|
+
|
|
14301
|
+
// src/types/git-provider.ts
|
|
14302
|
+
import { z as z51 } from "zod/mini";
|
|
14303
|
+
var ALL_GIT_PROVIDERS = ["github", "gitlab"];
|
|
14304
|
+
var GitProviderSchema = z51.enum(ALL_GIT_PROVIDERS);
|
|
14305
|
+
|
|
14306
|
+
// src/lib/source-parser.ts
|
|
14307
|
+
var GITHUB_HOSTS = /* @__PURE__ */ new Set(["github.com", "www.github.com"]);
|
|
14308
|
+
var GITLAB_HOSTS = /* @__PURE__ */ new Set(["gitlab.com", "www.gitlab.com"]);
|
|
14273
14309
|
function parseSource(source) {
|
|
14274
14310
|
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
14275
14311
|
return parseUrl(source);
|
|
@@ -14286,18 +14322,6 @@ function parseSource(source) {
|
|
|
14286
14322
|
}
|
|
14287
14323
|
return { provider: "github", ...parseShorthand(source) };
|
|
14288
14324
|
}
|
|
14289
|
-
var GITHUB_HOSTS = /* @__PURE__ */ new Set(["github.com", "www.github.com"]);
|
|
14290
|
-
var GITLAB_HOSTS = /* @__PURE__ */ new Set(["gitlab.com", "www.gitlab.com"]);
|
|
14291
|
-
var MAX_RECURSION_DEPTH = 15;
|
|
14292
|
-
var FETCH_CONCURRENCY_LIMIT = 10;
|
|
14293
|
-
async function withSemaphore(semaphore, fn) {
|
|
14294
|
-
await semaphore.acquire();
|
|
14295
|
-
try {
|
|
14296
|
-
return await fn();
|
|
14297
|
-
} finally {
|
|
14298
|
-
semaphore.release();
|
|
14299
|
-
}
|
|
14300
|
-
}
|
|
14301
14325
|
function parseUrl(url) {
|
|
14302
14326
|
const urlObj = new URL(url);
|
|
14303
14327
|
const host = urlObj.hostname.toLowerCase();
|
|
@@ -14372,6 +14396,97 @@ function parseShorthand(source) {
|
|
|
14372
14396
|
path: path4
|
|
14373
14397
|
};
|
|
14374
14398
|
}
|
|
14399
|
+
|
|
14400
|
+
// src/lib/fetch.ts
|
|
14401
|
+
var FEATURE_PATHS = {
|
|
14402
|
+
rules: ["rules"],
|
|
14403
|
+
commands: ["commands"],
|
|
14404
|
+
subagents: ["subagents"],
|
|
14405
|
+
skills: ["skills"],
|
|
14406
|
+
ignore: [RULESYNC_AIIGNORE_FILE_NAME],
|
|
14407
|
+
mcp: [RULESYNC_MCP_FILE_NAME],
|
|
14408
|
+
hooks: [RULESYNC_HOOKS_FILE_NAME]
|
|
14409
|
+
};
|
|
14410
|
+
function isToolTarget(target) {
|
|
14411
|
+
return target !== "rulesync";
|
|
14412
|
+
}
|
|
14413
|
+
function validateFileSize(relativePath, size) {
|
|
14414
|
+
if (size > MAX_FILE_SIZE) {
|
|
14415
|
+
throw new GitHubClientError(
|
|
14416
|
+
`File "${relativePath}" exceeds maximum size limit (${(size / 1024 / 1024).toFixed(2)}MB > ${MAX_FILE_SIZE / 1024 / 1024}MB)`
|
|
14417
|
+
);
|
|
14418
|
+
}
|
|
14419
|
+
}
|
|
14420
|
+
async function processFeatureConversion(params) {
|
|
14421
|
+
const { processor, outputDir } = params;
|
|
14422
|
+
const paths = [];
|
|
14423
|
+
const toolFiles = await processor.loadToolFiles();
|
|
14424
|
+
if (toolFiles.length === 0) {
|
|
14425
|
+
return { paths: [] };
|
|
14426
|
+
}
|
|
14427
|
+
const rulesyncFiles = await processor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
14428
|
+
for (const file of rulesyncFiles) {
|
|
14429
|
+
const relativePath = join108(file.getRelativeDirPath(), file.getRelativeFilePath());
|
|
14430
|
+
const outputPath = join108(outputDir, relativePath);
|
|
14431
|
+
await writeFileContent(outputPath, file.getFileContent());
|
|
14432
|
+
paths.push(relativePath);
|
|
14433
|
+
}
|
|
14434
|
+
return { paths };
|
|
14435
|
+
}
|
|
14436
|
+
async function convertFetchedFilesToRulesync(params) {
|
|
14437
|
+
const { tempDir, outputDir, target, features } = params;
|
|
14438
|
+
const convertedPaths = [];
|
|
14439
|
+
const featureConfigs = [
|
|
14440
|
+
{
|
|
14441
|
+
feature: "rules",
|
|
14442
|
+
getTargets: () => RulesProcessor.getToolTargets({ global: false }),
|
|
14443
|
+
createProcessor: () => new RulesProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14444
|
+
},
|
|
14445
|
+
{
|
|
14446
|
+
feature: "commands",
|
|
14447
|
+
getTargets: () => CommandsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14448
|
+
createProcessor: () => new CommandsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14449
|
+
},
|
|
14450
|
+
{
|
|
14451
|
+
feature: "subagents",
|
|
14452
|
+
getTargets: () => SubagentsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14453
|
+
createProcessor: () => new SubagentsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14454
|
+
},
|
|
14455
|
+
{
|
|
14456
|
+
feature: "ignore",
|
|
14457
|
+
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
14458
|
+
createProcessor: () => new IgnoreProcessor({ baseDir: tempDir, toolTarget: target })
|
|
14459
|
+
},
|
|
14460
|
+
{
|
|
14461
|
+
feature: "mcp",
|
|
14462
|
+
getTargets: () => McpProcessor.getToolTargets({ global: false }),
|
|
14463
|
+
createProcessor: () => new McpProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14464
|
+
},
|
|
14465
|
+
{
|
|
14466
|
+
feature: "hooks",
|
|
14467
|
+
getTargets: () => HooksProcessor.getToolTargets({ global: false }),
|
|
14468
|
+
createProcessor: () => new HooksProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14469
|
+
}
|
|
14470
|
+
];
|
|
14471
|
+
for (const config of featureConfigs) {
|
|
14472
|
+
if (!features.includes(config.feature)) {
|
|
14473
|
+
continue;
|
|
14474
|
+
}
|
|
14475
|
+
const supportedTargets = config.getTargets();
|
|
14476
|
+
if (!supportedTargets.includes(target)) {
|
|
14477
|
+
continue;
|
|
14478
|
+
}
|
|
14479
|
+
const processor = config.createProcessor();
|
|
14480
|
+
const result = await processFeatureConversion({ processor, outputDir });
|
|
14481
|
+
convertedPaths.push(...result.paths);
|
|
14482
|
+
}
|
|
14483
|
+
if (features.includes("skills")) {
|
|
14484
|
+
logger.debug(
|
|
14485
|
+
"Skills conversion is not yet supported in fetch command. Use import command instead."
|
|
14486
|
+
);
|
|
14487
|
+
}
|
|
14488
|
+
return { converted: convertedPaths.length, convertedPaths };
|
|
14489
|
+
}
|
|
14375
14490
|
function resolveFeatures(features) {
|
|
14376
14491
|
if (!features || features.length === 0 || features.includes("*")) {
|
|
14377
14492
|
return [...ALL_FEATURES];
|
|
@@ -14458,7 +14573,7 @@ async function fetchFiles(params) {
|
|
|
14458
14573
|
skipped: 0
|
|
14459
14574
|
};
|
|
14460
14575
|
}
|
|
14461
|
-
const outputBasePath =
|
|
14576
|
+
const outputBasePath = join108(baseDir, outputDir);
|
|
14462
14577
|
for (const { relativePath, size } of filesToFetch) {
|
|
14463
14578
|
checkPathTraversal({
|
|
14464
14579
|
relativePath,
|
|
@@ -14468,7 +14583,7 @@ async function fetchFiles(params) {
|
|
|
14468
14583
|
}
|
|
14469
14584
|
const results = await Promise.all(
|
|
14470
14585
|
filesToFetch.map(async ({ remotePath, relativePath }) => {
|
|
14471
|
-
const localPath =
|
|
14586
|
+
const localPath = join108(outputBasePath, relativePath);
|
|
14472
14587
|
const exists = await fileExists(localPath);
|
|
14473
14588
|
if (exists && conflictStrategy === "skip") {
|
|
14474
14589
|
logger.debug(`Skipping existing file: ${relativePath}`);
|
|
@@ -14510,7 +14625,7 @@ async function collectFeatureFiles(params) {
|
|
|
14510
14625
|
);
|
|
14511
14626
|
const results = await Promise.all(
|
|
14512
14627
|
tasks.map(async ({ featurePath }) => {
|
|
14513
|
-
const fullPath = basePath === "." || basePath === "" ? featurePath :
|
|
14628
|
+
const fullPath = basePath === "." || basePath === "" ? featurePath : join108(basePath, featurePath);
|
|
14514
14629
|
const collected = [];
|
|
14515
14630
|
try {
|
|
14516
14631
|
if (featurePath.includes(".")) {
|
|
@@ -14563,41 +14678,6 @@ async function collectFeatureFiles(params) {
|
|
|
14563
14678
|
);
|
|
14564
14679
|
return results.flat();
|
|
14565
14680
|
}
|
|
14566
|
-
async function listDirectoryRecursive(params) {
|
|
14567
|
-
const { client, owner, repo, path: path4, ref, depth = 0, semaphore } = params;
|
|
14568
|
-
if (depth > MAX_RECURSION_DEPTH) {
|
|
14569
|
-
throw new Error(
|
|
14570
|
-
`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while listing directory: ${path4}`
|
|
14571
|
-
);
|
|
14572
|
-
}
|
|
14573
|
-
const entries = await withSemaphore(
|
|
14574
|
-
semaphore,
|
|
14575
|
-
() => client.listDirectory(owner, repo, path4, ref)
|
|
14576
|
-
);
|
|
14577
|
-
const files = [];
|
|
14578
|
-
const directories = [];
|
|
14579
|
-
for (const entry of entries) {
|
|
14580
|
-
if (entry.type === "file") {
|
|
14581
|
-
files.push(entry);
|
|
14582
|
-
} else if (entry.type === "dir") {
|
|
14583
|
-
directories.push(entry);
|
|
14584
|
-
}
|
|
14585
|
-
}
|
|
14586
|
-
const subResults = await Promise.all(
|
|
14587
|
-
directories.map(
|
|
14588
|
-
(dir) => listDirectoryRecursive({
|
|
14589
|
-
client,
|
|
14590
|
-
owner,
|
|
14591
|
-
repo,
|
|
14592
|
-
path: dir.path,
|
|
14593
|
-
ref,
|
|
14594
|
-
depth: depth + 1,
|
|
14595
|
-
semaphore
|
|
14596
|
-
})
|
|
14597
|
-
)
|
|
14598
|
-
);
|
|
14599
|
-
return [...files, ...subResults.flat()];
|
|
14600
|
-
}
|
|
14601
14681
|
async function fetchAndConvertToolFiles(params) {
|
|
14602
14682
|
const {
|
|
14603
14683
|
client,
|
|
@@ -14645,7 +14725,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14645
14725
|
relativePath: toolRelativePath,
|
|
14646
14726
|
intendedRootDir: tempDir
|
|
14647
14727
|
});
|
|
14648
|
-
const localPath =
|
|
14728
|
+
const localPath = join108(tempDir, toolRelativePath);
|
|
14649
14729
|
const content = await withSemaphore(
|
|
14650
14730
|
semaphore,
|
|
14651
14731
|
() => client.getFileContent(parsed.owner, parsed.repo, remotePath, ref)
|
|
@@ -14654,7 +14734,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14654
14734
|
logger.debug(`Fetched to temp: ${toolRelativePath}`);
|
|
14655
14735
|
})
|
|
14656
14736
|
);
|
|
14657
|
-
const outputBasePath =
|
|
14737
|
+
const outputBasePath = join108(baseDir, outputDir);
|
|
14658
14738
|
const { converted, convertedPaths } = await convertFetchedFilesToRulesync({
|
|
14659
14739
|
tempDir,
|
|
14660
14740
|
outputDir: outputBasePath,
|
|
@@ -14665,7 +14745,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14665
14745
|
relativePath,
|
|
14666
14746
|
status: "created"
|
|
14667
14747
|
}));
|
|
14668
|
-
logger.
|
|
14748
|
+
logger.debug(`Converted ${converted} files from ${target} format to rulesync format`);
|
|
14669
14749
|
return {
|
|
14670
14750
|
source: `${parsed.owner}/${parsed.repo}`,
|
|
14671
14751
|
ref,
|
|
@@ -14727,7 +14807,7 @@ function mapToToolPath(relativePath, toolPaths) {
|
|
|
14727
14807
|
if (relativePath.startsWith("rules/")) {
|
|
14728
14808
|
const restPath = relativePath.substring("rules/".length);
|
|
14729
14809
|
if (toolPaths.rules?.nonRoot) {
|
|
14730
|
-
return
|
|
14810
|
+
return join108(toolPaths.rules.nonRoot, restPath);
|
|
14731
14811
|
}
|
|
14732
14812
|
}
|
|
14733
14813
|
if (toolPaths.rules?.root && relativePath === toolPaths.rules.root) {
|
|
@@ -14736,19 +14816,19 @@ function mapToToolPath(relativePath, toolPaths) {
|
|
|
14736
14816
|
if (relativePath.startsWith("commands/")) {
|
|
14737
14817
|
const restPath = relativePath.substring("commands/".length);
|
|
14738
14818
|
if (toolPaths.commands) {
|
|
14739
|
-
return
|
|
14819
|
+
return join108(toolPaths.commands, restPath);
|
|
14740
14820
|
}
|
|
14741
14821
|
}
|
|
14742
14822
|
if (relativePath.startsWith("subagents/")) {
|
|
14743
14823
|
const restPath = relativePath.substring("subagents/".length);
|
|
14744
14824
|
if (toolPaths.subagents) {
|
|
14745
|
-
return
|
|
14825
|
+
return join108(toolPaths.subagents, restPath);
|
|
14746
14826
|
}
|
|
14747
14827
|
}
|
|
14748
14828
|
if (relativePath.startsWith("skills/")) {
|
|
14749
14829
|
const restPath = relativePath.substring("skills/".length);
|
|
14750
14830
|
if (toolPaths.skills) {
|
|
14751
|
-
return
|
|
14831
|
+
return join108(toolPaths.skills, restPath);
|
|
14752
14832
|
}
|
|
14753
14833
|
}
|
|
14754
14834
|
return relativePath;
|
|
@@ -14778,7 +14858,7 @@ async function fetchCommand(options) {
|
|
|
14778
14858
|
verbose: fetchOptions.verbose ?? false,
|
|
14779
14859
|
silent: fetchOptions.silent ?? false
|
|
14780
14860
|
});
|
|
14781
|
-
logger.
|
|
14861
|
+
logger.debug(`Fetching files from ${source}...`);
|
|
14782
14862
|
try {
|
|
14783
14863
|
const summary = await fetchFiles({
|
|
14784
14864
|
source,
|
|
@@ -14801,10 +14881,14 @@ async function fetchCommand(options) {
|
|
|
14801
14881
|
|
|
14802
14882
|
// src/config/config-resolver.ts
|
|
14803
14883
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
14804
|
-
import { dirname as dirname2, join as
|
|
14884
|
+
import { dirname as dirname2, join as join109, resolve as resolve4 } from "path";
|
|
14805
14885
|
|
|
14806
14886
|
// src/config/config.ts
|
|
14807
|
-
import { optional as optional3, z as z52 } from "zod/mini";
|
|
14887
|
+
import { minLength, optional as optional3, z as z52 } from "zod/mini";
|
|
14888
|
+
var SourceEntrySchema = z52.object({
|
|
14889
|
+
source: z52.string().check(minLength(1, "source must be a non-empty string")),
|
|
14890
|
+
skills: optional3(z52.array(z52.string()))
|
|
14891
|
+
});
|
|
14808
14892
|
var ConfigParamsSchema = z52.object({
|
|
14809
14893
|
baseDirs: z52.array(z52.string()),
|
|
14810
14894
|
targets: RulesyncTargetsSchema,
|
|
@@ -14818,7 +14902,9 @@ var ConfigParamsSchema = z52.object({
|
|
|
14818
14902
|
simulateSubagents: optional3(z52.boolean()),
|
|
14819
14903
|
simulateSkills: optional3(z52.boolean()),
|
|
14820
14904
|
dryRun: optional3(z52.boolean()),
|
|
14821
|
-
check: optional3(z52.boolean())
|
|
14905
|
+
check: optional3(z52.boolean()),
|
|
14906
|
+
// Declarative skill sources
|
|
14907
|
+
sources: optional3(z52.array(SourceEntrySchema))
|
|
14822
14908
|
});
|
|
14823
14909
|
var PartialConfigParamsSchema = z52.partial(ConfigParamsSchema);
|
|
14824
14910
|
var ConfigFileSchema = z52.object({
|
|
@@ -14844,6 +14930,7 @@ var Config = class {
|
|
|
14844
14930
|
simulateSkills;
|
|
14845
14931
|
dryRun;
|
|
14846
14932
|
check;
|
|
14933
|
+
sources;
|
|
14847
14934
|
constructor({
|
|
14848
14935
|
baseDirs,
|
|
14849
14936
|
targets,
|
|
@@ -14856,7 +14943,8 @@ var Config = class {
|
|
|
14856
14943
|
simulateSubagents,
|
|
14857
14944
|
simulateSkills,
|
|
14858
14945
|
dryRun,
|
|
14859
|
-
check
|
|
14946
|
+
check,
|
|
14947
|
+
sources
|
|
14860
14948
|
}) {
|
|
14861
14949
|
this.validateConflictingTargets(targets);
|
|
14862
14950
|
if (dryRun && check) {
|
|
@@ -14874,6 +14962,7 @@ var Config = class {
|
|
|
14874
14962
|
this.simulateSkills = simulateSkills ?? false;
|
|
14875
14963
|
this.dryRun = dryRun ?? false;
|
|
14876
14964
|
this.check = check ?? false;
|
|
14965
|
+
this.sources = sources ?? [];
|
|
14877
14966
|
}
|
|
14878
14967
|
validateConflictingTargets(targets) {
|
|
14879
14968
|
for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
|
|
@@ -14964,6 +15053,9 @@ var Config = class {
|
|
|
14964
15053
|
getCheck() {
|
|
14965
15054
|
return this.check;
|
|
14966
15055
|
}
|
|
15056
|
+
getSources() {
|
|
15057
|
+
return this.sources;
|
|
15058
|
+
}
|
|
14967
15059
|
/**
|
|
14968
15060
|
* Returns true if either dry-run or check mode is enabled.
|
|
14969
15061
|
* In both modes, no files should be written.
|
|
@@ -14987,7 +15079,8 @@ var getDefaults = () => ({
|
|
|
14987
15079
|
simulateSubagents: false,
|
|
14988
15080
|
simulateSkills: false,
|
|
14989
15081
|
dryRun: false,
|
|
14990
|
-
check: false
|
|
15082
|
+
check: false,
|
|
15083
|
+
sources: []
|
|
14991
15084
|
});
|
|
14992
15085
|
var loadConfigFromFile = async (filePath) => {
|
|
14993
15086
|
if (!await fileExists(filePath)) {
|
|
@@ -15017,7 +15110,8 @@ var mergeConfigs = (baseConfig, localConfig) => {
|
|
|
15017
15110
|
simulateSubagents: localConfig.simulateSubagents ?? baseConfig.simulateSubagents,
|
|
15018
15111
|
simulateSkills: localConfig.simulateSkills ?? baseConfig.simulateSkills,
|
|
15019
15112
|
dryRun: localConfig.dryRun ?? baseConfig.dryRun,
|
|
15020
|
-
check: localConfig.check ?? baseConfig.check
|
|
15113
|
+
check: localConfig.check ?? baseConfig.check,
|
|
15114
|
+
sources: localConfig.sources ?? baseConfig.sources
|
|
15021
15115
|
};
|
|
15022
15116
|
};
|
|
15023
15117
|
var ConfigResolver = class {
|
|
@@ -15039,7 +15133,7 @@ var ConfigResolver = class {
|
|
|
15039
15133
|
const validatedConfigPath = resolvePath(configPath, process.cwd());
|
|
15040
15134
|
const baseConfig = await loadConfigFromFile(validatedConfigPath);
|
|
15041
15135
|
const configDir = dirname2(validatedConfigPath);
|
|
15042
|
-
const localConfigPath =
|
|
15136
|
+
const localConfigPath = join109(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
15043
15137
|
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
15044
15138
|
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
15045
15139
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
@@ -15061,7 +15155,8 @@ var ConfigResolver = class {
|
|
|
15061
15155
|
simulateSubagents: resolvedSimulateSubagents,
|
|
15062
15156
|
simulateSkills: resolvedSimulateSkills,
|
|
15063
15157
|
dryRun: dryRun ?? configByFile.dryRun ?? getDefaults().dryRun,
|
|
15064
|
-
check: check ?? configByFile.check ?? getDefaults().check
|
|
15158
|
+
check: check ?? configByFile.check ?? getDefaults().check,
|
|
15159
|
+
sources: configByFile.sources ?? getDefaults().sources
|
|
15065
15160
|
};
|
|
15066
15161
|
return new Config(configParams);
|
|
15067
15162
|
}
|
|
@@ -15082,34 +15177,38 @@ function getBaseDirsInLightOfGlobal({
|
|
|
15082
15177
|
|
|
15083
15178
|
// src/lib/generate.ts
|
|
15084
15179
|
import { intersection } from "es-toolkit";
|
|
15085
|
-
import { join as
|
|
15180
|
+
import { join as join110 } from "path";
|
|
15086
15181
|
async function processFeatureGeneration(params) {
|
|
15087
15182
|
const { config, processor, toolFiles } = params;
|
|
15088
15183
|
let totalCount = 0;
|
|
15184
|
+
const allPaths = [];
|
|
15089
15185
|
let hasDiff = false;
|
|
15090
|
-
const
|
|
15091
|
-
totalCount +=
|
|
15092
|
-
|
|
15186
|
+
const writeResult = await processor.writeAiFiles(toolFiles);
|
|
15187
|
+
totalCount += writeResult.count;
|
|
15188
|
+
allPaths.push(...writeResult.paths);
|
|
15189
|
+
if (writeResult.count > 0) hasDiff = true;
|
|
15093
15190
|
if (config.getDelete()) {
|
|
15094
15191
|
const existingToolFiles = await processor.loadToolFiles({ forDeletion: true });
|
|
15095
15192
|
const orphanCount = await processor.removeOrphanAiFiles(existingToolFiles, toolFiles);
|
|
15096
15193
|
if (orphanCount > 0) hasDiff = true;
|
|
15097
15194
|
}
|
|
15098
|
-
return { count: totalCount, hasDiff };
|
|
15195
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15099
15196
|
}
|
|
15100
15197
|
async function processDirFeatureGeneration(params) {
|
|
15101
15198
|
const { config, processor, toolDirs } = params;
|
|
15102
15199
|
let totalCount = 0;
|
|
15200
|
+
const allPaths = [];
|
|
15103
15201
|
let hasDiff = false;
|
|
15104
|
-
const
|
|
15105
|
-
totalCount +=
|
|
15106
|
-
|
|
15202
|
+
const writeResult = await processor.writeAiDirs(toolDirs);
|
|
15203
|
+
totalCount += writeResult.count;
|
|
15204
|
+
allPaths.push(...writeResult.paths);
|
|
15205
|
+
if (writeResult.count > 0) hasDiff = true;
|
|
15107
15206
|
if (config.getDelete()) {
|
|
15108
15207
|
const existingToolDirs = await processor.loadToolDirsToDelete();
|
|
15109
15208
|
const orphanCount = await processor.removeOrphanAiDirs(existingToolDirs, toolDirs);
|
|
15110
15209
|
if (orphanCount > 0) hasDiff = true;
|
|
15111
15210
|
}
|
|
15112
|
-
return { count: totalCount, hasDiff };
|
|
15211
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15113
15212
|
}
|
|
15114
15213
|
async function processEmptyFeatureGeneration(params) {
|
|
15115
15214
|
const { config, processor } = params;
|
|
@@ -15120,10 +15219,10 @@ async function processEmptyFeatureGeneration(params) {
|
|
|
15120
15219
|
const orphanCount = await processor.removeOrphanAiFiles(existingToolFiles, []);
|
|
15121
15220
|
if (orphanCount > 0) hasDiff = true;
|
|
15122
15221
|
}
|
|
15123
|
-
return { count: totalCount, hasDiff };
|
|
15222
|
+
return { count: totalCount, paths: [], hasDiff };
|
|
15124
15223
|
}
|
|
15125
15224
|
async function checkRulesyncDirExists(params) {
|
|
15126
|
-
return fileExists(
|
|
15225
|
+
return fileExists(join110(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
|
|
15127
15226
|
}
|
|
15128
15227
|
async function generate(params) {
|
|
15129
15228
|
const { config } = params;
|
|
@@ -15137,12 +15236,19 @@ async function generate(params) {
|
|
|
15137
15236
|
const hasDiff = ignoreResult.hasDiff || mcpResult.hasDiff || commandsResult.hasDiff || subagentsResult.hasDiff || skillsResult.hasDiff || hooksResult.hasDiff || rulesResult.hasDiff;
|
|
15138
15237
|
return {
|
|
15139
15238
|
rulesCount: rulesResult.count,
|
|
15239
|
+
rulesPaths: rulesResult.paths,
|
|
15140
15240
|
ignoreCount: ignoreResult.count,
|
|
15241
|
+
ignorePaths: ignoreResult.paths,
|
|
15141
15242
|
mcpCount: mcpResult.count,
|
|
15243
|
+
mcpPaths: mcpResult.paths,
|
|
15142
15244
|
commandsCount: commandsResult.count,
|
|
15245
|
+
commandsPaths: commandsResult.paths,
|
|
15143
15246
|
subagentsCount: subagentsResult.count,
|
|
15247
|
+
subagentsPaths: subagentsResult.paths,
|
|
15144
15248
|
skillsCount: skillsResult.count,
|
|
15249
|
+
skillsPaths: skillsResult.paths,
|
|
15145
15250
|
hooksCount: hooksResult.count,
|
|
15251
|
+
hooksPaths: hooksResult.paths,
|
|
15146
15252
|
skills: skillsResult.skills,
|
|
15147
15253
|
hasDiff
|
|
15148
15254
|
};
|
|
@@ -15150,6 +15256,7 @@ async function generate(params) {
|
|
|
15150
15256
|
async function generateRulesCore(params) {
|
|
15151
15257
|
const { config, skills } = params;
|
|
15152
15258
|
let totalCount = 0;
|
|
15259
|
+
const allPaths = [];
|
|
15153
15260
|
let hasDiff = false;
|
|
15154
15261
|
const toolTargets = intersection(
|
|
15155
15262
|
config.getTargets(),
|
|
@@ -15178,17 +15285,19 @@ async function generateRulesCore(params) {
|
|
|
15178
15285
|
toolFiles
|
|
15179
15286
|
});
|
|
15180
15287
|
totalCount += result.count;
|
|
15288
|
+
allPaths.push(...result.paths);
|
|
15181
15289
|
if (result.hasDiff) hasDiff = true;
|
|
15182
15290
|
}
|
|
15183
15291
|
}
|
|
15184
|
-
return { count: totalCount, hasDiff };
|
|
15292
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15185
15293
|
}
|
|
15186
15294
|
async function generateIgnoreCore(params) {
|
|
15187
15295
|
const { config } = params;
|
|
15188
15296
|
if (config.getGlobal()) {
|
|
15189
|
-
return { count: 0, hasDiff: false };
|
|
15297
|
+
return { count: 0, paths: [], hasDiff: false };
|
|
15190
15298
|
}
|
|
15191
15299
|
let totalCount = 0;
|
|
15300
|
+
const allPaths = [];
|
|
15192
15301
|
let hasDiff = false;
|
|
15193
15302
|
for (const toolTarget of intersection(config.getTargets(), IgnoreProcessor.getToolTargets())) {
|
|
15194
15303
|
if (!config.getFeatures(toolTarget).includes("ignore")) {
|
|
@@ -15217,6 +15326,7 @@ async function generateIgnoreCore(params) {
|
|
|
15217
15326
|
});
|
|
15218
15327
|
}
|
|
15219
15328
|
totalCount += result.count;
|
|
15329
|
+
allPaths.push(...result.paths);
|
|
15220
15330
|
if (result.hasDiff) hasDiff = true;
|
|
15221
15331
|
} catch (error) {
|
|
15222
15332
|
logger.warn(
|
|
@@ -15226,11 +15336,12 @@ async function generateIgnoreCore(params) {
|
|
|
15226
15336
|
}
|
|
15227
15337
|
}
|
|
15228
15338
|
}
|
|
15229
|
-
return { count: totalCount, hasDiff };
|
|
15339
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15230
15340
|
}
|
|
15231
15341
|
async function generateMcpCore(params) {
|
|
15232
15342
|
const { config } = params;
|
|
15233
15343
|
let totalCount = 0;
|
|
15344
|
+
const allPaths = [];
|
|
15234
15345
|
let hasDiff = false;
|
|
15235
15346
|
const toolTargets = intersection(
|
|
15236
15347
|
config.getTargets(),
|
|
@@ -15255,14 +15366,16 @@ async function generateMcpCore(params) {
|
|
|
15255
15366
|
toolFiles
|
|
15256
15367
|
});
|
|
15257
15368
|
totalCount += result.count;
|
|
15369
|
+
allPaths.push(...result.paths);
|
|
15258
15370
|
if (result.hasDiff) hasDiff = true;
|
|
15259
15371
|
}
|
|
15260
15372
|
}
|
|
15261
|
-
return { count: totalCount, hasDiff };
|
|
15373
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15262
15374
|
}
|
|
15263
15375
|
async function generateCommandsCore(params) {
|
|
15264
15376
|
const { config } = params;
|
|
15265
15377
|
let totalCount = 0;
|
|
15378
|
+
const allPaths = [];
|
|
15266
15379
|
let hasDiff = false;
|
|
15267
15380
|
const toolTargets = intersection(
|
|
15268
15381
|
config.getTargets(),
|
|
@@ -15290,14 +15403,16 @@ async function generateCommandsCore(params) {
|
|
|
15290
15403
|
toolFiles
|
|
15291
15404
|
});
|
|
15292
15405
|
totalCount += result.count;
|
|
15406
|
+
allPaths.push(...result.paths);
|
|
15293
15407
|
if (result.hasDiff) hasDiff = true;
|
|
15294
15408
|
}
|
|
15295
15409
|
}
|
|
15296
|
-
return { count: totalCount, hasDiff };
|
|
15410
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15297
15411
|
}
|
|
15298
15412
|
async function generateSubagentsCore(params) {
|
|
15299
15413
|
const { config } = params;
|
|
15300
15414
|
let totalCount = 0;
|
|
15415
|
+
const allPaths = [];
|
|
15301
15416
|
let hasDiff = false;
|
|
15302
15417
|
const toolTargets = intersection(
|
|
15303
15418
|
config.getTargets(),
|
|
@@ -15325,14 +15440,16 @@ async function generateSubagentsCore(params) {
|
|
|
15325
15440
|
toolFiles
|
|
15326
15441
|
});
|
|
15327
15442
|
totalCount += result.count;
|
|
15443
|
+
allPaths.push(...result.paths);
|
|
15328
15444
|
if (result.hasDiff) hasDiff = true;
|
|
15329
15445
|
}
|
|
15330
15446
|
}
|
|
15331
|
-
return { count: totalCount, hasDiff };
|
|
15447
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15332
15448
|
}
|
|
15333
15449
|
async function generateSkillsCore(params) {
|
|
15334
15450
|
const { config } = params;
|
|
15335
15451
|
let totalCount = 0;
|
|
15452
|
+
const allPaths = [];
|
|
15336
15453
|
let hasDiff = false;
|
|
15337
15454
|
const allSkills = [];
|
|
15338
15455
|
const toolTargets = intersection(
|
|
@@ -15366,14 +15483,16 @@ async function generateSkillsCore(params) {
|
|
|
15366
15483
|
toolDirs
|
|
15367
15484
|
});
|
|
15368
15485
|
totalCount += result.count;
|
|
15486
|
+
allPaths.push(...result.paths);
|
|
15369
15487
|
if (result.hasDiff) hasDiff = true;
|
|
15370
15488
|
}
|
|
15371
15489
|
}
|
|
15372
|
-
return { count: totalCount, skills: allSkills, hasDiff };
|
|
15490
|
+
return { count: totalCount, paths: allPaths, skills: allSkills, hasDiff };
|
|
15373
15491
|
}
|
|
15374
15492
|
async function generateHooksCore(params) {
|
|
15375
15493
|
const { config } = params;
|
|
15376
15494
|
let totalCount = 0;
|
|
15495
|
+
const allPaths = [];
|
|
15377
15496
|
let hasDiff = false;
|
|
15378
15497
|
const toolTargets = intersection(
|
|
15379
15498
|
config.getTargets(),
|
|
@@ -15406,10 +15525,11 @@ async function generateHooksCore(params) {
|
|
|
15406
15525
|
});
|
|
15407
15526
|
}
|
|
15408
15527
|
totalCount += result.count;
|
|
15528
|
+
allPaths.push(...result.paths);
|
|
15409
15529
|
if (result.hasDiff) hasDiff = true;
|
|
15410
15530
|
}
|
|
15411
15531
|
}
|
|
15412
|
-
return { count: totalCount, hasDiff };
|
|
15532
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15413
15533
|
}
|
|
15414
15534
|
|
|
15415
15535
|
// src/utils/result.ts
|
|
@@ -15419,13 +15539,16 @@ function calculateTotalCount(result) {
|
|
|
15419
15539
|
|
|
15420
15540
|
// src/cli/commands/generate.ts
|
|
15421
15541
|
function logFeatureResult(params) {
|
|
15422
|
-
const { count, featureName, isPreview, modePrefix } = params;
|
|
15542
|
+
const { count, paths, featureName, isPreview, modePrefix } = params;
|
|
15423
15543
|
if (count > 0) {
|
|
15424
15544
|
if (isPreview) {
|
|
15425
15545
|
logger.info(`${modePrefix} Would write ${count} ${featureName}`);
|
|
15426
15546
|
} else {
|
|
15427
15547
|
logger.success(`Written ${count} ${featureName}`);
|
|
15428
15548
|
}
|
|
15549
|
+
for (const p of paths) {
|
|
15550
|
+
logger.info(` ${p}`);
|
|
15551
|
+
}
|
|
15429
15552
|
}
|
|
15430
15553
|
}
|
|
15431
15554
|
async function generateCommand(options) {
|
|
@@ -15437,73 +15560,80 @@ async function generateCommand(options) {
|
|
|
15437
15560
|
const check = config.getCheck();
|
|
15438
15561
|
const isPreview = config.isPreviewMode();
|
|
15439
15562
|
const modePrefix = isPreview ? "[DRY RUN]" : "";
|
|
15440
|
-
logger.
|
|
15563
|
+
logger.debug("Generating files...");
|
|
15441
15564
|
if (!await checkRulesyncDirExists({ baseDir: process.cwd() })) {
|
|
15442
15565
|
logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
15443
15566
|
process.exit(1);
|
|
15444
15567
|
}
|
|
15445
|
-
logger.
|
|
15568
|
+
logger.debug(`Base directories: ${config.getBaseDirs().join(", ")}`);
|
|
15446
15569
|
const features = config.getFeatures();
|
|
15447
15570
|
if (features.includes("ignore")) {
|
|
15448
|
-
logger.
|
|
15571
|
+
logger.debug("Generating ignore files...");
|
|
15449
15572
|
}
|
|
15450
15573
|
if (features.includes("mcp")) {
|
|
15451
|
-
logger.
|
|
15574
|
+
logger.debug("Generating MCP files...");
|
|
15452
15575
|
}
|
|
15453
15576
|
if (features.includes("commands")) {
|
|
15454
|
-
logger.
|
|
15577
|
+
logger.debug("Generating command files...");
|
|
15455
15578
|
}
|
|
15456
15579
|
if (features.includes("subagents")) {
|
|
15457
|
-
logger.
|
|
15580
|
+
logger.debug("Generating subagent files...");
|
|
15458
15581
|
}
|
|
15459
15582
|
if (features.includes("skills")) {
|
|
15460
|
-
logger.
|
|
15583
|
+
logger.debug("Generating skill files...");
|
|
15461
15584
|
}
|
|
15462
15585
|
if (features.includes("hooks")) {
|
|
15463
|
-
logger.
|
|
15586
|
+
logger.debug("Generating hooks...");
|
|
15464
15587
|
}
|
|
15465
15588
|
if (features.includes("rules")) {
|
|
15466
|
-
logger.
|
|
15589
|
+
logger.debug("Generating rule files...");
|
|
15467
15590
|
}
|
|
15468
15591
|
const result = await generate({ config });
|
|
15469
15592
|
logFeatureResult({
|
|
15470
15593
|
count: result.ignoreCount,
|
|
15594
|
+
paths: result.ignorePaths,
|
|
15471
15595
|
featureName: "ignore file(s)",
|
|
15472
15596
|
isPreview,
|
|
15473
15597
|
modePrefix
|
|
15474
15598
|
});
|
|
15475
15599
|
logFeatureResult({
|
|
15476
15600
|
count: result.mcpCount,
|
|
15601
|
+
paths: result.mcpPaths,
|
|
15477
15602
|
featureName: "MCP configuration(s)",
|
|
15478
15603
|
isPreview,
|
|
15479
15604
|
modePrefix
|
|
15480
15605
|
});
|
|
15481
15606
|
logFeatureResult({
|
|
15482
15607
|
count: result.commandsCount,
|
|
15608
|
+
paths: result.commandsPaths,
|
|
15483
15609
|
featureName: "command(s)",
|
|
15484
15610
|
isPreview,
|
|
15485
15611
|
modePrefix
|
|
15486
15612
|
});
|
|
15487
15613
|
logFeatureResult({
|
|
15488
15614
|
count: result.subagentsCount,
|
|
15615
|
+
paths: result.subagentsPaths,
|
|
15489
15616
|
featureName: "subagent(s)",
|
|
15490
15617
|
isPreview,
|
|
15491
15618
|
modePrefix
|
|
15492
15619
|
});
|
|
15493
15620
|
logFeatureResult({
|
|
15494
15621
|
count: result.skillsCount,
|
|
15622
|
+
paths: result.skillsPaths,
|
|
15495
15623
|
featureName: "skill(s)",
|
|
15496
15624
|
isPreview,
|
|
15497
15625
|
modePrefix
|
|
15498
15626
|
});
|
|
15499
15627
|
logFeatureResult({
|
|
15500
15628
|
count: result.hooksCount,
|
|
15629
|
+
paths: result.hooksPaths,
|
|
15501
15630
|
featureName: "hooks file(s)",
|
|
15502
15631
|
isPreview,
|
|
15503
15632
|
modePrefix
|
|
15504
15633
|
});
|
|
15505
15634
|
logFeatureResult({
|
|
15506
15635
|
count: result.rulesCount,
|
|
15636
|
+
paths: result.rulesPaths,
|
|
15507
15637
|
featureName: "rule(s)",
|
|
15508
15638
|
isPreview,
|
|
15509
15639
|
modePrefix
|
|
@@ -15538,10 +15668,12 @@ async function generateCommand(options) {
|
|
|
15538
15668
|
}
|
|
15539
15669
|
|
|
15540
15670
|
// src/cli/commands/gitignore.ts
|
|
15541
|
-
import { join as
|
|
15671
|
+
import { join as join111 } from "path";
|
|
15542
15672
|
var RULESYNC_HEADER = "# Generated by Rulesync";
|
|
15543
15673
|
var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
|
|
15544
15674
|
var RULESYNC_IGNORE_ENTRIES = [
|
|
15675
|
+
// Rulesync curated (fetched) skills
|
|
15676
|
+
".rulesync/skills/.curated/",
|
|
15545
15677
|
// AGENTS.md
|
|
15546
15678
|
"**/AGENTS.md",
|
|
15547
15679
|
"**/.agents/",
|
|
@@ -15686,7 +15818,7 @@ var removeExistingRulesyncEntries = (content) => {
|
|
|
15686
15818
|
return result;
|
|
15687
15819
|
};
|
|
15688
15820
|
var gitignoreCommand = async () => {
|
|
15689
|
-
const gitignorePath =
|
|
15821
|
+
const gitignorePath = join111(process.cwd(), ".gitignore");
|
|
15690
15822
|
let gitignoreContent = "";
|
|
15691
15823
|
if (await fileExists(gitignorePath)) {
|
|
15692
15824
|
gitignoreContent = await readFileContent(gitignorePath);
|
|
@@ -15758,7 +15890,7 @@ async function importRulesCore(params) {
|
|
|
15758
15890
|
return 0;
|
|
15759
15891
|
}
|
|
15760
15892
|
const rulesyncFiles = await rulesProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15761
|
-
const writtenCount = await rulesProcessor.writeAiFiles(rulesyncFiles);
|
|
15893
|
+
const { count: writtenCount } = await rulesProcessor.writeAiFiles(rulesyncFiles);
|
|
15762
15894
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15763
15895
|
logger.success(`Created ${writtenCount} rule files`);
|
|
15764
15896
|
}
|
|
@@ -15785,7 +15917,7 @@ async function importIgnoreCore(params) {
|
|
|
15785
15917
|
return 0;
|
|
15786
15918
|
}
|
|
15787
15919
|
const rulesyncFiles = await ignoreProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15788
|
-
const writtenCount = await ignoreProcessor.writeAiFiles(rulesyncFiles);
|
|
15920
|
+
const { count: writtenCount } = await ignoreProcessor.writeAiFiles(rulesyncFiles);
|
|
15789
15921
|
if (config.getVerbose()) {
|
|
15790
15922
|
logger.success(`Created ignore files from ${toolFiles.length} tool ignore configurations`);
|
|
15791
15923
|
}
|
|
@@ -15814,7 +15946,7 @@ async function importMcpCore(params) {
|
|
|
15814
15946
|
return 0;
|
|
15815
15947
|
}
|
|
15816
15948
|
const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15817
|
-
const writtenCount = await mcpProcessor.writeAiFiles(rulesyncFiles);
|
|
15949
|
+
const { count: writtenCount } = await mcpProcessor.writeAiFiles(rulesyncFiles);
|
|
15818
15950
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15819
15951
|
logger.success(`Created ${writtenCount} MCP files`);
|
|
15820
15952
|
}
|
|
@@ -15840,7 +15972,7 @@ async function importCommandsCore(params) {
|
|
|
15840
15972
|
return 0;
|
|
15841
15973
|
}
|
|
15842
15974
|
const rulesyncFiles = await commandsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15843
|
-
const writtenCount = await commandsProcessor.writeAiFiles(rulesyncFiles);
|
|
15975
|
+
const { count: writtenCount } = await commandsProcessor.writeAiFiles(rulesyncFiles);
|
|
15844
15976
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15845
15977
|
logger.success(`Created ${writtenCount} command files`);
|
|
15846
15978
|
}
|
|
@@ -15866,7 +15998,7 @@ async function importSubagentsCore(params) {
|
|
|
15866
15998
|
return 0;
|
|
15867
15999
|
}
|
|
15868
16000
|
const rulesyncFiles = await subagentsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15869
|
-
const writtenCount = await subagentsProcessor.writeAiFiles(rulesyncFiles);
|
|
16001
|
+
const { count: writtenCount } = await subagentsProcessor.writeAiFiles(rulesyncFiles);
|
|
15870
16002
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15871
16003
|
logger.success(`Created ${writtenCount} subagent files`);
|
|
15872
16004
|
}
|
|
@@ -15892,7 +16024,7 @@ async function importSkillsCore(params) {
|
|
|
15892
16024
|
return 0;
|
|
15893
16025
|
}
|
|
15894
16026
|
const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
|
|
15895
|
-
const writtenCount = await skillsProcessor.writeAiDirs(rulesyncDirs);
|
|
16027
|
+
const { count: writtenCount } = await skillsProcessor.writeAiDirs(rulesyncDirs);
|
|
15896
16028
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15897
16029
|
logger.success(`Created ${writtenCount} skill directories`);
|
|
15898
16030
|
}
|
|
@@ -15923,7 +16055,7 @@ async function importHooksCore(params) {
|
|
|
15923
16055
|
return 0;
|
|
15924
16056
|
}
|
|
15925
16057
|
const rulesyncFiles = await hooksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15926
|
-
const writtenCount = await hooksProcessor.writeAiFiles(rulesyncFiles);
|
|
16058
|
+
const { count: writtenCount } = await hooksProcessor.writeAiFiles(rulesyncFiles);
|
|
15927
16059
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15928
16060
|
logger.success(`Created ${writtenCount} hooks file(s)`);
|
|
15929
16061
|
}
|
|
@@ -15946,7 +16078,7 @@ async function importCommand(options) {
|
|
|
15946
16078
|
silent: config.getSilent()
|
|
15947
16079
|
});
|
|
15948
16080
|
const tool = config.getTargets()[0];
|
|
15949
|
-
logger.
|
|
16081
|
+
logger.debug(`Importing files from ${tool}...`);
|
|
15950
16082
|
const result = await importFromTool({ config, tool });
|
|
15951
16083
|
const totalImported = calculateTotalCount(result);
|
|
15952
16084
|
if (totalImported === 0) {
|
|
@@ -15966,7 +16098,7 @@ async function importCommand(options) {
|
|
|
15966
16098
|
}
|
|
15967
16099
|
|
|
15968
16100
|
// src/lib/init.ts
|
|
15969
|
-
import { join as
|
|
16101
|
+
import { join as join112 } from "path";
|
|
15970
16102
|
async function init() {
|
|
15971
16103
|
const sampleFiles = await createSampleFiles();
|
|
15972
16104
|
const configFile = await createConfigFile();
|
|
@@ -16156,27 +16288,27 @@ Keep the summary concise and ready to reuse in future tasks.`
|
|
|
16156
16288
|
await ensureDir(subagentPaths.relativeDirPath);
|
|
16157
16289
|
await ensureDir(skillPaths.relativeDirPath);
|
|
16158
16290
|
await ensureDir(ignorePaths.recommended.relativeDirPath);
|
|
16159
|
-
const ruleFilepath =
|
|
16291
|
+
const ruleFilepath = join112(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
|
|
16160
16292
|
results.push(await writeIfNotExists(ruleFilepath, sampleRuleFile.content));
|
|
16161
|
-
const mcpFilepath =
|
|
16293
|
+
const mcpFilepath = join112(
|
|
16162
16294
|
mcpPaths.recommended.relativeDirPath,
|
|
16163
16295
|
mcpPaths.recommended.relativeFilePath
|
|
16164
16296
|
);
|
|
16165
16297
|
results.push(await writeIfNotExists(mcpFilepath, sampleMcpFile.content));
|
|
16166
|
-
const commandFilepath =
|
|
16298
|
+
const commandFilepath = join112(commandPaths.relativeDirPath, sampleCommandFile.filename);
|
|
16167
16299
|
results.push(await writeIfNotExists(commandFilepath, sampleCommandFile.content));
|
|
16168
|
-
const subagentFilepath =
|
|
16300
|
+
const subagentFilepath = join112(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
|
|
16169
16301
|
results.push(await writeIfNotExists(subagentFilepath, sampleSubagentFile.content));
|
|
16170
|
-
const skillDirPath =
|
|
16302
|
+
const skillDirPath = join112(skillPaths.relativeDirPath, sampleSkillFile.dirName);
|
|
16171
16303
|
await ensureDir(skillDirPath);
|
|
16172
|
-
const skillFilepath =
|
|
16304
|
+
const skillFilepath = join112(skillDirPath, SKILL_FILE_NAME);
|
|
16173
16305
|
results.push(await writeIfNotExists(skillFilepath, sampleSkillFile.content));
|
|
16174
|
-
const ignoreFilepath =
|
|
16306
|
+
const ignoreFilepath = join112(
|
|
16175
16307
|
ignorePaths.recommended.relativeDirPath,
|
|
16176
16308
|
ignorePaths.recommended.relativeFilePath
|
|
16177
16309
|
);
|
|
16178
16310
|
results.push(await writeIfNotExists(ignoreFilepath, sampleIgnoreFile.content));
|
|
16179
|
-
const hooksFilepath =
|
|
16311
|
+
const hooksFilepath = join112(hooksPaths.relativeDirPath, hooksPaths.relativeFilePath);
|
|
16180
16312
|
results.push(await writeIfNotExists(hooksFilepath, sampleHooksFile.content));
|
|
16181
16313
|
return results;
|
|
16182
16314
|
}
|
|
@@ -16190,7 +16322,7 @@ async function writeIfNotExists(path4, content) {
|
|
|
16190
16322
|
|
|
16191
16323
|
// src/cli/commands/init.ts
|
|
16192
16324
|
async function initCommand() {
|
|
16193
|
-
logger.
|
|
16325
|
+
logger.debug("Initializing rulesync...");
|
|
16194
16326
|
await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
|
|
16195
16327
|
const result = await init();
|
|
16196
16328
|
for (const file of result.sampleFiles) {
|
|
@@ -16213,19 +16345,447 @@ async function initCommand() {
|
|
|
16213
16345
|
logger.info("2. Run 'rulesync generate' to create configuration files");
|
|
16214
16346
|
}
|
|
16215
16347
|
|
|
16348
|
+
// src/lib/sources.ts
|
|
16349
|
+
import { Semaphore as Semaphore2 } from "es-toolkit/promise";
|
|
16350
|
+
import { join as join114, resolve as resolve5, sep } from "path";
|
|
16351
|
+
|
|
16352
|
+
// src/lib/sources-lock.ts
|
|
16353
|
+
import { createHash } from "crypto";
|
|
16354
|
+
import { join as join113 } from "path";
|
|
16355
|
+
import { optional as optional4, z as z53 } from "zod/mini";
|
|
16356
|
+
var LOCKFILE_VERSION = 1;
|
|
16357
|
+
var LockedSkillSchema = z53.object({
|
|
16358
|
+
integrity: z53.string()
|
|
16359
|
+
});
|
|
16360
|
+
var LockedSourceSchema = z53.object({
|
|
16361
|
+
requestedRef: optional4(z53.string()),
|
|
16362
|
+
resolvedRef: z53.string(),
|
|
16363
|
+
resolvedAt: optional4(z53.string()),
|
|
16364
|
+
skills: z53.record(z53.string(), LockedSkillSchema)
|
|
16365
|
+
});
|
|
16366
|
+
var SourcesLockSchema = z53.object({
|
|
16367
|
+
lockfileVersion: z53.number(),
|
|
16368
|
+
sources: z53.record(z53.string(), LockedSourceSchema)
|
|
16369
|
+
});
|
|
16370
|
+
var LegacyLockedSourceSchema = z53.object({
|
|
16371
|
+
resolvedRef: z53.string(),
|
|
16372
|
+
skills: z53.array(z53.string())
|
|
16373
|
+
});
|
|
16374
|
+
var LegacySourcesLockSchema = z53.object({
|
|
16375
|
+
sources: z53.record(z53.string(), LegacyLockedSourceSchema)
|
|
16376
|
+
});
|
|
16377
|
+
function migrateLegacyLock(legacy) {
|
|
16378
|
+
const sources = {};
|
|
16379
|
+
for (const [key, entry] of Object.entries(legacy.sources)) {
|
|
16380
|
+
const skills = {};
|
|
16381
|
+
for (const name of entry.skills) {
|
|
16382
|
+
skills[name] = { integrity: "" };
|
|
16383
|
+
}
|
|
16384
|
+
sources[key] = {
|
|
16385
|
+
resolvedRef: entry.resolvedRef,
|
|
16386
|
+
skills
|
|
16387
|
+
};
|
|
16388
|
+
}
|
|
16389
|
+
logger.info(
|
|
16390
|
+
"Migrated legacy sources lockfile to version 1. Run 'rulesync install --update' to populate integrity hashes."
|
|
16391
|
+
);
|
|
16392
|
+
return { lockfileVersion: LOCKFILE_VERSION, sources };
|
|
16393
|
+
}
|
|
16394
|
+
function createEmptyLock() {
|
|
16395
|
+
return { lockfileVersion: LOCKFILE_VERSION, sources: {} };
|
|
16396
|
+
}
|
|
16397
|
+
async function readLockFile(params) {
|
|
16398
|
+
const lockPath = join113(params.baseDir, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
16399
|
+
if (!await fileExists(lockPath)) {
|
|
16400
|
+
logger.debug("No sources lockfile found, starting fresh.");
|
|
16401
|
+
return createEmptyLock();
|
|
16402
|
+
}
|
|
16403
|
+
try {
|
|
16404
|
+
const content = await readFileContent(lockPath);
|
|
16405
|
+
const data = JSON.parse(content);
|
|
16406
|
+
const result = SourcesLockSchema.safeParse(data);
|
|
16407
|
+
if (result.success) {
|
|
16408
|
+
return result.data;
|
|
16409
|
+
}
|
|
16410
|
+
const legacyResult = LegacySourcesLockSchema.safeParse(data);
|
|
16411
|
+
if (legacyResult.success) {
|
|
16412
|
+
return migrateLegacyLock(legacyResult.data);
|
|
16413
|
+
}
|
|
16414
|
+
logger.warn(
|
|
16415
|
+
`Invalid sources lockfile format (${RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH}). Starting fresh.`
|
|
16416
|
+
);
|
|
16417
|
+
return createEmptyLock();
|
|
16418
|
+
} catch {
|
|
16419
|
+
logger.warn(
|
|
16420
|
+
`Failed to read sources lockfile (${RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH}). Starting fresh.`
|
|
16421
|
+
);
|
|
16422
|
+
return createEmptyLock();
|
|
16423
|
+
}
|
|
16424
|
+
}
|
|
16425
|
+
async function writeLockFile(params) {
|
|
16426
|
+
const lockPath = join113(params.baseDir, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
16427
|
+
const content = JSON.stringify(params.lock, null, 2) + "\n";
|
|
16428
|
+
await writeFileContent(lockPath, content);
|
|
16429
|
+
logger.debug(`Wrote sources lockfile to ${lockPath}`);
|
|
16430
|
+
}
|
|
16431
|
+
function computeSkillIntegrity(files) {
|
|
16432
|
+
const hash = createHash("sha256");
|
|
16433
|
+
const sorted = files.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
16434
|
+
for (const file of sorted) {
|
|
16435
|
+
hash.update(file.path);
|
|
16436
|
+
hash.update("\0");
|
|
16437
|
+
hash.update(file.content);
|
|
16438
|
+
hash.update("\0");
|
|
16439
|
+
}
|
|
16440
|
+
return `sha256-${hash.digest("hex")}`;
|
|
16441
|
+
}
|
|
16442
|
+
function normalizeSourceKey(source) {
|
|
16443
|
+
let key = source;
|
|
16444
|
+
for (const prefix of [
|
|
16445
|
+
"https://www.github.com/",
|
|
16446
|
+
"https://github.com/",
|
|
16447
|
+
"http://www.github.com/",
|
|
16448
|
+
"http://github.com/"
|
|
16449
|
+
]) {
|
|
16450
|
+
if (key.toLowerCase().startsWith(prefix)) {
|
|
16451
|
+
key = key.substring(prefix.length);
|
|
16452
|
+
break;
|
|
16453
|
+
}
|
|
16454
|
+
}
|
|
16455
|
+
if (key.startsWith("github:")) {
|
|
16456
|
+
key = key.substring("github:".length);
|
|
16457
|
+
}
|
|
16458
|
+
key = key.replace(/\/+$/, "");
|
|
16459
|
+
key = key.replace(/\.git$/, "");
|
|
16460
|
+
key = key.toLowerCase();
|
|
16461
|
+
return key;
|
|
16462
|
+
}
|
|
16463
|
+
function getLockedSource(lock, sourceKey) {
|
|
16464
|
+
const normalized = normalizeSourceKey(sourceKey);
|
|
16465
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16466
|
+
if (normalizeSourceKey(key) === normalized) {
|
|
16467
|
+
return value;
|
|
16468
|
+
}
|
|
16469
|
+
}
|
|
16470
|
+
return void 0;
|
|
16471
|
+
}
|
|
16472
|
+
function setLockedSource(lock, sourceKey, entry) {
|
|
16473
|
+
const normalized = normalizeSourceKey(sourceKey);
|
|
16474
|
+
const filteredSources = {};
|
|
16475
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16476
|
+
if (normalizeSourceKey(key) !== normalized) {
|
|
16477
|
+
filteredSources[key] = value;
|
|
16478
|
+
}
|
|
16479
|
+
}
|
|
16480
|
+
return {
|
|
16481
|
+
lockfileVersion: lock.lockfileVersion,
|
|
16482
|
+
sources: {
|
|
16483
|
+
...filteredSources,
|
|
16484
|
+
[normalized]: entry
|
|
16485
|
+
}
|
|
16486
|
+
};
|
|
16487
|
+
}
|
|
16488
|
+
function getLockedSkillNames(entry) {
|
|
16489
|
+
return Object.keys(entry.skills);
|
|
16490
|
+
}
|
|
16491
|
+
|
|
16492
|
+
// src/lib/sources.ts
|
|
16493
|
+
async function resolveAndFetchSources(params) {
|
|
16494
|
+
const { sources, baseDir, options = {} } = params;
|
|
16495
|
+
if (sources.length === 0) {
|
|
16496
|
+
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
16497
|
+
}
|
|
16498
|
+
if (options.skipSources) {
|
|
16499
|
+
logger.info("Skipping source fetching.");
|
|
16500
|
+
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
16501
|
+
}
|
|
16502
|
+
let lock = options.updateSources ? createEmptyLock() : await readLockFile({ baseDir });
|
|
16503
|
+
if (options.frozen) {
|
|
16504
|
+
const missingKeys = [];
|
|
16505
|
+
const missingSkills = [];
|
|
16506
|
+
const curatedDir = join114(baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
16507
|
+
for (const source of sources) {
|
|
16508
|
+
const locked = getLockedSource(lock, source.source);
|
|
16509
|
+
if (!locked) {
|
|
16510
|
+
missingKeys.push(source.source);
|
|
16511
|
+
continue;
|
|
16512
|
+
}
|
|
16513
|
+
const skillNames = getLockedSkillNames(locked);
|
|
16514
|
+
for (const skillName of skillNames) {
|
|
16515
|
+
if (!await directoryExists(join114(curatedDir, skillName))) {
|
|
16516
|
+
missingSkills.push(`${source.source}:${skillName}`);
|
|
16517
|
+
}
|
|
16518
|
+
}
|
|
16519
|
+
}
|
|
16520
|
+
if (missingKeys.length > 0) {
|
|
16521
|
+
throw new Error(
|
|
16522
|
+
`Frozen install failed: lockfile is missing entries for: ${missingKeys.join(", ")}. Run 'rulesync install' to update the lockfile.`
|
|
16523
|
+
);
|
|
16524
|
+
}
|
|
16525
|
+
if (missingSkills.length > 0) {
|
|
16526
|
+
throw new Error(
|
|
16527
|
+
`Frozen install failed: locked skills missing from disk: ${missingSkills.join(", ")}. Run 'rulesync install' to fetch missing skills.`
|
|
16528
|
+
);
|
|
16529
|
+
}
|
|
16530
|
+
}
|
|
16531
|
+
const originalLockJson = JSON.stringify(lock);
|
|
16532
|
+
const token = GitHubClient.resolveToken(options.token);
|
|
16533
|
+
const client = new GitHubClient({ token });
|
|
16534
|
+
const localSkillNames = await getLocalSkillDirNames(baseDir);
|
|
16535
|
+
let totalSkillCount = 0;
|
|
16536
|
+
const allFetchedSkillNames = /* @__PURE__ */ new Set();
|
|
16537
|
+
for (const sourceEntry of sources) {
|
|
16538
|
+
try {
|
|
16539
|
+
const { skillCount, fetchedSkillNames, updatedLock } = await fetchSource({
|
|
16540
|
+
sourceEntry,
|
|
16541
|
+
client,
|
|
16542
|
+
baseDir,
|
|
16543
|
+
lock,
|
|
16544
|
+
localSkillNames,
|
|
16545
|
+
alreadyFetchedSkillNames: allFetchedSkillNames,
|
|
16546
|
+
updateSources: options.updateSources ?? false
|
|
16547
|
+
});
|
|
16548
|
+
lock = updatedLock;
|
|
16549
|
+
totalSkillCount += skillCount;
|
|
16550
|
+
for (const name of fetchedSkillNames) {
|
|
16551
|
+
allFetchedSkillNames.add(name);
|
|
16552
|
+
}
|
|
16553
|
+
} catch (error) {
|
|
16554
|
+
if (error instanceof GitHubClientError) {
|
|
16555
|
+
logGitHubAuthHints(error);
|
|
16556
|
+
} else {
|
|
16557
|
+
logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
|
|
16558
|
+
}
|
|
16559
|
+
}
|
|
16560
|
+
}
|
|
16561
|
+
const sourceKeys = new Set(sources.map((s) => normalizeSourceKey(s.source)));
|
|
16562
|
+
const prunedSources = {};
|
|
16563
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16564
|
+
if (sourceKeys.has(normalizeSourceKey(key))) {
|
|
16565
|
+
prunedSources[key] = value;
|
|
16566
|
+
} else {
|
|
16567
|
+
logger.debug(`Pruned stale lockfile entry: ${key}`);
|
|
16568
|
+
}
|
|
16569
|
+
}
|
|
16570
|
+
lock = { lockfileVersion: lock.lockfileVersion, sources: prunedSources };
|
|
16571
|
+
if (!options.frozen && JSON.stringify(lock) !== originalLockJson) {
|
|
16572
|
+
await writeLockFile({ baseDir, lock });
|
|
16573
|
+
} else {
|
|
16574
|
+
logger.debug("Lockfile unchanged, skipping write.");
|
|
16575
|
+
}
|
|
16576
|
+
return { fetchedSkillCount: totalSkillCount, sourcesProcessed: sources.length };
|
|
16577
|
+
}
|
|
16578
|
+
async function checkLockedSkillsExist(curatedDir, skillNames) {
|
|
16579
|
+
if (skillNames.length === 0) return true;
|
|
16580
|
+
for (const name of skillNames) {
|
|
16581
|
+
if (!await directoryExists(join114(curatedDir, name))) {
|
|
16582
|
+
return false;
|
|
16583
|
+
}
|
|
16584
|
+
}
|
|
16585
|
+
return true;
|
|
16586
|
+
}
|
|
16587
|
+
async function fetchSource(params) {
|
|
16588
|
+
const { sourceEntry, client, baseDir, localSkillNames, alreadyFetchedSkillNames, updateSources } = params;
|
|
16589
|
+
let { lock } = params;
|
|
16590
|
+
const parsed = parseSource(sourceEntry.source);
|
|
16591
|
+
if (parsed.provider === "gitlab") {
|
|
16592
|
+
throw new Error("GitLab sources are not yet supported.");
|
|
16593
|
+
}
|
|
16594
|
+
const sourceKey = sourceEntry.source;
|
|
16595
|
+
const locked = getLockedSource(lock, sourceKey);
|
|
16596
|
+
const lockedSkillNames = locked ? getLockedSkillNames(locked) : [];
|
|
16597
|
+
let ref;
|
|
16598
|
+
let resolvedSha;
|
|
16599
|
+
let requestedRef;
|
|
16600
|
+
if (locked && !updateSources) {
|
|
16601
|
+
ref = locked.resolvedRef;
|
|
16602
|
+
resolvedSha = locked.resolvedRef;
|
|
16603
|
+
requestedRef = locked.requestedRef;
|
|
16604
|
+
logger.debug(`Using locked ref for ${sourceKey}: ${resolvedSha}`);
|
|
16605
|
+
} else {
|
|
16606
|
+
requestedRef = parsed.ref ?? await client.getDefaultBranch(parsed.owner, parsed.repo);
|
|
16607
|
+
resolvedSha = await client.resolveRefToSha(parsed.owner, parsed.repo, requestedRef);
|
|
16608
|
+
ref = resolvedSha;
|
|
16609
|
+
logger.debug(`Resolved ${sourceKey} ref "${requestedRef}" to SHA: ${resolvedSha}`);
|
|
16610
|
+
}
|
|
16611
|
+
const curatedDir = join114(baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
16612
|
+
if (locked && resolvedSha === locked.resolvedRef && !updateSources) {
|
|
16613
|
+
const allExist = await checkLockedSkillsExist(curatedDir, lockedSkillNames);
|
|
16614
|
+
if (allExist) {
|
|
16615
|
+
logger.debug(`SHA unchanged for ${sourceKey}, skipping re-fetch.`);
|
|
16616
|
+
return {
|
|
16617
|
+
skillCount: 0,
|
|
16618
|
+
fetchedSkillNames: lockedSkillNames,
|
|
16619
|
+
updatedLock: lock
|
|
16620
|
+
};
|
|
16621
|
+
}
|
|
16622
|
+
}
|
|
16623
|
+
const skillFilter = sourceEntry.skills ?? ["*"];
|
|
16624
|
+
const isWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
16625
|
+
const skillsBasePath = parsed.path ?? "skills";
|
|
16626
|
+
let remoteSkillDirs;
|
|
16627
|
+
try {
|
|
16628
|
+
const entries = await client.listDirectory(parsed.owner, parsed.repo, skillsBasePath, ref);
|
|
16629
|
+
remoteSkillDirs = entries.filter((e) => e.type === "dir").map((e) => ({ name: e.name, path: e.path }));
|
|
16630
|
+
} catch (error) {
|
|
16631
|
+
if (error instanceof GitHubClientError && error.statusCode === 404) {
|
|
16632
|
+
logger.warn(`No skills/ directory found in ${sourceKey}. Skipping.`);
|
|
16633
|
+
return { skillCount: 0, fetchedSkillNames: [], updatedLock: lock };
|
|
16634
|
+
}
|
|
16635
|
+
throw error;
|
|
16636
|
+
}
|
|
16637
|
+
const filteredDirs = isWildcard ? remoteSkillDirs : remoteSkillDirs.filter((d) => skillFilter.includes(d.name));
|
|
16638
|
+
const semaphore = new Semaphore2(FETCH_CONCURRENCY_LIMIT);
|
|
16639
|
+
const fetchedSkills = {};
|
|
16640
|
+
if (locked) {
|
|
16641
|
+
const resolvedCuratedDir = resolve5(curatedDir);
|
|
16642
|
+
for (const prevSkill of lockedSkillNames) {
|
|
16643
|
+
const prevDir = join114(curatedDir, prevSkill);
|
|
16644
|
+
if (!resolve5(prevDir).startsWith(resolvedCuratedDir + sep)) {
|
|
16645
|
+
logger.warn(
|
|
16646
|
+
`Skipping removal of "${prevSkill}": resolved path is outside the curated directory.`
|
|
16647
|
+
);
|
|
16648
|
+
continue;
|
|
16649
|
+
}
|
|
16650
|
+
if (await directoryExists(prevDir)) {
|
|
16651
|
+
await removeDirectory(prevDir);
|
|
16652
|
+
}
|
|
16653
|
+
}
|
|
16654
|
+
}
|
|
16655
|
+
for (const skillDir of filteredDirs) {
|
|
16656
|
+
if (skillDir.name.includes("..") || skillDir.name.includes("/") || skillDir.name.includes("\\")) {
|
|
16657
|
+
logger.warn(
|
|
16658
|
+
`Skipping skill with invalid name "${skillDir.name}" from ${sourceKey}: contains path traversal characters.`
|
|
16659
|
+
);
|
|
16660
|
+
continue;
|
|
16661
|
+
}
|
|
16662
|
+
if (localSkillNames.has(skillDir.name)) {
|
|
16663
|
+
logger.debug(
|
|
16664
|
+
`Skipping remote skill "${skillDir.name}" from ${sourceKey}: local skill takes precedence.`
|
|
16665
|
+
);
|
|
16666
|
+
continue;
|
|
16667
|
+
}
|
|
16668
|
+
if (alreadyFetchedSkillNames.has(skillDir.name)) {
|
|
16669
|
+
logger.warn(
|
|
16670
|
+
`Skipping duplicate skill "${skillDir.name}" from ${sourceKey}: already fetched from another source.`
|
|
16671
|
+
);
|
|
16672
|
+
continue;
|
|
16673
|
+
}
|
|
16674
|
+
const allFiles = await listDirectoryRecursive({
|
|
16675
|
+
client,
|
|
16676
|
+
owner: parsed.owner,
|
|
16677
|
+
repo: parsed.repo,
|
|
16678
|
+
path: skillDir.path,
|
|
16679
|
+
ref,
|
|
16680
|
+
semaphore
|
|
16681
|
+
});
|
|
16682
|
+
const files = allFiles.filter((file) => {
|
|
16683
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
16684
|
+
logger.warn(
|
|
16685
|
+
`Skipping file "${file.path}" (${(file.size / 1024 / 1024).toFixed(2)}MB exceeds ${MAX_FILE_SIZE / 1024 / 1024}MB limit).`
|
|
16686
|
+
);
|
|
16687
|
+
return false;
|
|
16688
|
+
}
|
|
16689
|
+
return true;
|
|
16690
|
+
});
|
|
16691
|
+
const skillFiles = [];
|
|
16692
|
+
for (const file of files) {
|
|
16693
|
+
const relativeToSkill = file.path.substring(skillDir.path.length + 1);
|
|
16694
|
+
const localFilePath = join114(curatedDir, skillDir.name, relativeToSkill);
|
|
16695
|
+
checkPathTraversal({
|
|
16696
|
+
relativePath: relativeToSkill,
|
|
16697
|
+
intendedRootDir: join114(curatedDir, skillDir.name)
|
|
16698
|
+
});
|
|
16699
|
+
const content = await withSemaphore(
|
|
16700
|
+
semaphore,
|
|
16701
|
+
() => client.getFileContent(parsed.owner, parsed.repo, file.path, ref)
|
|
16702
|
+
);
|
|
16703
|
+
await writeFileContent(localFilePath, content);
|
|
16704
|
+
skillFiles.push({ path: relativeToSkill, content });
|
|
16705
|
+
}
|
|
16706
|
+
const integrity = computeSkillIntegrity(skillFiles);
|
|
16707
|
+
const lockedSkillEntry = locked?.skills[skillDir.name];
|
|
16708
|
+
if (lockedSkillEntry && lockedSkillEntry.integrity && lockedSkillEntry.integrity !== integrity && resolvedSha === locked?.resolvedRef) {
|
|
16709
|
+
logger.warn(
|
|
16710
|
+
`Integrity mismatch for skill "${skillDir.name}" from ${sourceKey}: expected "${lockedSkillEntry.integrity}", got "${integrity}". Content may have been tampered with.`
|
|
16711
|
+
);
|
|
16712
|
+
}
|
|
16713
|
+
fetchedSkills[skillDir.name] = { integrity };
|
|
16714
|
+
logger.debug(`Fetched skill "${skillDir.name}" from ${sourceKey}`);
|
|
16715
|
+
}
|
|
16716
|
+
const fetchedNames = Object.keys(fetchedSkills);
|
|
16717
|
+
const mergedSkills = { ...fetchedSkills };
|
|
16718
|
+
if (locked) {
|
|
16719
|
+
for (const [skillName, skillEntry] of Object.entries(locked.skills)) {
|
|
16720
|
+
if (!(skillName in mergedSkills)) {
|
|
16721
|
+
mergedSkills[skillName] = skillEntry;
|
|
16722
|
+
}
|
|
16723
|
+
}
|
|
16724
|
+
}
|
|
16725
|
+
lock = setLockedSource(lock, sourceKey, {
|
|
16726
|
+
requestedRef,
|
|
16727
|
+
resolvedRef: resolvedSha,
|
|
16728
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16729
|
+
skills: mergedSkills
|
|
16730
|
+
});
|
|
16731
|
+
logger.info(
|
|
16732
|
+
`Fetched ${fetchedNames.length} skill(s) from ${sourceKey}: ${fetchedNames.join(", ") || "(none)"}`
|
|
16733
|
+
);
|
|
16734
|
+
return {
|
|
16735
|
+
skillCount: fetchedNames.length,
|
|
16736
|
+
fetchedSkillNames: fetchedNames,
|
|
16737
|
+
updatedLock: lock
|
|
16738
|
+
};
|
|
16739
|
+
}
|
|
16740
|
+
|
|
16741
|
+
// src/cli/commands/install.ts
|
|
16742
|
+
async function installCommand(options) {
|
|
16743
|
+
logger.configure({
|
|
16744
|
+
verbose: options.verbose ?? false,
|
|
16745
|
+
silent: options.silent ?? false
|
|
16746
|
+
});
|
|
16747
|
+
const config = await ConfigResolver.resolve({
|
|
16748
|
+
configPath: options.configPath,
|
|
16749
|
+
verbose: options.verbose,
|
|
16750
|
+
silent: options.silent
|
|
16751
|
+
});
|
|
16752
|
+
const sources = config.getSources();
|
|
16753
|
+
if (sources.length === 0) {
|
|
16754
|
+
logger.warn("No sources defined in configuration. Nothing to install.");
|
|
16755
|
+
return;
|
|
16756
|
+
}
|
|
16757
|
+
logger.debug(`Installing skills from ${sources.length} source(s)...`);
|
|
16758
|
+
const result = await resolveAndFetchSources({
|
|
16759
|
+
sources,
|
|
16760
|
+
baseDir: process.cwd(),
|
|
16761
|
+
options: {
|
|
16762
|
+
updateSources: options.update,
|
|
16763
|
+
frozen: options.frozen,
|
|
16764
|
+
token: options.token
|
|
16765
|
+
}
|
|
16766
|
+
});
|
|
16767
|
+
if (result.fetchedSkillCount > 0) {
|
|
16768
|
+
logger.success(
|
|
16769
|
+
`Installed ${result.fetchedSkillCount} skill(s) from ${result.sourcesProcessed} source(s).`
|
|
16770
|
+
);
|
|
16771
|
+
} else {
|
|
16772
|
+
logger.success(`All skills up to date (${result.sourcesProcessed} source(s) checked).`);
|
|
16773
|
+
}
|
|
16774
|
+
}
|
|
16775
|
+
|
|
16216
16776
|
// src/cli/commands/mcp.ts
|
|
16217
16777
|
import { FastMCP } from "fastmcp";
|
|
16218
16778
|
|
|
16219
16779
|
// src/mcp/tools.ts
|
|
16220
|
-
import { z as
|
|
16780
|
+
import { z as z62 } from "zod/mini";
|
|
16221
16781
|
|
|
16222
16782
|
// src/mcp/commands.ts
|
|
16223
|
-
import { basename as
|
|
16224
|
-
import { z as
|
|
16783
|
+
import { basename as basename25, join as join115 } from "path";
|
|
16784
|
+
import { z as z54 } from "zod/mini";
|
|
16225
16785
|
var maxCommandSizeBytes = 1024 * 1024;
|
|
16226
16786
|
var maxCommandsCount = 1e3;
|
|
16227
16787
|
async function listCommands() {
|
|
16228
|
-
const commandsDir =
|
|
16788
|
+
const commandsDir = join115(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
16229
16789
|
try {
|
|
16230
16790
|
const files = await listDirectoryFiles(commandsDir);
|
|
16231
16791
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -16237,7 +16797,7 @@ async function listCommands() {
|
|
|
16237
16797
|
});
|
|
16238
16798
|
const frontmatter = command.getFrontmatter();
|
|
16239
16799
|
return {
|
|
16240
|
-
relativePathFromCwd:
|
|
16800
|
+
relativePathFromCwd: join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
|
|
16241
16801
|
frontmatter
|
|
16242
16802
|
};
|
|
16243
16803
|
} catch (error) {
|
|
@@ -16248,7 +16808,9 @@ async function listCommands() {
|
|
|
16248
16808
|
);
|
|
16249
16809
|
return commands.filter((command) => command !== null);
|
|
16250
16810
|
} catch (error) {
|
|
16251
|
-
logger.error(
|
|
16811
|
+
logger.error(
|
|
16812
|
+
`Failed to read commands directory (${RULESYNC_COMMANDS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
16813
|
+
);
|
|
16252
16814
|
return [];
|
|
16253
16815
|
}
|
|
16254
16816
|
}
|
|
@@ -16257,13 +16819,13 @@ async function getCommand({ relativePathFromCwd }) {
|
|
|
16257
16819
|
relativePath: relativePathFromCwd,
|
|
16258
16820
|
intendedRootDir: process.cwd()
|
|
16259
16821
|
});
|
|
16260
|
-
const filename =
|
|
16822
|
+
const filename = basename25(relativePathFromCwd);
|
|
16261
16823
|
try {
|
|
16262
16824
|
const command = await RulesyncCommand.fromFile({
|
|
16263
16825
|
relativeFilePath: filename
|
|
16264
16826
|
});
|
|
16265
16827
|
return {
|
|
16266
|
-
relativePathFromCwd:
|
|
16828
|
+
relativePathFromCwd: join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
16267
16829
|
frontmatter: command.getFrontmatter(),
|
|
16268
16830
|
body: command.getBody()
|
|
16269
16831
|
};
|
|
@@ -16282,20 +16844,22 @@ async function putCommand({
|
|
|
16282
16844
|
relativePath: relativePathFromCwd,
|
|
16283
16845
|
intendedRootDir: process.cwd()
|
|
16284
16846
|
});
|
|
16285
|
-
const filename =
|
|
16847
|
+
const filename = basename25(relativePathFromCwd);
|
|
16286
16848
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
16287
16849
|
if (estimatedSize > maxCommandSizeBytes) {
|
|
16288
16850
|
throw new Error(
|
|
16289
|
-
`Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB)`
|
|
16851
|
+
`Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
16290
16852
|
);
|
|
16291
16853
|
}
|
|
16292
16854
|
try {
|
|
16293
16855
|
const existingCommands = await listCommands();
|
|
16294
16856
|
const isUpdate = existingCommands.some(
|
|
16295
|
-
(command2) => command2.relativePathFromCwd ===
|
|
16857
|
+
(command2) => command2.relativePathFromCwd === join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
16296
16858
|
);
|
|
16297
16859
|
if (!isUpdate && existingCommands.length >= maxCommandsCount) {
|
|
16298
|
-
throw new Error(
|
|
16860
|
+
throw new Error(
|
|
16861
|
+
`Maximum number of commands (${maxCommandsCount}) reached in ${RULESYNC_COMMANDS_RELATIVE_DIR_PATH}`
|
|
16862
|
+
);
|
|
16299
16863
|
}
|
|
16300
16864
|
const fileContent = stringifyFrontmatter(body, frontmatter);
|
|
16301
16865
|
const command = new RulesyncCommand({
|
|
@@ -16307,11 +16871,11 @@ async function putCommand({
|
|
|
16307
16871
|
fileContent,
|
|
16308
16872
|
validate: true
|
|
16309
16873
|
});
|
|
16310
|
-
const commandsDir =
|
|
16874
|
+
const commandsDir = join115(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
16311
16875
|
await ensureDir(commandsDir);
|
|
16312
16876
|
await writeFileContent(command.getFilePath(), command.getFileContent());
|
|
16313
16877
|
return {
|
|
16314
|
-
relativePathFromCwd:
|
|
16878
|
+
relativePathFromCwd: join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
16315
16879
|
frontmatter: command.getFrontmatter(),
|
|
16316
16880
|
body: command.getBody()
|
|
16317
16881
|
};
|
|
@@ -16326,12 +16890,12 @@ async function deleteCommand({ relativePathFromCwd }) {
|
|
|
16326
16890
|
relativePath: relativePathFromCwd,
|
|
16327
16891
|
intendedRootDir: process.cwd()
|
|
16328
16892
|
});
|
|
16329
|
-
const filename =
|
|
16330
|
-
const fullPath =
|
|
16893
|
+
const filename = basename25(relativePathFromCwd);
|
|
16894
|
+
const fullPath = join115(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
|
|
16331
16895
|
try {
|
|
16332
16896
|
await removeFile(fullPath);
|
|
16333
16897
|
return {
|
|
16334
|
-
relativePathFromCwd:
|
|
16898
|
+
relativePathFromCwd: join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
16335
16899
|
};
|
|
16336
16900
|
} catch (error) {
|
|
16337
16901
|
throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -16340,23 +16904,23 @@ async function deleteCommand({ relativePathFromCwd }) {
|
|
|
16340
16904
|
}
|
|
16341
16905
|
}
|
|
16342
16906
|
var commandToolSchemas = {
|
|
16343
|
-
listCommands:
|
|
16344
|
-
getCommand:
|
|
16345
|
-
relativePathFromCwd:
|
|
16907
|
+
listCommands: z54.object({}),
|
|
16908
|
+
getCommand: z54.object({
|
|
16909
|
+
relativePathFromCwd: z54.string()
|
|
16346
16910
|
}),
|
|
16347
|
-
putCommand:
|
|
16348
|
-
relativePathFromCwd:
|
|
16911
|
+
putCommand: z54.object({
|
|
16912
|
+
relativePathFromCwd: z54.string(),
|
|
16349
16913
|
frontmatter: RulesyncCommandFrontmatterSchema,
|
|
16350
|
-
body:
|
|
16914
|
+
body: z54.string()
|
|
16351
16915
|
}),
|
|
16352
|
-
deleteCommand:
|
|
16353
|
-
relativePathFromCwd:
|
|
16916
|
+
deleteCommand: z54.object({
|
|
16917
|
+
relativePathFromCwd: z54.string()
|
|
16354
16918
|
})
|
|
16355
16919
|
};
|
|
16356
16920
|
var commandTools = {
|
|
16357
16921
|
listCommands: {
|
|
16358
16922
|
name: "listCommands",
|
|
16359
|
-
description: `List all commands from ${
|
|
16923
|
+
description: `List all commands from ${join115(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
16360
16924
|
parameters: commandToolSchemas.listCommands,
|
|
16361
16925
|
execute: async () => {
|
|
16362
16926
|
const commands = await listCommands();
|
|
@@ -16398,15 +16962,15 @@ var commandTools = {
|
|
|
16398
16962
|
};
|
|
16399
16963
|
|
|
16400
16964
|
// src/mcp/generate.ts
|
|
16401
|
-
import { z as
|
|
16402
|
-
var generateOptionsSchema =
|
|
16403
|
-
targets:
|
|
16404
|
-
features:
|
|
16405
|
-
delete:
|
|
16406
|
-
global:
|
|
16407
|
-
simulateCommands:
|
|
16408
|
-
simulateSubagents:
|
|
16409
|
-
simulateSkills:
|
|
16965
|
+
import { z as z55 } from "zod/mini";
|
|
16966
|
+
var generateOptionsSchema = z55.object({
|
|
16967
|
+
targets: z55.optional(z55.array(z55.string())),
|
|
16968
|
+
features: z55.optional(z55.array(z55.string())),
|
|
16969
|
+
delete: z55.optional(z55.boolean()),
|
|
16970
|
+
global: z55.optional(z55.boolean()),
|
|
16971
|
+
simulateCommands: z55.optional(z55.boolean()),
|
|
16972
|
+
simulateSubagents: z55.optional(z55.boolean()),
|
|
16973
|
+
simulateSkills: z55.optional(z55.boolean())
|
|
16410
16974
|
});
|
|
16411
16975
|
async function executeGenerate(options = {}) {
|
|
16412
16976
|
try {
|
|
@@ -16483,11 +17047,11 @@ var generateTools = {
|
|
|
16483
17047
|
};
|
|
16484
17048
|
|
|
16485
17049
|
// src/mcp/ignore.ts
|
|
16486
|
-
import { join as
|
|
16487
|
-
import { z as
|
|
17050
|
+
import { join as join116 } from "path";
|
|
17051
|
+
import { z as z56 } from "zod/mini";
|
|
16488
17052
|
var maxIgnoreFileSizeBytes = 100 * 1024;
|
|
16489
17053
|
async function getIgnoreFile() {
|
|
16490
|
-
const ignoreFilePath =
|
|
17054
|
+
const ignoreFilePath = join116(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
16491
17055
|
try {
|
|
16492
17056
|
const content = await readFileContent(ignoreFilePath);
|
|
16493
17057
|
return {
|
|
@@ -16495,17 +17059,20 @@ async function getIgnoreFile() {
|
|
|
16495
17059
|
content
|
|
16496
17060
|
};
|
|
16497
17061
|
} catch (error) {
|
|
16498
|
-
throw new Error(
|
|
16499
|
-
|
|
16500
|
-
|
|
17062
|
+
throw new Error(
|
|
17063
|
+
`Failed to read ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17064
|
+
{
|
|
17065
|
+
cause: error
|
|
17066
|
+
}
|
|
17067
|
+
);
|
|
16501
17068
|
}
|
|
16502
17069
|
}
|
|
16503
17070
|
async function putIgnoreFile({ content }) {
|
|
16504
|
-
const ignoreFilePath =
|
|
17071
|
+
const ignoreFilePath = join116(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
16505
17072
|
const contentSizeBytes = Buffer.byteLength(content, "utf8");
|
|
16506
17073
|
if (contentSizeBytes > maxIgnoreFileSizeBytes) {
|
|
16507
17074
|
throw new Error(
|
|
16508
|
-
`Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB)`
|
|
17075
|
+
`Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB) for ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}`
|
|
16509
17076
|
);
|
|
16510
17077
|
}
|
|
16511
17078
|
try {
|
|
@@ -16516,14 +17083,17 @@ async function putIgnoreFile({ content }) {
|
|
|
16516
17083
|
content
|
|
16517
17084
|
};
|
|
16518
17085
|
} catch (error) {
|
|
16519
|
-
throw new Error(
|
|
16520
|
-
|
|
16521
|
-
|
|
17086
|
+
throw new Error(
|
|
17087
|
+
`Failed to write ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17088
|
+
{
|
|
17089
|
+
cause: error
|
|
17090
|
+
}
|
|
17091
|
+
);
|
|
16522
17092
|
}
|
|
16523
17093
|
}
|
|
16524
17094
|
async function deleteIgnoreFile() {
|
|
16525
|
-
const aiignorePath =
|
|
16526
|
-
const legacyIgnorePath =
|
|
17095
|
+
const aiignorePath = join116(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
17096
|
+
const legacyIgnorePath = join116(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
|
|
16527
17097
|
try {
|
|
16528
17098
|
await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
|
|
16529
17099
|
return {
|
|
@@ -16533,7 +17103,7 @@ async function deleteIgnoreFile() {
|
|
|
16533
17103
|
};
|
|
16534
17104
|
} catch (error) {
|
|
16535
17105
|
throw new Error(
|
|
16536
|
-
`Failed to delete
|
|
17106
|
+
`Failed to delete ignore files (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}, ${RULESYNC_IGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
16537
17107
|
{
|
|
16538
17108
|
cause: error
|
|
16539
17109
|
}
|
|
@@ -16541,11 +17111,11 @@ async function deleteIgnoreFile() {
|
|
|
16541
17111
|
}
|
|
16542
17112
|
}
|
|
16543
17113
|
var ignoreToolSchemas = {
|
|
16544
|
-
getIgnoreFile:
|
|
16545
|
-
putIgnoreFile:
|
|
16546
|
-
content:
|
|
17114
|
+
getIgnoreFile: z56.object({}),
|
|
17115
|
+
putIgnoreFile: z56.object({
|
|
17116
|
+
content: z56.string()
|
|
16547
17117
|
}),
|
|
16548
|
-
deleteIgnoreFile:
|
|
17118
|
+
deleteIgnoreFile: z56.object({})
|
|
16549
17119
|
};
|
|
16550
17120
|
var ignoreTools = {
|
|
16551
17121
|
getIgnoreFile: {
|
|
@@ -16578,11 +17148,11 @@ var ignoreTools = {
|
|
|
16578
17148
|
};
|
|
16579
17149
|
|
|
16580
17150
|
// src/mcp/import.ts
|
|
16581
|
-
import { z as
|
|
16582
|
-
var importOptionsSchema =
|
|
16583
|
-
target:
|
|
16584
|
-
features:
|
|
16585
|
-
global:
|
|
17151
|
+
import { z as z57 } from "zod/mini";
|
|
17152
|
+
var importOptionsSchema = z57.object({
|
|
17153
|
+
target: z57.string(),
|
|
17154
|
+
features: z57.optional(z57.array(z57.string())),
|
|
17155
|
+
global: z57.optional(z57.boolean())
|
|
16586
17156
|
});
|
|
16587
17157
|
async function executeImport(options) {
|
|
16588
17158
|
try {
|
|
@@ -16651,15 +17221,15 @@ var importTools = {
|
|
|
16651
17221
|
};
|
|
16652
17222
|
|
|
16653
17223
|
// src/mcp/mcp.ts
|
|
16654
|
-
import { join as
|
|
16655
|
-
import { z as
|
|
17224
|
+
import { join as join117 } from "path";
|
|
17225
|
+
import { z as z58 } from "zod/mini";
|
|
16656
17226
|
var maxMcpSizeBytes = 1024 * 1024;
|
|
16657
17227
|
async function getMcpFile() {
|
|
16658
17228
|
try {
|
|
16659
17229
|
const rulesyncMcp = await RulesyncMcp.fromFile({
|
|
16660
17230
|
validate: true
|
|
16661
17231
|
});
|
|
16662
|
-
const relativePathFromCwd =
|
|
17232
|
+
const relativePathFromCwd = join117(
|
|
16663
17233
|
rulesyncMcp.getRelativeDirPath(),
|
|
16664
17234
|
rulesyncMcp.getRelativeFilePath()
|
|
16665
17235
|
);
|
|
@@ -16668,30 +17238,36 @@ async function getMcpFile() {
|
|
|
16668
17238
|
content: rulesyncMcp.getFileContent()
|
|
16669
17239
|
};
|
|
16670
17240
|
} catch (error) {
|
|
16671
|
-
throw new Error(
|
|
16672
|
-
|
|
16673
|
-
|
|
17241
|
+
throw new Error(
|
|
17242
|
+
`Failed to read MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17243
|
+
{
|
|
17244
|
+
cause: error
|
|
17245
|
+
}
|
|
17246
|
+
);
|
|
16674
17247
|
}
|
|
16675
17248
|
}
|
|
16676
17249
|
async function putMcpFile({ content }) {
|
|
16677
17250
|
if (content.length > maxMcpSizeBytes) {
|
|
16678
17251
|
throw new Error(
|
|
16679
|
-
`MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB)`
|
|
17252
|
+
`MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB) for ${RULESYNC_MCP_RELATIVE_FILE_PATH}`
|
|
16680
17253
|
);
|
|
16681
17254
|
}
|
|
16682
17255
|
try {
|
|
16683
17256
|
JSON.parse(content);
|
|
16684
17257
|
} catch (error) {
|
|
16685
|
-
throw new Error(
|
|
16686
|
-
|
|
16687
|
-
|
|
17258
|
+
throw new Error(
|
|
17259
|
+
`Invalid JSON format in MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17260
|
+
{
|
|
17261
|
+
cause: error
|
|
17262
|
+
}
|
|
17263
|
+
);
|
|
16688
17264
|
}
|
|
16689
17265
|
try {
|
|
16690
17266
|
const baseDir = process.cwd();
|
|
16691
17267
|
const paths = RulesyncMcp.getSettablePaths();
|
|
16692
17268
|
const relativeDirPath = paths.recommended.relativeDirPath;
|
|
16693
17269
|
const relativeFilePath = paths.recommended.relativeFilePath;
|
|
16694
|
-
const fullPath =
|
|
17270
|
+
const fullPath = join117(baseDir, relativeDirPath, relativeFilePath);
|
|
16695
17271
|
const rulesyncMcp = new RulesyncMcp({
|
|
16696
17272
|
baseDir,
|
|
16697
17273
|
relativeDirPath,
|
|
@@ -16699,32 +17275,35 @@ async function putMcpFile({ content }) {
|
|
|
16699
17275
|
fileContent: content,
|
|
16700
17276
|
validate: true
|
|
16701
17277
|
});
|
|
16702
|
-
await ensureDir(
|
|
17278
|
+
await ensureDir(join117(baseDir, relativeDirPath));
|
|
16703
17279
|
await writeFileContent(fullPath, content);
|
|
16704
|
-
const relativePathFromCwd =
|
|
17280
|
+
const relativePathFromCwd = join117(relativeDirPath, relativeFilePath);
|
|
16705
17281
|
return {
|
|
16706
17282
|
relativePathFromCwd,
|
|
16707
17283
|
content: rulesyncMcp.getFileContent()
|
|
16708
17284
|
};
|
|
16709
17285
|
} catch (error) {
|
|
16710
|
-
throw new Error(
|
|
16711
|
-
|
|
16712
|
-
|
|
17286
|
+
throw new Error(
|
|
17287
|
+
`Failed to write MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17288
|
+
{
|
|
17289
|
+
cause: error
|
|
17290
|
+
}
|
|
17291
|
+
);
|
|
16713
17292
|
}
|
|
16714
17293
|
}
|
|
16715
17294
|
async function deleteMcpFile() {
|
|
16716
17295
|
try {
|
|
16717
17296
|
const baseDir = process.cwd();
|
|
16718
17297
|
const paths = RulesyncMcp.getSettablePaths();
|
|
16719
|
-
const recommendedPath =
|
|
17298
|
+
const recommendedPath = join117(
|
|
16720
17299
|
baseDir,
|
|
16721
17300
|
paths.recommended.relativeDirPath,
|
|
16722
17301
|
paths.recommended.relativeFilePath
|
|
16723
17302
|
);
|
|
16724
|
-
const legacyPath =
|
|
17303
|
+
const legacyPath = join117(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
|
|
16725
17304
|
await removeFile(recommendedPath);
|
|
16726
17305
|
await removeFile(legacyPath);
|
|
16727
|
-
const relativePathFromCwd =
|
|
17306
|
+
const relativePathFromCwd = join117(
|
|
16728
17307
|
paths.recommended.relativeDirPath,
|
|
16729
17308
|
paths.recommended.relativeFilePath
|
|
16730
17309
|
);
|
|
@@ -16732,17 +17311,20 @@ async function deleteMcpFile() {
|
|
|
16732
17311
|
relativePathFromCwd
|
|
16733
17312
|
};
|
|
16734
17313
|
} catch (error) {
|
|
16735
|
-
throw new Error(
|
|
16736
|
-
|
|
16737
|
-
|
|
17314
|
+
throw new Error(
|
|
17315
|
+
`Failed to delete MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17316
|
+
{
|
|
17317
|
+
cause: error
|
|
17318
|
+
}
|
|
17319
|
+
);
|
|
16738
17320
|
}
|
|
16739
17321
|
}
|
|
16740
17322
|
var mcpToolSchemas = {
|
|
16741
|
-
getMcpFile:
|
|
16742
|
-
putMcpFile:
|
|
16743
|
-
content:
|
|
17323
|
+
getMcpFile: z58.object({}),
|
|
17324
|
+
putMcpFile: z58.object({
|
|
17325
|
+
content: z58.string()
|
|
16744
17326
|
}),
|
|
16745
|
-
deleteMcpFile:
|
|
17327
|
+
deleteMcpFile: z58.object({})
|
|
16746
17328
|
};
|
|
16747
17329
|
var mcpTools = {
|
|
16748
17330
|
getMcpFile: {
|
|
@@ -16775,12 +17357,12 @@ var mcpTools = {
|
|
|
16775
17357
|
};
|
|
16776
17358
|
|
|
16777
17359
|
// src/mcp/rules.ts
|
|
16778
|
-
import { basename as
|
|
16779
|
-
import { z as
|
|
17360
|
+
import { basename as basename26, join as join118 } from "path";
|
|
17361
|
+
import { z as z59 } from "zod/mini";
|
|
16780
17362
|
var maxRuleSizeBytes = 1024 * 1024;
|
|
16781
17363
|
var maxRulesCount = 1e3;
|
|
16782
17364
|
async function listRules() {
|
|
16783
|
-
const rulesDir =
|
|
17365
|
+
const rulesDir = join118(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
16784
17366
|
try {
|
|
16785
17367
|
const files = await listDirectoryFiles(rulesDir);
|
|
16786
17368
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -16793,7 +17375,7 @@ async function listRules() {
|
|
|
16793
17375
|
});
|
|
16794
17376
|
const frontmatter = rule.getFrontmatter();
|
|
16795
17377
|
return {
|
|
16796
|
-
relativePathFromCwd:
|
|
17378
|
+
relativePathFromCwd: join118(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
|
|
16797
17379
|
frontmatter
|
|
16798
17380
|
};
|
|
16799
17381
|
} catch (error) {
|
|
@@ -16804,7 +17386,9 @@ async function listRules() {
|
|
|
16804
17386
|
);
|
|
16805
17387
|
return rules.filter((rule) => rule !== null);
|
|
16806
17388
|
} catch (error) {
|
|
16807
|
-
logger.error(
|
|
17389
|
+
logger.error(
|
|
17390
|
+
`Failed to read rules directory (${RULESYNC_RULES_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17391
|
+
);
|
|
16808
17392
|
return [];
|
|
16809
17393
|
}
|
|
16810
17394
|
}
|
|
@@ -16813,14 +17397,14 @@ async function getRule({ relativePathFromCwd }) {
|
|
|
16813
17397
|
relativePath: relativePathFromCwd,
|
|
16814
17398
|
intendedRootDir: process.cwd()
|
|
16815
17399
|
});
|
|
16816
|
-
const filename =
|
|
17400
|
+
const filename = basename26(relativePathFromCwd);
|
|
16817
17401
|
try {
|
|
16818
17402
|
const rule = await RulesyncRule.fromFile({
|
|
16819
17403
|
relativeFilePath: filename,
|
|
16820
17404
|
validate: true
|
|
16821
17405
|
});
|
|
16822
17406
|
return {
|
|
16823
|
-
relativePathFromCwd:
|
|
17407
|
+
relativePathFromCwd: join118(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
16824
17408
|
frontmatter: rule.getFrontmatter(),
|
|
16825
17409
|
body: rule.getBody()
|
|
16826
17410
|
};
|
|
@@ -16839,20 +17423,22 @@ async function putRule({
|
|
|
16839
17423
|
relativePath: relativePathFromCwd,
|
|
16840
17424
|
intendedRootDir: process.cwd()
|
|
16841
17425
|
});
|
|
16842
|
-
const filename =
|
|
17426
|
+
const filename = basename26(relativePathFromCwd);
|
|
16843
17427
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
16844
17428
|
if (estimatedSize > maxRuleSizeBytes) {
|
|
16845
17429
|
throw new Error(
|
|
16846
|
-
`Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB)`
|
|
17430
|
+
`Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
16847
17431
|
);
|
|
16848
17432
|
}
|
|
16849
17433
|
try {
|
|
16850
17434
|
const existingRules = await listRules();
|
|
16851
17435
|
const isUpdate = existingRules.some(
|
|
16852
|
-
(rule2) => rule2.relativePathFromCwd ===
|
|
17436
|
+
(rule2) => rule2.relativePathFromCwd === join118(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
16853
17437
|
);
|
|
16854
17438
|
if (!isUpdate && existingRules.length >= maxRulesCount) {
|
|
16855
|
-
throw new Error(
|
|
17439
|
+
throw new Error(
|
|
17440
|
+
`Maximum number of rules (${maxRulesCount}) reached in ${RULESYNC_RULES_RELATIVE_DIR_PATH}`
|
|
17441
|
+
);
|
|
16856
17442
|
}
|
|
16857
17443
|
const rule = new RulesyncRule({
|
|
16858
17444
|
baseDir: process.cwd(),
|
|
@@ -16862,11 +17448,11 @@ async function putRule({
|
|
|
16862
17448
|
body,
|
|
16863
17449
|
validate: true
|
|
16864
17450
|
});
|
|
16865
|
-
const rulesDir =
|
|
17451
|
+
const rulesDir = join118(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
16866
17452
|
await ensureDir(rulesDir);
|
|
16867
17453
|
await writeFileContent(rule.getFilePath(), rule.getFileContent());
|
|
16868
17454
|
return {
|
|
16869
|
-
relativePathFromCwd:
|
|
17455
|
+
relativePathFromCwd: join118(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
16870
17456
|
frontmatter: rule.getFrontmatter(),
|
|
16871
17457
|
body: rule.getBody()
|
|
16872
17458
|
};
|
|
@@ -16881,12 +17467,12 @@ async function deleteRule({ relativePathFromCwd }) {
|
|
|
16881
17467
|
relativePath: relativePathFromCwd,
|
|
16882
17468
|
intendedRootDir: process.cwd()
|
|
16883
17469
|
});
|
|
16884
|
-
const filename =
|
|
16885
|
-
const fullPath =
|
|
17470
|
+
const filename = basename26(relativePathFromCwd);
|
|
17471
|
+
const fullPath = join118(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
|
|
16886
17472
|
try {
|
|
16887
17473
|
await removeFile(fullPath);
|
|
16888
17474
|
return {
|
|
16889
|
-
relativePathFromCwd:
|
|
17475
|
+
relativePathFromCwd: join118(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
16890
17476
|
};
|
|
16891
17477
|
} catch (error) {
|
|
16892
17478
|
throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -16895,23 +17481,23 @@ async function deleteRule({ relativePathFromCwd }) {
|
|
|
16895
17481
|
}
|
|
16896
17482
|
}
|
|
16897
17483
|
var ruleToolSchemas = {
|
|
16898
|
-
listRules:
|
|
16899
|
-
getRule:
|
|
16900
|
-
relativePathFromCwd:
|
|
17484
|
+
listRules: z59.object({}),
|
|
17485
|
+
getRule: z59.object({
|
|
17486
|
+
relativePathFromCwd: z59.string()
|
|
16901
17487
|
}),
|
|
16902
|
-
putRule:
|
|
16903
|
-
relativePathFromCwd:
|
|
17488
|
+
putRule: z59.object({
|
|
17489
|
+
relativePathFromCwd: z59.string(),
|
|
16904
17490
|
frontmatter: RulesyncRuleFrontmatterSchema,
|
|
16905
|
-
body:
|
|
17491
|
+
body: z59.string()
|
|
16906
17492
|
}),
|
|
16907
|
-
deleteRule:
|
|
16908
|
-
relativePathFromCwd:
|
|
17493
|
+
deleteRule: z59.object({
|
|
17494
|
+
relativePathFromCwd: z59.string()
|
|
16909
17495
|
})
|
|
16910
17496
|
};
|
|
16911
17497
|
var ruleTools = {
|
|
16912
17498
|
listRules: {
|
|
16913
17499
|
name: "listRules",
|
|
16914
|
-
description: `List all rules from ${
|
|
17500
|
+
description: `List all rules from ${join118(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
16915
17501
|
parameters: ruleToolSchemas.listRules,
|
|
16916
17502
|
execute: async () => {
|
|
16917
17503
|
const rules = await listRules();
|
|
@@ -16953,8 +17539,8 @@ var ruleTools = {
|
|
|
16953
17539
|
};
|
|
16954
17540
|
|
|
16955
17541
|
// src/mcp/skills.ts
|
|
16956
|
-
import { basename as
|
|
16957
|
-
import { z as
|
|
17542
|
+
import { basename as basename27, dirname as dirname3, join as join119 } from "path";
|
|
17543
|
+
import { z as z60 } from "zod/mini";
|
|
16958
17544
|
var maxSkillSizeBytes = 1024 * 1024;
|
|
16959
17545
|
var maxSkillsCount = 1e3;
|
|
16960
17546
|
function aiDirFileToMcpSkillFile(file) {
|
|
@@ -16970,19 +17556,19 @@ function mcpSkillFileToAiDirFile(file) {
|
|
|
16970
17556
|
};
|
|
16971
17557
|
}
|
|
16972
17558
|
function extractDirName(relativeDirPathFromCwd) {
|
|
16973
|
-
const dirName =
|
|
17559
|
+
const dirName = basename27(relativeDirPathFromCwd);
|
|
16974
17560
|
if (!dirName) {
|
|
16975
17561
|
throw new Error(`Invalid path: ${relativeDirPathFromCwd}`);
|
|
16976
17562
|
}
|
|
16977
17563
|
return dirName;
|
|
16978
17564
|
}
|
|
16979
17565
|
async function listSkills() {
|
|
16980
|
-
const skillsDir =
|
|
17566
|
+
const skillsDir = join119(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
|
|
16981
17567
|
try {
|
|
16982
|
-
const skillDirPaths = await findFilesByGlobs(
|
|
17568
|
+
const skillDirPaths = await findFilesByGlobs(join119(skillsDir, "*"), { type: "dir" });
|
|
16983
17569
|
const skills = await Promise.all(
|
|
16984
17570
|
skillDirPaths.map(async (dirPath) => {
|
|
16985
|
-
const dirName =
|
|
17571
|
+
const dirName = basename27(dirPath);
|
|
16986
17572
|
if (!dirName) return null;
|
|
16987
17573
|
try {
|
|
16988
17574
|
const skill = await RulesyncSkill.fromDir({
|
|
@@ -16990,7 +17576,7 @@ async function listSkills() {
|
|
|
16990
17576
|
});
|
|
16991
17577
|
const frontmatter = skill.getFrontmatter();
|
|
16992
17578
|
return {
|
|
16993
|
-
relativeDirPathFromCwd:
|
|
17579
|
+
relativeDirPathFromCwd: join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
16994
17580
|
frontmatter
|
|
16995
17581
|
};
|
|
16996
17582
|
} catch (error) {
|
|
@@ -17001,7 +17587,9 @@ async function listSkills() {
|
|
|
17001
17587
|
);
|
|
17002
17588
|
return skills.filter((skill) => skill !== null);
|
|
17003
17589
|
} catch (error) {
|
|
17004
|
-
logger.error(
|
|
17590
|
+
logger.error(
|
|
17591
|
+
`Failed to read skills directory (${RULESYNC_SKILLS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17592
|
+
);
|
|
17005
17593
|
return [];
|
|
17006
17594
|
}
|
|
17007
17595
|
}
|
|
@@ -17016,7 +17604,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
|
|
|
17016
17604
|
dirName
|
|
17017
17605
|
});
|
|
17018
17606
|
return {
|
|
17019
|
-
relativeDirPathFromCwd:
|
|
17607
|
+
relativeDirPathFromCwd: join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
17020
17608
|
frontmatter: skill.getFrontmatter(),
|
|
17021
17609
|
body: skill.getBody(),
|
|
17022
17610
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -17044,16 +17632,18 @@ async function putSkill({
|
|
|
17044
17632
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length + otherFiles.reduce((acc, file) => acc + file.name.length + file.body.length, 0);
|
|
17045
17633
|
if (estimatedSize > maxSkillSizeBytes) {
|
|
17046
17634
|
throw new Error(
|
|
17047
|
-
`Skill size ${estimatedSize} bytes exceeds maximum ${maxSkillSizeBytes} bytes (1MB)`
|
|
17635
|
+
`Skill size ${estimatedSize} bytes exceeds maximum ${maxSkillSizeBytes} bytes (1MB) for ${relativeDirPathFromCwd}`
|
|
17048
17636
|
);
|
|
17049
17637
|
}
|
|
17050
17638
|
try {
|
|
17051
17639
|
const existingSkills = await listSkills();
|
|
17052
17640
|
const isUpdate = existingSkills.some(
|
|
17053
|
-
(skill2) => skill2.relativeDirPathFromCwd ===
|
|
17641
|
+
(skill2) => skill2.relativeDirPathFromCwd === join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
17054
17642
|
);
|
|
17055
17643
|
if (!isUpdate && existingSkills.length >= maxSkillsCount) {
|
|
17056
|
-
throw new Error(
|
|
17644
|
+
throw new Error(
|
|
17645
|
+
`Maximum number of skills (${maxSkillsCount}) reached in ${RULESYNC_SKILLS_RELATIVE_DIR_PATH}`
|
|
17646
|
+
);
|
|
17057
17647
|
}
|
|
17058
17648
|
const aiDirFiles = otherFiles.map(mcpSkillFileToAiDirFile);
|
|
17059
17649
|
const skill = new RulesyncSkill({
|
|
@@ -17065,9 +17655,9 @@ async function putSkill({
|
|
|
17065
17655
|
otherFiles: aiDirFiles,
|
|
17066
17656
|
validate: true
|
|
17067
17657
|
});
|
|
17068
|
-
const skillDirPath =
|
|
17658
|
+
const skillDirPath = join119(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
17069
17659
|
await ensureDir(skillDirPath);
|
|
17070
|
-
const skillFilePath =
|
|
17660
|
+
const skillFilePath = join119(skillDirPath, SKILL_FILE_NAME);
|
|
17071
17661
|
const skillFileContent = stringifyFrontmatter(body, frontmatter);
|
|
17072
17662
|
await writeFileContent(skillFilePath, skillFileContent);
|
|
17073
17663
|
for (const file of otherFiles) {
|
|
@@ -17075,15 +17665,15 @@ async function putSkill({
|
|
|
17075
17665
|
relativePath: file.name,
|
|
17076
17666
|
intendedRootDir: skillDirPath
|
|
17077
17667
|
});
|
|
17078
|
-
const filePath =
|
|
17079
|
-
const fileDir =
|
|
17668
|
+
const filePath = join119(skillDirPath, file.name);
|
|
17669
|
+
const fileDir = join119(skillDirPath, dirname3(file.name));
|
|
17080
17670
|
if (fileDir !== skillDirPath) {
|
|
17081
17671
|
await ensureDir(fileDir);
|
|
17082
17672
|
}
|
|
17083
17673
|
await writeFileContent(filePath, file.body);
|
|
17084
17674
|
}
|
|
17085
17675
|
return {
|
|
17086
|
-
relativeDirPathFromCwd:
|
|
17676
|
+
relativeDirPathFromCwd: join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
17087
17677
|
frontmatter: skill.getFrontmatter(),
|
|
17088
17678
|
body: skill.getBody(),
|
|
17089
17679
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -17105,13 +17695,13 @@ async function deleteSkill({
|
|
|
17105
17695
|
intendedRootDir: process.cwd()
|
|
17106
17696
|
});
|
|
17107
17697
|
const dirName = extractDirName(relativeDirPathFromCwd);
|
|
17108
|
-
const skillDirPath =
|
|
17698
|
+
const skillDirPath = join119(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
17109
17699
|
try {
|
|
17110
17700
|
if (await directoryExists(skillDirPath)) {
|
|
17111
17701
|
await removeDirectory(skillDirPath);
|
|
17112
17702
|
}
|
|
17113
17703
|
return {
|
|
17114
|
-
relativeDirPathFromCwd:
|
|
17704
|
+
relativeDirPathFromCwd: join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
17115
17705
|
};
|
|
17116
17706
|
} catch (error) {
|
|
17117
17707
|
throw new Error(
|
|
@@ -17122,29 +17712,29 @@ async function deleteSkill({
|
|
|
17122
17712
|
);
|
|
17123
17713
|
}
|
|
17124
17714
|
}
|
|
17125
|
-
var McpSkillFileSchema =
|
|
17126
|
-
name:
|
|
17127
|
-
body:
|
|
17715
|
+
var McpSkillFileSchema = z60.object({
|
|
17716
|
+
name: z60.string(),
|
|
17717
|
+
body: z60.string()
|
|
17128
17718
|
});
|
|
17129
17719
|
var skillToolSchemas = {
|
|
17130
|
-
listSkills:
|
|
17131
|
-
getSkill:
|
|
17132
|
-
relativeDirPathFromCwd:
|
|
17720
|
+
listSkills: z60.object({}),
|
|
17721
|
+
getSkill: z60.object({
|
|
17722
|
+
relativeDirPathFromCwd: z60.string()
|
|
17133
17723
|
}),
|
|
17134
|
-
putSkill:
|
|
17135
|
-
relativeDirPathFromCwd:
|
|
17724
|
+
putSkill: z60.object({
|
|
17725
|
+
relativeDirPathFromCwd: z60.string(),
|
|
17136
17726
|
frontmatter: RulesyncSkillFrontmatterSchema,
|
|
17137
|
-
body:
|
|
17138
|
-
otherFiles:
|
|
17727
|
+
body: z60.string(),
|
|
17728
|
+
otherFiles: z60.optional(z60.array(McpSkillFileSchema))
|
|
17139
17729
|
}),
|
|
17140
|
-
deleteSkill:
|
|
17141
|
-
relativeDirPathFromCwd:
|
|
17730
|
+
deleteSkill: z60.object({
|
|
17731
|
+
relativeDirPathFromCwd: z60.string()
|
|
17142
17732
|
})
|
|
17143
17733
|
};
|
|
17144
17734
|
var skillTools = {
|
|
17145
17735
|
listSkills: {
|
|
17146
17736
|
name: "listSkills",
|
|
17147
|
-
description: `List all skills from ${
|
|
17737
|
+
description: `List all skills from ${join119(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
|
|
17148
17738
|
parameters: skillToolSchemas.listSkills,
|
|
17149
17739
|
execute: async () => {
|
|
17150
17740
|
const skills = await listSkills();
|
|
@@ -17187,12 +17777,12 @@ var skillTools = {
|
|
|
17187
17777
|
};
|
|
17188
17778
|
|
|
17189
17779
|
// src/mcp/subagents.ts
|
|
17190
|
-
import { basename as
|
|
17191
|
-
import { z as
|
|
17780
|
+
import { basename as basename28, join as join120 } from "path";
|
|
17781
|
+
import { z as z61 } from "zod/mini";
|
|
17192
17782
|
var maxSubagentSizeBytes = 1024 * 1024;
|
|
17193
17783
|
var maxSubagentsCount = 1e3;
|
|
17194
17784
|
async function listSubagents() {
|
|
17195
|
-
const subagentsDir =
|
|
17785
|
+
const subagentsDir = join120(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
17196
17786
|
try {
|
|
17197
17787
|
const files = await listDirectoryFiles(subagentsDir);
|
|
17198
17788
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -17205,7 +17795,7 @@ async function listSubagents() {
|
|
|
17205
17795
|
});
|
|
17206
17796
|
const frontmatter = subagent.getFrontmatter();
|
|
17207
17797
|
return {
|
|
17208
|
-
relativePathFromCwd:
|
|
17798
|
+
relativePathFromCwd: join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
|
|
17209
17799
|
frontmatter
|
|
17210
17800
|
};
|
|
17211
17801
|
} catch (error) {
|
|
@@ -17218,7 +17808,9 @@ async function listSubagents() {
|
|
|
17218
17808
|
(subagent) => subagent !== null
|
|
17219
17809
|
);
|
|
17220
17810
|
} catch (error) {
|
|
17221
|
-
logger.error(
|
|
17811
|
+
logger.error(
|
|
17812
|
+
`Failed to read subagents directory (${RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17813
|
+
);
|
|
17222
17814
|
return [];
|
|
17223
17815
|
}
|
|
17224
17816
|
}
|
|
@@ -17227,14 +17819,14 @@ async function getSubagent({ relativePathFromCwd }) {
|
|
|
17227
17819
|
relativePath: relativePathFromCwd,
|
|
17228
17820
|
intendedRootDir: process.cwd()
|
|
17229
17821
|
});
|
|
17230
|
-
const filename =
|
|
17822
|
+
const filename = basename28(relativePathFromCwd);
|
|
17231
17823
|
try {
|
|
17232
17824
|
const subagent = await RulesyncSubagent.fromFile({
|
|
17233
17825
|
relativeFilePath: filename,
|
|
17234
17826
|
validate: true
|
|
17235
17827
|
});
|
|
17236
17828
|
return {
|
|
17237
|
-
relativePathFromCwd:
|
|
17829
|
+
relativePathFromCwd: join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
17238
17830
|
frontmatter: subagent.getFrontmatter(),
|
|
17239
17831
|
body: subagent.getBody()
|
|
17240
17832
|
};
|
|
@@ -17253,20 +17845,22 @@ async function putSubagent({
|
|
|
17253
17845
|
relativePath: relativePathFromCwd,
|
|
17254
17846
|
intendedRootDir: process.cwd()
|
|
17255
17847
|
});
|
|
17256
|
-
const filename =
|
|
17848
|
+
const filename = basename28(relativePathFromCwd);
|
|
17257
17849
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
17258
17850
|
if (estimatedSize > maxSubagentSizeBytes) {
|
|
17259
17851
|
throw new Error(
|
|
17260
|
-
`Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB)`
|
|
17852
|
+
`Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
17261
17853
|
);
|
|
17262
17854
|
}
|
|
17263
17855
|
try {
|
|
17264
17856
|
const existingSubagents = await listSubagents();
|
|
17265
17857
|
const isUpdate = existingSubagents.some(
|
|
17266
|
-
(subagent2) => subagent2.relativePathFromCwd ===
|
|
17858
|
+
(subagent2) => subagent2.relativePathFromCwd === join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
17267
17859
|
);
|
|
17268
17860
|
if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
|
|
17269
|
-
throw new Error(
|
|
17861
|
+
throw new Error(
|
|
17862
|
+
`Maximum number of subagents (${maxSubagentsCount}) reached in ${RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH}`
|
|
17863
|
+
);
|
|
17270
17864
|
}
|
|
17271
17865
|
const subagent = new RulesyncSubagent({
|
|
17272
17866
|
baseDir: process.cwd(),
|
|
@@ -17276,11 +17870,11 @@ async function putSubagent({
|
|
|
17276
17870
|
body,
|
|
17277
17871
|
validate: true
|
|
17278
17872
|
});
|
|
17279
|
-
const subagentsDir =
|
|
17873
|
+
const subagentsDir = join120(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
17280
17874
|
await ensureDir(subagentsDir);
|
|
17281
17875
|
await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
|
|
17282
17876
|
return {
|
|
17283
|
-
relativePathFromCwd:
|
|
17877
|
+
relativePathFromCwd: join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
17284
17878
|
frontmatter: subagent.getFrontmatter(),
|
|
17285
17879
|
body: subagent.getBody()
|
|
17286
17880
|
};
|
|
@@ -17295,12 +17889,12 @@ async function deleteSubagent({ relativePathFromCwd }) {
|
|
|
17295
17889
|
relativePath: relativePathFromCwd,
|
|
17296
17890
|
intendedRootDir: process.cwd()
|
|
17297
17891
|
});
|
|
17298
|
-
const filename =
|
|
17299
|
-
const fullPath =
|
|
17892
|
+
const filename = basename28(relativePathFromCwd);
|
|
17893
|
+
const fullPath = join120(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
|
|
17300
17894
|
try {
|
|
17301
17895
|
await removeFile(fullPath);
|
|
17302
17896
|
return {
|
|
17303
|
-
relativePathFromCwd:
|
|
17897
|
+
relativePathFromCwd: join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
17304
17898
|
};
|
|
17305
17899
|
} catch (error) {
|
|
17306
17900
|
throw new Error(
|
|
@@ -17312,23 +17906,23 @@ async function deleteSubagent({ relativePathFromCwd }) {
|
|
|
17312
17906
|
}
|
|
17313
17907
|
}
|
|
17314
17908
|
var subagentToolSchemas = {
|
|
17315
|
-
listSubagents:
|
|
17316
|
-
getSubagent:
|
|
17317
|
-
relativePathFromCwd:
|
|
17909
|
+
listSubagents: z61.object({}),
|
|
17910
|
+
getSubagent: z61.object({
|
|
17911
|
+
relativePathFromCwd: z61.string()
|
|
17318
17912
|
}),
|
|
17319
|
-
putSubagent:
|
|
17320
|
-
relativePathFromCwd:
|
|
17913
|
+
putSubagent: z61.object({
|
|
17914
|
+
relativePathFromCwd: z61.string(),
|
|
17321
17915
|
frontmatter: RulesyncSubagentFrontmatterSchema,
|
|
17322
|
-
body:
|
|
17916
|
+
body: z61.string()
|
|
17323
17917
|
}),
|
|
17324
|
-
deleteSubagent:
|
|
17325
|
-
relativePathFromCwd:
|
|
17918
|
+
deleteSubagent: z61.object({
|
|
17919
|
+
relativePathFromCwd: z61.string()
|
|
17326
17920
|
})
|
|
17327
17921
|
};
|
|
17328
17922
|
var subagentTools = {
|
|
17329
17923
|
listSubagents: {
|
|
17330
17924
|
name: "listSubagents",
|
|
17331
|
-
description: `List all subagents from ${
|
|
17925
|
+
description: `List all subagents from ${join120(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
17332
17926
|
parameters: subagentToolSchemas.listSubagents,
|
|
17333
17927
|
execute: async () => {
|
|
17334
17928
|
const subagents = await listSubagents();
|
|
@@ -17370,7 +17964,7 @@ var subagentTools = {
|
|
|
17370
17964
|
};
|
|
17371
17965
|
|
|
17372
17966
|
// src/mcp/tools.ts
|
|
17373
|
-
var rulesyncFeatureSchema =
|
|
17967
|
+
var rulesyncFeatureSchema = z62.enum([
|
|
17374
17968
|
"rule",
|
|
17375
17969
|
"command",
|
|
17376
17970
|
"subagent",
|
|
@@ -17380,21 +17974,21 @@ var rulesyncFeatureSchema = z61.enum([
|
|
|
17380
17974
|
"generate",
|
|
17381
17975
|
"import"
|
|
17382
17976
|
]);
|
|
17383
|
-
var rulesyncOperationSchema =
|
|
17384
|
-
var skillFileSchema =
|
|
17385
|
-
name:
|
|
17386
|
-
body:
|
|
17977
|
+
var rulesyncOperationSchema = z62.enum(["list", "get", "put", "delete", "run"]);
|
|
17978
|
+
var skillFileSchema = z62.object({
|
|
17979
|
+
name: z62.string(),
|
|
17980
|
+
body: z62.string()
|
|
17387
17981
|
});
|
|
17388
|
-
var rulesyncToolSchema =
|
|
17982
|
+
var rulesyncToolSchema = z62.object({
|
|
17389
17983
|
feature: rulesyncFeatureSchema,
|
|
17390
17984
|
operation: rulesyncOperationSchema,
|
|
17391
|
-
targetPathFromCwd:
|
|
17392
|
-
frontmatter:
|
|
17393
|
-
body:
|
|
17394
|
-
otherFiles:
|
|
17395
|
-
content:
|
|
17396
|
-
generateOptions:
|
|
17397
|
-
importOptions:
|
|
17985
|
+
targetPathFromCwd: z62.optional(z62.string()),
|
|
17986
|
+
frontmatter: z62.optional(z62.unknown()),
|
|
17987
|
+
body: z62.optional(z62.string()),
|
|
17988
|
+
otherFiles: z62.optional(z62.array(skillFileSchema)),
|
|
17989
|
+
content: z62.optional(z62.string()),
|
|
17990
|
+
generateOptions: z62.optional(generateOptionsSchema),
|
|
17991
|
+
importOptions: z62.optional(importOptionsSchema)
|
|
17398
17992
|
});
|
|
17399
17993
|
var supportedOperationsByFeature = {
|
|
17400
17994
|
rule: ["list", "get", "put", "delete"],
|
|
@@ -17723,7 +18317,7 @@ async function downloadFile(url, destPath) {
|
|
|
17723
18317
|
redirect: "follow"
|
|
17724
18318
|
});
|
|
17725
18319
|
if (!response.ok) {
|
|
17726
|
-
throw new Error(`Failed to download: HTTP ${response.status}`);
|
|
18320
|
+
throw new Error(`Failed to download ${url}: HTTP ${response.status}`);
|
|
17727
18321
|
}
|
|
17728
18322
|
if (response.url) {
|
|
17729
18323
|
validateDownloadUrl(response.url);
|
|
@@ -17953,7 +18547,7 @@ async function updateCommand(currentVersion, options) {
|
|
|
17953
18547
|
}
|
|
17954
18548
|
|
|
17955
18549
|
// src/cli/index.ts
|
|
17956
|
-
var getVersion = () => "7.
|
|
18550
|
+
var getVersion = () => "7.1.0";
|
|
17957
18551
|
var main = async () => {
|
|
17958
18552
|
const program = new Command();
|
|
17959
18553
|
const version = getVersion();
|
|
@@ -18026,6 +18620,21 @@ var main = async () => {
|
|
|
18026
18620
|
process.exit(1);
|
|
18027
18621
|
}
|
|
18028
18622
|
});
|
|
18623
|
+
program.command("install").description("Install skills from declarative sources in rulesync.jsonc").option("--update", "Force re-resolve all source refs, ignoring lockfile").option("--frozen", "Fail if lockfile is missing or out of sync (for CI)").option("--token <token>", "GitHub token for private repos").option("-c, --config <path>", "Path to configuration file").option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").action(async (options) => {
|
|
18624
|
+
try {
|
|
18625
|
+
await installCommand({
|
|
18626
|
+
update: options.update,
|
|
18627
|
+
frozen: options.frozen,
|
|
18628
|
+
token: options.token,
|
|
18629
|
+
configPath: options.config,
|
|
18630
|
+
verbose: options.verbose,
|
|
18631
|
+
silent: options.silent
|
|
18632
|
+
});
|
|
18633
|
+
} catch (error) {
|
|
18634
|
+
logger.error(formatError(error));
|
|
18635
|
+
process.exit(1);
|
|
18636
|
+
}
|
|
18637
|
+
});
|
|
18029
18638
|
program.command("generate").description("Generate configuration files for AI tools").option(
|
|
18030
18639
|
"-t, --targets <tools>",
|
|
18031
18640
|
"Comma-separated list of tools to generate for (e.g., 'copilot,cursor,cline' or '*' for all)",
|