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.cjs
CHANGED
|
@@ -129,7 +129,7 @@ var logger = new Logger();
|
|
|
129
129
|
|
|
130
130
|
// src/lib/fetch.ts
|
|
131
131
|
var import_promise = require("es-toolkit/promise");
|
|
132
|
-
var
|
|
132
|
+
var import_node_path109 = require("path");
|
|
133
133
|
|
|
134
134
|
// src/constants/rulesync-paths.ts
|
|
135
135
|
var import_node_path = require("path");
|
|
@@ -146,9 +146,15 @@ var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = (0, import_node_path.join)(RULESYNC_R
|
|
|
146
146
|
var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
|
|
147
147
|
var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
|
|
148
148
|
var RULESYNC_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path.join)(RULESYNC_RELATIVE_DIR_PATH, "skills");
|
|
149
|
+
var RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path.join)(
|
|
150
|
+
RULESYNC_SKILLS_RELATIVE_DIR_PATH,
|
|
151
|
+
".curated"
|
|
152
|
+
);
|
|
153
|
+
var RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH = "rulesync.lock";
|
|
149
154
|
var RULESYNC_MCP_FILE_NAME = "mcp.json";
|
|
150
155
|
var RULESYNC_HOOKS_FILE_NAME = "hooks.json";
|
|
151
156
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
157
|
+
var FETCH_CONCURRENCY_LIMIT = 10;
|
|
152
158
|
|
|
153
159
|
// src/features/commands/commands-processor.ts
|
|
154
160
|
var import_node_path19 = require("path");
|
|
@@ -321,10 +327,11 @@ var FeatureProcessor = class {
|
|
|
321
327
|
}
|
|
322
328
|
/**
|
|
323
329
|
* Once converted to rulesync/tool files, write them to the filesystem.
|
|
324
|
-
* Returns the
|
|
330
|
+
* Returns the count and paths of files written.
|
|
325
331
|
*/
|
|
326
332
|
async writeAiFiles(aiFiles) {
|
|
327
333
|
let changedCount = 0;
|
|
334
|
+
const changedPaths = [];
|
|
328
335
|
for (const aiFile of aiFiles) {
|
|
329
336
|
const filePath = aiFile.getFilePath();
|
|
330
337
|
const contentWithNewline = addTrailingNewline(aiFile.getFileContent());
|
|
@@ -338,8 +345,9 @@ var FeatureProcessor = class {
|
|
|
338
345
|
await writeFileContent(filePath, contentWithNewline);
|
|
339
346
|
}
|
|
340
347
|
changedCount++;
|
|
348
|
+
changedPaths.push(aiFile.getRelativePathFromCwd());
|
|
341
349
|
}
|
|
342
|
-
return changedCount;
|
|
350
|
+
return { count: changedCount, paths: changedPaths };
|
|
343
351
|
}
|
|
344
352
|
async removeAiFiles(aiFiles) {
|
|
345
353
|
for (const aiFile of aiFiles) {
|
|
@@ -1679,7 +1687,7 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
|
|
|
1679
1687
|
const result = GeminiCliCommandFrontmatterSchema.safeParse(parsed);
|
|
1680
1688
|
if (!result.success) {
|
|
1681
1689
|
throw new Error(
|
|
1682
|
-
`Invalid frontmatter in
|
|
1690
|
+
`Invalid frontmatter in ${(0, import_node_path14.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
1683
1691
|
);
|
|
1684
1692
|
}
|
|
1685
1693
|
return {
|
|
@@ -1687,7 +1695,10 @@ var GeminiCliCommand = class _GeminiCliCommand extends ToolCommand {
|
|
|
1687
1695
|
description: result.data.description || ""
|
|
1688
1696
|
};
|
|
1689
1697
|
} catch (error) {
|
|
1690
|
-
throw new Error(
|
|
1698
|
+
throw new Error(
|
|
1699
|
+
`Failed to parse TOML command file (${(0, import_node_path14.join)(this.relativeDirPath, this.relativeFilePath)}): ${error}`,
|
|
1700
|
+
{ cause: error }
|
|
1701
|
+
);
|
|
1691
1702
|
}
|
|
1692
1703
|
}
|
|
1693
1704
|
getBody() {
|
|
@@ -2442,7 +2453,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2442
2453
|
(path4) => RulesyncCommand.fromFile({ relativeFilePath: (0, import_node_path19.basename)(path4) })
|
|
2443
2454
|
)
|
|
2444
2455
|
);
|
|
2445
|
-
logger.
|
|
2456
|
+
logger.debug(`Successfully loaded ${rulesyncCommands.length} rulesync commands`);
|
|
2446
2457
|
return rulesyncCommands;
|
|
2447
2458
|
}
|
|
2448
2459
|
/**
|
|
@@ -2466,7 +2477,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2466
2477
|
global: this.global
|
|
2467
2478
|
})
|
|
2468
2479
|
).filter((cmd) => cmd.isDeletable());
|
|
2469
|
-
logger.
|
|
2480
|
+
logger.debug(`Successfully loaded ${toolCommands2.length} ${paths.relativeDirPath} commands`);
|
|
2470
2481
|
return toolCommands2;
|
|
2471
2482
|
}
|
|
2472
2483
|
const toolCommands = await Promise.all(
|
|
@@ -2478,7 +2489,7 @@ var CommandsProcessor = class extends FeatureProcessor {
|
|
|
2478
2489
|
})
|
|
2479
2490
|
)
|
|
2480
2491
|
);
|
|
2481
|
-
logger.
|
|
2492
|
+
logger.debug(`Successfully loaded ${toolCommands.length} ${paths.relativeDirPath} commands`);
|
|
2482
2493
|
return toolCommands;
|
|
2483
2494
|
}
|
|
2484
2495
|
/**
|
|
@@ -2815,10 +2826,7 @@ var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
|
2815
2826
|
}) {
|
|
2816
2827
|
const paths = _ClaudecodeHooks.getSettablePaths({ global });
|
|
2817
2828
|
const filePath = (0, import_node_path21.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath);
|
|
2818
|
-
const fileContent = await
|
|
2819
|
-
filePath,
|
|
2820
|
-
JSON.stringify({ hooks: {} }, null, 2)
|
|
2821
|
-
);
|
|
2829
|
+
const fileContent = await readFileContentOrNull(filePath) ?? '{"hooks":{}}';
|
|
2822
2830
|
return new _ClaudecodeHooks({
|
|
2823
2831
|
baseDir,
|
|
2824
2832
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -2865,9 +2873,12 @@ var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
|
|
|
2865
2873
|
try {
|
|
2866
2874
|
settings = JSON.parse(this.getFileContent());
|
|
2867
2875
|
} catch (error) {
|
|
2868
|
-
throw new Error(
|
|
2869
|
-
|
|
2870
|
-
|
|
2876
|
+
throw new Error(
|
|
2877
|
+
`Failed to parse Claude hooks content in ${(0, import_node_path21.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`,
|
|
2878
|
+
{
|
|
2879
|
+
cause: error
|
|
2880
|
+
}
|
|
2881
|
+
);
|
|
2871
2882
|
}
|
|
2872
2883
|
const hooks = claudeHooksToCanonical(settings.hooks);
|
|
2873
2884
|
return this.toRulesyncHooksDefault({
|
|
@@ -3090,10 +3101,7 @@ var FactorydroidHooks = class _FactorydroidHooks extends ToolHooks {
|
|
|
3090
3101
|
}) {
|
|
3091
3102
|
const paths = _FactorydroidHooks.getSettablePaths({ global });
|
|
3092
3103
|
const filePath = (0, import_node_path23.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath);
|
|
3093
|
-
const fileContent = await
|
|
3094
|
-
filePath,
|
|
3095
|
-
JSON.stringify({ hooks: {} }, null, 2)
|
|
3096
|
-
);
|
|
3104
|
+
const fileContent = await readFileContentOrNull(filePath) ?? '{"hooks":{}}';
|
|
3097
3105
|
return new _FactorydroidHooks({
|
|
3098
3106
|
baseDir,
|
|
3099
3107
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -3140,9 +3148,12 @@ var FactorydroidHooks = class _FactorydroidHooks extends ToolHooks {
|
|
|
3140
3148
|
try {
|
|
3141
3149
|
settings = JSON.parse(this.getFileContent());
|
|
3142
3150
|
} catch (error) {
|
|
3143
|
-
throw new Error(
|
|
3144
|
-
|
|
3145
|
-
|
|
3151
|
+
throw new Error(
|
|
3152
|
+
`Failed to parse Factory Droid hooks content in ${(0, import_node_path23.join)(this.getRelativeDirPath(), this.getRelativeFilePath())}: ${formatError(error)}`,
|
|
3153
|
+
{
|
|
3154
|
+
cause: error
|
|
3155
|
+
}
|
|
3156
|
+
);
|
|
3146
3157
|
}
|
|
3147
3158
|
const hooks = factorydroidHooksToCanonical(settings.hooks);
|
|
3148
3159
|
return this.toRulesyncHooksDefault({
|
|
@@ -3395,7 +3406,9 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3395
3406
|
})
|
|
3396
3407
|
];
|
|
3397
3408
|
} catch (error) {
|
|
3398
|
-
logger.error(
|
|
3409
|
+
logger.error(
|
|
3410
|
+
`Failed to load Rulesync hooks file (${RULESYNC_HOOKS_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
3411
|
+
);
|
|
3399
3412
|
return [];
|
|
3400
3413
|
}
|
|
3401
3414
|
}
|
|
@@ -3412,7 +3425,7 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3412
3425
|
global: this.global
|
|
3413
3426
|
});
|
|
3414
3427
|
const list = toolHooks2.isDeletable?.() !== false ? [toolHooks2] : [];
|
|
3415
|
-
logger.
|
|
3428
|
+
logger.debug(
|
|
3416
3429
|
`Successfully loaded ${list.length} ${this.toolTarget} hooks files for deletion`
|
|
3417
3430
|
);
|
|
3418
3431
|
return list;
|
|
@@ -3422,7 +3435,7 @@ var HooksProcessor = class extends FeatureProcessor {
|
|
|
3422
3435
|
validate: true,
|
|
3423
3436
|
global: this.global
|
|
3424
3437
|
});
|
|
3425
|
-
logger.
|
|
3438
|
+
logger.debug(`Successfully loaded 1 ${this.toolTarget} hooks file`);
|
|
3426
3439
|
return [toolHooks];
|
|
3427
3440
|
} catch (error) {
|
|
3428
3441
|
const msg = `Failed to load hooks files for tool target: ${this.toolTarget}: ${formatError(error)}`;
|
|
@@ -4486,7 +4499,9 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
4486
4499
|
try {
|
|
4487
4500
|
return [await RulesyncIgnore.fromFile()];
|
|
4488
4501
|
} catch (error) {
|
|
4489
|
-
logger.error(
|
|
4502
|
+
logger.error(
|
|
4503
|
+
`Failed to load rulesync ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
4504
|
+
);
|
|
4490
4505
|
return [];
|
|
4491
4506
|
}
|
|
4492
4507
|
}
|
|
@@ -4512,7 +4527,7 @@ var IgnoreProcessor = class extends FeatureProcessor {
|
|
|
4512
4527
|
const toolIgnores = await this.loadToolIgnores();
|
|
4513
4528
|
return toolIgnores;
|
|
4514
4529
|
} catch (error) {
|
|
4515
|
-
const errorMessage = `Failed to load tool files: ${formatError(error)}`;
|
|
4530
|
+
const errorMessage = `Failed to load tool files for ${this.toolTarget}: ${formatError(error)}`;
|
|
4516
4531
|
if (error instanceof Error && error.message.includes("no such file or directory")) {
|
|
4517
4532
|
logger.debug(errorMessage);
|
|
4518
4533
|
} else {
|
|
@@ -4777,10 +4792,7 @@ var ClaudecodeMcp = class _ClaudecodeMcp extends ToolMcp {
|
|
|
4777
4792
|
global = false
|
|
4778
4793
|
}) {
|
|
4779
4794
|
const paths = this.getSettablePaths({ global });
|
|
4780
|
-
const fileContent = await
|
|
4781
|
-
(0, import_node_path39.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
4782
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
4783
|
-
);
|
|
4795
|
+
const fileContent = await readFileContentOrNull((0, import_node_path39.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
4784
4796
|
const json = JSON.parse(fileContent);
|
|
4785
4797
|
const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
|
|
4786
4798
|
return new _ClaudecodeMcp({
|
|
@@ -5333,10 +5345,7 @@ var GeminiCliMcp = class _GeminiCliMcp extends ToolMcp {
|
|
|
5333
5345
|
global = false
|
|
5334
5346
|
}) {
|
|
5335
5347
|
const paths = this.getSettablePaths({ global });
|
|
5336
|
-
const fileContent = await
|
|
5337
|
-
(0, import_node_path45.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5338
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5339
|
-
);
|
|
5348
|
+
const fileContent = await readFileContentOrNull((0, import_node_path45.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5340
5349
|
const json = JSON.parse(fileContent);
|
|
5341
5350
|
const newJson = { ...json, mcpServers: json.mcpServers ?? {} };
|
|
5342
5351
|
return new _GeminiCliMcp({
|
|
@@ -5491,10 +5500,7 @@ var KiloMcp = class _KiloMcp extends ToolMcp {
|
|
|
5491
5500
|
validate = true
|
|
5492
5501
|
}) {
|
|
5493
5502
|
const paths = this.getSettablePaths();
|
|
5494
|
-
const fileContent = await
|
|
5495
|
-
(0, import_node_path47.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5496
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5497
|
-
);
|
|
5503
|
+
const fileContent = await readFileContentOrNull((0, import_node_path47.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5498
5504
|
return new _KiloMcp({
|
|
5499
5505
|
baseDir,
|
|
5500
5506
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -5563,10 +5569,7 @@ var KiroMcp = class _KiroMcp extends ToolMcp {
|
|
|
5563
5569
|
validate = true
|
|
5564
5570
|
}) {
|
|
5565
5571
|
const paths = this.getSettablePaths();
|
|
5566
|
-
const fileContent = await
|
|
5567
|
-
(0, import_node_path48.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5568
|
-
JSON.stringify({ mcpServers: {} }, null, 2)
|
|
5569
|
-
);
|
|
5572
|
+
const fileContent = await readFileContentOrNull((0, import_node_path48.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcpServers":{}}';
|
|
5570
5573
|
return new _KiroMcp({
|
|
5571
5574
|
baseDir,
|
|
5572
5575
|
relativeDirPath: paths.relativeDirPath,
|
|
@@ -5737,10 +5740,7 @@ var OpencodeMcp = class _OpencodeMcp extends ToolMcp {
|
|
|
5737
5740
|
global = false
|
|
5738
5741
|
}) {
|
|
5739
5742
|
const paths = this.getSettablePaths({ global });
|
|
5740
|
-
const fileContent = await
|
|
5741
|
-
(0, import_node_path49.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath),
|
|
5742
|
-
JSON.stringify({ mcp: {} }, null, 2)
|
|
5743
|
-
);
|
|
5743
|
+
const fileContent = await readFileContentOrNull((0, import_node_path49.join)(baseDir, paths.relativeDirPath, paths.relativeFilePath)) ?? '{"mcp":{}}';
|
|
5744
5744
|
const json = JSON.parse(fileContent);
|
|
5745
5745
|
const newJson = { ...json, mcp: json.mcp ?? {} };
|
|
5746
5746
|
return new _OpencodeMcp({
|
|
@@ -6068,7 +6068,9 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6068
6068
|
try {
|
|
6069
6069
|
return [await RulesyncMcp.fromFile({})];
|
|
6070
6070
|
} catch (error) {
|
|
6071
|
-
logger.error(
|
|
6071
|
+
logger.error(
|
|
6072
|
+
`Failed to load a Rulesync MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`
|
|
6073
|
+
);
|
|
6072
6074
|
return [];
|
|
6073
6075
|
}
|
|
6074
6076
|
}
|
|
@@ -6090,7 +6092,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6090
6092
|
global: this.global
|
|
6091
6093
|
});
|
|
6092
6094
|
const toolMcps2 = toolMcp.isDeletable() ? [toolMcp] : [];
|
|
6093
|
-
logger.
|
|
6095
|
+
logger.debug(`Successfully loaded ${toolMcps2.length} ${this.toolTarget} MCP files`);
|
|
6094
6096
|
return toolMcps2;
|
|
6095
6097
|
}
|
|
6096
6098
|
const toolMcps = [
|
|
@@ -6100,7 +6102,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6100
6102
|
global: this.global
|
|
6101
6103
|
})
|
|
6102
6104
|
];
|
|
6103
|
-
logger.
|
|
6105
|
+
logger.debug(`Successfully loaded ${toolMcps.length} ${this.toolTarget} MCP files`);
|
|
6104
6106
|
return toolMcps;
|
|
6105
6107
|
} catch (error) {
|
|
6106
6108
|
const errorMessage = `Failed to load MCP files for tool target: ${this.toolTarget}: ${formatError(error)}`;
|
|
@@ -6160,7 +6162,7 @@ var McpProcessor = class extends FeatureProcessor {
|
|
|
6160
6162
|
|
|
6161
6163
|
// src/features/rules/rules-processor.ts
|
|
6162
6164
|
var import_toon = require("@toon-format/toon");
|
|
6163
|
-
var
|
|
6165
|
+
var import_node_path108 = require("path");
|
|
6164
6166
|
var import_mini48 = require("zod/mini");
|
|
6165
6167
|
|
|
6166
6168
|
// src/constants/general.ts
|
|
@@ -6623,7 +6625,7 @@ var FactorydroidSkill = class _FactorydroidSkill extends SimulatedSkill {
|
|
|
6623
6625
|
};
|
|
6624
6626
|
|
|
6625
6627
|
// src/features/skills/skills-processor.ts
|
|
6626
|
-
var
|
|
6628
|
+
var import_node_path71 = require("path");
|
|
6627
6629
|
var import_mini33 = require("zod/mini");
|
|
6628
6630
|
|
|
6629
6631
|
// src/types/dir-feature-processor.ts
|
|
@@ -6651,6 +6653,7 @@ var DirFeatureProcessor = class {
|
|
|
6651
6653
|
*/
|
|
6652
6654
|
async writeAiDirs(aiDirs) {
|
|
6653
6655
|
let changedCount = 0;
|
|
6656
|
+
const changedPaths = [];
|
|
6654
6657
|
for (const aiDir of aiDirs) {
|
|
6655
6658
|
const dirPath = aiDir.getDirPath();
|
|
6656
6659
|
let dirHasChanges = false;
|
|
@@ -6681,19 +6684,23 @@ var DirFeatureProcessor = class {
|
|
|
6681
6684
|
if (!dirHasChanges) {
|
|
6682
6685
|
continue;
|
|
6683
6686
|
}
|
|
6687
|
+
const relativeDir = aiDir.getRelativePathFromCwd();
|
|
6684
6688
|
if (this.dryRun) {
|
|
6685
6689
|
logger.info(`[DRY RUN] Would create directory: ${dirPath}`);
|
|
6686
6690
|
if (mainFile) {
|
|
6687
6691
|
logger.info(`[DRY RUN] Would write: ${(0, import_node_path56.join)(dirPath, mainFile.name)}`);
|
|
6692
|
+
changedPaths.push((0, import_node_path56.join)(relativeDir, mainFile.name));
|
|
6688
6693
|
}
|
|
6689
6694
|
for (const file of otherFiles) {
|
|
6690
6695
|
logger.info(`[DRY RUN] Would write: ${(0, import_node_path56.join)(dirPath, file.relativeFilePathToDirPath)}`);
|
|
6696
|
+
changedPaths.push((0, import_node_path56.join)(relativeDir, file.relativeFilePathToDirPath));
|
|
6691
6697
|
}
|
|
6692
6698
|
} else {
|
|
6693
6699
|
await ensureDir(dirPath);
|
|
6694
6700
|
if (mainFile && mainFileContent) {
|
|
6695
6701
|
const mainFilePath = (0, import_node_path56.join)(dirPath, mainFile.name);
|
|
6696
6702
|
await writeFileContent(mainFilePath, mainFileContent);
|
|
6703
|
+
changedPaths.push((0, import_node_path56.join)(relativeDir, mainFile.name));
|
|
6697
6704
|
}
|
|
6698
6705
|
for (const [i, file] of otherFiles.entries()) {
|
|
6699
6706
|
const filePath = (0, import_node_path56.join)(dirPath, file.relativeFilePathToDirPath);
|
|
@@ -6704,11 +6711,12 @@ var DirFeatureProcessor = class {
|
|
|
6704
6711
|
);
|
|
6705
6712
|
}
|
|
6706
6713
|
await writeFileContent(filePath, content);
|
|
6714
|
+
changedPaths.push((0, import_node_path56.join)(relativeDir, file.relativeFilePathToDirPath));
|
|
6707
6715
|
}
|
|
6708
6716
|
}
|
|
6709
6717
|
changedCount++;
|
|
6710
6718
|
}
|
|
6711
|
-
return changedCount;
|
|
6719
|
+
return { count: changedCount, paths: changedPaths };
|
|
6712
6720
|
}
|
|
6713
6721
|
async removeAiDirs(aiDirs) {
|
|
6714
6722
|
for (const aiDir of aiDirs) {
|
|
@@ -6805,7 +6813,7 @@ var RulesyncSkill = class _RulesyncSkill extends AiDir {
|
|
|
6805
6813
|
}
|
|
6806
6814
|
getFrontmatter() {
|
|
6807
6815
|
if (!this.mainFile?.frontmatter) {
|
|
6808
|
-
throw new Error(
|
|
6816
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path57.join)(this.relativeDirPath, this.dirName)}`);
|
|
6809
6817
|
}
|
|
6810
6818
|
const result = RulesyncSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
6811
6819
|
return result;
|
|
@@ -6906,7 +6914,7 @@ var AgentsSkillsSkill = class _AgentsSkillsSkill extends ToolSkill {
|
|
|
6906
6914
|
}
|
|
6907
6915
|
getFrontmatter() {
|
|
6908
6916
|
if (!this.mainFile?.frontmatter) {
|
|
6909
|
-
throw new Error(
|
|
6917
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path58.join)(this.relativeDirPath, this.dirName)}`);
|
|
6910
6918
|
}
|
|
6911
6919
|
const result = AgentsSkillsSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
6912
6920
|
return result;
|
|
@@ -7070,7 +7078,7 @@ var AntigravitySkill = class _AntigravitySkill extends ToolSkill {
|
|
|
7070
7078
|
}
|
|
7071
7079
|
getFrontmatter() {
|
|
7072
7080
|
if (!this.mainFile?.frontmatter) {
|
|
7073
|
-
throw new Error(
|
|
7081
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path59.join)(this.relativeDirPath, this.dirName)}`);
|
|
7074
7082
|
}
|
|
7075
7083
|
const result = AntigravitySkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7076
7084
|
return result;
|
|
@@ -7229,7 +7237,7 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
|
|
|
7229
7237
|
}
|
|
7230
7238
|
getFrontmatter() {
|
|
7231
7239
|
if (!this.mainFile?.frontmatter) {
|
|
7232
|
-
throw new Error(
|
|
7240
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path60.join)(this.relativeDirPath, this.dirName)}`);
|
|
7233
7241
|
}
|
|
7234
7242
|
const result = ClaudecodeSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7235
7243
|
return result;
|
|
@@ -7398,7 +7406,7 @@ var CodexCliSkill = class _CodexCliSkill extends ToolSkill {
|
|
|
7398
7406
|
}
|
|
7399
7407
|
getFrontmatter() {
|
|
7400
7408
|
if (!this.mainFile?.frontmatter) {
|
|
7401
|
-
throw new Error(
|
|
7409
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path61.join)(this.relativeDirPath, this.dirName)}`);
|
|
7402
7410
|
}
|
|
7403
7411
|
const result = CodexCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7404
7412
|
return result;
|
|
@@ -7568,7 +7576,7 @@ var CopilotSkill = class _CopilotSkill extends ToolSkill {
|
|
|
7568
7576
|
}
|
|
7569
7577
|
getFrontmatter() {
|
|
7570
7578
|
if (!this.mainFile?.frontmatter) {
|
|
7571
|
-
throw new Error(
|
|
7579
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path62.join)(this.relativeDirPath, this.dirName)}`);
|
|
7572
7580
|
}
|
|
7573
7581
|
const result = CopilotSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7574
7582
|
return result;
|
|
@@ -7731,7 +7739,7 @@ var CursorSkill = class _CursorSkill extends ToolSkill {
|
|
|
7731
7739
|
}
|
|
7732
7740
|
getFrontmatter() {
|
|
7733
7741
|
if (!this.mainFile?.frontmatter) {
|
|
7734
|
-
throw new Error(
|
|
7742
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path63.join)(this.relativeDirPath, this.dirName)}`);
|
|
7735
7743
|
}
|
|
7736
7744
|
const result = CursorSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7737
7745
|
return result;
|
|
@@ -7890,7 +7898,7 @@ var GeminiCliSkill = class _GeminiCliSkill extends ToolSkill {
|
|
|
7890
7898
|
}
|
|
7891
7899
|
getFrontmatter() {
|
|
7892
7900
|
if (!this.mainFile?.frontmatter) {
|
|
7893
|
-
throw new Error(
|
|
7901
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path64.join)(this.relativeDirPath, this.dirName)}`);
|
|
7894
7902
|
}
|
|
7895
7903
|
const result = GeminiCliSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
7896
7904
|
return result;
|
|
@@ -8049,7 +8057,7 @@ var KiloSkill = class _KiloSkill extends ToolSkill {
|
|
|
8049
8057
|
}
|
|
8050
8058
|
getFrontmatter() {
|
|
8051
8059
|
if (!this.mainFile?.frontmatter) {
|
|
8052
|
-
throw new Error(
|
|
8060
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path65.join)(this.relativeDirPath, this.dirName)}`);
|
|
8053
8061
|
}
|
|
8054
8062
|
const result = KiloSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8055
8063
|
return result;
|
|
@@ -8227,7 +8235,7 @@ var KiroSkill = class _KiroSkill extends ToolSkill {
|
|
|
8227
8235
|
}
|
|
8228
8236
|
getFrontmatter() {
|
|
8229
8237
|
if (!this.mainFile?.frontmatter) {
|
|
8230
|
-
throw new Error(
|
|
8238
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path66.join)(this.relativeDirPath, this.dirName)}`);
|
|
8231
8239
|
}
|
|
8232
8240
|
const result = KiroSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8233
8241
|
return result;
|
|
@@ -8404,7 +8412,7 @@ var OpenCodeSkill = class _OpenCodeSkill extends ToolSkill {
|
|
|
8404
8412
|
}
|
|
8405
8413
|
getFrontmatter() {
|
|
8406
8414
|
if (!this.mainFile?.frontmatter) {
|
|
8407
|
-
throw new Error(
|
|
8415
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path67.join)(this.relativeDirPath, this.dirName)}`);
|
|
8408
8416
|
}
|
|
8409
8417
|
const result = OpenCodeSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8410
8418
|
return result;
|
|
@@ -8569,7 +8577,7 @@ var ReplitSkill = class _ReplitSkill extends ToolSkill {
|
|
|
8569
8577
|
}
|
|
8570
8578
|
getFrontmatter() {
|
|
8571
8579
|
if (!this.mainFile?.frontmatter) {
|
|
8572
|
-
throw new Error(
|
|
8580
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path68.join)(this.relativeDirPath, this.dirName)}`);
|
|
8573
8581
|
}
|
|
8574
8582
|
const result = ReplitSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8575
8583
|
return result;
|
|
@@ -8728,7 +8736,7 @@ var RooSkill = class _RooSkill extends ToolSkill {
|
|
|
8728
8736
|
}
|
|
8729
8737
|
getFrontmatter() {
|
|
8730
8738
|
if (!this.mainFile?.frontmatter) {
|
|
8731
|
-
throw new Error(
|
|
8739
|
+
throw new Error(`Frontmatter is not defined in ${(0, import_node_path69.join)(this.relativeDirPath, this.dirName)}`);
|
|
8732
8740
|
}
|
|
8733
8741
|
const result = RooSkillFrontmatterSchema.parse(this.mainFile.frontmatter);
|
|
8734
8742
|
return result;
|
|
@@ -8859,6 +8867,23 @@ var RooSkill = class _RooSkill extends ToolSkill {
|
|
|
8859
8867
|
}
|
|
8860
8868
|
};
|
|
8861
8869
|
|
|
8870
|
+
// src/features/skills/skills-utils.ts
|
|
8871
|
+
var import_node_path70 = require("path");
|
|
8872
|
+
async function getLocalSkillDirNames(baseDir) {
|
|
8873
|
+
const skillsDir = (0, import_node_path70.join)(baseDir, RULESYNC_SKILLS_RELATIVE_DIR_PATH);
|
|
8874
|
+
const names = /* @__PURE__ */ new Set();
|
|
8875
|
+
if (!await directoryExists(skillsDir)) {
|
|
8876
|
+
return names;
|
|
8877
|
+
}
|
|
8878
|
+
const dirPaths = await findFilesByGlobs((0, import_node_path70.join)(skillsDir, "*"), { type: "dir" });
|
|
8879
|
+
for (const dirPath of dirPaths) {
|
|
8880
|
+
const name = (0, import_node_path70.basename)(dirPath);
|
|
8881
|
+
if (name === (0, import_node_path70.basename)(RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH)) continue;
|
|
8882
|
+
names.add(name);
|
|
8883
|
+
}
|
|
8884
|
+
return names;
|
|
8885
|
+
}
|
|
8886
|
+
|
|
8862
8887
|
// src/features/skills/skills-processor.ts
|
|
8863
8888
|
var skillsProcessorToolTargetTuple = [
|
|
8864
8889
|
"agentsmd",
|
|
@@ -9060,19 +9085,46 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9060
9085
|
/**
|
|
9061
9086
|
* Implementation of abstract method from DirFeatureProcessor
|
|
9062
9087
|
* Load and parse rulesync skill directories from .rulesync/skills/ directory
|
|
9088
|
+
* and also from .rulesync/skills/.curated/ for remote skills.
|
|
9089
|
+
* Local skills take precedence over curated skills with the same name.
|
|
9063
9090
|
*/
|
|
9064
9091
|
async loadRulesyncDirs() {
|
|
9065
|
-
const
|
|
9066
|
-
const
|
|
9067
|
-
|
|
9068
|
-
const dirNames = dirPaths.map((path4) => (0, import_node_path70.basename)(path4));
|
|
9069
|
-
const rulesyncSkills = await Promise.all(
|
|
9070
|
-
dirNames.map(
|
|
9092
|
+
const localDirNames = [...await getLocalSkillDirNames(this.baseDir)];
|
|
9093
|
+
const localSkills = await Promise.all(
|
|
9094
|
+
localDirNames.map(
|
|
9071
9095
|
(dirName) => RulesyncSkill.fromDir({ baseDir: this.baseDir, dirName, global: this.global })
|
|
9072
9096
|
)
|
|
9073
9097
|
);
|
|
9074
|
-
|
|
9075
|
-
|
|
9098
|
+
const localSkillNames = new Set(localDirNames);
|
|
9099
|
+
const curatedDirPath = (0, import_node_path71.join)(this.baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
9100
|
+
let curatedSkills = [];
|
|
9101
|
+
if (await directoryExists(curatedDirPath)) {
|
|
9102
|
+
const curatedDirPaths = await findFilesByGlobs((0, import_node_path71.join)(curatedDirPath, "*"), { type: "dir" });
|
|
9103
|
+
const curatedDirNames = curatedDirPaths.map((path4) => (0, import_node_path71.basename)(path4));
|
|
9104
|
+
const nonConflicting = curatedDirNames.filter((name) => {
|
|
9105
|
+
if (localSkillNames.has(name)) {
|
|
9106
|
+
logger.debug(`Skipping curated skill "${name}": local skill takes precedence.`);
|
|
9107
|
+
return false;
|
|
9108
|
+
}
|
|
9109
|
+
return true;
|
|
9110
|
+
});
|
|
9111
|
+
const curatedRelativeDirPath = RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH;
|
|
9112
|
+
curatedSkills = await Promise.all(
|
|
9113
|
+
nonConflicting.map(
|
|
9114
|
+
(dirName) => RulesyncSkill.fromDir({
|
|
9115
|
+
baseDir: this.baseDir,
|
|
9116
|
+
relativeDirPath: curatedRelativeDirPath,
|
|
9117
|
+
dirName,
|
|
9118
|
+
global: this.global
|
|
9119
|
+
})
|
|
9120
|
+
)
|
|
9121
|
+
);
|
|
9122
|
+
}
|
|
9123
|
+
const allSkills = [...localSkills, ...curatedSkills];
|
|
9124
|
+
logger.debug(
|
|
9125
|
+
`Successfully loaded ${allSkills.length} rulesync skills (${localSkills.length} local, ${curatedSkills.length} curated)`
|
|
9126
|
+
);
|
|
9127
|
+
return allSkills;
|
|
9076
9128
|
}
|
|
9077
9129
|
/**
|
|
9078
9130
|
* Implementation of abstract method from DirFeatureProcessor
|
|
@@ -9081,9 +9133,9 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9081
9133
|
async loadToolDirs() {
|
|
9082
9134
|
const factory = this.getFactory(this.toolTarget);
|
|
9083
9135
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
9084
|
-
const skillsDirPath = (0,
|
|
9085
|
-
const dirPaths = await findFilesByGlobs((0,
|
|
9086
|
-
const dirNames = dirPaths.map((path4) => (0,
|
|
9136
|
+
const skillsDirPath = (0, import_node_path71.join)(this.baseDir, paths.relativeDirPath);
|
|
9137
|
+
const dirPaths = await findFilesByGlobs((0, import_node_path71.join)(skillsDirPath, "*"), { type: "dir" });
|
|
9138
|
+
const dirNames = dirPaths.map((path4) => (0, import_node_path71.basename)(path4));
|
|
9087
9139
|
const toolSkills = await Promise.all(
|
|
9088
9140
|
dirNames.map(
|
|
9089
9141
|
(dirName) => factory.class.fromDir({
|
|
@@ -9093,15 +9145,15 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9093
9145
|
})
|
|
9094
9146
|
)
|
|
9095
9147
|
);
|
|
9096
|
-
logger.
|
|
9148
|
+
logger.debug(`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills`);
|
|
9097
9149
|
return toolSkills;
|
|
9098
9150
|
}
|
|
9099
9151
|
async loadToolDirsToDelete() {
|
|
9100
9152
|
const factory = this.getFactory(this.toolTarget);
|
|
9101
9153
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
9102
|
-
const skillsDirPath = (0,
|
|
9103
|
-
const dirPaths = await findFilesByGlobs((0,
|
|
9104
|
-
const dirNames = dirPaths.map((path4) => (0,
|
|
9154
|
+
const skillsDirPath = (0, import_node_path71.join)(this.baseDir, paths.relativeDirPath);
|
|
9155
|
+
const dirPaths = await findFilesByGlobs((0, import_node_path71.join)(skillsDirPath, "*"), { type: "dir" });
|
|
9156
|
+
const dirNames = dirPaths.map((path4) => (0, import_node_path71.basename)(path4));
|
|
9105
9157
|
const toolSkills = dirNames.map(
|
|
9106
9158
|
(dirName) => factory.class.forDeletion({
|
|
9107
9159
|
baseDir: this.baseDir,
|
|
@@ -9110,7 +9162,7 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9110
9162
|
global: this.global
|
|
9111
9163
|
})
|
|
9112
9164
|
);
|
|
9113
|
-
logger.
|
|
9165
|
+
logger.debug(
|
|
9114
9166
|
`Successfully loaded ${toolSkills.length} ${paths.relativeDirPath} skills for deletion`
|
|
9115
9167
|
);
|
|
9116
9168
|
return toolSkills;
|
|
@@ -9162,10 +9214,10 @@ var SkillsProcessor = class extends DirFeatureProcessor {
|
|
|
9162
9214
|
};
|
|
9163
9215
|
|
|
9164
9216
|
// src/features/subagents/agentsmd-subagent.ts
|
|
9165
|
-
var
|
|
9217
|
+
var import_node_path73 = require("path");
|
|
9166
9218
|
|
|
9167
9219
|
// src/features/subagents/simulated-subagent.ts
|
|
9168
|
-
var
|
|
9220
|
+
var import_node_path72 = require("path");
|
|
9169
9221
|
var import_mini34 = require("zod/mini");
|
|
9170
9222
|
|
|
9171
9223
|
// src/features/subagents/tool-subagent.ts
|
|
@@ -9221,7 +9273,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9221
9273
|
const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9222
9274
|
if (!result.success) {
|
|
9223
9275
|
throw new Error(
|
|
9224
|
-
`Invalid frontmatter in ${(0,
|
|
9276
|
+
`Invalid frontmatter in ${(0, import_node_path72.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9225
9277
|
);
|
|
9226
9278
|
}
|
|
9227
9279
|
}
|
|
@@ -9272,7 +9324,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9272
9324
|
return {
|
|
9273
9325
|
success: false,
|
|
9274
9326
|
error: new Error(
|
|
9275
|
-
`Invalid frontmatter in ${(0,
|
|
9327
|
+
`Invalid frontmatter in ${(0, import_node_path72.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9276
9328
|
)
|
|
9277
9329
|
};
|
|
9278
9330
|
}
|
|
@@ -9282,7 +9334,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9282
9334
|
relativeFilePath,
|
|
9283
9335
|
validate = true
|
|
9284
9336
|
}) {
|
|
9285
|
-
const filePath = (0,
|
|
9337
|
+
const filePath = (0, import_node_path72.join)(baseDir, this.getSettablePaths().relativeDirPath, relativeFilePath);
|
|
9286
9338
|
const fileContent = await readFileContent(filePath);
|
|
9287
9339
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9288
9340
|
const result = SimulatedSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9292,7 +9344,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9292
9344
|
return {
|
|
9293
9345
|
baseDir,
|
|
9294
9346
|
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
9295
|
-
relativeFilePath: (0,
|
|
9347
|
+
relativeFilePath: (0, import_node_path72.basename)(relativeFilePath),
|
|
9296
9348
|
frontmatter: result.data,
|
|
9297
9349
|
body: content.trim(),
|
|
9298
9350
|
validate
|
|
@@ -9318,7 +9370,7 @@ var SimulatedSubagent = class extends ToolSubagent {
|
|
|
9318
9370
|
var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
|
|
9319
9371
|
static getSettablePaths() {
|
|
9320
9372
|
return {
|
|
9321
|
-
relativeDirPath: (0,
|
|
9373
|
+
relativeDirPath: (0, import_node_path73.join)(".agents", "subagents")
|
|
9322
9374
|
};
|
|
9323
9375
|
}
|
|
9324
9376
|
static async fromFile(params) {
|
|
@@ -9341,11 +9393,11 @@ var AgentsmdSubagent = class _AgentsmdSubagent extends SimulatedSubagent {
|
|
|
9341
9393
|
};
|
|
9342
9394
|
|
|
9343
9395
|
// src/features/subagents/codexcli-subagent.ts
|
|
9344
|
-
var
|
|
9396
|
+
var import_node_path74 = require("path");
|
|
9345
9397
|
var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
|
|
9346
9398
|
static getSettablePaths() {
|
|
9347
9399
|
return {
|
|
9348
|
-
relativeDirPath: (0,
|
|
9400
|
+
relativeDirPath: (0, import_node_path74.join)(".codex", "subagents")
|
|
9349
9401
|
};
|
|
9350
9402
|
}
|
|
9351
9403
|
static async fromFile(params) {
|
|
@@ -9368,11 +9420,11 @@ var CodexCliSubagent = class _CodexCliSubagent extends SimulatedSubagent {
|
|
|
9368
9420
|
};
|
|
9369
9421
|
|
|
9370
9422
|
// src/features/subagents/factorydroid-subagent.ts
|
|
9371
|
-
var
|
|
9423
|
+
var import_node_path75 = require("path");
|
|
9372
9424
|
var FactorydroidSubagent = class _FactorydroidSubagent extends SimulatedSubagent {
|
|
9373
9425
|
static getSettablePaths(_options) {
|
|
9374
9426
|
return {
|
|
9375
|
-
relativeDirPath: (0,
|
|
9427
|
+
relativeDirPath: (0, import_node_path75.join)(".factory", "droids")
|
|
9376
9428
|
};
|
|
9377
9429
|
}
|
|
9378
9430
|
static async fromFile(params) {
|
|
@@ -9395,11 +9447,11 @@ var FactorydroidSubagent = class _FactorydroidSubagent extends SimulatedSubagent
|
|
|
9395
9447
|
};
|
|
9396
9448
|
|
|
9397
9449
|
// src/features/subagents/geminicli-subagent.ts
|
|
9398
|
-
var
|
|
9450
|
+
var import_node_path76 = require("path");
|
|
9399
9451
|
var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
|
|
9400
9452
|
static getSettablePaths() {
|
|
9401
9453
|
return {
|
|
9402
|
-
relativeDirPath: (0,
|
|
9454
|
+
relativeDirPath: (0, import_node_path76.join)(".gemini", "subagents")
|
|
9403
9455
|
};
|
|
9404
9456
|
}
|
|
9405
9457
|
static async fromFile(params) {
|
|
@@ -9422,11 +9474,11 @@ var GeminiCliSubagent = class _GeminiCliSubagent extends SimulatedSubagent {
|
|
|
9422
9474
|
};
|
|
9423
9475
|
|
|
9424
9476
|
// src/features/subagents/roo-subagent.ts
|
|
9425
|
-
var
|
|
9477
|
+
var import_node_path77 = require("path");
|
|
9426
9478
|
var RooSubagent = class _RooSubagent extends SimulatedSubagent {
|
|
9427
9479
|
static getSettablePaths() {
|
|
9428
9480
|
return {
|
|
9429
|
-
relativeDirPath: (0,
|
|
9481
|
+
relativeDirPath: (0, import_node_path77.join)(".roo", "subagents")
|
|
9430
9482
|
};
|
|
9431
9483
|
}
|
|
9432
9484
|
static async fromFile(params) {
|
|
@@ -9449,15 +9501,15 @@ var RooSubagent = class _RooSubagent extends SimulatedSubagent {
|
|
|
9449
9501
|
};
|
|
9450
9502
|
|
|
9451
9503
|
// src/features/subagents/subagents-processor.ts
|
|
9452
|
-
var
|
|
9504
|
+
var import_node_path84 = require("path");
|
|
9453
9505
|
var import_mini41 = require("zod/mini");
|
|
9454
9506
|
|
|
9455
9507
|
// src/features/subagents/claudecode-subagent.ts
|
|
9456
|
-
var
|
|
9508
|
+
var import_node_path79 = require("path");
|
|
9457
9509
|
var import_mini36 = require("zod/mini");
|
|
9458
9510
|
|
|
9459
9511
|
// src/features/subagents/rulesync-subagent.ts
|
|
9460
|
-
var
|
|
9512
|
+
var import_node_path78 = require("path");
|
|
9461
9513
|
var import_mini35 = require("zod/mini");
|
|
9462
9514
|
var RulesyncSubagentFrontmatterSchema = import_mini35.z.looseObject({
|
|
9463
9515
|
targets: import_mini35.z._default(RulesyncTargetsSchema, ["*"]),
|
|
@@ -9471,7 +9523,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9471
9523
|
const parseResult = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9472
9524
|
if (!parseResult.success && rest.validate !== false) {
|
|
9473
9525
|
throw new Error(
|
|
9474
|
-
`Invalid frontmatter in ${(0,
|
|
9526
|
+
`Invalid frontmatter in ${(0, import_node_path78.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`
|
|
9475
9527
|
);
|
|
9476
9528
|
}
|
|
9477
9529
|
const parsedFrontmatter = parseResult.success ? { ...frontmatter, ...parseResult.data } : { ...frontmatter, targets: frontmatter?.targets ?? ["*"] };
|
|
@@ -9504,7 +9556,7 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9504
9556
|
return {
|
|
9505
9557
|
success: false,
|
|
9506
9558
|
error: new Error(
|
|
9507
|
-
`Invalid frontmatter in ${(0,
|
|
9559
|
+
`Invalid frontmatter in ${(0, import_node_path78.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9508
9560
|
)
|
|
9509
9561
|
};
|
|
9510
9562
|
}
|
|
@@ -9513,14 +9565,14 @@ var RulesyncSubagent = class _RulesyncSubagent extends RulesyncFile {
|
|
|
9513
9565
|
relativeFilePath
|
|
9514
9566
|
}) {
|
|
9515
9567
|
const fileContent = await readFileContent(
|
|
9516
|
-
(0,
|
|
9568
|
+
(0, import_node_path78.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, relativeFilePath)
|
|
9517
9569
|
);
|
|
9518
9570
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9519
9571
|
const result = RulesyncSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9520
9572
|
if (!result.success) {
|
|
9521
9573
|
throw new Error(`Invalid frontmatter in ${relativeFilePath}: ${formatError(result.error)}`);
|
|
9522
9574
|
}
|
|
9523
|
-
const filename = (0,
|
|
9575
|
+
const filename = (0, import_node_path78.basename)(relativeFilePath);
|
|
9524
9576
|
return new _RulesyncSubagent({
|
|
9525
9577
|
baseDir: process.cwd(),
|
|
9526
9578
|
relativeDirPath: this.getSettablePaths().relativeDirPath,
|
|
@@ -9548,7 +9600,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9548
9600
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9549
9601
|
if (!result.success) {
|
|
9550
9602
|
throw new Error(
|
|
9551
|
-
`Invalid frontmatter in ${(0,
|
|
9603
|
+
`Invalid frontmatter in ${(0, import_node_path79.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9552
9604
|
);
|
|
9553
9605
|
}
|
|
9554
9606
|
}
|
|
@@ -9560,7 +9612,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9560
9612
|
}
|
|
9561
9613
|
static getSettablePaths(_options = {}) {
|
|
9562
9614
|
return {
|
|
9563
|
-
relativeDirPath: (0,
|
|
9615
|
+
relativeDirPath: (0, import_node_path79.join)(".claude", "agents")
|
|
9564
9616
|
};
|
|
9565
9617
|
}
|
|
9566
9618
|
getFrontmatter() {
|
|
@@ -9607,7 +9659,9 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9607
9659
|
};
|
|
9608
9660
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(rawClaudecodeFrontmatter);
|
|
9609
9661
|
if (!result.success) {
|
|
9610
|
-
throw new Error(
|
|
9662
|
+
throw new Error(
|
|
9663
|
+
`Invalid claudecode subagent frontmatter in ${rulesyncSubagent.getRelativeFilePath()}: ${formatError(result.error)}`
|
|
9664
|
+
);
|
|
9611
9665
|
}
|
|
9612
9666
|
const claudecodeFrontmatter = result.data;
|
|
9613
9667
|
const body = rulesyncSubagent.getBody();
|
|
@@ -9634,7 +9688,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9634
9688
|
return {
|
|
9635
9689
|
success: false,
|
|
9636
9690
|
error: new Error(
|
|
9637
|
-
`Invalid frontmatter in ${(0,
|
|
9691
|
+
`Invalid frontmatter in ${(0, import_node_path79.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9638
9692
|
)
|
|
9639
9693
|
};
|
|
9640
9694
|
}
|
|
@@ -9652,7 +9706,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9652
9706
|
global = false
|
|
9653
9707
|
}) {
|
|
9654
9708
|
const paths = this.getSettablePaths({ global });
|
|
9655
|
-
const filePath = (0,
|
|
9709
|
+
const filePath = (0, import_node_path79.join)(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9656
9710
|
const fileContent = await readFileContent(filePath);
|
|
9657
9711
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9658
9712
|
const result = ClaudecodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9687,7 +9741,7 @@ var ClaudecodeSubagent = class _ClaudecodeSubagent extends ToolSubagent {
|
|
|
9687
9741
|
};
|
|
9688
9742
|
|
|
9689
9743
|
// src/features/subagents/copilot-subagent.ts
|
|
9690
|
-
var
|
|
9744
|
+
var import_node_path80 = require("path");
|
|
9691
9745
|
var import_mini37 = require("zod/mini");
|
|
9692
9746
|
var REQUIRED_TOOL = "agent/runSubagent";
|
|
9693
9747
|
var CopilotSubagentFrontmatterSchema = import_mini37.z.looseObject({
|
|
@@ -9713,7 +9767,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9713
9767
|
const result = CopilotSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9714
9768
|
if (!result.success) {
|
|
9715
9769
|
throw new Error(
|
|
9716
|
-
`Invalid frontmatter in ${(0,
|
|
9770
|
+
`Invalid frontmatter in ${(0, import_node_path80.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9717
9771
|
);
|
|
9718
9772
|
}
|
|
9719
9773
|
}
|
|
@@ -9725,7 +9779,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9725
9779
|
}
|
|
9726
9780
|
static getSettablePaths(_options = {}) {
|
|
9727
9781
|
return {
|
|
9728
|
-
relativeDirPath: (0,
|
|
9782
|
+
relativeDirPath: (0, import_node_path80.join)(".github", "agents")
|
|
9729
9783
|
};
|
|
9730
9784
|
}
|
|
9731
9785
|
getFrontmatter() {
|
|
@@ -9799,7 +9853,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9799
9853
|
return {
|
|
9800
9854
|
success: false,
|
|
9801
9855
|
error: new Error(
|
|
9802
|
-
`Invalid frontmatter in ${(0,
|
|
9856
|
+
`Invalid frontmatter in ${(0, import_node_path80.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9803
9857
|
)
|
|
9804
9858
|
};
|
|
9805
9859
|
}
|
|
@@ -9817,7 +9871,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9817
9871
|
global = false
|
|
9818
9872
|
}) {
|
|
9819
9873
|
const paths = this.getSettablePaths({ global });
|
|
9820
|
-
const filePath = (0,
|
|
9874
|
+
const filePath = (0, import_node_path80.join)(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9821
9875
|
const fileContent = await readFileContent(filePath);
|
|
9822
9876
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9823
9877
|
const result = CopilotSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -9853,7 +9907,7 @@ var CopilotSubagent = class _CopilotSubagent extends ToolSubagent {
|
|
|
9853
9907
|
};
|
|
9854
9908
|
|
|
9855
9909
|
// src/features/subagents/cursor-subagent.ts
|
|
9856
|
-
var
|
|
9910
|
+
var import_node_path81 = require("path");
|
|
9857
9911
|
var import_mini38 = require("zod/mini");
|
|
9858
9912
|
var CursorSubagentFrontmatterSchema = import_mini38.z.looseObject({
|
|
9859
9913
|
name: import_mini38.z.string(),
|
|
@@ -9867,7 +9921,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9867
9921
|
const result = CursorSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
9868
9922
|
if (!result.success) {
|
|
9869
9923
|
throw new Error(
|
|
9870
|
-
`Invalid frontmatter in ${(0,
|
|
9924
|
+
`Invalid frontmatter in ${(0, import_node_path81.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
9871
9925
|
);
|
|
9872
9926
|
}
|
|
9873
9927
|
}
|
|
@@ -9879,7 +9933,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9879
9933
|
}
|
|
9880
9934
|
static getSettablePaths(_options = {}) {
|
|
9881
9935
|
return {
|
|
9882
|
-
relativeDirPath: (0,
|
|
9936
|
+
relativeDirPath: (0, import_node_path81.join)(".cursor", "agents")
|
|
9883
9937
|
};
|
|
9884
9938
|
}
|
|
9885
9939
|
getFrontmatter() {
|
|
@@ -9946,7 +10000,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9946
10000
|
return {
|
|
9947
10001
|
success: false,
|
|
9948
10002
|
error: new Error(
|
|
9949
|
-
`Invalid frontmatter in ${(0,
|
|
10003
|
+
`Invalid frontmatter in ${(0, import_node_path81.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
9950
10004
|
)
|
|
9951
10005
|
};
|
|
9952
10006
|
}
|
|
@@ -9964,7 +10018,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
9964
10018
|
global = false
|
|
9965
10019
|
}) {
|
|
9966
10020
|
const paths = this.getSettablePaths({ global });
|
|
9967
|
-
const filePath = (0,
|
|
10021
|
+
const filePath = (0, import_node_path81.join)(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
9968
10022
|
const fileContent = await readFileContent(filePath);
|
|
9969
10023
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
9970
10024
|
const result = CursorSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -10000,7 +10054,7 @@ var CursorSubagent = class _CursorSubagent extends ToolSubagent {
|
|
|
10000
10054
|
};
|
|
10001
10055
|
|
|
10002
10056
|
// src/features/subagents/kiro-subagent.ts
|
|
10003
|
-
var
|
|
10057
|
+
var import_node_path82 = require("path");
|
|
10004
10058
|
var import_mini39 = require("zod/mini");
|
|
10005
10059
|
var KiroCliSubagentJsonSchema = import_mini39.z.looseObject({
|
|
10006
10060
|
name: import_mini39.z.string(),
|
|
@@ -10028,7 +10082,7 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10028
10082
|
}
|
|
10029
10083
|
static getSettablePaths(_options = {}) {
|
|
10030
10084
|
return {
|
|
10031
|
-
relativeDirPath: (0,
|
|
10085
|
+
relativeDirPath: (0, import_node_path82.join)(".kiro", "agents")
|
|
10032
10086
|
};
|
|
10033
10087
|
}
|
|
10034
10088
|
getBody() {
|
|
@@ -10108,7 +10162,7 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10108
10162
|
global = false
|
|
10109
10163
|
}) {
|
|
10110
10164
|
const paths = this.getSettablePaths({ global });
|
|
10111
|
-
const filePath = (0,
|
|
10165
|
+
const filePath = (0, import_node_path82.join)(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
10112
10166
|
const fileContent = await readFileContent(filePath);
|
|
10113
10167
|
return new _KiroSubagent({
|
|
10114
10168
|
baseDir,
|
|
@@ -10137,11 +10191,11 @@ var KiroSubagent = class _KiroSubagent extends ToolSubagent {
|
|
|
10137
10191
|
};
|
|
10138
10192
|
|
|
10139
10193
|
// src/features/subagents/opencode-subagent.ts
|
|
10140
|
-
var
|
|
10194
|
+
var import_node_path83 = require("path");
|
|
10141
10195
|
var import_mini40 = require("zod/mini");
|
|
10142
10196
|
var OpenCodeSubagentFrontmatterSchema = import_mini40.z.looseObject({
|
|
10143
10197
|
description: import_mini40.z.string(),
|
|
10144
|
-
mode: import_mini40.z.
|
|
10198
|
+
mode: import_mini40.z.optional(import_mini40.z._default(import_mini40.z.string(), "subagent")),
|
|
10145
10199
|
name: import_mini40.z.optional(import_mini40.z.string())
|
|
10146
10200
|
});
|
|
10147
10201
|
var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
@@ -10152,7 +10206,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10152
10206
|
const result = OpenCodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
10153
10207
|
if (!result.success) {
|
|
10154
10208
|
throw new Error(
|
|
10155
|
-
`Invalid frontmatter in ${(0,
|
|
10209
|
+
`Invalid frontmatter in ${(0, import_node_path83.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
10156
10210
|
);
|
|
10157
10211
|
}
|
|
10158
10212
|
}
|
|
@@ -10166,7 +10220,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10166
10220
|
global = false
|
|
10167
10221
|
} = {}) {
|
|
10168
10222
|
return {
|
|
10169
|
-
relativeDirPath: global ? (0,
|
|
10223
|
+
relativeDirPath: global ? (0, import_node_path83.join)(".config", "opencode", "agent") : (0, import_node_path83.join)(".opencode", "agent")
|
|
10170
10224
|
};
|
|
10171
10225
|
}
|
|
10172
10226
|
getFrontmatter() {
|
|
@@ -10179,7 +10233,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10179
10233
|
const { description, mode, name, ...opencodeSection } = this.frontmatter;
|
|
10180
10234
|
const rulesyncFrontmatter = {
|
|
10181
10235
|
targets: ["*"],
|
|
10182
|
-
name: name ?? (0,
|
|
10236
|
+
name: name ?? (0, import_node_path83.basename)(this.getRelativeFilePath(), ".md"),
|
|
10183
10237
|
description,
|
|
10184
10238
|
opencode: { mode, ...opencodeSection }
|
|
10185
10239
|
};
|
|
@@ -10232,7 +10286,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10232
10286
|
return {
|
|
10233
10287
|
success: false,
|
|
10234
10288
|
error: new Error(
|
|
10235
|
-
`Invalid frontmatter in ${(0,
|
|
10289
|
+
`Invalid frontmatter in ${(0, import_node_path83.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
10236
10290
|
)
|
|
10237
10291
|
};
|
|
10238
10292
|
}
|
|
@@ -10249,7 +10303,7 @@ var OpenCodeSubagent = class _OpenCodeSubagent extends ToolSubagent {
|
|
|
10249
10303
|
global = false
|
|
10250
10304
|
}) {
|
|
10251
10305
|
const paths = this.getSettablePaths({ global });
|
|
10252
|
-
const filePath = (0,
|
|
10306
|
+
const filePath = (0, import_node_path83.join)(baseDir, paths.relativeDirPath, relativeFilePath);
|
|
10253
10307
|
const fileContent = await readFileContent(filePath);
|
|
10254
10308
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
10255
10309
|
const result = OpenCodeSubagentFrontmatterSchema.safeParse(frontmatter);
|
|
@@ -10460,7 +10514,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10460
10514
|
* Load and parse rulesync subagent files from .rulesync/subagents/ directory
|
|
10461
10515
|
*/
|
|
10462
10516
|
async loadRulesyncFiles() {
|
|
10463
|
-
const subagentsDir = (0,
|
|
10517
|
+
const subagentsDir = (0, import_node_path84.join)(this.baseDir, RulesyncSubagent.getSettablePaths().relativeDirPath);
|
|
10464
10518
|
const dirExists = await directoryExists(subagentsDir);
|
|
10465
10519
|
if (!dirExists) {
|
|
10466
10520
|
logger.debug(`Rulesync subagents directory not found: ${subagentsDir}`);
|
|
@@ -10472,10 +10526,10 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10472
10526
|
logger.debug(`No markdown files found in rulesync subagents directory: ${subagentsDir}`);
|
|
10473
10527
|
return [];
|
|
10474
10528
|
}
|
|
10475
|
-
logger.
|
|
10529
|
+
logger.debug(`Found ${mdFiles.length} subagent files in ${subagentsDir}`);
|
|
10476
10530
|
const rulesyncSubagents = [];
|
|
10477
10531
|
for (const mdFile of mdFiles) {
|
|
10478
|
-
const filepath = (0,
|
|
10532
|
+
const filepath = (0, import_node_path84.join)(subagentsDir, mdFile);
|
|
10479
10533
|
try {
|
|
10480
10534
|
const rulesyncSubagent = await RulesyncSubagent.fromFile({
|
|
10481
10535
|
relativeFilePath: mdFile,
|
|
@@ -10484,7 +10538,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10484
10538
|
rulesyncSubagents.push(rulesyncSubagent);
|
|
10485
10539
|
logger.debug(`Successfully loaded subagent: ${mdFile}`);
|
|
10486
10540
|
} catch (error) {
|
|
10487
|
-
logger.warn(`Failed to load subagent file ${filepath}
|
|
10541
|
+
logger.warn(`Failed to load subagent file ${filepath}: ${formatError(error)}`);
|
|
10488
10542
|
continue;
|
|
10489
10543
|
}
|
|
10490
10544
|
}
|
|
@@ -10492,7 +10546,7 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10492
10546
|
logger.debug(`No valid subagents found in ${subagentsDir}`);
|
|
10493
10547
|
return [];
|
|
10494
10548
|
}
|
|
10495
|
-
logger.
|
|
10549
|
+
logger.debug(`Successfully loaded ${rulesyncSubagents.length} rulesync subagents`);
|
|
10496
10550
|
return rulesyncSubagents;
|
|
10497
10551
|
}
|
|
10498
10552
|
/**
|
|
@@ -10505,30 +10559,32 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10505
10559
|
const factory = this.getFactory(this.toolTarget);
|
|
10506
10560
|
const paths = factory.class.getSettablePaths({ global: this.global });
|
|
10507
10561
|
const subagentFilePaths = await findFilesByGlobs(
|
|
10508
|
-
(0,
|
|
10562
|
+
(0, import_node_path84.join)(this.baseDir, paths.relativeDirPath, factory.meta.filePattern)
|
|
10509
10563
|
);
|
|
10510
10564
|
if (forDeletion) {
|
|
10511
10565
|
const toolSubagents2 = subagentFilePaths.map(
|
|
10512
10566
|
(path4) => factory.class.forDeletion({
|
|
10513
10567
|
baseDir: this.baseDir,
|
|
10514
10568
|
relativeDirPath: paths.relativeDirPath,
|
|
10515
|
-
relativeFilePath: (0,
|
|
10569
|
+
relativeFilePath: (0, import_node_path84.basename)(path4),
|
|
10516
10570
|
global: this.global
|
|
10517
10571
|
})
|
|
10518
10572
|
).filter((subagent) => subagent.isDeletable());
|
|
10519
|
-
logger.
|
|
10573
|
+
logger.debug(
|
|
10574
|
+
`Successfully loaded ${toolSubagents2.length} ${paths.relativeDirPath} subagents`
|
|
10575
|
+
);
|
|
10520
10576
|
return toolSubagents2;
|
|
10521
10577
|
}
|
|
10522
10578
|
const toolSubagents = await Promise.all(
|
|
10523
10579
|
subagentFilePaths.map(
|
|
10524
10580
|
(path4) => factory.class.fromFile({
|
|
10525
10581
|
baseDir: this.baseDir,
|
|
10526
|
-
relativeFilePath: (0,
|
|
10582
|
+
relativeFilePath: (0, import_node_path84.basename)(path4),
|
|
10527
10583
|
global: this.global
|
|
10528
10584
|
})
|
|
10529
10585
|
)
|
|
10530
10586
|
);
|
|
10531
|
-
logger.
|
|
10587
|
+
logger.debug(`Successfully loaded ${toolSubagents.length} ${paths.relativeDirPath} subagents`);
|
|
10532
10588
|
return toolSubagents;
|
|
10533
10589
|
}
|
|
10534
10590
|
/**
|
|
@@ -10568,13 +10624,13 @@ var SubagentsProcessor = class extends FeatureProcessor {
|
|
|
10568
10624
|
};
|
|
10569
10625
|
|
|
10570
10626
|
// src/features/rules/agentsmd-rule.ts
|
|
10571
|
-
var
|
|
10627
|
+
var import_node_path87 = require("path");
|
|
10572
10628
|
|
|
10573
10629
|
// src/features/rules/tool-rule.ts
|
|
10574
|
-
var
|
|
10630
|
+
var import_node_path86 = require("path");
|
|
10575
10631
|
|
|
10576
10632
|
// src/features/rules/rulesync-rule.ts
|
|
10577
|
-
var
|
|
10633
|
+
var import_node_path85 = require("path");
|
|
10578
10634
|
var import_mini42 = require("zod/mini");
|
|
10579
10635
|
var RulesyncRuleFrontmatterSchema = import_mini42.z.object({
|
|
10580
10636
|
root: import_mini42.z.optional(import_mini42.z.boolean()),
|
|
@@ -10621,7 +10677,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10621
10677
|
const parseResult = RulesyncRuleFrontmatterSchema.safeParse(frontmatter);
|
|
10622
10678
|
if (!parseResult.success && rest.validate !== false) {
|
|
10623
10679
|
throw new Error(
|
|
10624
|
-
`Invalid frontmatter in ${(0,
|
|
10680
|
+
`Invalid frontmatter in ${(0, import_node_path85.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(parseResult.error)}`
|
|
10625
10681
|
);
|
|
10626
10682
|
}
|
|
10627
10683
|
const parsedFrontmatter = parseResult.success ? parseResult.data : { ...frontmatter, targets: frontmatter.targets ?? ["*"] };
|
|
@@ -10656,7 +10712,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10656
10712
|
return {
|
|
10657
10713
|
success: false,
|
|
10658
10714
|
error: new Error(
|
|
10659
|
-
`Invalid frontmatter in ${(0,
|
|
10715
|
+
`Invalid frontmatter in ${(0, import_node_path85.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
10660
10716
|
)
|
|
10661
10717
|
};
|
|
10662
10718
|
}
|
|
@@ -10665,7 +10721,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
|
|
|
10665
10721
|
relativeFilePath,
|
|
10666
10722
|
validate = true
|
|
10667
10723
|
}) {
|
|
10668
|
-
const filePath = (0,
|
|
10724
|
+
const filePath = (0, import_node_path85.join)(
|
|
10669
10725
|
process.cwd(),
|
|
10670
10726
|
this.getSettablePaths().recommended.relativeDirPath,
|
|
10671
10727
|
relativeFilePath
|
|
@@ -10749,7 +10805,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10749
10805
|
};
|
|
10750
10806
|
}
|
|
10751
10807
|
if (!nonRootPath) {
|
|
10752
|
-
throw new Error(
|
|
10808
|
+
throw new Error(`nonRootPath is not set for ${rulesyncRule.getRelativeFilePath()}`);
|
|
10753
10809
|
}
|
|
10754
10810
|
return {
|
|
10755
10811
|
baseDir,
|
|
@@ -10767,7 +10823,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10767
10823
|
rulesyncRule,
|
|
10768
10824
|
validate = true,
|
|
10769
10825
|
rootPath = { relativeDirPath: ".", relativeFilePath: "AGENTS.md" },
|
|
10770
|
-
nonRootPath = { relativeDirPath: (0,
|
|
10826
|
+
nonRootPath = { relativeDirPath: (0, import_node_path86.join)(".agents", "memories") }
|
|
10771
10827
|
}) {
|
|
10772
10828
|
const params = this.buildToolRuleParamsDefault({
|
|
10773
10829
|
baseDir,
|
|
@@ -10778,7 +10834,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10778
10834
|
});
|
|
10779
10835
|
const rulesyncFrontmatter = rulesyncRule.getFrontmatter();
|
|
10780
10836
|
if (!rulesyncFrontmatter.root && rulesyncFrontmatter.agentsmd?.subprojectPath) {
|
|
10781
|
-
params.relativeDirPath = (0,
|
|
10837
|
+
params.relativeDirPath = (0, import_node_path86.join)(rulesyncFrontmatter.agentsmd.subprojectPath);
|
|
10782
10838
|
params.relativeFilePath = "AGENTS.md";
|
|
10783
10839
|
}
|
|
10784
10840
|
return params;
|
|
@@ -10827,7 +10883,7 @@ var ToolRule = class extends ToolFile {
|
|
|
10827
10883
|
}
|
|
10828
10884
|
};
|
|
10829
10885
|
function buildToolPath(toolDir, subDir, excludeToolDir) {
|
|
10830
|
-
return excludeToolDir ? subDir : (0,
|
|
10886
|
+
return excludeToolDir ? subDir : (0, import_node_path86.join)(toolDir, subDir);
|
|
10831
10887
|
}
|
|
10832
10888
|
|
|
10833
10889
|
// src/features/rules/agentsmd-rule.ts
|
|
@@ -10856,8 +10912,8 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
|
|
|
10856
10912
|
validate = true
|
|
10857
10913
|
}) {
|
|
10858
10914
|
const isRoot = relativeFilePath === "AGENTS.md";
|
|
10859
|
-
const relativePath = isRoot ? "AGENTS.md" : (0,
|
|
10860
|
-
const fileContent = await readFileContent((0,
|
|
10915
|
+
const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path87.join)(".agents", "memories", relativeFilePath);
|
|
10916
|
+
const fileContent = await readFileContent((0, import_node_path87.join)(baseDir, relativePath));
|
|
10861
10917
|
return new _AgentsMdRule({
|
|
10862
10918
|
baseDir,
|
|
10863
10919
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -10912,7 +10968,7 @@ var AgentsMdRule = class _AgentsMdRule extends ToolRule {
|
|
|
10912
10968
|
};
|
|
10913
10969
|
|
|
10914
10970
|
// src/features/rules/antigravity-rule.ts
|
|
10915
|
-
var
|
|
10971
|
+
var import_node_path88 = require("path");
|
|
10916
10972
|
var import_mini43 = require("zod/mini");
|
|
10917
10973
|
var AntigravityRuleFrontmatterSchema = import_mini43.z.looseObject({
|
|
10918
10974
|
trigger: import_mini43.z.optional(
|
|
@@ -11071,7 +11127,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11071
11127
|
const result = AntigravityRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11072
11128
|
if (!result.success) {
|
|
11073
11129
|
throw new Error(
|
|
11074
|
-
`Invalid frontmatter in ${(0,
|
|
11130
|
+
`Invalid frontmatter in ${(0, import_node_path88.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11075
11131
|
);
|
|
11076
11132
|
}
|
|
11077
11133
|
}
|
|
@@ -11095,7 +11151,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11095
11151
|
relativeFilePath,
|
|
11096
11152
|
validate = true
|
|
11097
11153
|
}) {
|
|
11098
|
-
const filePath = (0,
|
|
11154
|
+
const filePath = (0, import_node_path88.join)(
|
|
11099
11155
|
baseDir,
|
|
11100
11156
|
this.getSettablePaths().nonRoot.relativeDirPath,
|
|
11101
11157
|
relativeFilePath
|
|
@@ -11236,7 +11292,7 @@ var AntigravityRule = class _AntigravityRule extends ToolRule {
|
|
|
11236
11292
|
};
|
|
11237
11293
|
|
|
11238
11294
|
// src/features/rules/augmentcode-legacy-rule.ts
|
|
11239
|
-
var
|
|
11295
|
+
var import_node_path89 = require("path");
|
|
11240
11296
|
var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
11241
11297
|
toRulesyncRule() {
|
|
11242
11298
|
const rulesyncFrontmatter = {
|
|
@@ -11297,8 +11353,8 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
|
11297
11353
|
}) {
|
|
11298
11354
|
const settablePaths = this.getSettablePaths();
|
|
11299
11355
|
const isRoot = relativeFilePath === settablePaths.root.relativeFilePath;
|
|
11300
|
-
const relativePath = isRoot ? settablePaths.root.relativeFilePath : (0,
|
|
11301
|
-
const fileContent = await readFileContent((0,
|
|
11356
|
+
const relativePath = isRoot ? settablePaths.root.relativeFilePath : (0, import_node_path89.join)(settablePaths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11357
|
+
const fileContent = await readFileContent((0, import_node_path89.join)(baseDir, relativePath));
|
|
11302
11358
|
return new _AugmentcodeLegacyRule({
|
|
11303
11359
|
baseDir,
|
|
11304
11360
|
relativeDirPath: isRoot ? settablePaths.root.relativeDirPath : settablePaths.nonRoot.relativeDirPath,
|
|
@@ -11327,7 +11383,7 @@ var AugmentcodeLegacyRule = class _AugmentcodeLegacyRule extends ToolRule {
|
|
|
11327
11383
|
};
|
|
11328
11384
|
|
|
11329
11385
|
// src/features/rules/augmentcode-rule.ts
|
|
11330
|
-
var
|
|
11386
|
+
var import_node_path90 = require("path");
|
|
11331
11387
|
var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
11332
11388
|
toRulesyncRule() {
|
|
11333
11389
|
return this.toRulesyncRuleDefault();
|
|
@@ -11359,7 +11415,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
|
11359
11415
|
validate = true
|
|
11360
11416
|
}) {
|
|
11361
11417
|
const fileContent = await readFileContent(
|
|
11362
|
-
(0,
|
|
11418
|
+
(0, import_node_path90.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
11363
11419
|
);
|
|
11364
11420
|
const { body: content } = parseFrontmatter(fileContent);
|
|
11365
11421
|
return new _AugmentcodeRule({
|
|
@@ -11395,7 +11451,7 @@ var AugmentcodeRule = class _AugmentcodeRule extends ToolRule {
|
|
|
11395
11451
|
};
|
|
11396
11452
|
|
|
11397
11453
|
// src/features/rules/claudecode-legacy-rule.ts
|
|
11398
|
-
var
|
|
11454
|
+
var import_node_path91 = require("path");
|
|
11399
11455
|
var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
11400
11456
|
static getSettablePaths({
|
|
11401
11457
|
global,
|
|
@@ -11430,7 +11486,7 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11430
11486
|
if (isRoot) {
|
|
11431
11487
|
const relativePath2 = paths.root.relativeFilePath;
|
|
11432
11488
|
const fileContent2 = await readFileContent(
|
|
11433
|
-
(0,
|
|
11489
|
+
(0, import_node_path91.join)(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
11434
11490
|
);
|
|
11435
11491
|
return new _ClaudecodeLegacyRule({
|
|
11436
11492
|
baseDir,
|
|
@@ -11442,10 +11498,10 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11442
11498
|
});
|
|
11443
11499
|
}
|
|
11444
11500
|
if (!paths.nonRoot) {
|
|
11445
|
-
throw new Error(
|
|
11501
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11446
11502
|
}
|
|
11447
|
-
const relativePath = (0,
|
|
11448
|
-
const fileContent = await readFileContent((0,
|
|
11503
|
+
const relativePath = (0, import_node_path91.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11504
|
+
const fileContent = await readFileContent((0, import_node_path91.join)(baseDir, relativePath));
|
|
11449
11505
|
return new _ClaudecodeLegacyRule({
|
|
11450
11506
|
baseDir,
|
|
11451
11507
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -11504,7 +11560,7 @@ var ClaudecodeLegacyRule = class _ClaudecodeLegacyRule extends ToolRule {
|
|
|
11504
11560
|
};
|
|
11505
11561
|
|
|
11506
11562
|
// src/features/rules/claudecode-rule.ts
|
|
11507
|
-
var
|
|
11563
|
+
var import_node_path92 = require("path");
|
|
11508
11564
|
var import_mini44 = require("zod/mini");
|
|
11509
11565
|
var ClaudecodeRuleFrontmatterSchema = import_mini44.z.object({
|
|
11510
11566
|
paths: import_mini44.z.optional(import_mini44.z.array(import_mini44.z.string()))
|
|
@@ -11539,7 +11595,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11539
11595
|
const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11540
11596
|
if (!result.success) {
|
|
11541
11597
|
throw new Error(
|
|
11542
|
-
`Invalid frontmatter in ${(0,
|
|
11598
|
+
`Invalid frontmatter in ${(0, import_node_path92.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11543
11599
|
);
|
|
11544
11600
|
}
|
|
11545
11601
|
}
|
|
@@ -11567,7 +11623,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11567
11623
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
11568
11624
|
if (isRoot) {
|
|
11569
11625
|
const fileContent2 = await readFileContent(
|
|
11570
|
-
(0,
|
|
11626
|
+
(0, import_node_path92.join)(baseDir, paths.root.relativeDirPath, paths.root.relativeFilePath)
|
|
11571
11627
|
);
|
|
11572
11628
|
return new _ClaudecodeRule({
|
|
11573
11629
|
baseDir,
|
|
@@ -11580,15 +11636,15 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11580
11636
|
});
|
|
11581
11637
|
}
|
|
11582
11638
|
if (!paths.nonRoot) {
|
|
11583
|
-
throw new Error(
|
|
11639
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11584
11640
|
}
|
|
11585
|
-
const relativePath = (0,
|
|
11586
|
-
const fileContent = await readFileContent((0,
|
|
11641
|
+
const relativePath = (0, import_node_path92.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11642
|
+
const fileContent = await readFileContent((0, import_node_path92.join)(baseDir, relativePath));
|
|
11587
11643
|
const { frontmatter, body: content } = parseFrontmatter(fileContent);
|
|
11588
11644
|
const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11589
11645
|
if (!result.success) {
|
|
11590
11646
|
throw new Error(
|
|
11591
|
-
`Invalid frontmatter in ${(0,
|
|
11647
|
+
`Invalid frontmatter in ${(0, import_node_path92.join)(baseDir, relativePath)}: ${formatError(result.error)}`
|
|
11592
11648
|
);
|
|
11593
11649
|
}
|
|
11594
11650
|
return new _ClaudecodeRule({
|
|
@@ -11647,7 +11703,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11647
11703
|
});
|
|
11648
11704
|
}
|
|
11649
11705
|
if (!paths.nonRoot) {
|
|
11650
|
-
throw new Error(
|
|
11706
|
+
throw new Error(`nonRoot path is not set for ${rulesyncRule.getRelativeFilePath()}`);
|
|
11651
11707
|
}
|
|
11652
11708
|
return new _ClaudecodeRule({
|
|
11653
11709
|
baseDir,
|
|
@@ -11695,7 +11751,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11695
11751
|
return {
|
|
11696
11752
|
success: false,
|
|
11697
11753
|
error: new Error(
|
|
11698
|
-
`Invalid frontmatter in ${(0,
|
|
11754
|
+
`Invalid frontmatter in ${(0, import_node_path92.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
11699
11755
|
)
|
|
11700
11756
|
};
|
|
11701
11757
|
}
|
|
@@ -11715,7 +11771,7 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
|
|
|
11715
11771
|
};
|
|
11716
11772
|
|
|
11717
11773
|
// src/features/rules/cline-rule.ts
|
|
11718
|
-
var
|
|
11774
|
+
var import_node_path93 = require("path");
|
|
11719
11775
|
var import_mini45 = require("zod/mini");
|
|
11720
11776
|
var ClineRuleFrontmatterSchema = import_mini45.z.object({
|
|
11721
11777
|
description: import_mini45.z.string()
|
|
@@ -11761,7 +11817,7 @@ var ClineRule = class _ClineRule extends ToolRule {
|
|
|
11761
11817
|
validate = true
|
|
11762
11818
|
}) {
|
|
11763
11819
|
const fileContent = await readFileContent(
|
|
11764
|
-
(0,
|
|
11820
|
+
(0, import_node_path93.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
11765
11821
|
);
|
|
11766
11822
|
return new _ClineRule({
|
|
11767
11823
|
baseDir,
|
|
@@ -11787,7 +11843,7 @@ var ClineRule = class _ClineRule extends ToolRule {
|
|
|
11787
11843
|
};
|
|
11788
11844
|
|
|
11789
11845
|
// src/features/rules/codexcli-rule.ts
|
|
11790
|
-
var
|
|
11846
|
+
var import_node_path94 = require("path");
|
|
11791
11847
|
var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
11792
11848
|
static getSettablePaths({
|
|
11793
11849
|
global,
|
|
@@ -11822,7 +11878,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11822
11878
|
if (isRoot) {
|
|
11823
11879
|
const relativePath2 = paths.root.relativeFilePath;
|
|
11824
11880
|
const fileContent2 = await readFileContent(
|
|
11825
|
-
(0,
|
|
11881
|
+
(0, import_node_path94.join)(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
11826
11882
|
);
|
|
11827
11883
|
return new _CodexcliRule({
|
|
11828
11884
|
baseDir,
|
|
@@ -11834,10 +11890,10 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11834
11890
|
});
|
|
11835
11891
|
}
|
|
11836
11892
|
if (!paths.nonRoot) {
|
|
11837
|
-
throw new Error(
|
|
11893
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
11838
11894
|
}
|
|
11839
|
-
const relativePath = (0,
|
|
11840
|
-
const fileContent = await readFileContent((0,
|
|
11895
|
+
const relativePath = (0, import_node_path94.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
11896
|
+
const fileContent = await readFileContent((0, import_node_path94.join)(baseDir, relativePath));
|
|
11841
11897
|
return new _CodexcliRule({
|
|
11842
11898
|
baseDir,
|
|
11843
11899
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -11896,7 +11952,7 @@ var CodexcliRule = class _CodexcliRule extends ToolRule {
|
|
|
11896
11952
|
};
|
|
11897
11953
|
|
|
11898
11954
|
// src/features/rules/copilot-rule.ts
|
|
11899
|
-
var
|
|
11955
|
+
var import_node_path95 = require("path");
|
|
11900
11956
|
var import_mini46 = require("zod/mini");
|
|
11901
11957
|
var CopilotRuleFrontmatterSchema = import_mini46.z.object({
|
|
11902
11958
|
description: import_mini46.z.optional(import_mini46.z.string()),
|
|
@@ -11922,7 +11978,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
11922
11978
|
const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
|
|
11923
11979
|
if (!result.success) {
|
|
11924
11980
|
throw new Error(
|
|
11925
|
-
`Invalid frontmatter in ${(0,
|
|
11981
|
+
`Invalid frontmatter in ${(0, import_node_path95.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
11926
11982
|
);
|
|
11927
11983
|
}
|
|
11928
11984
|
}
|
|
@@ -12004,11 +12060,11 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12004
12060
|
validate = true
|
|
12005
12061
|
}) {
|
|
12006
12062
|
const isRoot = relativeFilePath === "copilot-instructions.md";
|
|
12007
|
-
const relativePath = isRoot ? (0,
|
|
12063
|
+
const relativePath = isRoot ? (0, import_node_path95.join)(
|
|
12008
12064
|
this.getSettablePaths().root.relativeDirPath,
|
|
12009
12065
|
this.getSettablePaths().root.relativeFilePath
|
|
12010
|
-
) : (0,
|
|
12011
|
-
const fileContent = await readFileContent((0,
|
|
12066
|
+
) : (0, import_node_path95.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
|
|
12067
|
+
const fileContent = await readFileContent((0, import_node_path95.join)(baseDir, relativePath));
|
|
12012
12068
|
if (isRoot) {
|
|
12013
12069
|
return new _CopilotRule({
|
|
12014
12070
|
baseDir,
|
|
@@ -12024,7 +12080,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12024
12080
|
const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12025
12081
|
if (!result.success) {
|
|
12026
12082
|
throw new Error(
|
|
12027
|
-
`Invalid frontmatter in ${(0,
|
|
12083
|
+
`Invalid frontmatter in ${(0, import_node_path95.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
|
|
12028
12084
|
);
|
|
12029
12085
|
}
|
|
12030
12086
|
return new _CopilotRule({
|
|
@@ -12064,7 +12120,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12064
12120
|
return {
|
|
12065
12121
|
success: false,
|
|
12066
12122
|
error: new Error(
|
|
12067
|
-
`Invalid frontmatter in ${(0,
|
|
12123
|
+
`Invalid frontmatter in ${(0, import_node_path95.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
12068
12124
|
)
|
|
12069
12125
|
};
|
|
12070
12126
|
}
|
|
@@ -12084,7 +12140,7 @@ var CopilotRule = class _CopilotRule extends ToolRule {
|
|
|
12084
12140
|
};
|
|
12085
12141
|
|
|
12086
12142
|
// src/features/rules/cursor-rule.ts
|
|
12087
|
-
var
|
|
12143
|
+
var import_node_path96 = require("path");
|
|
12088
12144
|
var import_mini47 = require("zod/mini");
|
|
12089
12145
|
var CursorRuleFrontmatterSchema = import_mini47.z.object({
|
|
12090
12146
|
description: import_mini47.z.optional(import_mini47.z.string()),
|
|
@@ -12106,7 +12162,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12106
12162
|
const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12107
12163
|
if (!result.success) {
|
|
12108
12164
|
throw new Error(
|
|
12109
|
-
`Invalid frontmatter in ${(0,
|
|
12165
|
+
`Invalid frontmatter in ${(0, import_node_path96.join)(rest.relativeDirPath, rest.relativeFilePath)}: ${formatError(result.error)}`
|
|
12110
12166
|
);
|
|
12111
12167
|
}
|
|
12112
12168
|
}
|
|
@@ -12223,13 +12279,13 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12223
12279
|
validate = true
|
|
12224
12280
|
}) {
|
|
12225
12281
|
const fileContent = await readFileContent(
|
|
12226
|
-
(0,
|
|
12282
|
+
(0, import_node_path96.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12227
12283
|
);
|
|
12228
12284
|
const { frontmatter, body: content } = _CursorRule.parseCursorFrontmatter(fileContent);
|
|
12229
12285
|
const result = CursorRuleFrontmatterSchema.safeParse(frontmatter);
|
|
12230
12286
|
if (!result.success) {
|
|
12231
12287
|
throw new Error(
|
|
12232
|
-
`Invalid frontmatter in ${(0,
|
|
12288
|
+
`Invalid frontmatter in ${(0, import_node_path96.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
|
|
12233
12289
|
);
|
|
12234
12290
|
}
|
|
12235
12291
|
return new _CursorRule({
|
|
@@ -12266,7 +12322,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12266
12322
|
return {
|
|
12267
12323
|
success: false,
|
|
12268
12324
|
error: new Error(
|
|
12269
|
-
`Invalid frontmatter in ${(0,
|
|
12325
|
+
`Invalid frontmatter in ${(0, import_node_path96.join)(this.relativeDirPath, this.relativeFilePath)}: ${formatError(result.error)}`
|
|
12270
12326
|
)
|
|
12271
12327
|
};
|
|
12272
12328
|
}
|
|
@@ -12286,7 +12342,7 @@ var CursorRule = class _CursorRule extends ToolRule {
|
|
|
12286
12342
|
};
|
|
12287
12343
|
|
|
12288
12344
|
// src/features/rules/factorydroid-rule.ts
|
|
12289
|
-
var
|
|
12345
|
+
var import_node_path97 = require("path");
|
|
12290
12346
|
var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
12291
12347
|
constructor({ fileContent, root, ...rest }) {
|
|
12292
12348
|
super({
|
|
@@ -12326,8 +12382,8 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12326
12382
|
const paths = this.getSettablePaths({ global });
|
|
12327
12383
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
12328
12384
|
if (isRoot) {
|
|
12329
|
-
const relativePath2 = (0,
|
|
12330
|
-
const fileContent2 = await readFileContent((0,
|
|
12385
|
+
const relativePath2 = (0, import_node_path97.join)(paths.root.relativeDirPath, paths.root.relativeFilePath);
|
|
12386
|
+
const fileContent2 = await readFileContent((0, import_node_path97.join)(baseDir, relativePath2));
|
|
12331
12387
|
return new _FactorydroidRule({
|
|
12332
12388
|
baseDir,
|
|
12333
12389
|
relativeDirPath: paths.root.relativeDirPath,
|
|
@@ -12338,10 +12394,10 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12338
12394
|
});
|
|
12339
12395
|
}
|
|
12340
12396
|
if (!paths.nonRoot) {
|
|
12341
|
-
throw new Error(
|
|
12397
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
12342
12398
|
}
|
|
12343
|
-
const relativePath = (0,
|
|
12344
|
-
const fileContent = await readFileContent((0,
|
|
12399
|
+
const relativePath = (0, import_node_path97.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
12400
|
+
const fileContent = await readFileContent((0, import_node_path97.join)(baseDir, relativePath));
|
|
12345
12401
|
return new _FactorydroidRule({
|
|
12346
12402
|
baseDir,
|
|
12347
12403
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -12400,7 +12456,7 @@ var FactorydroidRule = class _FactorydroidRule extends ToolRule {
|
|
|
12400
12456
|
};
|
|
12401
12457
|
|
|
12402
12458
|
// src/features/rules/geminicli-rule.ts
|
|
12403
|
-
var
|
|
12459
|
+
var import_node_path98 = require("path");
|
|
12404
12460
|
var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
12405
12461
|
static getSettablePaths({
|
|
12406
12462
|
global,
|
|
@@ -12435,7 +12491,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12435
12491
|
if (isRoot) {
|
|
12436
12492
|
const relativePath2 = paths.root.relativeFilePath;
|
|
12437
12493
|
const fileContent2 = await readFileContent(
|
|
12438
|
-
(0,
|
|
12494
|
+
(0, import_node_path98.join)(baseDir, paths.root.relativeDirPath, relativePath2)
|
|
12439
12495
|
);
|
|
12440
12496
|
return new _GeminiCliRule({
|
|
12441
12497
|
baseDir,
|
|
@@ -12447,10 +12503,10 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12447
12503
|
});
|
|
12448
12504
|
}
|
|
12449
12505
|
if (!paths.nonRoot) {
|
|
12450
|
-
throw new Error(
|
|
12506
|
+
throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
|
|
12451
12507
|
}
|
|
12452
|
-
const relativePath = (0,
|
|
12453
|
-
const fileContent = await readFileContent((0,
|
|
12508
|
+
const relativePath = (0, import_node_path98.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
|
|
12509
|
+
const fileContent = await readFileContent((0, import_node_path98.join)(baseDir, relativePath));
|
|
12454
12510
|
return new _GeminiCliRule({
|
|
12455
12511
|
baseDir,
|
|
12456
12512
|
relativeDirPath: paths.nonRoot.relativeDirPath,
|
|
@@ -12509,7 +12565,7 @@ var GeminiCliRule = class _GeminiCliRule extends ToolRule {
|
|
|
12509
12565
|
};
|
|
12510
12566
|
|
|
12511
12567
|
// src/features/rules/junie-rule.ts
|
|
12512
|
-
var
|
|
12568
|
+
var import_node_path99 = require("path");
|
|
12513
12569
|
var JunieRule = class _JunieRule extends ToolRule {
|
|
12514
12570
|
static getSettablePaths(_options = {}) {
|
|
12515
12571
|
return {
|
|
@@ -12528,8 +12584,8 @@ var JunieRule = class _JunieRule extends ToolRule {
|
|
|
12528
12584
|
validate = true
|
|
12529
12585
|
}) {
|
|
12530
12586
|
const isRoot = relativeFilePath === "guidelines.md";
|
|
12531
|
-
const relativePath = isRoot ? "guidelines.md" : (0,
|
|
12532
|
-
const fileContent = await readFileContent((0,
|
|
12587
|
+
const relativePath = isRoot ? "guidelines.md" : (0, import_node_path99.join)(".junie", "memories", relativeFilePath);
|
|
12588
|
+
const fileContent = await readFileContent((0, import_node_path99.join)(baseDir, relativePath));
|
|
12533
12589
|
return new _JunieRule({
|
|
12534
12590
|
baseDir,
|
|
12535
12591
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12584,7 +12640,7 @@ var JunieRule = class _JunieRule extends ToolRule {
|
|
|
12584
12640
|
};
|
|
12585
12641
|
|
|
12586
12642
|
// src/features/rules/kilo-rule.ts
|
|
12587
|
-
var
|
|
12643
|
+
var import_node_path100 = require("path");
|
|
12588
12644
|
var KiloRule = class _KiloRule extends ToolRule {
|
|
12589
12645
|
static getSettablePaths(_options = {}) {
|
|
12590
12646
|
return {
|
|
@@ -12599,7 +12655,7 @@ var KiloRule = class _KiloRule extends ToolRule {
|
|
|
12599
12655
|
validate = true
|
|
12600
12656
|
}) {
|
|
12601
12657
|
const fileContent = await readFileContent(
|
|
12602
|
-
(0,
|
|
12658
|
+
(0, import_node_path100.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12603
12659
|
);
|
|
12604
12660
|
return new _KiloRule({
|
|
12605
12661
|
baseDir,
|
|
@@ -12651,7 +12707,7 @@ var KiloRule = class _KiloRule extends ToolRule {
|
|
|
12651
12707
|
};
|
|
12652
12708
|
|
|
12653
12709
|
// src/features/rules/kiro-rule.ts
|
|
12654
|
-
var
|
|
12710
|
+
var import_node_path101 = require("path");
|
|
12655
12711
|
var KiroRule = class _KiroRule extends ToolRule {
|
|
12656
12712
|
static getSettablePaths(_options = {}) {
|
|
12657
12713
|
return {
|
|
@@ -12666,7 +12722,7 @@ var KiroRule = class _KiroRule extends ToolRule {
|
|
|
12666
12722
|
validate = true
|
|
12667
12723
|
}) {
|
|
12668
12724
|
const fileContent = await readFileContent(
|
|
12669
|
-
(0,
|
|
12725
|
+
(0, import_node_path101.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12670
12726
|
);
|
|
12671
12727
|
return new _KiroRule({
|
|
12672
12728
|
baseDir,
|
|
@@ -12720,7 +12776,7 @@ var KiroRule = class _KiroRule extends ToolRule {
|
|
|
12720
12776
|
};
|
|
12721
12777
|
|
|
12722
12778
|
// src/features/rules/opencode-rule.ts
|
|
12723
|
-
var
|
|
12779
|
+
var import_node_path102 = require("path");
|
|
12724
12780
|
var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
12725
12781
|
static getSettablePaths(_options = {}) {
|
|
12726
12782
|
return {
|
|
@@ -12739,8 +12795,8 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
|
12739
12795
|
validate = true
|
|
12740
12796
|
}) {
|
|
12741
12797
|
const isRoot = relativeFilePath === "AGENTS.md";
|
|
12742
|
-
const relativePath = isRoot ? "AGENTS.md" : (0,
|
|
12743
|
-
const fileContent = await readFileContent((0,
|
|
12798
|
+
const relativePath = isRoot ? "AGENTS.md" : (0, import_node_path102.join)(".opencode", "memories", relativeFilePath);
|
|
12799
|
+
const fileContent = await readFileContent((0, import_node_path102.join)(baseDir, relativePath));
|
|
12744
12800
|
return new _OpenCodeRule({
|
|
12745
12801
|
baseDir,
|
|
12746
12802
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12795,7 +12851,7 @@ var OpenCodeRule = class _OpenCodeRule extends ToolRule {
|
|
|
12795
12851
|
};
|
|
12796
12852
|
|
|
12797
12853
|
// src/features/rules/qwencode-rule.ts
|
|
12798
|
-
var
|
|
12854
|
+
var import_node_path103 = require("path");
|
|
12799
12855
|
var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
12800
12856
|
static getSettablePaths(_options = {}) {
|
|
12801
12857
|
return {
|
|
@@ -12814,8 +12870,8 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
|
12814
12870
|
validate = true
|
|
12815
12871
|
}) {
|
|
12816
12872
|
const isRoot = relativeFilePath === "QWEN.md";
|
|
12817
|
-
const relativePath = isRoot ? "QWEN.md" : (0,
|
|
12818
|
-
const fileContent = await readFileContent((0,
|
|
12873
|
+
const relativePath = isRoot ? "QWEN.md" : (0, import_node_path103.join)(".qwen", "memories", relativeFilePath);
|
|
12874
|
+
const fileContent = await readFileContent((0, import_node_path103.join)(baseDir, relativePath));
|
|
12819
12875
|
return new _QwencodeRule({
|
|
12820
12876
|
baseDir,
|
|
12821
12877
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : this.getSettablePaths().nonRoot.relativeDirPath,
|
|
@@ -12867,7 +12923,7 @@ var QwencodeRule = class _QwencodeRule extends ToolRule {
|
|
|
12867
12923
|
};
|
|
12868
12924
|
|
|
12869
12925
|
// src/features/rules/replit-rule.ts
|
|
12870
|
-
var
|
|
12926
|
+
var import_node_path104 = require("path");
|
|
12871
12927
|
var ReplitRule = class _ReplitRule extends ToolRule {
|
|
12872
12928
|
static getSettablePaths(_options = {}) {
|
|
12873
12929
|
return {
|
|
@@ -12885,11 +12941,11 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12885
12941
|
const paths = this.getSettablePaths();
|
|
12886
12942
|
const isRoot = relativeFilePath === paths.root.relativeFilePath;
|
|
12887
12943
|
if (!isRoot) {
|
|
12888
|
-
throw new Error(
|
|
12944
|
+
throw new Error(`ReplitRule only supports root rules: ${relativeFilePath}`);
|
|
12889
12945
|
}
|
|
12890
12946
|
const relativePath = paths.root.relativeFilePath;
|
|
12891
12947
|
const fileContent = await readFileContent(
|
|
12892
|
-
(0,
|
|
12948
|
+
(0, import_node_path104.join)(baseDir, paths.root.relativeDirPath, relativePath)
|
|
12893
12949
|
);
|
|
12894
12950
|
return new _ReplitRule({
|
|
12895
12951
|
baseDir,
|
|
@@ -12908,7 +12964,7 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12908
12964
|
const paths = this.getSettablePaths();
|
|
12909
12965
|
const isRoot = rulesyncRule.getFrontmatter().root ?? false;
|
|
12910
12966
|
if (!isRoot) {
|
|
12911
|
-
throw new Error(
|
|
12967
|
+
throw new Error(`ReplitRule only supports root rules: ${rulesyncRule.getRelativeFilePath()}`);
|
|
12912
12968
|
}
|
|
12913
12969
|
return new _ReplitRule(
|
|
12914
12970
|
this.buildToolRuleParamsDefault({
|
|
@@ -12955,7 +13011,7 @@ var ReplitRule = class _ReplitRule extends ToolRule {
|
|
|
12955
13011
|
};
|
|
12956
13012
|
|
|
12957
13013
|
// src/features/rules/roo-rule.ts
|
|
12958
|
-
var
|
|
13014
|
+
var import_node_path105 = require("path");
|
|
12959
13015
|
var RooRule = class _RooRule extends ToolRule {
|
|
12960
13016
|
static getSettablePaths(_options = {}) {
|
|
12961
13017
|
return {
|
|
@@ -12970,7 +13026,7 @@ var RooRule = class _RooRule extends ToolRule {
|
|
|
12970
13026
|
validate = true
|
|
12971
13027
|
}) {
|
|
12972
13028
|
const fileContent = await readFileContent(
|
|
12973
|
-
(0,
|
|
13029
|
+
(0, import_node_path105.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
12974
13030
|
);
|
|
12975
13031
|
return new _RooRule({
|
|
12976
13032
|
baseDir,
|
|
@@ -13039,7 +13095,7 @@ var RooRule = class _RooRule extends ToolRule {
|
|
|
13039
13095
|
};
|
|
13040
13096
|
|
|
13041
13097
|
// src/features/rules/warp-rule.ts
|
|
13042
|
-
var
|
|
13098
|
+
var import_node_path106 = require("path");
|
|
13043
13099
|
var WarpRule = class _WarpRule extends ToolRule {
|
|
13044
13100
|
constructor({ fileContent, root, ...rest }) {
|
|
13045
13101
|
super({
|
|
@@ -13065,8 +13121,8 @@ var WarpRule = class _WarpRule extends ToolRule {
|
|
|
13065
13121
|
validate = true
|
|
13066
13122
|
}) {
|
|
13067
13123
|
const isRoot = relativeFilePath === this.getSettablePaths().root.relativeFilePath;
|
|
13068
|
-
const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : (0,
|
|
13069
|
-
const fileContent = await readFileContent((0,
|
|
13124
|
+
const relativePath = isRoot ? this.getSettablePaths().root.relativeFilePath : (0, import_node_path106.join)(this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath);
|
|
13125
|
+
const fileContent = await readFileContent((0, import_node_path106.join)(baseDir, relativePath));
|
|
13070
13126
|
return new _WarpRule({
|
|
13071
13127
|
baseDir,
|
|
13072
13128
|
relativeDirPath: isRoot ? this.getSettablePaths().root.relativeDirPath : ".warp",
|
|
@@ -13121,7 +13177,7 @@ var WarpRule = class _WarpRule extends ToolRule {
|
|
|
13121
13177
|
};
|
|
13122
13178
|
|
|
13123
13179
|
// src/features/rules/windsurf-rule.ts
|
|
13124
|
-
var
|
|
13180
|
+
var import_node_path107 = require("path");
|
|
13125
13181
|
var WindsurfRule = class _WindsurfRule extends ToolRule {
|
|
13126
13182
|
static getSettablePaths(_options = {}) {
|
|
13127
13183
|
return {
|
|
@@ -13136,7 +13192,7 @@ var WindsurfRule = class _WindsurfRule extends ToolRule {
|
|
|
13136
13192
|
validate = true
|
|
13137
13193
|
}) {
|
|
13138
13194
|
const fileContent = await readFileContent(
|
|
13139
|
-
(0,
|
|
13195
|
+
(0, import_node_path107.join)(baseDir, this.getSettablePaths().nonRoot.relativeDirPath, relativeFilePath)
|
|
13140
13196
|
);
|
|
13141
13197
|
return new _WindsurfRule({
|
|
13142
13198
|
baseDir,
|
|
@@ -13522,7 +13578,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13522
13578
|
}).relativeDirPath;
|
|
13523
13579
|
return this.skills.filter((skill) => skillClass.isTargetedByRulesyncSkill(skill)).map((skill) => {
|
|
13524
13580
|
const frontmatter = skill.getFrontmatter();
|
|
13525
|
-
const relativePath = (0,
|
|
13581
|
+
const relativePath = (0, import_node_path108.join)(toolRelativeDirPath, skill.getDirName(), SKILL_FILE_NAME);
|
|
13526
13582
|
return {
|
|
13527
13583
|
name: frontmatter.name,
|
|
13528
13584
|
description: frontmatter.description,
|
|
@@ -13633,12 +13689,12 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13633
13689
|
* Load and parse rulesync rule files from .rulesync/rules/ directory
|
|
13634
13690
|
*/
|
|
13635
13691
|
async loadRulesyncFiles() {
|
|
13636
|
-
const rulesyncBaseDir = (0,
|
|
13637
|
-
const files = await findFilesByGlobs((0,
|
|
13692
|
+
const rulesyncBaseDir = (0, import_node_path108.join)(this.baseDir, RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
13693
|
+
const files = await findFilesByGlobs((0, import_node_path108.join)(rulesyncBaseDir, "**", "*.md"));
|
|
13638
13694
|
logger.debug(`Found ${files.length} rulesync files`);
|
|
13639
13695
|
const rulesyncRules = await Promise.all(
|
|
13640
13696
|
files.map((file) => {
|
|
13641
|
-
const relativeFilePath = (0,
|
|
13697
|
+
const relativeFilePath = (0, import_node_path108.relative)(rulesyncBaseDir, file);
|
|
13642
13698
|
checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: rulesyncBaseDir });
|
|
13643
13699
|
return RulesyncRule.fromFile({
|
|
13644
13700
|
relativeFilePath
|
|
@@ -13647,7 +13703,9 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13647
13703
|
);
|
|
13648
13704
|
const rootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().root);
|
|
13649
13705
|
if (rootRules.length > 1) {
|
|
13650
|
-
throw new Error(
|
|
13706
|
+
throw new Error(
|
|
13707
|
+
`Multiple root rulesync rules found: ${rootRules.map((r) => (0, import_node_path108.join)(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13708
|
+
);
|
|
13651
13709
|
}
|
|
13652
13710
|
if (rootRules.length === 0 && rulesyncRules.length > 0) {
|
|
13653
13711
|
logger.warn(
|
|
@@ -13656,21 +13714,25 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13656
13714
|
}
|
|
13657
13715
|
const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
|
|
13658
13716
|
if (localRootRules.length > 1) {
|
|
13659
|
-
throw new Error(
|
|
13717
|
+
throw new Error(
|
|
13718
|
+
`Multiple localRoot rules found: ${localRootRules.map((r) => (0, import_node_path108.join)(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}. Only one rule can have localRoot: true`
|
|
13719
|
+
);
|
|
13660
13720
|
}
|
|
13661
13721
|
if (localRootRules.length > 0 && rootRules.length === 0) {
|
|
13662
|
-
throw new Error(
|
|
13722
|
+
throw new Error(
|
|
13723
|
+
`localRoot: true requires a root: true rule to exist (found in ${localRootRules.map((r) => (0, import_node_path108.join)(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")})`
|
|
13724
|
+
);
|
|
13663
13725
|
}
|
|
13664
13726
|
if (this.global) {
|
|
13665
13727
|
const nonRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().root);
|
|
13666
13728
|
if (nonRootRules.length > 0) {
|
|
13667
13729
|
logger.warn(
|
|
13668
|
-
`${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them`
|
|
13730
|
+
`${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them: ${nonRootRules.map((r) => (0, import_node_path108.join)(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13669
13731
|
);
|
|
13670
13732
|
}
|
|
13671
13733
|
if (localRootRules.length > 0) {
|
|
13672
13734
|
logger.warn(
|
|
13673
|
-
`${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them`
|
|
13735
|
+
`${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them: ${localRootRules.map((r) => (0, import_node_path108.join)(r.getRelativeDirPath(), r.getRelativeFilePath())).join(", ")}`
|
|
13674
13736
|
);
|
|
13675
13737
|
}
|
|
13676
13738
|
return rootRules;
|
|
@@ -13692,7 +13754,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13692
13754
|
return [];
|
|
13693
13755
|
}
|
|
13694
13756
|
const rootFilePaths = await findFilesByGlobs(
|
|
13695
|
-
(0,
|
|
13757
|
+
(0, import_node_path108.join)(
|
|
13696
13758
|
this.baseDir,
|
|
13697
13759
|
settablePaths.root.relativeDirPath ?? ".",
|
|
13698
13760
|
settablePaths.root.relativeFilePath
|
|
@@ -13703,7 +13765,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13703
13765
|
(filePath) => factory.class.forDeletion({
|
|
13704
13766
|
baseDir: this.baseDir,
|
|
13705
13767
|
relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
|
|
13706
|
-
relativeFilePath: (0,
|
|
13768
|
+
relativeFilePath: (0, import_node_path108.basename)(filePath),
|
|
13707
13769
|
global: this.global
|
|
13708
13770
|
})
|
|
13709
13771
|
).filter((rule) => rule.isDeletable());
|
|
@@ -13712,7 +13774,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13712
13774
|
rootFilePaths.map(
|
|
13713
13775
|
(filePath) => factory.class.fromFile({
|
|
13714
13776
|
baseDir: this.baseDir,
|
|
13715
|
-
relativeFilePath: (0,
|
|
13777
|
+
relativeFilePath: (0, import_node_path108.basename)(filePath),
|
|
13716
13778
|
global: this.global
|
|
13717
13779
|
})
|
|
13718
13780
|
)
|
|
@@ -13730,13 +13792,13 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13730
13792
|
return [];
|
|
13731
13793
|
}
|
|
13732
13794
|
const localRootFilePaths = await findFilesByGlobs(
|
|
13733
|
-
(0,
|
|
13795
|
+
(0, import_node_path108.join)(this.baseDir, settablePaths.root.relativeDirPath ?? ".", "CLAUDE.local.md")
|
|
13734
13796
|
);
|
|
13735
13797
|
return localRootFilePaths.map(
|
|
13736
13798
|
(filePath) => factory.class.forDeletion({
|
|
13737
13799
|
baseDir: this.baseDir,
|
|
13738
13800
|
relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
|
|
13739
|
-
relativeFilePath: (0,
|
|
13801
|
+
relativeFilePath: (0, import_node_path108.basename)(filePath),
|
|
13740
13802
|
global: this.global
|
|
13741
13803
|
})
|
|
13742
13804
|
).filter((rule) => rule.isDeletable());
|
|
@@ -13746,13 +13808,13 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13746
13808
|
if (!settablePaths.nonRoot) {
|
|
13747
13809
|
return [];
|
|
13748
13810
|
}
|
|
13749
|
-
const nonRootBaseDir = (0,
|
|
13811
|
+
const nonRootBaseDir = (0, import_node_path108.join)(this.baseDir, settablePaths.nonRoot.relativeDirPath);
|
|
13750
13812
|
const nonRootFilePaths = await findFilesByGlobs(
|
|
13751
|
-
(0,
|
|
13813
|
+
(0, import_node_path108.join)(nonRootBaseDir, "**", `*.${factory.meta.extension}`)
|
|
13752
13814
|
);
|
|
13753
13815
|
if (forDeletion) {
|
|
13754
13816
|
return nonRootFilePaths.map((filePath) => {
|
|
13755
|
-
const relativeFilePath = (0,
|
|
13817
|
+
const relativeFilePath = (0, import_node_path108.relative)(nonRootBaseDir, filePath);
|
|
13756
13818
|
checkPathTraversal({
|
|
13757
13819
|
relativePath: relativeFilePath,
|
|
13758
13820
|
intendedRootDir: nonRootBaseDir
|
|
@@ -13767,7 +13829,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13767
13829
|
}
|
|
13768
13830
|
return await Promise.all(
|
|
13769
13831
|
nonRootFilePaths.map((filePath) => {
|
|
13770
|
-
const relativeFilePath = (0,
|
|
13832
|
+
const relativeFilePath = (0, import_node_path108.relative)(nonRootBaseDir, filePath);
|
|
13771
13833
|
checkPathTraversal({ relativePath: relativeFilePath, intendedRootDir: nonRootBaseDir });
|
|
13772
13834
|
return factory.class.fromFile({
|
|
13773
13835
|
baseDir: this.baseDir,
|
|
@@ -13780,7 +13842,7 @@ var RulesProcessor = class extends FeatureProcessor {
|
|
|
13780
13842
|
logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
|
|
13781
13843
|
return [...rootToolRules, ...localRootToolRules, ...nonRootToolRules];
|
|
13782
13844
|
} catch (error) {
|
|
13783
|
-
logger.error(`Failed to load tool files: ${formatError(error)}`);
|
|
13845
|
+
logger.error(`Failed to load tool files for ${this.toolTarget}: ${formatError(error)}`);
|
|
13784
13846
|
return [];
|
|
13785
13847
|
}
|
|
13786
13848
|
}
|
|
@@ -13877,14 +13939,14 @@ s/<command> [arguments]
|
|
|
13877
13939
|
This syntax employs a double slash (\`s/\`) to prevent conflicts with built-in slash commands.
|
|
13878
13940
|
The \`s\` in \`s/\` stands for *simulate*. Because custom slash commands are not built-in, this syntax provides a pseudo way to invoke them.
|
|
13879
13941
|
|
|
13880
|
-
When users call a custom slash command, you have to look for the markdown file, \`${(0,
|
|
13942
|
+
When users call a custom slash command, you have to look for the markdown file, \`${(0, import_node_path108.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "{command}.md")}\`, then execute the contents of that file as the block of operations.` : "";
|
|
13881
13943
|
const subagentsSection = subagents ? `## Simulated Subagents
|
|
13882
13944
|
|
|
13883
13945
|
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.
|
|
13884
13946
|
|
|
13885
|
-
When users call a simulated subagent, it will look for the corresponding markdown file, \`${(0,
|
|
13947
|
+
When users call a simulated subagent, it will look for the corresponding markdown file, \`${(0, import_node_path108.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "{subagent}.md")}\`, and execute its contents as the block of operations.
|
|
13886
13948
|
|
|
13887
|
-
For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${(0,
|
|
13949
|
+
For example, if the user instructs \`Call planner subagent to plan the refactoring\`, you have to look for the markdown file, \`${(0, import_node_path108.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "planner.md")}\`, and execute its contents as the block of operations.` : "";
|
|
13888
13950
|
const skillsSection = skills ? this.generateSkillsSection(skills) : "";
|
|
13889
13951
|
const result = [
|
|
13890
13952
|
overview,
|
|
@@ -13911,61 +13973,56 @@ ${toonContent}`;
|
|
|
13911
13973
|
}
|
|
13912
13974
|
};
|
|
13913
13975
|
|
|
13914
|
-
// src/types/git-provider.ts
|
|
13915
|
-
var import_mini49 = require("zod/mini");
|
|
13916
|
-
var ALL_GIT_PROVIDERS = ["github", "gitlab"];
|
|
13917
|
-
var GitProviderSchema = import_mini49.z.enum(ALL_GIT_PROVIDERS);
|
|
13918
|
-
|
|
13919
13976
|
// src/lib/github-client.ts
|
|
13920
13977
|
var import_request_error = require("@octokit/request-error");
|
|
13921
13978
|
var import_rest = require("@octokit/rest");
|
|
13922
13979
|
|
|
13923
13980
|
// src/types/fetch.ts
|
|
13924
|
-
var
|
|
13981
|
+
var import_mini50 = require("zod/mini");
|
|
13925
13982
|
|
|
13926
13983
|
// src/types/fetch-targets.ts
|
|
13927
|
-
var
|
|
13984
|
+
var import_mini49 = require("zod/mini");
|
|
13928
13985
|
var ALL_FETCH_TARGETS = ["rulesync", ...ALL_TOOL_TARGETS];
|
|
13929
|
-
var FetchTargetSchema =
|
|
13986
|
+
var FetchTargetSchema = import_mini49.z.enum(ALL_FETCH_TARGETS);
|
|
13930
13987
|
|
|
13931
13988
|
// src/types/fetch.ts
|
|
13932
|
-
var ConflictStrategySchema =
|
|
13933
|
-
var GitHubFileTypeSchema =
|
|
13934
|
-
var GitHubFileEntrySchema =
|
|
13935
|
-
name:
|
|
13936
|
-
path:
|
|
13937
|
-
sha:
|
|
13938
|
-
size:
|
|
13989
|
+
var ConflictStrategySchema = import_mini50.z.enum(["skip", "overwrite"]);
|
|
13990
|
+
var GitHubFileTypeSchema = import_mini50.z.enum(["file", "dir", "symlink", "submodule"]);
|
|
13991
|
+
var GitHubFileEntrySchema = import_mini50.z.looseObject({
|
|
13992
|
+
name: import_mini50.z.string(),
|
|
13993
|
+
path: import_mini50.z.string(),
|
|
13994
|
+
sha: import_mini50.z.string(),
|
|
13995
|
+
size: import_mini50.z.number(),
|
|
13939
13996
|
type: GitHubFileTypeSchema,
|
|
13940
|
-
download_url:
|
|
13997
|
+
download_url: import_mini50.z.nullable(import_mini50.z.string())
|
|
13941
13998
|
});
|
|
13942
|
-
var FetchOptionsSchema =
|
|
13943
|
-
target:
|
|
13944
|
-
features:
|
|
13945
|
-
ref:
|
|
13946
|
-
path:
|
|
13947
|
-
output:
|
|
13948
|
-
conflict:
|
|
13949
|
-
token:
|
|
13950
|
-
verbose:
|
|
13951
|
-
silent:
|
|
13999
|
+
var FetchOptionsSchema = import_mini50.z.looseObject({
|
|
14000
|
+
target: import_mini50.z.optional(FetchTargetSchema),
|
|
14001
|
+
features: import_mini50.z.optional(import_mini50.z.array(import_mini50.z.enum(ALL_FEATURES_WITH_WILDCARD))),
|
|
14002
|
+
ref: import_mini50.z.optional(import_mini50.z.string()),
|
|
14003
|
+
path: import_mini50.z.optional(import_mini50.z.string()),
|
|
14004
|
+
output: import_mini50.z.optional(import_mini50.z.string()),
|
|
14005
|
+
conflict: import_mini50.z.optional(ConflictStrategySchema),
|
|
14006
|
+
token: import_mini50.z.optional(import_mini50.z.string()),
|
|
14007
|
+
verbose: import_mini50.z.optional(import_mini50.z.boolean()),
|
|
14008
|
+
silent: import_mini50.z.optional(import_mini50.z.boolean())
|
|
13952
14009
|
});
|
|
13953
|
-
var FetchFileStatusSchema =
|
|
13954
|
-
var GitHubRepoInfoSchema =
|
|
13955
|
-
default_branch:
|
|
13956
|
-
private:
|
|
14010
|
+
var FetchFileStatusSchema = import_mini50.z.enum(["created", "overwritten", "skipped"]);
|
|
14011
|
+
var GitHubRepoInfoSchema = import_mini50.z.looseObject({
|
|
14012
|
+
default_branch: import_mini50.z.string(),
|
|
14013
|
+
private: import_mini50.z.boolean()
|
|
13957
14014
|
});
|
|
13958
|
-
var GitHubReleaseAssetSchema =
|
|
13959
|
-
name:
|
|
13960
|
-
browser_download_url:
|
|
13961
|
-
size:
|
|
14015
|
+
var GitHubReleaseAssetSchema = import_mini50.z.looseObject({
|
|
14016
|
+
name: import_mini50.z.string(),
|
|
14017
|
+
browser_download_url: import_mini50.z.string(),
|
|
14018
|
+
size: import_mini50.z.number()
|
|
13962
14019
|
});
|
|
13963
|
-
var GitHubReleaseSchema =
|
|
13964
|
-
tag_name:
|
|
13965
|
-
name:
|
|
13966
|
-
prerelease:
|
|
13967
|
-
draft:
|
|
13968
|
-
assets:
|
|
14020
|
+
var GitHubReleaseSchema = import_mini50.z.looseObject({
|
|
14021
|
+
tag_name: import_mini50.z.string(),
|
|
14022
|
+
name: import_mini50.z.nullable(import_mini50.z.string()),
|
|
14023
|
+
prerelease: import_mini50.z.boolean(),
|
|
14024
|
+
draft: import_mini50.z.boolean(),
|
|
14025
|
+
assets: import_mini50.z.array(GitHubReleaseAssetSchema)
|
|
13969
14026
|
});
|
|
13970
14027
|
|
|
13971
14028
|
// src/lib/github-client.ts
|
|
@@ -14133,6 +14190,21 @@ var GitHubClient = class {
|
|
|
14133
14190
|
throw error;
|
|
14134
14191
|
}
|
|
14135
14192
|
}
|
|
14193
|
+
/**
|
|
14194
|
+
* Resolve a ref (branch, tag, or SHA) to a full commit SHA.
|
|
14195
|
+
*/
|
|
14196
|
+
async resolveRefToSha(owner, repo, ref) {
|
|
14197
|
+
try {
|
|
14198
|
+
const { data } = await this.octokit.repos.getCommit({
|
|
14199
|
+
owner,
|
|
14200
|
+
repo,
|
|
14201
|
+
ref
|
|
14202
|
+
});
|
|
14203
|
+
return data.sha;
|
|
14204
|
+
} catch (error) {
|
|
14205
|
+
throw this.handleError(error);
|
|
14206
|
+
}
|
|
14207
|
+
}
|
|
14136
14208
|
/**
|
|
14137
14209
|
* Get the latest release from a repository
|
|
14138
14210
|
*/
|
|
@@ -14203,96 +14275,60 @@ var GitHubClient = class {
|
|
|
14203
14275
|
}
|
|
14204
14276
|
};
|
|
14205
14277
|
|
|
14206
|
-
// src/lib/
|
|
14207
|
-
var
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
|
|
14215
|
-
};
|
|
14216
|
-
function isToolTarget(target) {
|
|
14217
|
-
return target !== "rulesync";
|
|
14278
|
+
// src/lib/github-utils.ts
|
|
14279
|
+
var MAX_RECURSION_DEPTH = 15;
|
|
14280
|
+
async function withSemaphore(semaphore, fn) {
|
|
14281
|
+
await semaphore.acquire();
|
|
14282
|
+
try {
|
|
14283
|
+
return await fn();
|
|
14284
|
+
} finally {
|
|
14285
|
+
semaphore.release();
|
|
14286
|
+
}
|
|
14218
14287
|
}
|
|
14219
|
-
function
|
|
14220
|
-
|
|
14221
|
-
|
|
14222
|
-
|
|
14288
|
+
async function listDirectoryRecursive(params) {
|
|
14289
|
+
const { client, owner, repo, path: path4, ref, depth = 0, semaphore } = params;
|
|
14290
|
+
if (depth > MAX_RECURSION_DEPTH) {
|
|
14291
|
+
throw new Error(
|
|
14292
|
+
`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while listing directory: ${path4}`
|
|
14223
14293
|
);
|
|
14224
14294
|
}
|
|
14225
|
-
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
const
|
|
14230
|
-
|
|
14231
|
-
|
|
14295
|
+
const entries = await withSemaphore(
|
|
14296
|
+
semaphore,
|
|
14297
|
+
() => client.listDirectory(owner, repo, path4, ref)
|
|
14298
|
+
);
|
|
14299
|
+
const files = [];
|
|
14300
|
+
const directories = [];
|
|
14301
|
+
for (const entry of entries) {
|
|
14302
|
+
if (entry.type === "file") {
|
|
14303
|
+
files.push(entry);
|
|
14304
|
+
} else if (entry.type === "dir") {
|
|
14305
|
+
directories.push(entry);
|
|
14306
|
+
}
|
|
14232
14307
|
}
|
|
14233
|
-
const
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
|
|
14237
|
-
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
feature: "rules",
|
|
14248
|
-
getTargets: () => RulesProcessor.getToolTargets({ global: false }),
|
|
14249
|
-
createProcessor: () => new RulesProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14250
|
-
},
|
|
14251
|
-
{
|
|
14252
|
-
feature: "commands",
|
|
14253
|
-
getTargets: () => CommandsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14254
|
-
createProcessor: () => new CommandsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14255
|
-
},
|
|
14256
|
-
{
|
|
14257
|
-
feature: "subagents",
|
|
14258
|
-
getTargets: () => SubagentsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14259
|
-
createProcessor: () => new SubagentsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14260
|
-
},
|
|
14261
|
-
{
|
|
14262
|
-
feature: "ignore",
|
|
14263
|
-
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
14264
|
-
createProcessor: () => new IgnoreProcessor({ baseDir: tempDir, toolTarget: target })
|
|
14265
|
-
},
|
|
14266
|
-
{
|
|
14267
|
-
feature: "mcp",
|
|
14268
|
-
getTargets: () => McpProcessor.getToolTargets({ global: false }),
|
|
14269
|
-
createProcessor: () => new McpProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14270
|
-
},
|
|
14271
|
-
{
|
|
14272
|
-
feature: "hooks",
|
|
14273
|
-
getTargets: () => HooksProcessor.getToolTargets({ global: false }),
|
|
14274
|
-
createProcessor: () => new HooksProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14275
|
-
}
|
|
14276
|
-
];
|
|
14277
|
-
for (const config of featureConfigs) {
|
|
14278
|
-
if (!features.includes(config.feature)) {
|
|
14279
|
-
continue;
|
|
14280
|
-
}
|
|
14281
|
-
const supportedTargets = config.getTargets();
|
|
14282
|
-
if (!supportedTargets.includes(target)) {
|
|
14283
|
-
continue;
|
|
14284
|
-
}
|
|
14285
|
-
const processor = config.createProcessor();
|
|
14286
|
-
const result = await processFeatureConversion({ processor, outputDir });
|
|
14287
|
-
convertedPaths.push(...result.paths);
|
|
14288
|
-
}
|
|
14289
|
-
if (features.includes("skills")) {
|
|
14290
|
-
logger.debug(
|
|
14291
|
-
"Skills conversion is not yet supported in fetch command. Use import command instead."
|
|
14292
|
-
);
|
|
14293
|
-
}
|
|
14294
|
-
return { converted: convertedPaths.length, convertedPaths };
|
|
14308
|
+
const subResults = await Promise.all(
|
|
14309
|
+
directories.map(
|
|
14310
|
+
(dir) => listDirectoryRecursive({
|
|
14311
|
+
client,
|
|
14312
|
+
owner,
|
|
14313
|
+
repo,
|
|
14314
|
+
path: dir.path,
|
|
14315
|
+
ref,
|
|
14316
|
+
depth: depth + 1,
|
|
14317
|
+
semaphore
|
|
14318
|
+
})
|
|
14319
|
+
)
|
|
14320
|
+
);
|
|
14321
|
+
return [...files, ...subResults.flat()];
|
|
14295
14322
|
}
|
|
14323
|
+
|
|
14324
|
+
// src/types/git-provider.ts
|
|
14325
|
+
var import_mini51 = require("zod/mini");
|
|
14326
|
+
var ALL_GIT_PROVIDERS = ["github", "gitlab"];
|
|
14327
|
+
var GitProviderSchema = import_mini51.z.enum(ALL_GIT_PROVIDERS);
|
|
14328
|
+
|
|
14329
|
+
// src/lib/source-parser.ts
|
|
14330
|
+
var GITHUB_HOSTS = /* @__PURE__ */ new Set(["github.com", "www.github.com"]);
|
|
14331
|
+
var GITLAB_HOSTS = /* @__PURE__ */ new Set(["gitlab.com", "www.gitlab.com"]);
|
|
14296
14332
|
function parseSource(source) {
|
|
14297
14333
|
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
14298
14334
|
return parseUrl(source);
|
|
@@ -14309,18 +14345,6 @@ function parseSource(source) {
|
|
|
14309
14345
|
}
|
|
14310
14346
|
return { provider: "github", ...parseShorthand(source) };
|
|
14311
14347
|
}
|
|
14312
|
-
var GITHUB_HOSTS = /* @__PURE__ */ new Set(["github.com", "www.github.com"]);
|
|
14313
|
-
var GITLAB_HOSTS = /* @__PURE__ */ new Set(["gitlab.com", "www.gitlab.com"]);
|
|
14314
|
-
var MAX_RECURSION_DEPTH = 15;
|
|
14315
|
-
var FETCH_CONCURRENCY_LIMIT = 10;
|
|
14316
|
-
async function withSemaphore(semaphore, fn) {
|
|
14317
|
-
await semaphore.acquire();
|
|
14318
|
-
try {
|
|
14319
|
-
return await fn();
|
|
14320
|
-
} finally {
|
|
14321
|
-
semaphore.release();
|
|
14322
|
-
}
|
|
14323
|
-
}
|
|
14324
14348
|
function parseUrl(url) {
|
|
14325
14349
|
const urlObj = new URL(url);
|
|
14326
14350
|
const host = urlObj.hostname.toLowerCase();
|
|
@@ -14395,6 +14419,97 @@ function parseShorthand(source) {
|
|
|
14395
14419
|
path: path4
|
|
14396
14420
|
};
|
|
14397
14421
|
}
|
|
14422
|
+
|
|
14423
|
+
// src/lib/fetch.ts
|
|
14424
|
+
var FEATURE_PATHS = {
|
|
14425
|
+
rules: ["rules"],
|
|
14426
|
+
commands: ["commands"],
|
|
14427
|
+
subagents: ["subagents"],
|
|
14428
|
+
skills: ["skills"],
|
|
14429
|
+
ignore: [RULESYNC_AIIGNORE_FILE_NAME],
|
|
14430
|
+
mcp: [RULESYNC_MCP_FILE_NAME],
|
|
14431
|
+
hooks: [RULESYNC_HOOKS_FILE_NAME]
|
|
14432
|
+
};
|
|
14433
|
+
function isToolTarget(target) {
|
|
14434
|
+
return target !== "rulesync";
|
|
14435
|
+
}
|
|
14436
|
+
function validateFileSize(relativePath, size) {
|
|
14437
|
+
if (size > MAX_FILE_SIZE) {
|
|
14438
|
+
throw new GitHubClientError(
|
|
14439
|
+
`File "${relativePath}" exceeds maximum size limit (${(size / 1024 / 1024).toFixed(2)}MB > ${MAX_FILE_SIZE / 1024 / 1024}MB)`
|
|
14440
|
+
);
|
|
14441
|
+
}
|
|
14442
|
+
}
|
|
14443
|
+
async function processFeatureConversion(params) {
|
|
14444
|
+
const { processor, outputDir } = params;
|
|
14445
|
+
const paths = [];
|
|
14446
|
+
const toolFiles = await processor.loadToolFiles();
|
|
14447
|
+
if (toolFiles.length === 0) {
|
|
14448
|
+
return { paths: [] };
|
|
14449
|
+
}
|
|
14450
|
+
const rulesyncFiles = await processor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
14451
|
+
for (const file of rulesyncFiles) {
|
|
14452
|
+
const relativePath = (0, import_node_path109.join)(file.getRelativeDirPath(), file.getRelativeFilePath());
|
|
14453
|
+
const outputPath = (0, import_node_path109.join)(outputDir, relativePath);
|
|
14454
|
+
await writeFileContent(outputPath, file.getFileContent());
|
|
14455
|
+
paths.push(relativePath);
|
|
14456
|
+
}
|
|
14457
|
+
return { paths };
|
|
14458
|
+
}
|
|
14459
|
+
async function convertFetchedFilesToRulesync(params) {
|
|
14460
|
+
const { tempDir, outputDir, target, features } = params;
|
|
14461
|
+
const convertedPaths = [];
|
|
14462
|
+
const featureConfigs = [
|
|
14463
|
+
{
|
|
14464
|
+
feature: "rules",
|
|
14465
|
+
getTargets: () => RulesProcessor.getToolTargets({ global: false }),
|
|
14466
|
+
createProcessor: () => new RulesProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14467
|
+
},
|
|
14468
|
+
{
|
|
14469
|
+
feature: "commands",
|
|
14470
|
+
getTargets: () => CommandsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14471
|
+
createProcessor: () => new CommandsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14472
|
+
},
|
|
14473
|
+
{
|
|
14474
|
+
feature: "subagents",
|
|
14475
|
+
getTargets: () => SubagentsProcessor.getToolTargets({ global: false, includeSimulated: false }),
|
|
14476
|
+
createProcessor: () => new SubagentsProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14477
|
+
},
|
|
14478
|
+
{
|
|
14479
|
+
feature: "ignore",
|
|
14480
|
+
getTargets: () => IgnoreProcessor.getToolTargets(),
|
|
14481
|
+
createProcessor: () => new IgnoreProcessor({ baseDir: tempDir, toolTarget: target })
|
|
14482
|
+
},
|
|
14483
|
+
{
|
|
14484
|
+
feature: "mcp",
|
|
14485
|
+
getTargets: () => McpProcessor.getToolTargets({ global: false }),
|
|
14486
|
+
createProcessor: () => new McpProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14487
|
+
},
|
|
14488
|
+
{
|
|
14489
|
+
feature: "hooks",
|
|
14490
|
+
getTargets: () => HooksProcessor.getToolTargets({ global: false }),
|
|
14491
|
+
createProcessor: () => new HooksProcessor({ baseDir: tempDir, toolTarget: target, global: false })
|
|
14492
|
+
}
|
|
14493
|
+
];
|
|
14494
|
+
for (const config of featureConfigs) {
|
|
14495
|
+
if (!features.includes(config.feature)) {
|
|
14496
|
+
continue;
|
|
14497
|
+
}
|
|
14498
|
+
const supportedTargets = config.getTargets();
|
|
14499
|
+
if (!supportedTargets.includes(target)) {
|
|
14500
|
+
continue;
|
|
14501
|
+
}
|
|
14502
|
+
const processor = config.createProcessor();
|
|
14503
|
+
const result = await processFeatureConversion({ processor, outputDir });
|
|
14504
|
+
convertedPaths.push(...result.paths);
|
|
14505
|
+
}
|
|
14506
|
+
if (features.includes("skills")) {
|
|
14507
|
+
logger.debug(
|
|
14508
|
+
"Skills conversion is not yet supported in fetch command. Use import command instead."
|
|
14509
|
+
);
|
|
14510
|
+
}
|
|
14511
|
+
return { converted: convertedPaths.length, convertedPaths };
|
|
14512
|
+
}
|
|
14398
14513
|
function resolveFeatures(features) {
|
|
14399
14514
|
if (!features || features.length === 0 || features.includes("*")) {
|
|
14400
14515
|
return [...ALL_FEATURES];
|
|
@@ -14481,7 +14596,7 @@ async function fetchFiles(params) {
|
|
|
14481
14596
|
skipped: 0
|
|
14482
14597
|
};
|
|
14483
14598
|
}
|
|
14484
|
-
const outputBasePath = (0,
|
|
14599
|
+
const outputBasePath = (0, import_node_path109.join)(baseDir, outputDir);
|
|
14485
14600
|
for (const { relativePath, size } of filesToFetch) {
|
|
14486
14601
|
checkPathTraversal({
|
|
14487
14602
|
relativePath,
|
|
@@ -14491,7 +14606,7 @@ async function fetchFiles(params) {
|
|
|
14491
14606
|
}
|
|
14492
14607
|
const results = await Promise.all(
|
|
14493
14608
|
filesToFetch.map(async ({ remotePath, relativePath }) => {
|
|
14494
|
-
const localPath = (0,
|
|
14609
|
+
const localPath = (0, import_node_path109.join)(outputBasePath, relativePath);
|
|
14495
14610
|
const exists = await fileExists(localPath);
|
|
14496
14611
|
if (exists && conflictStrategy === "skip") {
|
|
14497
14612
|
logger.debug(`Skipping existing file: ${relativePath}`);
|
|
@@ -14533,7 +14648,7 @@ async function collectFeatureFiles(params) {
|
|
|
14533
14648
|
);
|
|
14534
14649
|
const results = await Promise.all(
|
|
14535
14650
|
tasks.map(async ({ featurePath }) => {
|
|
14536
|
-
const fullPath = basePath === "." || basePath === "" ? featurePath : (0,
|
|
14651
|
+
const fullPath = basePath === "." || basePath === "" ? featurePath : (0, import_node_path109.join)(basePath, featurePath);
|
|
14537
14652
|
const collected = [];
|
|
14538
14653
|
try {
|
|
14539
14654
|
if (featurePath.includes(".")) {
|
|
@@ -14586,41 +14701,6 @@ async function collectFeatureFiles(params) {
|
|
|
14586
14701
|
);
|
|
14587
14702
|
return results.flat();
|
|
14588
14703
|
}
|
|
14589
|
-
async function listDirectoryRecursive(params) {
|
|
14590
|
-
const { client, owner, repo, path: path4, ref, depth = 0, semaphore } = params;
|
|
14591
|
-
if (depth > MAX_RECURSION_DEPTH) {
|
|
14592
|
-
throw new Error(
|
|
14593
|
-
`Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded while listing directory: ${path4}`
|
|
14594
|
-
);
|
|
14595
|
-
}
|
|
14596
|
-
const entries = await withSemaphore(
|
|
14597
|
-
semaphore,
|
|
14598
|
-
() => client.listDirectory(owner, repo, path4, ref)
|
|
14599
|
-
);
|
|
14600
|
-
const files = [];
|
|
14601
|
-
const directories = [];
|
|
14602
|
-
for (const entry of entries) {
|
|
14603
|
-
if (entry.type === "file") {
|
|
14604
|
-
files.push(entry);
|
|
14605
|
-
} else if (entry.type === "dir") {
|
|
14606
|
-
directories.push(entry);
|
|
14607
|
-
}
|
|
14608
|
-
}
|
|
14609
|
-
const subResults = await Promise.all(
|
|
14610
|
-
directories.map(
|
|
14611
|
-
(dir) => listDirectoryRecursive({
|
|
14612
|
-
client,
|
|
14613
|
-
owner,
|
|
14614
|
-
repo,
|
|
14615
|
-
path: dir.path,
|
|
14616
|
-
ref,
|
|
14617
|
-
depth: depth + 1,
|
|
14618
|
-
semaphore
|
|
14619
|
-
})
|
|
14620
|
-
)
|
|
14621
|
-
);
|
|
14622
|
-
return [...files, ...subResults.flat()];
|
|
14623
|
-
}
|
|
14624
14704
|
async function fetchAndConvertToolFiles(params) {
|
|
14625
14705
|
const {
|
|
14626
14706
|
client,
|
|
@@ -14668,7 +14748,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14668
14748
|
relativePath: toolRelativePath,
|
|
14669
14749
|
intendedRootDir: tempDir
|
|
14670
14750
|
});
|
|
14671
|
-
const localPath = (0,
|
|
14751
|
+
const localPath = (0, import_node_path109.join)(tempDir, toolRelativePath);
|
|
14672
14752
|
const content = await withSemaphore(
|
|
14673
14753
|
semaphore,
|
|
14674
14754
|
() => client.getFileContent(parsed.owner, parsed.repo, remotePath, ref)
|
|
@@ -14677,7 +14757,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14677
14757
|
logger.debug(`Fetched to temp: ${toolRelativePath}`);
|
|
14678
14758
|
})
|
|
14679
14759
|
);
|
|
14680
|
-
const outputBasePath = (0,
|
|
14760
|
+
const outputBasePath = (0, import_node_path109.join)(baseDir, outputDir);
|
|
14681
14761
|
const { converted, convertedPaths } = await convertFetchedFilesToRulesync({
|
|
14682
14762
|
tempDir,
|
|
14683
14763
|
outputDir: outputBasePath,
|
|
@@ -14688,7 +14768,7 @@ async function fetchAndConvertToolFiles(params) {
|
|
|
14688
14768
|
relativePath,
|
|
14689
14769
|
status: "created"
|
|
14690
14770
|
}));
|
|
14691
|
-
logger.
|
|
14771
|
+
logger.debug(`Converted ${converted} files from ${target} format to rulesync format`);
|
|
14692
14772
|
return {
|
|
14693
14773
|
source: `${parsed.owner}/${parsed.repo}`,
|
|
14694
14774
|
ref,
|
|
@@ -14750,7 +14830,7 @@ function mapToToolPath(relativePath, toolPaths) {
|
|
|
14750
14830
|
if (relativePath.startsWith("rules/")) {
|
|
14751
14831
|
const restPath = relativePath.substring("rules/".length);
|
|
14752
14832
|
if (toolPaths.rules?.nonRoot) {
|
|
14753
|
-
return (0,
|
|
14833
|
+
return (0, import_node_path109.join)(toolPaths.rules.nonRoot, restPath);
|
|
14754
14834
|
}
|
|
14755
14835
|
}
|
|
14756
14836
|
if (toolPaths.rules?.root && relativePath === toolPaths.rules.root) {
|
|
@@ -14759,19 +14839,19 @@ function mapToToolPath(relativePath, toolPaths) {
|
|
|
14759
14839
|
if (relativePath.startsWith("commands/")) {
|
|
14760
14840
|
const restPath = relativePath.substring("commands/".length);
|
|
14761
14841
|
if (toolPaths.commands) {
|
|
14762
|
-
return (0,
|
|
14842
|
+
return (0, import_node_path109.join)(toolPaths.commands, restPath);
|
|
14763
14843
|
}
|
|
14764
14844
|
}
|
|
14765
14845
|
if (relativePath.startsWith("subagents/")) {
|
|
14766
14846
|
const restPath = relativePath.substring("subagents/".length);
|
|
14767
14847
|
if (toolPaths.subagents) {
|
|
14768
|
-
return (0,
|
|
14848
|
+
return (0, import_node_path109.join)(toolPaths.subagents, restPath);
|
|
14769
14849
|
}
|
|
14770
14850
|
}
|
|
14771
14851
|
if (relativePath.startsWith("skills/")) {
|
|
14772
14852
|
const restPath = relativePath.substring("skills/".length);
|
|
14773
14853
|
if (toolPaths.skills) {
|
|
14774
|
-
return (0,
|
|
14854
|
+
return (0, import_node_path109.join)(toolPaths.skills, restPath);
|
|
14775
14855
|
}
|
|
14776
14856
|
}
|
|
14777
14857
|
return relativePath;
|
|
@@ -14801,7 +14881,7 @@ async function fetchCommand(options) {
|
|
|
14801
14881
|
verbose: fetchOptions.verbose ?? false,
|
|
14802
14882
|
silent: fetchOptions.silent ?? false
|
|
14803
14883
|
});
|
|
14804
|
-
logger.
|
|
14884
|
+
logger.debug(`Fetching files from ${source}...`);
|
|
14805
14885
|
try {
|
|
14806
14886
|
const summary = await fetchFiles({
|
|
14807
14887
|
source,
|
|
@@ -14824,10 +14904,14 @@ async function fetchCommand(options) {
|
|
|
14824
14904
|
|
|
14825
14905
|
// src/config/config-resolver.ts
|
|
14826
14906
|
var import_jsonc_parser = require("jsonc-parser");
|
|
14827
|
-
var
|
|
14907
|
+
var import_node_path110 = require("path");
|
|
14828
14908
|
|
|
14829
14909
|
// src/config/config.ts
|
|
14830
14910
|
var import_mini52 = require("zod/mini");
|
|
14911
|
+
var SourceEntrySchema = import_mini52.z.object({
|
|
14912
|
+
source: import_mini52.z.string().check((0, import_mini52.minLength)(1, "source must be a non-empty string")),
|
|
14913
|
+
skills: (0, import_mini52.optional)(import_mini52.z.array(import_mini52.z.string()))
|
|
14914
|
+
});
|
|
14831
14915
|
var ConfigParamsSchema = import_mini52.z.object({
|
|
14832
14916
|
baseDirs: import_mini52.z.array(import_mini52.z.string()),
|
|
14833
14917
|
targets: RulesyncTargetsSchema,
|
|
@@ -14841,7 +14925,9 @@ var ConfigParamsSchema = import_mini52.z.object({
|
|
|
14841
14925
|
simulateSubagents: (0, import_mini52.optional)(import_mini52.z.boolean()),
|
|
14842
14926
|
simulateSkills: (0, import_mini52.optional)(import_mini52.z.boolean()),
|
|
14843
14927
|
dryRun: (0, import_mini52.optional)(import_mini52.z.boolean()),
|
|
14844
|
-
check: (0, import_mini52.optional)(import_mini52.z.boolean())
|
|
14928
|
+
check: (0, import_mini52.optional)(import_mini52.z.boolean()),
|
|
14929
|
+
// Declarative skill sources
|
|
14930
|
+
sources: (0, import_mini52.optional)(import_mini52.z.array(SourceEntrySchema))
|
|
14845
14931
|
});
|
|
14846
14932
|
var PartialConfigParamsSchema = import_mini52.z.partial(ConfigParamsSchema);
|
|
14847
14933
|
var ConfigFileSchema = import_mini52.z.object({
|
|
@@ -14867,6 +14953,7 @@ var Config = class {
|
|
|
14867
14953
|
simulateSkills;
|
|
14868
14954
|
dryRun;
|
|
14869
14955
|
check;
|
|
14956
|
+
sources;
|
|
14870
14957
|
constructor({
|
|
14871
14958
|
baseDirs,
|
|
14872
14959
|
targets,
|
|
@@ -14879,7 +14966,8 @@ var Config = class {
|
|
|
14879
14966
|
simulateSubagents,
|
|
14880
14967
|
simulateSkills,
|
|
14881
14968
|
dryRun,
|
|
14882
|
-
check
|
|
14969
|
+
check,
|
|
14970
|
+
sources
|
|
14883
14971
|
}) {
|
|
14884
14972
|
this.validateConflictingTargets(targets);
|
|
14885
14973
|
if (dryRun && check) {
|
|
@@ -14897,6 +14985,7 @@ var Config = class {
|
|
|
14897
14985
|
this.simulateSkills = simulateSkills ?? false;
|
|
14898
14986
|
this.dryRun = dryRun ?? false;
|
|
14899
14987
|
this.check = check ?? false;
|
|
14988
|
+
this.sources = sources ?? [];
|
|
14900
14989
|
}
|
|
14901
14990
|
validateConflictingTargets(targets) {
|
|
14902
14991
|
for (const [target1, target2] of CONFLICTING_TARGET_PAIRS) {
|
|
@@ -14987,6 +15076,9 @@ var Config = class {
|
|
|
14987
15076
|
getCheck() {
|
|
14988
15077
|
return this.check;
|
|
14989
15078
|
}
|
|
15079
|
+
getSources() {
|
|
15080
|
+
return this.sources;
|
|
15081
|
+
}
|
|
14990
15082
|
/**
|
|
14991
15083
|
* Returns true if either dry-run or check mode is enabled.
|
|
14992
15084
|
* In both modes, no files should be written.
|
|
@@ -15010,7 +15102,8 @@ var getDefaults = () => ({
|
|
|
15010
15102
|
simulateSubagents: false,
|
|
15011
15103
|
simulateSkills: false,
|
|
15012
15104
|
dryRun: false,
|
|
15013
|
-
check: false
|
|
15105
|
+
check: false,
|
|
15106
|
+
sources: []
|
|
15014
15107
|
});
|
|
15015
15108
|
var loadConfigFromFile = async (filePath) => {
|
|
15016
15109
|
if (!await fileExists(filePath)) {
|
|
@@ -15040,7 +15133,8 @@ var mergeConfigs = (baseConfig, localConfig) => {
|
|
|
15040
15133
|
simulateSubagents: localConfig.simulateSubagents ?? baseConfig.simulateSubagents,
|
|
15041
15134
|
simulateSkills: localConfig.simulateSkills ?? baseConfig.simulateSkills,
|
|
15042
15135
|
dryRun: localConfig.dryRun ?? baseConfig.dryRun,
|
|
15043
|
-
check: localConfig.check ?? baseConfig.check
|
|
15136
|
+
check: localConfig.check ?? baseConfig.check,
|
|
15137
|
+
sources: localConfig.sources ?? baseConfig.sources
|
|
15044
15138
|
};
|
|
15045
15139
|
};
|
|
15046
15140
|
var ConfigResolver = class {
|
|
@@ -15061,8 +15155,8 @@ var ConfigResolver = class {
|
|
|
15061
15155
|
}) {
|
|
15062
15156
|
const validatedConfigPath = resolvePath(configPath, process.cwd());
|
|
15063
15157
|
const baseConfig = await loadConfigFromFile(validatedConfigPath);
|
|
15064
|
-
const configDir = (0,
|
|
15065
|
-
const localConfigPath = (0,
|
|
15158
|
+
const configDir = (0, import_node_path110.dirname)(validatedConfigPath);
|
|
15159
|
+
const localConfigPath = (0, import_node_path110.join)(configDir, RULESYNC_LOCAL_CONFIG_RELATIVE_FILE_PATH);
|
|
15066
15160
|
const localConfig = await loadConfigFromFile(localConfigPath);
|
|
15067
15161
|
const configByFile = mergeConfigs(baseConfig, localConfig);
|
|
15068
15162
|
const resolvedGlobal = global ?? configByFile.global ?? getDefaults().global;
|
|
@@ -15084,7 +15178,8 @@ var ConfigResolver = class {
|
|
|
15084
15178
|
simulateSubagents: resolvedSimulateSubagents,
|
|
15085
15179
|
simulateSkills: resolvedSimulateSkills,
|
|
15086
15180
|
dryRun: dryRun ?? configByFile.dryRun ?? getDefaults().dryRun,
|
|
15087
|
-
check: check ?? configByFile.check ?? getDefaults().check
|
|
15181
|
+
check: check ?? configByFile.check ?? getDefaults().check,
|
|
15182
|
+
sources: configByFile.sources ?? getDefaults().sources
|
|
15088
15183
|
};
|
|
15089
15184
|
return new Config(configParams);
|
|
15090
15185
|
}
|
|
@@ -15096,7 +15191,7 @@ function getBaseDirsInLightOfGlobal({
|
|
|
15096
15191
|
if (global) {
|
|
15097
15192
|
return [getHomeDirectory()];
|
|
15098
15193
|
}
|
|
15099
|
-
const resolvedBaseDirs = baseDirs.map((baseDir) => (0,
|
|
15194
|
+
const resolvedBaseDirs = baseDirs.map((baseDir) => (0, import_node_path110.resolve)(baseDir));
|
|
15100
15195
|
resolvedBaseDirs.forEach((baseDir) => {
|
|
15101
15196
|
validateBaseDir(baseDir);
|
|
15102
15197
|
});
|
|
@@ -15105,34 +15200,38 @@ function getBaseDirsInLightOfGlobal({
|
|
|
15105
15200
|
|
|
15106
15201
|
// src/lib/generate.ts
|
|
15107
15202
|
var import_es_toolkit4 = require("es-toolkit");
|
|
15108
|
-
var
|
|
15203
|
+
var import_node_path111 = require("path");
|
|
15109
15204
|
async function processFeatureGeneration(params) {
|
|
15110
15205
|
const { config, processor, toolFiles } = params;
|
|
15111
15206
|
let totalCount = 0;
|
|
15207
|
+
const allPaths = [];
|
|
15112
15208
|
let hasDiff = false;
|
|
15113
|
-
const
|
|
15114
|
-
totalCount +=
|
|
15115
|
-
|
|
15209
|
+
const writeResult = await processor.writeAiFiles(toolFiles);
|
|
15210
|
+
totalCount += writeResult.count;
|
|
15211
|
+
allPaths.push(...writeResult.paths);
|
|
15212
|
+
if (writeResult.count > 0) hasDiff = true;
|
|
15116
15213
|
if (config.getDelete()) {
|
|
15117
15214
|
const existingToolFiles = await processor.loadToolFiles({ forDeletion: true });
|
|
15118
15215
|
const orphanCount = await processor.removeOrphanAiFiles(existingToolFiles, toolFiles);
|
|
15119
15216
|
if (orphanCount > 0) hasDiff = true;
|
|
15120
15217
|
}
|
|
15121
|
-
return { count: totalCount, hasDiff };
|
|
15218
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15122
15219
|
}
|
|
15123
15220
|
async function processDirFeatureGeneration(params) {
|
|
15124
15221
|
const { config, processor, toolDirs } = params;
|
|
15125
15222
|
let totalCount = 0;
|
|
15223
|
+
const allPaths = [];
|
|
15126
15224
|
let hasDiff = false;
|
|
15127
|
-
const
|
|
15128
|
-
totalCount +=
|
|
15129
|
-
|
|
15225
|
+
const writeResult = await processor.writeAiDirs(toolDirs);
|
|
15226
|
+
totalCount += writeResult.count;
|
|
15227
|
+
allPaths.push(...writeResult.paths);
|
|
15228
|
+
if (writeResult.count > 0) hasDiff = true;
|
|
15130
15229
|
if (config.getDelete()) {
|
|
15131
15230
|
const existingToolDirs = await processor.loadToolDirsToDelete();
|
|
15132
15231
|
const orphanCount = await processor.removeOrphanAiDirs(existingToolDirs, toolDirs);
|
|
15133
15232
|
if (orphanCount > 0) hasDiff = true;
|
|
15134
15233
|
}
|
|
15135
|
-
return { count: totalCount, hasDiff };
|
|
15234
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15136
15235
|
}
|
|
15137
15236
|
async function processEmptyFeatureGeneration(params) {
|
|
15138
15237
|
const { config, processor } = params;
|
|
@@ -15143,10 +15242,10 @@ async function processEmptyFeatureGeneration(params) {
|
|
|
15143
15242
|
const orphanCount = await processor.removeOrphanAiFiles(existingToolFiles, []);
|
|
15144
15243
|
if (orphanCount > 0) hasDiff = true;
|
|
15145
15244
|
}
|
|
15146
|
-
return { count: totalCount, hasDiff };
|
|
15245
|
+
return { count: totalCount, paths: [], hasDiff };
|
|
15147
15246
|
}
|
|
15148
15247
|
async function checkRulesyncDirExists(params) {
|
|
15149
|
-
return fileExists((0,
|
|
15248
|
+
return fileExists((0, import_node_path111.join)(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
|
|
15150
15249
|
}
|
|
15151
15250
|
async function generate(params) {
|
|
15152
15251
|
const { config } = params;
|
|
@@ -15160,12 +15259,19 @@ async function generate(params) {
|
|
|
15160
15259
|
const hasDiff = ignoreResult.hasDiff || mcpResult.hasDiff || commandsResult.hasDiff || subagentsResult.hasDiff || skillsResult.hasDiff || hooksResult.hasDiff || rulesResult.hasDiff;
|
|
15161
15260
|
return {
|
|
15162
15261
|
rulesCount: rulesResult.count,
|
|
15262
|
+
rulesPaths: rulesResult.paths,
|
|
15163
15263
|
ignoreCount: ignoreResult.count,
|
|
15264
|
+
ignorePaths: ignoreResult.paths,
|
|
15164
15265
|
mcpCount: mcpResult.count,
|
|
15266
|
+
mcpPaths: mcpResult.paths,
|
|
15165
15267
|
commandsCount: commandsResult.count,
|
|
15268
|
+
commandsPaths: commandsResult.paths,
|
|
15166
15269
|
subagentsCount: subagentsResult.count,
|
|
15270
|
+
subagentsPaths: subagentsResult.paths,
|
|
15167
15271
|
skillsCount: skillsResult.count,
|
|
15272
|
+
skillsPaths: skillsResult.paths,
|
|
15168
15273
|
hooksCount: hooksResult.count,
|
|
15274
|
+
hooksPaths: hooksResult.paths,
|
|
15169
15275
|
skills: skillsResult.skills,
|
|
15170
15276
|
hasDiff
|
|
15171
15277
|
};
|
|
@@ -15173,6 +15279,7 @@ async function generate(params) {
|
|
|
15173
15279
|
async function generateRulesCore(params) {
|
|
15174
15280
|
const { config, skills } = params;
|
|
15175
15281
|
let totalCount = 0;
|
|
15282
|
+
const allPaths = [];
|
|
15176
15283
|
let hasDiff = false;
|
|
15177
15284
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
15178
15285
|
config.getTargets(),
|
|
@@ -15201,17 +15308,19 @@ async function generateRulesCore(params) {
|
|
|
15201
15308
|
toolFiles
|
|
15202
15309
|
});
|
|
15203
15310
|
totalCount += result.count;
|
|
15311
|
+
allPaths.push(...result.paths);
|
|
15204
15312
|
if (result.hasDiff) hasDiff = true;
|
|
15205
15313
|
}
|
|
15206
15314
|
}
|
|
15207
|
-
return { count: totalCount, hasDiff };
|
|
15315
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15208
15316
|
}
|
|
15209
15317
|
async function generateIgnoreCore(params) {
|
|
15210
15318
|
const { config } = params;
|
|
15211
15319
|
if (config.getGlobal()) {
|
|
15212
|
-
return { count: 0, hasDiff: false };
|
|
15320
|
+
return { count: 0, paths: [], hasDiff: false };
|
|
15213
15321
|
}
|
|
15214
15322
|
let totalCount = 0;
|
|
15323
|
+
const allPaths = [];
|
|
15215
15324
|
let hasDiff = false;
|
|
15216
15325
|
for (const toolTarget of (0, import_es_toolkit4.intersection)(config.getTargets(), IgnoreProcessor.getToolTargets())) {
|
|
15217
15326
|
if (!config.getFeatures(toolTarget).includes("ignore")) {
|
|
@@ -15240,6 +15349,7 @@ async function generateIgnoreCore(params) {
|
|
|
15240
15349
|
});
|
|
15241
15350
|
}
|
|
15242
15351
|
totalCount += result.count;
|
|
15352
|
+
allPaths.push(...result.paths);
|
|
15243
15353
|
if (result.hasDiff) hasDiff = true;
|
|
15244
15354
|
} catch (error) {
|
|
15245
15355
|
logger.warn(
|
|
@@ -15249,11 +15359,12 @@ async function generateIgnoreCore(params) {
|
|
|
15249
15359
|
}
|
|
15250
15360
|
}
|
|
15251
15361
|
}
|
|
15252
|
-
return { count: totalCount, hasDiff };
|
|
15362
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15253
15363
|
}
|
|
15254
15364
|
async function generateMcpCore(params) {
|
|
15255
15365
|
const { config } = params;
|
|
15256
15366
|
let totalCount = 0;
|
|
15367
|
+
const allPaths = [];
|
|
15257
15368
|
let hasDiff = false;
|
|
15258
15369
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
15259
15370
|
config.getTargets(),
|
|
@@ -15278,14 +15389,16 @@ async function generateMcpCore(params) {
|
|
|
15278
15389
|
toolFiles
|
|
15279
15390
|
});
|
|
15280
15391
|
totalCount += result.count;
|
|
15392
|
+
allPaths.push(...result.paths);
|
|
15281
15393
|
if (result.hasDiff) hasDiff = true;
|
|
15282
15394
|
}
|
|
15283
15395
|
}
|
|
15284
|
-
return { count: totalCount, hasDiff };
|
|
15396
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15285
15397
|
}
|
|
15286
15398
|
async function generateCommandsCore(params) {
|
|
15287
15399
|
const { config } = params;
|
|
15288
15400
|
let totalCount = 0;
|
|
15401
|
+
const allPaths = [];
|
|
15289
15402
|
let hasDiff = false;
|
|
15290
15403
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
15291
15404
|
config.getTargets(),
|
|
@@ -15313,14 +15426,16 @@ async function generateCommandsCore(params) {
|
|
|
15313
15426
|
toolFiles
|
|
15314
15427
|
});
|
|
15315
15428
|
totalCount += result.count;
|
|
15429
|
+
allPaths.push(...result.paths);
|
|
15316
15430
|
if (result.hasDiff) hasDiff = true;
|
|
15317
15431
|
}
|
|
15318
15432
|
}
|
|
15319
|
-
return { count: totalCount, hasDiff };
|
|
15433
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15320
15434
|
}
|
|
15321
15435
|
async function generateSubagentsCore(params) {
|
|
15322
15436
|
const { config } = params;
|
|
15323
15437
|
let totalCount = 0;
|
|
15438
|
+
const allPaths = [];
|
|
15324
15439
|
let hasDiff = false;
|
|
15325
15440
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
15326
15441
|
config.getTargets(),
|
|
@@ -15348,14 +15463,16 @@ async function generateSubagentsCore(params) {
|
|
|
15348
15463
|
toolFiles
|
|
15349
15464
|
});
|
|
15350
15465
|
totalCount += result.count;
|
|
15466
|
+
allPaths.push(...result.paths);
|
|
15351
15467
|
if (result.hasDiff) hasDiff = true;
|
|
15352
15468
|
}
|
|
15353
15469
|
}
|
|
15354
|
-
return { count: totalCount, hasDiff };
|
|
15470
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15355
15471
|
}
|
|
15356
15472
|
async function generateSkillsCore(params) {
|
|
15357
15473
|
const { config } = params;
|
|
15358
15474
|
let totalCount = 0;
|
|
15475
|
+
const allPaths = [];
|
|
15359
15476
|
let hasDiff = false;
|
|
15360
15477
|
const allSkills = [];
|
|
15361
15478
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
@@ -15389,14 +15506,16 @@ async function generateSkillsCore(params) {
|
|
|
15389
15506
|
toolDirs
|
|
15390
15507
|
});
|
|
15391
15508
|
totalCount += result.count;
|
|
15509
|
+
allPaths.push(...result.paths);
|
|
15392
15510
|
if (result.hasDiff) hasDiff = true;
|
|
15393
15511
|
}
|
|
15394
15512
|
}
|
|
15395
|
-
return { count: totalCount, skills: allSkills, hasDiff };
|
|
15513
|
+
return { count: totalCount, paths: allPaths, skills: allSkills, hasDiff };
|
|
15396
15514
|
}
|
|
15397
15515
|
async function generateHooksCore(params) {
|
|
15398
15516
|
const { config } = params;
|
|
15399
15517
|
let totalCount = 0;
|
|
15518
|
+
const allPaths = [];
|
|
15400
15519
|
let hasDiff = false;
|
|
15401
15520
|
const toolTargets = (0, import_es_toolkit4.intersection)(
|
|
15402
15521
|
config.getTargets(),
|
|
@@ -15429,10 +15548,11 @@ async function generateHooksCore(params) {
|
|
|
15429
15548
|
});
|
|
15430
15549
|
}
|
|
15431
15550
|
totalCount += result.count;
|
|
15551
|
+
allPaths.push(...result.paths);
|
|
15432
15552
|
if (result.hasDiff) hasDiff = true;
|
|
15433
15553
|
}
|
|
15434
15554
|
}
|
|
15435
|
-
return { count: totalCount, hasDiff };
|
|
15555
|
+
return { count: totalCount, paths: allPaths, hasDiff };
|
|
15436
15556
|
}
|
|
15437
15557
|
|
|
15438
15558
|
// src/utils/result.ts
|
|
@@ -15442,13 +15562,16 @@ function calculateTotalCount(result) {
|
|
|
15442
15562
|
|
|
15443
15563
|
// src/cli/commands/generate.ts
|
|
15444
15564
|
function logFeatureResult(params) {
|
|
15445
|
-
const { count, featureName, isPreview, modePrefix } = params;
|
|
15565
|
+
const { count, paths, featureName, isPreview, modePrefix } = params;
|
|
15446
15566
|
if (count > 0) {
|
|
15447
15567
|
if (isPreview) {
|
|
15448
15568
|
logger.info(`${modePrefix} Would write ${count} ${featureName}`);
|
|
15449
15569
|
} else {
|
|
15450
15570
|
logger.success(`Written ${count} ${featureName}`);
|
|
15451
15571
|
}
|
|
15572
|
+
for (const p of paths) {
|
|
15573
|
+
logger.info(` ${p}`);
|
|
15574
|
+
}
|
|
15452
15575
|
}
|
|
15453
15576
|
}
|
|
15454
15577
|
async function generateCommand(options) {
|
|
@@ -15460,73 +15583,80 @@ async function generateCommand(options) {
|
|
|
15460
15583
|
const check = config.getCheck();
|
|
15461
15584
|
const isPreview = config.isPreviewMode();
|
|
15462
15585
|
const modePrefix = isPreview ? "[DRY RUN]" : "";
|
|
15463
|
-
logger.
|
|
15586
|
+
logger.debug("Generating files...");
|
|
15464
15587
|
if (!await checkRulesyncDirExists({ baseDir: process.cwd() })) {
|
|
15465
15588
|
logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
15466
15589
|
process.exit(1);
|
|
15467
15590
|
}
|
|
15468
|
-
logger.
|
|
15591
|
+
logger.debug(`Base directories: ${config.getBaseDirs().join(", ")}`);
|
|
15469
15592
|
const features = config.getFeatures();
|
|
15470
15593
|
if (features.includes("ignore")) {
|
|
15471
|
-
logger.
|
|
15594
|
+
logger.debug("Generating ignore files...");
|
|
15472
15595
|
}
|
|
15473
15596
|
if (features.includes("mcp")) {
|
|
15474
|
-
logger.
|
|
15597
|
+
logger.debug("Generating MCP files...");
|
|
15475
15598
|
}
|
|
15476
15599
|
if (features.includes("commands")) {
|
|
15477
|
-
logger.
|
|
15600
|
+
logger.debug("Generating command files...");
|
|
15478
15601
|
}
|
|
15479
15602
|
if (features.includes("subagents")) {
|
|
15480
|
-
logger.
|
|
15603
|
+
logger.debug("Generating subagent files...");
|
|
15481
15604
|
}
|
|
15482
15605
|
if (features.includes("skills")) {
|
|
15483
|
-
logger.
|
|
15606
|
+
logger.debug("Generating skill files...");
|
|
15484
15607
|
}
|
|
15485
15608
|
if (features.includes("hooks")) {
|
|
15486
|
-
logger.
|
|
15609
|
+
logger.debug("Generating hooks...");
|
|
15487
15610
|
}
|
|
15488
15611
|
if (features.includes("rules")) {
|
|
15489
|
-
logger.
|
|
15612
|
+
logger.debug("Generating rule files...");
|
|
15490
15613
|
}
|
|
15491
15614
|
const result = await generate({ config });
|
|
15492
15615
|
logFeatureResult({
|
|
15493
15616
|
count: result.ignoreCount,
|
|
15617
|
+
paths: result.ignorePaths,
|
|
15494
15618
|
featureName: "ignore file(s)",
|
|
15495
15619
|
isPreview,
|
|
15496
15620
|
modePrefix
|
|
15497
15621
|
});
|
|
15498
15622
|
logFeatureResult({
|
|
15499
15623
|
count: result.mcpCount,
|
|
15624
|
+
paths: result.mcpPaths,
|
|
15500
15625
|
featureName: "MCP configuration(s)",
|
|
15501
15626
|
isPreview,
|
|
15502
15627
|
modePrefix
|
|
15503
15628
|
});
|
|
15504
15629
|
logFeatureResult({
|
|
15505
15630
|
count: result.commandsCount,
|
|
15631
|
+
paths: result.commandsPaths,
|
|
15506
15632
|
featureName: "command(s)",
|
|
15507
15633
|
isPreview,
|
|
15508
15634
|
modePrefix
|
|
15509
15635
|
});
|
|
15510
15636
|
logFeatureResult({
|
|
15511
15637
|
count: result.subagentsCount,
|
|
15638
|
+
paths: result.subagentsPaths,
|
|
15512
15639
|
featureName: "subagent(s)",
|
|
15513
15640
|
isPreview,
|
|
15514
15641
|
modePrefix
|
|
15515
15642
|
});
|
|
15516
15643
|
logFeatureResult({
|
|
15517
15644
|
count: result.skillsCount,
|
|
15645
|
+
paths: result.skillsPaths,
|
|
15518
15646
|
featureName: "skill(s)",
|
|
15519
15647
|
isPreview,
|
|
15520
15648
|
modePrefix
|
|
15521
15649
|
});
|
|
15522
15650
|
logFeatureResult({
|
|
15523
15651
|
count: result.hooksCount,
|
|
15652
|
+
paths: result.hooksPaths,
|
|
15524
15653
|
featureName: "hooks file(s)",
|
|
15525
15654
|
isPreview,
|
|
15526
15655
|
modePrefix
|
|
15527
15656
|
});
|
|
15528
15657
|
logFeatureResult({
|
|
15529
15658
|
count: result.rulesCount,
|
|
15659
|
+
paths: result.rulesPaths,
|
|
15530
15660
|
featureName: "rule(s)",
|
|
15531
15661
|
isPreview,
|
|
15532
15662
|
modePrefix
|
|
@@ -15561,10 +15691,12 @@ async function generateCommand(options) {
|
|
|
15561
15691
|
}
|
|
15562
15692
|
|
|
15563
15693
|
// src/cli/commands/gitignore.ts
|
|
15564
|
-
var
|
|
15694
|
+
var import_node_path112 = require("path");
|
|
15565
15695
|
var RULESYNC_HEADER = "# Generated by Rulesync";
|
|
15566
15696
|
var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
|
|
15567
15697
|
var RULESYNC_IGNORE_ENTRIES = [
|
|
15698
|
+
// Rulesync curated (fetched) skills
|
|
15699
|
+
".rulesync/skills/.curated/",
|
|
15568
15700
|
// AGENTS.md
|
|
15569
15701
|
"**/AGENTS.md",
|
|
15570
15702
|
"**/.agents/",
|
|
@@ -15709,7 +15841,7 @@ var removeExistingRulesyncEntries = (content) => {
|
|
|
15709
15841
|
return result;
|
|
15710
15842
|
};
|
|
15711
15843
|
var gitignoreCommand = async () => {
|
|
15712
|
-
const gitignorePath = (0,
|
|
15844
|
+
const gitignorePath = (0, import_node_path112.join)(process.cwd(), ".gitignore");
|
|
15713
15845
|
let gitignoreContent = "";
|
|
15714
15846
|
if (await fileExists(gitignorePath)) {
|
|
15715
15847
|
gitignoreContent = await readFileContent(gitignorePath);
|
|
@@ -15781,7 +15913,7 @@ async function importRulesCore(params) {
|
|
|
15781
15913
|
return 0;
|
|
15782
15914
|
}
|
|
15783
15915
|
const rulesyncFiles = await rulesProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15784
|
-
const writtenCount = await rulesProcessor.writeAiFiles(rulesyncFiles);
|
|
15916
|
+
const { count: writtenCount } = await rulesProcessor.writeAiFiles(rulesyncFiles);
|
|
15785
15917
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15786
15918
|
logger.success(`Created ${writtenCount} rule files`);
|
|
15787
15919
|
}
|
|
@@ -15808,7 +15940,7 @@ async function importIgnoreCore(params) {
|
|
|
15808
15940
|
return 0;
|
|
15809
15941
|
}
|
|
15810
15942
|
const rulesyncFiles = await ignoreProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15811
|
-
const writtenCount = await ignoreProcessor.writeAiFiles(rulesyncFiles);
|
|
15943
|
+
const { count: writtenCount } = await ignoreProcessor.writeAiFiles(rulesyncFiles);
|
|
15812
15944
|
if (config.getVerbose()) {
|
|
15813
15945
|
logger.success(`Created ignore files from ${toolFiles.length} tool ignore configurations`);
|
|
15814
15946
|
}
|
|
@@ -15837,7 +15969,7 @@ async function importMcpCore(params) {
|
|
|
15837
15969
|
return 0;
|
|
15838
15970
|
}
|
|
15839
15971
|
const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15840
|
-
const writtenCount = await mcpProcessor.writeAiFiles(rulesyncFiles);
|
|
15972
|
+
const { count: writtenCount } = await mcpProcessor.writeAiFiles(rulesyncFiles);
|
|
15841
15973
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15842
15974
|
logger.success(`Created ${writtenCount} MCP files`);
|
|
15843
15975
|
}
|
|
@@ -15863,7 +15995,7 @@ async function importCommandsCore(params) {
|
|
|
15863
15995
|
return 0;
|
|
15864
15996
|
}
|
|
15865
15997
|
const rulesyncFiles = await commandsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15866
|
-
const writtenCount = await commandsProcessor.writeAiFiles(rulesyncFiles);
|
|
15998
|
+
const { count: writtenCount } = await commandsProcessor.writeAiFiles(rulesyncFiles);
|
|
15867
15999
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15868
16000
|
logger.success(`Created ${writtenCount} command files`);
|
|
15869
16001
|
}
|
|
@@ -15889,7 +16021,7 @@ async function importSubagentsCore(params) {
|
|
|
15889
16021
|
return 0;
|
|
15890
16022
|
}
|
|
15891
16023
|
const rulesyncFiles = await subagentsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15892
|
-
const writtenCount = await subagentsProcessor.writeAiFiles(rulesyncFiles);
|
|
16024
|
+
const { count: writtenCount } = await subagentsProcessor.writeAiFiles(rulesyncFiles);
|
|
15893
16025
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15894
16026
|
logger.success(`Created ${writtenCount} subagent files`);
|
|
15895
16027
|
}
|
|
@@ -15915,7 +16047,7 @@ async function importSkillsCore(params) {
|
|
|
15915
16047
|
return 0;
|
|
15916
16048
|
}
|
|
15917
16049
|
const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
|
|
15918
|
-
const writtenCount = await skillsProcessor.writeAiDirs(rulesyncDirs);
|
|
16050
|
+
const { count: writtenCount } = await skillsProcessor.writeAiDirs(rulesyncDirs);
|
|
15919
16051
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15920
16052
|
logger.success(`Created ${writtenCount} skill directories`);
|
|
15921
16053
|
}
|
|
@@ -15946,7 +16078,7 @@ async function importHooksCore(params) {
|
|
|
15946
16078
|
return 0;
|
|
15947
16079
|
}
|
|
15948
16080
|
const rulesyncFiles = await hooksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
|
|
15949
|
-
const writtenCount = await hooksProcessor.writeAiFiles(rulesyncFiles);
|
|
16081
|
+
const { count: writtenCount } = await hooksProcessor.writeAiFiles(rulesyncFiles);
|
|
15950
16082
|
if (config.getVerbose() && writtenCount > 0) {
|
|
15951
16083
|
logger.success(`Created ${writtenCount} hooks file(s)`);
|
|
15952
16084
|
}
|
|
@@ -15969,7 +16101,7 @@ async function importCommand(options) {
|
|
|
15969
16101
|
silent: config.getSilent()
|
|
15970
16102
|
});
|
|
15971
16103
|
const tool = config.getTargets()[0];
|
|
15972
|
-
logger.
|
|
16104
|
+
logger.debug(`Importing files from ${tool}...`);
|
|
15973
16105
|
const result = await importFromTool({ config, tool });
|
|
15974
16106
|
const totalImported = calculateTotalCount(result);
|
|
15975
16107
|
if (totalImported === 0) {
|
|
@@ -15989,7 +16121,7 @@ async function importCommand(options) {
|
|
|
15989
16121
|
}
|
|
15990
16122
|
|
|
15991
16123
|
// src/lib/init.ts
|
|
15992
|
-
var
|
|
16124
|
+
var import_node_path113 = require("path");
|
|
15993
16125
|
async function init() {
|
|
15994
16126
|
const sampleFiles = await createSampleFiles();
|
|
15995
16127
|
const configFile = await createConfigFile();
|
|
@@ -16179,27 +16311,27 @@ Keep the summary concise and ready to reuse in future tasks.`
|
|
|
16179
16311
|
await ensureDir(subagentPaths.relativeDirPath);
|
|
16180
16312
|
await ensureDir(skillPaths.relativeDirPath);
|
|
16181
16313
|
await ensureDir(ignorePaths.recommended.relativeDirPath);
|
|
16182
|
-
const ruleFilepath = (0,
|
|
16314
|
+
const ruleFilepath = (0, import_node_path113.join)(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
|
|
16183
16315
|
results.push(await writeIfNotExists(ruleFilepath, sampleRuleFile.content));
|
|
16184
|
-
const mcpFilepath = (0,
|
|
16316
|
+
const mcpFilepath = (0, import_node_path113.join)(
|
|
16185
16317
|
mcpPaths.recommended.relativeDirPath,
|
|
16186
16318
|
mcpPaths.recommended.relativeFilePath
|
|
16187
16319
|
);
|
|
16188
16320
|
results.push(await writeIfNotExists(mcpFilepath, sampleMcpFile.content));
|
|
16189
|
-
const commandFilepath = (0,
|
|
16321
|
+
const commandFilepath = (0, import_node_path113.join)(commandPaths.relativeDirPath, sampleCommandFile.filename);
|
|
16190
16322
|
results.push(await writeIfNotExists(commandFilepath, sampleCommandFile.content));
|
|
16191
|
-
const subagentFilepath = (0,
|
|
16323
|
+
const subagentFilepath = (0, import_node_path113.join)(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
|
|
16192
16324
|
results.push(await writeIfNotExists(subagentFilepath, sampleSubagentFile.content));
|
|
16193
|
-
const skillDirPath = (0,
|
|
16325
|
+
const skillDirPath = (0, import_node_path113.join)(skillPaths.relativeDirPath, sampleSkillFile.dirName);
|
|
16194
16326
|
await ensureDir(skillDirPath);
|
|
16195
|
-
const skillFilepath = (0,
|
|
16327
|
+
const skillFilepath = (0, import_node_path113.join)(skillDirPath, SKILL_FILE_NAME);
|
|
16196
16328
|
results.push(await writeIfNotExists(skillFilepath, sampleSkillFile.content));
|
|
16197
|
-
const ignoreFilepath = (0,
|
|
16329
|
+
const ignoreFilepath = (0, import_node_path113.join)(
|
|
16198
16330
|
ignorePaths.recommended.relativeDirPath,
|
|
16199
16331
|
ignorePaths.recommended.relativeFilePath
|
|
16200
16332
|
);
|
|
16201
16333
|
results.push(await writeIfNotExists(ignoreFilepath, sampleIgnoreFile.content));
|
|
16202
|
-
const hooksFilepath = (0,
|
|
16334
|
+
const hooksFilepath = (0, import_node_path113.join)(hooksPaths.relativeDirPath, hooksPaths.relativeFilePath);
|
|
16203
16335
|
results.push(await writeIfNotExists(hooksFilepath, sampleHooksFile.content));
|
|
16204
16336
|
return results;
|
|
16205
16337
|
}
|
|
@@ -16213,7 +16345,7 @@ async function writeIfNotExists(path4, content) {
|
|
|
16213
16345
|
|
|
16214
16346
|
// src/cli/commands/init.ts
|
|
16215
16347
|
async function initCommand() {
|
|
16216
|
-
logger.
|
|
16348
|
+
logger.debug("Initializing rulesync...");
|
|
16217
16349
|
await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
|
|
16218
16350
|
const result = await init();
|
|
16219
16351
|
for (const file of result.sampleFiles) {
|
|
@@ -16236,19 +16368,447 @@ async function initCommand() {
|
|
|
16236
16368
|
logger.info("2. Run 'rulesync generate' to create configuration files");
|
|
16237
16369
|
}
|
|
16238
16370
|
|
|
16371
|
+
// src/lib/sources.ts
|
|
16372
|
+
var import_promise2 = require("es-toolkit/promise");
|
|
16373
|
+
var import_node_path115 = require("path");
|
|
16374
|
+
|
|
16375
|
+
// src/lib/sources-lock.ts
|
|
16376
|
+
var import_node_crypto = require("crypto");
|
|
16377
|
+
var import_node_path114 = require("path");
|
|
16378
|
+
var import_mini53 = require("zod/mini");
|
|
16379
|
+
var LOCKFILE_VERSION = 1;
|
|
16380
|
+
var LockedSkillSchema = import_mini53.z.object({
|
|
16381
|
+
integrity: import_mini53.z.string()
|
|
16382
|
+
});
|
|
16383
|
+
var LockedSourceSchema = import_mini53.z.object({
|
|
16384
|
+
requestedRef: (0, import_mini53.optional)(import_mini53.z.string()),
|
|
16385
|
+
resolvedRef: import_mini53.z.string(),
|
|
16386
|
+
resolvedAt: (0, import_mini53.optional)(import_mini53.z.string()),
|
|
16387
|
+
skills: import_mini53.z.record(import_mini53.z.string(), LockedSkillSchema)
|
|
16388
|
+
});
|
|
16389
|
+
var SourcesLockSchema = import_mini53.z.object({
|
|
16390
|
+
lockfileVersion: import_mini53.z.number(),
|
|
16391
|
+
sources: import_mini53.z.record(import_mini53.z.string(), LockedSourceSchema)
|
|
16392
|
+
});
|
|
16393
|
+
var LegacyLockedSourceSchema = import_mini53.z.object({
|
|
16394
|
+
resolvedRef: import_mini53.z.string(),
|
|
16395
|
+
skills: import_mini53.z.array(import_mini53.z.string())
|
|
16396
|
+
});
|
|
16397
|
+
var LegacySourcesLockSchema = import_mini53.z.object({
|
|
16398
|
+
sources: import_mini53.z.record(import_mini53.z.string(), LegacyLockedSourceSchema)
|
|
16399
|
+
});
|
|
16400
|
+
function migrateLegacyLock(legacy) {
|
|
16401
|
+
const sources = {};
|
|
16402
|
+
for (const [key, entry] of Object.entries(legacy.sources)) {
|
|
16403
|
+
const skills = {};
|
|
16404
|
+
for (const name of entry.skills) {
|
|
16405
|
+
skills[name] = { integrity: "" };
|
|
16406
|
+
}
|
|
16407
|
+
sources[key] = {
|
|
16408
|
+
resolvedRef: entry.resolvedRef,
|
|
16409
|
+
skills
|
|
16410
|
+
};
|
|
16411
|
+
}
|
|
16412
|
+
logger.info(
|
|
16413
|
+
"Migrated legacy sources lockfile to version 1. Run 'rulesync install --update' to populate integrity hashes."
|
|
16414
|
+
);
|
|
16415
|
+
return { lockfileVersion: LOCKFILE_VERSION, sources };
|
|
16416
|
+
}
|
|
16417
|
+
function createEmptyLock() {
|
|
16418
|
+
return { lockfileVersion: LOCKFILE_VERSION, sources: {} };
|
|
16419
|
+
}
|
|
16420
|
+
async function readLockFile(params) {
|
|
16421
|
+
const lockPath = (0, import_node_path114.join)(params.baseDir, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
16422
|
+
if (!await fileExists(lockPath)) {
|
|
16423
|
+
logger.debug("No sources lockfile found, starting fresh.");
|
|
16424
|
+
return createEmptyLock();
|
|
16425
|
+
}
|
|
16426
|
+
try {
|
|
16427
|
+
const content = await readFileContent(lockPath);
|
|
16428
|
+
const data = JSON.parse(content);
|
|
16429
|
+
const result = SourcesLockSchema.safeParse(data);
|
|
16430
|
+
if (result.success) {
|
|
16431
|
+
return result.data;
|
|
16432
|
+
}
|
|
16433
|
+
const legacyResult = LegacySourcesLockSchema.safeParse(data);
|
|
16434
|
+
if (legacyResult.success) {
|
|
16435
|
+
return migrateLegacyLock(legacyResult.data);
|
|
16436
|
+
}
|
|
16437
|
+
logger.warn(
|
|
16438
|
+
`Invalid sources lockfile format (${RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH}). Starting fresh.`
|
|
16439
|
+
);
|
|
16440
|
+
return createEmptyLock();
|
|
16441
|
+
} catch {
|
|
16442
|
+
logger.warn(
|
|
16443
|
+
`Failed to read sources lockfile (${RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH}). Starting fresh.`
|
|
16444
|
+
);
|
|
16445
|
+
return createEmptyLock();
|
|
16446
|
+
}
|
|
16447
|
+
}
|
|
16448
|
+
async function writeLockFile(params) {
|
|
16449
|
+
const lockPath = (0, import_node_path114.join)(params.baseDir, RULESYNC_SOURCES_LOCK_RELATIVE_FILE_PATH);
|
|
16450
|
+
const content = JSON.stringify(params.lock, null, 2) + "\n";
|
|
16451
|
+
await writeFileContent(lockPath, content);
|
|
16452
|
+
logger.debug(`Wrote sources lockfile to ${lockPath}`);
|
|
16453
|
+
}
|
|
16454
|
+
function computeSkillIntegrity(files) {
|
|
16455
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
16456
|
+
const sorted = files.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
16457
|
+
for (const file of sorted) {
|
|
16458
|
+
hash.update(file.path);
|
|
16459
|
+
hash.update("\0");
|
|
16460
|
+
hash.update(file.content);
|
|
16461
|
+
hash.update("\0");
|
|
16462
|
+
}
|
|
16463
|
+
return `sha256-${hash.digest("hex")}`;
|
|
16464
|
+
}
|
|
16465
|
+
function normalizeSourceKey(source) {
|
|
16466
|
+
let key = source;
|
|
16467
|
+
for (const prefix of [
|
|
16468
|
+
"https://www.github.com/",
|
|
16469
|
+
"https://github.com/",
|
|
16470
|
+
"http://www.github.com/",
|
|
16471
|
+
"http://github.com/"
|
|
16472
|
+
]) {
|
|
16473
|
+
if (key.toLowerCase().startsWith(prefix)) {
|
|
16474
|
+
key = key.substring(prefix.length);
|
|
16475
|
+
break;
|
|
16476
|
+
}
|
|
16477
|
+
}
|
|
16478
|
+
if (key.startsWith("github:")) {
|
|
16479
|
+
key = key.substring("github:".length);
|
|
16480
|
+
}
|
|
16481
|
+
key = key.replace(/\/+$/, "");
|
|
16482
|
+
key = key.replace(/\.git$/, "");
|
|
16483
|
+
key = key.toLowerCase();
|
|
16484
|
+
return key;
|
|
16485
|
+
}
|
|
16486
|
+
function getLockedSource(lock, sourceKey) {
|
|
16487
|
+
const normalized = normalizeSourceKey(sourceKey);
|
|
16488
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16489
|
+
if (normalizeSourceKey(key) === normalized) {
|
|
16490
|
+
return value;
|
|
16491
|
+
}
|
|
16492
|
+
}
|
|
16493
|
+
return void 0;
|
|
16494
|
+
}
|
|
16495
|
+
function setLockedSource(lock, sourceKey, entry) {
|
|
16496
|
+
const normalized = normalizeSourceKey(sourceKey);
|
|
16497
|
+
const filteredSources = {};
|
|
16498
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16499
|
+
if (normalizeSourceKey(key) !== normalized) {
|
|
16500
|
+
filteredSources[key] = value;
|
|
16501
|
+
}
|
|
16502
|
+
}
|
|
16503
|
+
return {
|
|
16504
|
+
lockfileVersion: lock.lockfileVersion,
|
|
16505
|
+
sources: {
|
|
16506
|
+
...filteredSources,
|
|
16507
|
+
[normalized]: entry
|
|
16508
|
+
}
|
|
16509
|
+
};
|
|
16510
|
+
}
|
|
16511
|
+
function getLockedSkillNames(entry) {
|
|
16512
|
+
return Object.keys(entry.skills);
|
|
16513
|
+
}
|
|
16514
|
+
|
|
16515
|
+
// src/lib/sources.ts
|
|
16516
|
+
async function resolveAndFetchSources(params) {
|
|
16517
|
+
const { sources, baseDir, options = {} } = params;
|
|
16518
|
+
if (sources.length === 0) {
|
|
16519
|
+
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
16520
|
+
}
|
|
16521
|
+
if (options.skipSources) {
|
|
16522
|
+
logger.info("Skipping source fetching.");
|
|
16523
|
+
return { fetchedSkillCount: 0, sourcesProcessed: 0 };
|
|
16524
|
+
}
|
|
16525
|
+
let lock = options.updateSources ? createEmptyLock() : await readLockFile({ baseDir });
|
|
16526
|
+
if (options.frozen) {
|
|
16527
|
+
const missingKeys = [];
|
|
16528
|
+
const missingSkills = [];
|
|
16529
|
+
const curatedDir = (0, import_node_path115.join)(baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
16530
|
+
for (const source of sources) {
|
|
16531
|
+
const locked = getLockedSource(lock, source.source);
|
|
16532
|
+
if (!locked) {
|
|
16533
|
+
missingKeys.push(source.source);
|
|
16534
|
+
continue;
|
|
16535
|
+
}
|
|
16536
|
+
const skillNames = getLockedSkillNames(locked);
|
|
16537
|
+
for (const skillName of skillNames) {
|
|
16538
|
+
if (!await directoryExists((0, import_node_path115.join)(curatedDir, skillName))) {
|
|
16539
|
+
missingSkills.push(`${source.source}:${skillName}`);
|
|
16540
|
+
}
|
|
16541
|
+
}
|
|
16542
|
+
}
|
|
16543
|
+
if (missingKeys.length > 0) {
|
|
16544
|
+
throw new Error(
|
|
16545
|
+
`Frozen install failed: lockfile is missing entries for: ${missingKeys.join(", ")}. Run 'rulesync install' to update the lockfile.`
|
|
16546
|
+
);
|
|
16547
|
+
}
|
|
16548
|
+
if (missingSkills.length > 0) {
|
|
16549
|
+
throw new Error(
|
|
16550
|
+
`Frozen install failed: locked skills missing from disk: ${missingSkills.join(", ")}. Run 'rulesync install' to fetch missing skills.`
|
|
16551
|
+
);
|
|
16552
|
+
}
|
|
16553
|
+
}
|
|
16554
|
+
const originalLockJson = JSON.stringify(lock);
|
|
16555
|
+
const token = GitHubClient.resolveToken(options.token);
|
|
16556
|
+
const client = new GitHubClient({ token });
|
|
16557
|
+
const localSkillNames = await getLocalSkillDirNames(baseDir);
|
|
16558
|
+
let totalSkillCount = 0;
|
|
16559
|
+
const allFetchedSkillNames = /* @__PURE__ */ new Set();
|
|
16560
|
+
for (const sourceEntry of sources) {
|
|
16561
|
+
try {
|
|
16562
|
+
const { skillCount, fetchedSkillNames, updatedLock } = await fetchSource({
|
|
16563
|
+
sourceEntry,
|
|
16564
|
+
client,
|
|
16565
|
+
baseDir,
|
|
16566
|
+
lock,
|
|
16567
|
+
localSkillNames,
|
|
16568
|
+
alreadyFetchedSkillNames: allFetchedSkillNames,
|
|
16569
|
+
updateSources: options.updateSources ?? false
|
|
16570
|
+
});
|
|
16571
|
+
lock = updatedLock;
|
|
16572
|
+
totalSkillCount += skillCount;
|
|
16573
|
+
for (const name of fetchedSkillNames) {
|
|
16574
|
+
allFetchedSkillNames.add(name);
|
|
16575
|
+
}
|
|
16576
|
+
} catch (error) {
|
|
16577
|
+
if (error instanceof GitHubClientError) {
|
|
16578
|
+
logGitHubAuthHints(error);
|
|
16579
|
+
} else {
|
|
16580
|
+
logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
|
|
16581
|
+
}
|
|
16582
|
+
}
|
|
16583
|
+
}
|
|
16584
|
+
const sourceKeys = new Set(sources.map((s) => normalizeSourceKey(s.source)));
|
|
16585
|
+
const prunedSources = {};
|
|
16586
|
+
for (const [key, value] of Object.entries(lock.sources)) {
|
|
16587
|
+
if (sourceKeys.has(normalizeSourceKey(key))) {
|
|
16588
|
+
prunedSources[key] = value;
|
|
16589
|
+
} else {
|
|
16590
|
+
logger.debug(`Pruned stale lockfile entry: ${key}`);
|
|
16591
|
+
}
|
|
16592
|
+
}
|
|
16593
|
+
lock = { lockfileVersion: lock.lockfileVersion, sources: prunedSources };
|
|
16594
|
+
if (!options.frozen && JSON.stringify(lock) !== originalLockJson) {
|
|
16595
|
+
await writeLockFile({ baseDir, lock });
|
|
16596
|
+
} else {
|
|
16597
|
+
logger.debug("Lockfile unchanged, skipping write.");
|
|
16598
|
+
}
|
|
16599
|
+
return { fetchedSkillCount: totalSkillCount, sourcesProcessed: sources.length };
|
|
16600
|
+
}
|
|
16601
|
+
async function checkLockedSkillsExist(curatedDir, skillNames) {
|
|
16602
|
+
if (skillNames.length === 0) return true;
|
|
16603
|
+
for (const name of skillNames) {
|
|
16604
|
+
if (!await directoryExists((0, import_node_path115.join)(curatedDir, name))) {
|
|
16605
|
+
return false;
|
|
16606
|
+
}
|
|
16607
|
+
}
|
|
16608
|
+
return true;
|
|
16609
|
+
}
|
|
16610
|
+
async function fetchSource(params) {
|
|
16611
|
+
const { sourceEntry, client, baseDir, localSkillNames, alreadyFetchedSkillNames, updateSources } = params;
|
|
16612
|
+
let { lock } = params;
|
|
16613
|
+
const parsed = parseSource(sourceEntry.source);
|
|
16614
|
+
if (parsed.provider === "gitlab") {
|
|
16615
|
+
throw new Error("GitLab sources are not yet supported.");
|
|
16616
|
+
}
|
|
16617
|
+
const sourceKey = sourceEntry.source;
|
|
16618
|
+
const locked = getLockedSource(lock, sourceKey);
|
|
16619
|
+
const lockedSkillNames = locked ? getLockedSkillNames(locked) : [];
|
|
16620
|
+
let ref;
|
|
16621
|
+
let resolvedSha;
|
|
16622
|
+
let requestedRef;
|
|
16623
|
+
if (locked && !updateSources) {
|
|
16624
|
+
ref = locked.resolvedRef;
|
|
16625
|
+
resolvedSha = locked.resolvedRef;
|
|
16626
|
+
requestedRef = locked.requestedRef;
|
|
16627
|
+
logger.debug(`Using locked ref for ${sourceKey}: ${resolvedSha}`);
|
|
16628
|
+
} else {
|
|
16629
|
+
requestedRef = parsed.ref ?? await client.getDefaultBranch(parsed.owner, parsed.repo);
|
|
16630
|
+
resolvedSha = await client.resolveRefToSha(parsed.owner, parsed.repo, requestedRef);
|
|
16631
|
+
ref = resolvedSha;
|
|
16632
|
+
logger.debug(`Resolved ${sourceKey} ref "${requestedRef}" to SHA: ${resolvedSha}`);
|
|
16633
|
+
}
|
|
16634
|
+
const curatedDir = (0, import_node_path115.join)(baseDir, RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH);
|
|
16635
|
+
if (locked && resolvedSha === locked.resolvedRef && !updateSources) {
|
|
16636
|
+
const allExist = await checkLockedSkillsExist(curatedDir, lockedSkillNames);
|
|
16637
|
+
if (allExist) {
|
|
16638
|
+
logger.debug(`SHA unchanged for ${sourceKey}, skipping re-fetch.`);
|
|
16639
|
+
return {
|
|
16640
|
+
skillCount: 0,
|
|
16641
|
+
fetchedSkillNames: lockedSkillNames,
|
|
16642
|
+
updatedLock: lock
|
|
16643
|
+
};
|
|
16644
|
+
}
|
|
16645
|
+
}
|
|
16646
|
+
const skillFilter = sourceEntry.skills ?? ["*"];
|
|
16647
|
+
const isWildcard = skillFilter.length === 1 && skillFilter[0] === "*";
|
|
16648
|
+
const skillsBasePath = parsed.path ?? "skills";
|
|
16649
|
+
let remoteSkillDirs;
|
|
16650
|
+
try {
|
|
16651
|
+
const entries = await client.listDirectory(parsed.owner, parsed.repo, skillsBasePath, ref);
|
|
16652
|
+
remoteSkillDirs = entries.filter((e) => e.type === "dir").map((e) => ({ name: e.name, path: e.path }));
|
|
16653
|
+
} catch (error) {
|
|
16654
|
+
if (error instanceof GitHubClientError && error.statusCode === 404) {
|
|
16655
|
+
logger.warn(`No skills/ directory found in ${sourceKey}. Skipping.`);
|
|
16656
|
+
return { skillCount: 0, fetchedSkillNames: [], updatedLock: lock };
|
|
16657
|
+
}
|
|
16658
|
+
throw error;
|
|
16659
|
+
}
|
|
16660
|
+
const filteredDirs = isWildcard ? remoteSkillDirs : remoteSkillDirs.filter((d) => skillFilter.includes(d.name));
|
|
16661
|
+
const semaphore = new import_promise2.Semaphore(FETCH_CONCURRENCY_LIMIT);
|
|
16662
|
+
const fetchedSkills = {};
|
|
16663
|
+
if (locked) {
|
|
16664
|
+
const resolvedCuratedDir = (0, import_node_path115.resolve)(curatedDir);
|
|
16665
|
+
for (const prevSkill of lockedSkillNames) {
|
|
16666
|
+
const prevDir = (0, import_node_path115.join)(curatedDir, prevSkill);
|
|
16667
|
+
if (!(0, import_node_path115.resolve)(prevDir).startsWith(resolvedCuratedDir + import_node_path115.sep)) {
|
|
16668
|
+
logger.warn(
|
|
16669
|
+
`Skipping removal of "${prevSkill}": resolved path is outside the curated directory.`
|
|
16670
|
+
);
|
|
16671
|
+
continue;
|
|
16672
|
+
}
|
|
16673
|
+
if (await directoryExists(prevDir)) {
|
|
16674
|
+
await removeDirectory(prevDir);
|
|
16675
|
+
}
|
|
16676
|
+
}
|
|
16677
|
+
}
|
|
16678
|
+
for (const skillDir of filteredDirs) {
|
|
16679
|
+
if (skillDir.name.includes("..") || skillDir.name.includes("/") || skillDir.name.includes("\\")) {
|
|
16680
|
+
logger.warn(
|
|
16681
|
+
`Skipping skill with invalid name "${skillDir.name}" from ${sourceKey}: contains path traversal characters.`
|
|
16682
|
+
);
|
|
16683
|
+
continue;
|
|
16684
|
+
}
|
|
16685
|
+
if (localSkillNames.has(skillDir.name)) {
|
|
16686
|
+
logger.debug(
|
|
16687
|
+
`Skipping remote skill "${skillDir.name}" from ${sourceKey}: local skill takes precedence.`
|
|
16688
|
+
);
|
|
16689
|
+
continue;
|
|
16690
|
+
}
|
|
16691
|
+
if (alreadyFetchedSkillNames.has(skillDir.name)) {
|
|
16692
|
+
logger.warn(
|
|
16693
|
+
`Skipping duplicate skill "${skillDir.name}" from ${sourceKey}: already fetched from another source.`
|
|
16694
|
+
);
|
|
16695
|
+
continue;
|
|
16696
|
+
}
|
|
16697
|
+
const allFiles = await listDirectoryRecursive({
|
|
16698
|
+
client,
|
|
16699
|
+
owner: parsed.owner,
|
|
16700
|
+
repo: parsed.repo,
|
|
16701
|
+
path: skillDir.path,
|
|
16702
|
+
ref,
|
|
16703
|
+
semaphore
|
|
16704
|
+
});
|
|
16705
|
+
const files = allFiles.filter((file) => {
|
|
16706
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
16707
|
+
logger.warn(
|
|
16708
|
+
`Skipping file "${file.path}" (${(file.size / 1024 / 1024).toFixed(2)}MB exceeds ${MAX_FILE_SIZE / 1024 / 1024}MB limit).`
|
|
16709
|
+
);
|
|
16710
|
+
return false;
|
|
16711
|
+
}
|
|
16712
|
+
return true;
|
|
16713
|
+
});
|
|
16714
|
+
const skillFiles = [];
|
|
16715
|
+
for (const file of files) {
|
|
16716
|
+
const relativeToSkill = file.path.substring(skillDir.path.length + 1);
|
|
16717
|
+
const localFilePath = (0, import_node_path115.join)(curatedDir, skillDir.name, relativeToSkill);
|
|
16718
|
+
checkPathTraversal({
|
|
16719
|
+
relativePath: relativeToSkill,
|
|
16720
|
+
intendedRootDir: (0, import_node_path115.join)(curatedDir, skillDir.name)
|
|
16721
|
+
});
|
|
16722
|
+
const content = await withSemaphore(
|
|
16723
|
+
semaphore,
|
|
16724
|
+
() => client.getFileContent(parsed.owner, parsed.repo, file.path, ref)
|
|
16725
|
+
);
|
|
16726
|
+
await writeFileContent(localFilePath, content);
|
|
16727
|
+
skillFiles.push({ path: relativeToSkill, content });
|
|
16728
|
+
}
|
|
16729
|
+
const integrity = computeSkillIntegrity(skillFiles);
|
|
16730
|
+
const lockedSkillEntry = locked?.skills[skillDir.name];
|
|
16731
|
+
if (lockedSkillEntry && lockedSkillEntry.integrity && lockedSkillEntry.integrity !== integrity && resolvedSha === locked?.resolvedRef) {
|
|
16732
|
+
logger.warn(
|
|
16733
|
+
`Integrity mismatch for skill "${skillDir.name}" from ${sourceKey}: expected "${lockedSkillEntry.integrity}", got "${integrity}". Content may have been tampered with.`
|
|
16734
|
+
);
|
|
16735
|
+
}
|
|
16736
|
+
fetchedSkills[skillDir.name] = { integrity };
|
|
16737
|
+
logger.debug(`Fetched skill "${skillDir.name}" from ${sourceKey}`);
|
|
16738
|
+
}
|
|
16739
|
+
const fetchedNames = Object.keys(fetchedSkills);
|
|
16740
|
+
const mergedSkills = { ...fetchedSkills };
|
|
16741
|
+
if (locked) {
|
|
16742
|
+
for (const [skillName, skillEntry] of Object.entries(locked.skills)) {
|
|
16743
|
+
if (!(skillName in mergedSkills)) {
|
|
16744
|
+
mergedSkills[skillName] = skillEntry;
|
|
16745
|
+
}
|
|
16746
|
+
}
|
|
16747
|
+
}
|
|
16748
|
+
lock = setLockedSource(lock, sourceKey, {
|
|
16749
|
+
requestedRef,
|
|
16750
|
+
resolvedRef: resolvedSha,
|
|
16751
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16752
|
+
skills: mergedSkills
|
|
16753
|
+
});
|
|
16754
|
+
logger.info(
|
|
16755
|
+
`Fetched ${fetchedNames.length} skill(s) from ${sourceKey}: ${fetchedNames.join(", ") || "(none)"}`
|
|
16756
|
+
);
|
|
16757
|
+
return {
|
|
16758
|
+
skillCount: fetchedNames.length,
|
|
16759
|
+
fetchedSkillNames: fetchedNames,
|
|
16760
|
+
updatedLock: lock
|
|
16761
|
+
};
|
|
16762
|
+
}
|
|
16763
|
+
|
|
16764
|
+
// src/cli/commands/install.ts
|
|
16765
|
+
async function installCommand(options) {
|
|
16766
|
+
logger.configure({
|
|
16767
|
+
verbose: options.verbose ?? false,
|
|
16768
|
+
silent: options.silent ?? false
|
|
16769
|
+
});
|
|
16770
|
+
const config = await ConfigResolver.resolve({
|
|
16771
|
+
configPath: options.configPath,
|
|
16772
|
+
verbose: options.verbose,
|
|
16773
|
+
silent: options.silent
|
|
16774
|
+
});
|
|
16775
|
+
const sources = config.getSources();
|
|
16776
|
+
if (sources.length === 0) {
|
|
16777
|
+
logger.warn("No sources defined in configuration. Nothing to install.");
|
|
16778
|
+
return;
|
|
16779
|
+
}
|
|
16780
|
+
logger.debug(`Installing skills from ${sources.length} source(s)...`);
|
|
16781
|
+
const result = await resolveAndFetchSources({
|
|
16782
|
+
sources,
|
|
16783
|
+
baseDir: process.cwd(),
|
|
16784
|
+
options: {
|
|
16785
|
+
updateSources: options.update,
|
|
16786
|
+
frozen: options.frozen,
|
|
16787
|
+
token: options.token
|
|
16788
|
+
}
|
|
16789
|
+
});
|
|
16790
|
+
if (result.fetchedSkillCount > 0) {
|
|
16791
|
+
logger.success(
|
|
16792
|
+
`Installed ${result.fetchedSkillCount} skill(s) from ${result.sourcesProcessed} source(s).`
|
|
16793
|
+
);
|
|
16794
|
+
} else {
|
|
16795
|
+
logger.success(`All skills up to date (${result.sourcesProcessed} source(s) checked).`);
|
|
16796
|
+
}
|
|
16797
|
+
}
|
|
16798
|
+
|
|
16239
16799
|
// src/cli/commands/mcp.ts
|
|
16240
16800
|
var import_fastmcp = require("fastmcp");
|
|
16241
16801
|
|
|
16242
16802
|
// src/mcp/tools.ts
|
|
16243
|
-
var
|
|
16803
|
+
var import_mini62 = require("zod/mini");
|
|
16244
16804
|
|
|
16245
16805
|
// src/mcp/commands.ts
|
|
16246
|
-
var
|
|
16247
|
-
var
|
|
16806
|
+
var import_node_path116 = require("path");
|
|
16807
|
+
var import_mini54 = require("zod/mini");
|
|
16248
16808
|
var maxCommandSizeBytes = 1024 * 1024;
|
|
16249
16809
|
var maxCommandsCount = 1e3;
|
|
16250
16810
|
async function listCommands() {
|
|
16251
|
-
const commandsDir = (0,
|
|
16811
|
+
const commandsDir = (0, import_node_path116.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
16252
16812
|
try {
|
|
16253
16813
|
const files = await listDirectoryFiles(commandsDir);
|
|
16254
16814
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -16260,7 +16820,7 @@ async function listCommands() {
|
|
|
16260
16820
|
});
|
|
16261
16821
|
const frontmatter = command.getFrontmatter();
|
|
16262
16822
|
return {
|
|
16263
|
-
relativePathFromCwd: (0,
|
|
16823
|
+
relativePathFromCwd: (0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
|
|
16264
16824
|
frontmatter
|
|
16265
16825
|
};
|
|
16266
16826
|
} catch (error) {
|
|
@@ -16271,7 +16831,9 @@ async function listCommands() {
|
|
|
16271
16831
|
);
|
|
16272
16832
|
return commands.filter((command) => command !== null);
|
|
16273
16833
|
} catch (error) {
|
|
16274
|
-
logger.error(
|
|
16834
|
+
logger.error(
|
|
16835
|
+
`Failed to read commands directory (${RULESYNC_COMMANDS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
16836
|
+
);
|
|
16275
16837
|
return [];
|
|
16276
16838
|
}
|
|
16277
16839
|
}
|
|
@@ -16280,13 +16842,13 @@ async function getCommand({ relativePathFromCwd }) {
|
|
|
16280
16842
|
relativePath: relativePathFromCwd,
|
|
16281
16843
|
intendedRootDir: process.cwd()
|
|
16282
16844
|
});
|
|
16283
|
-
const filename = (0,
|
|
16845
|
+
const filename = (0, import_node_path116.basename)(relativePathFromCwd);
|
|
16284
16846
|
try {
|
|
16285
16847
|
const command = await RulesyncCommand.fromFile({
|
|
16286
16848
|
relativeFilePath: filename
|
|
16287
16849
|
});
|
|
16288
16850
|
return {
|
|
16289
|
-
relativePathFromCwd: (0,
|
|
16851
|
+
relativePathFromCwd: (0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
16290
16852
|
frontmatter: command.getFrontmatter(),
|
|
16291
16853
|
body: command.getBody()
|
|
16292
16854
|
};
|
|
@@ -16305,20 +16867,22 @@ async function putCommand({
|
|
|
16305
16867
|
relativePath: relativePathFromCwd,
|
|
16306
16868
|
intendedRootDir: process.cwd()
|
|
16307
16869
|
});
|
|
16308
|
-
const filename = (0,
|
|
16870
|
+
const filename = (0, import_node_path116.basename)(relativePathFromCwd);
|
|
16309
16871
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
16310
16872
|
if (estimatedSize > maxCommandSizeBytes) {
|
|
16311
16873
|
throw new Error(
|
|
16312
|
-
`Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB)`
|
|
16874
|
+
`Command size ${estimatedSize} bytes exceeds maximum ${maxCommandSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
16313
16875
|
);
|
|
16314
16876
|
}
|
|
16315
16877
|
try {
|
|
16316
16878
|
const existingCommands = await listCommands();
|
|
16317
16879
|
const isUpdate = existingCommands.some(
|
|
16318
|
-
(command2) => command2.relativePathFromCwd === (0,
|
|
16880
|
+
(command2) => command2.relativePathFromCwd === (0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
16319
16881
|
);
|
|
16320
16882
|
if (!isUpdate && existingCommands.length >= maxCommandsCount) {
|
|
16321
|
-
throw new Error(
|
|
16883
|
+
throw new Error(
|
|
16884
|
+
`Maximum number of commands (${maxCommandsCount}) reached in ${RULESYNC_COMMANDS_RELATIVE_DIR_PATH}`
|
|
16885
|
+
);
|
|
16322
16886
|
}
|
|
16323
16887
|
const fileContent = stringifyFrontmatter(body, frontmatter);
|
|
16324
16888
|
const command = new RulesyncCommand({
|
|
@@ -16330,11 +16894,11 @@ async function putCommand({
|
|
|
16330
16894
|
fileContent,
|
|
16331
16895
|
validate: true
|
|
16332
16896
|
});
|
|
16333
|
-
const commandsDir = (0,
|
|
16897
|
+
const commandsDir = (0, import_node_path116.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
|
|
16334
16898
|
await ensureDir(commandsDir);
|
|
16335
16899
|
await writeFileContent(command.getFilePath(), command.getFileContent());
|
|
16336
16900
|
return {
|
|
16337
|
-
relativePathFromCwd: (0,
|
|
16901
|
+
relativePathFromCwd: (0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
|
|
16338
16902
|
frontmatter: command.getFrontmatter(),
|
|
16339
16903
|
body: command.getBody()
|
|
16340
16904
|
};
|
|
@@ -16349,12 +16913,12 @@ async function deleteCommand({ relativePathFromCwd }) {
|
|
|
16349
16913
|
relativePath: relativePathFromCwd,
|
|
16350
16914
|
intendedRootDir: process.cwd()
|
|
16351
16915
|
});
|
|
16352
|
-
const filename = (0,
|
|
16353
|
-
const fullPath = (0,
|
|
16916
|
+
const filename = (0, import_node_path116.basename)(relativePathFromCwd);
|
|
16917
|
+
const fullPath = (0, import_node_path116.join)(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
|
|
16354
16918
|
try {
|
|
16355
16919
|
await removeFile(fullPath);
|
|
16356
16920
|
return {
|
|
16357
|
-
relativePathFromCwd: (0,
|
|
16921
|
+
relativePathFromCwd: (0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
|
|
16358
16922
|
};
|
|
16359
16923
|
} catch (error) {
|
|
16360
16924
|
throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -16363,23 +16927,23 @@ async function deleteCommand({ relativePathFromCwd }) {
|
|
|
16363
16927
|
}
|
|
16364
16928
|
}
|
|
16365
16929
|
var commandToolSchemas = {
|
|
16366
|
-
listCommands:
|
|
16367
|
-
getCommand:
|
|
16368
|
-
relativePathFromCwd:
|
|
16930
|
+
listCommands: import_mini54.z.object({}),
|
|
16931
|
+
getCommand: import_mini54.z.object({
|
|
16932
|
+
relativePathFromCwd: import_mini54.z.string()
|
|
16369
16933
|
}),
|
|
16370
|
-
putCommand:
|
|
16371
|
-
relativePathFromCwd:
|
|
16934
|
+
putCommand: import_mini54.z.object({
|
|
16935
|
+
relativePathFromCwd: import_mini54.z.string(),
|
|
16372
16936
|
frontmatter: RulesyncCommandFrontmatterSchema,
|
|
16373
|
-
body:
|
|
16937
|
+
body: import_mini54.z.string()
|
|
16374
16938
|
}),
|
|
16375
|
-
deleteCommand:
|
|
16376
|
-
relativePathFromCwd:
|
|
16939
|
+
deleteCommand: import_mini54.z.object({
|
|
16940
|
+
relativePathFromCwd: import_mini54.z.string()
|
|
16377
16941
|
})
|
|
16378
16942
|
};
|
|
16379
16943
|
var commandTools = {
|
|
16380
16944
|
listCommands: {
|
|
16381
16945
|
name: "listCommands",
|
|
16382
|
-
description: `List all commands from ${(0,
|
|
16946
|
+
description: `List all commands from ${(0, import_node_path116.join)(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
16383
16947
|
parameters: commandToolSchemas.listCommands,
|
|
16384
16948
|
execute: async () => {
|
|
16385
16949
|
const commands = await listCommands();
|
|
@@ -16421,15 +16985,15 @@ var commandTools = {
|
|
|
16421
16985
|
};
|
|
16422
16986
|
|
|
16423
16987
|
// src/mcp/generate.ts
|
|
16424
|
-
var
|
|
16425
|
-
var generateOptionsSchema =
|
|
16426
|
-
targets:
|
|
16427
|
-
features:
|
|
16428
|
-
delete:
|
|
16429
|
-
global:
|
|
16430
|
-
simulateCommands:
|
|
16431
|
-
simulateSubagents:
|
|
16432
|
-
simulateSkills:
|
|
16988
|
+
var import_mini55 = require("zod/mini");
|
|
16989
|
+
var generateOptionsSchema = import_mini55.z.object({
|
|
16990
|
+
targets: import_mini55.z.optional(import_mini55.z.array(import_mini55.z.string())),
|
|
16991
|
+
features: import_mini55.z.optional(import_mini55.z.array(import_mini55.z.string())),
|
|
16992
|
+
delete: import_mini55.z.optional(import_mini55.z.boolean()),
|
|
16993
|
+
global: import_mini55.z.optional(import_mini55.z.boolean()),
|
|
16994
|
+
simulateCommands: import_mini55.z.optional(import_mini55.z.boolean()),
|
|
16995
|
+
simulateSubagents: import_mini55.z.optional(import_mini55.z.boolean()),
|
|
16996
|
+
simulateSkills: import_mini55.z.optional(import_mini55.z.boolean())
|
|
16433
16997
|
});
|
|
16434
16998
|
async function executeGenerate(options = {}) {
|
|
16435
16999
|
try {
|
|
@@ -16506,11 +17070,11 @@ var generateTools = {
|
|
|
16506
17070
|
};
|
|
16507
17071
|
|
|
16508
17072
|
// src/mcp/ignore.ts
|
|
16509
|
-
var
|
|
16510
|
-
var
|
|
17073
|
+
var import_node_path117 = require("path");
|
|
17074
|
+
var import_mini56 = require("zod/mini");
|
|
16511
17075
|
var maxIgnoreFileSizeBytes = 100 * 1024;
|
|
16512
17076
|
async function getIgnoreFile() {
|
|
16513
|
-
const ignoreFilePath = (0,
|
|
17077
|
+
const ignoreFilePath = (0, import_node_path117.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
16514
17078
|
try {
|
|
16515
17079
|
const content = await readFileContent(ignoreFilePath);
|
|
16516
17080
|
return {
|
|
@@ -16518,17 +17082,20 @@ async function getIgnoreFile() {
|
|
|
16518
17082
|
content
|
|
16519
17083
|
};
|
|
16520
17084
|
} catch (error) {
|
|
16521
|
-
throw new Error(
|
|
16522
|
-
|
|
16523
|
-
|
|
17085
|
+
throw new Error(
|
|
17086
|
+
`Failed to read ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17087
|
+
{
|
|
17088
|
+
cause: error
|
|
17089
|
+
}
|
|
17090
|
+
);
|
|
16524
17091
|
}
|
|
16525
17092
|
}
|
|
16526
17093
|
async function putIgnoreFile({ content }) {
|
|
16527
|
-
const ignoreFilePath = (0,
|
|
17094
|
+
const ignoreFilePath = (0, import_node_path117.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
16528
17095
|
const contentSizeBytes = Buffer.byteLength(content, "utf8");
|
|
16529
17096
|
if (contentSizeBytes > maxIgnoreFileSizeBytes) {
|
|
16530
17097
|
throw new Error(
|
|
16531
|
-
`Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB)`
|
|
17098
|
+
`Ignore file size ${contentSizeBytes} bytes exceeds maximum ${maxIgnoreFileSizeBytes} bytes (100KB) for ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}`
|
|
16532
17099
|
);
|
|
16533
17100
|
}
|
|
16534
17101
|
try {
|
|
@@ -16539,14 +17106,17 @@ async function putIgnoreFile({ content }) {
|
|
|
16539
17106
|
content
|
|
16540
17107
|
};
|
|
16541
17108
|
} catch (error) {
|
|
16542
|
-
throw new Error(
|
|
16543
|
-
|
|
16544
|
-
|
|
17109
|
+
throw new Error(
|
|
17110
|
+
`Failed to write ignore file (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17111
|
+
{
|
|
17112
|
+
cause: error
|
|
17113
|
+
}
|
|
17114
|
+
);
|
|
16545
17115
|
}
|
|
16546
17116
|
}
|
|
16547
17117
|
async function deleteIgnoreFile() {
|
|
16548
|
-
const aiignorePath = (0,
|
|
16549
|
-
const legacyIgnorePath = (0,
|
|
17118
|
+
const aiignorePath = (0, import_node_path117.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
|
|
17119
|
+
const legacyIgnorePath = (0, import_node_path117.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
|
|
16550
17120
|
try {
|
|
16551
17121
|
await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
|
|
16552
17122
|
return {
|
|
@@ -16556,7 +17126,7 @@ async function deleteIgnoreFile() {
|
|
|
16556
17126
|
};
|
|
16557
17127
|
} catch (error) {
|
|
16558
17128
|
throw new Error(
|
|
16559
|
-
`Failed to delete
|
|
17129
|
+
`Failed to delete ignore files (${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}, ${RULESYNC_IGNORE_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
16560
17130
|
{
|
|
16561
17131
|
cause: error
|
|
16562
17132
|
}
|
|
@@ -16564,11 +17134,11 @@ async function deleteIgnoreFile() {
|
|
|
16564
17134
|
}
|
|
16565
17135
|
}
|
|
16566
17136
|
var ignoreToolSchemas = {
|
|
16567
|
-
getIgnoreFile:
|
|
16568
|
-
putIgnoreFile:
|
|
16569
|
-
content:
|
|
17137
|
+
getIgnoreFile: import_mini56.z.object({}),
|
|
17138
|
+
putIgnoreFile: import_mini56.z.object({
|
|
17139
|
+
content: import_mini56.z.string()
|
|
16570
17140
|
}),
|
|
16571
|
-
deleteIgnoreFile:
|
|
17141
|
+
deleteIgnoreFile: import_mini56.z.object({})
|
|
16572
17142
|
};
|
|
16573
17143
|
var ignoreTools = {
|
|
16574
17144
|
getIgnoreFile: {
|
|
@@ -16601,11 +17171,11 @@ var ignoreTools = {
|
|
|
16601
17171
|
};
|
|
16602
17172
|
|
|
16603
17173
|
// src/mcp/import.ts
|
|
16604
|
-
var
|
|
16605
|
-
var importOptionsSchema =
|
|
16606
|
-
target:
|
|
16607
|
-
features:
|
|
16608
|
-
global:
|
|
17174
|
+
var import_mini57 = require("zod/mini");
|
|
17175
|
+
var importOptionsSchema = import_mini57.z.object({
|
|
17176
|
+
target: import_mini57.z.string(),
|
|
17177
|
+
features: import_mini57.z.optional(import_mini57.z.array(import_mini57.z.string())),
|
|
17178
|
+
global: import_mini57.z.optional(import_mini57.z.boolean())
|
|
16609
17179
|
});
|
|
16610
17180
|
async function executeImport(options) {
|
|
16611
17181
|
try {
|
|
@@ -16674,15 +17244,15 @@ var importTools = {
|
|
|
16674
17244
|
};
|
|
16675
17245
|
|
|
16676
17246
|
// src/mcp/mcp.ts
|
|
16677
|
-
var
|
|
16678
|
-
var
|
|
17247
|
+
var import_node_path118 = require("path");
|
|
17248
|
+
var import_mini58 = require("zod/mini");
|
|
16679
17249
|
var maxMcpSizeBytes = 1024 * 1024;
|
|
16680
17250
|
async function getMcpFile() {
|
|
16681
17251
|
try {
|
|
16682
17252
|
const rulesyncMcp = await RulesyncMcp.fromFile({
|
|
16683
17253
|
validate: true
|
|
16684
17254
|
});
|
|
16685
|
-
const relativePathFromCwd = (0,
|
|
17255
|
+
const relativePathFromCwd = (0, import_node_path118.join)(
|
|
16686
17256
|
rulesyncMcp.getRelativeDirPath(),
|
|
16687
17257
|
rulesyncMcp.getRelativeFilePath()
|
|
16688
17258
|
);
|
|
@@ -16691,30 +17261,36 @@ async function getMcpFile() {
|
|
|
16691
17261
|
content: rulesyncMcp.getFileContent()
|
|
16692
17262
|
};
|
|
16693
17263
|
} catch (error) {
|
|
16694
|
-
throw new Error(
|
|
16695
|
-
|
|
16696
|
-
|
|
17264
|
+
throw new Error(
|
|
17265
|
+
`Failed to read MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17266
|
+
{
|
|
17267
|
+
cause: error
|
|
17268
|
+
}
|
|
17269
|
+
);
|
|
16697
17270
|
}
|
|
16698
17271
|
}
|
|
16699
17272
|
async function putMcpFile({ content }) {
|
|
16700
17273
|
if (content.length > maxMcpSizeBytes) {
|
|
16701
17274
|
throw new Error(
|
|
16702
|
-
`MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB)`
|
|
17275
|
+
`MCP file size ${content.length} bytes exceeds maximum ${maxMcpSizeBytes} bytes (1MB) for ${RULESYNC_MCP_RELATIVE_FILE_PATH}`
|
|
16703
17276
|
);
|
|
16704
17277
|
}
|
|
16705
17278
|
try {
|
|
16706
17279
|
JSON.parse(content);
|
|
16707
17280
|
} catch (error) {
|
|
16708
|
-
throw new Error(
|
|
16709
|
-
|
|
16710
|
-
|
|
17281
|
+
throw new Error(
|
|
17282
|
+
`Invalid JSON format in MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17283
|
+
{
|
|
17284
|
+
cause: error
|
|
17285
|
+
}
|
|
17286
|
+
);
|
|
16711
17287
|
}
|
|
16712
17288
|
try {
|
|
16713
17289
|
const baseDir = process.cwd();
|
|
16714
17290
|
const paths = RulesyncMcp.getSettablePaths();
|
|
16715
17291
|
const relativeDirPath = paths.recommended.relativeDirPath;
|
|
16716
17292
|
const relativeFilePath = paths.recommended.relativeFilePath;
|
|
16717
|
-
const fullPath = (0,
|
|
17293
|
+
const fullPath = (0, import_node_path118.join)(baseDir, relativeDirPath, relativeFilePath);
|
|
16718
17294
|
const rulesyncMcp = new RulesyncMcp({
|
|
16719
17295
|
baseDir,
|
|
16720
17296
|
relativeDirPath,
|
|
@@ -16722,32 +17298,35 @@ async function putMcpFile({ content }) {
|
|
|
16722
17298
|
fileContent: content,
|
|
16723
17299
|
validate: true
|
|
16724
17300
|
});
|
|
16725
|
-
await ensureDir((0,
|
|
17301
|
+
await ensureDir((0, import_node_path118.join)(baseDir, relativeDirPath));
|
|
16726
17302
|
await writeFileContent(fullPath, content);
|
|
16727
|
-
const relativePathFromCwd = (0,
|
|
17303
|
+
const relativePathFromCwd = (0, import_node_path118.join)(relativeDirPath, relativeFilePath);
|
|
16728
17304
|
return {
|
|
16729
17305
|
relativePathFromCwd,
|
|
16730
17306
|
content: rulesyncMcp.getFileContent()
|
|
16731
17307
|
};
|
|
16732
17308
|
} catch (error) {
|
|
16733
|
-
throw new Error(
|
|
16734
|
-
|
|
16735
|
-
|
|
17309
|
+
throw new Error(
|
|
17310
|
+
`Failed to write MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17311
|
+
{
|
|
17312
|
+
cause: error
|
|
17313
|
+
}
|
|
17314
|
+
);
|
|
16736
17315
|
}
|
|
16737
17316
|
}
|
|
16738
17317
|
async function deleteMcpFile() {
|
|
16739
17318
|
try {
|
|
16740
17319
|
const baseDir = process.cwd();
|
|
16741
17320
|
const paths = RulesyncMcp.getSettablePaths();
|
|
16742
|
-
const recommendedPath = (0,
|
|
17321
|
+
const recommendedPath = (0, import_node_path118.join)(
|
|
16743
17322
|
baseDir,
|
|
16744
17323
|
paths.recommended.relativeDirPath,
|
|
16745
17324
|
paths.recommended.relativeFilePath
|
|
16746
17325
|
);
|
|
16747
|
-
const legacyPath = (0,
|
|
17326
|
+
const legacyPath = (0, import_node_path118.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
|
|
16748
17327
|
await removeFile(recommendedPath);
|
|
16749
17328
|
await removeFile(legacyPath);
|
|
16750
|
-
const relativePathFromCwd = (0,
|
|
17329
|
+
const relativePathFromCwd = (0, import_node_path118.join)(
|
|
16751
17330
|
paths.recommended.relativeDirPath,
|
|
16752
17331
|
paths.recommended.relativeFilePath
|
|
16753
17332
|
);
|
|
@@ -16755,17 +17334,20 @@ async function deleteMcpFile() {
|
|
|
16755
17334
|
relativePathFromCwd
|
|
16756
17335
|
};
|
|
16757
17336
|
} catch (error) {
|
|
16758
|
-
throw new Error(
|
|
16759
|
-
|
|
16760
|
-
|
|
17337
|
+
throw new Error(
|
|
17338
|
+
`Failed to delete MCP file (${RULESYNC_MCP_RELATIVE_FILE_PATH}): ${formatError(error)}`,
|
|
17339
|
+
{
|
|
17340
|
+
cause: error
|
|
17341
|
+
}
|
|
17342
|
+
);
|
|
16761
17343
|
}
|
|
16762
17344
|
}
|
|
16763
17345
|
var mcpToolSchemas = {
|
|
16764
|
-
getMcpFile:
|
|
16765
|
-
putMcpFile:
|
|
16766
|
-
content:
|
|
17346
|
+
getMcpFile: import_mini58.z.object({}),
|
|
17347
|
+
putMcpFile: import_mini58.z.object({
|
|
17348
|
+
content: import_mini58.z.string()
|
|
16767
17349
|
}),
|
|
16768
|
-
deleteMcpFile:
|
|
17350
|
+
deleteMcpFile: import_mini58.z.object({})
|
|
16769
17351
|
};
|
|
16770
17352
|
var mcpTools = {
|
|
16771
17353
|
getMcpFile: {
|
|
@@ -16798,12 +17380,12 @@ var mcpTools = {
|
|
|
16798
17380
|
};
|
|
16799
17381
|
|
|
16800
17382
|
// src/mcp/rules.ts
|
|
16801
|
-
var
|
|
16802
|
-
var
|
|
17383
|
+
var import_node_path119 = require("path");
|
|
17384
|
+
var import_mini59 = require("zod/mini");
|
|
16803
17385
|
var maxRuleSizeBytes = 1024 * 1024;
|
|
16804
17386
|
var maxRulesCount = 1e3;
|
|
16805
17387
|
async function listRules() {
|
|
16806
|
-
const rulesDir = (0,
|
|
17388
|
+
const rulesDir = (0, import_node_path119.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
16807
17389
|
try {
|
|
16808
17390
|
const files = await listDirectoryFiles(rulesDir);
|
|
16809
17391
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -16816,7 +17398,7 @@ async function listRules() {
|
|
|
16816
17398
|
});
|
|
16817
17399
|
const frontmatter = rule.getFrontmatter();
|
|
16818
17400
|
return {
|
|
16819
|
-
relativePathFromCwd: (0,
|
|
17401
|
+
relativePathFromCwd: (0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
|
|
16820
17402
|
frontmatter
|
|
16821
17403
|
};
|
|
16822
17404
|
} catch (error) {
|
|
@@ -16827,7 +17409,9 @@ async function listRules() {
|
|
|
16827
17409
|
);
|
|
16828
17410
|
return rules.filter((rule) => rule !== null);
|
|
16829
17411
|
} catch (error) {
|
|
16830
|
-
logger.error(
|
|
17412
|
+
logger.error(
|
|
17413
|
+
`Failed to read rules directory (${RULESYNC_RULES_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17414
|
+
);
|
|
16831
17415
|
return [];
|
|
16832
17416
|
}
|
|
16833
17417
|
}
|
|
@@ -16836,14 +17420,14 @@ async function getRule({ relativePathFromCwd }) {
|
|
|
16836
17420
|
relativePath: relativePathFromCwd,
|
|
16837
17421
|
intendedRootDir: process.cwd()
|
|
16838
17422
|
});
|
|
16839
|
-
const filename = (0,
|
|
17423
|
+
const filename = (0, import_node_path119.basename)(relativePathFromCwd);
|
|
16840
17424
|
try {
|
|
16841
17425
|
const rule = await RulesyncRule.fromFile({
|
|
16842
17426
|
relativeFilePath: filename,
|
|
16843
17427
|
validate: true
|
|
16844
17428
|
});
|
|
16845
17429
|
return {
|
|
16846
|
-
relativePathFromCwd: (0,
|
|
17430
|
+
relativePathFromCwd: (0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
16847
17431
|
frontmatter: rule.getFrontmatter(),
|
|
16848
17432
|
body: rule.getBody()
|
|
16849
17433
|
};
|
|
@@ -16862,20 +17446,22 @@ async function putRule({
|
|
|
16862
17446
|
relativePath: relativePathFromCwd,
|
|
16863
17447
|
intendedRootDir: process.cwd()
|
|
16864
17448
|
});
|
|
16865
|
-
const filename = (0,
|
|
17449
|
+
const filename = (0, import_node_path119.basename)(relativePathFromCwd);
|
|
16866
17450
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
16867
17451
|
if (estimatedSize > maxRuleSizeBytes) {
|
|
16868
17452
|
throw new Error(
|
|
16869
|
-
`Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB)`
|
|
17453
|
+
`Rule size ${estimatedSize} bytes exceeds maximum ${maxRuleSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
16870
17454
|
);
|
|
16871
17455
|
}
|
|
16872
17456
|
try {
|
|
16873
17457
|
const existingRules = await listRules();
|
|
16874
17458
|
const isUpdate = existingRules.some(
|
|
16875
|
-
(rule2) => rule2.relativePathFromCwd === (0,
|
|
17459
|
+
(rule2) => rule2.relativePathFromCwd === (0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
16876
17460
|
);
|
|
16877
17461
|
if (!isUpdate && existingRules.length >= maxRulesCount) {
|
|
16878
|
-
throw new Error(
|
|
17462
|
+
throw new Error(
|
|
17463
|
+
`Maximum number of rules (${maxRulesCount}) reached in ${RULESYNC_RULES_RELATIVE_DIR_PATH}`
|
|
17464
|
+
);
|
|
16879
17465
|
}
|
|
16880
17466
|
const rule = new RulesyncRule({
|
|
16881
17467
|
baseDir: process.cwd(),
|
|
@@ -16885,11 +17471,11 @@ async function putRule({
|
|
|
16885
17471
|
body,
|
|
16886
17472
|
validate: true
|
|
16887
17473
|
});
|
|
16888
|
-
const rulesDir = (0,
|
|
17474
|
+
const rulesDir = (0, import_node_path119.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
|
|
16889
17475
|
await ensureDir(rulesDir);
|
|
16890
17476
|
await writeFileContent(rule.getFilePath(), rule.getFileContent());
|
|
16891
17477
|
return {
|
|
16892
|
-
relativePathFromCwd: (0,
|
|
17478
|
+
relativePathFromCwd: (0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
|
|
16893
17479
|
frontmatter: rule.getFrontmatter(),
|
|
16894
17480
|
body: rule.getBody()
|
|
16895
17481
|
};
|
|
@@ -16904,12 +17490,12 @@ async function deleteRule({ relativePathFromCwd }) {
|
|
|
16904
17490
|
relativePath: relativePathFromCwd,
|
|
16905
17491
|
intendedRootDir: process.cwd()
|
|
16906
17492
|
});
|
|
16907
|
-
const filename = (0,
|
|
16908
|
-
const fullPath = (0,
|
|
17493
|
+
const filename = (0, import_node_path119.basename)(relativePathFromCwd);
|
|
17494
|
+
const fullPath = (0, import_node_path119.join)(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
|
|
16909
17495
|
try {
|
|
16910
17496
|
await removeFile(fullPath);
|
|
16911
17497
|
return {
|
|
16912
|
-
relativePathFromCwd: (0,
|
|
17498
|
+
relativePathFromCwd: (0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
|
|
16913
17499
|
};
|
|
16914
17500
|
} catch (error) {
|
|
16915
17501
|
throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
|
|
@@ -16918,23 +17504,23 @@ async function deleteRule({ relativePathFromCwd }) {
|
|
|
16918
17504
|
}
|
|
16919
17505
|
}
|
|
16920
17506
|
var ruleToolSchemas = {
|
|
16921
|
-
listRules:
|
|
16922
|
-
getRule:
|
|
16923
|
-
relativePathFromCwd:
|
|
17507
|
+
listRules: import_mini59.z.object({}),
|
|
17508
|
+
getRule: import_mini59.z.object({
|
|
17509
|
+
relativePathFromCwd: import_mini59.z.string()
|
|
16924
17510
|
}),
|
|
16925
|
-
putRule:
|
|
16926
|
-
relativePathFromCwd:
|
|
17511
|
+
putRule: import_mini59.z.object({
|
|
17512
|
+
relativePathFromCwd: import_mini59.z.string(),
|
|
16927
17513
|
frontmatter: RulesyncRuleFrontmatterSchema,
|
|
16928
|
-
body:
|
|
17514
|
+
body: import_mini59.z.string()
|
|
16929
17515
|
}),
|
|
16930
|
-
deleteRule:
|
|
16931
|
-
relativePathFromCwd:
|
|
17516
|
+
deleteRule: import_mini59.z.object({
|
|
17517
|
+
relativePathFromCwd: import_mini59.z.string()
|
|
16932
17518
|
})
|
|
16933
17519
|
};
|
|
16934
17520
|
var ruleTools = {
|
|
16935
17521
|
listRules: {
|
|
16936
17522
|
name: "listRules",
|
|
16937
|
-
description: `List all rules from ${(0,
|
|
17523
|
+
description: `List all rules from ${(0, import_node_path119.join)(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
16938
17524
|
parameters: ruleToolSchemas.listRules,
|
|
16939
17525
|
execute: async () => {
|
|
16940
17526
|
const rules = await listRules();
|
|
@@ -16976,8 +17562,8 @@ var ruleTools = {
|
|
|
16976
17562
|
};
|
|
16977
17563
|
|
|
16978
17564
|
// src/mcp/skills.ts
|
|
16979
|
-
var
|
|
16980
|
-
var
|
|
17565
|
+
var import_node_path120 = require("path");
|
|
17566
|
+
var import_mini60 = require("zod/mini");
|
|
16981
17567
|
var maxSkillSizeBytes = 1024 * 1024;
|
|
16982
17568
|
var maxSkillsCount = 1e3;
|
|
16983
17569
|
function aiDirFileToMcpSkillFile(file) {
|
|
@@ -16993,19 +17579,19 @@ function mcpSkillFileToAiDirFile(file) {
|
|
|
16993
17579
|
};
|
|
16994
17580
|
}
|
|
16995
17581
|
function extractDirName(relativeDirPathFromCwd) {
|
|
16996
|
-
const dirName = (0,
|
|
17582
|
+
const dirName = (0, import_node_path120.basename)(relativeDirPathFromCwd);
|
|
16997
17583
|
if (!dirName) {
|
|
16998
17584
|
throw new Error(`Invalid path: ${relativeDirPathFromCwd}`);
|
|
16999
17585
|
}
|
|
17000
17586
|
return dirName;
|
|
17001
17587
|
}
|
|
17002
17588
|
async function listSkills() {
|
|
17003
|
-
const skillsDir = (0,
|
|
17589
|
+
const skillsDir = (0, import_node_path120.join)(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
|
|
17004
17590
|
try {
|
|
17005
|
-
const skillDirPaths = await findFilesByGlobs((0,
|
|
17591
|
+
const skillDirPaths = await findFilesByGlobs((0, import_node_path120.join)(skillsDir, "*"), { type: "dir" });
|
|
17006
17592
|
const skills = await Promise.all(
|
|
17007
17593
|
skillDirPaths.map(async (dirPath) => {
|
|
17008
|
-
const dirName = (0,
|
|
17594
|
+
const dirName = (0, import_node_path120.basename)(dirPath);
|
|
17009
17595
|
if (!dirName) return null;
|
|
17010
17596
|
try {
|
|
17011
17597
|
const skill = await RulesyncSkill.fromDir({
|
|
@@ -17013,7 +17599,7 @@ async function listSkills() {
|
|
|
17013
17599
|
});
|
|
17014
17600
|
const frontmatter = skill.getFrontmatter();
|
|
17015
17601
|
return {
|
|
17016
|
-
relativeDirPathFromCwd: (0,
|
|
17602
|
+
relativeDirPathFromCwd: (0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
17017
17603
|
frontmatter
|
|
17018
17604
|
};
|
|
17019
17605
|
} catch (error) {
|
|
@@ -17024,7 +17610,9 @@ async function listSkills() {
|
|
|
17024
17610
|
);
|
|
17025
17611
|
return skills.filter((skill) => skill !== null);
|
|
17026
17612
|
} catch (error) {
|
|
17027
|
-
logger.error(
|
|
17613
|
+
logger.error(
|
|
17614
|
+
`Failed to read skills directory (${RULESYNC_SKILLS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17615
|
+
);
|
|
17028
17616
|
return [];
|
|
17029
17617
|
}
|
|
17030
17618
|
}
|
|
@@ -17039,7 +17627,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
|
|
|
17039
17627
|
dirName
|
|
17040
17628
|
});
|
|
17041
17629
|
return {
|
|
17042
|
-
relativeDirPathFromCwd: (0,
|
|
17630
|
+
relativeDirPathFromCwd: (0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
17043
17631
|
frontmatter: skill.getFrontmatter(),
|
|
17044
17632
|
body: skill.getBody(),
|
|
17045
17633
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -17067,16 +17655,18 @@ async function putSkill({
|
|
|
17067
17655
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length + otherFiles.reduce((acc, file) => acc + file.name.length + file.body.length, 0);
|
|
17068
17656
|
if (estimatedSize > maxSkillSizeBytes) {
|
|
17069
17657
|
throw new Error(
|
|
17070
|
-
`Skill size ${estimatedSize} bytes exceeds maximum ${maxSkillSizeBytes} bytes (1MB)`
|
|
17658
|
+
`Skill size ${estimatedSize} bytes exceeds maximum ${maxSkillSizeBytes} bytes (1MB) for ${relativeDirPathFromCwd}`
|
|
17071
17659
|
);
|
|
17072
17660
|
}
|
|
17073
17661
|
try {
|
|
17074
17662
|
const existingSkills = await listSkills();
|
|
17075
17663
|
const isUpdate = existingSkills.some(
|
|
17076
|
-
(skill2) => skill2.relativeDirPathFromCwd === (0,
|
|
17664
|
+
(skill2) => skill2.relativeDirPathFromCwd === (0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
17077
17665
|
);
|
|
17078
17666
|
if (!isUpdate && existingSkills.length >= maxSkillsCount) {
|
|
17079
|
-
throw new Error(
|
|
17667
|
+
throw new Error(
|
|
17668
|
+
`Maximum number of skills (${maxSkillsCount}) reached in ${RULESYNC_SKILLS_RELATIVE_DIR_PATH}`
|
|
17669
|
+
);
|
|
17080
17670
|
}
|
|
17081
17671
|
const aiDirFiles = otherFiles.map(mcpSkillFileToAiDirFile);
|
|
17082
17672
|
const skill = new RulesyncSkill({
|
|
@@ -17088,9 +17678,9 @@ async function putSkill({
|
|
|
17088
17678
|
otherFiles: aiDirFiles,
|
|
17089
17679
|
validate: true
|
|
17090
17680
|
});
|
|
17091
|
-
const skillDirPath = (0,
|
|
17681
|
+
const skillDirPath = (0, import_node_path120.join)(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
17092
17682
|
await ensureDir(skillDirPath);
|
|
17093
|
-
const skillFilePath = (0,
|
|
17683
|
+
const skillFilePath = (0, import_node_path120.join)(skillDirPath, SKILL_FILE_NAME);
|
|
17094
17684
|
const skillFileContent = stringifyFrontmatter(body, frontmatter);
|
|
17095
17685
|
await writeFileContent(skillFilePath, skillFileContent);
|
|
17096
17686
|
for (const file of otherFiles) {
|
|
@@ -17098,15 +17688,15 @@ async function putSkill({
|
|
|
17098
17688
|
relativePath: file.name,
|
|
17099
17689
|
intendedRootDir: skillDirPath
|
|
17100
17690
|
});
|
|
17101
|
-
const filePath = (0,
|
|
17102
|
-
const fileDir = (0,
|
|
17691
|
+
const filePath = (0, import_node_path120.join)(skillDirPath, file.name);
|
|
17692
|
+
const fileDir = (0, import_node_path120.join)(skillDirPath, (0, import_node_path120.dirname)(file.name));
|
|
17103
17693
|
if (fileDir !== skillDirPath) {
|
|
17104
17694
|
await ensureDir(fileDir);
|
|
17105
17695
|
}
|
|
17106
17696
|
await writeFileContent(filePath, file.body);
|
|
17107
17697
|
}
|
|
17108
17698
|
return {
|
|
17109
|
-
relativeDirPathFromCwd: (0,
|
|
17699
|
+
relativeDirPathFromCwd: (0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
|
|
17110
17700
|
frontmatter: skill.getFrontmatter(),
|
|
17111
17701
|
body: skill.getBody(),
|
|
17112
17702
|
otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
|
|
@@ -17128,13 +17718,13 @@ async function deleteSkill({
|
|
|
17128
17718
|
intendedRootDir: process.cwd()
|
|
17129
17719
|
});
|
|
17130
17720
|
const dirName = extractDirName(relativeDirPathFromCwd);
|
|
17131
|
-
const skillDirPath = (0,
|
|
17721
|
+
const skillDirPath = (0, import_node_path120.join)(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
|
|
17132
17722
|
try {
|
|
17133
17723
|
if (await directoryExists(skillDirPath)) {
|
|
17134
17724
|
await removeDirectory(skillDirPath);
|
|
17135
17725
|
}
|
|
17136
17726
|
return {
|
|
17137
|
-
relativeDirPathFromCwd: (0,
|
|
17727
|
+
relativeDirPathFromCwd: (0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
|
|
17138
17728
|
};
|
|
17139
17729
|
} catch (error) {
|
|
17140
17730
|
throw new Error(
|
|
@@ -17145,29 +17735,29 @@ async function deleteSkill({
|
|
|
17145
17735
|
);
|
|
17146
17736
|
}
|
|
17147
17737
|
}
|
|
17148
|
-
var McpSkillFileSchema =
|
|
17149
|
-
name:
|
|
17150
|
-
body:
|
|
17738
|
+
var McpSkillFileSchema = import_mini60.z.object({
|
|
17739
|
+
name: import_mini60.z.string(),
|
|
17740
|
+
body: import_mini60.z.string()
|
|
17151
17741
|
});
|
|
17152
17742
|
var skillToolSchemas = {
|
|
17153
|
-
listSkills:
|
|
17154
|
-
getSkill:
|
|
17155
|
-
relativeDirPathFromCwd:
|
|
17743
|
+
listSkills: import_mini60.z.object({}),
|
|
17744
|
+
getSkill: import_mini60.z.object({
|
|
17745
|
+
relativeDirPathFromCwd: import_mini60.z.string()
|
|
17156
17746
|
}),
|
|
17157
|
-
putSkill:
|
|
17158
|
-
relativeDirPathFromCwd:
|
|
17747
|
+
putSkill: import_mini60.z.object({
|
|
17748
|
+
relativeDirPathFromCwd: import_mini60.z.string(),
|
|
17159
17749
|
frontmatter: RulesyncSkillFrontmatterSchema,
|
|
17160
|
-
body:
|
|
17161
|
-
otherFiles:
|
|
17750
|
+
body: import_mini60.z.string(),
|
|
17751
|
+
otherFiles: import_mini60.z.optional(import_mini60.z.array(McpSkillFileSchema))
|
|
17162
17752
|
}),
|
|
17163
|
-
deleteSkill:
|
|
17164
|
-
relativeDirPathFromCwd:
|
|
17753
|
+
deleteSkill: import_mini60.z.object({
|
|
17754
|
+
relativeDirPathFromCwd: import_mini60.z.string()
|
|
17165
17755
|
})
|
|
17166
17756
|
};
|
|
17167
17757
|
var skillTools = {
|
|
17168
17758
|
listSkills: {
|
|
17169
17759
|
name: "listSkills",
|
|
17170
|
-
description: `List all skills from ${(0,
|
|
17760
|
+
description: `List all skills from ${(0, import_node_path120.join)(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
|
|
17171
17761
|
parameters: skillToolSchemas.listSkills,
|
|
17172
17762
|
execute: async () => {
|
|
17173
17763
|
const skills = await listSkills();
|
|
@@ -17210,12 +17800,12 @@ var skillTools = {
|
|
|
17210
17800
|
};
|
|
17211
17801
|
|
|
17212
17802
|
// src/mcp/subagents.ts
|
|
17213
|
-
var
|
|
17214
|
-
var
|
|
17803
|
+
var import_node_path121 = require("path");
|
|
17804
|
+
var import_mini61 = require("zod/mini");
|
|
17215
17805
|
var maxSubagentSizeBytes = 1024 * 1024;
|
|
17216
17806
|
var maxSubagentsCount = 1e3;
|
|
17217
17807
|
async function listSubagents() {
|
|
17218
|
-
const subagentsDir = (0,
|
|
17808
|
+
const subagentsDir = (0, import_node_path121.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
17219
17809
|
try {
|
|
17220
17810
|
const files = await listDirectoryFiles(subagentsDir);
|
|
17221
17811
|
const mdFiles = files.filter((file) => file.endsWith(".md"));
|
|
@@ -17228,7 +17818,7 @@ async function listSubagents() {
|
|
|
17228
17818
|
});
|
|
17229
17819
|
const frontmatter = subagent.getFrontmatter();
|
|
17230
17820
|
return {
|
|
17231
|
-
relativePathFromCwd: (0,
|
|
17821
|
+
relativePathFromCwd: (0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
|
|
17232
17822
|
frontmatter
|
|
17233
17823
|
};
|
|
17234
17824
|
} catch (error) {
|
|
@@ -17241,7 +17831,9 @@ async function listSubagents() {
|
|
|
17241
17831
|
(subagent) => subagent !== null
|
|
17242
17832
|
);
|
|
17243
17833
|
} catch (error) {
|
|
17244
|
-
logger.error(
|
|
17834
|
+
logger.error(
|
|
17835
|
+
`Failed to read subagents directory (${RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH}): ${formatError(error)}`
|
|
17836
|
+
);
|
|
17245
17837
|
return [];
|
|
17246
17838
|
}
|
|
17247
17839
|
}
|
|
@@ -17250,14 +17842,14 @@ async function getSubagent({ relativePathFromCwd }) {
|
|
|
17250
17842
|
relativePath: relativePathFromCwd,
|
|
17251
17843
|
intendedRootDir: process.cwd()
|
|
17252
17844
|
});
|
|
17253
|
-
const filename = (0,
|
|
17845
|
+
const filename = (0, import_node_path121.basename)(relativePathFromCwd);
|
|
17254
17846
|
try {
|
|
17255
17847
|
const subagent = await RulesyncSubagent.fromFile({
|
|
17256
17848
|
relativeFilePath: filename,
|
|
17257
17849
|
validate: true
|
|
17258
17850
|
});
|
|
17259
17851
|
return {
|
|
17260
|
-
relativePathFromCwd: (0,
|
|
17852
|
+
relativePathFromCwd: (0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
17261
17853
|
frontmatter: subagent.getFrontmatter(),
|
|
17262
17854
|
body: subagent.getBody()
|
|
17263
17855
|
};
|
|
@@ -17276,20 +17868,22 @@ async function putSubagent({
|
|
|
17276
17868
|
relativePath: relativePathFromCwd,
|
|
17277
17869
|
intendedRootDir: process.cwd()
|
|
17278
17870
|
});
|
|
17279
|
-
const filename = (0,
|
|
17871
|
+
const filename = (0, import_node_path121.basename)(relativePathFromCwd);
|
|
17280
17872
|
const estimatedSize = JSON.stringify(frontmatter).length + body.length;
|
|
17281
17873
|
if (estimatedSize > maxSubagentSizeBytes) {
|
|
17282
17874
|
throw new Error(
|
|
17283
|
-
`Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB)`
|
|
17875
|
+
`Subagent size ${estimatedSize} bytes exceeds maximum ${maxSubagentSizeBytes} bytes (1MB) for ${relativePathFromCwd}`
|
|
17284
17876
|
);
|
|
17285
17877
|
}
|
|
17286
17878
|
try {
|
|
17287
17879
|
const existingSubagents = await listSubagents();
|
|
17288
17880
|
const isUpdate = existingSubagents.some(
|
|
17289
|
-
(subagent2) => subagent2.relativePathFromCwd === (0,
|
|
17881
|
+
(subagent2) => subagent2.relativePathFromCwd === (0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
17290
17882
|
);
|
|
17291
17883
|
if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
|
|
17292
|
-
throw new Error(
|
|
17884
|
+
throw new Error(
|
|
17885
|
+
`Maximum number of subagents (${maxSubagentsCount}) reached in ${RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH}`
|
|
17886
|
+
);
|
|
17293
17887
|
}
|
|
17294
17888
|
const subagent = new RulesyncSubagent({
|
|
17295
17889
|
baseDir: process.cwd(),
|
|
@@ -17299,11 +17893,11 @@ async function putSubagent({
|
|
|
17299
17893
|
body,
|
|
17300
17894
|
validate: true
|
|
17301
17895
|
});
|
|
17302
|
-
const subagentsDir = (0,
|
|
17896
|
+
const subagentsDir = (0, import_node_path121.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
|
|
17303
17897
|
await ensureDir(subagentsDir);
|
|
17304
17898
|
await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
|
|
17305
17899
|
return {
|
|
17306
|
-
relativePathFromCwd: (0,
|
|
17900
|
+
relativePathFromCwd: (0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
|
|
17307
17901
|
frontmatter: subagent.getFrontmatter(),
|
|
17308
17902
|
body: subagent.getBody()
|
|
17309
17903
|
};
|
|
@@ -17318,12 +17912,12 @@ async function deleteSubagent({ relativePathFromCwd }) {
|
|
|
17318
17912
|
relativePath: relativePathFromCwd,
|
|
17319
17913
|
intendedRootDir: process.cwd()
|
|
17320
17914
|
});
|
|
17321
|
-
const filename = (0,
|
|
17322
|
-
const fullPath = (0,
|
|
17915
|
+
const filename = (0, import_node_path121.basename)(relativePathFromCwd);
|
|
17916
|
+
const fullPath = (0, import_node_path121.join)(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
|
|
17323
17917
|
try {
|
|
17324
17918
|
await removeFile(fullPath);
|
|
17325
17919
|
return {
|
|
17326
|
-
relativePathFromCwd: (0,
|
|
17920
|
+
relativePathFromCwd: (0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
|
|
17327
17921
|
};
|
|
17328
17922
|
} catch (error) {
|
|
17329
17923
|
throw new Error(
|
|
@@ -17335,23 +17929,23 @@ async function deleteSubagent({ relativePathFromCwd }) {
|
|
|
17335
17929
|
}
|
|
17336
17930
|
}
|
|
17337
17931
|
var subagentToolSchemas = {
|
|
17338
|
-
listSubagents:
|
|
17339
|
-
getSubagent:
|
|
17340
|
-
relativePathFromCwd:
|
|
17932
|
+
listSubagents: import_mini61.z.object({}),
|
|
17933
|
+
getSubagent: import_mini61.z.object({
|
|
17934
|
+
relativePathFromCwd: import_mini61.z.string()
|
|
17341
17935
|
}),
|
|
17342
|
-
putSubagent:
|
|
17343
|
-
relativePathFromCwd:
|
|
17936
|
+
putSubagent: import_mini61.z.object({
|
|
17937
|
+
relativePathFromCwd: import_mini61.z.string(),
|
|
17344
17938
|
frontmatter: RulesyncSubagentFrontmatterSchema,
|
|
17345
|
-
body:
|
|
17939
|
+
body: import_mini61.z.string()
|
|
17346
17940
|
}),
|
|
17347
|
-
deleteSubagent:
|
|
17348
|
-
relativePathFromCwd:
|
|
17941
|
+
deleteSubagent: import_mini61.z.object({
|
|
17942
|
+
relativePathFromCwd: import_mini61.z.string()
|
|
17349
17943
|
})
|
|
17350
17944
|
};
|
|
17351
17945
|
var subagentTools = {
|
|
17352
17946
|
listSubagents: {
|
|
17353
17947
|
name: "listSubagents",
|
|
17354
|
-
description: `List all subagents from ${(0,
|
|
17948
|
+
description: `List all subagents from ${(0, import_node_path121.join)(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
|
|
17355
17949
|
parameters: subagentToolSchemas.listSubagents,
|
|
17356
17950
|
execute: async () => {
|
|
17357
17951
|
const subagents = await listSubagents();
|
|
@@ -17393,7 +17987,7 @@ var subagentTools = {
|
|
|
17393
17987
|
};
|
|
17394
17988
|
|
|
17395
17989
|
// src/mcp/tools.ts
|
|
17396
|
-
var rulesyncFeatureSchema =
|
|
17990
|
+
var rulesyncFeatureSchema = import_mini62.z.enum([
|
|
17397
17991
|
"rule",
|
|
17398
17992
|
"command",
|
|
17399
17993
|
"subagent",
|
|
@@ -17403,21 +17997,21 @@ var rulesyncFeatureSchema = import_mini61.z.enum([
|
|
|
17403
17997
|
"generate",
|
|
17404
17998
|
"import"
|
|
17405
17999
|
]);
|
|
17406
|
-
var rulesyncOperationSchema =
|
|
17407
|
-
var skillFileSchema =
|
|
17408
|
-
name:
|
|
17409
|
-
body:
|
|
18000
|
+
var rulesyncOperationSchema = import_mini62.z.enum(["list", "get", "put", "delete", "run"]);
|
|
18001
|
+
var skillFileSchema = import_mini62.z.object({
|
|
18002
|
+
name: import_mini62.z.string(),
|
|
18003
|
+
body: import_mini62.z.string()
|
|
17410
18004
|
});
|
|
17411
|
-
var rulesyncToolSchema =
|
|
18005
|
+
var rulesyncToolSchema = import_mini62.z.object({
|
|
17412
18006
|
feature: rulesyncFeatureSchema,
|
|
17413
18007
|
operation: rulesyncOperationSchema,
|
|
17414
|
-
targetPathFromCwd:
|
|
17415
|
-
frontmatter:
|
|
17416
|
-
body:
|
|
17417
|
-
otherFiles:
|
|
17418
|
-
content:
|
|
17419
|
-
generateOptions:
|
|
17420
|
-
importOptions:
|
|
18008
|
+
targetPathFromCwd: import_mini62.z.optional(import_mini62.z.string()),
|
|
18009
|
+
frontmatter: import_mini62.z.optional(import_mini62.z.unknown()),
|
|
18010
|
+
body: import_mini62.z.optional(import_mini62.z.string()),
|
|
18011
|
+
otherFiles: import_mini62.z.optional(import_mini62.z.array(skillFileSchema)),
|
|
18012
|
+
content: import_mini62.z.optional(import_mini62.z.string()),
|
|
18013
|
+
generateOptions: import_mini62.z.optional(generateOptionsSchema),
|
|
18014
|
+
importOptions: import_mini62.z.optional(importOptionsSchema)
|
|
17421
18015
|
});
|
|
17422
18016
|
var supportedOperationsByFeature = {
|
|
17423
18017
|
rule: ["list", "get", "put", "delete"],
|
|
@@ -17746,7 +18340,7 @@ async function downloadFile(url, destPath) {
|
|
|
17746
18340
|
redirect: "follow"
|
|
17747
18341
|
});
|
|
17748
18342
|
if (!response.ok) {
|
|
17749
|
-
throw new Error(`Failed to download: HTTP ${response.status}`);
|
|
18343
|
+
throw new Error(`Failed to download ${url}: HTTP ${response.status}`);
|
|
17750
18344
|
}
|
|
17751
18345
|
if (response.url) {
|
|
17752
18346
|
validateDownloadUrl(response.url);
|
|
@@ -17976,7 +18570,7 @@ async function updateCommand(currentVersion, options) {
|
|
|
17976
18570
|
}
|
|
17977
18571
|
|
|
17978
18572
|
// src/cli/index.ts
|
|
17979
|
-
var getVersion = () => "7.
|
|
18573
|
+
var getVersion = () => "7.1.0";
|
|
17980
18574
|
var main = async () => {
|
|
17981
18575
|
const program = new import_commander.Command();
|
|
17982
18576
|
const version = getVersion();
|
|
@@ -18049,6 +18643,21 @@ var main = async () => {
|
|
|
18049
18643
|
process.exit(1);
|
|
18050
18644
|
}
|
|
18051
18645
|
});
|
|
18646
|
+
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) => {
|
|
18647
|
+
try {
|
|
18648
|
+
await installCommand({
|
|
18649
|
+
update: options.update,
|
|
18650
|
+
frozen: options.frozen,
|
|
18651
|
+
token: options.token,
|
|
18652
|
+
configPath: options.config,
|
|
18653
|
+
verbose: options.verbose,
|
|
18654
|
+
silent: options.silent
|
|
18655
|
+
});
|
|
18656
|
+
} catch (error) {
|
|
18657
|
+
logger.error(formatError(error));
|
|
18658
|
+
process.exit(1);
|
|
18659
|
+
}
|
|
18660
|
+
});
|
|
18052
18661
|
program.command("generate").description("Generate configuration files for AI tools").option(
|
|
18053
18662
|
"-t, --targets <tools>",
|
|
18054
18663
|
"Comma-separated list of tools to generate for (e.g., 'copilot,cursor,cline' or '*' for all)",
|