compose-agentsmd 3.2.3 → 3.2.5
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 +8 -1
- package/dist/compose-agents.js +76 -44
- package/package.json +1 -1
- package/tools/tool-rules.md +4 -0
- package/tools/usage.txt +3 -1
package/README.md
CHANGED
|
@@ -134,4 +134,11 @@ npm install
|
|
|
134
134
|
npm run lint
|
|
135
135
|
npm run build
|
|
136
136
|
npm test
|
|
137
|
-
```
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Overview
|
|
140
|
+
This repository contains the compose-agentsmd project.
|
|
141
|
+
|
|
142
|
+
## Requirements and Configuration
|
|
143
|
+
- No required environment variables are documented.
|
|
144
|
+
|
package/dist/compose-agents.js
CHANGED
|
@@ -16,6 +16,13 @@ const RULESET_SCHEMA_PATH = new URL("../agent-ruleset.schema.json", import.meta.
|
|
|
16
16
|
const PACKAGE_JSON_PATH = new URL("../package.json", import.meta.url);
|
|
17
17
|
const TOOL_RULES_PATH = new URL("../tools/tool-rules.md", import.meta.url);
|
|
18
18
|
const USAGE_PATH = new URL("../tools/usage.txt", import.meta.url);
|
|
19
|
+
const readValueArg = (remaining, index, flag) => {
|
|
20
|
+
const value = remaining[index + 1];
|
|
21
|
+
if (!value) {
|
|
22
|
+
throw new Error(`Missing value for ${flag}`);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
};
|
|
19
26
|
const parseArgs = (argv) => {
|
|
20
27
|
const args = {};
|
|
21
28
|
const knownCommands = new Set(["edit-rules", "apply-rules", "init"]);
|
|
@@ -37,29 +44,28 @@ const parseArgs = (argv) => {
|
|
|
37
44
|
args.verbose = true;
|
|
38
45
|
continue;
|
|
39
46
|
}
|
|
47
|
+
if (arg === "--quiet" || arg === "-q") {
|
|
48
|
+
args.quiet = true;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (arg === "--json") {
|
|
52
|
+
args.json = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
40
55
|
if (arg === "--root") {
|
|
41
|
-
const value = remaining
|
|
42
|
-
if (!value) {
|
|
43
|
-
throw new Error("Missing value for --root");
|
|
44
|
-
}
|
|
56
|
+
const value = readValueArg(remaining, i, "--root");
|
|
45
57
|
args.root = value;
|
|
46
58
|
i += 1;
|
|
47
59
|
continue;
|
|
48
60
|
}
|
|
49
61
|
if (arg === "--ruleset") {
|
|
50
|
-
const value = remaining
|
|
51
|
-
if (!value) {
|
|
52
|
-
throw new Error("Missing value for --ruleset");
|
|
53
|
-
}
|
|
62
|
+
const value = readValueArg(remaining, i, "--ruleset");
|
|
54
63
|
args.ruleset = value;
|
|
55
64
|
i += 1;
|
|
56
65
|
continue;
|
|
57
66
|
}
|
|
58
67
|
if (arg === "--ruleset-name") {
|
|
59
|
-
const value = remaining
|
|
60
|
-
if (!value) {
|
|
61
|
-
throw new Error("Missing value for --ruleset-name");
|
|
62
|
-
}
|
|
68
|
+
const value = readValueArg(remaining, i, "--ruleset-name");
|
|
63
69
|
args.rulesetName = value;
|
|
64
70
|
i += 1;
|
|
65
71
|
continue;
|
|
@@ -73,19 +79,13 @@ const parseArgs = (argv) => {
|
|
|
73
79
|
continue;
|
|
74
80
|
}
|
|
75
81
|
if (arg === "--source") {
|
|
76
|
-
const value = remaining
|
|
77
|
-
if (!value) {
|
|
78
|
-
throw new Error("Missing value for --source");
|
|
79
|
-
}
|
|
82
|
+
const value = readValueArg(remaining, i, "--source");
|
|
80
83
|
args.source = value;
|
|
81
84
|
i += 1;
|
|
82
85
|
continue;
|
|
83
86
|
}
|
|
84
87
|
if (arg === "--domains") {
|
|
85
|
-
const value = remaining
|
|
86
|
-
if (!value) {
|
|
87
|
-
throw new Error("Missing value for --domains");
|
|
88
|
-
}
|
|
88
|
+
const value = readValueArg(remaining, i, "--domains");
|
|
89
89
|
args.domains = [...(args.domains ?? []), ...value.split(",").map((entry) => entry.trim())];
|
|
90
90
|
i += 1;
|
|
91
91
|
continue;
|
|
@@ -95,10 +95,7 @@ const parseArgs = (argv) => {
|
|
|
95
95
|
continue;
|
|
96
96
|
}
|
|
97
97
|
if (arg === "--extra") {
|
|
98
|
-
const value = remaining
|
|
99
|
-
if (!value) {
|
|
100
|
-
throw new Error("Missing value for --extra");
|
|
101
|
-
}
|
|
98
|
+
const value = readValueArg(remaining, i, "--extra");
|
|
102
99
|
args.extra = [...(args.extra ?? []), ...value.split(",").map((entry) => entry.trim())];
|
|
103
100
|
i += 1;
|
|
104
101
|
continue;
|
|
@@ -108,10 +105,7 @@ const parseArgs = (argv) => {
|
|
|
108
105
|
continue;
|
|
109
106
|
}
|
|
110
107
|
if (arg === "--output") {
|
|
111
|
-
const value = remaining
|
|
112
|
-
if (!value) {
|
|
113
|
-
throw new Error("Missing value for --output");
|
|
114
|
-
}
|
|
108
|
+
const value = readValueArg(remaining, i, "--output");
|
|
115
109
|
args.output = value;
|
|
116
110
|
i += 1;
|
|
117
111
|
continue;
|
|
@@ -550,8 +544,10 @@ const composeRuleset = (rulesetPath, rootDir, options) => {
|
|
|
550
544
|
const lintHeader = "<!-- markdownlint-disable MD025 -->";
|
|
551
545
|
const toolRules = normalizeTrailingWhitespace(TOOL_RULES);
|
|
552
546
|
const output = `${lintHeader}\n${[toolRules, ...parts].join("\n\n")}\n`;
|
|
553
|
-
|
|
554
|
-
|
|
547
|
+
if (!options.dryRun) {
|
|
548
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
549
|
+
fs.writeFileSync(outputPath, output, "utf8");
|
|
550
|
+
}
|
|
555
551
|
return normalizePath(path.relative(rootDir, outputPath));
|
|
556
552
|
};
|
|
557
553
|
const LOCAL_RULES_TEMPLATE = "# Local Rules\n\n- Add project-specific instructions here.\n";
|
|
@@ -655,9 +651,22 @@ const initProject = async (args, rootDir, rulesetName) => {
|
|
|
655
651
|
plan.push({ action: "create", path: outputPath });
|
|
656
652
|
}
|
|
657
653
|
}
|
|
658
|
-
|
|
654
|
+
if (!args.quiet && !args.json) {
|
|
655
|
+
process.stdout.write(formatPlan(plan, rootDir));
|
|
656
|
+
}
|
|
659
657
|
if (args.dryRun) {
|
|
660
|
-
|
|
658
|
+
if (args.json) {
|
|
659
|
+
process.stdout.write(JSON.stringify({
|
|
660
|
+
dryRun: true,
|
|
661
|
+
plan: plan.map((item) => ({
|
|
662
|
+
action: item.action,
|
|
663
|
+
path: normalizePath(path.relative(rootDir, item.path))
|
|
664
|
+
}))
|
|
665
|
+
}, null, 2) + "\n");
|
|
666
|
+
}
|
|
667
|
+
else if (!args.quiet) {
|
|
668
|
+
process.stdout.write("Dry run: no changes made.\n");
|
|
669
|
+
}
|
|
661
670
|
return;
|
|
662
671
|
}
|
|
663
672
|
await confirmInit(args);
|
|
@@ -667,15 +676,28 @@ const initProject = async (args, rootDir, rulesetName) => {
|
|
|
667
676
|
fs.mkdirSync(path.dirname(extraPath), { recursive: true });
|
|
668
677
|
fs.writeFileSync(extraPath, LOCAL_RULES_TEMPLATE, "utf8");
|
|
669
678
|
}
|
|
670
|
-
|
|
671
|
-
if (extraToWrite.length > 0) {
|
|
672
|
-
process.stdout.write(`Initialized local rules:\n${extraToWrite
|
|
673
|
-
.map((filePath) => `- ${normalizePath(path.relative(rootDir, filePath))}`)
|
|
674
|
-
.join("\n")}\n`);
|
|
675
|
-
}
|
|
679
|
+
let composedOutput;
|
|
676
680
|
if (args.compose) {
|
|
677
|
-
|
|
678
|
-
|
|
681
|
+
composedOutput = composeRuleset(rulesetPath, rootDir, { refresh: args.refresh ?? false });
|
|
682
|
+
}
|
|
683
|
+
if (args.json) {
|
|
684
|
+
process.stdout.write(JSON.stringify({
|
|
685
|
+
initialized: [normalizePath(path.relative(rootDir, rulesetPath))],
|
|
686
|
+
localRules: extraToWrite.map((filePath) => normalizePath(path.relative(rootDir, filePath))),
|
|
687
|
+
composed: composedOutput ? [composedOutput] : [],
|
|
688
|
+
dryRun: false
|
|
689
|
+
}, null, 2) + "\n");
|
|
690
|
+
}
|
|
691
|
+
else if (!args.quiet) {
|
|
692
|
+
process.stdout.write(`Initialized ruleset:\n- ${normalizePath(path.relative(rootDir, rulesetPath))}\n`);
|
|
693
|
+
if (extraToWrite.length > 0) {
|
|
694
|
+
process.stdout.write(`Initialized local rules:\n${extraToWrite
|
|
695
|
+
.map((filePath) => `- ${normalizePath(path.relative(rootDir, filePath))}`)
|
|
696
|
+
.join("\n")}\n`);
|
|
697
|
+
}
|
|
698
|
+
if (composedOutput) {
|
|
699
|
+
process.stdout.write(`Composed AGENTS.md:\n- ${composedOutput}\n`);
|
|
700
|
+
}
|
|
679
701
|
}
|
|
680
702
|
};
|
|
681
703
|
const getRulesetFiles = (rootDir, specificRuleset, rulesetName) => {
|
|
@@ -745,8 +767,13 @@ const main = async () => {
|
|
|
745
767
|
const rulesetDir = path.dirname(rulesetPath);
|
|
746
768
|
const ruleset = readProjectRuleset(rulesetPath);
|
|
747
769
|
applyRulesFromWorkspace(rulesetDir, ruleset.source);
|
|
748
|
-
const output = composeRuleset(rulesetPath, rootDir, { refresh: true });
|
|
749
|
-
|
|
770
|
+
const output = composeRuleset(rulesetPath, rootDir, { refresh: true, dryRun: args.dryRun });
|
|
771
|
+
if (args.json) {
|
|
772
|
+
process.stdout.write(JSON.stringify({ composed: [output], dryRun: !!args.dryRun }, null, 2) + "\n");
|
|
773
|
+
}
|
|
774
|
+
else if (!args.quiet) {
|
|
775
|
+
process.stdout.write(`Composed AGENTS.md:\n- ${output}\n`);
|
|
776
|
+
}
|
|
750
777
|
return;
|
|
751
778
|
}
|
|
752
779
|
if (rulesetFiles.length === 0) {
|
|
@@ -755,8 +782,13 @@ const main = async () => {
|
|
|
755
782
|
}
|
|
756
783
|
const outputs = rulesetFiles
|
|
757
784
|
.sort()
|
|
758
|
-
.map((rulesetPath) => composeRuleset(rulesetPath, rootDir, { refresh: args.refresh }));
|
|
759
|
-
|
|
785
|
+
.map((rulesetPath) => composeRuleset(rulesetPath, rootDir, { refresh: args.refresh, dryRun: args.dryRun }));
|
|
786
|
+
if (args.json) {
|
|
787
|
+
process.stdout.write(JSON.stringify({ composed: outputs, dryRun: !!args.dryRun }, null, 2) + "\n");
|
|
788
|
+
}
|
|
789
|
+
else if (!args.quiet) {
|
|
790
|
+
process.stdout.write(`Composed AGENTS.md:\n${outputs.map((file) => `- ${file}`).join("\n")}\n`);
|
|
791
|
+
}
|
|
760
792
|
};
|
|
761
793
|
const run = async () => {
|
|
762
794
|
try {
|
package/package.json
CHANGED
package/tools/tool-rules.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# Tool Rules (compose-agentsmd)
|
|
2
2
|
- Before starting any work, run `compose-agentsmd` from the project root.
|
|
3
|
+
- `compose-agentsmd` intentionally regenerates `AGENTS.md`; any resulting `AGENTS.md` diff is expected and must not be treated as an unexpected external change.
|
|
4
|
+
- If `compose-agentsmd` is not available, install it via npm: `npm install -g compose-agentsmd`.
|
|
3
5
|
- To update shared rules, run `compose-agentsmd edit-rules`, edit the workspace rules, then run `compose-agentsmd apply-rules`.
|
|
4
6
|
- Do not edit `AGENTS.md` directly; update the source rules and regenerate.
|
|
7
|
+
- `tools/tool-rules.md` is the shared rule source for all repositories that use compose-agentsmd.
|
|
8
|
+
- Before applying any rule updates, present the planned changes first (prefer a colorized diff-style preview), ask for explicit approval, then make the edits.
|
|
5
9
|
- These tool rules live in tools/tool-rules.md in the compose-agentsmd repository; do not duplicate them in global rule modules.
|
|
6
10
|
- When updating rules, include a colorized diff-style summary in the final response. Use `git diff --stat` first, then include the raw ANSI-colored output of `git diff --color=always` (no sanitizing or reformatting), and limit the output to the rule files that changed.
|
|
7
11
|
- Also provide a short, copy-pasteable command the user can run to view the diff in the same format. Use absolute paths so it works regardless of the current working directory, and scope it to the changed rule files.
|
package/tools/usage.txt
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
Usage: compose-agentsmd [edit-rules|apply-rules|init] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--source <source>] [--domains <list>] [--extra <list>] [--output <file>] [--no-domains] [--no-extra] [--no-global] [--compose] [--dry-run] [--yes] [--force] [--refresh] [--clear-cache] [--version|-V] [--verbose|-v] [--help|-h]
|
|
1
|
+
Usage: compose-agentsmd [edit-rules|apply-rules|init] [--root <path>] [--ruleset <path>] [--ruleset-name <name>] [--source <source>] [--domains <list>] [--extra <list>] [--output <file>] [--no-domains] [--no-extra] [--no-global] [--compose] [--dry-run] [--yes] [--force] [--refresh] [--clear-cache] [--version|-V] [--verbose|-v] [--quiet|-q] [--json] [--help|-h]
|
|
2
2
|
|
|
3
3
|
Options:
|
|
4
4
|
--help, -h Show help and exit
|
|
5
5
|
--version, -V Show version and exit
|
|
6
6
|
--verbose, -v Show verbose diagnostics
|
|
7
|
+
--quiet, -q Suppress non-error human-readable output (JSON output is not suppressed)
|
|
8
|
+
--json Output machine-readable JSON (takes precedence over --quiet)
|
|
7
9
|
--root <path> Project root directory (default: current working directory)
|
|
8
10
|
--ruleset <path> Only compose a single ruleset file
|
|
9
11
|
--ruleset-name <name> Ruleset filename in the project root (default: agent-ruleset.json)
|