@googlarz/agents-sync 1.4.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/LICENSE +21 -0
- package/README.md +507 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +267 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/loader.d.ts +9 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +55 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +69 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +33 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/derivers/aider.d.ts +19 -0
- package/dist/derivers/aider.d.ts.map +1 -0
- package/dist/derivers/aider.js +117 -0
- package/dist/derivers/aider.js.map +1 -0
- package/dist/derivers/claude.d.ts +19 -0
- package/dist/derivers/claude.d.ts.map +1 -0
- package/dist/derivers/claude.js +93 -0
- package/dist/derivers/claude.js.map +1 -0
- package/dist/derivers/cline.d.ts +17 -0
- package/dist/derivers/cline.d.ts.map +1 -0
- package/dist/derivers/cline.js +92 -0
- package/dist/derivers/cline.js.map +1 -0
- package/dist/derivers/copilot.d.ts +16 -0
- package/dist/derivers/copilot.d.ts.map +1 -0
- package/dist/derivers/copilot.js +162 -0
- package/dist/derivers/copilot.js.map +1 -0
- package/dist/derivers/cursor.d.ts +16 -0
- package/dist/derivers/cursor.d.ts.map +1 -0
- package/dist/derivers/cursor.js +121 -0
- package/dist/derivers/cursor.js.map +1 -0
- package/dist/derivers/gemini.d.ts +19 -0
- package/dist/derivers/gemini.d.ts.map +1 -0
- package/dist/derivers/gemini.js +33 -0
- package/dist/derivers/gemini.js.map +1 -0
- package/dist/derivers/index.d.ts +33 -0
- package/dist/derivers/index.d.ts.map +1 -0
- package/dist/derivers/index.js +134 -0
- package/dist/derivers/index.js.map +1 -0
- package/dist/derivers/merger.d.ts +36 -0
- package/dist/derivers/merger.d.ts.map +1 -0
- package/dist/derivers/merger.js +83 -0
- package/dist/derivers/merger.js.map +1 -0
- package/dist/derivers/roo.d.ts +18 -0
- package/dist/derivers/roo.d.ts.map +1 -0
- package/dist/derivers/roo.js +92 -0
- package/dist/derivers/roo.js.map +1 -0
- package/dist/derivers/windsurf.d.ts +16 -0
- package/dist/derivers/windsurf.d.ts.map +1 -0
- package/dist/derivers/windsurf.js +91 -0
- package/dist/derivers/windsurf.js.map +1 -0
- package/dist/extractor/extractor.d.ts +4 -0
- package/dist/extractor/extractor.d.ts.map +1 -0
- package/dist/extractor/extractor.js +125 -0
- package/dist/extractor/extractor.js.map +1 -0
- package/dist/extractor/schema.d.ts +187 -0
- package/dist/extractor/schema.d.ts.map +1 -0
- package/dist/extractor/schema.js +44 -0
- package/dist/extractor/schema.js.map +1 -0
- package/dist/generator/agents-md.d.ts +6 -0
- package/dist/generator/agents-md.d.ts.map +1 -0
- package/dist/generator/agents-md.js +135 -0
- package/dist/generator/agents-md.js.map +1 -0
- package/dist/generator/validator.d.ts +7 -0
- package/dist/generator/validator.d.ts.map +1 -0
- package/dist/generator/validator.js +67 -0
- package/dist/generator/validator.js.map +1 -0
- package/dist/lib/claude-client.d.ts +11 -0
- package/dist/lib/claude-client.d.ts.map +1 -0
- package/dist/lib/claude-client.js +74 -0
- package/dist/lib/claude-client.js.map +1 -0
- package/dist/lib/errors.d.ts +10 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +27 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/file-utils.d.ts +7 -0
- package/dist/lib/file-utils.d.ts.map +1 -0
- package/dist/lib/file-utils.js +56 -0
- package/dist/lib/file-utils.js.map +1 -0
- package/dist/lib/token-estimate.d.ts +7 -0
- package/dist/lib/token-estimate.d.ts.map +1 -0
- package/dist/lib/token-estimate.js +15 -0
- package/dist/lib/token-estimate.js.map +1 -0
- package/dist/scanner/codegraph.d.ts +13 -0
- package/dist/scanner/codegraph.d.ts.map +1 -0
- package/dist/scanner/codegraph.js +65 -0
- package/dist/scanner/codegraph.js.map +1 -0
- package/dist/scanner/docs.d.ts +13 -0
- package/dist/scanner/docs.d.ts.map +1 -0
- package/dist/scanner/docs.js +63 -0
- package/dist/scanner/docs.js.map +1 -0
- package/dist/scanner/gotchas.d.ts +8 -0
- package/dist/scanner/gotchas.d.ts.map +1 -0
- package/dist/scanner/gotchas.js +107 -0
- package/dist/scanner/gotchas.js.map +1 -0
- package/dist/scanner/index.d.ts +26 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +95 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/manifest.d.ts +13 -0
- package/dist/scanner/manifest.d.ts.map +1 -0
- package/dist/scanner/manifest.js +285 -0
- package/dist/scanner/manifest.js.map +1 -0
- package/dist/scanner/mcp.d.ts +12 -0
- package/dist/scanner/mcp.d.ts.map +1 -0
- package/dist/scanner/mcp.js +96 -0
- package/dist/scanner/mcp.js.map +1 -0
- package/dist/scanner/repomix.d.ts +11 -0
- package/dist/scanner/repomix.d.ts.map +1 -0
- package/dist/scanner/repomix.js +87 -0
- package/dist/scanner/repomix.js.map +1 -0
- package/dist/scanner/skills.d.ts +18 -0
- package/dist/scanner/skills.d.ts.map +1 -0
- package/dist/scanner/skills.js +100 -0
- package/dist/scanner/skills.js.map +1 -0
- package/dist/scanner/source.d.ts +13 -0
- package/dist/scanner/source.d.ts.map +1 -0
- package/dist/scanner/source.js +157 -0
- package/dist/scanner/source.js.map +1 -0
- package/dist/scanner/structure.d.ts +10 -0
- package/dist/scanner/structure.d.ts.map +1 -0
- package/dist/scanner/structure.js +168 -0
- package/dist/scanner/structure.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +245 -0
- package/dist/server.js.map +1 -0
- package/dist/snapshot/drift.d.ts +28 -0
- package/dist/snapshot/drift.d.ts.map +1 -0
- package/dist/snapshot/drift.js +205 -0
- package/dist/snapshot/drift.js.map +1 -0
- package/dist/snapshot/schema.d.ts +94 -0
- package/dist/snapshot/schema.d.ts.map +1 -0
- package/dist/snapshot/schema.js +24 -0
- package/dist/snapshot/schema.js.map +1 -0
- package/dist/snapshot/writer.d.ts +17 -0
- package/dist/snapshot/writer.d.ts.map +1 -0
- package/dist/snapshot/writer.js +44 -0
- package/dist/snapshot/writer.js.map +1 -0
- package/dist/tools/drift.d.ts +15 -0
- package/dist/tools/drift.d.ts.map +1 -0
- package/dist/tools/drift.js +51 -0
- package/dist/tools/drift.js.map +1 -0
- package/dist/tools/export.d.ts +14 -0
- package/dist/tools/export.d.ts.map +1 -0
- package/dist/tools/export.js +53 -0
- package/dist/tools/export.js.map +1 -0
- package/dist/tools/init.d.ts +28 -0
- package/dist/tools/init.d.ts.map +1 -0
- package/dist/tools/init.js +103 -0
- package/dist/tools/init.js.map +1 -0
- package/dist/tools/lint.d.ts +24 -0
- package/dist/tools/lint.d.ts.map +1 -0
- package/dist/tools/lint.js +213 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/scan-report.d.ts +14 -0
- package/dist/tools/scan-report.d.ts.map +1 -0
- package/dist/tools/scan-report.js +136 -0
- package/dist/tools/scan-report.js.map +1 -0
- package/dist/tools/status.d.ts +18 -0
- package/dist/tools/status.d.ts.map +1 -0
- package/dist/tools/status.js +38 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/sync.d.ts +22 -0
- package/dist/tools/sync.d.ts.map +1 -0
- package/dist/tools/sync.js +123 -0
- package/dist/tools/sync.js.map +1 -0
- package/dist/tools/validate.d.ts +22 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +97 -0
- package/dist/tools/validate.js.map +1 -0
- package/docs/agents-md-spec.md +233 -0
- package/docs/examples/.clinerules +29 -0
- package/docs/examples/.cursorrules +19 -0
- package/docs/examples/.windsurfrules +14 -0
- package/docs/examples/AGENTS.md +97 -0
- package/docs/examples/CLAUDE.md +88 -0
- package/docs/examples/GEMINI.md +61 -0
- package/docs/examples/copilot-instructions.md +24 -0
- package/docs/github-action.yml +89 -0
- package/package.json +63 -0
- package/scripts/demo.sh +138 -0
- package/skill/SKILL.md +158 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectCustomBlocks, loadExistingCustomBlocks, loadUnmanagedFileAsCustomBlock } from "./merger.js";
|
|
3
|
+
import { scanProjectSkills, formatSkillsSection } from "../scanner/skills.js";
|
|
4
|
+
const CLAUDE_CODE_SECTION = `---
|
|
5
|
+
|
|
6
|
+
## Claude Code Notes
|
|
7
|
+
|
|
8
|
+
> This file is managed by agents-sync. Edit \`AGENTS.md\` and run \`/agents-sync sync\`.
|
|
9
|
+
|
|
10
|
+
### Tool Files
|
|
11
|
+
- Canonical: \`AGENTS.md\`
|
|
12
|
+
- Cursor: \`.cursorrules\`
|
|
13
|
+
- Copilot: \`.github/copilot-instructions.md\`
|
|
14
|
+
|
|
15
|
+
### Re-sync
|
|
16
|
+
Run \`/agents-sync sync\` after major refactors, new dependencies, or architecture changes.
|
|
17
|
+
Run \`/agents-sync drift\` to check what's changed since last sync.
|
|
18
|
+
`;
|
|
19
|
+
function recommendSkills(metadata) {
|
|
20
|
+
const recs = [];
|
|
21
|
+
const { project, stack, testing } = metadata;
|
|
22
|
+
const lang = project.language.toLowerCase();
|
|
23
|
+
const fw = (project.framework ?? "").toLowerCase();
|
|
24
|
+
const testFw = (testing.framework ?? stack.testing ?? "").toLowerCase();
|
|
25
|
+
const db = (stack.database ?? "").toLowerCase();
|
|
26
|
+
const auth = (stack.auth ?? "").toLowerCase();
|
|
27
|
+
const deploy = (stack.deploy ?? stack.deploy ?? "").toLowerCase();
|
|
28
|
+
// Universal
|
|
29
|
+
recs.push({ slug: "agent-skills:spec-driven-development", reason: "requirements before code" });
|
|
30
|
+
// Testing
|
|
31
|
+
if (testFw || testing.command) {
|
|
32
|
+
recs.push({ slug: "agent-skills:test-driven-development", reason: `${testFw || "tests"} workflow` });
|
|
33
|
+
}
|
|
34
|
+
// Frontend
|
|
35
|
+
if (/next|react|vue|svelte|solid|nuxt|remix|astro/.test(fw)) {
|
|
36
|
+
recs.push({ slug: "agent-skills:frontend-ui-engineering", reason: `${fw} UI work` });
|
|
37
|
+
}
|
|
38
|
+
// API / backend
|
|
39
|
+
if (/express|fastify|hono|django|fastapi|flask|axum|gin|echo/.test(fw) || /api|server|backend/.test(project.description?.toLowerCase() ?? "")) {
|
|
40
|
+
recs.push({ slug: "agent-skills:api-and-interface-design", reason: "API design" });
|
|
41
|
+
}
|
|
42
|
+
// Security-sensitive
|
|
43
|
+
if (auth || /payment|stripe|billing|oauth|jwt|session/.test([db, stack.other.join(" ")].join(" ").toLowerCase())) {
|
|
44
|
+
recs.push({ slug: "agent-skills:security-and-hardening", reason: "auth/payments in stack" });
|
|
45
|
+
}
|
|
46
|
+
// Observability — deploy target present
|
|
47
|
+
if (deploy) {
|
|
48
|
+
recs.push({ slug: "agent-skills:observability-and-monitoring", reason: `${deploy} deployment` });
|
|
49
|
+
}
|
|
50
|
+
// TypeScript-specific
|
|
51
|
+
if (lang === "typescript") {
|
|
52
|
+
recs.push({ slug: "agent-skills:code-review-and-quality", reason: "TypeScript quality gates" });
|
|
53
|
+
}
|
|
54
|
+
// Deduplicate by slug
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
return recs.filter((r) => {
|
|
57
|
+
if (seen.has(r.slug))
|
|
58
|
+
return false;
|
|
59
|
+
seen.add(r.slug);
|
|
60
|
+
return true;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Derives the full content for CLAUDE.md.
|
|
65
|
+
*
|
|
66
|
+
* Content = canonical AGENTS.md + Claude Code-specific section.
|
|
67
|
+
* If preserveCustom is true (default) any existing custom blocks from the
|
|
68
|
+
* current CLAUDE.md are appended after the generated body.
|
|
69
|
+
*
|
|
70
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
71
|
+
*/
|
|
72
|
+
export async function deriveClaudeMd(options) {
|
|
73
|
+
const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
|
|
74
|
+
const skillsSummary = await scanProjectSkills(projectPath);
|
|
75
|
+
const skillsSection = formatSkillsSection(skillsSummary);
|
|
76
|
+
const skillsBlock = skillsSection ? `\n${skillsSection}\n` : "";
|
|
77
|
+
const recs = recommendSkills(metadata);
|
|
78
|
+
const recsBlock = recs.length > 0
|
|
79
|
+
? `\n## Recommended Skills\n\n${recs.map((r) => `- \`/${r.slug}\` — ${r.reason}`).join("\n")}\n`
|
|
80
|
+
: "";
|
|
81
|
+
const generated = `${agentsMdContent.trimEnd()}${skillsBlock}${recsBlock}\n${CLAUDE_CODE_SECTION}`;
|
|
82
|
+
if (!preserveCustom)
|
|
83
|
+
return generated;
|
|
84
|
+
const claudeMdPath = path.join(projectPath, "CLAUDE.md");
|
|
85
|
+
// Preserve managed custom blocks first; fall back to wrapping the whole
|
|
86
|
+
// file if it exists but was never managed by agents-sync.
|
|
87
|
+
const existingBlocks = await loadExistingCustomBlocks(claudeMdPath);
|
|
88
|
+
const blocks = existingBlocks.length > 0
|
|
89
|
+
? existingBlocks
|
|
90
|
+
: await loadUnmanagedFileAsCustomBlock(claudeMdPath);
|
|
91
|
+
return injectCustomBlocks(generated, blocks);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/derivers/claude.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAU9E,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;CAc3B,CAAC;AAIF,SAAS,eAAe,CAAC,QAAyB;IAChD,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACxE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAElE,YAAY;IACZ,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sCAAsC,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAEhG,UAAU;IACV,IAAI,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QAC9B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sCAAsC,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,OAAO,WAAW,EAAE,CAAC,CAAC;IACvG,CAAC;IAED,WAAW;IACX,IAAI,8CAA8C,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sCAAsC,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IACvF,CAAC;IAED,gBAAgB;IAChB,IAAI,yDAAyD,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAC9I,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,uCAAuC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;IACrF,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI,IAAI,0CAA0C,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QACjH,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,qCAAqC,EAAE,MAAM,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,wCAAwC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,2CAA2C,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,EAAE,CAAC,CAAC;IACnG,CAAC;IAED,sBAAsB;IACtB,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sCAAsC,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAAC;IAClG,CAAC;IAED,sBAAsB;IACtB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACnC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgC;IACnE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAElF,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,aAAa,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhE,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC;QAC/B,CAAC,CAAC,8BAA8B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAChG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,SAAS,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,GAAG,WAAW,GAAG,SAAS,KAAK,mBAAmB,EAAE,CAAC;IAEnG,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAEtC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACzD,wEAAwE;IACxE,0DAA0D;IAC1D,MAAM,cAAc,GAAG,MAAM,wBAAwB,CAAC,YAAY,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,MAAM,8BAA8B,CAAC,YAAY,CAAC,CAAC;IAEvD,OAAO,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ProjectMetadata } from "../extractor/schema.js";
|
|
2
|
+
export interface ClineDerivationOptions {
|
|
3
|
+
projectPath: string;
|
|
4
|
+
agentsMdContent: string;
|
|
5
|
+
metadata: ProjectMetadata;
|
|
6
|
+
/** @default true */
|
|
7
|
+
preserveCustom?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derives `.clinerules` content from AGENTS.md + metadata.
|
|
11
|
+
* Cline reads this file for project-specific AI instructions.
|
|
12
|
+
* Target < 400 words.
|
|
13
|
+
*
|
|
14
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
15
|
+
*/
|
|
16
|
+
export declare function deriveClineRules(options: ClineDerivationOptions): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=cline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cline.d.ts","sourceRoot":"","sources":["../../src/derivers/cline.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyCD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiEvF"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
|
|
3
|
+
function escapeRegExp(s) {
|
|
4
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5
|
+
}
|
|
6
|
+
function extractSection(content, heading) {
|
|
7
|
+
const re = new RegExp(`^##\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^##\\s|$)`, "mi");
|
|
8
|
+
const match = re.exec(content);
|
|
9
|
+
return match ? match[1].trim() : "";
|
|
10
|
+
}
|
|
11
|
+
function extractSubSection(content, heading) {
|
|
12
|
+
const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
|
|
13
|
+
const match = re.exec(content);
|
|
14
|
+
return match ? match[1].trim() : "";
|
|
15
|
+
}
|
|
16
|
+
function sectionToLines(text) {
|
|
17
|
+
return text
|
|
18
|
+
.split("\n")
|
|
19
|
+
.map((l) => l.replace(/^[\s\-*>]+/, "").trim())
|
|
20
|
+
.filter((l) => l.length > 0);
|
|
21
|
+
}
|
|
22
|
+
function deduplicateLines(items) {
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
return items.filter((item) => {
|
|
25
|
+
const key = item.toLowerCase().trim();
|
|
26
|
+
if (seen.has(key))
|
|
27
|
+
return false;
|
|
28
|
+
seen.add(key);
|
|
29
|
+
return true;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Derives `.clinerules` content from AGENTS.md + metadata.
|
|
34
|
+
* Cline reads this file for project-specific AI instructions.
|
|
35
|
+
* Target < 400 words.
|
|
36
|
+
*
|
|
37
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
38
|
+
*/
|
|
39
|
+
export async function deriveClineRules(options) {
|
|
40
|
+
const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
|
|
41
|
+
const { project, conventions: metaConventions, gotchas: metaGotchas, boundaries, testing } = metadata;
|
|
42
|
+
const conventionsSection = sectionToLines(extractSection(agentsMdContent, "Conventions"));
|
|
43
|
+
const gotchasSection = sectionToLines(extractSection(agentsMdContent, "Gotchas"));
|
|
44
|
+
const neverSection = sectionToLines(extractSubSection(agentsMdContent, "Never"));
|
|
45
|
+
const allConventions = deduplicateLines([...metaConventions, ...conventionsSection]);
|
|
46
|
+
const allGotchas = deduplicateLines([...metaGotchas, ...gotchasSection]);
|
|
47
|
+
const allNever = deduplicateLines([...boundaries.never, ...neverSection]);
|
|
48
|
+
const lines = [];
|
|
49
|
+
const fwPart = project.framework ? ` / ${project.framework}` : "";
|
|
50
|
+
lines.push(`# .clinerules — managed by agents-sync`);
|
|
51
|
+
lines.push(`# Language: ${project.language}${fwPart}`);
|
|
52
|
+
lines.push("");
|
|
53
|
+
if (allConventions.length > 0) {
|
|
54
|
+
lines.push("## Conventions");
|
|
55
|
+
for (const rule of allConventions) {
|
|
56
|
+
lines.push(`- ${rule}`);
|
|
57
|
+
}
|
|
58
|
+
lines.push("");
|
|
59
|
+
}
|
|
60
|
+
if (allGotchas.length > 0) {
|
|
61
|
+
lines.push("## Gotchas");
|
|
62
|
+
for (const gotcha of allGotchas) {
|
|
63
|
+
lines.push(`- ${gotcha}`);
|
|
64
|
+
}
|
|
65
|
+
lines.push("");
|
|
66
|
+
}
|
|
67
|
+
if (allNever.length > 0) {
|
|
68
|
+
lines.push("## Never");
|
|
69
|
+
for (const rule of allNever) {
|
|
70
|
+
lines.push(`- ${rule}`);
|
|
71
|
+
}
|
|
72
|
+
lines.push("");
|
|
73
|
+
}
|
|
74
|
+
if (boundaries.alwaysDo.length > 0) {
|
|
75
|
+
lines.push("## Always");
|
|
76
|
+
for (const rule of boundaries.alwaysDo) {
|
|
77
|
+
lines.push(`- ${rule}`);
|
|
78
|
+
}
|
|
79
|
+
lines.push("");
|
|
80
|
+
}
|
|
81
|
+
if (testing.command) {
|
|
82
|
+
lines.push(`**Tests:** \`${testing.command}\``);
|
|
83
|
+
lines.push("");
|
|
84
|
+
}
|
|
85
|
+
const generated = lines.join("\n").trimEnd() + "\n";
|
|
86
|
+
if (!preserveCustom)
|
|
87
|
+
return generated;
|
|
88
|
+
const clinePath = path.join(projectPath, ".clinerules");
|
|
89
|
+
const existingBlocks = await loadExistingCustomBlocks(clinePath);
|
|
90
|
+
return injectCustomBlocks(generated, existingBlocks);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=cline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cline.js","sourceRoot":"","sources":["../../src/derivers/cline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProjectMetadata } from "../extractor/schema.js";
|
|
2
|
+
export interface CopilotDerivationOptions {
|
|
3
|
+
projectPath: string;
|
|
4
|
+
agentsMdContent: string;
|
|
5
|
+
metadata: ProjectMetadata;
|
|
6
|
+
/** @default true */
|
|
7
|
+
preserveCustom?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derives `.github/copilot-instructions.md` content from AGENTS.md + metadata.
|
|
11
|
+
* Focuses strictly on inline code-generation context — target < 300 words.
|
|
12
|
+
*
|
|
13
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deriveCopilotInstructions(options: CopilotDerivationOptions): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=copilot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../src/derivers/copilot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAyGD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,MAAM,CAAC,CA4EjB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Framework-specific hints
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/**
|
|
7
|
+
* Maps known framework names to inline code-generation hints.
|
|
8
|
+
* Keeps it short — only things that meaningfully affect completion quality.
|
|
9
|
+
*/
|
|
10
|
+
const FRAMEWORK_HINTS = {
|
|
11
|
+
nextjs: "prefer Server Components; use `'use client'` only when necessary",
|
|
12
|
+
"next.js": "prefer Server Components; use `'use client'` only when necessary",
|
|
13
|
+
react: "functional components only; hooks over class components",
|
|
14
|
+
django: "use async views where possible; prefer class-based views for CRUD",
|
|
15
|
+
fastapi: "async endpoints; pydantic models for all request/response shapes",
|
|
16
|
+
express: "async route handlers; centralise error handling via middleware",
|
|
17
|
+
axum: "use `#[axum::debug_handler]` during development; prefer extractors",
|
|
18
|
+
flask: "use blueprints; prefer `current_app` over global state",
|
|
19
|
+
nuxt: "use `<script setup lang='ts'>`; prefer composables over options API",
|
|
20
|
+
vue: "use Composition API with `<script setup>`; TypeScript by default",
|
|
21
|
+
angular: "standalone components preferred; inject via `inject()` function",
|
|
22
|
+
svelte: "prefer `$state` runes (Svelte 5); avoid legacy reactive statements",
|
|
23
|
+
remix: "loaders and actions for all data; avoid client-side fetching",
|
|
24
|
+
nestjs: "dependency injection everywhere; DTOs with class-validator decorators",
|
|
25
|
+
};
|
|
26
|
+
function frameworkHint(framework) {
|
|
27
|
+
if (!framework)
|
|
28
|
+
return null;
|
|
29
|
+
const key = framework.toLowerCase();
|
|
30
|
+
return FRAMEWORK_HINTS[key] ?? null;
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Parsing helpers (minimal — only what copilot needs)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
function escapeRegExp(s) {
|
|
36
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
37
|
+
}
|
|
38
|
+
function extractSubSection(content, heading) {
|
|
39
|
+
const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
|
|
40
|
+
const match = re.exec(content);
|
|
41
|
+
return match ? match[1].trim() : "";
|
|
42
|
+
}
|
|
43
|
+
function sectionToLines(text) {
|
|
44
|
+
return text
|
|
45
|
+
.split("\n")
|
|
46
|
+
.map((l) => l.replace(/^[\s\-*>]+/, "").trim())
|
|
47
|
+
.filter((l) => l.length > 0);
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Convention filters — keep only lines relevant to code-level suggestions
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
const CODE_LEVEL_KEYWORDS = [
|
|
53
|
+
"import",
|
|
54
|
+
"export",
|
|
55
|
+
"naming",
|
|
56
|
+
"filename",
|
|
57
|
+
"file name",
|
|
58
|
+
"type",
|
|
59
|
+
"interface",
|
|
60
|
+
"async",
|
|
61
|
+
"await",
|
|
62
|
+
"module",
|
|
63
|
+
"esm",
|
|
64
|
+
"cjs",
|
|
65
|
+
"require",
|
|
66
|
+
"class",
|
|
67
|
+
"function",
|
|
68
|
+
"const ",
|
|
69
|
+
"let ",
|
|
70
|
+
"var ",
|
|
71
|
+
"enum",
|
|
72
|
+
"generic",
|
|
73
|
+
"zod",
|
|
74
|
+
"schema",
|
|
75
|
+
"validation",
|
|
76
|
+
"null",
|
|
77
|
+
"undefined",
|
|
78
|
+
"error",
|
|
79
|
+
"throw",
|
|
80
|
+
"return",
|
|
81
|
+
"comment",
|
|
82
|
+
"doc",
|
|
83
|
+
"format",
|
|
84
|
+
"lint",
|
|
85
|
+
];
|
|
86
|
+
function isCodeLevel(rule) {
|
|
87
|
+
const lower = rule.toLowerCase();
|
|
88
|
+
return CODE_LEVEL_KEYWORDS.some((kw) => lower.includes(kw));
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Deriver
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
/**
|
|
94
|
+
* Derives `.github/copilot-instructions.md` content from AGENTS.md + metadata.
|
|
95
|
+
* Focuses strictly on inline code-generation context — target < 300 words.
|
|
96
|
+
*
|
|
97
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
98
|
+
*/
|
|
99
|
+
export async function deriveCopilotInstructions(options) {
|
|
100
|
+
const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
|
|
101
|
+
const { project, stack, conventions: metaConventions, boundaries, testing } = metadata;
|
|
102
|
+
// Code-level conventions only
|
|
103
|
+
const codeLevelConventions = metaConventions.filter(isCodeLevel);
|
|
104
|
+
// "Never" rules that directly affect code generation (short enough to fit)
|
|
105
|
+
const neverLines = sectionToLines(extractSubSection(agentsMdContent, "Never"));
|
|
106
|
+
const codeNever = [...boundaries.never, ...neverLines]
|
|
107
|
+
.filter(isCodeLevel)
|
|
108
|
+
.slice(0, 6); // hard cap to stay under word budget
|
|
109
|
+
const lines = [];
|
|
110
|
+
// Header
|
|
111
|
+
lines.push("# GitHub Copilot Instructions — managed by agents-sync");
|
|
112
|
+
lines.push("");
|
|
113
|
+
// Language + framework
|
|
114
|
+
const fwPart = project.framework ? ` / ${project.framework}` : "";
|
|
115
|
+
lines.push(`**Stack:** ${project.language}${fwPart}${stack.runtime ? ` (${stack.runtime})` : ""}`);
|
|
116
|
+
lines.push("");
|
|
117
|
+
// Framework-specific hint
|
|
118
|
+
const hint = frameworkHint(project.framework);
|
|
119
|
+
if (hint) {
|
|
120
|
+
lines.push(`**Framework:** ${hint}`);
|
|
121
|
+
lines.push("");
|
|
122
|
+
}
|
|
123
|
+
// Import style — derive from conventions or fall back to language default
|
|
124
|
+
const importConvention = metaConventions.find((c) => c.toLowerCase().includes("import") || c.toLowerCase().includes("esm") || c.toLowerCase().includes("require"));
|
|
125
|
+
if (importConvention) {
|
|
126
|
+
lines.push(`**Imports:** ${importConvention}`);
|
|
127
|
+
lines.push("");
|
|
128
|
+
}
|
|
129
|
+
// Test location / naming
|
|
130
|
+
if (testing.location || testing.command) {
|
|
131
|
+
const testParts = [];
|
|
132
|
+
if (testing.location)
|
|
133
|
+
testParts.push(`location: ${testing.location}`);
|
|
134
|
+
if (testing.command)
|
|
135
|
+
testParts.push(`run: \`${testing.command}\``);
|
|
136
|
+
lines.push(`**Tests:** ${testParts.join(" · ")}`);
|
|
137
|
+
lines.push("");
|
|
138
|
+
}
|
|
139
|
+
// Code-level conventions
|
|
140
|
+
if (codeLevelConventions.length > 0) {
|
|
141
|
+
lines.push("## Conventions");
|
|
142
|
+
for (const rule of codeLevelConventions) {
|
|
143
|
+
lines.push(`- ${rule}`);
|
|
144
|
+
}
|
|
145
|
+
lines.push("");
|
|
146
|
+
}
|
|
147
|
+
// Hard never rules (code-affecting)
|
|
148
|
+
if (codeNever.length > 0) {
|
|
149
|
+
lines.push("## Never");
|
|
150
|
+
for (const rule of codeNever) {
|
|
151
|
+
lines.push(`- ${rule}`);
|
|
152
|
+
}
|
|
153
|
+
lines.push("");
|
|
154
|
+
}
|
|
155
|
+
const generated = lines.join("\n").trimEnd() + "\n";
|
|
156
|
+
if (!preserveCustom)
|
|
157
|
+
return generated;
|
|
158
|
+
const copilotPath = path.join(projectPath, ".github", "copilot-instructions.md");
|
|
159
|
+
const existingBlocks = await loadExistingCustomBlocks(copilotPath);
|
|
160
|
+
return injectCustomBlocks(generated, existingBlocks);
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=copilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/derivers/copilot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ProjectMetadata } from "../extractor/schema.js";
|
|
2
|
+
export interface CursorDerivationOptions {
|
|
3
|
+
projectPath: string;
|
|
4
|
+
agentsMdContent: string;
|
|
5
|
+
metadata: ProjectMetadata;
|
|
6
|
+
/** @default true */
|
|
7
|
+
preserveCustom?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derives directive-style `.cursorrules` content from AGENTS.md + metadata.
|
|
11
|
+
* Keeps output terse and scannable — target < 400 words.
|
|
12
|
+
*
|
|
13
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deriveCursorRules(options: CursorDerivationOptions): Promise<string>;
|
|
16
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/derivers/cursor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAkDD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6EzF"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectCustomBlocks, loadExistingCustomBlocks } from "./merger.js";
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Parsing helpers
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/**
|
|
7
|
+
* Extracts the text body of the first `## Heading` section that matches the
|
|
8
|
+
* given heading name (case-insensitive). Returns an empty string when not found.
|
|
9
|
+
*/
|
|
10
|
+
function extractSection(content, heading) {
|
|
11
|
+
const re = new RegExp(`^##\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^##\\s|$)`, "mi");
|
|
12
|
+
const match = re.exec(content);
|
|
13
|
+
return match ? match[1].trim() : "";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extracts the text body of the first `### Heading` subsection that matches.
|
|
17
|
+
*/
|
|
18
|
+
function extractSubSection(content, heading) {
|
|
19
|
+
const re = new RegExp(`^###\\s+${escapeRegExp(heading)}\\s*$([\\s\\S]*?)(?=^###\\s|^##\\s|$)`, "mi");
|
|
20
|
+
const match = re.exec(content);
|
|
21
|
+
return match ? match[1].trim() : "";
|
|
22
|
+
}
|
|
23
|
+
function escapeRegExp(s) {
|
|
24
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parses a markdown section into a list of individual rule strings, stripping
|
|
28
|
+
* leading list markers and blank lines.
|
|
29
|
+
*/
|
|
30
|
+
function sectionToLines(text) {
|
|
31
|
+
return text
|
|
32
|
+
.split("\n")
|
|
33
|
+
.map((l) => l.replace(/^[\s\-*>]+/, "").trim())
|
|
34
|
+
.filter((l) => l.length > 0);
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Deriver
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Derives directive-style `.cursorrules` content from AGENTS.md + metadata.
|
|
41
|
+
* Keeps output terse and scannable — target < 400 words.
|
|
42
|
+
*
|
|
43
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
44
|
+
*/
|
|
45
|
+
export async function deriveCursorRules(options) {
|
|
46
|
+
const { projectPath, agentsMdContent, metadata, preserveCustom = true } = options;
|
|
47
|
+
const { project, conventions: metaConventions, gotchas: metaGotchas, boundaries, testing } = metadata;
|
|
48
|
+
// Pull extra rules from AGENTS.md prose
|
|
49
|
+
const conventionsSection = sectionToLines(extractSection(agentsMdContent, "Conventions"));
|
|
50
|
+
const gotchasSection = sectionToLines(extractSection(agentsMdContent, "Gotchas"));
|
|
51
|
+
const neverSection = sectionToLines(extractSubSection(agentsMdContent, "Never"));
|
|
52
|
+
// Merge with metadata, preferring metadata as it's structured
|
|
53
|
+
const allConventions = deduplicateLines([...metaConventions, ...conventionsSection]);
|
|
54
|
+
const allGotchas = deduplicateLines([...metaGotchas, ...gotchasSection]);
|
|
55
|
+
const allNever = deduplicateLines([...boundaries.never, ...neverSection]);
|
|
56
|
+
const lines = [];
|
|
57
|
+
// Header
|
|
58
|
+
lines.push("# .cursorrules — managed by agents-sync");
|
|
59
|
+
lines.push("");
|
|
60
|
+
// Project identity
|
|
61
|
+
const frameworkPart = project.framework ? ` · ${project.framework}` : "";
|
|
62
|
+
lines.push(`${project.name} — ${project.language}${frameworkPart}`);
|
|
63
|
+
lines.push("");
|
|
64
|
+
// Test command
|
|
65
|
+
if (testing.command) {
|
|
66
|
+
lines.push(`**Test command:** \`${testing.command}\``);
|
|
67
|
+
lines.push("");
|
|
68
|
+
}
|
|
69
|
+
// Conventions
|
|
70
|
+
if (allConventions.length > 0) {
|
|
71
|
+
lines.push("## Conventions");
|
|
72
|
+
for (const rule of allConventions) {
|
|
73
|
+
lines.push(`- Always: ${rule}`);
|
|
74
|
+
}
|
|
75
|
+
lines.push("");
|
|
76
|
+
}
|
|
77
|
+
// Gotchas
|
|
78
|
+
if (allGotchas.length > 0) {
|
|
79
|
+
lines.push("## Gotchas");
|
|
80
|
+
for (const gotcha of allGotchas) {
|
|
81
|
+
// Gotchas already include consequence phrasing; surface as "Never" hints
|
|
82
|
+
lines.push(`- Never: ${gotcha}`);
|
|
83
|
+
}
|
|
84
|
+
lines.push("");
|
|
85
|
+
}
|
|
86
|
+
// Hard never rules (boundaries)
|
|
87
|
+
if (allNever.length > 0) {
|
|
88
|
+
lines.push("## Hard boundaries");
|
|
89
|
+
for (const rule of allNever) {
|
|
90
|
+
lines.push(`- Never: ${rule}`);
|
|
91
|
+
}
|
|
92
|
+
lines.push("");
|
|
93
|
+
}
|
|
94
|
+
// Always-do boundaries
|
|
95
|
+
if (boundaries.alwaysDo.length > 0) {
|
|
96
|
+
lines.push("## Always do");
|
|
97
|
+
for (const rule of boundaries.alwaysDo) {
|
|
98
|
+
lines.push(`- ${rule}`);
|
|
99
|
+
}
|
|
100
|
+
lines.push("");
|
|
101
|
+
}
|
|
102
|
+
const generated = lines.join("\n").trimEnd() + "\n";
|
|
103
|
+
if (!preserveCustom)
|
|
104
|
+
return generated;
|
|
105
|
+
const cursorPath = path.join(projectPath, ".cursorrules");
|
|
106
|
+
const existingBlocks = await loadExistingCustomBlocks(cursorPath);
|
|
107
|
+
return injectCustomBlocks(generated, existingBlocks);
|
|
108
|
+
}
|
|
109
|
+
function deduplicateLines(items) {
|
|
110
|
+
const seen = new Set();
|
|
111
|
+
const result = [];
|
|
112
|
+
for (const item of items) {
|
|
113
|
+
const key = item.toLowerCase().trim();
|
|
114
|
+
if (!seen.has(key)) {
|
|
115
|
+
seen.add(key);
|
|
116
|
+
result.push(item);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/derivers/cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ProjectMetadata } from "../extractor/schema.js";
|
|
2
|
+
export interface GeminiDerivationOptions {
|
|
3
|
+
projectPath: string;
|
|
4
|
+
agentsMdContent: string;
|
|
5
|
+
metadata: ProjectMetadata;
|
|
6
|
+
/** @default true */
|
|
7
|
+
preserveCustom?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Derives the full content for GEMINI.md.
|
|
11
|
+
*
|
|
12
|
+
* Content = canonical AGENTS.md + Gemini CLI-specific section.
|
|
13
|
+
* If preserveCustom is true (default) any existing custom blocks from the
|
|
14
|
+
* current GEMINI.md are appended after the generated body.
|
|
15
|
+
*
|
|
16
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function deriveGeminiMd(options: GeminiDerivationOptions): Promise<string>;
|
|
19
|
+
//# sourceMappingURL=gemini.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/derivers/gemini.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,eAAe,CAAC;IAC1B,oBAAoB;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAYD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CActF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { injectCustomBlocks, loadExistingCustomBlocks, loadUnmanagedFileAsCustomBlock } from "./merger.js";
|
|
3
|
+
const GEMINI_SECTION = `---
|
|
4
|
+
|
|
5
|
+
## Gemini CLI Notes
|
|
6
|
+
|
|
7
|
+
> This file is managed by agents-sync. Edit \`AGENTS.md\` and run \`/agents-sync sync\`.
|
|
8
|
+
|
|
9
|
+
### Re-sync
|
|
10
|
+
Run \`agents-sync sync\` after major refactors, new dependencies, or architecture changes.
|
|
11
|
+
`;
|
|
12
|
+
/**
|
|
13
|
+
* Derives the full content for GEMINI.md.
|
|
14
|
+
*
|
|
15
|
+
* Content = canonical AGENTS.md + Gemini CLI-specific section.
|
|
16
|
+
* If preserveCustom is true (default) any existing custom blocks from the
|
|
17
|
+
* current GEMINI.md are appended after the generated body.
|
|
18
|
+
*
|
|
19
|
+
* Does NOT write the file — the caller is responsible for writing.
|
|
20
|
+
*/
|
|
21
|
+
export async function deriveGeminiMd(options) {
|
|
22
|
+
const { projectPath, agentsMdContent, preserveCustom = true } = options;
|
|
23
|
+
const generated = `${agentsMdContent.trimEnd()}\n\n${GEMINI_SECTION}`;
|
|
24
|
+
if (!preserveCustom)
|
|
25
|
+
return generated;
|
|
26
|
+
const geminiPath = path.join(projectPath, "GEMINI.md");
|
|
27
|
+
const existingBlocks = await loadExistingCustomBlocks(geminiPath);
|
|
28
|
+
const blocks = existingBlocks.length > 0
|
|
29
|
+
? existingBlocks
|
|
30
|
+
: await loadUnmanagedFileAsCustomBlock(geminiPath);
|
|
31
|
+
return injectCustomBlocks(generated, blocks);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/derivers/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAU3G,MAAM,cAAc,GAAG;;;;;;;;CAQtB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgC;IACnE,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,cAAc,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAExE,MAAM,SAAS,GAAG,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,cAAc,EAAE,CAAC;IAEtE,IAAI,CAAC,cAAc;QAAE,OAAO,SAAS,CAAC;IAEtC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,MAAM,wBAAwB,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC;QACtC,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,MAAM,8BAA8B,CAAC,UAAU,CAAC,CAAC;IAErD,OAAO,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|