compose-agentsmd 2.0.2 → 3.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 +3 -1
- package/dist/compose-agents.js +33 -47
- package/package.json +1 -1
- package/tools/tool-rules.md +2 -1
- package/tools/usage.txt +6 -3
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ From each project root, run:
|
|
|
30
30
|
compose-agentsmd
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
The tool
|
|
33
|
+
The tool reads `agent-ruleset.json` from the given root directory (default: current working directory), and writes the output file specified by the ruleset. If `output` is omitted, it defaults to `AGENTS.md`.
|
|
34
34
|
|
|
35
35
|
The tool prepends a small "Tool Rules" block to every generated `AGENTS.md` so agents know how to regenerate or update rules.
|
|
36
36
|
|
|
@@ -85,6 +85,8 @@ Remote sources are cached under `~/.agentsmd/cache/<owner>/<repo>/<ref>/`. Use `
|
|
|
85
85
|
- `--ruleset-name <name>`: override the ruleset filename (default: `agent-ruleset.json`)
|
|
86
86
|
- `--refresh`: refresh cached remote rules
|
|
87
87
|
- `--clear-cache`: remove cached remote rules and exit
|
|
88
|
+
- `--version` / `-V`: show version and exit
|
|
89
|
+
- `--verbose` / `-v`: show verbose diagnostics
|
|
88
90
|
- `edit-rules`: prepare or locate a writable rules workspace
|
|
89
91
|
- `apply-rules`: push workspace changes (if GitHub source) and regenerate rules with refresh
|
|
90
92
|
|
package/dist/compose-agents.js
CHANGED
|
@@ -9,21 +9,7 @@ const DEFAULT_OUTPUT = "AGENTS.md";
|
|
|
9
9
|
const DEFAULT_CACHE_ROOT = path.join(os.homedir(), ".agentsmd", "cache");
|
|
10
10
|
const DEFAULT_WORKSPACE_ROOT = path.join(os.homedir(), ".agentsmd", "workspace");
|
|
11
11
|
const RULESET_SCHEMA_PATH = new URL("../agent-ruleset.schema.json", import.meta.url);
|
|
12
|
-
const
|
|
13
|
-
".git",
|
|
14
|
-
"agent-rules",
|
|
15
|
-
"agent-rules-private",
|
|
16
|
-
"agent-rules-local",
|
|
17
|
-
"agent-rules-tools",
|
|
18
|
-
"compose-agentsmd",
|
|
19
|
-
"node_modules",
|
|
20
|
-
"dist",
|
|
21
|
-
"build",
|
|
22
|
-
"out",
|
|
23
|
-
".next",
|
|
24
|
-
".turbo",
|
|
25
|
-
"coverage"
|
|
26
|
-
]);
|
|
12
|
+
const PACKAGE_JSON_PATH = new URL("../package.json", import.meta.url);
|
|
27
13
|
const TOOL_RULES_PATH = new URL("../tools/tool-rules.md", import.meta.url);
|
|
28
14
|
const USAGE_PATH = new URL("../tools/usage.txt", import.meta.url);
|
|
29
15
|
const parseArgs = (argv) => {
|
|
@@ -39,6 +25,14 @@ const parseArgs = (argv) => {
|
|
|
39
25
|
args.help = true;
|
|
40
26
|
continue;
|
|
41
27
|
}
|
|
28
|
+
if (arg === "--version" || arg === "-V") {
|
|
29
|
+
args.version = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (arg === "--verbose" || arg === "-v") {
|
|
33
|
+
args.verbose = true;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
42
36
|
if (arg === "--root") {
|
|
43
37
|
const value = remaining[i + 1];
|
|
44
38
|
if (!value) {
|
|
@@ -82,6 +76,8 @@ const normalizeTrailingWhitespace = (content) => content.replace(/\s+$/u, "");
|
|
|
82
76
|
const normalizePath = (filePath) => filePath.replace(/\\/g, "/");
|
|
83
77
|
const isNonEmptyString = (value) => typeof value === "string" && value.trim() !== "";
|
|
84
78
|
const usage = normalizeTrailingWhitespace(fs.readFileSync(USAGE_PATH, "utf8"));
|
|
79
|
+
const packageJson = JSON.parse(fs.readFileSync(PACKAGE_JSON_PATH, "utf8"));
|
|
80
|
+
const getVersion = () => packageJson.version ?? "unknown";
|
|
85
81
|
const rulesetSchema = JSON.parse(fs.readFileSync(RULESET_SCHEMA_PATH, "utf8"));
|
|
86
82
|
const TOOL_RULES = normalizeTrailingWhitespace(fs.readFileSync(TOOL_RULES_PATH, "utf8"));
|
|
87
83
|
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
@@ -394,51 +390,31 @@ const composeRuleset = (rulesetPath, rootDir, options) => {
|
|
|
394
390
|
fs.writeFileSync(outputPath, output, "utf8");
|
|
395
391
|
return normalizePath(path.relative(rootDir, outputPath));
|
|
396
392
|
};
|
|
397
|
-
const findRulesetFiles = (rootDir, rulesetName) => {
|
|
398
|
-
const results = [];
|
|
399
|
-
const pending = [rootDir];
|
|
400
|
-
while (pending.length > 0) {
|
|
401
|
-
const currentDir = pending.pop();
|
|
402
|
-
if (!currentDir) {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
406
|
-
for (const entry of entries) {
|
|
407
|
-
const entryPath = path.join(currentDir, entry.name);
|
|
408
|
-
if (entry.isDirectory()) {
|
|
409
|
-
if (DEFAULT_IGNORE_DIRS.has(entry.name)) {
|
|
410
|
-
continue;
|
|
411
|
-
}
|
|
412
|
-
pending.push(entryPath);
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
if (entry.isFile() && entry.name === rulesetName) {
|
|
416
|
-
results.push(entryPath);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return results;
|
|
421
|
-
};
|
|
422
393
|
const getRulesetFiles = (rootDir, specificRuleset, rulesetName) => {
|
|
423
394
|
if (specificRuleset) {
|
|
424
395
|
const resolved = resolveFrom(rootDir, specificRuleset);
|
|
425
396
|
ensureFileExists(resolved);
|
|
426
397
|
return [resolved];
|
|
427
398
|
}
|
|
428
|
-
|
|
399
|
+
const defaultRuleset = path.join(rootDir, rulesetName);
|
|
400
|
+
if (!fs.existsSync(defaultRuleset)) {
|
|
401
|
+
return [];
|
|
402
|
+
}
|
|
403
|
+
return [defaultRuleset];
|
|
429
404
|
};
|
|
430
405
|
const ensureSingleRuleset = (rulesetFiles, rootDir, rulesetName) => {
|
|
431
406
|
if (rulesetFiles.length === 0) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (rulesetFiles.length > 1) {
|
|
435
|
-
const list = rulesetFiles.map((file) => `- ${normalizePath(path.relative(rootDir, file))}`).join("\n");
|
|
436
|
-
throw new Error(`Multiple ruleset files found. Specify one with --ruleset:\n${list}`);
|
|
407
|
+
const expectedPath = normalizePath(path.join(rootDir, rulesetName));
|
|
408
|
+
throw new Error(`Missing ruleset file: ${expectedPath}`);
|
|
437
409
|
}
|
|
438
410
|
return rulesetFiles[0];
|
|
439
411
|
};
|
|
440
412
|
const main = () => {
|
|
441
413
|
const args = parseArgs(process.argv.slice(2));
|
|
414
|
+
if (args.version) {
|
|
415
|
+
process.stdout.write(`${getVersion()}\n`);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
442
418
|
if (args.help) {
|
|
443
419
|
process.stdout.write(`${usage}\n`);
|
|
444
420
|
return;
|
|
@@ -452,6 +428,15 @@ const main = () => {
|
|
|
452
428
|
const rulesetName = args.rulesetName || DEFAULT_RULESET_NAME;
|
|
453
429
|
const rulesetFiles = getRulesetFiles(rootDir, args.ruleset, rulesetName);
|
|
454
430
|
const command = args.command ?? "compose";
|
|
431
|
+
const logVerbose = (message) => {
|
|
432
|
+
if (args.verbose) {
|
|
433
|
+
process.stdout.write(`${message}\n`);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
logVerbose("Verbose:");
|
|
437
|
+
logVerbose(`- Root: ${rootDir}`);
|
|
438
|
+
logVerbose(`- Ruleset name: ${rulesetName}`);
|
|
439
|
+
logVerbose(`- Ruleset files:\n${rulesetFiles.map((file) => ` - ${normalizePath(path.relative(rootDir, file))}`).join("\n")}`);
|
|
455
440
|
if (command === "edit-rules") {
|
|
456
441
|
const rulesetPath = ensureSingleRuleset(rulesetFiles, rootDir, rulesetName);
|
|
457
442
|
const rulesetDir = path.dirname(rulesetPath);
|
|
@@ -473,7 +458,8 @@ const main = () => {
|
|
|
473
458
|
return;
|
|
474
459
|
}
|
|
475
460
|
if (rulesetFiles.length === 0) {
|
|
476
|
-
|
|
461
|
+
const expectedPath = normalizePath(path.join(rootDir, rulesetName));
|
|
462
|
+
throw new Error(`Missing ruleset file: ${expectedPath}`);
|
|
477
463
|
}
|
|
478
464
|
const outputs = rulesetFiles
|
|
479
465
|
.sort()
|
package/package.json
CHANGED
package/tools/tool-rules.md
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# Tool Rules (compose-agentsmd)
|
|
2
2
|
- Before starting any work, run `compose-agentsmd` from the project root.
|
|
3
3
|
- To update shared rules, run `compose-agentsmd edit-rules`, edit the workspace rules, then run `compose-agentsmd apply-rules`.
|
|
4
|
-
- Do not edit `AGENTS.md` directly; update the source rules and regenerate.
|
|
4
|
+
- Do not edit `AGENTS.md` directly; update the source rules and regenerate.
|
|
5
|
+
- When updating rules, include a detailed summary of what changed (added/removed/modified items) in the final response.
|
package/tools/usage.txt
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
Usage: compose-agentsmd [edit-rules|apply-rules] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--refresh] [--clear-cache]
|
|
1
|
+
Usage: compose-agentsmd [edit-rules|apply-rules] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--refresh] [--clear-cache] [--version|-V] [--verbose|-v] [--help|-h]
|
|
2
2
|
|
|
3
3
|
Options:
|
|
4
|
+
--help, -h Show help and exit
|
|
5
|
+
--version, -V Show version and exit
|
|
6
|
+
--verbose, -v Show verbose diagnostics
|
|
4
7
|
--root <path> Project root directory (default: current working directory)
|
|
5
8
|
--ruleset <path> Only compose a single ruleset file
|
|
6
|
-
--ruleset-name <name> Ruleset filename
|
|
9
|
+
--ruleset-name <name> Ruleset filename in the project root (default: agent-ruleset.json)
|
|
7
10
|
--refresh Refresh cached remote rules
|
|
8
|
-
--clear-cache Remove cached remote rules and exit
|
|
11
|
+
--clear-cache Remove cached remote rules and exit
|