agentsmesh 0.2.9 → 0.3.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/CHANGELOG.md +25 -1
- package/README.md +23 -33
- package/dist/cli.js +1292 -765
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -91,7 +91,12 @@ var COMMANDS = [
|
|
|
91
91
|
name: "init",
|
|
92
92
|
usage: "agentsmesh init [flags]",
|
|
93
93
|
description: "Create agentsmesh.yaml, agentsmesh.local.yaml, and canonical .agentsmesh scaffold",
|
|
94
|
-
flags: [
|
|
94
|
+
flags: [
|
|
95
|
+
{
|
|
96
|
+
name: "--yes",
|
|
97
|
+
description: "Auto-import detected tool configs, then add example scaffold only under empty canonical paths"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
95
100
|
},
|
|
96
101
|
{
|
|
97
102
|
name: "generate",
|
|
@@ -247,7 +252,7 @@ function handleError(err, options) {
|
|
|
247
252
|
}
|
|
248
253
|
|
|
249
254
|
// src/cli/commands/generate.ts
|
|
250
|
-
import { join as
|
|
255
|
+
import { join as join56, resolve as resolve4, sep } from "path";
|
|
251
256
|
|
|
252
257
|
// src/config/core/loader.ts
|
|
253
258
|
import { parse as parseYaml } from "yaml";
|
|
@@ -355,6 +360,7 @@ var TARGET_IDS = [
|
|
|
355
360
|
"copilot",
|
|
356
361
|
"continue",
|
|
357
362
|
"junie",
|
|
363
|
+
"kiro",
|
|
358
364
|
"gemini-cli",
|
|
359
365
|
"cline",
|
|
360
366
|
"codex-cli",
|
|
@@ -525,7 +531,7 @@ async function loadConfigFromDir(startDir) {
|
|
|
525
531
|
}
|
|
526
532
|
|
|
527
533
|
// src/canonical/extends/extends.ts
|
|
528
|
-
import { join as
|
|
534
|
+
import { join as join48 } from "path";
|
|
529
535
|
|
|
530
536
|
// src/config/resolve/resolver.ts
|
|
531
537
|
import { mkdir as mkdir4, rm as rm4 } from "fs/promises";
|
|
@@ -1465,7 +1471,7 @@ function mergeIgnore(base, overlay) {
|
|
|
1465
1471
|
}
|
|
1466
1472
|
|
|
1467
1473
|
// src/canonical/extends/extend-load.ts
|
|
1468
|
-
import { join as
|
|
1474
|
+
import { join as join45 } from "path";
|
|
1469
1475
|
|
|
1470
1476
|
// src/config/resolve/native-format-detector.ts
|
|
1471
1477
|
import { join as join10 } from "path";
|
|
@@ -1521,6 +1527,10 @@ var TARGET_SIGNATURES = [
|
|
|
1521
1527
|
{
|
|
1522
1528
|
target: "junie",
|
|
1523
1529
|
paths: [".junie", ".junie/guidelines.md"]
|
|
1530
|
+
},
|
|
1531
|
+
{
|
|
1532
|
+
target: "kiro",
|
|
1533
|
+
paths: [".kiro", ".kiro/steering", ".kiro/settings/mcp.json"]
|
|
1524
1534
|
}
|
|
1525
1535
|
];
|
|
1526
1536
|
async function detectNativeFormat(repoPath) {
|
|
@@ -1543,11 +1553,11 @@ var KNOWN_NATIVE_PATHS = TARGET_SIGNATURES.map((sig) => sig.paths[0]).filter(
|
|
|
1543
1553
|
);
|
|
1544
1554
|
|
|
1545
1555
|
// src/targets/claude-code/importer.ts
|
|
1546
|
-
import { join as
|
|
1556
|
+
import { join as join42, basename as basename27, relative as relative17, dirname as dirname18 } from "path";
|
|
1547
1557
|
|
|
1548
1558
|
// src/core/reference/import-rewriter.ts
|
|
1549
1559
|
import { existsSync as existsSync2, realpathSync as realpathSync3 } from "fs";
|
|
1550
|
-
import { join as
|
|
1560
|
+
import { join as join39 } from "path";
|
|
1551
1561
|
import { normalize as normalizePath } from "path";
|
|
1552
1562
|
|
|
1553
1563
|
// src/config/core/conversions.ts
|
|
@@ -1562,22 +1572,22 @@ var DEFAULT_AGENTS_TO_SKILLS = {
|
|
|
1562
1572
|
// native .codex/agents/*.toml per agent-structures
|
|
1563
1573
|
windsurf: true
|
|
1564
1574
|
};
|
|
1565
|
-
function hasOwnTarget(map,
|
|
1566
|
-
return Object.prototype.hasOwnProperty.call(map,
|
|
1575
|
+
function hasOwnTarget(map, target13) {
|
|
1576
|
+
return Object.prototype.hasOwnProperty.call(map, target13);
|
|
1567
1577
|
}
|
|
1568
|
-
function usesCommandSkillProjection(
|
|
1569
|
-
return hasOwnTarget(DEFAULT_COMMANDS_TO_SKILLS,
|
|
1578
|
+
function usesCommandSkillProjection(target13) {
|
|
1579
|
+
return hasOwnTarget(DEFAULT_COMMANDS_TO_SKILLS, target13);
|
|
1570
1580
|
}
|
|
1571
|
-
function usesAgentSkillProjection(
|
|
1572
|
-
return hasOwnTarget(DEFAULT_AGENTS_TO_SKILLS,
|
|
1581
|
+
function usesAgentSkillProjection(target13) {
|
|
1582
|
+
return hasOwnTarget(DEFAULT_AGENTS_TO_SKILLS, target13);
|
|
1573
1583
|
}
|
|
1574
|
-
function shouldConvertCommandsToSkills(config,
|
|
1575
|
-
if (!usesCommandSkillProjection(
|
|
1576
|
-
return config.conversions?.commands_to_skills?.[
|
|
1584
|
+
function shouldConvertCommandsToSkills(config, target13) {
|
|
1585
|
+
if (!usesCommandSkillProjection(target13)) return false;
|
|
1586
|
+
return config.conversions?.commands_to_skills?.[target13] ?? DEFAULT_COMMANDS_TO_SKILLS[target13];
|
|
1577
1587
|
}
|
|
1578
|
-
function shouldConvertAgentsToSkills(config,
|
|
1579
|
-
if (!usesAgentSkillProjection(
|
|
1580
|
-
return config.conversions?.agents_to_skills?.[
|
|
1588
|
+
function shouldConvertAgentsToSkills(config, target13) {
|
|
1589
|
+
if (!usesAgentSkillProjection(target13)) return false;
|
|
1590
|
+
return config.conversions?.agents_to_skills?.[target13] ?? DEFAULT_AGENTS_TO_SKILLS[target13];
|
|
1581
1591
|
}
|
|
1582
1592
|
|
|
1583
1593
|
// src/targets/claude-code/constants.ts
|
|
@@ -1874,6 +1884,22 @@ var JUNIE_CANONICAL_AGENTS_DIR = ".agentsmesh/agents";
|
|
|
1874
1884
|
var JUNIE_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
1875
1885
|
var JUNIE_CANONICAL_IGNORE = ".agentsmesh/ignore";
|
|
1876
1886
|
|
|
1887
|
+
// src/targets/kiro/constants.ts
|
|
1888
|
+
var KIRO_TARGET = "kiro";
|
|
1889
|
+
var KIRO_AGENTS_MD = "AGENTS.md";
|
|
1890
|
+
var KIRO_DIR = ".kiro";
|
|
1891
|
+
var KIRO_STEERING_DIR = `${KIRO_DIR}/steering`;
|
|
1892
|
+
var KIRO_SKILLS_DIR = `${KIRO_DIR}/skills`;
|
|
1893
|
+
var KIRO_HOOKS_DIR = `${KIRO_DIR}/hooks`;
|
|
1894
|
+
var KIRO_SETTINGS_DIR = `${KIRO_DIR}/settings`;
|
|
1895
|
+
var KIRO_MCP_FILE = `${KIRO_SETTINGS_DIR}/mcp.json`;
|
|
1896
|
+
var KIRO_IGNORE = ".kiroignore";
|
|
1897
|
+
var KIRO_CANONICAL_ROOT_RULE = ".agentsmesh/rules/_root.md";
|
|
1898
|
+
var KIRO_CANONICAL_RULES_DIR = ".agentsmesh/rules";
|
|
1899
|
+
var KIRO_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
1900
|
+
var KIRO_CANONICAL_HOOKS = ".agentsmesh/hooks.yaml";
|
|
1901
|
+
var KIRO_CANONICAL_IGNORE = ".agentsmesh/ignore";
|
|
1902
|
+
|
|
1877
1903
|
// src/targets/roo-code/constants.ts
|
|
1878
1904
|
var ROO_CODE_TARGET = "roo-code";
|
|
1879
1905
|
var ROO_CODE_DIR = ".roo";
|
|
@@ -2233,6 +2259,15 @@ async function buildJunieImportPaths(refs, projectRoot) {
|
|
|
2233
2259
|
addSkillLikeMapping(refs, rel(projectRoot, absPath), ".junie/skills");
|
|
2234
2260
|
}
|
|
2235
2261
|
}
|
|
2262
|
+
async function buildKiroImportPaths(refs, projectRoot) {
|
|
2263
|
+
refs.set(KIRO_AGENTS_MD, `${AB_RULES2}/_root.md`);
|
|
2264
|
+
for (const absPath of await listFiles(projectRoot, KIRO_STEERING_DIR)) {
|
|
2265
|
+
addSimpleFileMapping(refs, rel(projectRoot, absPath), AB_RULES2, ".md");
|
|
2266
|
+
}
|
|
2267
|
+
for (const absPath of await listFiles(projectRoot, KIRO_SKILLS_DIR)) {
|
|
2268
|
+
addSkillLikeMapping(refs, rel(projectRoot, absPath), KIRO_SKILLS_DIR);
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2236
2271
|
async function buildGeminiCliImportPaths(refs, projectRoot) {
|
|
2237
2272
|
for (const absPath of await listFiles(projectRoot, ".gemini/rules")) {
|
|
2238
2273
|
addSimpleFileMapping(refs, rel(projectRoot, absPath), AB_RULES2, ".md");
|
|
@@ -2534,64 +2569,82 @@ import { join as join15, dirname as dirname9 } from "path";
|
|
|
2534
2569
|
import { basename as basename8, dirname as dirname5 } from "path";
|
|
2535
2570
|
|
|
2536
2571
|
// src/targets/projection/root-instruction-paragraph.ts
|
|
2537
|
-
var
|
|
2538
|
-
var
|
|
2539
|
-
var
|
|
2572
|
+
var ROOT_INSTRUCTION_BODY_V1 = "AgentsMesh is a config sync library for AI coding tools. The only canonical source of truth is `.agentsmesh/`; files emitted into target formats such as `AGENTS.md`, `.claude/`, `.cursor/`, `.junie/`, and similar directories are generated artifacts. When making changes, edit canonical config first, then regenerate and verify the target outputs. Preserve the library's bidirectional contract: import native tool config into canonical form, generate back to target-specific layouts, and keep projected or embedded features round-trippable rather than treating them as plain text exports.";
|
|
2573
|
+
var ROOT_INSTRUCTION_BODY_V2 = "AgentsMesh is a config sync library for AI coding tools. The only canonical source of truth is the `.agentsmesh` directory at the project root; files emitted into target formats such as `AGENTS.md`, `.claude/`, `.cursor/`, `.junie/`, and similar directories are generated artifacts. When making changes, edit canonical config first, then regenerate and verify the target outputs. Preserve the library's bidirectional contract: import native tool config into canonical form, generate back to target-specific layouts, and keep projected or embedded features round-trippable rather than treating them as plain text exports.";
|
|
2574
|
+
var ROOT_INSTRUCTION_BODY_V3 = "AgentsMesh syncs AI coding tool configuration from a single canonical `.agentsmesh` directory. All target-specific files (`.claude/`, `.cursor/`, `AGENTS.md`, etc.) are generated artifacts \u2014 edit canonical config first, then regenerate. The import/generate contract is bidirectional and lossless: embedded or projected features round-trip without data loss.";
|
|
2575
|
+
var ROOT_INSTRUCTION_BODY_V4 = "Create agents, skills, commands, rules, hooks, and MCP in `.agentsmesh`, then run `agentsmesh generate` to sync each tool's native files. Edit `.agentsmesh`, not generated outputs.";
|
|
2576
|
+
var ROOT_INSTRUCTION_BODY_V5 = "Use Claude-style Markdown in `.agentsmesh`: `agents/*.md`, `commands/*.md`, and `skills/*/SKILL.md`; keep rules in `rules/*.md`, hooks in `hooks.yaml`, MCP in `mcp.json`, permissions in `permissions.yaml`, and ignore patterns in `ignore`, then run `agentsmesh generate`.";
|
|
2577
|
+
var ROOT_INSTRUCTION_BODY_V6 = "Create canonical files in `.agentsmesh`: `rules/_root.md` and `rules/*.md` are Markdown rules; `commands/*.md`, `agents/*.md`, and `skills/*/SKILL.md` plus supporting files use Claude-style frontmatter Markdown; `mcp.json` is MCP JSON; `hooks.yaml` and `permissions.yaml` are YAML; `ignore` is gitignore-style text. Then run `agentsmesh generate`.";
|
|
2578
|
+
var ROOT_INSTRUCTION_BODY_V7 = "`.agentsmesh` is the only folder you edit or add these files in: `rules/_root.md` and `rules/*.md` are Markdown rules; `commands/*.md`, `agents/*.md`, and `skills/*/SKILL.md` plus supporting files use Claude-style frontmatter Markdown; `mcp.json` is MCP JSON; `hooks.yaml` and `permissions.yaml` are YAML; `ignore` is gitignore-style text. Do not edit generated tool files; run `agentsmesh generate`.";
|
|
2579
|
+
var ROOT_INSTRUCTION_BODY = "`agentsmesh.yaml` selects targets/features (`agentsmesh.local.yaml` overrides locally), and `.agentsmesh` is the only place to add or edit canonical items: `rules/_root.md`, `rules/*.md`, `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md` plus supporting files, `mcp.json`, `hooks.yaml`, `permissions.yaml`, and `ignore`; if missing run `agentsmesh init`, use `agentsmesh import --from <tool>` for native configs, `agentsmesh install <source>` or `install --sync` for reusable packs, then run `agentsmesh generate`. Use `diff`, `lint`, `check`, `watch`, `matrix`, and `merge` as needed; never edit generated tool files.";
|
|
2580
|
+
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = ROOT_INSTRUCTION_BODY_V1;
|
|
2540
2581
|
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION = `## Project-Specific Rules
|
|
2541
2582
|
|
|
2542
|
-
${
|
|
2543
|
-
var
|
|
2583
|
+
${ROOT_INSTRUCTION_BODY_V1}`;
|
|
2584
|
+
var AGENTSMESH_CONTRACT_WITH_V1_BODY = `## AgentsMesh Generation Contract
|
|
2585
|
+
|
|
2586
|
+
${ROOT_INSTRUCTION_BODY_V1}`;
|
|
2587
|
+
var AGENTSMESH_CONTRACT_WITH_V2_BODY = `## AgentsMesh Generation Contract
|
|
2544
2588
|
|
|
2545
|
-
${
|
|
2589
|
+
${ROOT_INSTRUCTION_BODY_V2}`;
|
|
2590
|
+
var AGENTSMESH_CONTRACT_WITH_V3_BODY = `## AgentsMesh Generation Contract
|
|
2591
|
+
|
|
2592
|
+
${ROOT_INSTRUCTION_BODY_V3}`;
|
|
2593
|
+
var AGENTSMESH_CONTRACT_WITH_V4_BODY = `## AgentsMesh Generation Contract
|
|
2594
|
+
|
|
2595
|
+
${ROOT_INSTRUCTION_BODY_V4}`;
|
|
2596
|
+
var AGENTSMESH_CONTRACT_WITH_V5_BODY = `## AgentsMesh Generation Contract
|
|
2597
|
+
|
|
2598
|
+
${ROOT_INSTRUCTION_BODY_V5}`;
|
|
2599
|
+
var AGENTSMESH_CONTRACT_WITH_V6_BODY = `## AgentsMesh Generation Contract
|
|
2600
|
+
|
|
2601
|
+
${ROOT_INSTRUCTION_BODY_V6}`;
|
|
2602
|
+
var AGENTSMESH_CONTRACT_WITH_V7_BODY = `## AgentsMesh Generation Contract
|
|
2603
|
+
|
|
2604
|
+
${ROOT_INSTRUCTION_BODY_V7}`;
|
|
2546
2605
|
var AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = `## AgentsMesh Generation Contract
|
|
2547
2606
|
|
|
2548
2607
|
${ROOT_INSTRUCTION_BODY}`;
|
|
2549
2608
|
function normalizeWhitespace(value) {
|
|
2550
2609
|
return value.replace(/\s+/g, " ").trim();
|
|
2551
2610
|
}
|
|
2611
|
+
var LEGACY_FORMS = [
|
|
2612
|
+
AGENTSMESH_CONTRACT_WITH_V7_BODY,
|
|
2613
|
+
AGENTSMESH_CONTRACT_WITH_V6_BODY,
|
|
2614
|
+
AGENTSMESH_CONTRACT_WITH_V5_BODY,
|
|
2615
|
+
AGENTSMESH_CONTRACT_WITH_V4_BODY,
|
|
2616
|
+
AGENTSMESH_CONTRACT_WITH_V3_BODY,
|
|
2617
|
+
AGENTSMESH_CONTRACT_WITH_V2_BODY,
|
|
2618
|
+
AGENTSMESH_CONTRACT_WITH_V1_BODY,
|
|
2619
|
+
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION,
|
|
2620
|
+
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2621
|
+
];
|
|
2552
2622
|
function appendAgentsmeshRootInstructionParagraph(content) {
|
|
2553
2623
|
const trimmed = content.trim();
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
)) {
|
|
2624
|
+
const norm2 = normalizeWhitespace(trimmed);
|
|
2625
|
+
if (norm2.includes(normalizeWhitespace(AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH))) {
|
|
2557
2626
|
return trimmed;
|
|
2558
2627
|
}
|
|
2559
|
-
|
|
2560
|
-
normalizeWhitespace(
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION,
|
|
2564
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2565
|
-
);
|
|
2566
|
-
}
|
|
2567
|
-
if (normalizeWhitespace(trimmed).includes(normalizeWhitespace(AGENTSMESH_CONTRACT_WITH_LEGACY_BODY))) {
|
|
2568
|
-
return trimmed.replace(
|
|
2569
|
-
AGENTSMESH_CONTRACT_WITH_LEGACY_BODY,
|
|
2570
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2571
|
-
);
|
|
2572
|
-
}
|
|
2573
|
-
if (normalizeWhitespace(trimmed).includes(
|
|
2574
|
-
normalizeWhitespace(LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH)
|
|
2575
|
-
)) {
|
|
2576
|
-
return trimmed.replace(
|
|
2577
|
-
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH,
|
|
2578
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2579
|
-
);
|
|
2628
|
+
for (const legacy of LEGACY_FORMS) {
|
|
2629
|
+
if (norm2.includes(normalizeWhitespace(legacy))) {
|
|
2630
|
+
return trimmed.replace(legacy, AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH);
|
|
2631
|
+
}
|
|
2580
2632
|
}
|
|
2581
2633
|
return trimmed ? `${trimmed}
|
|
2582
2634
|
|
|
2583
2635
|
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}` : AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH;
|
|
2584
2636
|
}
|
|
2585
2637
|
function stripAgentsmeshRootInstructionParagraph(content) {
|
|
2586
|
-
|
|
2638
|
+
let result = content;
|
|
2639
|
+
result = result.replace(`
|
|
2587
2640
|
|
|
2588
|
-
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "")
|
|
2641
|
+
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "");
|
|
2642
|
+
for (const legacy of LEGACY_FORMS) {
|
|
2643
|
+
result = result.replace(`
|
|
2589
2644
|
|
|
2590
|
-
${
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
${LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "").trim();
|
|
2645
|
+
${legacy}`, "");
|
|
2646
|
+
}
|
|
2647
|
+
return result.trim();
|
|
2595
2648
|
}
|
|
2596
2649
|
|
|
2597
2650
|
// src/targets/import/import-metadata.ts
|
|
@@ -4379,6 +4432,347 @@ var descriptor5 = {
|
|
|
4379
4432
|
]
|
|
4380
4433
|
};
|
|
4381
4434
|
|
|
4435
|
+
// src/targets/kiro/generator.ts
|
|
4436
|
+
import { basename as basename17 } from "path";
|
|
4437
|
+
|
|
4438
|
+
// src/targets/kiro/hook-format.ts
|
|
4439
|
+
import { stringify as yamlStringify4 } from "yaml";
|
|
4440
|
+
var CANONICAL_TO_KIRO = {
|
|
4441
|
+
UserPromptSubmit: "promptSubmit",
|
|
4442
|
+
SubagentStop: "agentStop",
|
|
4443
|
+
PreToolUse: "preToolUse",
|
|
4444
|
+
PostToolUse: "postToolUse"
|
|
4445
|
+
};
|
|
4446
|
+
var KIRO_TO_CANONICAL = /* @__PURE__ */ new Map([
|
|
4447
|
+
["promptSubmit", "UserPromptSubmit"],
|
|
4448
|
+
["agentStop", "SubagentStop"],
|
|
4449
|
+
["preToolUse", "PreToolUse"],
|
|
4450
|
+
["postToolUse", "PostToolUse"]
|
|
4451
|
+
]);
|
|
4452
|
+
function toKebab(value) {
|
|
4453
|
+
return value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
|
|
4454
|
+
}
|
|
4455
|
+
function hookText(entry) {
|
|
4456
|
+
return entry.type === "prompt" ? entry.prompt : entry.command;
|
|
4457
|
+
}
|
|
4458
|
+
function toWhen(event, matcher) {
|
|
4459
|
+
const type = CANONICAL_TO_KIRO[event];
|
|
4460
|
+
if (event === "PreToolUse" || event === "PostToolUse") {
|
|
4461
|
+
return { type, tools: [matcher || "*"] };
|
|
4462
|
+
}
|
|
4463
|
+
return { type };
|
|
4464
|
+
}
|
|
4465
|
+
function generateKiroHooks(hooks) {
|
|
4466
|
+
const outputs = [];
|
|
4467
|
+
for (const [event, entries] of Object.entries(hooks)) {
|
|
4468
|
+
const mappedEvent = event;
|
|
4469
|
+
if (!(mappedEvent in CANONICAL_TO_KIRO) || !Array.isArray(entries)) continue;
|
|
4470
|
+
let index = 1;
|
|
4471
|
+
for (const entry of entries) {
|
|
4472
|
+
const text = hookText(entry);
|
|
4473
|
+
if (!text) continue;
|
|
4474
|
+
const file = {
|
|
4475
|
+
name: `${toKebab(event)} ${index}`,
|
|
4476
|
+
version: "1",
|
|
4477
|
+
when: toWhen(mappedEvent, entry.matcher),
|
|
4478
|
+
then: entry.type === "prompt" ? { type: "askAgent", prompt: text } : { type: "shellCommand", command: text }
|
|
4479
|
+
};
|
|
4480
|
+
outputs.push({
|
|
4481
|
+
name: `${toKebab(event)}-${index}.kiro.hook`,
|
|
4482
|
+
content: JSON.stringify(file, null, 2)
|
|
4483
|
+
});
|
|
4484
|
+
index += 1;
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
return outputs;
|
|
4488
|
+
}
|
|
4489
|
+
function toCanonicalEntry(file) {
|
|
4490
|
+
const canonicalEvent = KIRO_TO_CANONICAL.get(file.when.type);
|
|
4491
|
+
if (!canonicalEvent) return null;
|
|
4492
|
+
const matcher = file.when.tools?.[0] ?? file.when.patterns?.[0] ?? "*";
|
|
4493
|
+
if (file.then.type === "askAgent" && typeof file.then.prompt === "string") {
|
|
4494
|
+
return {
|
|
4495
|
+
event: canonicalEvent,
|
|
4496
|
+
entry: {
|
|
4497
|
+
matcher,
|
|
4498
|
+
command: file.then.prompt,
|
|
4499
|
+
prompt: file.then.prompt,
|
|
4500
|
+
type: "prompt"
|
|
4501
|
+
}
|
|
4502
|
+
};
|
|
4503
|
+
}
|
|
4504
|
+
if (file.then.type === "shellCommand" && typeof file.then.command === "string") {
|
|
4505
|
+
return {
|
|
4506
|
+
event: canonicalEvent,
|
|
4507
|
+
entry: { matcher, command: file.then.command, type: "command" }
|
|
4508
|
+
};
|
|
4509
|
+
}
|
|
4510
|
+
return null;
|
|
4511
|
+
}
|
|
4512
|
+
function parseKiroHookFile(content) {
|
|
4513
|
+
let parsed;
|
|
4514
|
+
try {
|
|
4515
|
+
parsed = JSON.parse(content);
|
|
4516
|
+
} catch {
|
|
4517
|
+
return null;
|
|
4518
|
+
}
|
|
4519
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
4520
|
+
const file = parsed;
|
|
4521
|
+
if (!file.when || !file.then || typeof file.when.type !== "string") return null;
|
|
4522
|
+
return toCanonicalEntry(file);
|
|
4523
|
+
}
|
|
4524
|
+
function serializeCanonicalHooks(hooks) {
|
|
4525
|
+
return yamlStringify4(hooks).trimEnd();
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4528
|
+
// src/targets/kiro/generator.ts
|
|
4529
|
+
function steeringFrontmatter(rule) {
|
|
4530
|
+
const frontmatter = {};
|
|
4531
|
+
if (rule.globs.length > 0) {
|
|
4532
|
+
frontmatter.inclusion = "fileMatch";
|
|
4533
|
+
frontmatter.fileMatchPattern = rule.globs.length === 1 ? rule.globs[0] : rule.globs;
|
|
4534
|
+
} else if (rule.trigger === "manual") {
|
|
4535
|
+
frontmatter.inclusion = "manual";
|
|
4536
|
+
} else if (rule.trigger === "model_decision") {
|
|
4537
|
+
frontmatter.inclusion = "auto";
|
|
4538
|
+
} else {
|
|
4539
|
+
frontmatter.inclusion = "always";
|
|
4540
|
+
}
|
|
4541
|
+
if (rule.description) frontmatter.description = rule.description;
|
|
4542
|
+
return frontmatter;
|
|
4543
|
+
}
|
|
4544
|
+
function generateRules6(canonical) {
|
|
4545
|
+
const outputs = [];
|
|
4546
|
+
const root = canonical.rules.find((rule) => rule.root);
|
|
4547
|
+
if (root) {
|
|
4548
|
+
outputs.push({ path: KIRO_AGENTS_MD, content: root.body.trim() || "" });
|
|
4549
|
+
}
|
|
4550
|
+
for (const rule of canonical.rules) {
|
|
4551
|
+
if (rule.root) continue;
|
|
4552
|
+
if (rule.targets.length > 0 && !rule.targets.includes(KIRO_TARGET)) continue;
|
|
4553
|
+
const slug = basename17(rule.source, ".md");
|
|
4554
|
+
outputs.push({
|
|
4555
|
+
path: `${KIRO_STEERING_DIR}/${slug}.md`,
|
|
4556
|
+
content: serializeFrontmatter(steeringFrontmatter(rule), rule.body.trim() || "")
|
|
4557
|
+
});
|
|
4558
|
+
}
|
|
4559
|
+
return outputs;
|
|
4560
|
+
}
|
|
4561
|
+
function generateSkills6(canonical) {
|
|
4562
|
+
return generateEmbeddedSkills(canonical, KIRO_SKILLS_DIR);
|
|
4563
|
+
}
|
|
4564
|
+
function generateMcp5(canonical) {
|
|
4565
|
+
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
4566
|
+
return [
|
|
4567
|
+
{
|
|
4568
|
+
path: KIRO_MCP_FILE,
|
|
4569
|
+
content: JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2)
|
|
4570
|
+
}
|
|
4571
|
+
];
|
|
4572
|
+
}
|
|
4573
|
+
function generateHooks4(canonical) {
|
|
4574
|
+
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
4575
|
+
return generateKiroHooks(canonical.hooks).map((hook) => ({
|
|
4576
|
+
path: `${KIRO_HOOKS_DIR}/${hook.name}`,
|
|
4577
|
+
content: hook.content
|
|
4578
|
+
}));
|
|
4579
|
+
}
|
|
4580
|
+
function generateIgnore4(canonical) {
|
|
4581
|
+
if (canonical.ignore.length === 0) return [];
|
|
4582
|
+
return [{ path: KIRO_IGNORE, content: canonical.ignore.join("\n") }];
|
|
4583
|
+
}
|
|
4584
|
+
|
|
4585
|
+
// src/targets/kiro/importer.ts
|
|
4586
|
+
import { join as join22 } from "path";
|
|
4587
|
+
function readMcpServers3(content) {
|
|
4588
|
+
const parsed = JSON.parse(content);
|
|
4589
|
+
const rawServers = parsed.mcpServers;
|
|
4590
|
+
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) return {};
|
|
4591
|
+
const servers = {};
|
|
4592
|
+
for (const [name, value] of Object.entries(rawServers)) {
|
|
4593
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
4594
|
+
const server = value;
|
|
4595
|
+
if (typeof server.command === "string") {
|
|
4596
|
+
servers[name] = {
|
|
4597
|
+
type: typeof server.type === "string" ? server.type : "stdio",
|
|
4598
|
+
command: server.command,
|
|
4599
|
+
args: toStringArray4(server.args),
|
|
4600
|
+
env: toStringRecord(server.env)
|
|
4601
|
+
};
|
|
4602
|
+
continue;
|
|
4603
|
+
}
|
|
4604
|
+
if (typeof server.url === "string") {
|
|
4605
|
+
servers[name] = {
|
|
4606
|
+
type: typeof server.type === "string" ? server.type : "http",
|
|
4607
|
+
url: server.url,
|
|
4608
|
+
headers: toStringRecord(server.headers),
|
|
4609
|
+
env: toStringRecord(server.env)
|
|
4610
|
+
};
|
|
4611
|
+
}
|
|
4612
|
+
}
|
|
4613
|
+
return servers;
|
|
4614
|
+
}
|
|
4615
|
+
function canonicalRuleMeta(frontmatter) {
|
|
4616
|
+
const inclusion = typeof frontmatter.inclusion === "string" ? frontmatter.inclusion : "";
|
|
4617
|
+
const meta = {
|
|
4618
|
+
root: false,
|
|
4619
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : void 0,
|
|
4620
|
+
globs: toGlobsArray(frontmatter.fileMatchPattern)
|
|
4621
|
+
};
|
|
4622
|
+
if (inclusion === "manual") meta.trigger = "manual";
|
|
4623
|
+
if (inclusion === "auto") meta.trigger = "model_decision";
|
|
4624
|
+
if (inclusion === "fileMatch") meta.trigger = "glob";
|
|
4625
|
+
return meta;
|
|
4626
|
+
}
|
|
4627
|
+
async function importRoot(projectRoot, results, normalize) {
|
|
4628
|
+
const srcPath = join22(projectRoot, KIRO_AGENTS_MD);
|
|
4629
|
+
const content = await readFileSafe(srcPath);
|
|
4630
|
+
if (content === null) return;
|
|
4631
|
+
const destPath = join22(projectRoot, KIRO_CANONICAL_ROOT_RULE);
|
|
4632
|
+
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
4633
|
+
await writeFileAtomic(
|
|
4634
|
+
destPath,
|
|
4635
|
+
await serializeImportedRuleWithFallback(destPath, { ...frontmatter, root: true }, body)
|
|
4636
|
+
);
|
|
4637
|
+
results.push({
|
|
4638
|
+
fromTool: KIRO_TARGET,
|
|
4639
|
+
fromPath: srcPath,
|
|
4640
|
+
toPath: KIRO_CANONICAL_ROOT_RULE,
|
|
4641
|
+
feature: "rules"
|
|
4642
|
+
});
|
|
4643
|
+
}
|
|
4644
|
+
async function importRules4(projectRoot, results, normalize) {
|
|
4645
|
+
results.push(
|
|
4646
|
+
...await importFileDirectory({
|
|
4647
|
+
srcDir: join22(projectRoot, KIRO_STEERING_DIR),
|
|
4648
|
+
destDir: join22(projectRoot, KIRO_CANONICAL_RULES_DIR),
|
|
4649
|
+
extensions: [".md"],
|
|
4650
|
+
fromTool: KIRO_TARGET,
|
|
4651
|
+
normalize,
|
|
4652
|
+
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
4653
|
+
const destPath = join22(projectRoot, KIRO_CANONICAL_RULES_DIR, relativePath);
|
|
4654
|
+
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
4655
|
+
return {
|
|
4656
|
+
destPath,
|
|
4657
|
+
toPath: `${KIRO_CANONICAL_RULES_DIR}/${relativePath}`,
|
|
4658
|
+
feature: "rules",
|
|
4659
|
+
content: await serializeImportedRuleWithFallback(
|
|
4660
|
+
destPath,
|
|
4661
|
+
canonicalRuleMeta(frontmatter),
|
|
4662
|
+
body
|
|
4663
|
+
)
|
|
4664
|
+
};
|
|
4665
|
+
}
|
|
4666
|
+
})
|
|
4667
|
+
);
|
|
4668
|
+
}
|
|
4669
|
+
async function importMcp4(projectRoot, results) {
|
|
4670
|
+
const content = await readFileSafe(join22(projectRoot, KIRO_MCP_FILE));
|
|
4671
|
+
if (content === null) return;
|
|
4672
|
+
const servers = readMcpServers3(content);
|
|
4673
|
+
if (Object.keys(servers).length === 0) return;
|
|
4674
|
+
await writeFileAtomic(
|
|
4675
|
+
join22(projectRoot, KIRO_CANONICAL_MCP),
|
|
4676
|
+
JSON.stringify({ mcpServers: servers }, null, 2)
|
|
4677
|
+
);
|
|
4678
|
+
results.push({
|
|
4679
|
+
fromTool: KIRO_TARGET,
|
|
4680
|
+
fromPath: join22(projectRoot, KIRO_MCP_FILE),
|
|
4681
|
+
toPath: KIRO_CANONICAL_MCP,
|
|
4682
|
+
feature: "mcp"
|
|
4683
|
+
});
|
|
4684
|
+
}
|
|
4685
|
+
async function importHooks2(projectRoot, results) {
|
|
4686
|
+
const hooks = {};
|
|
4687
|
+
for (const absPath of await readDirRecursive(join22(projectRoot, KIRO_HOOKS_DIR))) {
|
|
4688
|
+
if (!absPath.endsWith(".kiro.hook")) continue;
|
|
4689
|
+
const parsed = parseKiroHookFile(await readFileSafe(absPath) ?? "");
|
|
4690
|
+
if (!parsed) continue;
|
|
4691
|
+
hooks[parsed.event] ??= [];
|
|
4692
|
+
hooks[parsed.event].push(parsed.entry);
|
|
4693
|
+
}
|
|
4694
|
+
if (Object.keys(hooks).length === 0) return;
|
|
4695
|
+
await writeFileAtomic(join22(projectRoot, KIRO_CANONICAL_HOOKS), serializeCanonicalHooks(hooks));
|
|
4696
|
+
results.push({
|
|
4697
|
+
fromTool: KIRO_TARGET,
|
|
4698
|
+
fromPath: join22(projectRoot, KIRO_HOOKS_DIR),
|
|
4699
|
+
toPath: KIRO_CANONICAL_HOOKS,
|
|
4700
|
+
feature: "hooks"
|
|
4701
|
+
});
|
|
4702
|
+
}
|
|
4703
|
+
async function importIgnore3(projectRoot, results) {
|
|
4704
|
+
const content = await readFileSafe(join22(projectRoot, KIRO_IGNORE));
|
|
4705
|
+
if (content === null) return;
|
|
4706
|
+
await writeFileAtomic(join22(projectRoot, KIRO_CANONICAL_IGNORE), content.trimEnd());
|
|
4707
|
+
results.push({
|
|
4708
|
+
fromTool: KIRO_TARGET,
|
|
4709
|
+
fromPath: join22(projectRoot, KIRO_IGNORE),
|
|
4710
|
+
toPath: KIRO_CANONICAL_IGNORE,
|
|
4711
|
+
feature: "ignore"
|
|
4712
|
+
});
|
|
4713
|
+
}
|
|
4714
|
+
async function importFromKiro(projectRoot) {
|
|
4715
|
+
const results = [];
|
|
4716
|
+
const normalize = await createImportReferenceNormalizer(KIRO_TARGET, projectRoot);
|
|
4717
|
+
await importRoot(projectRoot, results, normalize);
|
|
4718
|
+
await importRules4(projectRoot, results, normalize);
|
|
4719
|
+
await importEmbeddedSkills(projectRoot, KIRO_SKILLS_DIR, KIRO_TARGET, results, normalize);
|
|
4720
|
+
await importMcp4(projectRoot, results);
|
|
4721
|
+
await importHooks2(projectRoot, results);
|
|
4722
|
+
await importIgnore3(projectRoot, results);
|
|
4723
|
+
return results;
|
|
4724
|
+
}
|
|
4725
|
+
|
|
4726
|
+
// src/targets/kiro/linter.ts
|
|
4727
|
+
function lintRules6(canonical, projectRoot, projectFiles) {
|
|
4728
|
+
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
4729
|
+
...diagnostic,
|
|
4730
|
+
target: KIRO_TARGET
|
|
4731
|
+
}));
|
|
4732
|
+
}
|
|
4733
|
+
|
|
4734
|
+
// src/targets/kiro/index.ts
|
|
4735
|
+
var target6 = {
|
|
4736
|
+
name: KIRO_TARGET,
|
|
4737
|
+
primaryRootInstructionPath: KIRO_AGENTS_MD,
|
|
4738
|
+
generateRules: generateRules6,
|
|
4739
|
+
generateSkills: generateSkills6,
|
|
4740
|
+
generateMcp: generateMcp5,
|
|
4741
|
+
generateHooks: generateHooks4,
|
|
4742
|
+
generateIgnore: generateIgnore4,
|
|
4743
|
+
importFrom: importFromKiro
|
|
4744
|
+
};
|
|
4745
|
+
var descriptor6 = {
|
|
4746
|
+
id: KIRO_TARGET,
|
|
4747
|
+
generators: target6,
|
|
4748
|
+
capabilities: {
|
|
4749
|
+
rules: "native",
|
|
4750
|
+
commands: "none",
|
|
4751
|
+
agents: "none",
|
|
4752
|
+
skills: "native",
|
|
4753
|
+
mcp: "native",
|
|
4754
|
+
hooks: "native",
|
|
4755
|
+
ignore: "native",
|
|
4756
|
+
permissions: "none"
|
|
4757
|
+
},
|
|
4758
|
+
emptyImportMessage: "No Kiro config found (AGENTS.md, .kiro/steering, .kiro/skills, .kiro/hooks, .kiro/settings/mcp.json, or .kiroignore).",
|
|
4759
|
+
lintRules: lintRules6,
|
|
4760
|
+
skillDir: KIRO_SKILLS_DIR,
|
|
4761
|
+
paths: {
|
|
4762
|
+
rulePath(slug, _rule) {
|
|
4763
|
+
return `${KIRO_STEERING_DIR}/${slug}.md`;
|
|
4764
|
+
},
|
|
4765
|
+
commandPath(_name, _config) {
|
|
4766
|
+
return null;
|
|
4767
|
+
},
|
|
4768
|
+
agentPath(_name, _config) {
|
|
4769
|
+
return null;
|
|
4770
|
+
}
|
|
4771
|
+
},
|
|
4772
|
+
buildImportPaths: buildKiroImportPaths,
|
|
4773
|
+
detectionPaths: [KIRO_STEERING_DIR, KIRO_SKILLS_DIR, KIRO_HOOKS_DIR, KIRO_MCP_FILE, KIRO_IGNORE]
|
|
4774
|
+
};
|
|
4775
|
+
|
|
4382
4776
|
// src/targets/gemini-cli/constants.ts
|
|
4383
4777
|
var GEMINI_TARGET = "gemini-cli";
|
|
4384
4778
|
var GEMINI_ROOT = "GEMINI.md";
|
|
@@ -4441,7 +4835,7 @@ function mapHookEvent2(event) {
|
|
|
4441
4835
|
return null;
|
|
4442
4836
|
}
|
|
4443
4837
|
}
|
|
4444
|
-
function
|
|
4838
|
+
function generateRules7(canonical) {
|
|
4445
4839
|
const root = canonical.rules.find((r) => r.root);
|
|
4446
4840
|
const nonRootRules = canonical.rules.filter((r) => {
|
|
4447
4841
|
if (r.root) return false;
|
|
@@ -4496,7 +4890,7 @@ function generateAgents5(canonical) {
|
|
|
4496
4890
|
return { path: `${GEMINI_AGENTS_DIR}/${agent.name}.md`, content };
|
|
4497
4891
|
});
|
|
4498
4892
|
}
|
|
4499
|
-
function
|
|
4893
|
+
function generateSkills7(canonical) {
|
|
4500
4894
|
const outputs = [];
|
|
4501
4895
|
for (const skill of canonical.skills) {
|
|
4502
4896
|
const frontmatter = {
|
|
@@ -4560,7 +4954,7 @@ function generateSettings(canonical) {
|
|
|
4560
4954
|
if (Object.keys(settings).length === 0) return [];
|
|
4561
4955
|
return [{ path: GEMINI_SETTINGS, content: JSON.stringify(settings, null, 2) }];
|
|
4562
4956
|
}
|
|
4563
|
-
function
|
|
4957
|
+
function generateIgnore5(canonical) {
|
|
4564
4958
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
4565
4959
|
return [{ path: GEMINI_IGNORE, content: canonical.ignore.join("\n") }];
|
|
4566
4960
|
}
|
|
@@ -4644,14 +5038,14 @@ function generateGeminiPermissionsPolicies(canonical) {
|
|
|
4644
5038
|
|
|
4645
5039
|
// src/targets/gemini-cli/importer.ts
|
|
4646
5040
|
import { realpathSync } from "fs";
|
|
4647
|
-
import { join as
|
|
5041
|
+
import { join as join26, basename as basename18, dirname as dirname13, relative as relative9 } from "path";
|
|
4648
5042
|
|
|
4649
5043
|
// src/targets/gemini-cli/importer-mappers.ts
|
|
4650
|
-
import { join as
|
|
5044
|
+
import { join as join24 } from "path";
|
|
4651
5045
|
import { parse as parseToml2 } from "smol-toml";
|
|
4652
5046
|
|
|
4653
5047
|
// src/targets/gemini-cli/format-helpers.ts
|
|
4654
|
-
import { join as
|
|
5048
|
+
import { join as join23 } from "path";
|
|
4655
5049
|
import { parse as parseToml } from "smol-toml";
|
|
4656
5050
|
import { stringify as stringifyYaml } from "yaml";
|
|
4657
5051
|
function mapGeminiHookEvent(event) {
|
|
@@ -4692,7 +5086,7 @@ function parseFlexibleFrontmatter(content) {
|
|
|
4692
5086
|
return { frontmatter: {}, body: content.trim() };
|
|
4693
5087
|
}
|
|
4694
5088
|
async function importGeminiSettings(projectRoot, results) {
|
|
4695
|
-
const settingsPath =
|
|
5089
|
+
const settingsPath = join23(projectRoot, GEMINI_SETTINGS);
|
|
4696
5090
|
const settingsContent = await readFileSafe(settingsPath);
|
|
4697
5091
|
if (settingsContent === null) return;
|
|
4698
5092
|
let settings;
|
|
@@ -4703,8 +5097,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4703
5097
|
if (!settings) return;
|
|
4704
5098
|
const mcpServers = settings.mcpServers;
|
|
4705
5099
|
if (mcpServers !== void 0 && typeof mcpServers === "object" && mcpServers !== null && Object.keys(mcpServers).length > 0) {
|
|
4706
|
-
const mcpPath =
|
|
4707
|
-
await mkdirp(
|
|
5100
|
+
const mcpPath = join23(projectRoot, GEMINI_CANONICAL_MCP);
|
|
5101
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4708
5102
|
await writeFileAtomic(mcpPath, JSON.stringify({ mcpServers }, null, 2));
|
|
4709
5103
|
results.push({
|
|
4710
5104
|
fromTool: "gemini-cli",
|
|
@@ -4715,8 +5109,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4715
5109
|
}
|
|
4716
5110
|
const ignorePatterns = settings.ignorePatterns;
|
|
4717
5111
|
if (Array.isArray(ignorePatterns) && ignorePatterns.length > 0 && ignorePatterns.every((p) => typeof p === "string")) {
|
|
4718
|
-
const ignorePath =
|
|
4719
|
-
await mkdirp(
|
|
5112
|
+
const ignorePath = join23(projectRoot, GEMINI_CANONICAL_IGNORE);
|
|
5113
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4720
5114
|
await writeFileAtomic(ignorePath, ignorePatterns.join("\n") + "\n");
|
|
4721
5115
|
results.push({
|
|
4722
5116
|
fromTool: "gemini-cli",
|
|
@@ -4758,8 +5152,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4758
5152
|
);
|
|
4759
5153
|
if (mappedHooks.length > 0) {
|
|
4760
5154
|
const hooksYaml = Object.fromEntries(mappedHooks);
|
|
4761
|
-
const hooksPath =
|
|
4762
|
-
await mkdirp(
|
|
5155
|
+
const hooksPath = join23(projectRoot, GEMINI_CANONICAL_HOOKS);
|
|
5156
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4763
5157
|
await writeFileAtomic(hooksPath, stringifyYaml(hooksYaml, { lineWidth: 0 }).trimEnd());
|
|
4764
5158
|
results.push({
|
|
4765
5159
|
fromTool: "gemini-cli",
|
|
@@ -4771,13 +5165,13 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4771
5165
|
}
|
|
4772
5166
|
}
|
|
4773
5167
|
async function importGeminiIgnore(projectRoot, results) {
|
|
4774
|
-
const geminiIgnorePath =
|
|
5168
|
+
const geminiIgnorePath = join23(projectRoot, GEMINI_IGNORE);
|
|
4775
5169
|
const geminiIgnoreContent = await readFileSafe(geminiIgnorePath);
|
|
4776
5170
|
if (geminiIgnoreContent !== null && geminiIgnoreContent.trim()) {
|
|
4777
5171
|
const patterns = geminiIgnoreContent.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
4778
5172
|
if (patterns.length > 0) {
|
|
4779
|
-
await mkdirp(
|
|
4780
|
-
const ignorePath =
|
|
5173
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
5174
|
+
const ignorePath = join23(projectRoot, GEMINI_CANONICAL_IGNORE);
|
|
4781
5175
|
await writeFileAtomic(ignorePath, patterns.join("\n") + "\n");
|
|
4782
5176
|
results.push({
|
|
4783
5177
|
fromTool: "gemini-cli",
|
|
@@ -4792,7 +5186,7 @@ async function importGeminiIgnore(projectRoot, results) {
|
|
|
4792
5186
|
// src/targets/gemini-cli/importer-mappers.ts
|
|
4793
5187
|
async function mapGeminiRuleFile(relativePath, destDir, normalizeTo) {
|
|
4794
5188
|
const relativeMdPath = relativePath.replace(/\\/g, "/");
|
|
4795
|
-
const destPath =
|
|
5189
|
+
const destPath = join24(destDir, relativeMdPath);
|
|
4796
5190
|
const { frontmatter, body } = parseFlexibleFrontmatter(normalizeTo(destPath));
|
|
4797
5191
|
const globs = toGlobsArray(frontmatter.globs);
|
|
4798
5192
|
const canonicalFm = {
|
|
@@ -4812,7 +5206,7 @@ async function mapGeminiRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
4812
5206
|
}
|
|
4813
5207
|
async function mapGeminiCommandFile(relativePath, destDir, normalizeTo) {
|
|
4814
5208
|
const relativeMdPath = relativePath.replace(/\.(toml|md)$/i, ".md").replace(/\\/g, "/");
|
|
4815
|
-
const destPath =
|
|
5209
|
+
const destPath = join24(destDir, relativeMdPath);
|
|
4816
5210
|
const normalized = normalizeTo(destPath);
|
|
4817
5211
|
const { frontmatter, body } = relativePath.endsWith(".toml") ? parseTomlCommand(normalized) : parseFlexibleFrontmatter(normalized);
|
|
4818
5212
|
const fromCamel = toToolsArray2(frontmatter.allowedTools);
|
|
@@ -4849,7 +5243,7 @@ function parseTomlCommand(normalized) {
|
|
|
4849
5243
|
// src/targets/gemini-cli/policies-importer.ts
|
|
4850
5244
|
import { parse as parseToml3 } from "smol-toml";
|
|
4851
5245
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
4852
|
-
import { join as
|
|
5246
|
+
import { join as join25 } from "path";
|
|
4853
5247
|
function unescapeRegexLiteral(value) {
|
|
4854
5248
|
return value.replace(/\\(.)/g, "$1");
|
|
4855
5249
|
}
|
|
@@ -4877,7 +5271,7 @@ function argsPatternToReadExpr(argsPattern) {
|
|
|
4877
5271
|
}
|
|
4878
5272
|
async function importGeminiPolicies(projectRoot) {
|
|
4879
5273
|
const results = [];
|
|
4880
|
-
const policiesDir =
|
|
5274
|
+
const policiesDir = join25(projectRoot, GEMINI_POLICIES_DIR);
|
|
4881
5275
|
let policyFiles;
|
|
4882
5276
|
try {
|
|
4883
5277
|
policyFiles = await readDirRecursive(policiesDir);
|
|
@@ -4938,13 +5332,13 @@ async function importGeminiPolicies(projectRoot) {
|
|
|
4938
5332
|
}
|
|
4939
5333
|
}
|
|
4940
5334
|
if (allow.length === 0 && deny.length === 0) return results;
|
|
4941
|
-
await mkdirp(
|
|
4942
|
-
const outPath =
|
|
5335
|
+
await mkdirp(join25(projectRoot, ".agentsmesh"));
|
|
5336
|
+
const outPath = join25(projectRoot, GEMINI_CANONICAL_PERMISSIONS);
|
|
4943
5337
|
const yaml = stringifyYaml2({ allow, deny });
|
|
4944
5338
|
await writeFileAtomic(outPath, yaml.trimEnd() + "\n");
|
|
4945
5339
|
results.push({
|
|
4946
5340
|
fromTool: GEMINI_TARGET,
|
|
4947
|
-
fromPath:
|
|
5341
|
+
fromPath: join25(projectRoot, GEMINI_POLICIES_DIR),
|
|
4948
5342
|
toPath: GEMINI_CANONICAL_PERMISSIONS,
|
|
4949
5343
|
feature: "permissions"
|
|
4950
5344
|
});
|
|
@@ -4956,12 +5350,12 @@ async function importFromGemini(projectRoot) {
|
|
|
4956
5350
|
const results = [];
|
|
4957
5351
|
const normalize = await createImportReferenceNormalizer(GEMINI_TARGET, projectRoot);
|
|
4958
5352
|
const normalizeCodex = await createImportReferenceNormalizer("codex-cli", projectRoot);
|
|
4959
|
-
const rulesDir =
|
|
4960
|
-
const commandsDir =
|
|
4961
|
-
const geminiRootPath =
|
|
4962
|
-
const compatAgentsRootPath =
|
|
4963
|
-
const compatInnerRootPath =
|
|
4964
|
-
const systemPath =
|
|
5353
|
+
const rulesDir = join26(projectRoot, GEMINI_CANONICAL_RULES_DIR);
|
|
5354
|
+
const commandsDir = join26(projectRoot, GEMINI_CANONICAL_COMMANDS_DIR);
|
|
5355
|
+
const geminiRootPath = join26(projectRoot, GEMINI_ROOT);
|
|
5356
|
+
const compatAgentsRootPath = join26(projectRoot, GEMINI_COMPAT_AGENTS);
|
|
5357
|
+
const compatInnerRootPath = join26(projectRoot, GEMINI_COMPAT_INNER_ROOT);
|
|
5358
|
+
const systemPath = join26(projectRoot, GEMINI_SYSTEM);
|
|
4965
5359
|
const geminiRootContent = await readFileSafe(geminiRootPath);
|
|
4966
5360
|
const compatAgentsRootContent = await readFileSafe(compatAgentsRootPath);
|
|
4967
5361
|
const compatInnerRootContent = await readFileSafe(compatInnerRootPath);
|
|
@@ -4976,7 +5370,7 @@ async function importFromGemini(projectRoot) {
|
|
|
4976
5370
|
const rootContent = rootCandidate?.content ?? null;
|
|
4977
5371
|
if (rootContent !== null) {
|
|
4978
5372
|
await mkdirp(rulesDir);
|
|
4979
|
-
const destPath =
|
|
5373
|
+
const destPath = join26(rulesDir, "_root.md");
|
|
4980
5374
|
const compatNormalized = rootSourcePath === compatAgentsRootPath || rootSourcePath === compatInnerRootPath ? normalize(normalizeCodex(rootContent, rootSourcePath, destPath), rootSourcePath, destPath) : normalize(rootContent, rootSourcePath, destPath);
|
|
4981
5375
|
const normalizedRoot = stripProjectRootCanonicalPrefix(
|
|
4982
5376
|
compatNormalized.replace(/\.agents\/skills\//g, ".agentsmesh/skills/").replace(/\.agents\\skills\\/g, ".agentsmesh/skills/"),
|
|
@@ -4997,7 +5391,7 @@ async function importFromGemini(projectRoot) {
|
|
|
4997
5391
|
feature: "rules"
|
|
4998
5392
|
});
|
|
4999
5393
|
}
|
|
5000
|
-
const geminiRulesPath =
|
|
5394
|
+
const geminiRulesPath = join26(projectRoot, GEMINI_RULES_DIR);
|
|
5001
5395
|
results.push(
|
|
5002
5396
|
...await importFileDirectory({
|
|
5003
5397
|
srcDir: geminiRulesPath,
|
|
@@ -5008,7 +5402,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5008
5402
|
mapEntry: ({ relativePath, normalizeTo }) => mapGeminiRuleFile(relativePath, rulesDir, normalizeTo)
|
|
5009
5403
|
})
|
|
5010
5404
|
);
|
|
5011
|
-
const geminiCommandsPath =
|
|
5405
|
+
const geminiCommandsPath = join26(projectRoot, GEMINI_COMMANDS_DIR);
|
|
5012
5406
|
results.push(
|
|
5013
5407
|
...await importFileDirectory({
|
|
5014
5408
|
srcDir: geminiCommandsPath,
|
|
@@ -5019,19 +5413,19 @@ async function importFromGemini(projectRoot) {
|
|
|
5019
5413
|
mapEntry: ({ relativePath, normalizeTo }) => mapGeminiCommandFile(relativePath, commandsDir, normalizeTo)
|
|
5020
5414
|
})
|
|
5021
5415
|
);
|
|
5022
|
-
const geminiSkillsPath =
|
|
5416
|
+
const geminiSkillsPath = join26(projectRoot, GEMINI_SKILLS_DIR);
|
|
5023
5417
|
const skillDirs = await readDirRecursive(geminiSkillsPath);
|
|
5024
|
-
const skillMdFiles = skillDirs.filter((f) =>
|
|
5418
|
+
const skillMdFiles = skillDirs.filter((f) => basename18(f) === "SKILL.md");
|
|
5025
5419
|
for (const srcPath of skillMdFiles) {
|
|
5026
5420
|
const content = await readFileSafe(srcPath);
|
|
5027
5421
|
if (!content) continue;
|
|
5028
|
-
const skillName =
|
|
5422
|
+
const skillName = basename18(srcPath.slice(0, -"/SKILL.md".length));
|
|
5029
5423
|
const rawParsed = parseFrontmatter(content);
|
|
5030
5424
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, skillName);
|
|
5031
5425
|
if (projectedAgent) {
|
|
5032
|
-
const agentsDir =
|
|
5426
|
+
const agentsDir = join26(projectRoot, GEMINI_CANONICAL_AGENTS_DIR);
|
|
5033
5427
|
await mkdirp(agentsDir);
|
|
5034
|
-
const agentPath =
|
|
5428
|
+
const agentPath = join26(agentsDir, `${projectedAgent.name}.md`);
|
|
5035
5429
|
await writeFileAtomic(
|
|
5036
5430
|
agentPath,
|
|
5037
5431
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, srcPath, agentPath))
|
|
@@ -5044,9 +5438,9 @@ async function importFromGemini(projectRoot) {
|
|
|
5044
5438
|
});
|
|
5045
5439
|
continue;
|
|
5046
5440
|
}
|
|
5047
|
-
const destPath =
|
|
5441
|
+
const destPath = join26(projectRoot, GEMINI_CANONICAL_SKILLS_DIR, skillName, "SKILL.md");
|
|
5048
5442
|
const normalized = normalize(content, srcPath, destPath);
|
|
5049
|
-
const skillDir =
|
|
5443
|
+
const skillDir = join26(projectRoot, GEMINI_CANONICAL_SKILLS_DIR, skillName);
|
|
5050
5444
|
await mkdirp(skillDir);
|
|
5051
5445
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
5052
5446
|
await writeFileAtomic(
|
|
@@ -5065,7 +5459,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5065
5459
|
const supportContent = await readFileSafe(absPath);
|
|
5066
5460
|
if (supportContent === null) continue;
|
|
5067
5461
|
const relPath = relative9(dirname13(srcPath), absPath).replace(/\\/g, "/");
|
|
5068
|
-
const destSupportPath =
|
|
5462
|
+
const destSupportPath = join26(skillDir, relPath);
|
|
5069
5463
|
await mkdirp(dirname13(destSupportPath));
|
|
5070
5464
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
5071
5465
|
results.push({
|
|
@@ -5076,7 +5470,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5076
5470
|
});
|
|
5077
5471
|
}
|
|
5078
5472
|
}
|
|
5079
|
-
const geminiAgentsPath =
|
|
5473
|
+
const geminiAgentsPath = join26(projectRoot, GEMINI_AGENTS_DIR);
|
|
5080
5474
|
try {
|
|
5081
5475
|
const agentFiles = await readDirRecursive(geminiAgentsPath);
|
|
5082
5476
|
const agentMdFiles = agentFiles.filter((f) => f.endsWith(".md"));
|
|
@@ -5086,9 +5480,9 @@ async function importFromGemini(projectRoot) {
|
|
|
5086
5480
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
5087
5481
|
const relPath = relative9(geminiAgentsPath, srcPath).replace(/\\/g, "/");
|
|
5088
5482
|
const relativeMdPath = relPath.replace(/\.md$/i, ".md");
|
|
5089
|
-
const agentsDir =
|
|
5483
|
+
const agentsDir = join26(projectRoot, GEMINI_CANONICAL_AGENTS_DIR);
|
|
5090
5484
|
await mkdirp(agentsDir);
|
|
5091
|
-
const destPath =
|
|
5485
|
+
const destPath = join26(agentsDir, relativeMdPath);
|
|
5092
5486
|
const normalizedBody = normalize(body, srcPath, destPath);
|
|
5093
5487
|
await writeFileAtomic(
|
|
5094
5488
|
destPath,
|
|
@@ -5096,7 +5490,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5096
5490
|
destPath,
|
|
5097
5491
|
{
|
|
5098
5492
|
...frontmatter,
|
|
5099
|
-
name: typeof frontmatter.name === "string" ? frontmatter.name :
|
|
5493
|
+
name: typeof frontmatter.name === "string" ? frontmatter.name : basename18(relativeMdPath, ".md"),
|
|
5100
5494
|
maxTurns: frontmatter.maxTurns ?? frontmatter["max-turns"] ?? frontmatter.max_turns,
|
|
5101
5495
|
permissionMode: frontmatter.permissionMode ?? frontmatter["permission-mode"] ?? frontmatter.permission_mode,
|
|
5102
5496
|
disallowedTools: frontmatter.disallowedTools ?? frontmatter["disallowed-tools"] ?? frontmatter.disallowed_tools
|
|
@@ -5137,27 +5531,27 @@ function stripProjectRootCanonicalPrefix(content, projectRoot) {
|
|
|
5137
5531
|
}
|
|
5138
5532
|
|
|
5139
5533
|
// src/targets/gemini-cli/linter.ts
|
|
5140
|
-
function
|
|
5534
|
+
function lintRules7(canonical, projectRoot, projectFiles) {
|
|
5141
5535
|
const diags = validateRules(canonical, projectRoot, projectFiles);
|
|
5142
5536
|
return diags.map((d) => ({ ...d, target: GEMINI_TARGET }));
|
|
5143
5537
|
}
|
|
5144
5538
|
|
|
5145
5539
|
// src/targets/gemini-cli/index.ts
|
|
5146
|
-
var
|
|
5540
|
+
var target7 = {
|
|
5147
5541
|
name: "gemini-cli",
|
|
5148
5542
|
primaryRootInstructionPath: GEMINI_ROOT,
|
|
5149
|
-
generateRules:
|
|
5543
|
+
generateRules: generateRules7,
|
|
5150
5544
|
generateCommands: generateCommands6,
|
|
5151
5545
|
generateAgents: generateAgents5,
|
|
5152
|
-
generateSkills:
|
|
5546
|
+
generateSkills: generateSkills7,
|
|
5153
5547
|
generateSettings,
|
|
5154
|
-
generateIgnore:
|
|
5548
|
+
generateIgnore: generateIgnore5,
|
|
5155
5549
|
generatePermissions: generateGeminiPermissionsPolicies,
|
|
5156
5550
|
importFrom: importFromGemini
|
|
5157
5551
|
};
|
|
5158
|
-
var
|
|
5552
|
+
var descriptor7 = {
|
|
5159
5553
|
id: "gemini-cli",
|
|
5160
|
-
generators:
|
|
5554
|
+
generators: target7,
|
|
5161
5555
|
capabilities: {
|
|
5162
5556
|
rules: "native",
|
|
5163
5557
|
commands: "native",
|
|
@@ -5169,7 +5563,7 @@ var descriptor6 = {
|
|
|
5169
5563
|
permissions: "partial"
|
|
5170
5564
|
},
|
|
5171
5565
|
emptyImportMessage: "No Gemini CLI config found (GEMINI.md or .gemini/rules, .gemini/commands, .gemini/settings.json).",
|
|
5172
|
-
lintRules:
|
|
5566
|
+
lintRules: lintRules7,
|
|
5173
5567
|
skillDir: ".gemini/skills",
|
|
5174
5568
|
paths: {
|
|
5175
5569
|
rulePath(_slug, _rule) {
|
|
@@ -5193,7 +5587,7 @@ var descriptor6 = {
|
|
|
5193
5587
|
};
|
|
5194
5588
|
|
|
5195
5589
|
// src/targets/cline/generator.ts
|
|
5196
|
-
import { basename as
|
|
5590
|
+
import { basename as basename19 } from "path";
|
|
5197
5591
|
|
|
5198
5592
|
// src/targets/cline/constants.ts
|
|
5199
5593
|
var CLINE_TARGET = "cline";
|
|
@@ -5214,10 +5608,10 @@ var CLINE_CANONICAL_SKILLS_DIR = ".agentsmesh/skills";
|
|
|
5214
5608
|
|
|
5215
5609
|
// src/targets/cline/generator.ts
|
|
5216
5610
|
function ruleSlug3(source) {
|
|
5217
|
-
const name =
|
|
5611
|
+
const name = basename19(source, ".md");
|
|
5218
5612
|
return name === "_root" ? "root" : name;
|
|
5219
5613
|
}
|
|
5220
|
-
function
|
|
5614
|
+
function generateRules8(canonical) {
|
|
5221
5615
|
const outputs = [];
|
|
5222
5616
|
const root = canonical.rules.find((r) => r.root);
|
|
5223
5617
|
if (root) {
|
|
@@ -5250,12 +5644,12 @@ ${body}` : desc || body;
|
|
|
5250
5644
|
return { path: `${CLINE_WORKFLOWS_DIR}/${cmd.name}.md`, content };
|
|
5251
5645
|
});
|
|
5252
5646
|
}
|
|
5253
|
-
function
|
|
5647
|
+
function generateIgnore6(canonical) {
|
|
5254
5648
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
5255
5649
|
const content = canonical.ignore.join("\n");
|
|
5256
5650
|
return [{ path: CLINE_IGNORE, content }];
|
|
5257
5651
|
}
|
|
5258
|
-
function
|
|
5652
|
+
function generateMcp6(canonical) {
|
|
5259
5653
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
5260
5654
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
5261
5655
|
return [{ path: CLINE_MCP_SETTINGS, content }];
|
|
@@ -5279,7 +5673,7 @@ function buildHookScript(command, matcher) {
|
|
|
5279
5673
|
""
|
|
5280
5674
|
].join("\n");
|
|
5281
5675
|
}
|
|
5282
|
-
function
|
|
5676
|
+
function generateHooks5(canonical) {
|
|
5283
5677
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
5284
5678
|
const outputs = [];
|
|
5285
5679
|
for (const [event, entries] of Object.entries(canonical.hooks)) {
|
|
@@ -5296,7 +5690,7 @@ function generateHooks4(canonical) {
|
|
|
5296
5690
|
}
|
|
5297
5691
|
return outputs;
|
|
5298
5692
|
}
|
|
5299
|
-
function
|
|
5693
|
+
function generateSkills8(canonical) {
|
|
5300
5694
|
const outputs = [];
|
|
5301
5695
|
for (const skill of canonical.skills) {
|
|
5302
5696
|
const frontmatter = {
|
|
@@ -5322,15 +5716,15 @@ function generateSkills7(canonical) {
|
|
|
5322
5716
|
|
|
5323
5717
|
// src/targets/cline/importer.ts
|
|
5324
5718
|
import { stat as stat3 } from "fs/promises";
|
|
5325
|
-
import { join as
|
|
5719
|
+
import { join as join30 } from "path";
|
|
5326
5720
|
|
|
5327
5721
|
// src/targets/cline/importer-mappers.ts
|
|
5328
|
-
import { join as
|
|
5722
|
+
import { join as join27 } from "path";
|
|
5329
5723
|
async function mapClineRuleFile(relativePath, destDir, normalizeTo) {
|
|
5330
5724
|
if (relativePath === "workflows" || relativePath.startsWith("workflows/")) return null;
|
|
5331
5725
|
const relativeMdPath = relativePath.replace(/\\/g, "/");
|
|
5332
5726
|
if (relativeMdPath === "_root.md") return null;
|
|
5333
|
-
const destPath =
|
|
5727
|
+
const destPath = join27(destDir, relativeMdPath);
|
|
5334
5728
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
5335
5729
|
const globs = toGlobsArray(frontmatter.paths ?? frontmatter.globs);
|
|
5336
5730
|
const canonicalFm = {
|
|
@@ -5349,7 +5743,7 @@ async function mapClineRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
5349
5743
|
};
|
|
5350
5744
|
}
|
|
5351
5745
|
async function mapClineWorkflowFile(relativePath, destDir, normalizeTo) {
|
|
5352
|
-
const destPath =
|
|
5746
|
+
const destPath = join27(destDir, relativePath);
|
|
5353
5747
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
5354
5748
|
const hasFrontmatterDescription = Object.prototype.hasOwnProperty.call(
|
|
5355
5749
|
frontmatter,
|
|
@@ -5387,7 +5781,7 @@ async function mapClineWorkflowFile(relativePath, destDir, normalizeTo) {
|
|
|
5387
5781
|
}
|
|
5388
5782
|
|
|
5389
5783
|
// src/targets/cline/mcp-mapper.ts
|
|
5390
|
-
import { join as
|
|
5784
|
+
import { join as join28 } from "path";
|
|
5391
5785
|
function mapClineServerToCanonical(raw) {
|
|
5392
5786
|
if (!raw || typeof raw !== "object") return null;
|
|
5393
5787
|
const obj = raw;
|
|
@@ -5412,7 +5806,7 @@ function mapClineServerToCanonical(raw) {
|
|
|
5412
5806
|
}
|
|
5413
5807
|
async function importClineMcp(projectRoot, results) {
|
|
5414
5808
|
const candidatePaths = [CLINE_MCP_SETTINGS, CLINE_MCP_SETTINGS_LEGACY].map(
|
|
5415
|
-
(path) =>
|
|
5809
|
+
(path) => join28(projectRoot, path)
|
|
5416
5810
|
);
|
|
5417
5811
|
let mcpPath = null;
|
|
5418
5812
|
let mcpContent = null;
|
|
@@ -5439,9 +5833,9 @@ async function importClineMcp(projectRoot, results) {
|
|
|
5439
5833
|
if (server) mcpServers[n] = server;
|
|
5440
5834
|
}
|
|
5441
5835
|
if (Object.keys(mcpServers).length > 0) {
|
|
5442
|
-
await mkdirp(
|
|
5836
|
+
await mkdirp(join28(projectRoot, ".agentsmesh"));
|
|
5443
5837
|
await writeFileAtomic(
|
|
5444
|
-
|
|
5838
|
+
join28(projectRoot, CLINE_CANONICAL_MCP),
|
|
5445
5839
|
JSON.stringify({ mcpServers }, null, 2)
|
|
5446
5840
|
);
|
|
5447
5841
|
results.push({
|
|
@@ -5456,16 +5850,16 @@ async function importClineMcp(projectRoot, results) {
|
|
|
5456
5850
|
|
|
5457
5851
|
// src/targets/cline/skills-helpers.ts
|
|
5458
5852
|
import { readdir as readdir6 } from "fs/promises";
|
|
5459
|
-
import { join as
|
|
5853
|
+
import { join as join29 } from "path";
|
|
5460
5854
|
async function importClineSkills(projectRoot, results, normalize) {
|
|
5461
|
-
const skillsDir =
|
|
5855
|
+
const skillsDir = join29(projectRoot, CLINE_SKILLS_DIR);
|
|
5462
5856
|
const skillDirs = [];
|
|
5463
5857
|
try {
|
|
5464
5858
|
const entries = await readdir6(skillsDir, { withFileTypes: true });
|
|
5465
5859
|
for (const ent of entries) {
|
|
5466
5860
|
if (!ent.isDirectory()) continue;
|
|
5467
|
-
const skillPath =
|
|
5468
|
-
const skillMd =
|
|
5861
|
+
const skillPath = join29(skillsDir, ent.name);
|
|
5862
|
+
const skillMd = join29(skillPath, "SKILL.md");
|
|
5469
5863
|
const content = await readFileSafe(skillMd);
|
|
5470
5864
|
if (!content) continue;
|
|
5471
5865
|
skillDirs.push({ name: ent.name, path: skillPath });
|
|
@@ -5473,15 +5867,15 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5473
5867
|
} catch {
|
|
5474
5868
|
}
|
|
5475
5869
|
for (const { name, path: skillPath } of skillDirs) {
|
|
5476
|
-
const skillMdPath =
|
|
5870
|
+
const skillMdPath = join29(skillPath, "SKILL.md");
|
|
5477
5871
|
const content = await readFileSafe(skillMdPath);
|
|
5478
5872
|
if (!content) continue;
|
|
5479
5873
|
const rawParsed = parseFrontmatter(content);
|
|
5480
5874
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, name);
|
|
5481
5875
|
if (projectedAgent) {
|
|
5482
|
-
const destAgentsDir =
|
|
5876
|
+
const destAgentsDir = join29(projectRoot, CLINE_CANONICAL_AGENTS_DIR);
|
|
5483
5877
|
await mkdirp(destAgentsDir);
|
|
5484
|
-
const agentPath =
|
|
5878
|
+
const agentPath = join29(destAgentsDir, `${projectedAgent.name}.md`);
|
|
5485
5879
|
await writeFileAtomic(
|
|
5486
5880
|
agentPath,
|
|
5487
5881
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
@@ -5494,10 +5888,10 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5494
5888
|
});
|
|
5495
5889
|
continue;
|
|
5496
5890
|
}
|
|
5497
|
-
const destSkillPath =
|
|
5891
|
+
const destSkillPath = join29(projectRoot, CLINE_CANONICAL_SKILLS_DIR, name, "SKILL.md");
|
|
5498
5892
|
const normalized = normalize(content, skillMdPath, destSkillPath);
|
|
5499
5893
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
5500
|
-
const destSkillDir =
|
|
5894
|
+
const destSkillDir = join29(projectRoot, CLINE_CANONICAL_SKILLS_DIR, name);
|
|
5501
5895
|
await mkdirp(destSkillDir);
|
|
5502
5896
|
const skillContent = await serializeImportedSkillWithFallback(
|
|
5503
5897
|
destSkillPath,
|
|
@@ -5517,8 +5911,8 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5517
5911
|
const relPath = absPath.slice(skillPath.length + 1).replace(/\\/g, "/");
|
|
5518
5912
|
const supportContent = await readFileSafe(absPath);
|
|
5519
5913
|
if (supportContent === null) continue;
|
|
5520
|
-
const destSupportPath =
|
|
5521
|
-
await mkdirp(
|
|
5914
|
+
const destSupportPath = join29(destSkillDir, relPath);
|
|
5915
|
+
await mkdirp(join29(destSupportPath, ".."));
|
|
5522
5916
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
5523
5917
|
results.push({
|
|
5524
5918
|
fromTool: CLINE_TARGET,
|
|
@@ -5534,9 +5928,9 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5534
5928
|
async function importFromCline(projectRoot) {
|
|
5535
5929
|
const results = [];
|
|
5536
5930
|
const normalize = await createImportReferenceNormalizer(CLINE_TARGET, projectRoot);
|
|
5537
|
-
const destRulesDir =
|
|
5538
|
-
const clineRulesPath =
|
|
5539
|
-
const clineRulesRaw =
|
|
5931
|
+
const destRulesDir = join30(projectRoot, CLINE_CANONICAL_RULES_DIR);
|
|
5932
|
+
const clineRulesPath = join30(projectRoot, CLINE_RULES_DIR);
|
|
5933
|
+
const clineRulesRaw = join30(projectRoot, CLINE_RULES_DIR);
|
|
5540
5934
|
let clineRulesIsFile = false;
|
|
5541
5935
|
try {
|
|
5542
5936
|
const clineRulesStat = await stat3(clineRulesRaw);
|
|
@@ -5547,7 +5941,7 @@ async function importFromCline(projectRoot) {
|
|
|
5547
5941
|
const flatContent = await readFileSafe(clineRulesRaw);
|
|
5548
5942
|
if (flatContent !== null) {
|
|
5549
5943
|
await mkdirp(destRulesDir);
|
|
5550
|
-
const destPath =
|
|
5944
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5551
5945
|
const { frontmatter, body } = parseFrontmatter(
|
|
5552
5946
|
normalize(flatContent, clineRulesRaw, destPath)
|
|
5553
5947
|
);
|
|
@@ -5564,15 +5958,15 @@ async function importFromCline(projectRoot) {
|
|
|
5564
5958
|
}
|
|
5565
5959
|
} else {
|
|
5566
5960
|
let rootSourcePath = null;
|
|
5567
|
-
const rootPath =
|
|
5961
|
+
const rootPath = join30(clineRulesPath, "_root.md");
|
|
5568
5962
|
const rootContent = await readFileSafe(rootPath);
|
|
5569
5963
|
if (rootContent === null) {
|
|
5570
|
-
const agentsMdPath =
|
|
5964
|
+
const agentsMdPath = join30(projectRoot, CLINE_AGENTS_MD);
|
|
5571
5965
|
const agentsMdContent = await readFileSafe(agentsMdPath);
|
|
5572
5966
|
if (agentsMdContent !== null) {
|
|
5573
5967
|
rootSourcePath = agentsMdPath;
|
|
5574
5968
|
await mkdirp(destRulesDir);
|
|
5575
|
-
const destPath =
|
|
5969
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5576
5970
|
const { frontmatter, body } = parseFrontmatter(
|
|
5577
5971
|
normalize(agentsMdContent, agentsMdPath, destPath)
|
|
5578
5972
|
);
|
|
@@ -5595,7 +5989,7 @@ async function importFromCline(projectRoot) {
|
|
|
5595
5989
|
if (fc !== null) {
|
|
5596
5990
|
rootSourcePath = first;
|
|
5597
5991
|
await mkdirp(destRulesDir);
|
|
5598
|
-
const destPath =
|
|
5992
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5599
5993
|
const { frontmatter, body } = parseFrontmatter(normalize(fc, first, destPath));
|
|
5600
5994
|
const hasRoot = frontmatter.root === true;
|
|
5601
5995
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -5613,7 +6007,7 @@ async function importFromCline(projectRoot) {
|
|
|
5613
6007
|
} else {
|
|
5614
6008
|
rootSourcePath = rootPath;
|
|
5615
6009
|
await mkdirp(destRulesDir);
|
|
5616
|
-
const destPath =
|
|
6010
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5617
6011
|
const { frontmatter, body } = parseFrontmatter(normalize(rootContent, rootPath, destPath));
|
|
5618
6012
|
const hasRoot = frontmatter.root === true;
|
|
5619
6013
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -5640,7 +6034,7 @@ async function importFromCline(projectRoot) {
|
|
|
5640
6034
|
})
|
|
5641
6035
|
);
|
|
5642
6036
|
}
|
|
5643
|
-
const ignorePath =
|
|
6037
|
+
const ignorePath = join30(projectRoot, CLINE_IGNORE);
|
|
5644
6038
|
const ignoreContent = await readFileSafe(ignorePath);
|
|
5645
6039
|
if (ignoreContent !== null && ignoreContent.trim()) {
|
|
5646
6040
|
const lines = ignoreContent.split(/\r?\n/);
|
|
@@ -5650,8 +6044,8 @@ async function importFromCline(projectRoot) {
|
|
|
5650
6044
|
if (t && !t.startsWith("#")) patterns.push(t);
|
|
5651
6045
|
}
|
|
5652
6046
|
if (patterns.length > 0) {
|
|
5653
|
-
await mkdirp(
|
|
5654
|
-
const destIgnorePath =
|
|
6047
|
+
await mkdirp(join30(projectRoot, ".agentsmesh"));
|
|
6048
|
+
const destIgnorePath = join30(projectRoot, CLINE_CANONICAL_IGNORE);
|
|
5655
6049
|
await writeFileAtomic(destIgnorePath, patterns.join("\n"));
|
|
5656
6050
|
results.push({
|
|
5657
6051
|
fromTool: "cline",
|
|
@@ -5662,11 +6056,11 @@ async function importFromCline(projectRoot) {
|
|
|
5662
6056
|
}
|
|
5663
6057
|
}
|
|
5664
6058
|
await importClineMcp(projectRoot, results);
|
|
5665
|
-
const destCommandsDir =
|
|
6059
|
+
const destCommandsDir = join30(projectRoot, CLINE_CANONICAL_COMMANDS_DIR);
|
|
5666
6060
|
if (!clineRulesIsFile) {
|
|
5667
6061
|
results.push(
|
|
5668
6062
|
...await importFileDirectory({
|
|
5669
|
-
srcDir:
|
|
6063
|
+
srcDir: join30(projectRoot, CLINE_WORKFLOWS_DIR),
|
|
5670
6064
|
destDir: destCommandsDir,
|
|
5671
6065
|
extensions: [".md"],
|
|
5672
6066
|
fromTool: "cline",
|
|
@@ -5680,27 +6074,27 @@ async function importFromCline(projectRoot) {
|
|
|
5680
6074
|
}
|
|
5681
6075
|
|
|
5682
6076
|
// src/targets/cline/linter.ts
|
|
5683
|
-
function
|
|
6077
|
+
function lintRules8(canonical, projectRoot, projectFiles) {
|
|
5684
6078
|
const diags = validateRules(canonical, projectRoot, projectFiles);
|
|
5685
6079
|
return diags.map((d) => ({ ...d, target: CLINE_TARGET }));
|
|
5686
6080
|
}
|
|
5687
6081
|
|
|
5688
6082
|
// src/targets/cline/index.ts
|
|
5689
|
-
var
|
|
6083
|
+
var target8 = {
|
|
5690
6084
|
name: "cline",
|
|
5691
6085
|
primaryRootInstructionPath: CLINE_AGENTS_MD,
|
|
5692
|
-
generateRules:
|
|
6086
|
+
generateRules: generateRules8,
|
|
5693
6087
|
generateWorkflows,
|
|
5694
6088
|
generateAgents: generateAgents6,
|
|
5695
|
-
generateSkills:
|
|
5696
|
-
generateMcp:
|
|
5697
|
-
generateHooks:
|
|
5698
|
-
generateIgnore:
|
|
6089
|
+
generateSkills: generateSkills8,
|
|
6090
|
+
generateMcp: generateMcp6,
|
|
6091
|
+
generateHooks: generateHooks5,
|
|
6092
|
+
generateIgnore: generateIgnore6,
|
|
5699
6093
|
importFrom: importFromCline
|
|
5700
6094
|
};
|
|
5701
|
-
var
|
|
6095
|
+
var descriptor8 = {
|
|
5702
6096
|
id: "cline",
|
|
5703
|
-
generators:
|
|
6097
|
+
generators: target8,
|
|
5704
6098
|
capabilities: {
|
|
5705
6099
|
rules: "native",
|
|
5706
6100
|
commands: "native",
|
|
@@ -5712,7 +6106,7 @@ var descriptor7 = {
|
|
|
5712
6106
|
permissions: "none"
|
|
5713
6107
|
},
|
|
5714
6108
|
emptyImportMessage: "No Cline config found (.clinerules, .clineignore, .cline/cline_mcp_settings.json, or .cline/skills).",
|
|
5715
|
-
lintRules:
|
|
6109
|
+
lintRules: lintRules8,
|
|
5716
6110
|
skillDir: ".cline/skills",
|
|
5717
6111
|
paths: {
|
|
5718
6112
|
rulePath(slug, _rule) {
|
|
@@ -5748,7 +6142,7 @@ function usesCursorSensitiveInterpolation(server) {
|
|
|
5748
6142
|
}
|
|
5749
6143
|
|
|
5750
6144
|
// src/targets/codex-cli/generator.ts
|
|
5751
|
-
import { basename as
|
|
6145
|
+
import { basename as basename21 } from "path";
|
|
5752
6146
|
|
|
5753
6147
|
// src/targets/codex-cli/constants.ts
|
|
5754
6148
|
var CODEX_TARGET = "codex-cli";
|
|
@@ -5774,9 +6168,9 @@ var CODEX_RULE_INDEX_START = "<!-- agentsmesh:codex-rule-index:start -->";
|
|
|
5774
6168
|
var CODEX_RULE_INDEX_END = "<!-- agentsmesh:codex-rule-index:end -->";
|
|
5775
6169
|
|
|
5776
6170
|
// src/targets/codex-cli/instruction-mirror.ts
|
|
5777
|
-
import { basename as
|
|
6171
|
+
import { basename as basename20 } from "path";
|
|
5778
6172
|
function ruleSlug4(source) {
|
|
5779
|
-
return
|
|
6173
|
+
return basename20(source, ".md");
|
|
5780
6174
|
}
|
|
5781
6175
|
function codexInstructionMirrorPath(rule) {
|
|
5782
6176
|
return `${CODEX_INSTRUCTIONS_DIR}/${ruleSlug4(rule.source)}.md`;
|
|
@@ -5811,7 +6205,7 @@ function summarizeRule(rule) {
|
|
|
5811
6205
|
scopes.push(`Enforced in \`${CODEX_RULES_DIR}/${ruleSlug4(rule.source)}.rules\`.`);
|
|
5812
6206
|
}
|
|
5813
6207
|
if (rule.targets.length > 0) {
|
|
5814
|
-
scopes.push(`Targeted to ${rule.targets.map((
|
|
6208
|
+
scopes.push(`Targeted to ${rule.targets.map((target13) => `\`${target13}\``).join(", ")}.`);
|
|
5815
6209
|
}
|
|
5816
6210
|
return scopes.join(" ");
|
|
5817
6211
|
}
|
|
@@ -5868,7 +6262,7 @@ function toSafeCodexRulesContent(body) {
|
|
|
5868
6262
|
return `${lines.join("\n")}
|
|
5869
6263
|
`;
|
|
5870
6264
|
}
|
|
5871
|
-
function
|
|
6265
|
+
function generateRules9(canonical) {
|
|
5872
6266
|
const root = canonical.rules.find((r) => r.root);
|
|
5873
6267
|
const outputs = [];
|
|
5874
6268
|
if (root) {
|
|
@@ -5876,7 +6270,7 @@ function generateRules8(canonical) {
|
|
|
5876
6270
|
}
|
|
5877
6271
|
for (const rule of canonical.rules) {
|
|
5878
6272
|
if (rule.root) continue;
|
|
5879
|
-
const slug =
|
|
6273
|
+
const slug = basename21(rule.source, ".md");
|
|
5880
6274
|
if (rule.targets.length > 0 && !rule.targets.includes("codex-cli")) continue;
|
|
5881
6275
|
if (rule.codexEmit === "execution") {
|
|
5882
6276
|
outputs.push({
|
|
@@ -5891,7 +6285,7 @@ function generateRules8(canonical) {
|
|
|
5891
6285
|
}
|
|
5892
6286
|
return outputs;
|
|
5893
6287
|
}
|
|
5894
|
-
function
|
|
6288
|
+
function generateSkills9(canonical) {
|
|
5895
6289
|
const outputs = [];
|
|
5896
6290
|
for (const skill of canonical.skills) {
|
|
5897
6291
|
const frontmatter = {
|
|
@@ -5956,7 +6350,7 @@ ${body}
|
|
|
5956
6350
|
}
|
|
5957
6351
|
return lines.join("\n") + "\n";
|
|
5958
6352
|
}
|
|
5959
|
-
function
|
|
6353
|
+
function generateMcp7(canonical) {
|
|
5960
6354
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
5961
6355
|
const stdioServers = Object.fromEntries(
|
|
5962
6356
|
Object.entries(canonical.mcp.mcpServers).flatMap(
|
|
@@ -5990,10 +6384,10 @@ function needsTomlQuoting(key) {
|
|
|
5990
6384
|
}
|
|
5991
6385
|
|
|
5992
6386
|
// src/targets/codex-cli/importer.ts
|
|
5993
|
-
import { join as
|
|
6387
|
+
import { join as join34, relative as relative12, dirname as dirname15, basename as basename22 } from "path";
|
|
5994
6388
|
|
|
5995
6389
|
// src/targets/codex-cli/import-codex-non-root-rules.ts
|
|
5996
|
-
import { join as
|
|
6390
|
+
import { join as join31, relative as relative10 } from "path";
|
|
5997
6391
|
|
|
5998
6392
|
// src/targets/codex-cli/codex-rules-embed.ts
|
|
5999
6393
|
import { Buffer } from "buffer";
|
|
@@ -6039,7 +6433,7 @@ function tryParseEmbeddedCanonicalFromCodexRules(content) {
|
|
|
6039
6433
|
// src/targets/codex-cli/import-codex-non-root-rules.ts
|
|
6040
6434
|
async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
6041
6435
|
const results = [];
|
|
6042
|
-
const codexRulesPath =
|
|
6436
|
+
const codexRulesPath = join31(projectRoot, CODEX_RULES_DIR);
|
|
6043
6437
|
try {
|
|
6044
6438
|
const ruleFiles = await readDirRecursive(codexRulesPath);
|
|
6045
6439
|
const mdFiles = ruleFiles.filter((f) => f.endsWith(".md"));
|
|
@@ -6047,7 +6441,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6047
6441
|
const content = await readFileSafe(srcPath);
|
|
6048
6442
|
if (!content) continue;
|
|
6049
6443
|
const relativePath = relative10(codexRulesPath, srcPath).replace(/\\/g, "/");
|
|
6050
|
-
const destPath =
|
|
6444
|
+
const destPath = join31(destDir, relativePath);
|
|
6051
6445
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
6052
6446
|
await mkdirp(destDir);
|
|
6053
6447
|
const outFm = frontmatter.root === true ? frontmatter : { ...frontmatter, root: false };
|
|
@@ -6065,7 +6459,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6065
6459
|
const raw = await readFileSafe(srcPath);
|
|
6066
6460
|
if (!raw) continue;
|
|
6067
6461
|
const relativePath = relative10(codexRulesPath, srcPath).replace(/\\/g, "/").replace(/\.rules$/i, ".md");
|
|
6068
|
-
const destPath =
|
|
6462
|
+
const destPath = join31(destDir, relativePath);
|
|
6069
6463
|
await mkdirp(destDir);
|
|
6070
6464
|
const embedded = tryParseEmbeddedCanonicalFromCodexRules(raw);
|
|
6071
6465
|
if (embedded) {
|
|
@@ -6105,7 +6499,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6105
6499
|
}
|
|
6106
6500
|
|
|
6107
6501
|
// src/targets/codex-cli/mcp-helpers.ts
|
|
6108
|
-
import { join as
|
|
6502
|
+
import { join as join32 } from "path";
|
|
6109
6503
|
import { parse as parseToml4 } from "smol-toml";
|
|
6110
6504
|
function mapTomlServerToCanonical(raw) {
|
|
6111
6505
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -6126,8 +6520,8 @@ function mapTomlServerToCanonical(raw) {
|
|
|
6126
6520
|
env
|
|
6127
6521
|
};
|
|
6128
6522
|
}
|
|
6129
|
-
async function
|
|
6130
|
-
const configPath =
|
|
6523
|
+
async function importMcp5(projectRoot, results) {
|
|
6524
|
+
const configPath = join32(projectRoot, CODEX_CONFIG_TOML);
|
|
6131
6525
|
const content = await readFileSafe(configPath);
|
|
6132
6526
|
if (content === null) return;
|
|
6133
6527
|
let parsed;
|
|
@@ -6146,9 +6540,9 @@ async function importMcp4(projectRoot, results) {
|
|
|
6146
6540
|
if (server) mcpServers[name] = server;
|
|
6147
6541
|
}
|
|
6148
6542
|
if (Object.keys(mcpServers).length === 0) return;
|
|
6149
|
-
await mkdirp(
|
|
6543
|
+
await mkdirp(join32(projectRoot, ".agentsmesh"));
|
|
6150
6544
|
await writeFileAtomic(
|
|
6151
|
-
|
|
6545
|
+
join32(projectRoot, CODEX_CANONICAL_MCP),
|
|
6152
6546
|
JSON.stringify({ mcpServers }, null, 2)
|
|
6153
6547
|
);
|
|
6154
6548
|
results.push({
|
|
@@ -6161,7 +6555,7 @@ async function importMcp4(projectRoot, results) {
|
|
|
6161
6555
|
|
|
6162
6556
|
// src/targets/codex-cli/skills-helpers.ts
|
|
6163
6557
|
import { readdir as readdir7 } from "fs/promises";
|
|
6164
|
-
import { join as
|
|
6558
|
+
import { join as join33, relative as relative11, dirname as dirname14 } from "path";
|
|
6165
6559
|
|
|
6166
6560
|
// src/targets/import/scoped-agents-import.ts
|
|
6167
6561
|
import { rm as rm5 } from "fs/promises";
|
|
@@ -6179,7 +6573,7 @@ async function removePathIfExists(path) {
|
|
|
6179
6573
|
// src/targets/codex-cli/skills-helpers.ts
|
|
6180
6574
|
async function importSkills3(projectRoot, results, normalize) {
|
|
6181
6575
|
for (const skillsRoot of [CODEX_SKILLS_DIR, CODEX_SKILLS_FALLBACK_DIR]) {
|
|
6182
|
-
const skillsDir =
|
|
6576
|
+
const skillsDir = join33(projectRoot, skillsRoot);
|
|
6183
6577
|
const entries = await readdir7(skillsDir, {
|
|
6184
6578
|
encoding: "utf8",
|
|
6185
6579
|
withFileTypes: true
|
|
@@ -6190,21 +6584,21 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6190
6584
|
let importedAny = false;
|
|
6191
6585
|
for (const ent of entries) {
|
|
6192
6586
|
if (!ent.isDirectory() && !ent.isSymbolicLink()) continue;
|
|
6193
|
-
const skillPath =
|
|
6194
|
-
const skillMdPath =
|
|
6587
|
+
const skillPath = join33(skillsDir, ent.name);
|
|
6588
|
+
const skillMdPath = join33(skillPath, "SKILL.md");
|
|
6195
6589
|
const skillMdContent = await readFileSafe(skillMdPath);
|
|
6196
6590
|
if (!skillMdContent) continue;
|
|
6197
6591
|
importedAny = true;
|
|
6198
6592
|
const skillName = ent.name;
|
|
6199
|
-
const destSkillPath =
|
|
6593
|
+
const destSkillPath = join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName, "SKILL.md");
|
|
6200
6594
|
const normalized = normalize(skillMdContent, skillMdPath, destSkillPath);
|
|
6201
6595
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
6202
6596
|
const command = parseCommandSkillFrontmatter(frontmatter, ent.name);
|
|
6203
6597
|
if (command) {
|
|
6204
|
-
await removePathIfExists(
|
|
6205
|
-
const destCommandsDir =
|
|
6598
|
+
await removePathIfExists(join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6599
|
+
const destCommandsDir = join33(projectRoot, CODEX_CANONICAL_COMMANDS_DIR);
|
|
6206
6600
|
await mkdirp(destCommandsDir);
|
|
6207
|
-
const commandPath =
|
|
6601
|
+
const commandPath = join33(destCommandsDir, `${command.name}.md`);
|
|
6208
6602
|
await writeFileAtomic(
|
|
6209
6603
|
commandPath,
|
|
6210
6604
|
serializeImportedCommand(command, normalize(body, skillMdPath, commandPath))
|
|
@@ -6219,10 +6613,10 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6219
6613
|
}
|
|
6220
6614
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(frontmatter, ent.name);
|
|
6221
6615
|
if (projectedAgent) {
|
|
6222
|
-
await removePathIfExists(
|
|
6223
|
-
const destAgentsDir =
|
|
6616
|
+
await removePathIfExists(join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6617
|
+
const destAgentsDir = join33(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
|
|
6224
6618
|
await mkdirp(destAgentsDir);
|
|
6225
|
-
const agentPath =
|
|
6619
|
+
const agentPath = join33(destAgentsDir, `${projectedAgent.name}.md`);
|
|
6226
6620
|
await writeFileAtomic(
|
|
6227
6621
|
agentPath,
|
|
6228
6622
|
serializeImportedAgent(projectedAgent, normalize(body, skillMdPath, agentPath))
|
|
@@ -6235,7 +6629,7 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6235
6629
|
});
|
|
6236
6630
|
continue;
|
|
6237
6631
|
}
|
|
6238
|
-
const destSkillDir =
|
|
6632
|
+
const destSkillDir = join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName);
|
|
6239
6633
|
await mkdirp(destSkillDir);
|
|
6240
6634
|
const outContent = await serializeImportedSkillWithFallback(
|
|
6241
6635
|
destSkillPath,
|
|
@@ -6255,7 +6649,7 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6255
6649
|
const relPath = relative11(skillPath, absPath).replace(/\\/g, "/");
|
|
6256
6650
|
const fileContent = await readFileSafe(absPath);
|
|
6257
6651
|
if (fileContent === null) continue;
|
|
6258
|
-
const destPath =
|
|
6652
|
+
const destPath = join33(destSkillDir, relPath);
|
|
6259
6653
|
await mkdirp(dirname14(destPath));
|
|
6260
6654
|
await writeFileAtomic(destPath, normalize(fileContent, absPath, destPath));
|
|
6261
6655
|
results.push({
|
|
@@ -6278,15 +6672,15 @@ async function importFromCodex(projectRoot) {
|
|
|
6278
6672
|
const results = [];
|
|
6279
6673
|
const normalize = await createImportReferenceNormalizer(CODEX_TARGET, projectRoot);
|
|
6280
6674
|
const normalizeWindsurf = await createImportReferenceNormalizer("windsurf", projectRoot);
|
|
6281
|
-
await
|
|
6675
|
+
await importRules5(projectRoot, results, normalize, normalizeWindsurf);
|
|
6282
6676
|
await importSkills3(projectRoot, results, normalize);
|
|
6283
6677
|
await importAgents4(projectRoot, results, normalize);
|
|
6284
|
-
await
|
|
6678
|
+
await importMcp5(projectRoot, results);
|
|
6285
6679
|
return results;
|
|
6286
6680
|
}
|
|
6287
6681
|
async function importAgents4(projectRoot, results, normalize) {
|
|
6288
|
-
const agentsPath =
|
|
6289
|
-
const agentsDestDir =
|
|
6682
|
+
const agentsPath = join34(projectRoot, CODEX_AGENTS_DIR);
|
|
6683
|
+
const agentsDestDir = join34(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
|
|
6290
6684
|
try {
|
|
6291
6685
|
const agentFiles = await readDirRecursive(agentsPath);
|
|
6292
6686
|
const tomlFiles = agentFiles.filter((f) => f.endsWith(".toml"));
|
|
@@ -6295,7 +6689,7 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6295
6689
|
if (!content) continue;
|
|
6296
6690
|
const parsed = parseToml5(content);
|
|
6297
6691
|
if (!parsed || typeof parsed !== "object") continue;
|
|
6298
|
-
const name = typeof parsed.name === "string" ? parsed.name :
|
|
6692
|
+
const name = typeof parsed.name === "string" ? parsed.name : basename22(srcPath, ".toml");
|
|
6299
6693
|
const description = typeof parsed.description === "string" ? parsed.description : "";
|
|
6300
6694
|
const body = typeof parsed.developer_instructions === "string" ? parsed.developer_instructions.trim() : "";
|
|
6301
6695
|
const model = typeof parsed.model === "string" ? parsed.model : "";
|
|
@@ -6303,7 +6697,7 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6303
6697
|
const permissionMode = sandbox === "read-only" ? "read-only" : sandbox === "workspace-write" ? "allow" : "";
|
|
6304
6698
|
const mcpServers = Array.isArray(parsed.mcp_servers) ? parsed.mcp_servers.filter((s) => typeof s === "string") : [];
|
|
6305
6699
|
await mkdirp(agentsDestDir);
|
|
6306
|
-
const destPath =
|
|
6700
|
+
const destPath = join34(agentsDestDir, `${name}.md`);
|
|
6307
6701
|
const normalizedBody = normalize(body, srcPath, destPath);
|
|
6308
6702
|
const agent = {
|
|
6309
6703
|
name,
|
|
@@ -6330,17 +6724,17 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6330
6724
|
} catch {
|
|
6331
6725
|
}
|
|
6332
6726
|
}
|
|
6333
|
-
async function
|
|
6334
|
-
const codexPath =
|
|
6335
|
-
const agentsPath =
|
|
6727
|
+
async function importRules5(projectRoot, results, normalize, normalizeWindsurf) {
|
|
6728
|
+
const codexPath = join34(projectRoot, CODEX_MD);
|
|
6729
|
+
const agentsPath = join34(projectRoot, AGENTS_MD);
|
|
6336
6730
|
const agentsContent = await readFileSafe(agentsPath);
|
|
6337
6731
|
const codexContent = await readFileSafe(codexPath);
|
|
6338
6732
|
const sourcePath = agentsContent !== null ? agentsPath : codexPath;
|
|
6339
|
-
const destDir =
|
|
6733
|
+
const destDir = join34(projectRoot, CODEX_CANONICAL_RULES_DIR);
|
|
6340
6734
|
const content = agentsContent ?? codexContent;
|
|
6341
6735
|
if (content !== null) {
|
|
6342
6736
|
await mkdirp(destDir);
|
|
6343
|
-
const destPath =
|
|
6737
|
+
const destPath = join34(destDir, "_root.md");
|
|
6344
6738
|
const stripped = sourcePath === agentsPath ? stripCodexRuleIndex(content) : content;
|
|
6345
6739
|
const normalizedContent = sourcePath === agentsPath ? normalize(normalizeWindsurf(stripped, sourcePath, destPath), sourcePath, destPath) : normalize(stripped, sourcePath, destPath);
|
|
6346
6740
|
const { frontmatter, body } = parseFrontmatter(normalizedContent);
|
|
@@ -6370,10 +6764,10 @@ async function importRules4(projectRoot, results, normalize, normalizeWindsurf)
|
|
|
6370
6764
|
if (!isOverride && !srcPath.endsWith("/AGENTS.md")) return null;
|
|
6371
6765
|
const ruleName = relDir.replace(/\//g, "-");
|
|
6372
6766
|
if (!shouldImportScopedAgentsRule(relDir)) {
|
|
6373
|
-
await removePathIfExists(
|
|
6767
|
+
await removePathIfExists(join34(destDir, `${ruleName}.md`));
|
|
6374
6768
|
return null;
|
|
6375
6769
|
}
|
|
6376
|
-
const destPath =
|
|
6770
|
+
const destPath = join34(destDir, `${ruleName}.md`);
|
|
6377
6771
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
6378
6772
|
return {
|
|
6379
6773
|
destPath,
|
|
@@ -6396,15 +6790,15 @@ async function importRules4(projectRoot, results, normalize, normalizeWindsurf)
|
|
|
6396
6790
|
}
|
|
6397
6791
|
async function importInstructionMirrors(projectRoot, destDir, results, normalize) {
|
|
6398
6792
|
try {
|
|
6399
|
-
const files = await readDirRecursive(
|
|
6793
|
+
const files = await readDirRecursive(join34(projectRoot, CODEX_INSTRUCTIONS_DIR));
|
|
6400
6794
|
const instructionFiles = files.filter((file) => file.endsWith(".md"));
|
|
6401
|
-
const instructionsRoot =
|
|
6795
|
+
const instructionsRoot = join34(projectRoot, CODEX_INSTRUCTIONS_DIR);
|
|
6402
6796
|
for (const srcPath of instructionFiles) {
|
|
6403
6797
|
const relativePath = relative12(instructionsRoot, srcPath).replace(/\\/g, "/");
|
|
6404
6798
|
if (relativePath === "_root.md") continue;
|
|
6405
6799
|
const content = await readFileSafe(srcPath);
|
|
6406
6800
|
if (!content) continue;
|
|
6407
|
-
const destPath =
|
|
6801
|
+
const destPath = join34(destDir, relativePath);
|
|
6408
6802
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
6409
6803
|
await mkdirp(destDir);
|
|
6410
6804
|
const outFm = frontmatter.root === true ? frontmatter : { ...frontmatter, root: false };
|
|
@@ -6423,7 +6817,7 @@ async function importInstructionMirrors(projectRoot, destDir, results, normalize
|
|
|
6423
6817
|
|
|
6424
6818
|
// src/targets/codex-cli/linter.ts
|
|
6425
6819
|
import { relative as relative13 } from "path";
|
|
6426
|
-
function
|
|
6820
|
+
function lintRules9(canonical, projectRoot, _projectFiles) {
|
|
6427
6821
|
const { rules } = canonical;
|
|
6428
6822
|
if (rules.length === 0) return [];
|
|
6429
6823
|
const hasRoot = rules.some((r) => r.root);
|
|
@@ -6446,19 +6840,19 @@ function codexAdvisoryInstructionPath(rule) {
|
|
|
6446
6840
|
}
|
|
6447
6841
|
|
|
6448
6842
|
// src/targets/codex-cli/index.ts
|
|
6449
|
-
var
|
|
6843
|
+
var target9 = {
|
|
6450
6844
|
name: "codex-cli",
|
|
6451
6845
|
primaryRootInstructionPath: AGENTS_MD,
|
|
6452
|
-
generateRules:
|
|
6846
|
+
generateRules: generateRules9,
|
|
6453
6847
|
generateCommands: generateCommands7,
|
|
6454
6848
|
generateAgents: generateAgents7,
|
|
6455
|
-
generateSkills:
|
|
6456
|
-
generateMcp:
|
|
6849
|
+
generateSkills: generateSkills9,
|
|
6850
|
+
generateMcp: generateMcp7,
|
|
6457
6851
|
importFrom: importFromCodex
|
|
6458
6852
|
};
|
|
6459
|
-
var
|
|
6853
|
+
var descriptor9 = {
|
|
6460
6854
|
id: "codex-cli",
|
|
6461
|
-
generators:
|
|
6855
|
+
generators: target9,
|
|
6462
6856
|
capabilities: {
|
|
6463
6857
|
rules: "native",
|
|
6464
6858
|
commands: "embedded",
|
|
@@ -6470,7 +6864,7 @@ var descriptor8 = {
|
|
|
6470
6864
|
permissions: "none"
|
|
6471
6865
|
},
|
|
6472
6866
|
emptyImportMessage: "No Codex config found (codex.md or AGENTS.md).",
|
|
6473
|
-
lintRules:
|
|
6867
|
+
lintRules: lintRules9,
|
|
6474
6868
|
skillDir: ".agents/skills",
|
|
6475
6869
|
paths: {
|
|
6476
6870
|
rulePath(_slug, rule) {
|
|
@@ -6488,7 +6882,7 @@ var descriptor8 = {
|
|
|
6488
6882
|
};
|
|
6489
6883
|
|
|
6490
6884
|
// src/targets/windsurf/generator.ts
|
|
6491
|
-
import { basename as
|
|
6885
|
+
import { basename as basename23 } from "path";
|
|
6492
6886
|
|
|
6493
6887
|
// src/targets/windsurf/constants.ts
|
|
6494
6888
|
var WINDSURF_TARGET = "windsurf";
|
|
@@ -6512,7 +6906,7 @@ var WINDSURF_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
|
6512
6906
|
|
|
6513
6907
|
// src/targets/windsurf/generator.ts
|
|
6514
6908
|
function ruleSlug5(source) {
|
|
6515
|
-
const name =
|
|
6909
|
+
const name = basename23(source, ".md");
|
|
6516
6910
|
return name === "_root" ? "root" : name;
|
|
6517
6911
|
}
|
|
6518
6912
|
function directoryScopedRuleDir(globs) {
|
|
@@ -6521,7 +6915,7 @@ function directoryScopedRuleDir(globs) {
|
|
|
6521
6915
|
if (dirs.length !== globs.length) return null;
|
|
6522
6916
|
return dirs.every((dir) => dir === dirs[0]) ? dirs[0] : null;
|
|
6523
6917
|
}
|
|
6524
|
-
function
|
|
6918
|
+
function generateRules10(canonical) {
|
|
6525
6919
|
const outputs = [];
|
|
6526
6920
|
const root = canonical.rules.find((r) => r.root);
|
|
6527
6921
|
if (!root) return [];
|
|
@@ -6555,7 +6949,7 @@ function generateRules9(canonical) {
|
|
|
6555
6949
|
}
|
|
6556
6950
|
return outputs;
|
|
6557
6951
|
}
|
|
6558
|
-
function
|
|
6952
|
+
function generateIgnore7(canonical) {
|
|
6559
6953
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
6560
6954
|
return [{ path: CODEIUM_IGNORE, content: canonical.ignore.join("\n") }];
|
|
6561
6955
|
}
|
|
@@ -6581,7 +6975,7 @@ function generateAgents8(canonical) {
|
|
|
6581
6975
|
content: serializeProjectedAgentSkill(agent)
|
|
6582
6976
|
}));
|
|
6583
6977
|
}
|
|
6584
|
-
function
|
|
6978
|
+
function generateMcp8(canonical) {
|
|
6585
6979
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
6586
6980
|
return [
|
|
6587
6981
|
{
|
|
@@ -6619,13 +7013,13 @@ function toWindsurfHooks(hooks) {
|
|
|
6619
7013
|
}
|
|
6620
7014
|
return result;
|
|
6621
7015
|
}
|
|
6622
|
-
function
|
|
7016
|
+
function generateHooks6(canonical) {
|
|
6623
7017
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
6624
7018
|
const hooks = toWindsurfHooks(canonical.hooks);
|
|
6625
7019
|
if (Object.keys(hooks).length === 0) return [];
|
|
6626
7020
|
return [{ path: WINDSURF_HOOKS_FILE, content: JSON.stringify({ hooks }, null, 2) }];
|
|
6627
7021
|
}
|
|
6628
|
-
function
|
|
7022
|
+
function generateSkills10(canonical) {
|
|
6629
7023
|
const outputs = [];
|
|
6630
7024
|
for (const skill of canonical.skills) {
|
|
6631
7025
|
const frontmatter = {
|
|
@@ -6646,11 +7040,11 @@ function generateSkills9(canonical) {
|
|
|
6646
7040
|
}
|
|
6647
7041
|
|
|
6648
7042
|
// src/targets/windsurf/importer.ts
|
|
6649
|
-
import { join as
|
|
6650
|
-
import { stringify as
|
|
7043
|
+
import { join as join36, dirname as dirname16, relative as relative15 } from "path";
|
|
7044
|
+
import { stringify as yamlStringify5 } from "yaml";
|
|
6651
7045
|
|
|
6652
7046
|
// src/targets/windsurf/workflows-skills-helpers.ts
|
|
6653
|
-
import { join as
|
|
7047
|
+
import { join as join35, relative as relative14 } from "path";
|
|
6654
7048
|
import { readdir as readdir8 } from "fs/promises";
|
|
6655
7049
|
function toStringArray7(value) {
|
|
6656
7050
|
if (Array.isArray(value)) {
|
|
@@ -6662,16 +7056,16 @@ function toStringArray7(value) {
|
|
|
6662
7056
|
return [];
|
|
6663
7057
|
}
|
|
6664
7058
|
async function importWorkflows(projectRoot, results, normalize) {
|
|
6665
|
-
const workflowsDir =
|
|
7059
|
+
const workflowsDir = join35(projectRoot, WINDSURF_WORKFLOWS_DIR);
|
|
6666
7060
|
const workflowFiles = await readDirRecursive(workflowsDir);
|
|
6667
7061
|
const workflowMdFiles = workflowFiles.filter((f) => f.endsWith(".md"));
|
|
6668
|
-
const destCommandsDir =
|
|
7062
|
+
const destCommandsDir = join35(projectRoot, WINDSURF_CANONICAL_COMMANDS_DIR);
|
|
6669
7063
|
for (const srcPath of workflowMdFiles) {
|
|
6670
7064
|
const content = await readFileSafe(srcPath);
|
|
6671
7065
|
if (!content) continue;
|
|
6672
7066
|
const relativePath = relative14(workflowsDir, srcPath).replace(/\\/g, "/");
|
|
6673
7067
|
await mkdirp(destCommandsDir);
|
|
6674
|
-
const destPath =
|
|
7068
|
+
const destPath = join35(destCommandsDir, relativePath);
|
|
6675
7069
|
const normalized = normalize(content, srcPath, destPath);
|
|
6676
7070
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
6677
7071
|
const outContent = await serializeImportedCommandWithFallback(
|
|
@@ -6697,22 +7091,22 @@ async function importWorkflows(projectRoot, results, normalize) {
|
|
|
6697
7091
|
}
|
|
6698
7092
|
}
|
|
6699
7093
|
async function importSkills4(projectRoot, results, normalize) {
|
|
6700
|
-
const windsurfSkillsBaseDir =
|
|
7094
|
+
const windsurfSkillsBaseDir = join35(projectRoot, WINDSURF_SKILLS_DIR);
|
|
6701
7095
|
try {
|
|
6702
7096
|
const skillEntries = await readdir8(windsurfSkillsBaseDir, { withFileTypes: true });
|
|
6703
7097
|
for (const ent of skillEntries) {
|
|
6704
7098
|
if (!ent.isDirectory()) continue;
|
|
6705
|
-
const skillPath =
|
|
6706
|
-
const skillMdPath =
|
|
7099
|
+
const skillPath = join35(windsurfSkillsBaseDir, ent.name);
|
|
7100
|
+
const skillMdPath = join35(skillPath, "SKILL.md");
|
|
6707
7101
|
const skillContent = await readFileSafe(skillMdPath);
|
|
6708
7102
|
if (!skillContent) continue;
|
|
6709
7103
|
const rawParsed = parseFrontmatter(skillContent);
|
|
6710
7104
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, ent.name);
|
|
6711
7105
|
if (projectedAgent) {
|
|
6712
|
-
await removePathIfExists(
|
|
6713
|
-
const destAgentsDir =
|
|
7106
|
+
await removePathIfExists(join35(projectRoot, WINDSURF_CANONICAL_SKILLS_DIR, ent.name));
|
|
7107
|
+
const destAgentsDir = join35(projectRoot, WINDSURF_CANONICAL_AGENTS_DIR);
|
|
6714
7108
|
await mkdirp(destAgentsDir);
|
|
6715
|
-
const agentPath =
|
|
7109
|
+
const agentPath = join35(destAgentsDir, `${projectedAgent.name}.md`);
|
|
6716
7110
|
await writeFileAtomic(
|
|
6717
7111
|
agentPath,
|
|
6718
7112
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
@@ -6725,8 +7119,8 @@ async function importSkills4(projectRoot, results, normalize) {
|
|
|
6725
7119
|
});
|
|
6726
7120
|
continue;
|
|
6727
7121
|
}
|
|
6728
|
-
const destSkillDir =
|
|
6729
|
-
const destSkillPath =
|
|
7122
|
+
const destSkillDir = join35(projectRoot, WINDSURF_CANONICAL_SKILLS_DIR, ent.name);
|
|
7123
|
+
const destSkillPath = join35(destSkillDir, "SKILL.md");
|
|
6730
7124
|
const normalized = normalize(skillContent, skillMdPath, destSkillPath);
|
|
6731
7125
|
await mkdirp(destSkillDir);
|
|
6732
7126
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
@@ -6750,8 +7144,8 @@ async function importSkills4(projectRoot, results, normalize) {
|
|
|
6750
7144
|
const relPath = absPath.slice(skillPath.length + 1).replace(/\\/g, "/");
|
|
6751
7145
|
const supportContent = await readFileSafe(absPath);
|
|
6752
7146
|
if (supportContent === null) continue;
|
|
6753
|
-
const destSupportPath =
|
|
6754
|
-
await mkdirp(
|
|
7147
|
+
const destSupportPath = join35(destSkillDir, relPath);
|
|
7148
|
+
await mkdirp(join35(destSupportPath, ".."));
|
|
6755
7149
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
6756
7150
|
results.push({
|
|
6757
7151
|
fromTool: WINDSURF_TARGET,
|
|
@@ -6770,12 +7164,12 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6770
7164
|
const results = [];
|
|
6771
7165
|
const normalize = await createImportReferenceNormalizer(WINDSURF_TARGET, projectRoot);
|
|
6772
7166
|
const normalizeCodex = await createImportReferenceNormalizer("codex-cli", projectRoot);
|
|
6773
|
-
const destRulesDir =
|
|
6774
|
-
const rootPath =
|
|
7167
|
+
const destRulesDir = join36(projectRoot, WINDSURF_CANONICAL_RULES_DIR);
|
|
7168
|
+
const rootPath = join36(projectRoot, WINDSURF_RULES_ROOT);
|
|
6775
7169
|
const rootContent = await readFileSafe(rootPath);
|
|
6776
7170
|
if (rootContent !== null) {
|
|
6777
7171
|
await mkdirp(destRulesDir);
|
|
6778
|
-
const destPath =
|
|
7172
|
+
const destPath = join36(destRulesDir, "_root.md");
|
|
6779
7173
|
const body = normalize(rootContent, rootPath, destPath).trim();
|
|
6780
7174
|
const outContent = await serializeImportedRuleWithFallback(destPath, { root: true }, body);
|
|
6781
7175
|
await writeFileAtomic(destPath, outContent);
|
|
@@ -6787,11 +7181,11 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6787
7181
|
});
|
|
6788
7182
|
}
|
|
6789
7183
|
if (rootContent === null) {
|
|
6790
|
-
const agentsMdPath =
|
|
7184
|
+
const agentsMdPath = join36(projectRoot, WINDSURF_AGENTS_MD);
|
|
6791
7185
|
const agentsMdContent = await readFileSafe(agentsMdPath);
|
|
6792
7186
|
if (agentsMdContent !== null) {
|
|
6793
7187
|
await mkdirp(destRulesDir);
|
|
6794
|
-
const destPath =
|
|
7188
|
+
const destPath = join36(destRulesDir, "_root.md");
|
|
6795
7189
|
const body = normalize(
|
|
6796
7190
|
normalizeCodex(agentsMdContent, agentsMdPath, destPath),
|
|
6797
7191
|
agentsMdPath,
|
|
@@ -6819,10 +7213,10 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6819
7213
|
if (!relDir || relDir === "." || !srcPath.endsWith("/AGENTS.md")) return null;
|
|
6820
7214
|
const ruleName = relDir.replace(/\//g, "-");
|
|
6821
7215
|
if (!shouldImportScopedAgentsRule(relDir)) {
|
|
6822
|
-
await removePathIfExists(
|
|
7216
|
+
await removePathIfExists(join36(destRulesDir, `${ruleName}.md`));
|
|
6823
7217
|
return null;
|
|
6824
7218
|
}
|
|
6825
|
-
const destPath =
|
|
7219
|
+
const destPath = join36(destRulesDir, `${ruleName}.md`);
|
|
6826
7220
|
return {
|
|
6827
7221
|
destPath,
|
|
6828
7222
|
toPath: `${WINDSURF_CANONICAL_RULES_DIR}/${ruleName}.md`,
|
|
@@ -6836,7 +7230,7 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6836
7230
|
}
|
|
6837
7231
|
})
|
|
6838
7232
|
);
|
|
6839
|
-
const rulesDir =
|
|
7233
|
+
const rulesDir = join36(projectRoot, WINDSURF_RULES_DIR);
|
|
6840
7234
|
results.push(
|
|
6841
7235
|
...await importFileDirectory({
|
|
6842
7236
|
srcDir: rulesDir,
|
|
@@ -6846,7 +7240,7 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6846
7240
|
normalize,
|
|
6847
7241
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
6848
7242
|
if (relativePath === "_root.md" && rootContent !== null) return null;
|
|
6849
|
-
const destPath =
|
|
7243
|
+
const destPath = join36(destRulesDir, relativePath);
|
|
6850
7244
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
6851
7245
|
const normalizedFrontmatter = { ...frontmatter };
|
|
6852
7246
|
if (typeof normalizedFrontmatter.glob === "string" && normalizedFrontmatter.glob.trim()) {
|
|
@@ -6866,10 +7260,10 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6866
7260
|
}
|
|
6867
7261
|
})
|
|
6868
7262
|
);
|
|
6869
|
-
let ignorePath =
|
|
7263
|
+
let ignorePath = join36(projectRoot, WINDSURF_IGNORE);
|
|
6870
7264
|
let ignoreContent = await readFileSafe(ignorePath);
|
|
6871
7265
|
if (ignoreContent === null || !ignoreContent.trim()) {
|
|
6872
|
-
ignorePath =
|
|
7266
|
+
ignorePath = join36(projectRoot, CODEIUM_IGNORE);
|
|
6873
7267
|
ignoreContent = await readFileSafe(ignorePath);
|
|
6874
7268
|
}
|
|
6875
7269
|
if (ignoreContent !== null && ignoreContent.trim()) {
|
|
@@ -6880,8 +7274,8 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6880
7274
|
if (t && !t.startsWith("#")) patterns.push(t);
|
|
6881
7275
|
}
|
|
6882
7276
|
if (patterns.length > 0) {
|
|
6883
|
-
await mkdirp(
|
|
6884
|
-
const destIgnorePath =
|
|
7277
|
+
await mkdirp(join36(projectRoot, ".agentsmesh"));
|
|
7278
|
+
const destIgnorePath = join36(projectRoot, WINDSURF_CANONICAL_IGNORE);
|
|
6885
7279
|
await writeFileAtomic(destIgnorePath, patterns.join("\n"));
|
|
6886
7280
|
results.push({
|
|
6887
7281
|
fromTool: "windsurf",
|
|
@@ -6893,12 +7287,12 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6893
7287
|
}
|
|
6894
7288
|
await importWorkflows(projectRoot, results, normalize);
|
|
6895
7289
|
await importSkills4(projectRoot, results, normalize);
|
|
6896
|
-
await
|
|
6897
|
-
await
|
|
7290
|
+
await importHooks3(projectRoot, results);
|
|
7291
|
+
await importMcp6(projectRoot, results);
|
|
6898
7292
|
return results;
|
|
6899
7293
|
}
|
|
6900
|
-
async function
|
|
6901
|
-
const hooksPath =
|
|
7294
|
+
async function importHooks3(projectRoot, results) {
|
|
7295
|
+
const hooksPath = join36(projectRoot, WINDSURF_HOOKS_FILE);
|
|
6902
7296
|
const hooksContent = await readFileSafe(hooksPath);
|
|
6903
7297
|
if (!hooksContent) return;
|
|
6904
7298
|
try {
|
|
@@ -6906,9 +7300,9 @@ async function importHooks2(projectRoot, results) {
|
|
|
6906
7300
|
if (!parsed.hooks || typeof parsed.hooks !== "object" || Array.isArray(parsed.hooks)) return;
|
|
6907
7301
|
const canonical = windsurfHooksToCanonical(parsed.hooks);
|
|
6908
7302
|
if (Object.keys(canonical).length === 0) return;
|
|
6909
|
-
const destPath =
|
|
7303
|
+
const destPath = join36(projectRoot, WINDSURF_CANONICAL_HOOKS);
|
|
6910
7304
|
await mkdirp(dirname16(destPath));
|
|
6911
|
-
await writeFileAtomic(destPath,
|
|
7305
|
+
await writeFileAtomic(destPath, yamlStringify5(canonical));
|
|
6912
7306
|
results.push({
|
|
6913
7307
|
fromTool: WINDSURF_TARGET,
|
|
6914
7308
|
fromPath: hooksPath,
|
|
@@ -6966,16 +7360,16 @@ function windsurfHooksToCanonical(hooks) {
|
|
|
6966
7360
|
}
|
|
6967
7361
|
return result;
|
|
6968
7362
|
}
|
|
6969
|
-
async function
|
|
7363
|
+
async function importMcp6(projectRoot, results) {
|
|
6970
7364
|
const sourceCandidates = [WINDSURF_MCP_EXAMPLE_FILE, WINDSURF_MCP_CONFIG_FILE];
|
|
6971
7365
|
for (const relPath of sourceCandidates) {
|
|
6972
|
-
const srcPath =
|
|
7366
|
+
const srcPath = join36(projectRoot, relPath);
|
|
6973
7367
|
const content = await readFileSafe(srcPath);
|
|
6974
7368
|
if (!content) continue;
|
|
6975
7369
|
try {
|
|
6976
7370
|
const parsed = JSON.parse(content);
|
|
6977
7371
|
if (!parsed.mcpServers || typeof parsed.mcpServers !== "object") continue;
|
|
6978
|
-
const destPath =
|
|
7372
|
+
const destPath = join36(projectRoot, WINDSURF_CANONICAL_MCP);
|
|
6979
7373
|
await mkdirp(dirname16(destPath));
|
|
6980
7374
|
await writeFileAtomic(destPath, JSON.stringify({ mcpServers: parsed.mcpServers }, null, 2));
|
|
6981
7375
|
results.push({
|
|
@@ -6992,7 +7386,7 @@ async function importMcp5(projectRoot, results) {
|
|
|
6992
7386
|
|
|
6993
7387
|
// src/targets/windsurf/linter.ts
|
|
6994
7388
|
import { relative as relative16 } from "path";
|
|
6995
|
-
function
|
|
7389
|
+
function lintRules10(canonical, projectRoot, _projectFiles) {
|
|
6996
7390
|
const diags = [];
|
|
6997
7391
|
const { rules } = canonical;
|
|
6998
7392
|
if (rules.length > 0) {
|
|
@@ -7021,21 +7415,21 @@ function lintRules9(canonical, projectRoot, _projectFiles) {
|
|
|
7021
7415
|
}
|
|
7022
7416
|
|
|
7023
7417
|
// src/targets/windsurf/index.ts
|
|
7024
|
-
var
|
|
7418
|
+
var target10 = {
|
|
7025
7419
|
name: "windsurf",
|
|
7026
7420
|
primaryRootInstructionPath: WINDSURF_AGENTS_MD,
|
|
7027
|
-
generateRules:
|
|
7421
|
+
generateRules: generateRules10,
|
|
7028
7422
|
generateWorkflows: generateWorkflows2,
|
|
7029
7423
|
generateAgents: generateAgents8,
|
|
7030
|
-
generateSkills:
|
|
7031
|
-
generateMcp:
|
|
7032
|
-
generateHooks:
|
|
7033
|
-
generateIgnore:
|
|
7424
|
+
generateSkills: generateSkills10,
|
|
7425
|
+
generateMcp: generateMcp8,
|
|
7426
|
+
generateHooks: generateHooks6,
|
|
7427
|
+
generateIgnore: generateIgnore7,
|
|
7034
7428
|
importFrom: importFromWindsurf
|
|
7035
7429
|
};
|
|
7036
|
-
var
|
|
7430
|
+
var descriptor10 = {
|
|
7037
7431
|
id: "windsurf",
|
|
7038
|
-
generators:
|
|
7432
|
+
generators: target10,
|
|
7039
7433
|
capabilities: {
|
|
7040
7434
|
rules: "native",
|
|
7041
7435
|
commands: "native",
|
|
@@ -7047,7 +7441,7 @@ var descriptor9 = {
|
|
|
7047
7441
|
permissions: "none"
|
|
7048
7442
|
},
|
|
7049
7443
|
emptyImportMessage: "No Windsurf config found (.windsurfrules, .windsurf/rules, .windsurfignore, or .codeiumignore).",
|
|
7050
|
-
lintRules:
|
|
7444
|
+
lintRules: lintRules10,
|
|
7051
7445
|
skillDir: ".windsurf/skills",
|
|
7052
7446
|
paths: {
|
|
7053
7447
|
rulePath(slug, _rule) {
|
|
@@ -7065,8 +7459,8 @@ var descriptor9 = {
|
|
|
7065
7459
|
};
|
|
7066
7460
|
|
|
7067
7461
|
// src/targets/antigravity/generator.ts
|
|
7068
|
-
import { basename as
|
|
7069
|
-
function
|
|
7462
|
+
import { basename as basename24 } from "path";
|
|
7463
|
+
function generateRules11(canonical) {
|
|
7070
7464
|
const root = canonical.rules.find((r) => r.root);
|
|
7071
7465
|
if (!root) return [];
|
|
7072
7466
|
const outputs = [
|
|
@@ -7075,7 +7469,7 @@ function generateRules10(canonical) {
|
|
|
7075
7469
|
for (const rule of canonical.rules) {
|
|
7076
7470
|
if (rule.root) continue;
|
|
7077
7471
|
if (rule.targets.length > 0 && !rule.targets.includes("antigravity")) continue;
|
|
7078
|
-
const slug =
|
|
7472
|
+
const slug = basename24(rule.source, ".md");
|
|
7079
7473
|
outputs.push({
|
|
7080
7474
|
path: `${ANTIGRAVITY_RULES_DIR}/${slug}.md`,
|
|
7081
7475
|
content: rule.body.trim() || ""
|
|
@@ -7096,15 +7490,15 @@ ${body}` : body || intro;
|
|
|
7096
7490
|
};
|
|
7097
7491
|
});
|
|
7098
7492
|
}
|
|
7099
|
-
function
|
|
7493
|
+
function generateSkills11(canonical) {
|
|
7100
7494
|
return generateEmbeddedSkills(canonical, ANTIGRAVITY_SKILLS_DIR);
|
|
7101
7495
|
}
|
|
7102
7496
|
|
|
7103
7497
|
// src/targets/antigravity/importer.ts
|
|
7104
|
-
import { basename as
|
|
7498
|
+
import { basename as basename25, join as join37 } from "path";
|
|
7105
7499
|
async function importRootRule(projectRoot, results, normalize) {
|
|
7106
|
-
const primary =
|
|
7107
|
-
const legacy =
|
|
7500
|
+
const primary = join37(projectRoot, ANTIGRAVITY_RULES_ROOT);
|
|
7501
|
+
const legacy = join37(projectRoot, ANTIGRAVITY_RULES_ROOT_LEGACY);
|
|
7108
7502
|
let srcPath = primary;
|
|
7109
7503
|
let content = await readFileSafe(primary);
|
|
7110
7504
|
if (content === null) {
|
|
@@ -7112,10 +7506,10 @@ async function importRootRule(projectRoot, results, normalize) {
|
|
|
7112
7506
|
content = await readFileSafe(legacy);
|
|
7113
7507
|
}
|
|
7114
7508
|
if (content === null) return;
|
|
7115
|
-
const destPath =
|
|
7509
|
+
const destPath = join37(projectRoot, ANTIGRAVITY_CANONICAL_ROOT_RULE);
|
|
7116
7510
|
const { body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
7117
7511
|
const output = await serializeImportedRuleWithFallback(destPath, { root: true }, body);
|
|
7118
|
-
await mkdirp(
|
|
7512
|
+
await mkdirp(join37(projectRoot, ANTIGRAVITY_CANONICAL_RULES_DIR));
|
|
7119
7513
|
await writeFileAtomic(destPath, output);
|
|
7120
7514
|
results.push({
|
|
7121
7515
|
fromTool: ANTIGRAVITY_TARGET,
|
|
@@ -7125,8 +7519,8 @@ async function importRootRule(projectRoot, results, normalize) {
|
|
|
7125
7519
|
});
|
|
7126
7520
|
}
|
|
7127
7521
|
async function importNonRootRules2(projectRoot, results, normalize) {
|
|
7128
|
-
const srcDir =
|
|
7129
|
-
const destDir =
|
|
7522
|
+
const srcDir = join37(projectRoot, ANTIGRAVITY_RULES_DIR);
|
|
7523
|
+
const destDir = join37(projectRoot, ANTIGRAVITY_CANONICAL_RULES_DIR);
|
|
7130
7524
|
results.push(
|
|
7131
7525
|
...await importFileDirectory({
|
|
7132
7526
|
srcDir,
|
|
@@ -7135,9 +7529,9 @@ async function importNonRootRules2(projectRoot, results, normalize) {
|
|
|
7135
7529
|
fromTool: ANTIGRAVITY_TARGET,
|
|
7136
7530
|
normalize,
|
|
7137
7531
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7138
|
-
if (
|
|
7532
|
+
if (basename25(relativePath) === "general.md" || basename25(relativePath) === "_root.md")
|
|
7139
7533
|
return null;
|
|
7140
|
-
const destPath =
|
|
7534
|
+
const destPath = join37(destDir, relativePath);
|
|
7141
7535
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7142
7536
|
const output = await serializeImportedRuleWithFallback(
|
|
7143
7537
|
destPath,
|
|
@@ -7159,8 +7553,8 @@ async function importNonRootRules2(projectRoot, results, normalize) {
|
|
|
7159
7553
|
);
|
|
7160
7554
|
}
|
|
7161
7555
|
async function importWorkflows2(projectRoot, results, normalize) {
|
|
7162
|
-
const srcDir =
|
|
7163
|
-
const destDir =
|
|
7556
|
+
const srcDir = join37(projectRoot, ANTIGRAVITY_WORKFLOWS_DIR);
|
|
7557
|
+
const destDir = join37(projectRoot, ANTIGRAVITY_CANONICAL_COMMANDS_DIR);
|
|
7164
7558
|
results.push(
|
|
7165
7559
|
...await importFileDirectory({
|
|
7166
7560
|
srcDir,
|
|
@@ -7169,7 +7563,7 @@ async function importWorkflows2(projectRoot, results, normalize) {
|
|
|
7169
7563
|
fromTool: ANTIGRAVITY_TARGET,
|
|
7170
7564
|
normalize,
|
|
7171
7565
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7172
|
-
const destPath =
|
|
7566
|
+
const destPath = join37(destDir, relativePath);
|
|
7173
7567
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7174
7568
|
const normalized = await serializeImportedCommandWithFallback(
|
|
7175
7569
|
destPath,
|
|
@@ -7208,7 +7602,7 @@ async function importFromAntigravity(projectRoot) {
|
|
|
7208
7602
|
}
|
|
7209
7603
|
|
|
7210
7604
|
// src/targets/antigravity/linter.ts
|
|
7211
|
-
function
|
|
7605
|
+
function lintRules11(canonical, projectRoot, projectFiles) {
|
|
7212
7606
|
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
7213
7607
|
...diagnostic,
|
|
7214
7608
|
target: ANTIGRAVITY_TARGET
|
|
@@ -7216,17 +7610,17 @@ function lintRules10(canonical, projectRoot, projectFiles) {
|
|
|
7216
7610
|
}
|
|
7217
7611
|
|
|
7218
7612
|
// src/targets/antigravity/index.ts
|
|
7219
|
-
var
|
|
7613
|
+
var target11 = {
|
|
7220
7614
|
name: "antigravity",
|
|
7221
7615
|
primaryRootInstructionPath: ANTIGRAVITY_RULES_ROOT,
|
|
7222
|
-
generateRules:
|
|
7616
|
+
generateRules: generateRules11,
|
|
7223
7617
|
generateCommands: generateWorkflows3,
|
|
7224
|
-
generateSkills:
|
|
7618
|
+
generateSkills: generateSkills11,
|
|
7225
7619
|
importFrom: importFromAntigravity
|
|
7226
7620
|
};
|
|
7227
|
-
var
|
|
7621
|
+
var descriptor11 = {
|
|
7228
7622
|
id: "antigravity",
|
|
7229
|
-
generators:
|
|
7623
|
+
generators: target11,
|
|
7230
7624
|
capabilities: {
|
|
7231
7625
|
rules: "native",
|
|
7232
7626
|
commands: "partial",
|
|
@@ -7238,7 +7632,7 @@ var descriptor10 = {
|
|
|
7238
7632
|
permissions: "none"
|
|
7239
7633
|
},
|
|
7240
7634
|
emptyImportMessage: "No Antigravity config found (.agents/rules/, .agents/skills/, or .agents/workflows/).",
|
|
7241
|
-
lintRules:
|
|
7635
|
+
lintRules: lintRules11,
|
|
7242
7636
|
skillDir: ".agents/skills",
|
|
7243
7637
|
paths: {
|
|
7244
7638
|
rulePath(slug, _rule) {
|
|
@@ -7261,8 +7655,8 @@ var descriptor10 = {
|
|
|
7261
7655
|
};
|
|
7262
7656
|
|
|
7263
7657
|
// src/targets/roo-code/generator.ts
|
|
7264
|
-
import { basename as
|
|
7265
|
-
function
|
|
7658
|
+
import { basename as basename26 } from "path";
|
|
7659
|
+
function generateRules12(canonical) {
|
|
7266
7660
|
const outputs = [];
|
|
7267
7661
|
const root = canonical.rules.find((rule) => rule.root);
|
|
7268
7662
|
if (root) {
|
|
@@ -7274,7 +7668,7 @@ function generateRules11(canonical) {
|
|
|
7274
7668
|
for (const rule of canonical.rules) {
|
|
7275
7669
|
if (rule.root) continue;
|
|
7276
7670
|
if (rule.targets.length > 0 && !rule.targets.includes(ROO_CODE_TARGET)) continue;
|
|
7277
|
-
const slug =
|
|
7671
|
+
const slug = basename26(rule.source, ".md");
|
|
7278
7672
|
outputs.push({
|
|
7279
7673
|
path: `${ROO_CODE_RULES_DIR}/${slug}.md`,
|
|
7280
7674
|
content: rule.body.trim() || ""
|
|
@@ -7292,7 +7686,7 @@ function generateCommands8(canonical) {
|
|
|
7292
7686
|
};
|
|
7293
7687
|
});
|
|
7294
7688
|
}
|
|
7295
|
-
function
|
|
7689
|
+
function generateMcp9(canonical) {
|
|
7296
7690
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
7297
7691
|
return [
|
|
7298
7692
|
{
|
|
@@ -7301,18 +7695,18 @@ function generateMcp8(canonical) {
|
|
|
7301
7695
|
}
|
|
7302
7696
|
];
|
|
7303
7697
|
}
|
|
7304
|
-
function
|
|
7698
|
+
function generateIgnore8(canonical) {
|
|
7305
7699
|
if (canonical.ignore.length === 0) return [];
|
|
7306
7700
|
return [{ path: ROO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
7307
7701
|
}
|
|
7308
|
-
function
|
|
7702
|
+
function generateSkills12(canonical) {
|
|
7309
7703
|
return generateEmbeddedSkills(canonical, ROO_CODE_SKILLS_DIR);
|
|
7310
7704
|
}
|
|
7311
7705
|
|
|
7312
7706
|
// src/targets/roo-code/importer.ts
|
|
7313
7707
|
import { readdir as readdir9 } from "fs/promises";
|
|
7314
|
-
import { join as
|
|
7315
|
-
function
|
|
7708
|
+
import { join as join38 } from "path";
|
|
7709
|
+
function readMcpServers4(content) {
|
|
7316
7710
|
const parsed = JSON.parse(content);
|
|
7317
7711
|
const rawServers = parsed.mcpServers;
|
|
7318
7712
|
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) return {};
|
|
@@ -7343,10 +7737,10 @@ function readMcpServers3(content) {
|
|
|
7343
7737
|
return servers;
|
|
7344
7738
|
}
|
|
7345
7739
|
async function importRootRule2(projectRoot, results, normalize) {
|
|
7346
|
-
const destPath =
|
|
7740
|
+
const destPath = join38(projectRoot, ROO_CODE_CANONICAL_ROOT_RULE);
|
|
7347
7741
|
const sources = [ROO_CODE_ROOT_RULE, ROO_CODE_ROOT_RULE_FALLBACK];
|
|
7348
7742
|
for (const relPath of sources) {
|
|
7349
|
-
const srcPath =
|
|
7743
|
+
const srcPath = join38(projectRoot, relPath);
|
|
7350
7744
|
const content = await readFileSafe(srcPath);
|
|
7351
7745
|
if (content === null) continue;
|
|
7352
7746
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
@@ -7370,8 +7764,8 @@ async function importRootRule2(projectRoot, results, normalize) {
|
|
|
7370
7764
|
}
|
|
7371
7765
|
}
|
|
7372
7766
|
async function importNonRootRules3(projectRoot, results, normalize) {
|
|
7373
|
-
const srcDir =
|
|
7374
|
-
const destDir =
|
|
7767
|
+
const srcDir = join38(projectRoot, ROO_CODE_RULES_DIR);
|
|
7768
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7375
7769
|
const rootRuleName = "00-root.md";
|
|
7376
7770
|
results.push(
|
|
7377
7771
|
...await importFileDirectory({
|
|
@@ -7382,7 +7776,7 @@ async function importNonRootRules3(projectRoot, results, normalize) {
|
|
|
7382
7776
|
normalize,
|
|
7383
7777
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7384
7778
|
if (relativePath === rootRuleName) return null;
|
|
7385
|
-
const destPath =
|
|
7779
|
+
const destPath = join38(destDir, relativePath);
|
|
7386
7780
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7387
7781
|
const output = await serializeImportedRuleWithFallback(
|
|
7388
7782
|
destPath,
|
|
@@ -7404,7 +7798,7 @@ async function importNonRootRules3(projectRoot, results, normalize) {
|
|
|
7404
7798
|
);
|
|
7405
7799
|
}
|
|
7406
7800
|
async function importPerModeRules(projectRoot, results, normalize) {
|
|
7407
|
-
const rooDir =
|
|
7801
|
+
const rooDir = join38(projectRoot, ROO_CODE_DIR);
|
|
7408
7802
|
let entries;
|
|
7409
7803
|
try {
|
|
7410
7804
|
entries = await readdir9(rooDir, { withFileTypes: true });
|
|
@@ -7413,8 +7807,8 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7413
7807
|
}
|
|
7414
7808
|
const modeRuleDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("rules-")).map((e) => e.name);
|
|
7415
7809
|
for (const dirName of modeRuleDirs) {
|
|
7416
|
-
const srcDir =
|
|
7417
|
-
const destDir =
|
|
7810
|
+
const srcDir = join38(rooDir, dirName);
|
|
7811
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7418
7812
|
results.push(
|
|
7419
7813
|
...await importFileDirectory({
|
|
7420
7814
|
srcDir,
|
|
@@ -7423,7 +7817,7 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7423
7817
|
fromTool: ROO_CODE_TARGET,
|
|
7424
7818
|
normalize,
|
|
7425
7819
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7426
|
-
const destPath =
|
|
7820
|
+
const destPath = join38(destDir, relativePath);
|
|
7427
7821
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7428
7822
|
const output = await serializeImportedRuleWithFallback(
|
|
7429
7823
|
destPath,
|
|
@@ -7446,8 +7840,8 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7446
7840
|
}
|
|
7447
7841
|
}
|
|
7448
7842
|
async function importCommands5(projectRoot, results, normalize) {
|
|
7449
|
-
const srcDir =
|
|
7450
|
-
const destDir =
|
|
7843
|
+
const srcDir = join38(projectRoot, ROO_CODE_COMMANDS_DIR);
|
|
7844
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_COMMANDS_DIR);
|
|
7451
7845
|
results.push(
|
|
7452
7846
|
...await importFileDirectory({
|
|
7453
7847
|
srcDir,
|
|
@@ -7456,7 +7850,7 @@ async function importCommands5(projectRoot, results, normalize) {
|
|
|
7456
7850
|
fromTool: ROO_CODE_TARGET,
|
|
7457
7851
|
normalize,
|
|
7458
7852
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7459
|
-
const destPath =
|
|
7853
|
+
const destPath = join38(destDir, relativePath);
|
|
7460
7854
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7461
7855
|
const output = await serializeImportedCommandWithFallback(
|
|
7462
7856
|
destPath,
|
|
@@ -7478,14 +7872,14 @@ async function importCommands5(projectRoot, results, normalize) {
|
|
|
7478
7872
|
})
|
|
7479
7873
|
);
|
|
7480
7874
|
}
|
|
7481
|
-
async function
|
|
7482
|
-
const srcPath =
|
|
7875
|
+
async function importMcp7(projectRoot, results) {
|
|
7876
|
+
const srcPath = join38(projectRoot, ROO_CODE_MCP_FILE);
|
|
7483
7877
|
const content = await readFileSafe(srcPath);
|
|
7484
7878
|
if (content === null) return;
|
|
7485
|
-
const servers =
|
|
7879
|
+
const servers = readMcpServers4(content);
|
|
7486
7880
|
if (Object.keys(servers).length === 0) return;
|
|
7487
7881
|
await writeFileAtomic(
|
|
7488
|
-
|
|
7882
|
+
join38(projectRoot, ROO_CODE_CANONICAL_MCP),
|
|
7489
7883
|
JSON.stringify({ mcpServers: servers }, null, 2)
|
|
7490
7884
|
);
|
|
7491
7885
|
results.push({
|
|
@@ -7495,11 +7889,11 @@ async function importMcp6(projectRoot, results) {
|
|
|
7495
7889
|
feature: "mcp"
|
|
7496
7890
|
});
|
|
7497
7891
|
}
|
|
7498
|
-
async function
|
|
7499
|
-
const srcPath =
|
|
7892
|
+
async function importIgnore4(projectRoot, results) {
|
|
7893
|
+
const srcPath = join38(projectRoot, ROO_CODE_IGNORE);
|
|
7500
7894
|
const content = await readFileSafe(srcPath);
|
|
7501
7895
|
if (content === null) return;
|
|
7502
|
-
await writeFileAtomic(
|
|
7896
|
+
await writeFileAtomic(join38(projectRoot, ROO_CODE_CANONICAL_IGNORE), content.trimEnd());
|
|
7503
7897
|
results.push({
|
|
7504
7898
|
fromTool: ROO_CODE_TARGET,
|
|
7505
7899
|
fromPath: srcPath,
|
|
@@ -7515,13 +7909,13 @@ async function importFromRooCode(projectRoot) {
|
|
|
7515
7909
|
await importPerModeRules(projectRoot, results, normalize);
|
|
7516
7910
|
await importCommands5(projectRoot, results, normalize);
|
|
7517
7911
|
await importEmbeddedSkills(projectRoot, ROO_CODE_SKILLS_DIR, ROO_CODE_TARGET, results, normalize);
|
|
7518
|
-
await
|
|
7519
|
-
await
|
|
7912
|
+
await importMcp7(projectRoot, results);
|
|
7913
|
+
await importIgnore4(projectRoot, results);
|
|
7520
7914
|
return results;
|
|
7521
7915
|
}
|
|
7522
7916
|
|
|
7523
7917
|
// src/targets/roo-code/linter.ts
|
|
7524
|
-
function
|
|
7918
|
+
function lintRules12(canonical, projectRoot, projectFiles) {
|
|
7525
7919
|
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
7526
7920
|
...diagnostic,
|
|
7527
7921
|
target: ROO_CODE_TARGET
|
|
@@ -7529,19 +7923,19 @@ function lintRules11(canonical, projectRoot, projectFiles) {
|
|
|
7529
7923
|
}
|
|
7530
7924
|
|
|
7531
7925
|
// src/targets/roo-code/index.ts
|
|
7532
|
-
var
|
|
7926
|
+
var target12 = {
|
|
7533
7927
|
name: "roo-code",
|
|
7534
7928
|
primaryRootInstructionPath: ROO_CODE_ROOT_RULE,
|
|
7535
|
-
generateRules:
|
|
7929
|
+
generateRules: generateRules12,
|
|
7536
7930
|
generateCommands: generateCommands8,
|
|
7537
|
-
generateSkills:
|
|
7538
|
-
generateMcp:
|
|
7539
|
-
generateIgnore:
|
|
7931
|
+
generateSkills: generateSkills12,
|
|
7932
|
+
generateMcp: generateMcp9,
|
|
7933
|
+
generateIgnore: generateIgnore8,
|
|
7540
7934
|
importFrom: importFromRooCode
|
|
7541
7935
|
};
|
|
7542
|
-
var
|
|
7936
|
+
var descriptor12 = {
|
|
7543
7937
|
id: "roo-code",
|
|
7544
|
-
generators:
|
|
7938
|
+
generators: target12,
|
|
7545
7939
|
capabilities: {
|
|
7546
7940
|
rules: "native",
|
|
7547
7941
|
commands: "native",
|
|
@@ -7553,7 +7947,7 @@ var descriptor11 = {
|
|
|
7553
7947
|
permissions: "none"
|
|
7554
7948
|
},
|
|
7555
7949
|
emptyImportMessage: "No Roo Code config found (.roo/rules, .roo/commands, .roo/skills, .roo/mcp.json, .rooignore, or .roorules).",
|
|
7556
|
-
lintRules:
|
|
7950
|
+
lintRules: lintRules12,
|
|
7557
7951
|
skillDir: ".roo/skills",
|
|
7558
7952
|
paths: {
|
|
7559
7953
|
rulePath(slug, _rule) {
|
|
@@ -7589,39 +7983,40 @@ var BUILTIN_TARGETS = [
|
|
|
7589
7983
|
descriptor8,
|
|
7590
7984
|
descriptor9,
|
|
7591
7985
|
descriptor10,
|
|
7592
|
-
descriptor11
|
|
7986
|
+
descriptor11,
|
|
7987
|
+
descriptor12
|
|
7593
7988
|
];
|
|
7594
|
-
function getBuiltinTargetDefinition(
|
|
7595
|
-
return BUILTIN_TARGETS.find((candidate) => candidate.id ===
|
|
7989
|
+
function getBuiltinTargetDefinition(target13) {
|
|
7990
|
+
return BUILTIN_TARGETS.find((candidate) => candidate.id === target13);
|
|
7596
7991
|
}
|
|
7597
|
-
function getTargetSkillDir(
|
|
7598
|
-
return getBuiltinTargetDefinition(
|
|
7992
|
+
function getTargetSkillDir(target13) {
|
|
7993
|
+
return getBuiltinTargetDefinition(target13)?.skillDir;
|
|
7599
7994
|
}
|
|
7600
|
-
function getEffectiveTargetSupportLevel(
|
|
7601
|
-
const definition = getBuiltinTargetDefinition(
|
|
7995
|
+
function getEffectiveTargetSupportLevel(target13, feature, config) {
|
|
7996
|
+
const definition = getBuiltinTargetDefinition(target13);
|
|
7602
7997
|
const baseLevel = definition?.capabilities[feature] ?? "none";
|
|
7603
7998
|
if (baseLevel !== "embedded") return baseLevel;
|
|
7604
|
-
if (feature === "commands" &&
|
|
7605
|
-
return shouldConvertCommandsToSkills(config,
|
|
7999
|
+
if (feature === "commands" && target13 === "codex-cli") {
|
|
8000
|
+
return shouldConvertCommandsToSkills(config, target13) ? "embedded" : "none";
|
|
7606
8001
|
}
|
|
7607
|
-
if (feature === "agents" && (
|
|
7608
|
-
return shouldConvertAgentsToSkills(config,
|
|
8002
|
+
if (feature === "agents" && (target13 === "cline" || target13 === "windsurf")) {
|
|
8003
|
+
return shouldConvertAgentsToSkills(config, target13) ? "embedded" : "none";
|
|
7609
8004
|
}
|
|
7610
8005
|
return baseLevel;
|
|
7611
8006
|
}
|
|
7612
|
-
function resolveTargetFeatureGenerator(
|
|
7613
|
-
const generators = getBuiltinTargetDefinition(
|
|
8007
|
+
function resolveTargetFeatureGenerator(target13, feature, config) {
|
|
8008
|
+
const generators = getBuiltinTargetDefinition(target13)?.generators;
|
|
7614
8009
|
if (!generators) return void 0;
|
|
7615
8010
|
switch (feature) {
|
|
7616
8011
|
case "rules":
|
|
7617
8012
|
return generators.generateRules;
|
|
7618
8013
|
case "commands":
|
|
7619
|
-
if (
|
|
8014
|
+
if (target13 === "codex-cli" && config && !shouldConvertCommandsToSkills(config, target13)) {
|
|
7620
8015
|
return void 0;
|
|
7621
8016
|
}
|
|
7622
8017
|
return generators.generateWorkflows ?? generators.generateCommands;
|
|
7623
8018
|
case "agents":
|
|
7624
|
-
if (config && (
|
|
8019
|
+
if (config && (target13 === "cline" || target13 === "windsurf") && !shouldConvertAgentsToSkills(config, target13)) {
|
|
7625
8020
|
return void 0;
|
|
7626
8021
|
}
|
|
7627
8022
|
return generators.generateAgents;
|
|
@@ -7641,9 +8036,9 @@ function resolveTargetFeatureGenerator(target12, feature, config) {
|
|
|
7641
8036
|
}
|
|
7642
8037
|
|
|
7643
8038
|
// src/core/reference/import-map.ts
|
|
7644
|
-
async function buildImportReferenceMap(
|
|
8039
|
+
async function buildImportReferenceMap(target13, projectRoot) {
|
|
7645
8040
|
const refs = /* @__PURE__ */ new Map();
|
|
7646
|
-
const def = getBuiltinTargetDefinition(
|
|
8041
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
7647
8042
|
if (def) {
|
|
7648
8043
|
await def.buildImportPaths(refs, projectRoot);
|
|
7649
8044
|
}
|
|
@@ -7695,6 +8090,7 @@ var ROOT_RELATIVE_PREFIXES = [
|
|
|
7695
8090
|
".github/",
|
|
7696
8091
|
".continue/",
|
|
7697
8092
|
".junie/",
|
|
8093
|
+
".kiro/",
|
|
7698
8094
|
".gemini/",
|
|
7699
8095
|
".clinerules/",
|
|
7700
8096
|
".cline/",
|
|
@@ -7717,7 +8113,7 @@ var EXTERNAL_REF_PATTERNS = [
|
|
|
7717
8113
|
/\/\/[A-Za-z0-9][\w.-]*\.[A-Za-z]{2,}[^\s<>()\]]*/g
|
|
7718
8114
|
];
|
|
7719
8115
|
var FENCED_CODE_BLOCK = /^(?:```|~~~)[^\n]*\n[\s\S]*?^(?:```|~~~)/gm;
|
|
7720
|
-
var PATH_TOKEN = /(?:\.\.[\\/]|\.\/|\.\\|\/[A-Za-z0-9._-]|[A-Za-z]:[\\/][A-Za-z0-9._-]|\.agentsmesh[\\/]|\.claude[\\/]|\.cursor[\\/]|\.github[\\/]|\.continue[\\/]|\.junie[\\/]|\.gemini[\\/]|\.clinerules[\\/]|\.cline[\\/]|\.agents[\\/]|\.windsurf[\\/]|\.roo[\\/]|(?:[A-Za-z0-9._-]+[\\/])+|[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+)[A-Za-z0-9._@%+~:\\/-]*/g;
|
|
8116
|
+
var PATH_TOKEN = /(?:\.\.[\\/]|\.\/|\.\\|\/[A-Za-z0-9._-]|[A-Za-z]:[\\/][A-Za-z0-9._-]|\.agentsmesh[\\/]|\.claude[\\/]|\.cursor[\\/]|\.github[\\/]|\.continue[\\/]|\.junie[\\/]|\.kiro[\\/]|\.gemini[\\/]|\.clinerules[\\/]|\.cline[\\/]|\.agents[\\/]|\.windsurf[\\/]|\.roo[\\/]|(?:[A-Za-z0-9._-]+[\\/])+|[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+)[A-Za-z0-9._@%+~:\\/-]*/g;
|
|
7721
8117
|
var LINE_NUMBER_SUFFIX = /(?::(\d+)){1,2}$/;
|
|
7722
8118
|
function resolveProjectPath(token, projectRoot, sourceFile) {
|
|
7723
8119
|
const api = pathApi(projectRoot);
|
|
@@ -7861,6 +8257,7 @@ var IMPORT_REFERENCE_TARGETS = [
|
|
|
7861
8257
|
"copilot",
|
|
7862
8258
|
"continue",
|
|
7863
8259
|
"junie",
|
|
8260
|
+
"kiro",
|
|
7864
8261
|
"gemini-cli",
|
|
7865
8262
|
"cline",
|
|
7866
8263
|
"codex-cli",
|
|
@@ -7880,9 +8277,9 @@ function pathVariants(path) {
|
|
|
7880
8277
|
}
|
|
7881
8278
|
return variants;
|
|
7882
8279
|
}
|
|
7883
|
-
async function createImportReferenceNormalizer(
|
|
8280
|
+
async function createImportReferenceNormalizer(target13, projectRoot) {
|
|
7884
8281
|
const refs = /* @__PURE__ */ new Map();
|
|
7885
|
-
const targets = Array.from(/* @__PURE__ */ new Set([
|
|
8282
|
+
const targets = Array.from(/* @__PURE__ */ new Set([target13, ...IMPORT_REFERENCE_TARGETS]));
|
|
7886
8283
|
for (const candidate of targets) {
|
|
7887
8284
|
const candidateRefs = await buildImportReferenceMap(candidate, projectRoot);
|
|
7888
8285
|
for (const [targetPath, canonicalPath] of candidateRefs.entries()) {
|
|
@@ -7891,8 +8288,8 @@ async function createImportReferenceNormalizer(target12, projectRoot) {
|
|
|
7891
8288
|
}
|
|
7892
8289
|
const artifactMap = /* @__PURE__ */ new Map();
|
|
7893
8290
|
for (const [targetPath, canonicalPath] of refs.entries()) {
|
|
7894
|
-
const canonicalAbsPath = normalizePath(
|
|
7895
|
-
for (const variant of pathVariants(
|
|
8291
|
+
const canonicalAbsPath = normalizePath(join39(projectRoot, canonicalPath));
|
|
8292
|
+
for (const variant of pathVariants(join39(projectRoot, targetPath))) {
|
|
7896
8293
|
artifactMap.set(variant, canonicalAbsPath);
|
|
7897
8294
|
}
|
|
7898
8295
|
}
|
|
@@ -7907,9 +8304,9 @@ async function createImportReferenceNormalizer(target12, projectRoot) {
|
|
|
7907
8304
|
}
|
|
7908
8305
|
|
|
7909
8306
|
// src/targets/claude-code/importer-mappers.ts
|
|
7910
|
-
import { join as
|
|
8307
|
+
import { join as join40 } from "path";
|
|
7911
8308
|
async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
7912
|
-
const destPath =
|
|
8309
|
+
const destPath = join40(destDir, relativePath);
|
|
7913
8310
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7914
8311
|
return {
|
|
7915
8312
|
destPath,
|
|
@@ -7923,7 +8320,7 @@ async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
7923
8320
|
};
|
|
7924
8321
|
}
|
|
7925
8322
|
async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo) {
|
|
7926
|
-
const destPath =
|
|
8323
|
+
const destPath = join40(destDir, relativePath);
|
|
7927
8324
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7928
8325
|
const basePath = feature === "commands" ? CLAUDE_CANONICAL_COMMANDS_DIR : CLAUDE_CANONICAL_AGENTS_DIR;
|
|
7929
8326
|
return {
|
|
@@ -7947,8 +8344,8 @@ async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo
|
|
|
7947
8344
|
}
|
|
7948
8345
|
|
|
7949
8346
|
// src/targets/claude-code/settings-helpers.ts
|
|
7950
|
-
import { join as
|
|
7951
|
-
import { stringify as
|
|
8347
|
+
import { join as join41, dirname as dirname17 } from "path";
|
|
8348
|
+
import { stringify as yamlStringify6 } from "yaml";
|
|
7952
8349
|
function claudeHooksToCanonical(hooks) {
|
|
7953
8350
|
const result = {};
|
|
7954
8351
|
for (const [event, entries] of Object.entries(hooks)) {
|
|
@@ -7974,7 +8371,7 @@ function claudeHooksToCanonical(hooks) {
|
|
|
7974
8371
|
return result;
|
|
7975
8372
|
}
|
|
7976
8373
|
async function importMcpJson(projectRoot, results) {
|
|
7977
|
-
const mcpPath =
|
|
8374
|
+
const mcpPath = join41(projectRoot, CLAUDE_MCP_JSON);
|
|
7978
8375
|
const content = await readFileSafe(mcpPath);
|
|
7979
8376
|
if (content === null) return;
|
|
7980
8377
|
let parsed;
|
|
@@ -7985,7 +8382,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7985
8382
|
}
|
|
7986
8383
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
7987
8384
|
const mcpContent = JSON.stringify({ mcpServers: parsed.mcpServers }, null, 2);
|
|
7988
|
-
const destPath =
|
|
8385
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
7989
8386
|
await mkdirp(dirname17(destPath));
|
|
7990
8387
|
await writeFileAtomic(destPath, mcpContent);
|
|
7991
8388
|
results.push({
|
|
@@ -7997,7 +8394,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7997
8394
|
}
|
|
7998
8395
|
}
|
|
7999
8396
|
async function importSettings2(projectRoot, results) {
|
|
8000
|
-
const settingsPath =
|
|
8397
|
+
const settingsPath = join41(projectRoot, CLAUDE_SETTINGS);
|
|
8001
8398
|
const content = await readFileSafe(settingsPath);
|
|
8002
8399
|
if (!content) return;
|
|
8003
8400
|
let settings;
|
|
@@ -8009,7 +8406,7 @@ async function importSettings2(projectRoot, results) {
|
|
|
8009
8406
|
const alreadyImportedMcp = results.some((r) => r.feature === "mcp");
|
|
8010
8407
|
if (!alreadyImportedMcp && settings.mcpServers && typeof settings.mcpServers === "object") {
|
|
8011
8408
|
const mcpContent = JSON.stringify({ mcpServers: settings.mcpServers }, null, 2);
|
|
8012
|
-
const destPath =
|
|
8409
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
8013
8410
|
await mkdirp(dirname17(destPath));
|
|
8014
8411
|
await writeFileAtomic(destPath, mcpContent);
|
|
8015
8412
|
results.push({
|
|
@@ -8025,8 +8422,8 @@ async function importSettings2(projectRoot, results) {
|
|
|
8025
8422
|
const allow = Array.isArray(perms.allow) ? perms.allow.filter((s) => typeof s === "string") : [];
|
|
8026
8423
|
const deny = Array.isArray(perms.deny) ? perms.deny.filter((s) => typeof s === "string") : [];
|
|
8027
8424
|
if (allow.length > 0 || deny.length > 0) {
|
|
8028
|
-
const permContent =
|
|
8029
|
-
const destPath =
|
|
8425
|
+
const permContent = yamlStringify6({ allow, deny });
|
|
8426
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_PERMISSIONS);
|
|
8030
8427
|
await mkdirp(dirname17(destPath));
|
|
8031
8428
|
await writeFileAtomic(destPath, permContent);
|
|
8032
8429
|
results.push({
|
|
@@ -8041,8 +8438,8 @@ async function importSettings2(projectRoot, results) {
|
|
|
8041
8438
|
if (rawHooks && typeof rawHooks === "object" && !Array.isArray(rawHooks)) {
|
|
8042
8439
|
const canonicalHooks = claudeHooksToCanonical(rawHooks);
|
|
8043
8440
|
if (Object.keys(canonicalHooks).length > 0) {
|
|
8044
|
-
const hooksContent =
|
|
8045
|
-
const destPath =
|
|
8441
|
+
const hooksContent = yamlStringify6(canonicalHooks);
|
|
8442
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_HOOKS);
|
|
8046
8443
|
await mkdirp(dirname17(destPath));
|
|
8047
8444
|
await writeFileAtomic(destPath, hooksContent);
|
|
8048
8445
|
results.push({
|
|
@@ -8059,26 +8456,26 @@ async function importSettings2(projectRoot, results) {
|
|
|
8059
8456
|
async function importFromClaudeCode(projectRoot) {
|
|
8060
8457
|
const results = [];
|
|
8061
8458
|
const normalize = await createImportReferenceNormalizer("claude-code", projectRoot);
|
|
8062
|
-
await
|
|
8459
|
+
await importRules6(projectRoot, results, normalize);
|
|
8063
8460
|
await importCommands6(projectRoot, results, normalize);
|
|
8064
8461
|
await importAgents5(projectRoot, results, normalize);
|
|
8065
8462
|
await importSkills5(projectRoot, results, normalize);
|
|
8066
8463
|
await importMcpJson(projectRoot, results);
|
|
8067
8464
|
await importSettings2(projectRoot, results);
|
|
8068
|
-
await
|
|
8465
|
+
await importIgnore5(projectRoot, results);
|
|
8069
8466
|
return results;
|
|
8070
8467
|
}
|
|
8071
|
-
async function
|
|
8072
|
-
const destDir =
|
|
8073
|
-
const primaryClaudePath =
|
|
8468
|
+
async function importRules6(projectRoot, results, normalize) {
|
|
8469
|
+
const destDir = join42(projectRoot, CLAUDE_CANONICAL_RULES_DIR);
|
|
8470
|
+
const primaryClaudePath = join42(projectRoot, CLAUDE_ROOT);
|
|
8074
8471
|
const primaryContent = await readFileSafe(primaryClaudePath);
|
|
8075
|
-
const legacyClaudePath =
|
|
8472
|
+
const legacyClaudePath = join42(projectRoot, CLAUDE_LEGACY_ROOT);
|
|
8076
8473
|
const legacyContent = primaryContent === null ? await readFileSafe(legacyClaudePath) : null;
|
|
8077
8474
|
const claudeContent = primaryContent ?? legacyContent;
|
|
8078
8475
|
const claudePath = primaryContent !== null ? primaryClaudePath : legacyClaudePath;
|
|
8079
8476
|
if (claudeContent !== null) {
|
|
8080
8477
|
await mkdirp(destDir);
|
|
8081
|
-
const destPath =
|
|
8478
|
+
const destPath = join42(destDir, "_root.md");
|
|
8082
8479
|
const { frontmatter, body } = parseFrontmatter(normalize(claudeContent, claudePath, destPath));
|
|
8083
8480
|
const hasRoot = frontmatter.root === true;
|
|
8084
8481
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -8091,7 +8488,7 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
8091
8488
|
feature: "rules"
|
|
8092
8489
|
});
|
|
8093
8490
|
}
|
|
8094
|
-
const rulesDir =
|
|
8491
|
+
const rulesDir = join42(projectRoot, CLAUDE_RULES_DIR);
|
|
8095
8492
|
results.push(
|
|
8096
8493
|
...await importFileDirectory({
|
|
8097
8494
|
srcDir: rulesDir,
|
|
@@ -8104,8 +8501,8 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
8104
8501
|
);
|
|
8105
8502
|
}
|
|
8106
8503
|
async function importCommands6(projectRoot, results, normalize) {
|
|
8107
|
-
const destDir =
|
|
8108
|
-
const commandsDir =
|
|
8504
|
+
const destDir = join42(projectRoot, CLAUDE_CANONICAL_COMMANDS_DIR);
|
|
8505
|
+
const commandsDir = join42(projectRoot, CLAUDE_COMMANDS_DIR);
|
|
8109
8506
|
results.push(
|
|
8110
8507
|
...await importFileDirectory({
|
|
8111
8508
|
srcDir: commandsDir,
|
|
@@ -8118,8 +8515,8 @@ async function importCommands6(projectRoot, results, normalize) {
|
|
|
8118
8515
|
);
|
|
8119
8516
|
}
|
|
8120
8517
|
async function importAgents5(projectRoot, results, normalize) {
|
|
8121
|
-
const destDir =
|
|
8122
|
-
const agentsDir =
|
|
8518
|
+
const destDir = join42(projectRoot, CLAUDE_CANONICAL_AGENTS_DIR);
|
|
8519
|
+
const agentsDir = join42(projectRoot, CLAUDE_AGENTS_DIR);
|
|
8123
8520
|
results.push(
|
|
8124
8521
|
...await importFileDirectory({
|
|
8125
8522
|
srcDir: agentsDir,
|
|
@@ -8132,20 +8529,20 @@ async function importAgents5(projectRoot, results, normalize) {
|
|
|
8132
8529
|
);
|
|
8133
8530
|
}
|
|
8134
8531
|
async function importSkills5(projectRoot, results, normalize) {
|
|
8135
|
-
const skillsBaseDir =
|
|
8136
|
-
const destBase =
|
|
8532
|
+
const skillsBaseDir = join42(projectRoot, CLAUDE_SKILLS_DIR);
|
|
8533
|
+
const destBase = join42(projectRoot, CLAUDE_CANONICAL_SKILLS_DIR);
|
|
8137
8534
|
const allFiles = await readDirRecursive(skillsBaseDir);
|
|
8138
8535
|
const skillMdFiles = allFiles.filter((f) => f.endsWith("SKILL.md"));
|
|
8139
8536
|
for (const skillMdPath of skillMdFiles) {
|
|
8140
8537
|
const skillDir = dirname18(skillMdPath);
|
|
8141
|
-
const skillName =
|
|
8142
|
-
const destSkillDir =
|
|
8538
|
+
const skillName = basename27(skillDir);
|
|
8539
|
+
const destSkillDir = join42(destBase, skillName);
|
|
8143
8540
|
const skillFiles = await readDirRecursive(skillDir);
|
|
8144
8541
|
for (const filePath of skillFiles) {
|
|
8145
8542
|
const fileContent = await readFileSafe(filePath);
|
|
8146
8543
|
if (fileContent === null) continue;
|
|
8147
8544
|
const relPath = relative17(skillDir, filePath);
|
|
8148
|
-
const destPath =
|
|
8545
|
+
const destPath = join42(destSkillDir, relPath);
|
|
8149
8546
|
await mkdirp(dirname18(destPath));
|
|
8150
8547
|
const normalized = normalize(fileContent, filePath, destPath);
|
|
8151
8548
|
const parsed = relPath === "SKILL.md" ? parseFrontmatter(normalized) : null;
|
|
@@ -8167,11 +8564,11 @@ async function importSkills5(projectRoot, results, normalize) {
|
|
|
8167
8564
|
}
|
|
8168
8565
|
}
|
|
8169
8566
|
}
|
|
8170
|
-
async function
|
|
8171
|
-
const ignorePath =
|
|
8567
|
+
async function importIgnore5(projectRoot, results) {
|
|
8568
|
+
const ignorePath = join42(projectRoot, CLAUDE_IGNORE);
|
|
8172
8569
|
const content = await readFileSafe(ignorePath);
|
|
8173
8570
|
if (content === null) return;
|
|
8174
|
-
const destPath =
|
|
8571
|
+
const destPath = join42(projectRoot, CLAUDE_CANONICAL_IGNORE);
|
|
8175
8572
|
await mkdirp(dirname18(destPath));
|
|
8176
8573
|
await writeFileAtomic(destPath, content);
|
|
8177
8574
|
results.push({
|
|
@@ -8192,7 +8589,8 @@ var NATIVE_IMPORTERS = {
|
|
|
8192
8589
|
windsurf: importFromWindsurf,
|
|
8193
8590
|
cline: importFromCline,
|
|
8194
8591
|
continue: importFromContinue,
|
|
8195
|
-
junie: importFromJunie
|
|
8592
|
+
junie: importFromJunie,
|
|
8593
|
+
kiro: importFromKiro
|
|
8196
8594
|
};
|
|
8197
8595
|
async function importNativeToCanonical(repoPath, targetName) {
|
|
8198
8596
|
const importFn = NATIVE_IMPORTERS[targetName];
|
|
@@ -8203,17 +8601,17 @@ async function importNativeToCanonical(repoPath, targetName) {
|
|
|
8203
8601
|
}
|
|
8204
8602
|
|
|
8205
8603
|
// src/canonical/load/skill-pack-load.ts
|
|
8206
|
-
import { join as
|
|
8604
|
+
import { join as join43 } from "path";
|
|
8207
8605
|
import { readdir as readdir10 } from "fs/promises";
|
|
8208
8606
|
var SKILL = "SKILL.md";
|
|
8209
8607
|
async function isSkillPackLayout(root) {
|
|
8210
8608
|
if (!await exists(root)) return false;
|
|
8211
|
-
if (await exists(
|
|
8609
|
+
if (await exists(join43(root, SKILL))) return true;
|
|
8212
8610
|
try {
|
|
8213
8611
|
const ents = await readdir10(root, { withFileTypes: true });
|
|
8214
8612
|
for (const e of ents) {
|
|
8215
8613
|
if (!e.isDirectory() || e.name.startsWith(".")) continue;
|
|
8216
|
-
if (await exists(
|
|
8614
|
+
if (await exists(join43(root, e.name, SKILL))) return true;
|
|
8217
8615
|
}
|
|
8218
8616
|
} catch {
|
|
8219
8617
|
return false;
|
|
@@ -8222,7 +8620,7 @@ async function isSkillPackLayout(root) {
|
|
|
8222
8620
|
}
|
|
8223
8621
|
async function loadSkillsAtExtendPath(skillsRoot) {
|
|
8224
8622
|
if (!await exists(skillsRoot)) return [];
|
|
8225
|
-
if (await exists(
|
|
8623
|
+
if (await exists(join43(skillsRoot, SKILL))) {
|
|
8226
8624
|
const one = await parseSkillDirectory(skillsRoot);
|
|
8227
8625
|
return one ? [one] : [];
|
|
8228
8626
|
}
|
|
@@ -8230,7 +8628,7 @@ async function loadSkillsAtExtendPath(skillsRoot) {
|
|
|
8230
8628
|
}
|
|
8231
8629
|
|
|
8232
8630
|
// src/canonical/load/load-canonical-slice.ts
|
|
8233
|
-
import { basename as
|
|
8631
|
+
import { basename as basename28, dirname as dirname19, join as join44 } from "path";
|
|
8234
8632
|
import { stat as stat4 } from "fs/promises";
|
|
8235
8633
|
function emptyCanonical() {
|
|
8236
8634
|
return {
|
|
@@ -8261,8 +8659,8 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
8261
8659
|
);
|
|
8262
8660
|
}
|
|
8263
8661
|
const parent = dirname19(absolutePath);
|
|
8264
|
-
const parentBase =
|
|
8265
|
-
const fileBase =
|
|
8662
|
+
const parentBase = basename28(parent);
|
|
8663
|
+
const fileBase = basename28(absolutePath);
|
|
8266
8664
|
const slug = fileBase.replace(/\.md$/i, "");
|
|
8267
8665
|
if (parentBase === "rules") {
|
|
8268
8666
|
return { sliceRoot: parent, implicitPick: { rules: [slug] } };
|
|
@@ -8278,33 +8676,33 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
8278
8676
|
);
|
|
8279
8677
|
}
|
|
8280
8678
|
async function parseRulesAt(sliceRoot) {
|
|
8281
|
-
const base =
|
|
8679
|
+
const base = basename28(sliceRoot);
|
|
8282
8680
|
if (base === "rules") {
|
|
8283
8681
|
return parseRules(sliceRoot);
|
|
8284
8682
|
}
|
|
8285
|
-
const nested =
|
|
8683
|
+
const nested = join44(sliceRoot, "rules");
|
|
8286
8684
|
if (await exists(nested)) {
|
|
8287
8685
|
return parseRules(nested);
|
|
8288
8686
|
}
|
|
8289
8687
|
return [];
|
|
8290
8688
|
}
|
|
8291
8689
|
async function parseCommandsAt(sliceRoot) {
|
|
8292
|
-
const base =
|
|
8690
|
+
const base = basename28(sliceRoot);
|
|
8293
8691
|
if (base === "commands") {
|
|
8294
8692
|
return parseCommands(sliceRoot);
|
|
8295
8693
|
}
|
|
8296
|
-
const nested =
|
|
8694
|
+
const nested = join44(sliceRoot, "commands");
|
|
8297
8695
|
if (await exists(nested)) {
|
|
8298
8696
|
return parseCommands(nested);
|
|
8299
8697
|
}
|
|
8300
8698
|
return [];
|
|
8301
8699
|
}
|
|
8302
8700
|
async function parseAgentsAt(sliceRoot) {
|
|
8303
|
-
const base =
|
|
8701
|
+
const base = basename28(sliceRoot);
|
|
8304
8702
|
if (base === "agents") {
|
|
8305
8703
|
return parseAgents(sliceRoot);
|
|
8306
8704
|
}
|
|
8307
|
-
const nested =
|
|
8705
|
+
const nested = join44(sliceRoot, "agents");
|
|
8308
8706
|
if (await exists(nested)) {
|
|
8309
8707
|
return parseAgents(nested);
|
|
8310
8708
|
}
|
|
@@ -8314,15 +8712,15 @@ async function loadSkillsForPartialSlice(sliceRoot) {
|
|
|
8314
8712
|
if (await isSkillPackLayout(sliceRoot)) {
|
|
8315
8713
|
return loadSkillsAtExtendPath(sliceRoot);
|
|
8316
8714
|
}
|
|
8317
|
-
const nestedSkills =
|
|
8715
|
+
const nestedSkills = join44(sliceRoot, "skills");
|
|
8318
8716
|
if (await isSkillPackLayout(nestedSkills)) {
|
|
8319
8717
|
return loadSkillsAtExtendPath(nestedSkills);
|
|
8320
8718
|
}
|
|
8321
8719
|
return [];
|
|
8322
8720
|
}
|
|
8323
8721
|
async function loadCanonicalSliceAtPath(sliceRoot) {
|
|
8324
|
-
const
|
|
8325
|
-
if (await exists(
|
|
8722
|
+
const ab2 = join44(sliceRoot, ".agentsmesh");
|
|
8723
|
+
if (await exists(ab2)) {
|
|
8326
8724
|
return loadCanonicalFiles(sliceRoot);
|
|
8327
8725
|
}
|
|
8328
8726
|
const partial = emptyCanonical();
|
|
@@ -8354,7 +8752,7 @@ function emptyCanonical2() {
|
|
|
8354
8752
|
async function loadCanonicalForExtend(ext) {
|
|
8355
8753
|
const base = ext.resolvedPath;
|
|
8356
8754
|
if (!ext.path) {
|
|
8357
|
-
const agentsmeshDir =
|
|
8755
|
+
const agentsmeshDir = join45(base, ".agentsmesh");
|
|
8358
8756
|
if (!await exists(agentsmeshDir)) {
|
|
8359
8757
|
if (await isSkillPackLayout(base)) {
|
|
8360
8758
|
const skills = await loadSkillsAtExtendPath(base);
|
|
@@ -8374,12 +8772,12 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8374
8772
|
}
|
|
8375
8773
|
return loadCanonicalFiles(base);
|
|
8376
8774
|
}
|
|
8377
|
-
const rawRoot =
|
|
8775
|
+
const rawRoot = join45(base, ext.path);
|
|
8378
8776
|
if (!await exists(rawRoot)) {
|
|
8379
8777
|
throw new Error(`Extend "${ext.name}": path does not exist: ${rawRoot}`);
|
|
8380
8778
|
}
|
|
8381
8779
|
if (ext.target) {
|
|
8382
|
-
const agentsmeshDir =
|
|
8780
|
+
const agentsmeshDir = join45(base, ".agentsmesh");
|
|
8383
8781
|
if (!await exists(agentsmeshDir)) {
|
|
8384
8782
|
logger.info(
|
|
8385
8783
|
`[agentsmesh] Extend "${ext.name}": path "${ext.path}" with target "${ext.target}" \u2014 importing at extend root, then loading canonical.`
|
|
@@ -8400,7 +8798,7 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8400
8798
|
}
|
|
8401
8799
|
|
|
8402
8800
|
// src/canonical/extends/extend-pick.ts
|
|
8403
|
-
import { basename as
|
|
8801
|
+
import { basename as basename29 } from "path";
|
|
8404
8802
|
function applyExtendPick(canonical, features, pick, extendName) {
|
|
8405
8803
|
if (!pick) return canonical;
|
|
8406
8804
|
let next = { ...canonical };
|
|
@@ -8443,7 +8841,7 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8443
8841
|
if (pick.rules?.length && features.includes("rules")) {
|
|
8444
8842
|
const wanted = new Set(pick.rules);
|
|
8445
8843
|
const prev = next.rules;
|
|
8446
|
-
const stem = (src) =>
|
|
8844
|
+
const stem = (src) => basename29(src).replace(/\.md$/i, "");
|
|
8447
8845
|
next = {
|
|
8448
8846
|
...next,
|
|
8449
8847
|
rules: prev.filter((r) => wanted.has(stem(r.source)))
|
|
@@ -8460,10 +8858,10 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8460
8858
|
}
|
|
8461
8859
|
|
|
8462
8860
|
// src/canonical/load/pack-load.ts
|
|
8463
|
-
import { join as
|
|
8861
|
+
import { join as join47 } from "path";
|
|
8464
8862
|
|
|
8465
8863
|
// src/install/pack/pack-reader.ts
|
|
8466
|
-
import { join as
|
|
8864
|
+
import { join as join46 } from "path";
|
|
8467
8865
|
import { readdir as readdir11 } from "fs/promises";
|
|
8468
8866
|
import { parse as parseYaml5 } from "yaml";
|
|
8469
8867
|
|
|
@@ -8510,7 +8908,7 @@ function sameFeatures(a, b) {
|
|
|
8510
8908
|
return a.length === b.length && [...a].sort().every((feature, index) => feature === [...b].sort()[index]);
|
|
8511
8909
|
}
|
|
8512
8910
|
async function readPackMetadata(packDir) {
|
|
8513
|
-
const metaPath =
|
|
8911
|
+
const metaPath = join46(packDir, "pack.yaml");
|
|
8514
8912
|
const content = await readFileSafe(metaPath);
|
|
8515
8913
|
if (content === null) return null;
|
|
8516
8914
|
try {
|
|
@@ -8531,7 +8929,7 @@ async function findExistingPack(packsDir, source, scope) {
|
|
|
8531
8929
|
}
|
|
8532
8930
|
for (const entry of entries) {
|
|
8533
8931
|
if (!entry.isDirectory()) continue;
|
|
8534
|
-
const packDir =
|
|
8932
|
+
const packDir = join46(packsDir, entry.name);
|
|
8535
8933
|
const meta = await readPackMetadata(packDir);
|
|
8536
8934
|
if (meta && sourceIdentity(meta.source) === requestedIdentity && meta.target === scope.target && meta.as === scope.as && sameFeatures(meta.features, scope.features)) {
|
|
8537
8935
|
return { meta, packDir, name: meta.name };
|
|
@@ -8550,7 +8948,7 @@ async function listPacks(packsDir) {
|
|
|
8550
8948
|
const result = [];
|
|
8551
8949
|
for (const entry of entries) {
|
|
8552
8950
|
if (!entry.isDirectory()) continue;
|
|
8553
|
-
const packDir =
|
|
8951
|
+
const packDir = join46(packsDir, entry.name);
|
|
8554
8952
|
const meta = await readPackMetadata(packDir);
|
|
8555
8953
|
if (meta) {
|
|
8556
8954
|
result.push({ meta, packDir, name: meta.name });
|
|
@@ -8574,19 +8972,19 @@ function emptyCanonical3() {
|
|
|
8574
8972
|
}
|
|
8575
8973
|
async function loadPackCanonical(packDir) {
|
|
8576
8974
|
const [rules, commands, agents, skills, mcp, permissions, hooks, ignore] = await Promise.all([
|
|
8577
|
-
parseRules(
|
|
8578
|
-
parseCommands(
|
|
8579
|
-
parseAgents(
|
|
8580
|
-
parseSkills(
|
|
8581
|
-
parseMcp(
|
|
8582
|
-
parsePermissions(
|
|
8583
|
-
parseHooks(
|
|
8584
|
-
parseIgnore(
|
|
8975
|
+
parseRules(join47(packDir, "rules")),
|
|
8976
|
+
parseCommands(join47(packDir, "commands")),
|
|
8977
|
+
parseAgents(join47(packDir, "agents")),
|
|
8978
|
+
parseSkills(join47(packDir, "skills")),
|
|
8979
|
+
parseMcp(join47(packDir, "mcp.json")),
|
|
8980
|
+
parsePermissions(join47(packDir, "permissions.yaml")),
|
|
8981
|
+
parseHooks(join47(packDir, "hooks.yaml")),
|
|
8982
|
+
parseIgnore(join47(packDir, "ignore"))
|
|
8585
8983
|
]);
|
|
8586
8984
|
return { ...emptyCanonical3(), rules, commands, agents, skills, mcp, permissions, hooks, ignore };
|
|
8587
8985
|
}
|
|
8588
8986
|
async function loadPacksCanonical(abDir) {
|
|
8589
|
-
const packsDir =
|
|
8987
|
+
const packsDir = join47(abDir, "packs");
|
|
8590
8988
|
const packs = await listPacks(packsDir);
|
|
8591
8989
|
let merged = emptyCanonical3();
|
|
8592
8990
|
for (const { meta, packDir } of packs) {
|
|
@@ -8648,7 +9046,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8648
9046
|
const picked = applyExtendPick(filtered, ext.features, ext.pick, ext.name);
|
|
8649
9047
|
merged = mergeCanonicalFiles(merged, picked);
|
|
8650
9048
|
}
|
|
8651
|
-
const packsCanonical = await loadPacksCanonical(
|
|
9049
|
+
const packsCanonical = await loadPacksCanonical(join48(configDir, ".agentsmesh"));
|
|
8652
9050
|
merged = mergeCanonicalFiles(merged, packsCanonical);
|
|
8653
9051
|
const localCanonical = await loadCanonicalFiles(configDir);
|
|
8654
9052
|
merged = mergeCanonicalFiles(merged, localCanonical);
|
|
@@ -8657,7 +9055,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8657
9055
|
|
|
8658
9056
|
// src/config/core/lock.ts
|
|
8659
9057
|
import { parse as parseYaml6, stringify as stringifyYaml3 } from "yaml";
|
|
8660
|
-
import { join as
|
|
9058
|
+
import { join as join49, relative as relative18 } from "path";
|
|
8661
9059
|
|
|
8662
9060
|
// src/utils/crypto/hash.ts
|
|
8663
9061
|
import { createHash } from "crypto";
|
|
@@ -8704,7 +9102,7 @@ var FEATURE_PATTERNS = {
|
|
|
8704
9102
|
ignore: (path) => path === "ignore"
|
|
8705
9103
|
};
|
|
8706
9104
|
async function readLock(abDir) {
|
|
8707
|
-
const lockPath =
|
|
9105
|
+
const lockPath = join49(abDir, LOCK_FILENAME);
|
|
8708
9106
|
const content = await readFileSafe(lockPath);
|
|
8709
9107
|
if (content === null) return null;
|
|
8710
9108
|
try {
|
|
@@ -8723,7 +9121,7 @@ async function readLock(abDir) {
|
|
|
8723
9121
|
}
|
|
8724
9122
|
}
|
|
8725
9123
|
async function writeLock(abDir, lock) {
|
|
8726
|
-
const lockPath =
|
|
9124
|
+
const lockPath = join49(abDir, LOCK_FILENAME);
|
|
8727
9125
|
const raw = {
|
|
8728
9126
|
generated_at: lock.generatedAt,
|
|
8729
9127
|
generated_by: lock.generatedBy,
|
|
@@ -8777,7 +9175,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8777
9175
|
result[ext.name] = ext.version;
|
|
8778
9176
|
continue;
|
|
8779
9177
|
}
|
|
8780
|
-
const abDir =
|
|
9178
|
+
const abDir = join49(ext.resolvedPath, ".agentsmesh");
|
|
8781
9179
|
const checksums = await buildChecksums(abDir);
|
|
8782
9180
|
const fingerprint = Object.keys(checksums).sort().map((p) => `${p}:${checksums[p]}`).join("\n");
|
|
8783
9181
|
const h = hashContent(fingerprint);
|
|
@@ -8788,7 +9186,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8788
9186
|
}
|
|
8789
9187
|
|
|
8790
9188
|
// src/core/reference/map.ts
|
|
8791
|
-
import { basename as
|
|
9189
|
+
import { basename as basename31 } from "path";
|
|
8792
9190
|
|
|
8793
9191
|
// src/core/reference/map-directories.ts
|
|
8794
9192
|
import { posix as posix2 } from "path";
|
|
@@ -8807,29 +9205,29 @@ function addSkillDirectoryMappings(refs, canonicalPath, targetPath) {
|
|
|
8807
9205
|
}
|
|
8808
9206
|
|
|
8809
9207
|
// src/core/reference/map-targets.ts
|
|
8810
|
-
import { basename as
|
|
9208
|
+
import { basename as basename30 } from "path";
|
|
8811
9209
|
var SKILL_DIRS = Object.fromEntries(
|
|
8812
|
-
TARGET_IDS.map((
|
|
9210
|
+
TARGET_IDS.map((target13) => [target13, getTargetSkillDir(target13)]).filter(
|
|
8813
9211
|
(entry) => typeof entry[1] === "string"
|
|
8814
9212
|
)
|
|
8815
9213
|
);
|
|
8816
|
-
function ruleTargetPath(
|
|
8817
|
-
const def = getBuiltinTargetDefinition(
|
|
9214
|
+
function ruleTargetPath(target13, rule) {
|
|
9215
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8818
9216
|
if (!def) return null;
|
|
8819
9217
|
if (rule.root) {
|
|
8820
9218
|
return def.generators.primaryRootInstructionPath ?? null;
|
|
8821
9219
|
}
|
|
8822
|
-
if (rule.targets.length > 0 && !rule.targets.includes(
|
|
8823
|
-
const slug =
|
|
9220
|
+
if (rule.targets.length > 0 && !rule.targets.includes(target13)) return null;
|
|
9221
|
+
const slug = basename30(rule.source, ".md");
|
|
8824
9222
|
return def.paths.rulePath(slug, rule);
|
|
8825
9223
|
}
|
|
8826
|
-
function commandTargetPath(
|
|
8827
|
-
const def = getBuiltinTargetDefinition(
|
|
9224
|
+
function commandTargetPath(target13, name, config) {
|
|
9225
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8828
9226
|
if (!def) return null;
|
|
8829
9227
|
return def.paths.commandPath(name, config);
|
|
8830
9228
|
}
|
|
8831
|
-
function agentTargetPath(
|
|
8832
|
-
const def = getBuiltinTargetDefinition(
|
|
9229
|
+
function agentTargetPath(target13, name, config) {
|
|
9230
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8833
9231
|
if (!def) return null;
|
|
8834
9232
|
return def.paths.agentPath(name, config);
|
|
8835
9233
|
}
|
|
@@ -8839,21 +9237,21 @@ function addDirectoryMapping3(refs, from, to) {
|
|
|
8839
9237
|
refs.set(from, to);
|
|
8840
9238
|
refs.set(`${from}/`, `${to}/`);
|
|
8841
9239
|
}
|
|
8842
|
-
function buildReferenceMap(
|
|
9240
|
+
function buildReferenceMap(target13, canonical, config) {
|
|
8843
9241
|
const refs = /* @__PURE__ */ new Map();
|
|
8844
9242
|
for (const rule of canonical.rules) {
|
|
8845
|
-
const path = ruleTargetPath(
|
|
8846
|
-
if (path) refs.set(`.agentsmesh/rules/${
|
|
9243
|
+
const path = ruleTargetPath(target13, rule);
|
|
9244
|
+
if (path) refs.set(`.agentsmesh/rules/${basename31(rule.source)}`, path);
|
|
8847
9245
|
}
|
|
8848
9246
|
for (const command of canonical.commands) {
|
|
8849
|
-
const path = commandTargetPath(
|
|
9247
|
+
const path = commandTargetPath(target13, command.name, config);
|
|
8850
9248
|
if (path) refs.set(`.agentsmesh/commands/${command.name}.md`, path);
|
|
8851
9249
|
}
|
|
8852
9250
|
for (const agent of canonical.agents) {
|
|
8853
|
-
const path = agentTargetPath(
|
|
9251
|
+
const path = agentTargetPath(target13, agent.name, config);
|
|
8854
9252
|
if (path) refs.set(`.agentsmesh/agents/${agent.name}.md`, path);
|
|
8855
9253
|
}
|
|
8856
|
-
const skillDir = SKILL_DIRS[
|
|
9254
|
+
const skillDir = SKILL_DIRS[target13];
|
|
8857
9255
|
if (!skillDir) return refs;
|
|
8858
9256
|
for (const skill of canonical.skills) {
|
|
8859
9257
|
addDirectoryMapping3(refs, `.agentsmesh/skills/${skill.name}`, `${skillDir}/${skill.name}`);
|
|
@@ -8886,17 +9284,20 @@ function isCursorAgents(result) {
|
|
|
8886
9284
|
function isGeminiAgents(result) {
|
|
8887
9285
|
return result.target === "gemini-cli" && result.path.endsWith(AGENTS_SUFFIX);
|
|
8888
9286
|
}
|
|
9287
|
+
function isKiroAgents(result) {
|
|
9288
|
+
return result.target === "kiro" && result.path.endsWith(AGENTS_SUFFIX);
|
|
9289
|
+
}
|
|
8889
9290
|
function isCompatibilityAgents(result) {
|
|
8890
9291
|
return isCursorAgents(result) || isGeminiAgents(result);
|
|
8891
9292
|
}
|
|
8892
|
-
function reverseReferenceMap(
|
|
8893
|
-
const cached = cache.get(
|
|
9293
|
+
function reverseReferenceMap(target13, canonical, config, cache) {
|
|
9294
|
+
const cached = cache.get(target13);
|
|
8894
9295
|
if (cached) return cached;
|
|
8895
9296
|
const reversed = /* @__PURE__ */ new Map();
|
|
8896
|
-
for (const [canonicalPath, targetPath] of buildReferenceMap(
|
|
9297
|
+
for (const [canonicalPath, targetPath] of buildReferenceMap(target13, canonical, config)) {
|
|
8897
9298
|
if (!reversed.has(targetPath)) reversed.set(targetPath, canonicalPath);
|
|
8898
9299
|
}
|
|
8899
|
-
cache.set(
|
|
9300
|
+
cache.set(target13, reversed);
|
|
8900
9301
|
return reversed;
|
|
8901
9302
|
}
|
|
8902
9303
|
function normalizeContent(content, refs) {
|
|
@@ -8912,6 +9313,13 @@ function hasEquivalentCanonicalContent(left, right, canonical, config, cache) {
|
|
|
8912
9313
|
const rightRefs = reverseReferenceMap(right.target, canonical, config, cache);
|
|
8913
9314
|
return normalizeContent(left.content, leftRefs) === normalizeContent(right.content, rightRefs);
|
|
8914
9315
|
}
|
|
9316
|
+
function hasCanonicalSupersetContent(richer, plainer, canonical, config, cache) {
|
|
9317
|
+
const richerRefs = reverseReferenceMap(richer.target, canonical, config, cache);
|
|
9318
|
+
const plainerRefs = reverseReferenceMap(plainer.target, canonical, config, cache);
|
|
9319
|
+
const richerContent = normalizeContent(richer.content, richerRefs).trim();
|
|
9320
|
+
const plainerContent = normalizeContent(plainer.content, plainerRefs).trim();
|
|
9321
|
+
return richerContent.length > plainerContent.length && richerContent.includes(plainerContent);
|
|
9322
|
+
}
|
|
8915
9323
|
function preferEquivalentCodexAgents(results, canonical, config) {
|
|
8916
9324
|
const overlapTargetsByPath = /* @__PURE__ */ new Map();
|
|
8917
9325
|
for (const result of results) {
|
|
@@ -8928,15 +9336,15 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8928
9336
|
return results.filter((result) => {
|
|
8929
9337
|
if (isCursorAgents(result)) {
|
|
8930
9338
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8931
|
-
if (targets && [...targets].some((
|
|
9339
|
+
if (targets && [...targets].some((target13) => target13 !== "cursor")) return false;
|
|
8932
9340
|
}
|
|
8933
9341
|
if (isGeminiAgents(result)) {
|
|
8934
9342
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8935
|
-
if (targets && [...targets].some((
|
|
9343
|
+
if (targets && [...targets].some((target13) => target13 !== "cursor" && target13 !== "gemini-cli")) {
|
|
8936
9344
|
return false;
|
|
8937
9345
|
}
|
|
8938
9346
|
}
|
|
8939
|
-
if (!isWindsurfAgents(result) && !isClineAgents(result) && !isCursorAgents(result) && !isGeminiAgents(result)) {
|
|
9347
|
+
if (!isWindsurfAgents(result) && !isClineAgents(result) && !isCursorAgents(result) && !isGeminiAgents(result) && !isKiroAgents(result)) {
|
|
8940
9348
|
return true;
|
|
8941
9349
|
}
|
|
8942
9350
|
const codexResult = codexByPath.get(result.path);
|
|
@@ -8944,16 +9352,16 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8944
9352
|
if (isCompatibilityAgents(result) || isWindsurfAgents(result) || isClineAgents(result)) {
|
|
8945
9353
|
return false;
|
|
8946
9354
|
}
|
|
8947
|
-
return !hasEquivalentCanonicalContent(codexResult, result, canonical, config, reverseCache);
|
|
9355
|
+
return !(hasEquivalentCanonicalContent(codexResult, result, canonical, config, reverseCache) || hasCanonicalSupersetContent(codexResult, result, canonical, config, reverseCache));
|
|
8948
9356
|
});
|
|
8949
9357
|
}
|
|
8950
9358
|
|
|
8951
9359
|
// src/core/reference/rewriter.ts
|
|
8952
9360
|
import { existsSync as existsSync3 } from "fs";
|
|
8953
|
-
import { dirname as dirname21, join as
|
|
9361
|
+
import { dirname as dirname21, join as join51 } from "path";
|
|
8954
9362
|
|
|
8955
9363
|
// src/core/reference/output-source-map.ts
|
|
8956
|
-
import { dirname as dirname20, join as
|
|
9364
|
+
import { dirname as dirname20, join as join50, normalize as normalizePath2 } from "path";
|
|
8957
9365
|
function canonicalRulePath(rule) {
|
|
8958
9366
|
return `.agentsmesh/rules/${rule.source.split("/").pop()}`;
|
|
8959
9367
|
}
|
|
@@ -8976,17 +9384,17 @@ function copilotInstructionsPath(rule) {
|
|
|
8976
9384
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
8977
9385
|
return `.github/instructions/${slug}.instructions.md`;
|
|
8978
9386
|
}
|
|
8979
|
-
function ruleOutputPaths(
|
|
9387
|
+
function ruleOutputPaths(target13, rule, refs) {
|
|
8980
9388
|
const paths = [];
|
|
8981
9389
|
const targetPath = refs.get(canonicalRulePath(rule));
|
|
8982
9390
|
if (targetPath) paths.push(targetPath);
|
|
8983
|
-
if (
|
|
9391
|
+
if (target13 === "copilot" && !rule.root && rule.globs.length > 0) {
|
|
8984
9392
|
paths.push(copilotInstructionsPath(rule));
|
|
8985
9393
|
}
|
|
8986
|
-
if ((
|
|
9394
|
+
if ((target13 === "cline" || target13 === "cursor") && rule.root) {
|
|
8987
9395
|
paths.push("AGENTS.md");
|
|
8988
9396
|
}
|
|
8989
|
-
if (
|
|
9397
|
+
if (target13 === "windsurf") {
|
|
8990
9398
|
if (rule.root) {
|
|
8991
9399
|
paths.push("AGENTS.md");
|
|
8992
9400
|
} else {
|
|
@@ -8994,10 +9402,10 @@ function ruleOutputPaths(target12, rule, refs) {
|
|
|
8994
9402
|
if (dir) paths.push(`${dir}/AGENTS.md`);
|
|
8995
9403
|
}
|
|
8996
9404
|
}
|
|
8997
|
-
if (
|
|
9405
|
+
if (target13 === "gemini-cli") {
|
|
8998
9406
|
paths.push(GEMINI_COMPAT_AGENTS);
|
|
8999
9407
|
}
|
|
9000
|
-
if (
|
|
9408
|
+
if (target13 === "codex-cli") {
|
|
9001
9409
|
if (!rule.root && rule.codexEmit === "execution") {
|
|
9002
9410
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
9003
9411
|
paths.push(`${CODEX_RULES_DIR}/${slug}.rules`);
|
|
@@ -9005,46 +9413,46 @@ function ruleOutputPaths(target12, rule, refs) {
|
|
|
9005
9413
|
}
|
|
9006
9414
|
return paths;
|
|
9007
9415
|
}
|
|
9008
|
-
function addPackSkillPaths(refs,
|
|
9009
|
-
const skillDir = SKILL_DIRS[
|
|
9416
|
+
function addPackSkillPaths(refs, target13, canonical, projectRoot) {
|
|
9417
|
+
const skillDir = SKILL_DIRS[target13];
|
|
9010
9418
|
if (!skillDir) return;
|
|
9011
|
-
const packsPrefix =
|
|
9419
|
+
const packsPrefix = join50(projectRoot, ".agentsmesh", "packs");
|
|
9012
9420
|
for (const skill of canonical.skills) {
|
|
9013
9421
|
const skillSourceDir = dirname20(skill.source);
|
|
9014
9422
|
if (!skillSourceDir.startsWith(packsPrefix)) continue;
|
|
9015
|
-
const targetSkillDir = normalizePath2(
|
|
9423
|
+
const targetSkillDir = normalizePath2(join50(projectRoot, skillDir, skill.name));
|
|
9016
9424
|
refs.set(normalizePath2(skillSourceDir), targetSkillDir);
|
|
9017
|
-
refs.set(normalizePath2(skill.source), normalizePath2(
|
|
9425
|
+
refs.set(normalizePath2(skill.source), normalizePath2(join50(targetSkillDir, "SKILL.md")));
|
|
9018
9426
|
for (const file of skill.supportingFiles) {
|
|
9019
|
-
const targetFilePath = normalizePath2(
|
|
9427
|
+
const targetFilePath = normalizePath2(join50(targetSkillDir, file.relativePath));
|
|
9020
9428
|
refs.set(normalizePath2(file.absolutePath), targetFilePath);
|
|
9021
9429
|
}
|
|
9022
9430
|
}
|
|
9023
9431
|
}
|
|
9024
|
-
function buildArtifactPathMap(
|
|
9432
|
+
function buildArtifactPathMap(target13, canonical, config, projectRoot, destinationPath) {
|
|
9025
9433
|
const refs = new Map(
|
|
9026
|
-
[...buildReferenceMap(
|
|
9027
|
-
normalizePath2(
|
|
9028
|
-
normalizePath2(
|
|
9434
|
+
[...buildReferenceMap(target13, canonical, config)].map(([canonicalPath, targetPath]) => [
|
|
9435
|
+
normalizePath2(join50(projectRoot, canonicalPath)),
|
|
9436
|
+
normalizePath2(join50(projectRoot, targetPath))
|
|
9029
9437
|
])
|
|
9030
9438
|
);
|
|
9031
|
-
if (
|
|
9439
|
+
if (target13 === "copilot" && destinationPath?.startsWith(".github/instructions/")) {
|
|
9032
9440
|
for (const rule of canonical.rules) {
|
|
9033
9441
|
if (rule.root || rule.globs.length === 0) continue;
|
|
9034
9442
|
refs.set(
|
|
9035
|
-
normalizePath2(
|
|
9036
|
-
normalizePath2(
|
|
9443
|
+
normalizePath2(join50(projectRoot, canonicalRulePath(rule))),
|
|
9444
|
+
normalizePath2(join50(projectRoot, copilotInstructionsPath(rule)))
|
|
9037
9445
|
);
|
|
9038
9446
|
}
|
|
9039
9447
|
}
|
|
9040
|
-
addPackSkillPaths(refs,
|
|
9448
|
+
addPackSkillPaths(refs, target13, canonical, projectRoot);
|
|
9041
9449
|
return refs;
|
|
9042
9450
|
}
|
|
9043
|
-
function buildOutputSourceMap(
|
|
9044
|
-
const refs = buildReferenceMap(
|
|
9451
|
+
function buildOutputSourceMap(target13, canonical, config) {
|
|
9452
|
+
const refs = buildReferenceMap(target13, canonical, config);
|
|
9045
9453
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
9046
9454
|
for (const rule of canonical.rules) {
|
|
9047
|
-
for (const targetPath of ruleOutputPaths(
|
|
9455
|
+
for (const targetPath of ruleOutputPaths(target13, rule, refs)) {
|
|
9048
9456
|
sourceMap.set(targetPath, rule.source);
|
|
9049
9457
|
}
|
|
9050
9458
|
}
|
|
@@ -9072,7 +9480,7 @@ function buildOutputSourceMap(target12, canonical, config) {
|
|
|
9072
9480
|
function collectPlannedPaths(projectRoot, results) {
|
|
9073
9481
|
const planned = /* @__PURE__ */ new Set();
|
|
9074
9482
|
for (const result of results) {
|
|
9075
|
-
const absolutePath =
|
|
9483
|
+
const absolutePath = join51(projectRoot, result.path);
|
|
9076
9484
|
planned.add(absolutePath);
|
|
9077
9485
|
let current = dirname21(absolutePath);
|
|
9078
9486
|
while (current.startsWith(projectRoot) && !planned.has(current)) {
|
|
@@ -9114,7 +9522,7 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot) {
|
|
|
9114
9522
|
content: result.content,
|
|
9115
9523
|
projectRoot,
|
|
9116
9524
|
sourceFile,
|
|
9117
|
-
destinationFile:
|
|
9525
|
+
destinationFile: join51(projectRoot, result.path),
|
|
9118
9526
|
translatePath: (absolutePath) => artifactMap.get(absolutePath) ?? absolutePath,
|
|
9119
9527
|
pathExists: (absolutePath) => plannedPaths.has(absolutePath) || existsSync3(absolutePath)
|
|
9120
9528
|
});
|
|
@@ -9123,6 +9531,8 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot) {
|
|
|
9123
9531
|
}
|
|
9124
9532
|
|
|
9125
9533
|
// src/core/generate/collision.ts
|
|
9534
|
+
var AGENTS_SUFFIX2 = "AGENTS.md";
|
|
9535
|
+
var CODEX_TARGET2 = "codex-cli";
|
|
9126
9536
|
function statusRank(status) {
|
|
9127
9537
|
switch (status) {
|
|
9128
9538
|
case "created":
|
|
@@ -9135,6 +9545,34 @@ function statusRank(status) {
|
|
|
9135
9545
|
return 0;
|
|
9136
9546
|
}
|
|
9137
9547
|
}
|
|
9548
|
+
function mergeDuplicateMetadata(preferred, other) {
|
|
9549
|
+
if (statusRank(other.status) <= statusRank(preferred.status)) return preferred;
|
|
9550
|
+
return {
|
|
9551
|
+
...preferred,
|
|
9552
|
+
status: other.status,
|
|
9553
|
+
currentContent: other.currentContent ?? preferred.currentContent
|
|
9554
|
+
};
|
|
9555
|
+
}
|
|
9556
|
+
function trimmedContent(content) {
|
|
9557
|
+
return content.trim();
|
|
9558
|
+
}
|
|
9559
|
+
function richerAgentsResult(left, right) {
|
|
9560
|
+
if (!left.path.endsWith(AGENTS_SUFFIX2) || left.path !== right.path) return null;
|
|
9561
|
+
const leftTrimmed = trimmedContent(left.content);
|
|
9562
|
+
const rightTrimmed = trimmedContent(right.content);
|
|
9563
|
+
if (!leftTrimmed || !rightTrimmed) return null;
|
|
9564
|
+
const leftContainsRight = leftTrimmed.includes(rightTrimmed);
|
|
9565
|
+
const rightContainsLeft = rightTrimmed.includes(leftTrimmed);
|
|
9566
|
+
if (leftContainsRight === rightContainsLeft) return null;
|
|
9567
|
+
return leftContainsRight ? mergeDuplicateMetadata(left, right) : mergeDuplicateMetadata(right, left);
|
|
9568
|
+
}
|
|
9569
|
+
function richerCodexAgentsResult(left, right) {
|
|
9570
|
+
if (!left.path.endsWith(AGENTS_SUFFIX2) || left.path !== right.path) return null;
|
|
9571
|
+
const codex = left.target === CODEX_TARGET2 ? left : right.target === CODEX_TARGET2 ? right : null;
|
|
9572
|
+
const other = codex === left ? right : left;
|
|
9573
|
+
if (!codex) return null;
|
|
9574
|
+
return trimmedContent(codex.content).length > trimmedContent(other.content).length ? mergeDuplicateMetadata(codex, other) : null;
|
|
9575
|
+
}
|
|
9138
9576
|
function resolveOutputCollisions(results) {
|
|
9139
9577
|
const deduped = [];
|
|
9140
9578
|
for (const result of results) {
|
|
@@ -9145,17 +9583,21 @@ function resolveOutputCollisions(results) {
|
|
|
9145
9583
|
}
|
|
9146
9584
|
const existing = deduped[existingIdx];
|
|
9147
9585
|
if (existing.content !== result.content) {
|
|
9586
|
+
const richer = richerAgentsResult(existing, result);
|
|
9587
|
+
if (richer) {
|
|
9588
|
+
deduped[existingIdx] = richer;
|
|
9589
|
+
continue;
|
|
9590
|
+
}
|
|
9591
|
+
const richerCodex = richerCodexAgentsResult(existing, result);
|
|
9592
|
+
if (richerCodex) {
|
|
9593
|
+
deduped[existingIdx] = richerCodex;
|
|
9594
|
+
continue;
|
|
9595
|
+
}
|
|
9148
9596
|
throw new Error(
|
|
9149
9597
|
`Conflicting generated outputs for ${result.path}: ${existing.target} and ${result.target} produce different content.`
|
|
9150
9598
|
);
|
|
9151
9599
|
}
|
|
9152
|
-
|
|
9153
|
-
deduped[existingIdx] = {
|
|
9154
|
-
...existing,
|
|
9155
|
-
status: result.status,
|
|
9156
|
-
currentContent: result.currentContent ?? existing.currentContent
|
|
9157
|
-
};
|
|
9158
|
-
}
|
|
9600
|
+
deduped[existingIdx] = mergeDuplicateMetadata(existing, result);
|
|
9159
9601
|
}
|
|
9160
9602
|
return deduped;
|
|
9161
9603
|
}
|
|
@@ -9165,7 +9607,7 @@ function refreshResultStatus(result) {
|
|
|
9165
9607
|
}
|
|
9166
9608
|
|
|
9167
9609
|
// src/core/generate/feature-loop.ts
|
|
9168
|
-
import { join as
|
|
9610
|
+
import { join as join52 } from "path";
|
|
9169
9611
|
function computeStatus(existing, content) {
|
|
9170
9612
|
if (existing === null) return "created";
|
|
9171
9613
|
if (existing !== content) return "updated";
|
|
@@ -9173,13 +9615,13 @@ function computeStatus(existing, content) {
|
|
|
9173
9615
|
}
|
|
9174
9616
|
async function generateFeature(results, targets, canonical, projectRoot, enabled, getGen) {
|
|
9175
9617
|
if (!enabled) return;
|
|
9176
|
-
for (const
|
|
9177
|
-
const gen = getGen(
|
|
9618
|
+
for (const target13 of targets) {
|
|
9619
|
+
const gen = getGen(target13);
|
|
9178
9620
|
if (!gen) continue;
|
|
9179
9621
|
for (const out of gen(canonical)) {
|
|
9180
|
-
const existing = await readFileSafe(
|
|
9622
|
+
const existing = await readFileSafe(join52(projectRoot, out.path));
|
|
9181
9623
|
results.push({
|
|
9182
|
-
target:
|
|
9624
|
+
target: target13,
|
|
9183
9625
|
path: out.path,
|
|
9184
9626
|
content: out.content,
|
|
9185
9627
|
currentContent: existing ?? void 0,
|
|
@@ -9197,8 +9639,8 @@ function getDescriptor(name) {
|
|
|
9197
9639
|
return descriptorRegistry.get(name) ?? builtinDescriptors.get(name);
|
|
9198
9640
|
}
|
|
9199
9641
|
function getTarget(name) {
|
|
9200
|
-
const
|
|
9201
|
-
if (
|
|
9642
|
+
const descriptor13 = getDescriptor(name);
|
|
9643
|
+
if (descriptor13) return descriptor13.generators;
|
|
9202
9644
|
const legacy = legacyRegistry.get(name);
|
|
9203
9645
|
if (legacy) return legacy;
|
|
9204
9646
|
throw new Error(`Unknown target: ${name}`);
|
|
@@ -9222,10 +9664,10 @@ function decoratePrimaryRootInstructions(results) {
|
|
|
9222
9664
|
}
|
|
9223
9665
|
|
|
9224
9666
|
// src/core/generate/optional-features.ts
|
|
9225
|
-
import { join as
|
|
9667
|
+
import { join as join54 } from "path";
|
|
9226
9668
|
|
|
9227
9669
|
// src/targets/copilot/hook-assets.ts
|
|
9228
|
-
import { join as
|
|
9670
|
+
import { join as join53, relative as relative19 } from "path";
|
|
9229
9671
|
var SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
|
|
9230
9672
|
function safePhaseName(phase) {
|
|
9231
9673
|
return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
@@ -9246,7 +9688,7 @@ async function buildAssetOutput(projectRoot, command) {
|
|
|
9246
9688
|
const match = command.match(SCRIPT_PREFIX_RE);
|
|
9247
9689
|
const sourceToken = match?.groups?.["path"];
|
|
9248
9690
|
if (!sourceToken) return null;
|
|
9249
|
-
const sourcePath =
|
|
9691
|
+
const sourcePath = join53(projectRoot, sourceToken);
|
|
9250
9692
|
const assetContent = await readFileSafe(sourcePath);
|
|
9251
9693
|
if (assetContent === null) return null;
|
|
9252
9694
|
const repoRelative = toRepoRelative(projectRoot, sourcePath);
|
|
@@ -9334,14 +9776,14 @@ function mergeGeminiSettingsJson(existing, newContent) {
|
|
|
9334
9776
|
|
|
9335
9777
|
// src/core/generate/optional-features.ts
|
|
9336
9778
|
async function generatePermissionsFeature(results, targets, canonical, projectRoot) {
|
|
9337
|
-
for (const
|
|
9338
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9779
|
+
for (const target13 of targets) {
|
|
9780
|
+
const gen = resolveTargetFeatureGenerator(target13, "permissions");
|
|
9339
9781
|
if (!gen) continue;
|
|
9340
9782
|
for (const out of gen(canonical)) {
|
|
9341
|
-
const existing = await readFileSafe(
|
|
9783
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9342
9784
|
const content = existing !== null && SETTINGS_JSON_PATHS.includes(out.path) ? mergeSettingsJson(existing, out.content) : out.content;
|
|
9343
9785
|
results.push({
|
|
9344
|
-
target:
|
|
9786
|
+
target: target13,
|
|
9345
9787
|
path: out.path,
|
|
9346
9788
|
content,
|
|
9347
9789
|
currentContent: existing ?? void 0,
|
|
@@ -9351,15 +9793,15 @@ async function generatePermissionsFeature(results, targets, canonical, projectRo
|
|
|
9351
9793
|
}
|
|
9352
9794
|
}
|
|
9353
9795
|
async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
9354
|
-
for (const
|
|
9355
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9796
|
+
for (const target13 of targets) {
|
|
9797
|
+
const gen = resolveTargetFeatureGenerator(target13, "hooks");
|
|
9356
9798
|
if (!gen) continue;
|
|
9357
|
-
const outputs =
|
|
9799
|
+
const outputs = target13 === "copilot" ? await addHookScriptAssets(projectRoot, canonical, gen(canonical)) : gen(canonical);
|
|
9358
9800
|
for (const out of outputs) {
|
|
9359
|
-
const existing = await readFileSafe(
|
|
9801
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9360
9802
|
let content = out.content;
|
|
9361
9803
|
if (SETTINGS_JSON_PATHS.includes(out.path)) {
|
|
9362
|
-
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target ===
|
|
9804
|
+
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target === target13);
|
|
9363
9805
|
const pendingResult = pendingIdx >= 0 ? results[pendingIdx] : void 0;
|
|
9364
9806
|
const base = pendingResult?.content ?? existing;
|
|
9365
9807
|
if (base !== null) {
|
|
@@ -9370,7 +9812,7 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9370
9812
|
}
|
|
9371
9813
|
}
|
|
9372
9814
|
results.push({
|
|
9373
|
-
target:
|
|
9815
|
+
target: target13,
|
|
9374
9816
|
path: out.path,
|
|
9375
9817
|
content,
|
|
9376
9818
|
currentContent: existing ?? void 0,
|
|
@@ -9380,17 +9822,17 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9380
9822
|
}
|
|
9381
9823
|
}
|
|
9382
9824
|
async function generateGeminiSettingsFeature(results, targets, canonical, projectRoot) {
|
|
9383
|
-
for (const
|
|
9384
|
-
if (
|
|
9385
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9825
|
+
for (const target13 of targets) {
|
|
9826
|
+
if (target13 !== "gemini-cli") continue;
|
|
9827
|
+
const gen = resolveTargetFeatureGenerator(target13, "settings");
|
|
9386
9828
|
if (!gen) continue;
|
|
9387
9829
|
const outputs = gen(canonical);
|
|
9388
9830
|
if (outputs.length === 0) continue;
|
|
9389
9831
|
for (const out of outputs) {
|
|
9390
|
-
const existing = await readFileSafe(
|
|
9832
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9391
9833
|
const content = existing !== null && out.path === GEMINI_SETTINGS ? mergeGeminiSettingsJson(existing, out.content) : out.content;
|
|
9392
9834
|
results.push({
|
|
9393
|
-
target:
|
|
9835
|
+
target: target13,
|
|
9394
9836
|
path: out.path,
|
|
9395
9837
|
content,
|
|
9396
9838
|
currentContent: existing ?? void 0,
|
|
@@ -9419,7 +9861,7 @@ async function generate(ctx) {
|
|
|
9419
9861
|
canonical,
|
|
9420
9862
|
projectRoot,
|
|
9421
9863
|
hasRules,
|
|
9422
|
-
(
|
|
9864
|
+
(target13) => resolveTargetFeatureGenerator(target13, "rules", config)
|
|
9423
9865
|
);
|
|
9424
9866
|
await generateFeature(
|
|
9425
9867
|
results,
|
|
@@ -9427,7 +9869,7 @@ async function generate(ctx) {
|
|
|
9427
9869
|
canonical,
|
|
9428
9870
|
projectRoot,
|
|
9429
9871
|
hasCommands,
|
|
9430
|
-
(
|
|
9872
|
+
(target13) => resolveTargetFeatureGenerator(target13, "commands", config)
|
|
9431
9873
|
);
|
|
9432
9874
|
await generateFeature(
|
|
9433
9875
|
results,
|
|
@@ -9435,7 +9877,7 @@ async function generate(ctx) {
|
|
|
9435
9877
|
canonical,
|
|
9436
9878
|
projectRoot,
|
|
9437
9879
|
hasAgents,
|
|
9438
|
-
(
|
|
9880
|
+
(target13) => resolveTargetFeatureGenerator(target13, "agents", config)
|
|
9439
9881
|
);
|
|
9440
9882
|
await generateFeature(
|
|
9441
9883
|
results,
|
|
@@ -9443,7 +9885,7 @@ async function generate(ctx) {
|
|
|
9443
9885
|
canonical,
|
|
9444
9886
|
projectRoot,
|
|
9445
9887
|
hasSkills,
|
|
9446
|
-
(
|
|
9888
|
+
(target13) => resolveTargetFeatureGenerator(target13, "skills", config)
|
|
9447
9889
|
);
|
|
9448
9890
|
await generateFeature(
|
|
9449
9891
|
results,
|
|
@@ -9451,7 +9893,7 @@ async function generate(ctx) {
|
|
|
9451
9893
|
canonical,
|
|
9452
9894
|
projectRoot,
|
|
9453
9895
|
hasMcp,
|
|
9454
|
-
(
|
|
9896
|
+
(target13) => resolveTargetFeatureGenerator(target13, "mcp", config)
|
|
9455
9897
|
);
|
|
9456
9898
|
if (hasPermissions) await generatePermissionsFeature(results, targets, canonical, projectRoot);
|
|
9457
9899
|
if (hasHooks) await generateHooksFeature(results, targets, canonical, projectRoot);
|
|
@@ -9461,7 +9903,7 @@ async function generate(ctx) {
|
|
|
9461
9903
|
canonical,
|
|
9462
9904
|
projectRoot,
|
|
9463
9905
|
hasIgnore,
|
|
9464
|
-
(
|
|
9906
|
+
(target13) => resolveTargetFeatureGenerator(target13, "ignore", config)
|
|
9465
9907
|
);
|
|
9466
9908
|
if (hasMcp || hasIgnore || hasHooks || hasAgents) {
|
|
9467
9909
|
await generateGeminiSettingsFeature(results, targets, canonical, projectRoot);
|
|
@@ -9473,7 +9915,7 @@ async function generate(ctx) {
|
|
|
9473
9915
|
|
|
9474
9916
|
// src/core/generate/stale-cleanup.ts
|
|
9475
9917
|
import { readdir as readdir12, rm as rm6 } from "fs/promises";
|
|
9476
|
-
import { join as
|
|
9918
|
+
import { join as join55, relative as relative20 } from "path";
|
|
9477
9919
|
var TARGET_MANAGED_OUTPUTS = {
|
|
9478
9920
|
"claude-code": {
|
|
9479
9921
|
dirs: [".claude/agents", ".claude/commands", ".claude/rules", ".claude/skills"],
|
|
@@ -9501,6 +9943,10 @@ var TARGET_MANAGED_OUTPUTS = {
|
|
|
9501
9943
|
dirs: [".junie/agents", ".junie/commands", ".junie/rules", ".junie/skills"],
|
|
9502
9944
|
files: [".aiignore", ".junie/AGENTS.md", ".junie/mcp/mcp.json"]
|
|
9503
9945
|
},
|
|
9946
|
+
kiro: {
|
|
9947
|
+
dirs: [".kiro/hooks", ".kiro/skills", ".kiro/steering"],
|
|
9948
|
+
files: ["AGENTS.md", ".kiro/settings/mcp.json", ".kiroignore"]
|
|
9949
|
+
},
|
|
9504
9950
|
"gemini-cli": {
|
|
9505
9951
|
dirs: [".gemini/agents", ".gemini/commands", ".gemini/skills"],
|
|
9506
9952
|
files: [
|
|
@@ -9539,7 +9985,7 @@ async function listFiles2(root, base = root) {
|
|
|
9539
9985
|
const entries = await readdir12(root, { withFileTypes: true });
|
|
9540
9986
|
const files = [];
|
|
9541
9987
|
for (const entry of entries) {
|
|
9542
|
-
const abs =
|
|
9988
|
+
const abs = join55(root, entry.name);
|
|
9543
9989
|
if (entry.isDirectory()) {
|
|
9544
9990
|
files.push(...await listFiles2(abs, base));
|
|
9545
9991
|
continue;
|
|
@@ -9550,18 +9996,18 @@ async function listFiles2(root, base = root) {
|
|
|
9550
9996
|
}
|
|
9551
9997
|
async function removeIfStale(projectRoot, relPath, expected) {
|
|
9552
9998
|
if (expected.has(relPath)) return;
|
|
9553
|
-
const abs =
|
|
9999
|
+
const abs = join55(projectRoot, relPath);
|
|
9554
10000
|
if (await exists(abs)) await rm6(abs, { recursive: true, force: true });
|
|
9555
10001
|
}
|
|
9556
10002
|
async function cleanupStaleGeneratedOutputs(args) {
|
|
9557
10003
|
const expected = new Set(args.expectedPaths);
|
|
9558
10004
|
const stale = /* @__PURE__ */ new Set();
|
|
9559
|
-
for (const
|
|
9560
|
-
const managed = TARGET_MANAGED_OUTPUTS[
|
|
10005
|
+
for (const target13 of args.targets) {
|
|
10006
|
+
const managed = TARGET_MANAGED_OUTPUTS[target13];
|
|
9561
10007
|
if (!managed) continue;
|
|
9562
10008
|
for (const file of managed.files) stale.add(file);
|
|
9563
10009
|
for (const dir of managed.dirs) {
|
|
9564
|
-
const absDir =
|
|
10010
|
+
const absDir = join55(args.projectRoot, dir);
|
|
9565
10011
|
if (!await exists(absDir)) continue;
|
|
9566
10012
|
for (const file of await listFiles2(absDir)) {
|
|
9567
10013
|
stale.add(`${dir}/${file}`.replace(/\/+/g, "/"));
|
|
@@ -9574,17 +10020,17 @@ async function cleanupStaleGeneratedOutputs(args) {
|
|
|
9574
10020
|
}
|
|
9575
10021
|
|
|
9576
10022
|
// src/core/matrix/matrix.ts
|
|
9577
|
-
import { basename as
|
|
10023
|
+
import { basename as basename32 } from "path";
|
|
9578
10024
|
|
|
9579
10025
|
// src/targets/catalog/target-catalog.ts
|
|
9580
10026
|
var TARGET_CATALOG = Object.fromEntries(
|
|
9581
|
-
BUILTIN_TARGETS.map((
|
|
9582
|
-
|
|
10027
|
+
BUILTIN_TARGETS.map((target13) => [
|
|
10028
|
+
target13.id,
|
|
9583
10029
|
{
|
|
9584
|
-
importFrom:
|
|
9585
|
-
emptyImportMessage:
|
|
9586
|
-
lintRules:
|
|
9587
|
-
capabilities:
|
|
10030
|
+
importFrom: target13.generators.importFrom,
|
|
10031
|
+
emptyImportMessage: target13.emptyImportMessage,
|
|
10032
|
+
lintRules: target13.lintRules,
|
|
10033
|
+
capabilities: target13.capabilities
|
|
9588
10034
|
}
|
|
9589
10035
|
])
|
|
9590
10036
|
);
|
|
@@ -9611,7 +10057,7 @@ var SUPPORT_MATRIX = Object.fromEntries(
|
|
|
9611
10057
|
FEATURE_IDS.map((feature) => [
|
|
9612
10058
|
feature,
|
|
9613
10059
|
Object.fromEntries(
|
|
9614
|
-
TARGET_IDS.map((
|
|
10060
|
+
TARGET_IDS.map((target13) => [target13, TARGET_CATALOG[target13].capabilities[feature]])
|
|
9615
10061
|
)
|
|
9616
10062
|
])
|
|
9617
10063
|
);
|
|
@@ -9717,13 +10163,13 @@ function formatMatrix(rows, targets) {
|
|
|
9717
10163
|
function formatVerboseDetails(canonical) {
|
|
9718
10164
|
const lines = [];
|
|
9719
10165
|
if (canonical.rules.length > 0) {
|
|
9720
|
-
lines.push(`rules: ${canonical.rules.map((r) =>
|
|
10166
|
+
lines.push(`rules: ${canonical.rules.map((r) => basename32(r.source)).join(", ")}`);
|
|
9721
10167
|
}
|
|
9722
10168
|
if (canonical.commands.length > 0) {
|
|
9723
|
-
lines.push(`commands: ${canonical.commands.map((c2) =>
|
|
10169
|
+
lines.push(`commands: ${canonical.commands.map((c2) => basename32(c2.source)).join(", ")}`);
|
|
9724
10170
|
}
|
|
9725
10171
|
if (canonical.agents.length > 0) {
|
|
9726
|
-
lines.push(`agents: ${canonical.agents.map((a) =>
|
|
10172
|
+
lines.push(`agents: ${canonical.agents.map((a) => basename32(a.source)).join(", ")}`);
|
|
9727
10173
|
}
|
|
9728
10174
|
if (canonical.skills.length > 0) {
|
|
9729
10175
|
lines.push(`skills: ${canonical.skills.map((s) => s.name).join(", ")}`);
|
|
@@ -9775,11 +10221,11 @@ async function runMatrix(flags, projectRoot) {
|
|
|
9775
10221
|
}
|
|
9776
10222
|
|
|
9777
10223
|
// src/cli/commands/generate.ts
|
|
9778
|
-
function ensurePathInsideRoot(rootDir, relativePath,
|
|
10224
|
+
function ensurePathInsideRoot(rootDir, relativePath, target13) {
|
|
9779
10225
|
const rootAbs = resolve4(rootDir);
|
|
9780
10226
|
const outputAbs = resolve4(rootDir, relativePath);
|
|
9781
10227
|
if (outputAbs === rootAbs || outputAbs.startsWith(`${rootAbs}${sep}`)) return outputAbs;
|
|
9782
|
-
throw new Error(`Unsafe generated output path for ${
|
|
10228
|
+
throw new Error(`Unsafe generated output path for ${target13}: ${relativePath}`);
|
|
9783
10229
|
}
|
|
9784
10230
|
async function runGenerate(flags, projectRoot, options = {}) {
|
|
9785
10231
|
if (flags.features !== void 0) {
|
|
@@ -9795,7 +10241,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9795
10241
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
9796
10242
|
const lockFeatures = config.collaboration?.lock_features ?? [];
|
|
9797
10243
|
if (config.collaboration?.strategy === "lock" && !force && lockFeatures.length > 0) {
|
|
9798
|
-
const abDir =
|
|
10244
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9799
10245
|
const existingLock = await readLock(abDir);
|
|
9800
10246
|
if (existingLock !== null) {
|
|
9801
10247
|
const currentChecksums = await buildChecksums(abDir);
|
|
@@ -9831,10 +10277,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9831
10277
|
return 0;
|
|
9832
10278
|
}
|
|
9833
10279
|
if (!dryRun) {
|
|
9834
|
-
const abDir =
|
|
10280
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9835
10281
|
const checksums = await buildChecksums(abDir);
|
|
9836
10282
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9837
|
-
const packChecksums = await buildPackChecksums(
|
|
10283
|
+
const packChecksums = await buildPackChecksums(join56(abDir, "packs"));
|
|
9838
10284
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9839
10285
|
await writeLock(abDir, {
|
|
9840
10286
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9845,7 +10291,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9845
10291
|
packs: packChecksums
|
|
9846
10292
|
});
|
|
9847
10293
|
try {
|
|
9848
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
10294
|
+
await ensureCacheSymlink(getCacheDir(), join56(configDir, ".agentsmeshcache"));
|
|
9849
10295
|
} catch (err) {
|
|
9850
10296
|
logger.warn(
|
|
9851
10297
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9892,10 +10338,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9892
10338
|
} else {
|
|
9893
10339
|
logger.info(`Nothing changed. (${unchanged} unchanged)`);
|
|
9894
10340
|
}
|
|
9895
|
-
const abDir =
|
|
10341
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9896
10342
|
const checksums = await buildChecksums(abDir);
|
|
9897
10343
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9898
|
-
const packChecksums = await buildPackChecksums(
|
|
10344
|
+
const packChecksums = await buildPackChecksums(join56(abDir, "packs"));
|
|
9899
10345
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9900
10346
|
await writeLock(abDir, {
|
|
9901
10347
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9906,7 +10352,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9906
10352
|
packs: packChecksums
|
|
9907
10353
|
});
|
|
9908
10354
|
try {
|
|
9909
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
10355
|
+
await ensureCacheSymlink(getCacheDir(), join56(configDir, ".agentsmeshcache"));
|
|
9910
10356
|
} catch (err) {
|
|
9911
10357
|
logger.warn(
|
|
9912
10358
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9920,20 +10366,9 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9920
10366
|
}
|
|
9921
10367
|
|
|
9922
10368
|
// src/cli/commands/init.ts
|
|
9923
|
-
import { join as
|
|
10369
|
+
import { join as join59 } from "path";
|
|
9924
10370
|
|
|
9925
10371
|
// src/cli/commands/init-templates.ts
|
|
9926
|
-
var ALL_TARGETS = [
|
|
9927
|
-
"claude-code",
|
|
9928
|
-
"cursor",
|
|
9929
|
-
"copilot",
|
|
9930
|
-
"continue",
|
|
9931
|
-
"junie",
|
|
9932
|
-
"gemini-cli",
|
|
9933
|
-
"cline",
|
|
9934
|
-
"codex-cli",
|
|
9935
|
-
"windsurf"
|
|
9936
|
-
];
|
|
9937
10372
|
var ALL_FEATURES = [
|
|
9938
10373
|
"rules",
|
|
9939
10374
|
"commands",
|
|
@@ -9944,8 +10379,9 @@ var ALL_FEATURES = [
|
|
|
9944
10379
|
"ignore",
|
|
9945
10380
|
"permissions"
|
|
9946
10381
|
];
|
|
10382
|
+
var DEFAULT_INIT_TARGETS = TARGET_IDS.filter((target13) => target13 !== "codex-cli");
|
|
9947
10383
|
function buildConfig(targets) {
|
|
9948
|
-
const targetList = (targets.length > 0 ? targets :
|
|
10384
|
+
const targetList = (targets.length > 0 ? targets : DEFAULT_INIT_TARGETS).map((t) => ` - ${t}`).join("\n");
|
|
9949
10385
|
const featureList = ALL_FEATURES.map((f) => ` - ${f}`).join("\n");
|
|
9950
10386
|
return `version: 1
|
|
9951
10387
|
targets:
|
|
@@ -10076,7 +10512,7 @@ var LOCAL_TEMPLATE = `# Personal overrides \u2014 NOT committed to git
|
|
|
10076
10512
|
`;
|
|
10077
10513
|
|
|
10078
10514
|
// src/cli/commands/init-detect.ts
|
|
10079
|
-
import { join as
|
|
10515
|
+
import { join as join57 } from "path";
|
|
10080
10516
|
var TOOL_INDICATORS = BUILTIN_TARGETS.map((d) => ({
|
|
10081
10517
|
id: d.id,
|
|
10082
10518
|
paths: [...d.detectionPaths]
|
|
@@ -10085,7 +10521,7 @@ async function detectExistingConfigs(projectRoot) {
|
|
|
10085
10521
|
const found = [];
|
|
10086
10522
|
for (const { id, paths } of TOOL_INDICATORS) {
|
|
10087
10523
|
for (const p of paths) {
|
|
10088
|
-
const full =
|
|
10524
|
+
const full = join57(projectRoot, p);
|
|
10089
10525
|
if (await exists(full)) {
|
|
10090
10526
|
found.push(id);
|
|
10091
10527
|
break;
|
|
@@ -10095,6 +10531,110 @@ async function detectExistingConfigs(projectRoot) {
|
|
|
10095
10531
|
return [...new Set(found)];
|
|
10096
10532
|
}
|
|
10097
10533
|
|
|
10534
|
+
// src/cli/commands/init-scaffold.ts
|
|
10535
|
+
import { join as join58 } from "path";
|
|
10536
|
+
import { readdir as readdir13 } from "fs/promises";
|
|
10537
|
+
function ab(projectRoot, rel2) {
|
|
10538
|
+
return join58(projectRoot, ".agentsmesh", rel2);
|
|
10539
|
+
}
|
|
10540
|
+
async function countMdFiles(dir) {
|
|
10541
|
+
if (!await exists(dir)) return 0;
|
|
10542
|
+
const entries = await readdir13(dir, { withFileTypes: true });
|
|
10543
|
+
return entries.filter((e) => e.isFile() && e.name.endsWith(".md")).length;
|
|
10544
|
+
}
|
|
10545
|
+
async function hasAnyImportedSkill(projectRoot) {
|
|
10546
|
+
const skillsRoot = ab(projectRoot, "skills");
|
|
10547
|
+
if (!await exists(skillsRoot)) return false;
|
|
10548
|
+
const entries = await readdir13(skillsRoot, { withFileTypes: true });
|
|
10549
|
+
for (const e of entries) {
|
|
10550
|
+
if (!e.isDirectory()) continue;
|
|
10551
|
+
if (await exists(join58(skillsRoot, e.name, "SKILL.md"))) return true;
|
|
10552
|
+
}
|
|
10553
|
+
return false;
|
|
10554
|
+
}
|
|
10555
|
+
async function writeScaffoldFull(projectRoot) {
|
|
10556
|
+
const rulesDir = ab(projectRoot, "rules");
|
|
10557
|
+
await mkdirp(rulesDir);
|
|
10558
|
+
await writeFileAtomic(join58(rulesDir, "_root.md"), TEMPLATE_ROOT_RULE);
|
|
10559
|
+
logger.success("Created .agentsmesh/rules/_root.md");
|
|
10560
|
+
await writeFileAtomic(join58(rulesDir, "example.md"), TEMPLATE_EXAMPLE_RULE);
|
|
10561
|
+
logger.success("Created .agentsmesh/rules/example.md");
|
|
10562
|
+
const commandsDir = ab(projectRoot, "commands");
|
|
10563
|
+
await mkdirp(commandsDir);
|
|
10564
|
+
await writeFileAtomic(join58(commandsDir, "example.md"), TEMPLATE_EXAMPLE_COMMAND);
|
|
10565
|
+
logger.success("Created .agentsmesh/commands/example.md");
|
|
10566
|
+
const agentsDir = ab(projectRoot, "agents");
|
|
10567
|
+
await mkdirp(agentsDir);
|
|
10568
|
+
await writeFileAtomic(join58(agentsDir, "example.md"), TEMPLATE_EXAMPLE_AGENT);
|
|
10569
|
+
logger.success("Created .agentsmesh/agents/example.md");
|
|
10570
|
+
const skillDir = ab(projectRoot, join58("skills", "example"));
|
|
10571
|
+
await mkdirp(skillDir);
|
|
10572
|
+
await writeFileAtomic(join58(skillDir, "SKILL.md"), TEMPLATE_EXAMPLE_SKILL);
|
|
10573
|
+
logger.success("Created .agentsmesh/skills/example/SKILL.md");
|
|
10574
|
+
await writeFileAtomic(ab(projectRoot, "mcp.json"), TEMPLATE_MCP);
|
|
10575
|
+
logger.success("Created .agentsmesh/mcp.json");
|
|
10576
|
+
await writeFileAtomic(ab(projectRoot, "hooks.yaml"), TEMPLATE_HOOKS);
|
|
10577
|
+
logger.success("Created .agentsmesh/hooks.yaml");
|
|
10578
|
+
await writeFileAtomic(ab(projectRoot, "permissions.yaml"), TEMPLATE_PERMISSIONS);
|
|
10579
|
+
logger.success("Created .agentsmesh/permissions.yaml");
|
|
10580
|
+
await writeFileAtomic(ab(projectRoot, "ignore"), TEMPLATE_IGNORE);
|
|
10581
|
+
logger.success("Created .agentsmesh/ignore");
|
|
10582
|
+
}
|
|
10583
|
+
async function writeScaffoldGapFill(projectRoot) {
|
|
10584
|
+
const rulesDir = ab(projectRoot, "rules");
|
|
10585
|
+
const rulesMd = await countMdFiles(rulesDir);
|
|
10586
|
+
const rootPath = join58(rulesDir, "_root.md");
|
|
10587
|
+
const hasRoot = await exists(rootPath);
|
|
10588
|
+
await mkdirp(rulesDir);
|
|
10589
|
+
if (rulesMd === 0) {
|
|
10590
|
+
await writeFileAtomic(rootPath, TEMPLATE_ROOT_RULE);
|
|
10591
|
+
logger.success("Created .agentsmesh/rules/_root.md");
|
|
10592
|
+
await writeFileAtomic(join58(rulesDir, "example.md"), TEMPLATE_EXAMPLE_RULE);
|
|
10593
|
+
logger.success("Created .agentsmesh/rules/example.md");
|
|
10594
|
+
} else if (!hasRoot) {
|
|
10595
|
+
await writeFileAtomic(rootPath, TEMPLATE_ROOT_RULE);
|
|
10596
|
+
logger.success("Created .agentsmesh/rules/_root.md");
|
|
10597
|
+
}
|
|
10598
|
+
const commandsDir = ab(projectRoot, "commands");
|
|
10599
|
+
if (await countMdFiles(commandsDir) === 0) {
|
|
10600
|
+
await mkdirp(commandsDir);
|
|
10601
|
+
await writeFileAtomic(join58(commandsDir, "example.md"), TEMPLATE_EXAMPLE_COMMAND);
|
|
10602
|
+
logger.success("Created .agentsmesh/commands/example.md");
|
|
10603
|
+
}
|
|
10604
|
+
const agentsDir = ab(projectRoot, "agents");
|
|
10605
|
+
if (await countMdFiles(agentsDir) === 0) {
|
|
10606
|
+
await mkdirp(agentsDir);
|
|
10607
|
+
await writeFileAtomic(join58(agentsDir, "example.md"), TEMPLATE_EXAMPLE_AGENT);
|
|
10608
|
+
logger.success("Created .agentsmesh/agents/example.md");
|
|
10609
|
+
}
|
|
10610
|
+
if (!await hasAnyImportedSkill(projectRoot)) {
|
|
10611
|
+
const skillDir = ab(projectRoot, join58("skills", "example"));
|
|
10612
|
+
await mkdirp(skillDir);
|
|
10613
|
+
await writeFileAtomic(join58(skillDir, "SKILL.md"), TEMPLATE_EXAMPLE_SKILL);
|
|
10614
|
+
logger.success("Created .agentsmesh/skills/example/SKILL.md");
|
|
10615
|
+
}
|
|
10616
|
+
const mcpPath = ab(projectRoot, "mcp.json");
|
|
10617
|
+
if (!await exists(mcpPath)) {
|
|
10618
|
+
await writeFileAtomic(mcpPath, TEMPLATE_MCP);
|
|
10619
|
+
logger.success("Created .agentsmesh/mcp.json");
|
|
10620
|
+
}
|
|
10621
|
+
const hooksPath = ab(projectRoot, "hooks.yaml");
|
|
10622
|
+
if (!await exists(hooksPath)) {
|
|
10623
|
+
await writeFileAtomic(hooksPath, TEMPLATE_HOOKS);
|
|
10624
|
+
logger.success("Created .agentsmesh/hooks.yaml");
|
|
10625
|
+
}
|
|
10626
|
+
const permsPath = ab(projectRoot, "permissions.yaml");
|
|
10627
|
+
if (!await exists(permsPath)) {
|
|
10628
|
+
await writeFileAtomic(permsPath, TEMPLATE_PERMISSIONS);
|
|
10629
|
+
logger.success("Created .agentsmesh/permissions.yaml");
|
|
10630
|
+
}
|
|
10631
|
+
const ignorePath = ab(projectRoot, "ignore");
|
|
10632
|
+
if (!await exists(ignorePath)) {
|
|
10633
|
+
await writeFileAtomic(ignorePath, TEMPLATE_IGNORE);
|
|
10634
|
+
logger.success("Created .agentsmesh/ignore");
|
|
10635
|
+
}
|
|
10636
|
+
}
|
|
10637
|
+
|
|
10098
10638
|
// src/cli/commands/init.ts
|
|
10099
10639
|
var CONFIG_FILENAME2 = "agentsmesh.yaml";
|
|
10100
10640
|
var LOCAL_CONFIG_FILENAME2 = "agentsmesh.local.yaml";
|
|
@@ -10103,7 +10643,7 @@ var IMPORTERS = Object.fromEntries(
|
|
|
10103
10643
|
BUILTIN_TARGETS.map((d) => [d.id, (root) => d.generators.importFrom(root)])
|
|
10104
10644
|
);
|
|
10105
10645
|
async function appendToGitignore(projectRoot) {
|
|
10106
|
-
const gitignorePath =
|
|
10646
|
+
const gitignorePath = join59(projectRoot, ".gitignore");
|
|
10107
10647
|
const current = await readFileSafe(gitignorePath) ?? "";
|
|
10108
10648
|
const lines = new Set(current.split("\n").map((s) => s.trim()));
|
|
10109
10649
|
const toAdd = GITIGNORE_ENTRIES.filter((e) => !lines.has(e));
|
|
@@ -10111,33 +10651,8 @@ async function appendToGitignore(projectRoot) {
|
|
|
10111
10651
|
const suffix = current.endsWith("\n") || current === "" ? "" : "\n";
|
|
10112
10652
|
await writeFileAtomic(gitignorePath, current + suffix + toAdd.join("\n") + "\n");
|
|
10113
10653
|
}
|
|
10114
|
-
async function writeScaffold(projectRoot) {
|
|
10115
|
-
const ab = (rel2) => join57(projectRoot, ".agentsmesh", rel2);
|
|
10116
|
-
await mkdirp(ab("rules"));
|
|
10117
|
-
await writeFileAtomic(ab("rules/_root.md"), TEMPLATE_ROOT_RULE);
|
|
10118
|
-
logger.success("Created .agentsmesh/rules/_root.md");
|
|
10119
|
-
await writeFileAtomic(ab("rules/example.md"), TEMPLATE_EXAMPLE_RULE);
|
|
10120
|
-
logger.success("Created .agentsmesh/rules/example.md");
|
|
10121
|
-
await mkdirp(ab("commands"));
|
|
10122
|
-
await writeFileAtomic(ab("commands/example.md"), TEMPLATE_EXAMPLE_COMMAND);
|
|
10123
|
-
logger.success("Created .agentsmesh/commands/example.md");
|
|
10124
|
-
await mkdirp(ab("agents"));
|
|
10125
|
-
await writeFileAtomic(ab("agents/example.md"), TEMPLATE_EXAMPLE_AGENT);
|
|
10126
|
-
logger.success("Created .agentsmesh/agents/example.md");
|
|
10127
|
-
await mkdirp(ab("skills/example"));
|
|
10128
|
-
await writeFileAtomic(ab("skills/example/SKILL.md"), TEMPLATE_EXAMPLE_SKILL);
|
|
10129
|
-
logger.success("Created .agentsmesh/skills/example/SKILL.md");
|
|
10130
|
-
await writeFileAtomic(ab("mcp.json"), TEMPLATE_MCP);
|
|
10131
|
-
logger.success("Created .agentsmesh/mcp.json");
|
|
10132
|
-
await writeFileAtomic(ab("hooks.yaml"), TEMPLATE_HOOKS);
|
|
10133
|
-
logger.success("Created .agentsmesh/hooks.yaml");
|
|
10134
|
-
await writeFileAtomic(ab("permissions.yaml"), TEMPLATE_PERMISSIONS);
|
|
10135
|
-
logger.success("Created .agentsmesh/permissions.yaml");
|
|
10136
|
-
await writeFileAtomic(ab("ignore"), TEMPLATE_IGNORE);
|
|
10137
|
-
logger.success("Created .agentsmesh/ignore");
|
|
10138
|
-
}
|
|
10139
10654
|
async function runInit(projectRoot, options = {}) {
|
|
10140
|
-
const configPath =
|
|
10655
|
+
const configPath = join59(projectRoot, CONFIG_FILENAME2);
|
|
10141
10656
|
if (await exists(configPath)) {
|
|
10142
10657
|
throw new Error(`Already initialized. ${CONFIG_FILENAME2} exists. Remove it first to re-init.`);
|
|
10143
10658
|
}
|
|
@@ -10159,22 +10674,23 @@ async function runInit(projectRoot, options = {}) {
|
|
|
10159
10674
|
if (totalImported > 0) {
|
|
10160
10675
|
logger.info(`Imported ${totalImported} file(s) from ${existing.length} tool(s).`);
|
|
10161
10676
|
}
|
|
10677
|
+
await writeScaffoldGapFill(projectRoot);
|
|
10162
10678
|
await writeFileAtomic(configPath, buildConfig(existing));
|
|
10163
10679
|
logger.success(`Created ${CONFIG_FILENAME2} (targets: ${existing.join(", ")})`);
|
|
10164
10680
|
} else {
|
|
10165
10681
|
logger.info(
|
|
10166
10682
|
`Run 'agentsmesh init --yes' to auto-import, or 'agentsmesh import --from <tool>' manually.`
|
|
10167
10683
|
);
|
|
10168
|
-
await
|
|
10684
|
+
await writeScaffoldFull(projectRoot);
|
|
10169
10685
|
await writeFileAtomic(configPath, buildConfig([]));
|
|
10170
10686
|
logger.success(`Created ${CONFIG_FILENAME2}`);
|
|
10171
10687
|
}
|
|
10172
10688
|
} else {
|
|
10173
|
-
await
|
|
10689
|
+
await writeScaffoldFull(projectRoot);
|
|
10174
10690
|
await writeFileAtomic(configPath, buildConfig([]));
|
|
10175
10691
|
logger.success(`Created ${CONFIG_FILENAME2}`);
|
|
10176
10692
|
}
|
|
10177
|
-
const localPath =
|
|
10693
|
+
const localPath = join59(projectRoot, LOCAL_CONFIG_FILENAME2);
|
|
10178
10694
|
await writeFileAtomic(localPath, LOCAL_TEMPLATE);
|
|
10179
10695
|
logger.success(`Created ${LOCAL_CONFIG_FILENAME2}`);
|
|
10180
10696
|
await appendToGitignore(projectRoot);
|
|
@@ -10193,10 +10709,10 @@ async function runImport(flags, projectRoot) {
|
|
|
10193
10709
|
if (!isBuiltinTargetId(normalized)) {
|
|
10194
10710
|
throw new Error(`Unknown --from "${from}". Supported: ${TARGET_IDS.join(", ")}.`);
|
|
10195
10711
|
}
|
|
10196
|
-
const
|
|
10197
|
-
const results = await
|
|
10712
|
+
const target13 = getTargetCatalogEntry(normalized);
|
|
10713
|
+
const results = await target13.importFrom(root);
|
|
10198
10714
|
if (results.length === 0) {
|
|
10199
|
-
logger.info(
|
|
10715
|
+
logger.info(target13.emptyImportMessage);
|
|
10200
10716
|
return;
|
|
10201
10717
|
}
|
|
10202
10718
|
for (const r of results) {
|
|
@@ -10281,56 +10797,56 @@ async function runDiff(flags, projectRoot) {
|
|
|
10281
10797
|
import { relative as relative22 } from "path";
|
|
10282
10798
|
|
|
10283
10799
|
// src/core/lint/commands.ts
|
|
10284
|
-
function lintCommands(canonical,
|
|
10800
|
+
function lintCommands(canonical, target13) {
|
|
10285
10801
|
if (canonical.commands.length === 0) return [];
|
|
10286
10802
|
return canonical.commands.flatMap((command) => {
|
|
10287
|
-
if (
|
|
10803
|
+
if (target13 === "copilot" && command.allowedTools.length > 0) {
|
|
10288
10804
|
return [
|
|
10289
10805
|
{
|
|
10290
10806
|
level: "warning",
|
|
10291
10807
|
file: command.source,
|
|
10292
|
-
target:
|
|
10808
|
+
target: target13,
|
|
10293
10809
|
message: "Copilot prompt files do not enforce canonical allowed-tools natively."
|
|
10294
10810
|
}
|
|
10295
10811
|
];
|
|
10296
10812
|
}
|
|
10297
|
-
if (
|
|
10813
|
+
if (target13 === "cursor" && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
10298
10814
|
return [
|
|
10299
10815
|
{
|
|
10300
10816
|
level: "warning",
|
|
10301
10817
|
file: command.source,
|
|
10302
|
-
target:
|
|
10818
|
+
target: target13,
|
|
10303
10819
|
message: "Cursor command files are plain Markdown; command description and allowed-tools metadata are not projected."
|
|
10304
10820
|
}
|
|
10305
10821
|
];
|
|
10306
10822
|
}
|
|
10307
|
-
if (
|
|
10823
|
+
if (target13 === "gemini-cli" && command.allowedTools.length > 0) {
|
|
10308
10824
|
return [
|
|
10309
10825
|
{
|
|
10310
10826
|
level: "warning",
|
|
10311
10827
|
file: command.source,
|
|
10312
|
-
target:
|
|
10828
|
+
target: target13,
|
|
10313
10829
|
message: "Gemini TOML command files do not project canonical allowed-tools metadata."
|
|
10314
10830
|
}
|
|
10315
10831
|
];
|
|
10316
10832
|
}
|
|
10317
|
-
if (
|
|
10833
|
+
if (target13 === "continue" && command.allowedTools.length > 0) {
|
|
10318
10834
|
return [
|
|
10319
10835
|
{
|
|
10320
10836
|
level: "warning",
|
|
10321
10837
|
file: command.source,
|
|
10322
|
-
target:
|
|
10838
|
+
target: target13,
|
|
10323
10839
|
message: "Continue invokable prompt rules do not natively enforce canonical allowed-tools metadata."
|
|
10324
10840
|
}
|
|
10325
10841
|
];
|
|
10326
10842
|
}
|
|
10327
|
-
if (["cline", "windsurf"].includes(
|
|
10843
|
+
if (["cline", "windsurf"].includes(target13) && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
10328
10844
|
return [
|
|
10329
10845
|
{
|
|
10330
10846
|
level: "warning",
|
|
10331
10847
|
file: command.source,
|
|
10332
|
-
target:
|
|
10333
|
-
message: `${
|
|
10848
|
+
target: target13,
|
|
10849
|
+
message: `${target13} workflow files are plain Markdown; command description and allowed-tools metadata are not projected.`
|
|
10334
10850
|
}
|
|
10335
10851
|
];
|
|
10336
10852
|
}
|
|
@@ -10339,48 +10855,48 @@ function lintCommands(canonical, target12) {
|
|
|
10339
10855
|
}
|
|
10340
10856
|
|
|
10341
10857
|
// src/core/lint/mcp.ts
|
|
10342
|
-
function lintMcp(canonical,
|
|
10858
|
+
function lintMcp(canonical, target13) {
|
|
10343
10859
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
10344
10860
|
const diagnostics = [];
|
|
10345
10861
|
for (const [name, server] of Object.entries(canonical.mcp.mcpServers)) {
|
|
10346
|
-
if (
|
|
10862
|
+
if (target13 === "cursor" && usesCursorSensitiveInterpolation(server)) {
|
|
10347
10863
|
diagnostics.push({
|
|
10348
10864
|
level: "warning",
|
|
10349
10865
|
file: ".agentsmesh/mcp.json",
|
|
10350
|
-
target:
|
|
10866
|
+
target: target13,
|
|
10351
10867
|
message: `MCP server "${name}" uses env vars or URL/header interpolation; Cursor handling may differ from canonical MCP.`
|
|
10352
10868
|
});
|
|
10353
10869
|
}
|
|
10354
|
-
if (
|
|
10870
|
+
if (target13 === "codex-cli" && typeof server.description === "string" && server.description) {
|
|
10355
10871
|
diagnostics.push({
|
|
10356
10872
|
level: "warning",
|
|
10357
10873
|
file: ".agentsmesh/mcp.json",
|
|
10358
|
-
target:
|
|
10874
|
+
target: target13,
|
|
10359
10875
|
message: `MCP server "${name}" has a description, but codex-cli does not project MCP descriptions into .codex/config.toml.`
|
|
10360
10876
|
});
|
|
10361
10877
|
}
|
|
10362
|
-
if (
|
|
10878
|
+
if (target13 === "codex-cli" && isUrlMcpServer(server)) {
|
|
10363
10879
|
diagnostics.push({
|
|
10364
10880
|
level: "warning",
|
|
10365
10881
|
file: ".agentsmesh/mcp.json",
|
|
10366
|
-
target:
|
|
10882
|
+
target: target13,
|
|
10367
10883
|
message: `MCP server "${name}" uses ${server.type} transport; codex-cli only generates stdio MCP servers.`
|
|
10368
10884
|
});
|
|
10369
10885
|
}
|
|
10370
|
-
if (
|
|
10886
|
+
if (target13 === "junie" && isUrlMcpServer(server)) {
|
|
10371
10887
|
diagnostics.push({
|
|
10372
10888
|
level: "warning",
|
|
10373
10889
|
file: ".agentsmesh/mcp.json",
|
|
10374
|
-
target:
|
|
10890
|
+
target: target13,
|
|
10375
10891
|
message: `MCP server "${name}" uses ${server.type} transport; Junie project mcp.json currently documents stdio MCP servers only.`
|
|
10376
10892
|
});
|
|
10377
10893
|
}
|
|
10378
10894
|
}
|
|
10379
|
-
if (
|
|
10895
|
+
if (target13 === "windsurf") {
|
|
10380
10896
|
diagnostics.push({
|
|
10381
10897
|
level: "warning",
|
|
10382
10898
|
file: ".agentsmesh/mcp.json",
|
|
10383
|
-
target:
|
|
10899
|
+
target: target13,
|
|
10384
10900
|
message: "Windsurf MCP is partial; generated .windsurf/mcp_config.example.json is a reference artifact and may require manual setup."
|
|
10385
10901
|
});
|
|
10386
10902
|
}
|
|
@@ -10388,42 +10904,51 @@ function lintMcp(canonical, target12) {
|
|
|
10388
10904
|
}
|
|
10389
10905
|
|
|
10390
10906
|
// src/core/lint/permissions.ts
|
|
10391
|
-
function lintPermissions(canonical,
|
|
10907
|
+
function lintPermissions(canonical, target13) {
|
|
10392
10908
|
if (!canonical.permissions) return [];
|
|
10393
|
-
if (
|
|
10909
|
+
if (target13 !== "cursor") return [];
|
|
10394
10910
|
const hasEntries = canonical.permissions.allow.length > 0 || canonical.permissions.deny.length > 0;
|
|
10395
10911
|
if (!hasEntries) return [];
|
|
10396
10912
|
return [
|
|
10397
10913
|
{
|
|
10398
10914
|
level: "warning",
|
|
10399
10915
|
file: ".agentsmesh/permissions.yaml",
|
|
10400
|
-
target:
|
|
10916
|
+
target: target13,
|
|
10401
10917
|
message: "Cursor permissions are partial; tool-level allow/deny may lose fidelity."
|
|
10402
10918
|
}
|
|
10403
10919
|
];
|
|
10404
10920
|
}
|
|
10405
10921
|
|
|
10406
10922
|
// src/core/lint/hooks.ts
|
|
10407
|
-
function lintHooks(canonical,
|
|
10923
|
+
function lintHooks(canonical, target13) {
|
|
10408
10924
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
10409
|
-
if (
|
|
10925
|
+
if (target13 === "gemini-cli") {
|
|
10410
10926
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification"]);
|
|
10411
10927
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10412
10928
|
level: "warning",
|
|
10413
10929
|
file: ".agentsmesh/hooks.yaml",
|
|
10414
|
-
target:
|
|
10930
|
+
target: target13,
|
|
10415
10931
|
message: `${event} is not supported by gemini-cli; only PreToolUse, PostToolUse, and Notification are projected.`
|
|
10416
10932
|
}));
|
|
10417
10933
|
}
|
|
10418
|
-
if (
|
|
10934
|
+
if (target13 === "copilot") {
|
|
10419
10935
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit"]);
|
|
10420
10936
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10421
10937
|
level: "warning",
|
|
10422
10938
|
file: ".agentsmesh/hooks.yaml",
|
|
10423
|
-
target:
|
|
10939
|
+
target: target13,
|
|
10424
10940
|
message: `${event} is not supported by Copilot hooks; only PreToolUse, PostToolUse, Notification, and UserPromptSubmit are projected.`
|
|
10425
10941
|
}));
|
|
10426
10942
|
}
|
|
10943
|
+
if (target13 === "kiro") {
|
|
10944
|
+
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "UserPromptSubmit", "SubagentStop"]);
|
|
10945
|
+
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10946
|
+
level: "warning",
|
|
10947
|
+
file: ".agentsmesh/hooks.yaml",
|
|
10948
|
+
target: target13,
|
|
10949
|
+
message: `${event} is not supported by Kiro hooks; only PreToolUse, PostToolUse, UserPromptSubmit, and SubagentStop are projected.`
|
|
10950
|
+
}));
|
|
10951
|
+
}
|
|
10427
10952
|
return [];
|
|
10428
10953
|
}
|
|
10429
10954
|
|
|
@@ -10446,22 +10971,22 @@ async function runLint(config, canonical, projectRoot, targetFilter) {
|
|
|
10446
10971
|
const hasHooks = config.features.includes("hooks");
|
|
10447
10972
|
const diagnostics = [];
|
|
10448
10973
|
const projectFiles = await getProjectFiles(projectRoot);
|
|
10449
|
-
for (const
|
|
10450
|
-
const linter = isBuiltinTargetId(
|
|
10974
|
+
for (const target13 of targets) {
|
|
10975
|
+
const linter = isBuiltinTargetId(target13) ? getTargetCatalogEntry(target13).lintRules : null;
|
|
10451
10976
|
if (hasRules && linter) {
|
|
10452
10977
|
diagnostics.push(...linter(canonical, projectRoot, projectFiles));
|
|
10453
10978
|
}
|
|
10454
10979
|
if (hasCommands) {
|
|
10455
|
-
diagnostics.push(...lintCommands(canonical,
|
|
10980
|
+
diagnostics.push(...lintCommands(canonical, target13));
|
|
10456
10981
|
}
|
|
10457
10982
|
if (hasMcp) {
|
|
10458
|
-
diagnostics.push(...lintMcp(canonical,
|
|
10983
|
+
diagnostics.push(...lintMcp(canonical, target13));
|
|
10459
10984
|
}
|
|
10460
10985
|
if (hasPermissions) {
|
|
10461
|
-
diagnostics.push(...lintPermissions(canonical,
|
|
10986
|
+
diagnostics.push(...lintPermissions(canonical, target13));
|
|
10462
10987
|
}
|
|
10463
10988
|
if (hasHooks) {
|
|
10464
|
-
diagnostics.push(...lintHooks(canonical,
|
|
10989
|
+
diagnostics.push(...lintHooks(canonical, target13));
|
|
10465
10990
|
}
|
|
10466
10991
|
}
|
|
10467
10992
|
const hasErrors = diagnostics.some((d) => d.level === "error");
|
|
@@ -10501,7 +11026,7 @@ async function runLintCmd(flags, projectRoot) {
|
|
|
10501
11026
|
}
|
|
10502
11027
|
|
|
10503
11028
|
// src/cli/commands/watch.ts
|
|
10504
|
-
import { join as
|
|
11029
|
+
import { join as join60, relative as relative23 } from "path";
|
|
10505
11030
|
import chokidar from "chokidar";
|
|
10506
11031
|
var DEBOUNCE_MS = 300;
|
|
10507
11032
|
function normalizeWatchPath(path) {
|
|
@@ -10528,9 +11053,9 @@ async function runWatch(flags, projectRoot) {
|
|
|
10528
11053
|
const root = projectRoot ?? process.cwd();
|
|
10529
11054
|
const { configDir } = await loadConfigFromDir(root);
|
|
10530
11055
|
const paths = [
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
11056
|
+
join60(configDir, ".agentsmesh"),
|
|
11057
|
+
join60(configDir, "agentsmesh.yaml"),
|
|
11058
|
+
join60(configDir, "agentsmesh.local.yaml")
|
|
10534
11059
|
];
|
|
10535
11060
|
let debounceTimer = null;
|
|
10536
11061
|
let lastFingerprint = null;
|
|
@@ -10616,12 +11141,12 @@ async function runWatch(flags, projectRoot) {
|
|
|
10616
11141
|
}
|
|
10617
11142
|
|
|
10618
11143
|
// src/cli/commands/check.ts
|
|
10619
|
-
import { join as
|
|
11144
|
+
import { join as join61 } from "path";
|
|
10620
11145
|
async function runCheck(flags, projectRoot) {
|
|
10621
11146
|
void flags;
|
|
10622
11147
|
const root = projectRoot ?? process.cwd();
|
|
10623
11148
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10624
|
-
const abDir =
|
|
11149
|
+
const abDir = join61(configDir, ".agentsmesh");
|
|
10625
11150
|
const lock = await readLock(abDir);
|
|
10626
11151
|
if (lock === null) {
|
|
10627
11152
|
logger.error("Not initialized for collaboration. Run 'agentsmesh generate' first.");
|
|
@@ -10691,14 +11216,14 @@ async function runCheck(flags, projectRoot) {
|
|
|
10691
11216
|
}
|
|
10692
11217
|
|
|
10693
11218
|
// src/cli/commands/merge.ts
|
|
10694
|
-
import { join as
|
|
11219
|
+
import { join as join63 } from "path";
|
|
10695
11220
|
|
|
10696
11221
|
// src/core/merger.ts
|
|
10697
|
-
import { dirname as dirname22, join as
|
|
11222
|
+
import { dirname as dirname22, join as join62 } from "path";
|
|
10698
11223
|
var LOCK_FILENAME2 = ".lock";
|
|
10699
11224
|
var CONFLICT_MARKER = "<<<<<<<";
|
|
10700
11225
|
async function hasLockConflict(abDir) {
|
|
10701
|
-
const lockPath =
|
|
11226
|
+
const lockPath = join62(abDir, LOCK_FILENAME2);
|
|
10702
11227
|
const content = await readFileSafe(lockPath);
|
|
10703
11228
|
if (content === null) return false;
|
|
10704
11229
|
return content.includes(CONFLICT_MARKER);
|
|
@@ -10712,7 +11237,7 @@ async function resolveLockConflict(abDir, libVersion, config) {
|
|
|
10712
11237
|
const configDir = dirname22(abDir);
|
|
10713
11238
|
const resolvedExtends = config ? await resolveExtendPaths(config, configDir) : [];
|
|
10714
11239
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
10715
|
-
const packChecksums = await buildPackChecksums(
|
|
11240
|
+
const packChecksums = await buildPackChecksums(join62(abDir, "packs"));
|
|
10716
11241
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
10717
11242
|
await writeLock(abDir, {
|
|
10718
11243
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -10729,7 +11254,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10729
11254
|
void flags;
|
|
10730
11255
|
const root = projectRoot ?? process.cwd();
|
|
10731
11256
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10732
|
-
const abDir =
|
|
11257
|
+
const abDir = join63(configDir, ".agentsmesh");
|
|
10733
11258
|
const hasConflict = await hasLockConflict(abDir);
|
|
10734
11259
|
if (!hasConflict) {
|
|
10735
11260
|
logger.info("No conflicts to resolve.");
|
|
@@ -10740,7 +11265,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10740
11265
|
}
|
|
10741
11266
|
|
|
10742
11267
|
// src/install/run/run-install.ts
|
|
10743
|
-
import { join as
|
|
11268
|
+
import { join as join77 } from "path";
|
|
10744
11269
|
|
|
10745
11270
|
// src/install/source/git-pin.ts
|
|
10746
11271
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -10874,7 +11399,7 @@ async function confirm(message) {
|
|
|
10874
11399
|
}
|
|
10875
11400
|
|
|
10876
11401
|
// src/install/core/validate-resources.ts
|
|
10877
|
-
import { basename as
|
|
11402
|
+
import { basename as basename33 } from "path";
|
|
10878
11403
|
function validateSkill(skill) {
|
|
10879
11404
|
if (!skill.description.trim()) {
|
|
10880
11405
|
return { skill, ok: false, reason: "missing description in frontmatter" };
|
|
@@ -10900,7 +11425,7 @@ function validateAgent(agent) {
|
|
|
10900
11425
|
return { agent, ok: true };
|
|
10901
11426
|
}
|
|
10902
11427
|
function ruleSlug6(rule) {
|
|
10903
|
-
return
|
|
11428
|
+
return basename33(rule.source).replace(/\.md$/i, "");
|
|
10904
11429
|
}
|
|
10905
11430
|
|
|
10906
11431
|
// src/install/core/pool-resolution.ts
|
|
@@ -11394,7 +11919,7 @@ function ensureInstallSelection(args) {
|
|
|
11394
11919
|
}
|
|
11395
11920
|
|
|
11396
11921
|
// src/install/core/install-extend-entry.ts
|
|
11397
|
-
import { join as
|
|
11922
|
+
import { join as join64 } from "path";
|
|
11398
11923
|
|
|
11399
11924
|
// src/install/core/merge-extend-entry.ts
|
|
11400
11925
|
function assertExtendNameAvailable(extendsList, entry) {
|
|
@@ -11483,7 +12008,7 @@ async function writeInstallAsExtend(args) {
|
|
|
11483
12008
|
${JSON.stringify(entry, null, 2)}`);
|
|
11484
12009
|
return;
|
|
11485
12010
|
}
|
|
11486
|
-
const configPath =
|
|
12011
|
+
const configPath = join64(configDir, "agentsmesh.yaml");
|
|
11487
12012
|
await writeAgentsmeshWithNewExtend(configPath, config, entry);
|
|
11488
12013
|
logger.success(`Wrote extends entry "${entry.name}" to agentsmesh.yaml.`);
|
|
11489
12014
|
}
|
|
@@ -11500,13 +12025,13 @@ function toNewExtendEntry(args) {
|
|
|
11500
12025
|
}
|
|
11501
12026
|
|
|
11502
12027
|
// src/install/run/run-install-pack.ts
|
|
11503
|
-
import { join as
|
|
12028
|
+
import { join as join68 } from "path";
|
|
11504
12029
|
import { rename as rename4 } from "fs/promises";
|
|
11505
12030
|
|
|
11506
12031
|
// src/install/pack/pack-writer.ts
|
|
11507
|
-
import { join as
|
|
12032
|
+
import { join as join65, basename as basename34, dirname as dirname23 } from "path";
|
|
11508
12033
|
import { rm as rm7, rename as rename3, mkdir as mkdir5, copyFile as copyFile2 } from "fs/promises";
|
|
11509
|
-
import { stringify as
|
|
12034
|
+
import { stringify as yamlStringify7 } from "yaml";
|
|
11510
12035
|
|
|
11511
12036
|
// src/install/pack/pack-hash.ts
|
|
11512
12037
|
import { relative as relative25 } from "path";
|
|
@@ -11530,41 +12055,41 @@ async function hashPackContent(packDir) {
|
|
|
11530
12055
|
// src/install/pack/pack-writer.ts
|
|
11531
12056
|
async function writeRules(canonical, packDir) {
|
|
11532
12057
|
if (canonical.rules.length === 0) return;
|
|
11533
|
-
const rulesDir =
|
|
12058
|
+
const rulesDir = join65(packDir, "rules");
|
|
11534
12059
|
await mkdirp(rulesDir);
|
|
11535
12060
|
for (const rule of canonical.rules) {
|
|
11536
|
-
const dest =
|
|
12061
|
+
const dest = join65(rulesDir, basename34(rule.source));
|
|
11537
12062
|
await copyFile2(rule.source, dest);
|
|
11538
12063
|
}
|
|
11539
12064
|
}
|
|
11540
12065
|
async function writeCommands(canonical, packDir) {
|
|
11541
12066
|
if (canonical.commands.length === 0) return;
|
|
11542
|
-
const dir =
|
|
12067
|
+
const dir = join65(packDir, "commands");
|
|
11543
12068
|
await mkdirp(dir);
|
|
11544
12069
|
for (const cmd of canonical.commands) {
|
|
11545
|
-
const dest =
|
|
12070
|
+
const dest = join65(dir, basename34(cmd.source));
|
|
11546
12071
|
await copyFile2(cmd.source, dest);
|
|
11547
12072
|
}
|
|
11548
12073
|
}
|
|
11549
12074
|
async function writeAgents(canonical, packDir) {
|
|
11550
12075
|
if (canonical.agents.length === 0) return;
|
|
11551
|
-
const dir =
|
|
12076
|
+
const dir = join65(packDir, "agents");
|
|
11552
12077
|
await mkdirp(dir);
|
|
11553
12078
|
for (const agent of canonical.agents) {
|
|
11554
|
-
const dest =
|
|
12079
|
+
const dest = join65(dir, basename34(agent.source));
|
|
11555
12080
|
await copyFile2(agent.source, dest);
|
|
11556
12081
|
}
|
|
11557
12082
|
}
|
|
11558
12083
|
async function writeSkills(canonical, packDir) {
|
|
11559
12084
|
if (canonical.skills.length === 0) return;
|
|
11560
|
-
const skillsDir =
|
|
12085
|
+
const skillsDir = join65(packDir, "skills");
|
|
11561
12086
|
await mkdirp(skillsDir);
|
|
11562
12087
|
for (const skill of canonical.skills) {
|
|
11563
|
-
const skillDestDir =
|
|
12088
|
+
const skillDestDir = join65(skillsDir, skill.name);
|
|
11564
12089
|
await mkdirp(skillDestDir);
|
|
11565
|
-
await copyFile2(skill.source,
|
|
12090
|
+
await copyFile2(skill.source, join65(skillDestDir, "SKILL.md"));
|
|
11566
12091
|
for (const sf of skill.supportingFiles) {
|
|
11567
|
-
const destPath =
|
|
12092
|
+
const destPath = join65(skillDestDir, sf.relativePath);
|
|
11568
12093
|
await mkdirp(dirname23(destPath));
|
|
11569
12094
|
await copyFile2(sf.absolutePath, destPath);
|
|
11570
12095
|
}
|
|
@@ -11572,23 +12097,23 @@ async function writeSkills(canonical, packDir) {
|
|
|
11572
12097
|
}
|
|
11573
12098
|
async function writeSettings(canonical, packDir) {
|
|
11574
12099
|
if (canonical.mcp !== null) {
|
|
11575
|
-
await writeFileAtomic(
|
|
12100
|
+
await writeFileAtomic(join65(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11576
12101
|
`);
|
|
11577
12102
|
}
|
|
11578
12103
|
if (canonical.permissions !== null) {
|
|
11579
|
-
await writeFileAtomic(
|
|
12104
|
+
await writeFileAtomic(join65(packDir, "permissions.yaml"), yamlStringify7(canonical.permissions));
|
|
11580
12105
|
}
|
|
11581
12106
|
if (canonical.hooks !== null) {
|
|
11582
|
-
await writeFileAtomic(
|
|
12107
|
+
await writeFileAtomic(join65(packDir, "hooks.yaml"), yamlStringify7(canonical.hooks));
|
|
11583
12108
|
}
|
|
11584
12109
|
if (canonical.ignore.length > 0) {
|
|
11585
|
-
await writeFileAtomic(
|
|
12110
|
+
await writeFileAtomic(join65(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11586
12111
|
`);
|
|
11587
12112
|
}
|
|
11588
12113
|
}
|
|
11589
12114
|
async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
11590
|
-
const tmpDir =
|
|
11591
|
-
const finalDir =
|
|
12115
|
+
const tmpDir = join65(packsDir, `${packName}.tmp`);
|
|
12116
|
+
const finalDir = join65(packsDir, packName);
|
|
11592
12117
|
if (await exists(tmpDir)) {
|
|
11593
12118
|
await rm7(tmpDir, { recursive: true, force: true });
|
|
11594
12119
|
}
|
|
@@ -11600,7 +12125,7 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11600
12125
|
await writeSettings(canonical, tmpDir);
|
|
11601
12126
|
const contentHash = await hashPackContent(tmpDir);
|
|
11602
12127
|
const metadata = { ...metadataInput, content_hash: contentHash };
|
|
11603
|
-
await writeFileAtomic(
|
|
12128
|
+
await writeFileAtomic(join65(tmpDir, "pack.yaml"), yamlStringify7(metadata));
|
|
11604
12129
|
if (await exists(finalDir)) {
|
|
11605
12130
|
await rm7(finalDir, { recursive: true, force: true });
|
|
11606
12131
|
}
|
|
@@ -11610,9 +12135,9 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11610
12135
|
}
|
|
11611
12136
|
|
|
11612
12137
|
// src/install/pack/pack-merge.ts
|
|
11613
|
-
import { join as
|
|
12138
|
+
import { join as join66, basename as basename35, dirname as dirname24 } from "path";
|
|
11614
12139
|
import { copyFile as copyFile3 } from "fs/promises";
|
|
11615
|
-
import { stringify as
|
|
12140
|
+
import { stringify as yamlStringify8 } from "yaml";
|
|
11616
12141
|
function union(a, b) {
|
|
11617
12142
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
11618
12143
|
}
|
|
@@ -11641,38 +12166,38 @@ function mergePick2(existing, newFeatures, newPick) {
|
|
|
11641
12166
|
}
|
|
11642
12167
|
async function mergeRules(canonical, packDir) {
|
|
11643
12168
|
if (canonical.rules.length === 0) return;
|
|
11644
|
-
const dir =
|
|
12169
|
+
const dir = join66(packDir, "rules");
|
|
11645
12170
|
await mkdirp(dir);
|
|
11646
12171
|
for (const rule of canonical.rules) {
|
|
11647
|
-
await copyFile3(rule.source,
|
|
12172
|
+
await copyFile3(rule.source, join66(dir, basename35(rule.source)));
|
|
11648
12173
|
}
|
|
11649
12174
|
}
|
|
11650
12175
|
async function mergeCommands(canonical, packDir) {
|
|
11651
12176
|
if (canonical.commands.length === 0) return;
|
|
11652
|
-
const dir =
|
|
12177
|
+
const dir = join66(packDir, "commands");
|
|
11653
12178
|
await mkdirp(dir);
|
|
11654
12179
|
for (const cmd of canonical.commands) {
|
|
11655
|
-
await copyFile3(cmd.source,
|
|
12180
|
+
await copyFile3(cmd.source, join66(dir, basename35(cmd.source)));
|
|
11656
12181
|
}
|
|
11657
12182
|
}
|
|
11658
12183
|
async function mergeAgents(canonical, packDir) {
|
|
11659
12184
|
if (canonical.agents.length === 0) return;
|
|
11660
|
-
const dir =
|
|
12185
|
+
const dir = join66(packDir, "agents");
|
|
11661
12186
|
await mkdirp(dir);
|
|
11662
12187
|
for (const agent of canonical.agents) {
|
|
11663
|
-
await copyFile3(agent.source,
|
|
12188
|
+
await copyFile3(agent.source, join66(dir, basename35(agent.source)));
|
|
11664
12189
|
}
|
|
11665
12190
|
}
|
|
11666
12191
|
async function mergeSkills(canonical, packDir) {
|
|
11667
12192
|
if (canonical.skills.length === 0) return;
|
|
11668
|
-
const skillsDir =
|
|
12193
|
+
const skillsDir = join66(packDir, "skills");
|
|
11669
12194
|
await mkdirp(skillsDir);
|
|
11670
12195
|
for (const skill of canonical.skills) {
|
|
11671
|
-
const destDir =
|
|
12196
|
+
const destDir = join66(skillsDir, skill.name);
|
|
11672
12197
|
await mkdirp(destDir);
|
|
11673
|
-
await copyFile3(skill.source,
|
|
12198
|
+
await copyFile3(skill.source, join66(destDir, "SKILL.md"));
|
|
11674
12199
|
for (const sf of skill.supportingFiles) {
|
|
11675
|
-
const destPath =
|
|
12200
|
+
const destPath = join66(destDir, sf.relativePath);
|
|
11676
12201
|
await mkdirp(dirname24(destPath));
|
|
11677
12202
|
await copyFile3(sf.absolutePath, destPath);
|
|
11678
12203
|
}
|
|
@@ -11680,17 +12205,17 @@ async function mergeSkills(canonical, packDir) {
|
|
|
11680
12205
|
}
|
|
11681
12206
|
async function mergeSettings(canonical, packDir) {
|
|
11682
12207
|
if (canonical.mcp !== null) {
|
|
11683
|
-
await writeFileAtomic(
|
|
12208
|
+
await writeFileAtomic(join66(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11684
12209
|
`);
|
|
11685
12210
|
}
|
|
11686
12211
|
if (canonical.permissions !== null) {
|
|
11687
|
-
await writeFileAtomic(
|
|
12212
|
+
await writeFileAtomic(join66(packDir, "permissions.yaml"), yamlStringify8(canonical.permissions));
|
|
11688
12213
|
}
|
|
11689
12214
|
if (canonical.hooks !== null) {
|
|
11690
|
-
await writeFileAtomic(
|
|
12215
|
+
await writeFileAtomic(join66(packDir, "hooks.yaml"), yamlStringify8(canonical.hooks));
|
|
11691
12216
|
}
|
|
11692
12217
|
if (canonical.ignore.length > 0) {
|
|
11693
|
-
await writeFileAtomic(
|
|
12218
|
+
await writeFileAtomic(join66(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11694
12219
|
`);
|
|
11695
12220
|
}
|
|
11696
12221
|
}
|
|
@@ -11717,13 +12242,13 @@ async function mergeIntoPack(packDir, existingMeta, newCanonical, newFeatures, n
|
|
|
11717
12242
|
updated_at: updatedAt,
|
|
11718
12243
|
content_hash: contentHash
|
|
11719
12244
|
};
|
|
11720
|
-
await writeFileAtomic(
|
|
12245
|
+
await writeFileAtomic(join66(packDir, "pack.yaml"), yamlStringify8(updatedMeta));
|
|
11721
12246
|
return updatedMeta;
|
|
11722
12247
|
}
|
|
11723
12248
|
|
|
11724
12249
|
// src/install/core/install-manifest.ts
|
|
11725
|
-
import { join as
|
|
11726
|
-
import { parse as parseYaml8, stringify as
|
|
12250
|
+
import { join as join67 } from "path";
|
|
12251
|
+
import { parse as parseYaml8, stringify as yamlStringify9 } from "yaml";
|
|
11727
12252
|
import { z as z4 } from "zod";
|
|
11728
12253
|
var installManifestEntrySchema = z4.object({
|
|
11729
12254
|
name: z4.string().min(1),
|
|
@@ -11748,7 +12273,7 @@ function sameInstallIdentity(a, b) {
|
|
|
11748
12273
|
return a.source === b.source && a.target === b.target && a.as === b.as && sameFeatures2(a.features, b.features);
|
|
11749
12274
|
}
|
|
11750
12275
|
function manifestPath(configDir) {
|
|
11751
|
-
return
|
|
12276
|
+
return join67(configDir, ".agentsmesh", "installs.yaml");
|
|
11752
12277
|
}
|
|
11753
12278
|
async function readInstallManifest(configDir) {
|
|
11754
12279
|
const content = await readFileSafe(manifestPath(configDir));
|
|
@@ -11767,7 +12292,7 @@ async function upsertInstallManifestEntry(configDir, entry) {
|
|
|
11767
12292
|
next.push(entry);
|
|
11768
12293
|
await writeFileAtomic(
|
|
11769
12294
|
manifestPath(configDir),
|
|
11770
|
-
|
|
12295
|
+
yamlStringify9({ version: 1, installs: next.sort((a, b) => a.name.localeCompare(b.name)) })
|
|
11771
12296
|
);
|
|
11772
12297
|
}
|
|
11773
12298
|
function buildInstallManifestEntry(args) {
|
|
@@ -11821,7 +12346,7 @@ async function installAsPack(args) {
|
|
|
11821
12346
|
manualAs,
|
|
11822
12347
|
renameExistingPack
|
|
11823
12348
|
} = args;
|
|
11824
|
-
const packsDir =
|
|
12349
|
+
const packsDir = join68(configDir, ".agentsmesh", "packs");
|
|
11825
12350
|
const selectedCanonical = applySelection(narrowed, selected);
|
|
11826
12351
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11827
12352
|
const parsedTarget = yamlTarget !== void 0 ? targetSchema.parse(yamlTarget) : void 0;
|
|
@@ -11839,7 +12364,7 @@ async function installAsPack(args) {
|
|
|
11839
12364
|
let packDir = existingPack.packDir;
|
|
11840
12365
|
let packMeta = existingPack.meta;
|
|
11841
12366
|
if (renameExistingPack && existingPack.name !== packName) {
|
|
11842
|
-
const nextDir =
|
|
12367
|
+
const nextDir = join68(packsDir, packName);
|
|
11843
12368
|
if (await exists(nextDir)) {
|
|
11844
12369
|
throw new Error(
|
|
11845
12370
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11870,7 +12395,7 @@ async function installAsPack(args) {
|
|
|
11870
12395
|
persistedPaths = mergedMeta.paths;
|
|
11871
12396
|
logger.success(`Updated pack "${mergedMeta.name}" in .agentsmesh/packs/.`);
|
|
11872
12397
|
} else {
|
|
11873
|
-
const collidingMeta = await readPackMetadata(
|
|
12398
|
+
const collidingMeta = await readPackMetadata(join68(packsDir, packName));
|
|
11874
12399
|
if (collidingMeta) {
|
|
11875
12400
|
throw new Error(
|
|
11876
12401
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11912,7 +12437,7 @@ async function installAsPack(args) {
|
|
|
11912
12437
|
}
|
|
11913
12438
|
|
|
11914
12439
|
// src/install/run/install-sync.ts
|
|
11915
|
-
import { join as
|
|
12440
|
+
import { join as join69 } from "path";
|
|
11916
12441
|
async function syncInstalledPacks(args) {
|
|
11917
12442
|
const installs = await readInstallManifest(args.configDir);
|
|
11918
12443
|
if (installs.length === 0) {
|
|
@@ -11921,7 +12446,7 @@ async function syncInstalledPacks(args) {
|
|
|
11921
12446
|
}
|
|
11922
12447
|
const missing = [];
|
|
11923
12448
|
for (const entry of installs) {
|
|
11924
|
-
const packDir =
|
|
12449
|
+
const packDir = join69(args.configDir, ".agentsmesh", "packs", entry.name);
|
|
11925
12450
|
if (!await exists(packDir)) {
|
|
11926
12451
|
missing.push(entry);
|
|
11927
12452
|
}
|
|
@@ -12099,7 +12624,7 @@ function narrowDiscoveredForInstallScope(canonical, options) {
|
|
|
12099
12624
|
}
|
|
12100
12625
|
|
|
12101
12626
|
// src/install/manual/manual-install-scope.ts
|
|
12102
|
-
import { basename as
|
|
12627
|
+
import { basename as basename36, dirname as dirname25, join as join70, relative as relative27 } from "path";
|
|
12103
12628
|
import { cp as cp2, mkdtemp, stat as stat5, rm as rm8 } from "fs/promises";
|
|
12104
12629
|
import { tmpdir } from "os";
|
|
12105
12630
|
|
|
@@ -12159,9 +12684,9 @@ async function cpFilteredSkill(sourceRoot, destDir) {
|
|
|
12159
12684
|
|
|
12160
12685
|
// src/install/manual/manual-install-scope.ts
|
|
12161
12686
|
async function createStageRoot() {
|
|
12162
|
-
const stageBase = await mkdtemp(
|
|
12163
|
-
const discoveryRoot =
|
|
12164
|
-
await mkdirp(
|
|
12687
|
+
const stageBase = await mkdtemp(join70(tmpdir(), "am-install-manual-"));
|
|
12688
|
+
const discoveryRoot = join70(stageBase, "repo");
|
|
12689
|
+
await mkdirp(join70(discoveryRoot, ".agentsmesh"));
|
|
12165
12690
|
return {
|
|
12166
12691
|
discoveryRoot,
|
|
12167
12692
|
cleanup: async () => {
|
|
@@ -12176,7 +12701,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12176
12701
|
throw new Error(`Manual install only supports .md files for this collection: ${sourceRoot}`);
|
|
12177
12702
|
}
|
|
12178
12703
|
await mkdirp(destinationDir);
|
|
12179
|
-
await cp2(sourceRoot,
|
|
12704
|
+
await cp2(sourceRoot, join70(destinationDir, basename36(sourceRoot)));
|
|
12180
12705
|
return;
|
|
12181
12706
|
}
|
|
12182
12707
|
const files = (await readDirRecursive(sourceRoot)).filter(
|
|
@@ -12188,7 +12713,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12188
12713
|
const usedNames = /* @__PURE__ */ new Map();
|
|
12189
12714
|
await mkdirp(destinationDir);
|
|
12190
12715
|
for (const file of files) {
|
|
12191
|
-
const name =
|
|
12716
|
+
const name = basename36(file);
|
|
12192
12717
|
const previous = usedNames.get(name);
|
|
12193
12718
|
if (previous) {
|
|
12194
12719
|
throw new Error(
|
|
@@ -12196,7 +12721,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12196
12721
|
);
|
|
12197
12722
|
}
|
|
12198
12723
|
usedNames.set(name, file);
|
|
12199
|
-
await cp2(file,
|
|
12724
|
+
await cp2(file, join70(destinationDir, name));
|
|
12200
12725
|
}
|
|
12201
12726
|
}
|
|
12202
12727
|
async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNames) {
|
|
@@ -12208,7 +12733,7 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
12208
12733
|
for (const file of await readDirRecursive(sourceRoot)) {
|
|
12209
12734
|
if (!file.endsWith("/SKILL.md") && !file.endsWith("\\SKILL.md")) continue;
|
|
12210
12735
|
const skillDir = dirname25(file);
|
|
12211
|
-
const skillName =
|
|
12736
|
+
const skillName = basename36(skillDir);
|
|
12212
12737
|
if (!wanted.has(skillName)) continue;
|
|
12213
12738
|
const previous = matches.get(skillName);
|
|
12214
12739
|
if (previous && previous !== skillDir) {
|
|
@@ -12221,30 +12746,30 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
12221
12746
|
if (matches.size !== preferredSkillNames.length) return false;
|
|
12222
12747
|
await mkdirp(destinationDir);
|
|
12223
12748
|
for (const skillName of preferredSkillNames) {
|
|
12224
|
-
await cp2(matches.get(skillName),
|
|
12749
|
+
await cp2(matches.get(skillName), join70(destinationDir, skillName), { recursive: true });
|
|
12225
12750
|
}
|
|
12226
12751
|
return true;
|
|
12227
12752
|
}
|
|
12228
12753
|
async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
12229
12754
|
const info = await stat5(sourceRoot);
|
|
12230
12755
|
if (info.isFile()) {
|
|
12231
|
-
if (
|
|
12756
|
+
if (basename36(sourceRoot) !== "SKILL.md") {
|
|
12232
12757
|
throw new Error(`Manual skill install expects SKILL.md or a skill directory: ${sourceRoot}`);
|
|
12233
12758
|
}
|
|
12234
|
-
const skillName =
|
|
12235
|
-
const skillDir =
|
|
12759
|
+
const skillName = basename36(dirname25(sourceRoot));
|
|
12760
|
+
const skillDir = join70(destinationDir, skillName);
|
|
12236
12761
|
await mkdirp(skillDir);
|
|
12237
12762
|
await cp2(dirname25(sourceRoot), skillDir, { recursive: true });
|
|
12238
12763
|
return;
|
|
12239
12764
|
}
|
|
12240
12765
|
if (await isSkillPackLayout(sourceRoot)) {
|
|
12241
|
-
if ((await stat5(
|
|
12766
|
+
if ((await stat5(join70(sourceRoot, "SKILL.md")).catch(() => null))?.isFile()) {
|
|
12242
12767
|
if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
|
|
12243
12768
|
return;
|
|
12244
12769
|
}
|
|
12245
|
-
const fmName = await readSkillFrontmatterName(
|
|
12246
|
-
const skillName = fmName ||
|
|
12247
|
-
const skillDir =
|
|
12770
|
+
const fmName = await readSkillFrontmatterName(join70(sourceRoot, "SKILL.md"));
|
|
12771
|
+
const skillName = fmName || basename36(sourceRoot);
|
|
12772
|
+
const skillDir = join70(destinationDir, skillName);
|
|
12248
12773
|
await mkdirp(destinationDir);
|
|
12249
12774
|
await cpFilteredSkill(sourceRoot, skillDir);
|
|
12250
12775
|
return;
|
|
@@ -12261,7 +12786,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
12261
12786
|
roots.add(relative27(sourceRoot, dirname25(file)).split(/[\\/]/)[0]);
|
|
12262
12787
|
}
|
|
12263
12788
|
for (const root of roots) {
|
|
12264
|
-
await cp2(
|
|
12789
|
+
await cp2(join70(sourceRoot, root), join70(destinationDir, root), { recursive: true });
|
|
12265
12790
|
}
|
|
12266
12791
|
return;
|
|
12267
12792
|
}
|
|
@@ -12272,7 +12797,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
12272
12797
|
async function stageManualInstallScope(sourceRoot, as, options = {}) {
|
|
12273
12798
|
const staged = await createStageRoot();
|
|
12274
12799
|
try {
|
|
12275
|
-
const destDir =
|
|
12800
|
+
const destDir = join70(staged.discoveryRoot, ".agentsmesh", as);
|
|
12276
12801
|
if (as === "skills") {
|
|
12277
12802
|
await stageSkills(sourceRoot, destDir, options);
|
|
12278
12803
|
} else {
|
|
@@ -12306,7 +12831,7 @@ async function resolveManualDiscoveredForInstall(sourceRoot, explicitAs, explici
|
|
|
12306
12831
|
}
|
|
12307
12832
|
|
|
12308
12833
|
// src/install/core/prepare-install-discovery.ts
|
|
12309
|
-
import { join as
|
|
12834
|
+
import { join as join75 } from "path";
|
|
12310
12835
|
|
|
12311
12836
|
// src/install/native/native-path-pick.ts
|
|
12312
12837
|
var PATH_PREFIX_TO_TARGET = [
|
|
@@ -12333,6 +12858,8 @@ var PATH_PREFIX_TO_TARGET = [
|
|
|
12333
12858
|
{ prefix: ".junie/rules", target: "junie" },
|
|
12334
12859
|
{ prefix: ".junie/agents", target: "junie" },
|
|
12335
12860
|
{ prefix: ".junie/skills", target: "junie" },
|
|
12861
|
+
{ prefix: ".kiro/steering", target: "kiro" },
|
|
12862
|
+
{ prefix: ".kiro/skills", target: "kiro" },
|
|
12336
12863
|
{ prefix: ".cline/skills", target: "cline" },
|
|
12337
12864
|
{ prefix: ".clinerules/workflows", target: "cline" },
|
|
12338
12865
|
{ prefix: ".windsurf/rules", target: "windsurf" },
|
|
@@ -12344,14 +12871,14 @@ function norm(p) {
|
|
|
12344
12871
|
function targetHintFromNativePath(pathInRepoPosix) {
|
|
12345
12872
|
const p = norm(pathInRepoPosix);
|
|
12346
12873
|
const sorted = [...PATH_PREFIX_TO_TARGET].sort((a, b) => b.prefix.length - a.prefix.length);
|
|
12347
|
-
for (const { prefix, target:
|
|
12348
|
-
if (p === prefix || p.startsWith(`${prefix}/`)) return
|
|
12874
|
+
for (const { prefix, target: target13 } of sorted) {
|
|
12875
|
+
if (p === prefix || p.startsWith(`${prefix}/`)) return target13;
|
|
12349
12876
|
}
|
|
12350
12877
|
return void 0;
|
|
12351
12878
|
}
|
|
12352
|
-
function pathSupportsNativePick(pathInRepoPosix,
|
|
12879
|
+
function pathSupportsNativePick(pathInRepoPosix, target13) {
|
|
12353
12880
|
const hint = targetHintFromNativePath(pathInRepoPosix);
|
|
12354
|
-
return hint ===
|
|
12881
|
+
return hint === target13;
|
|
12355
12882
|
}
|
|
12356
12883
|
function validateTargetMatchesPath(explicitTarget, pathInRepoPosix) {
|
|
12357
12884
|
if (!explicitTarget || !pathInRepoPosix) return;
|
|
@@ -12367,13 +12894,13 @@ function extendPickHasArrays(p) {
|
|
|
12367
12894
|
}
|
|
12368
12895
|
|
|
12369
12896
|
// src/install/native/native-path-pick-infer.ts
|
|
12370
|
-
import { basename as
|
|
12897
|
+
import { basename as basename39, join as join73 } from "path";
|
|
12371
12898
|
|
|
12372
12899
|
// src/install/native/gemini-install-commands.ts
|
|
12373
|
-
import { join as
|
|
12900
|
+
import { join as join71, relative as relative28 } from "path";
|
|
12374
12901
|
async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
12375
|
-
const commandsRoot =
|
|
12376
|
-
const scanDir =
|
|
12902
|
+
const commandsRoot = join71(repoRoot, ...GEMINI_COMMANDS_DIR.split("/"));
|
|
12903
|
+
const scanDir = join71(repoRoot, ...pathInRepoPosix.split("/"));
|
|
12377
12904
|
const files = await readDirRecursive(scanDir);
|
|
12378
12905
|
const names = [];
|
|
12379
12906
|
for (const f of files) {
|
|
@@ -12388,32 +12915,32 @@ async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
|
12388
12915
|
}
|
|
12389
12916
|
|
|
12390
12917
|
// src/install/native/native-skill-scan.ts
|
|
12391
|
-
import { basename as
|
|
12918
|
+
import { basename as basename37, dirname as dirname26, relative as relative29 } from "path";
|
|
12392
12919
|
async function skillNamesFromNativeSkillDir(scanRoot) {
|
|
12393
12920
|
const files = await readDirRecursive(scanRoot);
|
|
12394
12921
|
const names = /* @__PURE__ */ new Set();
|
|
12395
12922
|
for (const f of files) {
|
|
12396
|
-
if (
|
|
12397
|
-
names.add(
|
|
12923
|
+
if (basename37(f) === "SKILL.md") {
|
|
12924
|
+
names.add(basename37(dirname26(f)));
|
|
12398
12925
|
continue;
|
|
12399
12926
|
}
|
|
12400
12927
|
const rel2 = relative29(scanRoot, f).replace(/\\/g, "/");
|
|
12401
12928
|
if (!rel2.includes("/") && f.toLowerCase().endsWith(".md")) {
|
|
12402
|
-
names.add(
|
|
12929
|
+
names.add(basename37(f, ".md"));
|
|
12403
12930
|
}
|
|
12404
12931
|
}
|
|
12405
12932
|
return [...names].filter(Boolean).sort();
|
|
12406
12933
|
}
|
|
12407
12934
|
|
|
12408
12935
|
// src/install/native/native-path-pick-infer-copilot.ts
|
|
12409
|
-
import { basename as
|
|
12936
|
+
import { basename as basename38, join as join72 } from "path";
|
|
12410
12937
|
async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
12411
|
-
const scan =
|
|
12938
|
+
const scan = join72(repoRoot, ...posixPath.split("/"));
|
|
12412
12939
|
if (posixPath.startsWith(COPILOT_PROMPTS_DIR)) {
|
|
12413
12940
|
const files = await readDirRecursive(scan);
|
|
12414
12941
|
const commands = [
|
|
12415
12942
|
...new Set(
|
|
12416
|
-
files.filter((f) => f.toLowerCase().endsWith(".prompt.md")).map((f) =>
|
|
12943
|
+
files.filter((f) => f.toLowerCase().endsWith(".prompt.md")).map((f) => basename38(f, ".prompt.md"))
|
|
12417
12944
|
)
|
|
12418
12945
|
].sort();
|
|
12419
12946
|
return commands.length ? { commands } : {};
|
|
@@ -12422,7 +12949,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12422
12949
|
const files = await readDirRecursive(scan);
|
|
12423
12950
|
const rules = [
|
|
12424
12951
|
...new Set(
|
|
12425
|
-
files.filter((f) => f.includes(".instructions.md")).map((f) =>
|
|
12952
|
+
files.filter((f) => f.includes(".instructions.md")).map((f) => basename38(f).replace(/\.instructions\.md$/i, ""))
|
|
12426
12953
|
)
|
|
12427
12954
|
].sort();
|
|
12428
12955
|
return rules.length ? { rules } : {};
|
|
@@ -12431,10 +12958,10 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12431
12958
|
const files = await readDirRecursive(scan);
|
|
12432
12959
|
const names = /* @__PURE__ */ new Set();
|
|
12433
12960
|
for (const f of files) {
|
|
12434
|
-
const b =
|
|
12961
|
+
const b = basename38(f);
|
|
12435
12962
|
if (b.toLowerCase().endsWith(".instructions.md"))
|
|
12436
12963
|
names.add(b.replace(/\.instructions\.md$/i, ""));
|
|
12437
|
-
else if (b.toLowerCase().endsWith(".md")) names.add(
|
|
12964
|
+
else if (b.toLowerCase().endsWith(".md")) names.add(basename38(f, ".md"));
|
|
12438
12965
|
}
|
|
12439
12966
|
const rules = [...names].sort();
|
|
12440
12967
|
return rules.length ? { rules } : {};
|
|
@@ -12447,7 +12974,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12447
12974
|
const files = await readDirRecursive(scan);
|
|
12448
12975
|
const agents = [
|
|
12449
12976
|
...new Set(
|
|
12450
|
-
files.filter((f) => f.toLowerCase().endsWith(".agent.md")).map((f) =>
|
|
12977
|
+
files.filter((f) => f.toLowerCase().endsWith(".agent.md")).map((f) => basename38(f, ".agent.md"))
|
|
12451
12978
|
)
|
|
12452
12979
|
].sort();
|
|
12453
12980
|
return agents.length ? { agents } : {};
|
|
@@ -12460,20 +12987,20 @@ async function mdNames(dir, ext) {
|
|
|
12460
12987
|
const files = await readDirRecursive(dir);
|
|
12461
12988
|
const e = ext.toLowerCase();
|
|
12462
12989
|
return [
|
|
12463
|
-
...new Set(files.filter((f) => f.toLowerCase().endsWith(e)).map((f) =>
|
|
12990
|
+
...new Set(files.filter((f) => f.toLowerCase().endsWith(e)).map((f) => basename39(f, ext)))
|
|
12464
12991
|
].sort();
|
|
12465
12992
|
}
|
|
12466
|
-
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix,
|
|
12993
|
+
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target13) {
|
|
12467
12994
|
const posixPath = pathInRepoPosix.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12468
|
-
const scan =
|
|
12469
|
-
if (
|
|
12995
|
+
const scan = join73(repoRoot, ...posixPath.split("/"));
|
|
12996
|
+
if (target13 === "gemini-cli") {
|
|
12470
12997
|
if (posixPath === GEMINI_COMMANDS_DIR || posixPath.startsWith(`${GEMINI_COMMANDS_DIR}/`)) {
|
|
12471
12998
|
const commands = await inferGeminiCommandNamesFromFiles(repoRoot, posixPath);
|
|
12472
12999
|
return commands.length ? { commands } : {};
|
|
12473
13000
|
}
|
|
12474
13001
|
return {};
|
|
12475
13002
|
}
|
|
12476
|
-
if (
|
|
13003
|
+
if (target13 === "claude-code") {
|
|
12477
13004
|
if (posixPath.startsWith(".claude/commands")) {
|
|
12478
13005
|
const commands = await mdNames(scan, ".md");
|
|
12479
13006
|
return commands.length ? { commands } : {};
|
|
@@ -12493,7 +13020,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12493
13020
|
}
|
|
12494
13021
|
return {};
|
|
12495
13022
|
}
|
|
12496
|
-
if (
|
|
13023
|
+
if (target13 === "cursor") {
|
|
12497
13024
|
if (posixPath.startsWith(".cursor/rules")) {
|
|
12498
13025
|
const rules = await mdNames(scan, ".mdc");
|
|
12499
13026
|
return rules.length ? { rules } : {};
|
|
@@ -12512,14 +13039,14 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12512
13039
|
}
|
|
12513
13040
|
return {};
|
|
12514
13041
|
}
|
|
12515
|
-
if (
|
|
13042
|
+
if (target13 === "copilot") {
|
|
12516
13043
|
return inferCopilotPickFromPath(repoRoot, posixPath);
|
|
12517
13044
|
}
|
|
12518
|
-
if (
|
|
13045
|
+
if (target13 === "windsurf" && posixPath.startsWith(".windsurf/rules")) {
|
|
12519
13046
|
const rules = await mdNames(scan, ".md");
|
|
12520
13047
|
return rules.length ? { rules } : {};
|
|
12521
13048
|
}
|
|
12522
|
-
if (
|
|
13049
|
+
if (target13 === "cline") {
|
|
12523
13050
|
if (posixPath.startsWith(CLINE_SKILLS_DIR)) {
|
|
12524
13051
|
const skills = await skillNamesFromNativeSkillDir(scan);
|
|
12525
13052
|
return skills.length ? { skills } : {};
|
|
@@ -12530,7 +13057,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12530
13057
|
}
|
|
12531
13058
|
return {};
|
|
12532
13059
|
}
|
|
12533
|
-
if (
|
|
13060
|
+
if (target13 === "continue") {
|
|
12534
13061
|
if (posixPath.startsWith(".continue/rules")) {
|
|
12535
13062
|
const rules = await mdNames(scan, ".md");
|
|
12536
13063
|
return rules.length ? { rules } : {};
|
|
@@ -12545,7 +13072,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12545
13072
|
}
|
|
12546
13073
|
return {};
|
|
12547
13074
|
}
|
|
12548
|
-
if (
|
|
13075
|
+
if (target13 === "junie") {
|
|
12549
13076
|
if (posixPath.startsWith(".junie/commands")) {
|
|
12550
13077
|
const commands = await mdNames(scan, ".md");
|
|
12551
13078
|
return commands.length ? { commands } : {};
|
|
@@ -12564,11 +13091,11 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12564
13091
|
}
|
|
12565
13092
|
return {};
|
|
12566
13093
|
}
|
|
12567
|
-
if (
|
|
13094
|
+
if (target13 === "codex-cli" && posixPath.startsWith(".codex")) {
|
|
12568
13095
|
const files = await readDirRecursive(scan);
|
|
12569
13096
|
const rules = [
|
|
12570
13097
|
...new Set(
|
|
12571
|
-
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) =>
|
|
13098
|
+
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) => basename39(f, ".md"))
|
|
12572
13099
|
)
|
|
12573
13100
|
].sort();
|
|
12574
13101
|
return rules.length ? { rules } : {};
|
|
@@ -12580,7 +13107,7 @@ function isImplicitPickEmpty(p) {
|
|
|
12580
13107
|
}
|
|
12581
13108
|
|
|
12582
13109
|
// src/install/native/native-install-scope.ts
|
|
12583
|
-
import { basename as
|
|
13110
|
+
import { basename as basename40, join as join74, relative as relative30 } from "path";
|
|
12584
13111
|
import { cp as cp3, mkdtemp as mkdtemp2, rm as rm9 } from "fs/promises";
|
|
12585
13112
|
import { tmpdir as tmpdir2 } from "os";
|
|
12586
13113
|
function normalizePath3(path) {
|
|
@@ -12591,14 +13118,14 @@ function overlapsPath(requested, imported) {
|
|
|
12591
13118
|
const b = normalizePath3(imported);
|
|
12592
13119
|
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
12593
13120
|
}
|
|
12594
|
-
function addUnique(
|
|
12595
|
-
const next =
|
|
13121
|
+
function addUnique(target13, value) {
|
|
13122
|
+
const next = target13 ?? [];
|
|
12596
13123
|
if (!next.includes(value)) next.push(value);
|
|
12597
13124
|
return next;
|
|
12598
13125
|
}
|
|
12599
13126
|
async function makeStageRoot(repoRoot) {
|
|
12600
|
-
const stageBase = await mkdtemp2(
|
|
12601
|
-
const stageRoot =
|
|
13127
|
+
const stageBase = await mkdtemp2(join74(tmpdir2(), "am-install-native-"));
|
|
13128
|
+
const stageRoot = join74(stageBase, "repo");
|
|
12602
13129
|
const cleanup = async () => {
|
|
12603
13130
|
await rm9(stageBase, { recursive: true, force: true });
|
|
12604
13131
|
};
|
|
@@ -12616,13 +13143,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12616
13143
|
if (result.feature === "rules" && result.toPath.startsWith(".agentsmesh/rules/")) {
|
|
12617
13144
|
pick = {
|
|
12618
13145
|
...pick,
|
|
12619
|
-
rules: addUnique(pick?.rules,
|
|
13146
|
+
rules: addUnique(pick?.rules, basename40(result.toPath, ".md"))
|
|
12620
13147
|
};
|
|
12621
13148
|
continue;
|
|
12622
13149
|
}
|
|
12623
13150
|
if (result.feature === "commands" && result.toPath.startsWith(".agentsmesh/commands/")) {
|
|
12624
13151
|
const rel2 = normalizePath3(
|
|
12625
|
-
relative30(
|
|
13152
|
+
relative30(join74(stageRoot, ".agentsmesh", "commands"), join74(stageRoot, result.toPath))
|
|
12626
13153
|
);
|
|
12627
13154
|
pick = {
|
|
12628
13155
|
...pick,
|
|
@@ -12636,13 +13163,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12636
13163
|
if (result.feature === "agents" && result.toPath.startsWith(".agentsmesh/agents/")) {
|
|
12637
13164
|
pick = {
|
|
12638
13165
|
...pick,
|
|
12639
|
-
agents: addUnique(pick?.agents,
|
|
13166
|
+
agents: addUnique(pick?.agents, basename40(result.toPath, ".md"))
|
|
12640
13167
|
};
|
|
12641
13168
|
continue;
|
|
12642
13169
|
}
|
|
12643
13170
|
if (result.feature === "skills" && result.toPath.startsWith(".agentsmesh/skills/")) {
|
|
12644
13171
|
const rel2 = normalizePath3(
|
|
12645
|
-
relative30(
|
|
13172
|
+
relative30(join74(stageRoot, ".agentsmesh", "skills"), join74(stageRoot, result.toPath))
|
|
12646
13173
|
);
|
|
12647
13174
|
const skillName = rel2.split("/")[0];
|
|
12648
13175
|
if (skillName) {
|
|
@@ -12657,12 +13184,12 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12657
13184
|
const hasAny = (pick.rules?.length ?? 0) + (pick.commands?.length ?? 0) + (pick.agents?.length ?? 0) + (pick.skills?.length ?? 0) > 0;
|
|
12658
13185
|
return hasAny ? pick : void 0;
|
|
12659
13186
|
}
|
|
12660
|
-
function scopeImportedResults(pathInRepoPosix, stageRoot, results,
|
|
12661
|
-
const requestedPath =
|
|
13187
|
+
function scopeImportedResults(pathInRepoPosix, stageRoot, results, target13) {
|
|
13188
|
+
const requestedPath = join74(stageRoot, ...normalizePath3(pathInRepoPosix).split("/"));
|
|
12662
13189
|
const filtered = results.filter((result) => overlapsPath(requestedPath, result.fromPath));
|
|
12663
13190
|
if (filtered.length === 0) {
|
|
12664
13191
|
throw new Error(
|
|
12665
|
-
`No installable native resources found under "${pathInRepoPosix}" for target "${
|
|
13192
|
+
`No installable native resources found under "${pathInRepoPosix}" for target "${target13}".`
|
|
12666
13193
|
);
|
|
12667
13194
|
}
|
|
12668
13195
|
return {
|
|
@@ -12670,23 +13197,23 @@ function scopeImportedResults(pathInRepoPosix, stageRoot, results, target12) {
|
|
|
12670
13197
|
pick: buildPickFromResults(filtered, stageRoot)
|
|
12671
13198
|
};
|
|
12672
13199
|
}
|
|
12673
|
-
async function stageImportedNativeRepo(repoRoot,
|
|
13200
|
+
async function stageImportedNativeRepo(repoRoot, target13) {
|
|
12674
13201
|
const { stageRoot, cleanup } = await makeStageRoot(repoRoot);
|
|
12675
13202
|
try {
|
|
12676
|
-
const results = await importNativeToCanonical(stageRoot,
|
|
13203
|
+
const results = await importNativeToCanonical(stageRoot, target13);
|
|
12677
13204
|
return { stageRoot, results, cleanup };
|
|
12678
13205
|
} catch (error) {
|
|
12679
13206
|
await cleanup();
|
|
12680
13207
|
throw error;
|
|
12681
13208
|
}
|
|
12682
13209
|
}
|
|
12683
|
-
async function stageNativeInstallScope(repoRoot, pathInRepoPosix,
|
|
12684
|
-
const staged = await stageImportedNativeRepo(repoRoot,
|
|
13210
|
+
async function stageNativeInstallScope(repoRoot, pathInRepoPosix, target13) {
|
|
13211
|
+
const staged = await stageImportedNativeRepo(repoRoot, target13);
|
|
12685
13212
|
try {
|
|
12686
13213
|
return {
|
|
12687
13214
|
stageRoot: staged.stageRoot,
|
|
12688
13215
|
cleanup: staged.cleanup,
|
|
12689
|
-
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results,
|
|
13216
|
+
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results, target13)
|
|
12690
13217
|
};
|
|
12691
13218
|
} catch (error) {
|
|
12692
13219
|
await staged.cleanup();
|
|
@@ -12702,7 +13229,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12702
13229
|
}
|
|
12703
13230
|
const posixPath = pathInRepo.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12704
13231
|
validateTargetMatchesPath(explicitTarget, posixPath);
|
|
12705
|
-
const agentsmeshAtRoot =
|
|
13232
|
+
const agentsmeshAtRoot = join75(repoRoot, ".agentsmesh");
|
|
12706
13233
|
const hasAbRoot = await exists(agentsmeshAtRoot);
|
|
12707
13234
|
const pathHint = posixPath ? targetHintFromNativePath(posixPath) : void 0;
|
|
12708
13235
|
const detectedTarget = !hasAbRoot && !explicitTarget ? await detectNativeFormat(repoRoot) ?? void 0 : void 0;
|
|
@@ -12727,7 +13254,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12727
13254
|
}
|
|
12728
13255
|
const staged = await stageImportedNativeRepo(repoRoot, effectiveTarget);
|
|
12729
13256
|
return {
|
|
12730
|
-
discoveryRoot: posixPath ?
|
|
13257
|
+
discoveryRoot: posixPath ? join75(staged.stageRoot, posixPath) : staged.stageRoot,
|
|
12731
13258
|
yamlTarget: effectiveTarget,
|
|
12732
13259
|
importHappened: true,
|
|
12733
13260
|
cleanup: staged.cleanup
|
|
@@ -12830,13 +13357,13 @@ function applyReplayInstallScope(narrowed, discoveredFeatures, replay) {
|
|
|
12830
13357
|
}
|
|
12831
13358
|
|
|
12832
13359
|
// src/install/manual/manual-install-persistence.ts
|
|
12833
|
-
import { basename as
|
|
13360
|
+
import { basename as basename41, dirname as dirname27, join as join76 } from "path";
|
|
12834
13361
|
import { stat as stat6 } from "fs/promises";
|
|
12835
13362
|
function trimDot(pathInRepo) {
|
|
12836
13363
|
return pathInRepo === "." || pathInRepo === "" ? void 0 : pathInRepo;
|
|
12837
13364
|
}
|
|
12838
13365
|
function markdownPick(as, pathValue) {
|
|
12839
|
-
const name =
|
|
13366
|
+
const name = basename41(pathValue).replace(/\.md$/i, "");
|
|
12840
13367
|
if (as === "agents") return { agents: [name] };
|
|
12841
13368
|
if (as === "commands") return { commands: [name] };
|
|
12842
13369
|
return { rules: [name] };
|
|
@@ -12854,23 +13381,23 @@ async function resolveManualInstallPersistence(args) {
|
|
|
12854
13381
|
};
|
|
12855
13382
|
}
|
|
12856
13383
|
if (args.as === "skills") {
|
|
12857
|
-
if (info.isFile() &&
|
|
13384
|
+
if (info.isFile() && basename41(args.contentRoot) === "SKILL.md") {
|
|
12858
13385
|
const skillDir = normalizedPath ? dirname27(normalizedPath) : dirname27(args.contentRoot);
|
|
12859
13386
|
return {
|
|
12860
13387
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12861
|
-
pick: { skills: [
|
|
13388
|
+
pick: { skills: [basename41(skillDir)] }
|
|
12862
13389
|
};
|
|
12863
13390
|
}
|
|
12864
13391
|
if (info.isDirectory()) {
|
|
12865
|
-
const skillDir = normalizedPath ||
|
|
12866
|
-
const skillFile =
|
|
13392
|
+
const skillDir = normalizedPath || basename41(args.contentRoot);
|
|
13393
|
+
const skillFile = join76(args.contentRoot.replace(/\/+$/g, ""), "SKILL.md");
|
|
12867
13394
|
try {
|
|
12868
13395
|
const skillStat = await stat6(skillFile);
|
|
12869
13396
|
if (skillStat.isFile()) {
|
|
12870
13397
|
const fmName = await readSkillFrontmatterName(skillFile);
|
|
12871
13398
|
return {
|
|
12872
13399
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12873
|
-
pick: { skills: [fmName ||
|
|
13400
|
+
pick: { skills: [fmName || basename41(skillDir)] }
|
|
12874
13401
|
};
|
|
12875
13402
|
}
|
|
12876
13403
|
} catch {
|
|
@@ -12938,7 +13465,7 @@ async function runInstall(flags, args, projectRoot, replay) {
|
|
|
12938
13465
|
sourceArg
|
|
12939
13466
|
);
|
|
12940
13467
|
const pathInRepo = parsed.pathInRepo.replace(/^\/+|\/+$/g, "");
|
|
12941
|
-
const contentRoot = pathInRepo ?
|
|
13468
|
+
const contentRoot = pathInRepo ? join77(resolvedPath, pathInRepo) : resolvedPath;
|
|
12942
13469
|
if (!await exists(contentRoot)) {
|
|
12943
13470
|
throw new Error(`Install path does not exist: ${contentRoot}`);
|
|
12944
13471
|
}
|