agentsmesh 0.2.10 → 0.3.1
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 +30 -1
- package/README.md +28 -33
- package/dist/cli.js +1263 -718
- package/dist/cli.js.map +1 -1
- package/package.json +13 -13
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");
|
|
@@ -2536,7 +2571,12 @@ import { basename as basename8, dirname as dirname5 } from "path";
|
|
|
2536
2571
|
// src/targets/projection/root-instruction-paragraph.ts
|
|
2537
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.";
|
|
2538
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.";
|
|
2539
|
-
var
|
|
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.";
|
|
2540
2580
|
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = ROOT_INSTRUCTION_BODY_V1;
|
|
2541
2581
|
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION = `## Project-Specific Rules
|
|
2542
2582
|
|
|
@@ -2547,6 +2587,21 @@ ${ROOT_INSTRUCTION_BODY_V1}`;
|
|
|
2547
2587
|
var AGENTSMESH_CONTRACT_WITH_V2_BODY = `## AgentsMesh Generation Contract
|
|
2548
2588
|
|
|
2549
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}`;
|
|
2550
2605
|
var AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = `## AgentsMesh Generation Contract
|
|
2551
2606
|
|
|
2552
2607
|
${ROOT_INSTRUCTION_BODY}`;
|
|
@@ -2554,6 +2609,11 @@ function normalizeWhitespace(value) {
|
|
|
2554
2609
|
return value.replace(/\s+/g, " ").trim();
|
|
2555
2610
|
}
|
|
2556
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,
|
|
2557
2617
|
AGENTSMESH_CONTRACT_WITH_V2_BODY,
|
|
2558
2618
|
AGENTSMESH_CONTRACT_WITH_V1_BODY,
|
|
2559
2619
|
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION,
|
|
@@ -4372,6 +4432,347 @@ var descriptor5 = {
|
|
|
4372
4432
|
]
|
|
4373
4433
|
};
|
|
4374
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
|
+
|
|
4375
4776
|
// src/targets/gemini-cli/constants.ts
|
|
4376
4777
|
var GEMINI_TARGET = "gemini-cli";
|
|
4377
4778
|
var GEMINI_ROOT = "GEMINI.md";
|
|
@@ -4434,7 +4835,7 @@ function mapHookEvent2(event) {
|
|
|
4434
4835
|
return null;
|
|
4435
4836
|
}
|
|
4436
4837
|
}
|
|
4437
|
-
function
|
|
4838
|
+
function generateRules7(canonical) {
|
|
4438
4839
|
const root = canonical.rules.find((r) => r.root);
|
|
4439
4840
|
const nonRootRules = canonical.rules.filter((r) => {
|
|
4440
4841
|
if (r.root) return false;
|
|
@@ -4489,7 +4890,7 @@ function generateAgents5(canonical) {
|
|
|
4489
4890
|
return { path: `${GEMINI_AGENTS_DIR}/${agent.name}.md`, content };
|
|
4490
4891
|
});
|
|
4491
4892
|
}
|
|
4492
|
-
function
|
|
4893
|
+
function generateSkills7(canonical) {
|
|
4493
4894
|
const outputs = [];
|
|
4494
4895
|
for (const skill of canonical.skills) {
|
|
4495
4896
|
const frontmatter = {
|
|
@@ -4553,7 +4954,7 @@ function generateSettings(canonical) {
|
|
|
4553
4954
|
if (Object.keys(settings).length === 0) return [];
|
|
4554
4955
|
return [{ path: GEMINI_SETTINGS, content: JSON.stringify(settings, null, 2) }];
|
|
4555
4956
|
}
|
|
4556
|
-
function
|
|
4957
|
+
function generateIgnore5(canonical) {
|
|
4557
4958
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
4558
4959
|
return [{ path: GEMINI_IGNORE, content: canonical.ignore.join("\n") }];
|
|
4559
4960
|
}
|
|
@@ -4637,14 +5038,14 @@ function generateGeminiPermissionsPolicies(canonical) {
|
|
|
4637
5038
|
|
|
4638
5039
|
// src/targets/gemini-cli/importer.ts
|
|
4639
5040
|
import { realpathSync } from "fs";
|
|
4640
|
-
import { join as
|
|
5041
|
+
import { join as join26, basename as basename18, dirname as dirname13, relative as relative9 } from "path";
|
|
4641
5042
|
|
|
4642
5043
|
// src/targets/gemini-cli/importer-mappers.ts
|
|
4643
|
-
import { join as
|
|
5044
|
+
import { join as join24 } from "path";
|
|
4644
5045
|
import { parse as parseToml2 } from "smol-toml";
|
|
4645
5046
|
|
|
4646
5047
|
// src/targets/gemini-cli/format-helpers.ts
|
|
4647
|
-
import { join as
|
|
5048
|
+
import { join as join23 } from "path";
|
|
4648
5049
|
import { parse as parseToml } from "smol-toml";
|
|
4649
5050
|
import { stringify as stringifyYaml } from "yaml";
|
|
4650
5051
|
function mapGeminiHookEvent(event) {
|
|
@@ -4685,7 +5086,7 @@ function parseFlexibleFrontmatter(content) {
|
|
|
4685
5086
|
return { frontmatter: {}, body: content.trim() };
|
|
4686
5087
|
}
|
|
4687
5088
|
async function importGeminiSettings(projectRoot, results) {
|
|
4688
|
-
const settingsPath =
|
|
5089
|
+
const settingsPath = join23(projectRoot, GEMINI_SETTINGS);
|
|
4689
5090
|
const settingsContent = await readFileSafe(settingsPath);
|
|
4690
5091
|
if (settingsContent === null) return;
|
|
4691
5092
|
let settings;
|
|
@@ -4696,8 +5097,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4696
5097
|
if (!settings) return;
|
|
4697
5098
|
const mcpServers = settings.mcpServers;
|
|
4698
5099
|
if (mcpServers !== void 0 && typeof mcpServers === "object" && mcpServers !== null && Object.keys(mcpServers).length > 0) {
|
|
4699
|
-
const mcpPath =
|
|
4700
|
-
await mkdirp(
|
|
5100
|
+
const mcpPath = join23(projectRoot, GEMINI_CANONICAL_MCP);
|
|
5101
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4701
5102
|
await writeFileAtomic(mcpPath, JSON.stringify({ mcpServers }, null, 2));
|
|
4702
5103
|
results.push({
|
|
4703
5104
|
fromTool: "gemini-cli",
|
|
@@ -4708,8 +5109,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4708
5109
|
}
|
|
4709
5110
|
const ignorePatterns = settings.ignorePatterns;
|
|
4710
5111
|
if (Array.isArray(ignorePatterns) && ignorePatterns.length > 0 && ignorePatterns.every((p) => typeof p === "string")) {
|
|
4711
|
-
const ignorePath =
|
|
4712
|
-
await mkdirp(
|
|
5112
|
+
const ignorePath = join23(projectRoot, GEMINI_CANONICAL_IGNORE);
|
|
5113
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4713
5114
|
await writeFileAtomic(ignorePath, ignorePatterns.join("\n") + "\n");
|
|
4714
5115
|
results.push({
|
|
4715
5116
|
fromTool: "gemini-cli",
|
|
@@ -4751,8 +5152,8 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4751
5152
|
);
|
|
4752
5153
|
if (mappedHooks.length > 0) {
|
|
4753
5154
|
const hooksYaml = Object.fromEntries(mappedHooks);
|
|
4754
|
-
const hooksPath =
|
|
4755
|
-
await mkdirp(
|
|
5155
|
+
const hooksPath = join23(projectRoot, GEMINI_CANONICAL_HOOKS);
|
|
5156
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
4756
5157
|
await writeFileAtomic(hooksPath, stringifyYaml(hooksYaml, { lineWidth: 0 }).trimEnd());
|
|
4757
5158
|
results.push({
|
|
4758
5159
|
fromTool: "gemini-cli",
|
|
@@ -4764,13 +5165,13 @@ async function importGeminiSettings(projectRoot, results) {
|
|
|
4764
5165
|
}
|
|
4765
5166
|
}
|
|
4766
5167
|
async function importGeminiIgnore(projectRoot, results) {
|
|
4767
|
-
const geminiIgnorePath =
|
|
5168
|
+
const geminiIgnorePath = join23(projectRoot, GEMINI_IGNORE);
|
|
4768
5169
|
const geminiIgnoreContent = await readFileSafe(geminiIgnorePath);
|
|
4769
5170
|
if (geminiIgnoreContent !== null && geminiIgnoreContent.trim()) {
|
|
4770
5171
|
const patterns = geminiIgnoreContent.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
4771
5172
|
if (patterns.length > 0) {
|
|
4772
|
-
await mkdirp(
|
|
4773
|
-
const ignorePath =
|
|
5173
|
+
await mkdirp(join23(projectRoot, ".agentsmesh"));
|
|
5174
|
+
const ignorePath = join23(projectRoot, GEMINI_CANONICAL_IGNORE);
|
|
4774
5175
|
await writeFileAtomic(ignorePath, patterns.join("\n") + "\n");
|
|
4775
5176
|
results.push({
|
|
4776
5177
|
fromTool: "gemini-cli",
|
|
@@ -4785,7 +5186,7 @@ async function importGeminiIgnore(projectRoot, results) {
|
|
|
4785
5186
|
// src/targets/gemini-cli/importer-mappers.ts
|
|
4786
5187
|
async function mapGeminiRuleFile(relativePath, destDir, normalizeTo) {
|
|
4787
5188
|
const relativeMdPath = relativePath.replace(/\\/g, "/");
|
|
4788
|
-
const destPath =
|
|
5189
|
+
const destPath = join24(destDir, relativeMdPath);
|
|
4789
5190
|
const { frontmatter, body } = parseFlexibleFrontmatter(normalizeTo(destPath));
|
|
4790
5191
|
const globs = toGlobsArray(frontmatter.globs);
|
|
4791
5192
|
const canonicalFm = {
|
|
@@ -4805,7 +5206,7 @@ async function mapGeminiRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
4805
5206
|
}
|
|
4806
5207
|
async function mapGeminiCommandFile(relativePath, destDir, normalizeTo) {
|
|
4807
5208
|
const relativeMdPath = relativePath.replace(/\.(toml|md)$/i, ".md").replace(/\\/g, "/");
|
|
4808
|
-
const destPath =
|
|
5209
|
+
const destPath = join24(destDir, relativeMdPath);
|
|
4809
5210
|
const normalized = normalizeTo(destPath);
|
|
4810
5211
|
const { frontmatter, body } = relativePath.endsWith(".toml") ? parseTomlCommand(normalized) : parseFlexibleFrontmatter(normalized);
|
|
4811
5212
|
const fromCamel = toToolsArray2(frontmatter.allowedTools);
|
|
@@ -4842,7 +5243,7 @@ function parseTomlCommand(normalized) {
|
|
|
4842
5243
|
// src/targets/gemini-cli/policies-importer.ts
|
|
4843
5244
|
import { parse as parseToml3 } from "smol-toml";
|
|
4844
5245
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
4845
|
-
import { join as
|
|
5246
|
+
import { join as join25 } from "path";
|
|
4846
5247
|
function unescapeRegexLiteral(value) {
|
|
4847
5248
|
return value.replace(/\\(.)/g, "$1");
|
|
4848
5249
|
}
|
|
@@ -4870,7 +5271,7 @@ function argsPatternToReadExpr(argsPattern) {
|
|
|
4870
5271
|
}
|
|
4871
5272
|
async function importGeminiPolicies(projectRoot) {
|
|
4872
5273
|
const results = [];
|
|
4873
|
-
const policiesDir =
|
|
5274
|
+
const policiesDir = join25(projectRoot, GEMINI_POLICIES_DIR);
|
|
4874
5275
|
let policyFiles;
|
|
4875
5276
|
try {
|
|
4876
5277
|
policyFiles = await readDirRecursive(policiesDir);
|
|
@@ -4931,13 +5332,13 @@ async function importGeminiPolicies(projectRoot) {
|
|
|
4931
5332
|
}
|
|
4932
5333
|
}
|
|
4933
5334
|
if (allow.length === 0 && deny.length === 0) return results;
|
|
4934
|
-
await mkdirp(
|
|
4935
|
-
const outPath =
|
|
5335
|
+
await mkdirp(join25(projectRoot, ".agentsmesh"));
|
|
5336
|
+
const outPath = join25(projectRoot, GEMINI_CANONICAL_PERMISSIONS);
|
|
4936
5337
|
const yaml = stringifyYaml2({ allow, deny });
|
|
4937
5338
|
await writeFileAtomic(outPath, yaml.trimEnd() + "\n");
|
|
4938
5339
|
results.push({
|
|
4939
5340
|
fromTool: GEMINI_TARGET,
|
|
4940
|
-
fromPath:
|
|
5341
|
+
fromPath: join25(projectRoot, GEMINI_POLICIES_DIR),
|
|
4941
5342
|
toPath: GEMINI_CANONICAL_PERMISSIONS,
|
|
4942
5343
|
feature: "permissions"
|
|
4943
5344
|
});
|
|
@@ -4949,12 +5350,12 @@ async function importFromGemini(projectRoot) {
|
|
|
4949
5350
|
const results = [];
|
|
4950
5351
|
const normalize = await createImportReferenceNormalizer(GEMINI_TARGET, projectRoot);
|
|
4951
5352
|
const normalizeCodex = await createImportReferenceNormalizer("codex-cli", projectRoot);
|
|
4952
|
-
const rulesDir =
|
|
4953
|
-
const commandsDir =
|
|
4954
|
-
const geminiRootPath =
|
|
4955
|
-
const compatAgentsRootPath =
|
|
4956
|
-
const compatInnerRootPath =
|
|
4957
|
-
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);
|
|
4958
5359
|
const geminiRootContent = await readFileSafe(geminiRootPath);
|
|
4959
5360
|
const compatAgentsRootContent = await readFileSafe(compatAgentsRootPath);
|
|
4960
5361
|
const compatInnerRootContent = await readFileSafe(compatInnerRootPath);
|
|
@@ -4969,7 +5370,7 @@ async function importFromGemini(projectRoot) {
|
|
|
4969
5370
|
const rootContent = rootCandidate?.content ?? null;
|
|
4970
5371
|
if (rootContent !== null) {
|
|
4971
5372
|
await mkdirp(rulesDir);
|
|
4972
|
-
const destPath =
|
|
5373
|
+
const destPath = join26(rulesDir, "_root.md");
|
|
4973
5374
|
const compatNormalized = rootSourcePath === compatAgentsRootPath || rootSourcePath === compatInnerRootPath ? normalize(normalizeCodex(rootContent, rootSourcePath, destPath), rootSourcePath, destPath) : normalize(rootContent, rootSourcePath, destPath);
|
|
4974
5375
|
const normalizedRoot = stripProjectRootCanonicalPrefix(
|
|
4975
5376
|
compatNormalized.replace(/\.agents\/skills\//g, ".agentsmesh/skills/").replace(/\.agents\\skills\\/g, ".agentsmesh/skills/"),
|
|
@@ -4990,7 +5391,7 @@ async function importFromGemini(projectRoot) {
|
|
|
4990
5391
|
feature: "rules"
|
|
4991
5392
|
});
|
|
4992
5393
|
}
|
|
4993
|
-
const geminiRulesPath =
|
|
5394
|
+
const geminiRulesPath = join26(projectRoot, GEMINI_RULES_DIR);
|
|
4994
5395
|
results.push(
|
|
4995
5396
|
...await importFileDirectory({
|
|
4996
5397
|
srcDir: geminiRulesPath,
|
|
@@ -5001,7 +5402,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5001
5402
|
mapEntry: ({ relativePath, normalizeTo }) => mapGeminiRuleFile(relativePath, rulesDir, normalizeTo)
|
|
5002
5403
|
})
|
|
5003
5404
|
);
|
|
5004
|
-
const geminiCommandsPath =
|
|
5405
|
+
const geminiCommandsPath = join26(projectRoot, GEMINI_COMMANDS_DIR);
|
|
5005
5406
|
results.push(
|
|
5006
5407
|
...await importFileDirectory({
|
|
5007
5408
|
srcDir: geminiCommandsPath,
|
|
@@ -5012,19 +5413,19 @@ async function importFromGemini(projectRoot) {
|
|
|
5012
5413
|
mapEntry: ({ relativePath, normalizeTo }) => mapGeminiCommandFile(relativePath, commandsDir, normalizeTo)
|
|
5013
5414
|
})
|
|
5014
5415
|
);
|
|
5015
|
-
const geminiSkillsPath =
|
|
5416
|
+
const geminiSkillsPath = join26(projectRoot, GEMINI_SKILLS_DIR);
|
|
5016
5417
|
const skillDirs = await readDirRecursive(geminiSkillsPath);
|
|
5017
|
-
const skillMdFiles = skillDirs.filter((f) =>
|
|
5418
|
+
const skillMdFiles = skillDirs.filter((f) => basename18(f) === "SKILL.md");
|
|
5018
5419
|
for (const srcPath of skillMdFiles) {
|
|
5019
5420
|
const content = await readFileSafe(srcPath);
|
|
5020
5421
|
if (!content) continue;
|
|
5021
|
-
const skillName =
|
|
5422
|
+
const skillName = basename18(srcPath.slice(0, -"/SKILL.md".length));
|
|
5022
5423
|
const rawParsed = parseFrontmatter(content);
|
|
5023
5424
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, skillName);
|
|
5024
5425
|
if (projectedAgent) {
|
|
5025
|
-
const agentsDir =
|
|
5426
|
+
const agentsDir = join26(projectRoot, GEMINI_CANONICAL_AGENTS_DIR);
|
|
5026
5427
|
await mkdirp(agentsDir);
|
|
5027
|
-
const agentPath =
|
|
5428
|
+
const agentPath = join26(agentsDir, `${projectedAgent.name}.md`);
|
|
5028
5429
|
await writeFileAtomic(
|
|
5029
5430
|
agentPath,
|
|
5030
5431
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, srcPath, agentPath))
|
|
@@ -5037,9 +5438,9 @@ async function importFromGemini(projectRoot) {
|
|
|
5037
5438
|
});
|
|
5038
5439
|
continue;
|
|
5039
5440
|
}
|
|
5040
|
-
const destPath =
|
|
5441
|
+
const destPath = join26(projectRoot, GEMINI_CANONICAL_SKILLS_DIR, skillName, "SKILL.md");
|
|
5041
5442
|
const normalized = normalize(content, srcPath, destPath);
|
|
5042
|
-
const skillDir =
|
|
5443
|
+
const skillDir = join26(projectRoot, GEMINI_CANONICAL_SKILLS_DIR, skillName);
|
|
5043
5444
|
await mkdirp(skillDir);
|
|
5044
5445
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
5045
5446
|
await writeFileAtomic(
|
|
@@ -5058,7 +5459,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5058
5459
|
const supportContent = await readFileSafe(absPath);
|
|
5059
5460
|
if (supportContent === null) continue;
|
|
5060
5461
|
const relPath = relative9(dirname13(srcPath), absPath).replace(/\\/g, "/");
|
|
5061
|
-
const destSupportPath =
|
|
5462
|
+
const destSupportPath = join26(skillDir, relPath);
|
|
5062
5463
|
await mkdirp(dirname13(destSupportPath));
|
|
5063
5464
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
5064
5465
|
results.push({
|
|
@@ -5069,7 +5470,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5069
5470
|
});
|
|
5070
5471
|
}
|
|
5071
5472
|
}
|
|
5072
|
-
const geminiAgentsPath =
|
|
5473
|
+
const geminiAgentsPath = join26(projectRoot, GEMINI_AGENTS_DIR);
|
|
5073
5474
|
try {
|
|
5074
5475
|
const agentFiles = await readDirRecursive(geminiAgentsPath);
|
|
5075
5476
|
const agentMdFiles = agentFiles.filter((f) => f.endsWith(".md"));
|
|
@@ -5079,9 +5480,9 @@ async function importFromGemini(projectRoot) {
|
|
|
5079
5480
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
5080
5481
|
const relPath = relative9(geminiAgentsPath, srcPath).replace(/\\/g, "/");
|
|
5081
5482
|
const relativeMdPath = relPath.replace(/\.md$/i, ".md");
|
|
5082
|
-
const agentsDir =
|
|
5483
|
+
const agentsDir = join26(projectRoot, GEMINI_CANONICAL_AGENTS_DIR);
|
|
5083
5484
|
await mkdirp(agentsDir);
|
|
5084
|
-
const destPath =
|
|
5485
|
+
const destPath = join26(agentsDir, relativeMdPath);
|
|
5085
5486
|
const normalizedBody = normalize(body, srcPath, destPath);
|
|
5086
5487
|
await writeFileAtomic(
|
|
5087
5488
|
destPath,
|
|
@@ -5089,7 +5490,7 @@ async function importFromGemini(projectRoot) {
|
|
|
5089
5490
|
destPath,
|
|
5090
5491
|
{
|
|
5091
5492
|
...frontmatter,
|
|
5092
|
-
name: typeof frontmatter.name === "string" ? frontmatter.name :
|
|
5493
|
+
name: typeof frontmatter.name === "string" ? frontmatter.name : basename18(relativeMdPath, ".md"),
|
|
5093
5494
|
maxTurns: frontmatter.maxTurns ?? frontmatter["max-turns"] ?? frontmatter.max_turns,
|
|
5094
5495
|
permissionMode: frontmatter.permissionMode ?? frontmatter["permission-mode"] ?? frontmatter.permission_mode,
|
|
5095
5496
|
disallowedTools: frontmatter.disallowedTools ?? frontmatter["disallowed-tools"] ?? frontmatter.disallowed_tools
|
|
@@ -5130,27 +5531,27 @@ function stripProjectRootCanonicalPrefix(content, projectRoot) {
|
|
|
5130
5531
|
}
|
|
5131
5532
|
|
|
5132
5533
|
// src/targets/gemini-cli/linter.ts
|
|
5133
|
-
function
|
|
5534
|
+
function lintRules7(canonical, projectRoot, projectFiles) {
|
|
5134
5535
|
const diags = validateRules(canonical, projectRoot, projectFiles);
|
|
5135
5536
|
return diags.map((d) => ({ ...d, target: GEMINI_TARGET }));
|
|
5136
5537
|
}
|
|
5137
5538
|
|
|
5138
5539
|
// src/targets/gemini-cli/index.ts
|
|
5139
|
-
var
|
|
5540
|
+
var target7 = {
|
|
5140
5541
|
name: "gemini-cli",
|
|
5141
5542
|
primaryRootInstructionPath: GEMINI_ROOT,
|
|
5142
|
-
generateRules:
|
|
5543
|
+
generateRules: generateRules7,
|
|
5143
5544
|
generateCommands: generateCommands6,
|
|
5144
5545
|
generateAgents: generateAgents5,
|
|
5145
|
-
generateSkills:
|
|
5546
|
+
generateSkills: generateSkills7,
|
|
5146
5547
|
generateSettings,
|
|
5147
|
-
generateIgnore:
|
|
5548
|
+
generateIgnore: generateIgnore5,
|
|
5148
5549
|
generatePermissions: generateGeminiPermissionsPolicies,
|
|
5149
5550
|
importFrom: importFromGemini
|
|
5150
5551
|
};
|
|
5151
|
-
var
|
|
5552
|
+
var descriptor7 = {
|
|
5152
5553
|
id: "gemini-cli",
|
|
5153
|
-
generators:
|
|
5554
|
+
generators: target7,
|
|
5154
5555
|
capabilities: {
|
|
5155
5556
|
rules: "native",
|
|
5156
5557
|
commands: "native",
|
|
@@ -5162,7 +5563,7 @@ var descriptor6 = {
|
|
|
5162
5563
|
permissions: "partial"
|
|
5163
5564
|
},
|
|
5164
5565
|
emptyImportMessage: "No Gemini CLI config found (GEMINI.md or .gemini/rules, .gemini/commands, .gemini/settings.json).",
|
|
5165
|
-
lintRules:
|
|
5566
|
+
lintRules: lintRules7,
|
|
5166
5567
|
skillDir: ".gemini/skills",
|
|
5167
5568
|
paths: {
|
|
5168
5569
|
rulePath(_slug, _rule) {
|
|
@@ -5186,7 +5587,7 @@ var descriptor6 = {
|
|
|
5186
5587
|
};
|
|
5187
5588
|
|
|
5188
5589
|
// src/targets/cline/generator.ts
|
|
5189
|
-
import { basename as
|
|
5590
|
+
import { basename as basename19 } from "path";
|
|
5190
5591
|
|
|
5191
5592
|
// src/targets/cline/constants.ts
|
|
5192
5593
|
var CLINE_TARGET = "cline";
|
|
@@ -5207,10 +5608,10 @@ var CLINE_CANONICAL_SKILLS_DIR = ".agentsmesh/skills";
|
|
|
5207
5608
|
|
|
5208
5609
|
// src/targets/cline/generator.ts
|
|
5209
5610
|
function ruleSlug3(source) {
|
|
5210
|
-
const name =
|
|
5611
|
+
const name = basename19(source, ".md");
|
|
5211
5612
|
return name === "_root" ? "root" : name;
|
|
5212
5613
|
}
|
|
5213
|
-
function
|
|
5614
|
+
function generateRules8(canonical) {
|
|
5214
5615
|
const outputs = [];
|
|
5215
5616
|
const root = canonical.rules.find((r) => r.root);
|
|
5216
5617
|
if (root) {
|
|
@@ -5243,12 +5644,12 @@ ${body}` : desc || body;
|
|
|
5243
5644
|
return { path: `${CLINE_WORKFLOWS_DIR}/${cmd.name}.md`, content };
|
|
5244
5645
|
});
|
|
5245
5646
|
}
|
|
5246
|
-
function
|
|
5647
|
+
function generateIgnore6(canonical) {
|
|
5247
5648
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
5248
5649
|
const content = canonical.ignore.join("\n");
|
|
5249
5650
|
return [{ path: CLINE_IGNORE, content }];
|
|
5250
5651
|
}
|
|
5251
|
-
function
|
|
5652
|
+
function generateMcp6(canonical) {
|
|
5252
5653
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
5253
5654
|
const content = JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2);
|
|
5254
5655
|
return [{ path: CLINE_MCP_SETTINGS, content }];
|
|
@@ -5272,7 +5673,7 @@ function buildHookScript(command, matcher) {
|
|
|
5272
5673
|
""
|
|
5273
5674
|
].join("\n");
|
|
5274
5675
|
}
|
|
5275
|
-
function
|
|
5676
|
+
function generateHooks5(canonical) {
|
|
5276
5677
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
5277
5678
|
const outputs = [];
|
|
5278
5679
|
for (const [event, entries] of Object.entries(canonical.hooks)) {
|
|
@@ -5289,7 +5690,7 @@ function generateHooks4(canonical) {
|
|
|
5289
5690
|
}
|
|
5290
5691
|
return outputs;
|
|
5291
5692
|
}
|
|
5292
|
-
function
|
|
5693
|
+
function generateSkills8(canonical) {
|
|
5293
5694
|
const outputs = [];
|
|
5294
5695
|
for (const skill of canonical.skills) {
|
|
5295
5696
|
const frontmatter = {
|
|
@@ -5315,15 +5716,15 @@ function generateSkills7(canonical) {
|
|
|
5315
5716
|
|
|
5316
5717
|
// src/targets/cline/importer.ts
|
|
5317
5718
|
import { stat as stat3 } from "fs/promises";
|
|
5318
|
-
import { join as
|
|
5719
|
+
import { join as join30 } from "path";
|
|
5319
5720
|
|
|
5320
5721
|
// src/targets/cline/importer-mappers.ts
|
|
5321
|
-
import { join as
|
|
5722
|
+
import { join as join27 } from "path";
|
|
5322
5723
|
async function mapClineRuleFile(relativePath, destDir, normalizeTo) {
|
|
5323
5724
|
if (relativePath === "workflows" || relativePath.startsWith("workflows/")) return null;
|
|
5324
5725
|
const relativeMdPath = relativePath.replace(/\\/g, "/");
|
|
5325
5726
|
if (relativeMdPath === "_root.md") return null;
|
|
5326
|
-
const destPath =
|
|
5727
|
+
const destPath = join27(destDir, relativeMdPath);
|
|
5327
5728
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
5328
5729
|
const globs = toGlobsArray(frontmatter.paths ?? frontmatter.globs);
|
|
5329
5730
|
const canonicalFm = {
|
|
@@ -5342,7 +5743,7 @@ async function mapClineRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
5342
5743
|
};
|
|
5343
5744
|
}
|
|
5344
5745
|
async function mapClineWorkflowFile(relativePath, destDir, normalizeTo) {
|
|
5345
|
-
const destPath =
|
|
5746
|
+
const destPath = join27(destDir, relativePath);
|
|
5346
5747
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
5347
5748
|
const hasFrontmatterDescription = Object.prototype.hasOwnProperty.call(
|
|
5348
5749
|
frontmatter,
|
|
@@ -5380,7 +5781,7 @@ async function mapClineWorkflowFile(relativePath, destDir, normalizeTo) {
|
|
|
5380
5781
|
}
|
|
5381
5782
|
|
|
5382
5783
|
// src/targets/cline/mcp-mapper.ts
|
|
5383
|
-
import { join as
|
|
5784
|
+
import { join as join28 } from "path";
|
|
5384
5785
|
function mapClineServerToCanonical(raw) {
|
|
5385
5786
|
if (!raw || typeof raw !== "object") return null;
|
|
5386
5787
|
const obj = raw;
|
|
@@ -5405,7 +5806,7 @@ function mapClineServerToCanonical(raw) {
|
|
|
5405
5806
|
}
|
|
5406
5807
|
async function importClineMcp(projectRoot, results) {
|
|
5407
5808
|
const candidatePaths = [CLINE_MCP_SETTINGS, CLINE_MCP_SETTINGS_LEGACY].map(
|
|
5408
|
-
(path) =>
|
|
5809
|
+
(path) => join28(projectRoot, path)
|
|
5409
5810
|
);
|
|
5410
5811
|
let mcpPath = null;
|
|
5411
5812
|
let mcpContent = null;
|
|
@@ -5432,9 +5833,9 @@ async function importClineMcp(projectRoot, results) {
|
|
|
5432
5833
|
if (server) mcpServers[n] = server;
|
|
5433
5834
|
}
|
|
5434
5835
|
if (Object.keys(mcpServers).length > 0) {
|
|
5435
|
-
await mkdirp(
|
|
5836
|
+
await mkdirp(join28(projectRoot, ".agentsmesh"));
|
|
5436
5837
|
await writeFileAtomic(
|
|
5437
|
-
|
|
5838
|
+
join28(projectRoot, CLINE_CANONICAL_MCP),
|
|
5438
5839
|
JSON.stringify({ mcpServers }, null, 2)
|
|
5439
5840
|
);
|
|
5440
5841
|
results.push({
|
|
@@ -5449,16 +5850,16 @@ async function importClineMcp(projectRoot, results) {
|
|
|
5449
5850
|
|
|
5450
5851
|
// src/targets/cline/skills-helpers.ts
|
|
5451
5852
|
import { readdir as readdir6 } from "fs/promises";
|
|
5452
|
-
import { join as
|
|
5853
|
+
import { join as join29 } from "path";
|
|
5453
5854
|
async function importClineSkills(projectRoot, results, normalize) {
|
|
5454
|
-
const skillsDir =
|
|
5855
|
+
const skillsDir = join29(projectRoot, CLINE_SKILLS_DIR);
|
|
5455
5856
|
const skillDirs = [];
|
|
5456
5857
|
try {
|
|
5457
5858
|
const entries = await readdir6(skillsDir, { withFileTypes: true });
|
|
5458
5859
|
for (const ent of entries) {
|
|
5459
5860
|
if (!ent.isDirectory()) continue;
|
|
5460
|
-
const skillPath =
|
|
5461
|
-
const skillMd =
|
|
5861
|
+
const skillPath = join29(skillsDir, ent.name);
|
|
5862
|
+
const skillMd = join29(skillPath, "SKILL.md");
|
|
5462
5863
|
const content = await readFileSafe(skillMd);
|
|
5463
5864
|
if (!content) continue;
|
|
5464
5865
|
skillDirs.push({ name: ent.name, path: skillPath });
|
|
@@ -5466,15 +5867,15 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5466
5867
|
} catch {
|
|
5467
5868
|
}
|
|
5468
5869
|
for (const { name, path: skillPath } of skillDirs) {
|
|
5469
|
-
const skillMdPath =
|
|
5870
|
+
const skillMdPath = join29(skillPath, "SKILL.md");
|
|
5470
5871
|
const content = await readFileSafe(skillMdPath);
|
|
5471
5872
|
if (!content) continue;
|
|
5472
5873
|
const rawParsed = parseFrontmatter(content);
|
|
5473
5874
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, name);
|
|
5474
5875
|
if (projectedAgent) {
|
|
5475
|
-
const destAgentsDir =
|
|
5876
|
+
const destAgentsDir = join29(projectRoot, CLINE_CANONICAL_AGENTS_DIR);
|
|
5476
5877
|
await mkdirp(destAgentsDir);
|
|
5477
|
-
const agentPath =
|
|
5878
|
+
const agentPath = join29(destAgentsDir, `${projectedAgent.name}.md`);
|
|
5478
5879
|
await writeFileAtomic(
|
|
5479
5880
|
agentPath,
|
|
5480
5881
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
@@ -5487,10 +5888,10 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5487
5888
|
});
|
|
5488
5889
|
continue;
|
|
5489
5890
|
}
|
|
5490
|
-
const destSkillPath =
|
|
5891
|
+
const destSkillPath = join29(projectRoot, CLINE_CANONICAL_SKILLS_DIR, name, "SKILL.md");
|
|
5491
5892
|
const normalized = normalize(content, skillMdPath, destSkillPath);
|
|
5492
5893
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
5493
|
-
const destSkillDir =
|
|
5894
|
+
const destSkillDir = join29(projectRoot, CLINE_CANONICAL_SKILLS_DIR, name);
|
|
5494
5895
|
await mkdirp(destSkillDir);
|
|
5495
5896
|
const skillContent = await serializeImportedSkillWithFallback(
|
|
5496
5897
|
destSkillPath,
|
|
@@ -5510,8 +5911,8 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5510
5911
|
const relPath = absPath.slice(skillPath.length + 1).replace(/\\/g, "/");
|
|
5511
5912
|
const supportContent = await readFileSafe(absPath);
|
|
5512
5913
|
if (supportContent === null) continue;
|
|
5513
|
-
const destSupportPath =
|
|
5514
|
-
await mkdirp(
|
|
5914
|
+
const destSupportPath = join29(destSkillDir, relPath);
|
|
5915
|
+
await mkdirp(join29(destSupportPath, ".."));
|
|
5515
5916
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
5516
5917
|
results.push({
|
|
5517
5918
|
fromTool: CLINE_TARGET,
|
|
@@ -5527,9 +5928,9 @@ async function importClineSkills(projectRoot, results, normalize) {
|
|
|
5527
5928
|
async function importFromCline(projectRoot) {
|
|
5528
5929
|
const results = [];
|
|
5529
5930
|
const normalize = await createImportReferenceNormalizer(CLINE_TARGET, projectRoot);
|
|
5530
|
-
const destRulesDir =
|
|
5531
|
-
const clineRulesPath =
|
|
5532
|
-
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);
|
|
5533
5934
|
let clineRulesIsFile = false;
|
|
5534
5935
|
try {
|
|
5535
5936
|
const clineRulesStat = await stat3(clineRulesRaw);
|
|
@@ -5540,7 +5941,7 @@ async function importFromCline(projectRoot) {
|
|
|
5540
5941
|
const flatContent = await readFileSafe(clineRulesRaw);
|
|
5541
5942
|
if (flatContent !== null) {
|
|
5542
5943
|
await mkdirp(destRulesDir);
|
|
5543
|
-
const destPath =
|
|
5944
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5544
5945
|
const { frontmatter, body } = parseFrontmatter(
|
|
5545
5946
|
normalize(flatContent, clineRulesRaw, destPath)
|
|
5546
5947
|
);
|
|
@@ -5557,15 +5958,15 @@ async function importFromCline(projectRoot) {
|
|
|
5557
5958
|
}
|
|
5558
5959
|
} else {
|
|
5559
5960
|
let rootSourcePath = null;
|
|
5560
|
-
const rootPath =
|
|
5961
|
+
const rootPath = join30(clineRulesPath, "_root.md");
|
|
5561
5962
|
const rootContent = await readFileSafe(rootPath);
|
|
5562
5963
|
if (rootContent === null) {
|
|
5563
|
-
const agentsMdPath =
|
|
5964
|
+
const agentsMdPath = join30(projectRoot, CLINE_AGENTS_MD);
|
|
5564
5965
|
const agentsMdContent = await readFileSafe(agentsMdPath);
|
|
5565
5966
|
if (agentsMdContent !== null) {
|
|
5566
5967
|
rootSourcePath = agentsMdPath;
|
|
5567
5968
|
await mkdirp(destRulesDir);
|
|
5568
|
-
const destPath =
|
|
5969
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5569
5970
|
const { frontmatter, body } = parseFrontmatter(
|
|
5570
5971
|
normalize(agentsMdContent, agentsMdPath, destPath)
|
|
5571
5972
|
);
|
|
@@ -5588,7 +5989,7 @@ async function importFromCline(projectRoot) {
|
|
|
5588
5989
|
if (fc !== null) {
|
|
5589
5990
|
rootSourcePath = first;
|
|
5590
5991
|
await mkdirp(destRulesDir);
|
|
5591
|
-
const destPath =
|
|
5992
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5592
5993
|
const { frontmatter, body } = parseFrontmatter(normalize(fc, first, destPath));
|
|
5593
5994
|
const hasRoot = frontmatter.root === true;
|
|
5594
5995
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -5606,7 +6007,7 @@ async function importFromCline(projectRoot) {
|
|
|
5606
6007
|
} else {
|
|
5607
6008
|
rootSourcePath = rootPath;
|
|
5608
6009
|
await mkdirp(destRulesDir);
|
|
5609
|
-
const destPath =
|
|
6010
|
+
const destPath = join30(destRulesDir, "_root.md");
|
|
5610
6011
|
const { frontmatter, body } = parseFrontmatter(normalize(rootContent, rootPath, destPath));
|
|
5611
6012
|
const hasRoot = frontmatter.root === true;
|
|
5612
6013
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -5633,7 +6034,7 @@ async function importFromCline(projectRoot) {
|
|
|
5633
6034
|
})
|
|
5634
6035
|
);
|
|
5635
6036
|
}
|
|
5636
|
-
const ignorePath =
|
|
6037
|
+
const ignorePath = join30(projectRoot, CLINE_IGNORE);
|
|
5637
6038
|
const ignoreContent = await readFileSafe(ignorePath);
|
|
5638
6039
|
if (ignoreContent !== null && ignoreContent.trim()) {
|
|
5639
6040
|
const lines = ignoreContent.split(/\r?\n/);
|
|
@@ -5643,8 +6044,8 @@ async function importFromCline(projectRoot) {
|
|
|
5643
6044
|
if (t && !t.startsWith("#")) patterns.push(t);
|
|
5644
6045
|
}
|
|
5645
6046
|
if (patterns.length > 0) {
|
|
5646
|
-
await mkdirp(
|
|
5647
|
-
const destIgnorePath =
|
|
6047
|
+
await mkdirp(join30(projectRoot, ".agentsmesh"));
|
|
6048
|
+
const destIgnorePath = join30(projectRoot, CLINE_CANONICAL_IGNORE);
|
|
5648
6049
|
await writeFileAtomic(destIgnorePath, patterns.join("\n"));
|
|
5649
6050
|
results.push({
|
|
5650
6051
|
fromTool: "cline",
|
|
@@ -5655,11 +6056,11 @@ async function importFromCline(projectRoot) {
|
|
|
5655
6056
|
}
|
|
5656
6057
|
}
|
|
5657
6058
|
await importClineMcp(projectRoot, results);
|
|
5658
|
-
const destCommandsDir =
|
|
6059
|
+
const destCommandsDir = join30(projectRoot, CLINE_CANONICAL_COMMANDS_DIR);
|
|
5659
6060
|
if (!clineRulesIsFile) {
|
|
5660
6061
|
results.push(
|
|
5661
6062
|
...await importFileDirectory({
|
|
5662
|
-
srcDir:
|
|
6063
|
+
srcDir: join30(projectRoot, CLINE_WORKFLOWS_DIR),
|
|
5663
6064
|
destDir: destCommandsDir,
|
|
5664
6065
|
extensions: [".md"],
|
|
5665
6066
|
fromTool: "cline",
|
|
@@ -5673,27 +6074,27 @@ async function importFromCline(projectRoot) {
|
|
|
5673
6074
|
}
|
|
5674
6075
|
|
|
5675
6076
|
// src/targets/cline/linter.ts
|
|
5676
|
-
function
|
|
6077
|
+
function lintRules8(canonical, projectRoot, projectFiles) {
|
|
5677
6078
|
const diags = validateRules(canonical, projectRoot, projectFiles);
|
|
5678
6079
|
return diags.map((d) => ({ ...d, target: CLINE_TARGET }));
|
|
5679
6080
|
}
|
|
5680
6081
|
|
|
5681
6082
|
// src/targets/cline/index.ts
|
|
5682
|
-
var
|
|
6083
|
+
var target8 = {
|
|
5683
6084
|
name: "cline",
|
|
5684
6085
|
primaryRootInstructionPath: CLINE_AGENTS_MD,
|
|
5685
|
-
generateRules:
|
|
6086
|
+
generateRules: generateRules8,
|
|
5686
6087
|
generateWorkflows,
|
|
5687
6088
|
generateAgents: generateAgents6,
|
|
5688
|
-
generateSkills:
|
|
5689
|
-
generateMcp:
|
|
5690
|
-
generateHooks:
|
|
5691
|
-
generateIgnore:
|
|
6089
|
+
generateSkills: generateSkills8,
|
|
6090
|
+
generateMcp: generateMcp6,
|
|
6091
|
+
generateHooks: generateHooks5,
|
|
6092
|
+
generateIgnore: generateIgnore6,
|
|
5692
6093
|
importFrom: importFromCline
|
|
5693
6094
|
};
|
|
5694
|
-
var
|
|
6095
|
+
var descriptor8 = {
|
|
5695
6096
|
id: "cline",
|
|
5696
|
-
generators:
|
|
6097
|
+
generators: target8,
|
|
5697
6098
|
capabilities: {
|
|
5698
6099
|
rules: "native",
|
|
5699
6100
|
commands: "native",
|
|
@@ -5705,7 +6106,7 @@ var descriptor7 = {
|
|
|
5705
6106
|
permissions: "none"
|
|
5706
6107
|
},
|
|
5707
6108
|
emptyImportMessage: "No Cline config found (.clinerules, .clineignore, .cline/cline_mcp_settings.json, or .cline/skills).",
|
|
5708
|
-
lintRules:
|
|
6109
|
+
lintRules: lintRules8,
|
|
5709
6110
|
skillDir: ".cline/skills",
|
|
5710
6111
|
paths: {
|
|
5711
6112
|
rulePath(slug, _rule) {
|
|
@@ -5741,7 +6142,7 @@ function usesCursorSensitiveInterpolation(server) {
|
|
|
5741
6142
|
}
|
|
5742
6143
|
|
|
5743
6144
|
// src/targets/codex-cli/generator.ts
|
|
5744
|
-
import { basename as
|
|
6145
|
+
import { basename as basename21 } from "path";
|
|
5745
6146
|
|
|
5746
6147
|
// src/targets/codex-cli/constants.ts
|
|
5747
6148
|
var CODEX_TARGET = "codex-cli";
|
|
@@ -5767,9 +6168,9 @@ var CODEX_RULE_INDEX_START = "<!-- agentsmesh:codex-rule-index:start -->";
|
|
|
5767
6168
|
var CODEX_RULE_INDEX_END = "<!-- agentsmesh:codex-rule-index:end -->";
|
|
5768
6169
|
|
|
5769
6170
|
// src/targets/codex-cli/instruction-mirror.ts
|
|
5770
|
-
import { basename as
|
|
6171
|
+
import { basename as basename20 } from "path";
|
|
5771
6172
|
function ruleSlug4(source) {
|
|
5772
|
-
return
|
|
6173
|
+
return basename20(source, ".md");
|
|
5773
6174
|
}
|
|
5774
6175
|
function codexInstructionMirrorPath(rule) {
|
|
5775
6176
|
return `${CODEX_INSTRUCTIONS_DIR}/${ruleSlug4(rule.source)}.md`;
|
|
@@ -5804,7 +6205,7 @@ function summarizeRule(rule) {
|
|
|
5804
6205
|
scopes.push(`Enforced in \`${CODEX_RULES_DIR}/${ruleSlug4(rule.source)}.rules\`.`);
|
|
5805
6206
|
}
|
|
5806
6207
|
if (rule.targets.length > 0) {
|
|
5807
|
-
scopes.push(`Targeted to ${rule.targets.map((
|
|
6208
|
+
scopes.push(`Targeted to ${rule.targets.map((target13) => `\`${target13}\``).join(", ")}.`);
|
|
5808
6209
|
}
|
|
5809
6210
|
return scopes.join(" ");
|
|
5810
6211
|
}
|
|
@@ -5861,7 +6262,7 @@ function toSafeCodexRulesContent(body) {
|
|
|
5861
6262
|
return `${lines.join("\n")}
|
|
5862
6263
|
`;
|
|
5863
6264
|
}
|
|
5864
|
-
function
|
|
6265
|
+
function generateRules9(canonical) {
|
|
5865
6266
|
const root = canonical.rules.find((r) => r.root);
|
|
5866
6267
|
const outputs = [];
|
|
5867
6268
|
if (root) {
|
|
@@ -5869,7 +6270,7 @@ function generateRules8(canonical) {
|
|
|
5869
6270
|
}
|
|
5870
6271
|
for (const rule of canonical.rules) {
|
|
5871
6272
|
if (rule.root) continue;
|
|
5872
|
-
const slug =
|
|
6273
|
+
const slug = basename21(rule.source, ".md");
|
|
5873
6274
|
if (rule.targets.length > 0 && !rule.targets.includes("codex-cli")) continue;
|
|
5874
6275
|
if (rule.codexEmit === "execution") {
|
|
5875
6276
|
outputs.push({
|
|
@@ -5884,7 +6285,7 @@ function generateRules8(canonical) {
|
|
|
5884
6285
|
}
|
|
5885
6286
|
return outputs;
|
|
5886
6287
|
}
|
|
5887
|
-
function
|
|
6288
|
+
function generateSkills9(canonical) {
|
|
5888
6289
|
const outputs = [];
|
|
5889
6290
|
for (const skill of canonical.skills) {
|
|
5890
6291
|
const frontmatter = {
|
|
@@ -5949,7 +6350,7 @@ ${body}
|
|
|
5949
6350
|
}
|
|
5950
6351
|
return lines.join("\n") + "\n";
|
|
5951
6352
|
}
|
|
5952
|
-
function
|
|
6353
|
+
function generateMcp7(canonical) {
|
|
5953
6354
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
5954
6355
|
const stdioServers = Object.fromEntries(
|
|
5955
6356
|
Object.entries(canonical.mcp.mcpServers).flatMap(
|
|
@@ -5983,10 +6384,10 @@ function needsTomlQuoting(key) {
|
|
|
5983
6384
|
}
|
|
5984
6385
|
|
|
5985
6386
|
// src/targets/codex-cli/importer.ts
|
|
5986
|
-
import { join as
|
|
6387
|
+
import { join as join34, relative as relative12, dirname as dirname15, basename as basename22 } from "path";
|
|
5987
6388
|
|
|
5988
6389
|
// src/targets/codex-cli/import-codex-non-root-rules.ts
|
|
5989
|
-
import { join as
|
|
6390
|
+
import { join as join31, relative as relative10 } from "path";
|
|
5990
6391
|
|
|
5991
6392
|
// src/targets/codex-cli/codex-rules-embed.ts
|
|
5992
6393
|
import { Buffer } from "buffer";
|
|
@@ -6032,7 +6433,7 @@ function tryParseEmbeddedCanonicalFromCodexRules(content) {
|
|
|
6032
6433
|
// src/targets/codex-cli/import-codex-non-root-rules.ts
|
|
6033
6434
|
async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
6034
6435
|
const results = [];
|
|
6035
|
-
const codexRulesPath =
|
|
6436
|
+
const codexRulesPath = join31(projectRoot, CODEX_RULES_DIR);
|
|
6036
6437
|
try {
|
|
6037
6438
|
const ruleFiles = await readDirRecursive(codexRulesPath);
|
|
6038
6439
|
const mdFiles = ruleFiles.filter((f) => f.endsWith(".md"));
|
|
@@ -6040,7 +6441,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6040
6441
|
const content = await readFileSafe(srcPath);
|
|
6041
6442
|
if (!content) continue;
|
|
6042
6443
|
const relativePath = relative10(codexRulesPath, srcPath).replace(/\\/g, "/");
|
|
6043
|
-
const destPath =
|
|
6444
|
+
const destPath = join31(destDir, relativePath);
|
|
6044
6445
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
6045
6446
|
await mkdirp(destDir);
|
|
6046
6447
|
const outFm = frontmatter.root === true ? frontmatter : { ...frontmatter, root: false };
|
|
@@ -6058,7 +6459,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6058
6459
|
const raw = await readFileSafe(srcPath);
|
|
6059
6460
|
if (!raw) continue;
|
|
6060
6461
|
const relativePath = relative10(codexRulesPath, srcPath).replace(/\\/g, "/").replace(/\.rules$/i, ".md");
|
|
6061
|
-
const destPath =
|
|
6462
|
+
const destPath = join31(destDir, relativePath);
|
|
6062
6463
|
await mkdirp(destDir);
|
|
6063
6464
|
const embedded = tryParseEmbeddedCanonicalFromCodexRules(raw);
|
|
6064
6465
|
if (embedded) {
|
|
@@ -6098,7 +6499,7 @@ async function importCodexNonRootRuleFiles(projectRoot, destDir, normalize) {
|
|
|
6098
6499
|
}
|
|
6099
6500
|
|
|
6100
6501
|
// src/targets/codex-cli/mcp-helpers.ts
|
|
6101
|
-
import { join as
|
|
6502
|
+
import { join as join32 } from "path";
|
|
6102
6503
|
import { parse as parseToml4 } from "smol-toml";
|
|
6103
6504
|
function mapTomlServerToCanonical(raw) {
|
|
6104
6505
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return null;
|
|
@@ -6119,8 +6520,8 @@ function mapTomlServerToCanonical(raw) {
|
|
|
6119
6520
|
env
|
|
6120
6521
|
};
|
|
6121
6522
|
}
|
|
6122
|
-
async function
|
|
6123
|
-
const configPath =
|
|
6523
|
+
async function importMcp5(projectRoot, results) {
|
|
6524
|
+
const configPath = join32(projectRoot, CODEX_CONFIG_TOML);
|
|
6124
6525
|
const content = await readFileSafe(configPath);
|
|
6125
6526
|
if (content === null) return;
|
|
6126
6527
|
let parsed;
|
|
@@ -6139,9 +6540,9 @@ async function importMcp4(projectRoot, results) {
|
|
|
6139
6540
|
if (server) mcpServers[name] = server;
|
|
6140
6541
|
}
|
|
6141
6542
|
if (Object.keys(mcpServers).length === 0) return;
|
|
6142
|
-
await mkdirp(
|
|
6543
|
+
await mkdirp(join32(projectRoot, ".agentsmesh"));
|
|
6143
6544
|
await writeFileAtomic(
|
|
6144
|
-
|
|
6545
|
+
join32(projectRoot, CODEX_CANONICAL_MCP),
|
|
6145
6546
|
JSON.stringify({ mcpServers }, null, 2)
|
|
6146
6547
|
);
|
|
6147
6548
|
results.push({
|
|
@@ -6154,7 +6555,7 @@ async function importMcp4(projectRoot, results) {
|
|
|
6154
6555
|
|
|
6155
6556
|
// src/targets/codex-cli/skills-helpers.ts
|
|
6156
6557
|
import { readdir as readdir7 } from "fs/promises";
|
|
6157
|
-
import { join as
|
|
6558
|
+
import { join as join33, relative as relative11, dirname as dirname14 } from "path";
|
|
6158
6559
|
|
|
6159
6560
|
// src/targets/import/scoped-agents-import.ts
|
|
6160
6561
|
import { rm as rm5 } from "fs/promises";
|
|
@@ -6172,7 +6573,7 @@ async function removePathIfExists(path) {
|
|
|
6172
6573
|
// src/targets/codex-cli/skills-helpers.ts
|
|
6173
6574
|
async function importSkills3(projectRoot, results, normalize) {
|
|
6174
6575
|
for (const skillsRoot of [CODEX_SKILLS_DIR, CODEX_SKILLS_FALLBACK_DIR]) {
|
|
6175
|
-
const skillsDir =
|
|
6576
|
+
const skillsDir = join33(projectRoot, skillsRoot);
|
|
6176
6577
|
const entries = await readdir7(skillsDir, {
|
|
6177
6578
|
encoding: "utf8",
|
|
6178
6579
|
withFileTypes: true
|
|
@@ -6183,21 +6584,21 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6183
6584
|
let importedAny = false;
|
|
6184
6585
|
for (const ent of entries) {
|
|
6185
6586
|
if (!ent.isDirectory() && !ent.isSymbolicLink()) continue;
|
|
6186
|
-
const skillPath =
|
|
6187
|
-
const skillMdPath =
|
|
6587
|
+
const skillPath = join33(skillsDir, ent.name);
|
|
6588
|
+
const skillMdPath = join33(skillPath, "SKILL.md");
|
|
6188
6589
|
const skillMdContent = await readFileSafe(skillMdPath);
|
|
6189
6590
|
if (!skillMdContent) continue;
|
|
6190
6591
|
importedAny = true;
|
|
6191
6592
|
const skillName = ent.name;
|
|
6192
|
-
const destSkillPath =
|
|
6593
|
+
const destSkillPath = join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName, "SKILL.md");
|
|
6193
6594
|
const normalized = normalize(skillMdContent, skillMdPath, destSkillPath);
|
|
6194
6595
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
6195
6596
|
const command = parseCommandSkillFrontmatter(frontmatter, ent.name);
|
|
6196
6597
|
if (command) {
|
|
6197
|
-
await removePathIfExists(
|
|
6198
|
-
const destCommandsDir =
|
|
6598
|
+
await removePathIfExists(join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6599
|
+
const destCommandsDir = join33(projectRoot, CODEX_CANONICAL_COMMANDS_DIR);
|
|
6199
6600
|
await mkdirp(destCommandsDir);
|
|
6200
|
-
const commandPath =
|
|
6601
|
+
const commandPath = join33(destCommandsDir, `${command.name}.md`);
|
|
6201
6602
|
await writeFileAtomic(
|
|
6202
6603
|
commandPath,
|
|
6203
6604
|
serializeImportedCommand(command, normalize(body, skillMdPath, commandPath))
|
|
@@ -6212,10 +6613,10 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6212
6613
|
}
|
|
6213
6614
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(frontmatter, ent.name);
|
|
6214
6615
|
if (projectedAgent) {
|
|
6215
|
-
await removePathIfExists(
|
|
6216
|
-
const destAgentsDir =
|
|
6616
|
+
await removePathIfExists(join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6617
|
+
const destAgentsDir = join33(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
|
|
6217
6618
|
await mkdirp(destAgentsDir);
|
|
6218
|
-
const agentPath =
|
|
6619
|
+
const agentPath = join33(destAgentsDir, `${projectedAgent.name}.md`);
|
|
6219
6620
|
await writeFileAtomic(
|
|
6220
6621
|
agentPath,
|
|
6221
6622
|
serializeImportedAgent(projectedAgent, normalize(body, skillMdPath, agentPath))
|
|
@@ -6228,7 +6629,7 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6228
6629
|
});
|
|
6229
6630
|
continue;
|
|
6230
6631
|
}
|
|
6231
|
-
const destSkillDir =
|
|
6632
|
+
const destSkillDir = join33(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName);
|
|
6232
6633
|
await mkdirp(destSkillDir);
|
|
6233
6634
|
const outContent = await serializeImportedSkillWithFallback(
|
|
6234
6635
|
destSkillPath,
|
|
@@ -6248,7 +6649,7 @@ async function importSkills3(projectRoot, results, normalize) {
|
|
|
6248
6649
|
const relPath = relative11(skillPath, absPath).replace(/\\/g, "/");
|
|
6249
6650
|
const fileContent = await readFileSafe(absPath);
|
|
6250
6651
|
if (fileContent === null) continue;
|
|
6251
|
-
const destPath =
|
|
6652
|
+
const destPath = join33(destSkillDir, relPath);
|
|
6252
6653
|
await mkdirp(dirname14(destPath));
|
|
6253
6654
|
await writeFileAtomic(destPath, normalize(fileContent, absPath, destPath));
|
|
6254
6655
|
results.push({
|
|
@@ -6271,15 +6672,15 @@ async function importFromCodex(projectRoot) {
|
|
|
6271
6672
|
const results = [];
|
|
6272
6673
|
const normalize = await createImportReferenceNormalizer(CODEX_TARGET, projectRoot);
|
|
6273
6674
|
const normalizeWindsurf = await createImportReferenceNormalizer("windsurf", projectRoot);
|
|
6274
|
-
await
|
|
6675
|
+
await importRules5(projectRoot, results, normalize, normalizeWindsurf);
|
|
6275
6676
|
await importSkills3(projectRoot, results, normalize);
|
|
6276
6677
|
await importAgents4(projectRoot, results, normalize);
|
|
6277
|
-
await
|
|
6678
|
+
await importMcp5(projectRoot, results);
|
|
6278
6679
|
return results;
|
|
6279
6680
|
}
|
|
6280
6681
|
async function importAgents4(projectRoot, results, normalize) {
|
|
6281
|
-
const agentsPath =
|
|
6282
|
-
const agentsDestDir =
|
|
6682
|
+
const agentsPath = join34(projectRoot, CODEX_AGENTS_DIR);
|
|
6683
|
+
const agentsDestDir = join34(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
|
|
6283
6684
|
try {
|
|
6284
6685
|
const agentFiles = await readDirRecursive(agentsPath);
|
|
6285
6686
|
const tomlFiles = agentFiles.filter((f) => f.endsWith(".toml"));
|
|
@@ -6288,7 +6689,7 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6288
6689
|
if (!content) continue;
|
|
6289
6690
|
const parsed = parseToml5(content);
|
|
6290
6691
|
if (!parsed || typeof parsed !== "object") continue;
|
|
6291
|
-
const name = typeof parsed.name === "string" ? parsed.name :
|
|
6692
|
+
const name = typeof parsed.name === "string" ? parsed.name : basename22(srcPath, ".toml");
|
|
6292
6693
|
const description = typeof parsed.description === "string" ? parsed.description : "";
|
|
6293
6694
|
const body = typeof parsed.developer_instructions === "string" ? parsed.developer_instructions.trim() : "";
|
|
6294
6695
|
const model = typeof parsed.model === "string" ? parsed.model : "";
|
|
@@ -6296,7 +6697,7 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6296
6697
|
const permissionMode = sandbox === "read-only" ? "read-only" : sandbox === "workspace-write" ? "allow" : "";
|
|
6297
6698
|
const mcpServers = Array.isArray(parsed.mcp_servers) ? parsed.mcp_servers.filter((s) => typeof s === "string") : [];
|
|
6298
6699
|
await mkdirp(agentsDestDir);
|
|
6299
|
-
const destPath =
|
|
6700
|
+
const destPath = join34(agentsDestDir, `${name}.md`);
|
|
6300
6701
|
const normalizedBody = normalize(body, srcPath, destPath);
|
|
6301
6702
|
const agent = {
|
|
6302
6703
|
name,
|
|
@@ -6323,17 +6724,17 @@ async function importAgents4(projectRoot, results, normalize) {
|
|
|
6323
6724
|
} catch {
|
|
6324
6725
|
}
|
|
6325
6726
|
}
|
|
6326
|
-
async function
|
|
6327
|
-
const codexPath =
|
|
6328
|
-
const agentsPath =
|
|
6727
|
+
async function importRules5(projectRoot, results, normalize, normalizeWindsurf) {
|
|
6728
|
+
const codexPath = join34(projectRoot, CODEX_MD);
|
|
6729
|
+
const agentsPath = join34(projectRoot, AGENTS_MD);
|
|
6329
6730
|
const agentsContent = await readFileSafe(agentsPath);
|
|
6330
6731
|
const codexContent = await readFileSafe(codexPath);
|
|
6331
6732
|
const sourcePath = agentsContent !== null ? agentsPath : codexPath;
|
|
6332
|
-
const destDir =
|
|
6733
|
+
const destDir = join34(projectRoot, CODEX_CANONICAL_RULES_DIR);
|
|
6333
6734
|
const content = agentsContent ?? codexContent;
|
|
6334
6735
|
if (content !== null) {
|
|
6335
6736
|
await mkdirp(destDir);
|
|
6336
|
-
const destPath =
|
|
6737
|
+
const destPath = join34(destDir, "_root.md");
|
|
6337
6738
|
const stripped = sourcePath === agentsPath ? stripCodexRuleIndex(content) : content;
|
|
6338
6739
|
const normalizedContent = sourcePath === agentsPath ? normalize(normalizeWindsurf(stripped, sourcePath, destPath), sourcePath, destPath) : normalize(stripped, sourcePath, destPath);
|
|
6339
6740
|
const { frontmatter, body } = parseFrontmatter(normalizedContent);
|
|
@@ -6363,10 +6764,10 @@ async function importRules4(projectRoot, results, normalize, normalizeWindsurf)
|
|
|
6363
6764
|
if (!isOverride && !srcPath.endsWith("/AGENTS.md")) return null;
|
|
6364
6765
|
const ruleName = relDir.replace(/\//g, "-");
|
|
6365
6766
|
if (!shouldImportScopedAgentsRule(relDir)) {
|
|
6366
|
-
await removePathIfExists(
|
|
6767
|
+
await removePathIfExists(join34(destDir, `${ruleName}.md`));
|
|
6367
6768
|
return null;
|
|
6368
6769
|
}
|
|
6369
|
-
const destPath =
|
|
6770
|
+
const destPath = join34(destDir, `${ruleName}.md`);
|
|
6370
6771
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
6371
6772
|
return {
|
|
6372
6773
|
destPath,
|
|
@@ -6389,15 +6790,15 @@ async function importRules4(projectRoot, results, normalize, normalizeWindsurf)
|
|
|
6389
6790
|
}
|
|
6390
6791
|
async function importInstructionMirrors(projectRoot, destDir, results, normalize) {
|
|
6391
6792
|
try {
|
|
6392
|
-
const files = await readDirRecursive(
|
|
6793
|
+
const files = await readDirRecursive(join34(projectRoot, CODEX_INSTRUCTIONS_DIR));
|
|
6393
6794
|
const instructionFiles = files.filter((file) => file.endsWith(".md"));
|
|
6394
|
-
const instructionsRoot =
|
|
6795
|
+
const instructionsRoot = join34(projectRoot, CODEX_INSTRUCTIONS_DIR);
|
|
6395
6796
|
for (const srcPath of instructionFiles) {
|
|
6396
6797
|
const relativePath = relative12(instructionsRoot, srcPath).replace(/\\/g, "/");
|
|
6397
6798
|
if (relativePath === "_root.md") continue;
|
|
6398
6799
|
const content = await readFileSafe(srcPath);
|
|
6399
6800
|
if (!content) continue;
|
|
6400
|
-
const destPath =
|
|
6801
|
+
const destPath = join34(destDir, relativePath);
|
|
6401
6802
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
6402
6803
|
await mkdirp(destDir);
|
|
6403
6804
|
const outFm = frontmatter.root === true ? frontmatter : { ...frontmatter, root: false };
|
|
@@ -6416,7 +6817,7 @@ async function importInstructionMirrors(projectRoot, destDir, results, normalize
|
|
|
6416
6817
|
|
|
6417
6818
|
// src/targets/codex-cli/linter.ts
|
|
6418
6819
|
import { relative as relative13 } from "path";
|
|
6419
|
-
function
|
|
6820
|
+
function lintRules9(canonical, projectRoot, _projectFiles) {
|
|
6420
6821
|
const { rules } = canonical;
|
|
6421
6822
|
if (rules.length === 0) return [];
|
|
6422
6823
|
const hasRoot = rules.some((r) => r.root);
|
|
@@ -6439,19 +6840,19 @@ function codexAdvisoryInstructionPath(rule) {
|
|
|
6439
6840
|
}
|
|
6440
6841
|
|
|
6441
6842
|
// src/targets/codex-cli/index.ts
|
|
6442
|
-
var
|
|
6843
|
+
var target9 = {
|
|
6443
6844
|
name: "codex-cli",
|
|
6444
6845
|
primaryRootInstructionPath: AGENTS_MD,
|
|
6445
|
-
generateRules:
|
|
6846
|
+
generateRules: generateRules9,
|
|
6446
6847
|
generateCommands: generateCommands7,
|
|
6447
6848
|
generateAgents: generateAgents7,
|
|
6448
|
-
generateSkills:
|
|
6449
|
-
generateMcp:
|
|
6849
|
+
generateSkills: generateSkills9,
|
|
6850
|
+
generateMcp: generateMcp7,
|
|
6450
6851
|
importFrom: importFromCodex
|
|
6451
6852
|
};
|
|
6452
|
-
var
|
|
6853
|
+
var descriptor9 = {
|
|
6453
6854
|
id: "codex-cli",
|
|
6454
|
-
generators:
|
|
6855
|
+
generators: target9,
|
|
6455
6856
|
capabilities: {
|
|
6456
6857
|
rules: "native",
|
|
6457
6858
|
commands: "embedded",
|
|
@@ -6463,7 +6864,7 @@ var descriptor8 = {
|
|
|
6463
6864
|
permissions: "none"
|
|
6464
6865
|
},
|
|
6465
6866
|
emptyImportMessage: "No Codex config found (codex.md or AGENTS.md).",
|
|
6466
|
-
lintRules:
|
|
6867
|
+
lintRules: lintRules9,
|
|
6467
6868
|
skillDir: ".agents/skills",
|
|
6468
6869
|
paths: {
|
|
6469
6870
|
rulePath(_slug, rule) {
|
|
@@ -6481,7 +6882,7 @@ var descriptor8 = {
|
|
|
6481
6882
|
};
|
|
6482
6883
|
|
|
6483
6884
|
// src/targets/windsurf/generator.ts
|
|
6484
|
-
import { basename as
|
|
6885
|
+
import { basename as basename23 } from "path";
|
|
6485
6886
|
|
|
6486
6887
|
// src/targets/windsurf/constants.ts
|
|
6487
6888
|
var WINDSURF_TARGET = "windsurf";
|
|
@@ -6505,7 +6906,7 @@ var WINDSURF_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
|
6505
6906
|
|
|
6506
6907
|
// src/targets/windsurf/generator.ts
|
|
6507
6908
|
function ruleSlug5(source) {
|
|
6508
|
-
const name =
|
|
6909
|
+
const name = basename23(source, ".md");
|
|
6509
6910
|
return name === "_root" ? "root" : name;
|
|
6510
6911
|
}
|
|
6511
6912
|
function directoryScopedRuleDir(globs) {
|
|
@@ -6514,7 +6915,7 @@ function directoryScopedRuleDir(globs) {
|
|
|
6514
6915
|
if (dirs.length !== globs.length) return null;
|
|
6515
6916
|
return dirs.every((dir) => dir === dirs[0]) ? dirs[0] : null;
|
|
6516
6917
|
}
|
|
6517
|
-
function
|
|
6918
|
+
function generateRules10(canonical) {
|
|
6518
6919
|
const outputs = [];
|
|
6519
6920
|
const root = canonical.rules.find((r) => r.root);
|
|
6520
6921
|
if (!root) return [];
|
|
@@ -6548,7 +6949,7 @@ function generateRules9(canonical) {
|
|
|
6548
6949
|
}
|
|
6549
6950
|
return outputs;
|
|
6550
6951
|
}
|
|
6551
|
-
function
|
|
6952
|
+
function generateIgnore7(canonical) {
|
|
6552
6953
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
6553
6954
|
return [{ path: CODEIUM_IGNORE, content: canonical.ignore.join("\n") }];
|
|
6554
6955
|
}
|
|
@@ -6574,7 +6975,7 @@ function generateAgents8(canonical) {
|
|
|
6574
6975
|
content: serializeProjectedAgentSkill(agent)
|
|
6575
6976
|
}));
|
|
6576
6977
|
}
|
|
6577
|
-
function
|
|
6978
|
+
function generateMcp8(canonical) {
|
|
6578
6979
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
6579
6980
|
return [
|
|
6580
6981
|
{
|
|
@@ -6612,13 +7013,13 @@ function toWindsurfHooks(hooks) {
|
|
|
6612
7013
|
}
|
|
6613
7014
|
return result;
|
|
6614
7015
|
}
|
|
6615
|
-
function
|
|
7016
|
+
function generateHooks6(canonical) {
|
|
6616
7017
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
6617
7018
|
const hooks = toWindsurfHooks(canonical.hooks);
|
|
6618
7019
|
if (Object.keys(hooks).length === 0) return [];
|
|
6619
7020
|
return [{ path: WINDSURF_HOOKS_FILE, content: JSON.stringify({ hooks }, null, 2) }];
|
|
6620
7021
|
}
|
|
6621
|
-
function
|
|
7022
|
+
function generateSkills10(canonical) {
|
|
6622
7023
|
const outputs = [];
|
|
6623
7024
|
for (const skill of canonical.skills) {
|
|
6624
7025
|
const frontmatter = {
|
|
@@ -6639,11 +7040,11 @@ function generateSkills9(canonical) {
|
|
|
6639
7040
|
}
|
|
6640
7041
|
|
|
6641
7042
|
// src/targets/windsurf/importer.ts
|
|
6642
|
-
import { join as
|
|
6643
|
-
import { stringify as
|
|
7043
|
+
import { join as join36, dirname as dirname16, relative as relative15 } from "path";
|
|
7044
|
+
import { stringify as yamlStringify5 } from "yaml";
|
|
6644
7045
|
|
|
6645
7046
|
// src/targets/windsurf/workflows-skills-helpers.ts
|
|
6646
|
-
import { join as
|
|
7047
|
+
import { join as join35, relative as relative14 } from "path";
|
|
6647
7048
|
import { readdir as readdir8 } from "fs/promises";
|
|
6648
7049
|
function toStringArray7(value) {
|
|
6649
7050
|
if (Array.isArray(value)) {
|
|
@@ -6655,16 +7056,16 @@ function toStringArray7(value) {
|
|
|
6655
7056
|
return [];
|
|
6656
7057
|
}
|
|
6657
7058
|
async function importWorkflows(projectRoot, results, normalize) {
|
|
6658
|
-
const workflowsDir =
|
|
7059
|
+
const workflowsDir = join35(projectRoot, WINDSURF_WORKFLOWS_DIR);
|
|
6659
7060
|
const workflowFiles = await readDirRecursive(workflowsDir);
|
|
6660
7061
|
const workflowMdFiles = workflowFiles.filter((f) => f.endsWith(".md"));
|
|
6661
|
-
const destCommandsDir =
|
|
7062
|
+
const destCommandsDir = join35(projectRoot, WINDSURF_CANONICAL_COMMANDS_DIR);
|
|
6662
7063
|
for (const srcPath of workflowMdFiles) {
|
|
6663
7064
|
const content = await readFileSafe(srcPath);
|
|
6664
7065
|
if (!content) continue;
|
|
6665
7066
|
const relativePath = relative14(workflowsDir, srcPath).replace(/\\/g, "/");
|
|
6666
7067
|
await mkdirp(destCommandsDir);
|
|
6667
|
-
const destPath =
|
|
7068
|
+
const destPath = join35(destCommandsDir, relativePath);
|
|
6668
7069
|
const normalized = normalize(content, srcPath, destPath);
|
|
6669
7070
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
6670
7071
|
const outContent = await serializeImportedCommandWithFallback(
|
|
@@ -6690,22 +7091,22 @@ async function importWorkflows(projectRoot, results, normalize) {
|
|
|
6690
7091
|
}
|
|
6691
7092
|
}
|
|
6692
7093
|
async function importSkills4(projectRoot, results, normalize) {
|
|
6693
|
-
const windsurfSkillsBaseDir =
|
|
7094
|
+
const windsurfSkillsBaseDir = join35(projectRoot, WINDSURF_SKILLS_DIR);
|
|
6694
7095
|
try {
|
|
6695
7096
|
const skillEntries = await readdir8(windsurfSkillsBaseDir, { withFileTypes: true });
|
|
6696
7097
|
for (const ent of skillEntries) {
|
|
6697
7098
|
if (!ent.isDirectory()) continue;
|
|
6698
|
-
const skillPath =
|
|
6699
|
-
const skillMdPath =
|
|
7099
|
+
const skillPath = join35(windsurfSkillsBaseDir, ent.name);
|
|
7100
|
+
const skillMdPath = join35(skillPath, "SKILL.md");
|
|
6700
7101
|
const skillContent = await readFileSafe(skillMdPath);
|
|
6701
7102
|
if (!skillContent) continue;
|
|
6702
7103
|
const rawParsed = parseFrontmatter(skillContent);
|
|
6703
7104
|
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, ent.name);
|
|
6704
7105
|
if (projectedAgent) {
|
|
6705
|
-
await removePathIfExists(
|
|
6706
|
-
const destAgentsDir =
|
|
7106
|
+
await removePathIfExists(join35(projectRoot, WINDSURF_CANONICAL_SKILLS_DIR, ent.name));
|
|
7107
|
+
const destAgentsDir = join35(projectRoot, WINDSURF_CANONICAL_AGENTS_DIR);
|
|
6707
7108
|
await mkdirp(destAgentsDir);
|
|
6708
|
-
const agentPath =
|
|
7109
|
+
const agentPath = join35(destAgentsDir, `${projectedAgent.name}.md`);
|
|
6709
7110
|
await writeFileAtomic(
|
|
6710
7111
|
agentPath,
|
|
6711
7112
|
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
@@ -6718,8 +7119,8 @@ async function importSkills4(projectRoot, results, normalize) {
|
|
|
6718
7119
|
});
|
|
6719
7120
|
continue;
|
|
6720
7121
|
}
|
|
6721
|
-
const destSkillDir =
|
|
6722
|
-
const destSkillPath =
|
|
7122
|
+
const destSkillDir = join35(projectRoot, WINDSURF_CANONICAL_SKILLS_DIR, ent.name);
|
|
7123
|
+
const destSkillPath = join35(destSkillDir, "SKILL.md");
|
|
6723
7124
|
const normalized = normalize(skillContent, skillMdPath, destSkillPath);
|
|
6724
7125
|
await mkdirp(destSkillDir);
|
|
6725
7126
|
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
@@ -6743,8 +7144,8 @@ async function importSkills4(projectRoot, results, normalize) {
|
|
|
6743
7144
|
const relPath = absPath.slice(skillPath.length + 1).replace(/\\/g, "/");
|
|
6744
7145
|
const supportContent = await readFileSafe(absPath);
|
|
6745
7146
|
if (supportContent === null) continue;
|
|
6746
|
-
const destSupportPath =
|
|
6747
|
-
await mkdirp(
|
|
7147
|
+
const destSupportPath = join35(destSkillDir, relPath);
|
|
7148
|
+
await mkdirp(join35(destSupportPath, ".."));
|
|
6748
7149
|
await writeFileAtomic(destSupportPath, normalize(supportContent, absPath, destSupportPath));
|
|
6749
7150
|
results.push({
|
|
6750
7151
|
fromTool: WINDSURF_TARGET,
|
|
@@ -6763,12 +7164,12 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6763
7164
|
const results = [];
|
|
6764
7165
|
const normalize = await createImportReferenceNormalizer(WINDSURF_TARGET, projectRoot);
|
|
6765
7166
|
const normalizeCodex = await createImportReferenceNormalizer("codex-cli", projectRoot);
|
|
6766
|
-
const destRulesDir =
|
|
6767
|
-
const rootPath =
|
|
7167
|
+
const destRulesDir = join36(projectRoot, WINDSURF_CANONICAL_RULES_DIR);
|
|
7168
|
+
const rootPath = join36(projectRoot, WINDSURF_RULES_ROOT);
|
|
6768
7169
|
const rootContent = await readFileSafe(rootPath);
|
|
6769
7170
|
if (rootContent !== null) {
|
|
6770
7171
|
await mkdirp(destRulesDir);
|
|
6771
|
-
const destPath =
|
|
7172
|
+
const destPath = join36(destRulesDir, "_root.md");
|
|
6772
7173
|
const body = normalize(rootContent, rootPath, destPath).trim();
|
|
6773
7174
|
const outContent = await serializeImportedRuleWithFallback(destPath, { root: true }, body);
|
|
6774
7175
|
await writeFileAtomic(destPath, outContent);
|
|
@@ -6780,11 +7181,11 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6780
7181
|
});
|
|
6781
7182
|
}
|
|
6782
7183
|
if (rootContent === null) {
|
|
6783
|
-
const agentsMdPath =
|
|
7184
|
+
const agentsMdPath = join36(projectRoot, WINDSURF_AGENTS_MD);
|
|
6784
7185
|
const agentsMdContent = await readFileSafe(agentsMdPath);
|
|
6785
7186
|
if (agentsMdContent !== null) {
|
|
6786
7187
|
await mkdirp(destRulesDir);
|
|
6787
|
-
const destPath =
|
|
7188
|
+
const destPath = join36(destRulesDir, "_root.md");
|
|
6788
7189
|
const body = normalize(
|
|
6789
7190
|
normalizeCodex(agentsMdContent, agentsMdPath, destPath),
|
|
6790
7191
|
agentsMdPath,
|
|
@@ -6812,10 +7213,10 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6812
7213
|
if (!relDir || relDir === "." || !srcPath.endsWith("/AGENTS.md")) return null;
|
|
6813
7214
|
const ruleName = relDir.replace(/\//g, "-");
|
|
6814
7215
|
if (!shouldImportScopedAgentsRule(relDir)) {
|
|
6815
|
-
await removePathIfExists(
|
|
7216
|
+
await removePathIfExists(join36(destRulesDir, `${ruleName}.md`));
|
|
6816
7217
|
return null;
|
|
6817
7218
|
}
|
|
6818
|
-
const destPath =
|
|
7219
|
+
const destPath = join36(destRulesDir, `${ruleName}.md`);
|
|
6819
7220
|
return {
|
|
6820
7221
|
destPath,
|
|
6821
7222
|
toPath: `${WINDSURF_CANONICAL_RULES_DIR}/${ruleName}.md`,
|
|
@@ -6829,7 +7230,7 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6829
7230
|
}
|
|
6830
7231
|
})
|
|
6831
7232
|
);
|
|
6832
|
-
const rulesDir =
|
|
7233
|
+
const rulesDir = join36(projectRoot, WINDSURF_RULES_DIR);
|
|
6833
7234
|
results.push(
|
|
6834
7235
|
...await importFileDirectory({
|
|
6835
7236
|
srcDir: rulesDir,
|
|
@@ -6839,7 +7240,7 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6839
7240
|
normalize,
|
|
6840
7241
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
6841
7242
|
if (relativePath === "_root.md" && rootContent !== null) return null;
|
|
6842
|
-
const destPath =
|
|
7243
|
+
const destPath = join36(destRulesDir, relativePath);
|
|
6843
7244
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
6844
7245
|
const normalizedFrontmatter = { ...frontmatter };
|
|
6845
7246
|
if (typeof normalizedFrontmatter.glob === "string" && normalizedFrontmatter.glob.trim()) {
|
|
@@ -6859,10 +7260,10 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6859
7260
|
}
|
|
6860
7261
|
})
|
|
6861
7262
|
);
|
|
6862
|
-
let ignorePath =
|
|
7263
|
+
let ignorePath = join36(projectRoot, WINDSURF_IGNORE);
|
|
6863
7264
|
let ignoreContent = await readFileSafe(ignorePath);
|
|
6864
7265
|
if (ignoreContent === null || !ignoreContent.trim()) {
|
|
6865
|
-
ignorePath =
|
|
7266
|
+
ignorePath = join36(projectRoot, CODEIUM_IGNORE);
|
|
6866
7267
|
ignoreContent = await readFileSafe(ignorePath);
|
|
6867
7268
|
}
|
|
6868
7269
|
if (ignoreContent !== null && ignoreContent.trim()) {
|
|
@@ -6873,8 +7274,8 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6873
7274
|
if (t && !t.startsWith("#")) patterns.push(t);
|
|
6874
7275
|
}
|
|
6875
7276
|
if (patterns.length > 0) {
|
|
6876
|
-
await mkdirp(
|
|
6877
|
-
const destIgnorePath =
|
|
7277
|
+
await mkdirp(join36(projectRoot, ".agentsmesh"));
|
|
7278
|
+
const destIgnorePath = join36(projectRoot, WINDSURF_CANONICAL_IGNORE);
|
|
6878
7279
|
await writeFileAtomic(destIgnorePath, patterns.join("\n"));
|
|
6879
7280
|
results.push({
|
|
6880
7281
|
fromTool: "windsurf",
|
|
@@ -6886,12 +7287,12 @@ async function importFromWindsurf(projectRoot) {
|
|
|
6886
7287
|
}
|
|
6887
7288
|
await importWorkflows(projectRoot, results, normalize);
|
|
6888
7289
|
await importSkills4(projectRoot, results, normalize);
|
|
6889
|
-
await
|
|
6890
|
-
await
|
|
7290
|
+
await importHooks3(projectRoot, results);
|
|
7291
|
+
await importMcp6(projectRoot, results);
|
|
6891
7292
|
return results;
|
|
6892
7293
|
}
|
|
6893
|
-
async function
|
|
6894
|
-
const hooksPath =
|
|
7294
|
+
async function importHooks3(projectRoot, results) {
|
|
7295
|
+
const hooksPath = join36(projectRoot, WINDSURF_HOOKS_FILE);
|
|
6895
7296
|
const hooksContent = await readFileSafe(hooksPath);
|
|
6896
7297
|
if (!hooksContent) return;
|
|
6897
7298
|
try {
|
|
@@ -6899,9 +7300,9 @@ async function importHooks2(projectRoot, results) {
|
|
|
6899
7300
|
if (!parsed.hooks || typeof parsed.hooks !== "object" || Array.isArray(parsed.hooks)) return;
|
|
6900
7301
|
const canonical = windsurfHooksToCanonical(parsed.hooks);
|
|
6901
7302
|
if (Object.keys(canonical).length === 0) return;
|
|
6902
|
-
const destPath =
|
|
7303
|
+
const destPath = join36(projectRoot, WINDSURF_CANONICAL_HOOKS);
|
|
6903
7304
|
await mkdirp(dirname16(destPath));
|
|
6904
|
-
await writeFileAtomic(destPath,
|
|
7305
|
+
await writeFileAtomic(destPath, yamlStringify5(canonical));
|
|
6905
7306
|
results.push({
|
|
6906
7307
|
fromTool: WINDSURF_TARGET,
|
|
6907
7308
|
fromPath: hooksPath,
|
|
@@ -6959,16 +7360,16 @@ function windsurfHooksToCanonical(hooks) {
|
|
|
6959
7360
|
}
|
|
6960
7361
|
return result;
|
|
6961
7362
|
}
|
|
6962
|
-
async function
|
|
7363
|
+
async function importMcp6(projectRoot, results) {
|
|
6963
7364
|
const sourceCandidates = [WINDSURF_MCP_EXAMPLE_FILE, WINDSURF_MCP_CONFIG_FILE];
|
|
6964
7365
|
for (const relPath of sourceCandidates) {
|
|
6965
|
-
const srcPath =
|
|
7366
|
+
const srcPath = join36(projectRoot, relPath);
|
|
6966
7367
|
const content = await readFileSafe(srcPath);
|
|
6967
7368
|
if (!content) continue;
|
|
6968
7369
|
try {
|
|
6969
7370
|
const parsed = JSON.parse(content);
|
|
6970
7371
|
if (!parsed.mcpServers || typeof parsed.mcpServers !== "object") continue;
|
|
6971
|
-
const destPath =
|
|
7372
|
+
const destPath = join36(projectRoot, WINDSURF_CANONICAL_MCP);
|
|
6972
7373
|
await mkdirp(dirname16(destPath));
|
|
6973
7374
|
await writeFileAtomic(destPath, JSON.stringify({ mcpServers: parsed.mcpServers }, null, 2));
|
|
6974
7375
|
results.push({
|
|
@@ -6985,7 +7386,7 @@ async function importMcp5(projectRoot, results) {
|
|
|
6985
7386
|
|
|
6986
7387
|
// src/targets/windsurf/linter.ts
|
|
6987
7388
|
import { relative as relative16 } from "path";
|
|
6988
|
-
function
|
|
7389
|
+
function lintRules10(canonical, projectRoot, _projectFiles) {
|
|
6989
7390
|
const diags = [];
|
|
6990
7391
|
const { rules } = canonical;
|
|
6991
7392
|
if (rules.length > 0) {
|
|
@@ -7014,21 +7415,21 @@ function lintRules9(canonical, projectRoot, _projectFiles) {
|
|
|
7014
7415
|
}
|
|
7015
7416
|
|
|
7016
7417
|
// src/targets/windsurf/index.ts
|
|
7017
|
-
var
|
|
7418
|
+
var target10 = {
|
|
7018
7419
|
name: "windsurf",
|
|
7019
7420
|
primaryRootInstructionPath: WINDSURF_AGENTS_MD,
|
|
7020
|
-
generateRules:
|
|
7421
|
+
generateRules: generateRules10,
|
|
7021
7422
|
generateWorkflows: generateWorkflows2,
|
|
7022
7423
|
generateAgents: generateAgents8,
|
|
7023
|
-
generateSkills:
|
|
7024
|
-
generateMcp:
|
|
7025
|
-
generateHooks:
|
|
7026
|
-
generateIgnore:
|
|
7424
|
+
generateSkills: generateSkills10,
|
|
7425
|
+
generateMcp: generateMcp8,
|
|
7426
|
+
generateHooks: generateHooks6,
|
|
7427
|
+
generateIgnore: generateIgnore7,
|
|
7027
7428
|
importFrom: importFromWindsurf
|
|
7028
7429
|
};
|
|
7029
|
-
var
|
|
7430
|
+
var descriptor10 = {
|
|
7030
7431
|
id: "windsurf",
|
|
7031
|
-
generators:
|
|
7432
|
+
generators: target10,
|
|
7032
7433
|
capabilities: {
|
|
7033
7434
|
rules: "native",
|
|
7034
7435
|
commands: "native",
|
|
@@ -7040,7 +7441,7 @@ var descriptor9 = {
|
|
|
7040
7441
|
permissions: "none"
|
|
7041
7442
|
},
|
|
7042
7443
|
emptyImportMessage: "No Windsurf config found (.windsurfrules, .windsurf/rules, .windsurfignore, or .codeiumignore).",
|
|
7043
|
-
lintRules:
|
|
7444
|
+
lintRules: lintRules10,
|
|
7044
7445
|
skillDir: ".windsurf/skills",
|
|
7045
7446
|
paths: {
|
|
7046
7447
|
rulePath(slug, _rule) {
|
|
@@ -7058,8 +7459,8 @@ var descriptor9 = {
|
|
|
7058
7459
|
};
|
|
7059
7460
|
|
|
7060
7461
|
// src/targets/antigravity/generator.ts
|
|
7061
|
-
import { basename as
|
|
7062
|
-
function
|
|
7462
|
+
import { basename as basename24 } from "path";
|
|
7463
|
+
function generateRules11(canonical) {
|
|
7063
7464
|
const root = canonical.rules.find((r) => r.root);
|
|
7064
7465
|
if (!root) return [];
|
|
7065
7466
|
const outputs = [
|
|
@@ -7068,7 +7469,7 @@ function generateRules10(canonical) {
|
|
|
7068
7469
|
for (const rule of canonical.rules) {
|
|
7069
7470
|
if (rule.root) continue;
|
|
7070
7471
|
if (rule.targets.length > 0 && !rule.targets.includes("antigravity")) continue;
|
|
7071
|
-
const slug =
|
|
7472
|
+
const slug = basename24(rule.source, ".md");
|
|
7072
7473
|
outputs.push({
|
|
7073
7474
|
path: `${ANTIGRAVITY_RULES_DIR}/${slug}.md`,
|
|
7074
7475
|
content: rule.body.trim() || ""
|
|
@@ -7089,15 +7490,15 @@ ${body}` : body || intro;
|
|
|
7089
7490
|
};
|
|
7090
7491
|
});
|
|
7091
7492
|
}
|
|
7092
|
-
function
|
|
7493
|
+
function generateSkills11(canonical) {
|
|
7093
7494
|
return generateEmbeddedSkills(canonical, ANTIGRAVITY_SKILLS_DIR);
|
|
7094
7495
|
}
|
|
7095
7496
|
|
|
7096
7497
|
// src/targets/antigravity/importer.ts
|
|
7097
|
-
import { basename as
|
|
7498
|
+
import { basename as basename25, join as join37 } from "path";
|
|
7098
7499
|
async function importRootRule(projectRoot, results, normalize) {
|
|
7099
|
-
const primary =
|
|
7100
|
-
const legacy =
|
|
7500
|
+
const primary = join37(projectRoot, ANTIGRAVITY_RULES_ROOT);
|
|
7501
|
+
const legacy = join37(projectRoot, ANTIGRAVITY_RULES_ROOT_LEGACY);
|
|
7101
7502
|
let srcPath = primary;
|
|
7102
7503
|
let content = await readFileSafe(primary);
|
|
7103
7504
|
if (content === null) {
|
|
@@ -7105,10 +7506,10 @@ async function importRootRule(projectRoot, results, normalize) {
|
|
|
7105
7506
|
content = await readFileSafe(legacy);
|
|
7106
7507
|
}
|
|
7107
7508
|
if (content === null) return;
|
|
7108
|
-
const destPath =
|
|
7509
|
+
const destPath = join37(projectRoot, ANTIGRAVITY_CANONICAL_ROOT_RULE);
|
|
7109
7510
|
const { body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
7110
7511
|
const output = await serializeImportedRuleWithFallback(destPath, { root: true }, body);
|
|
7111
|
-
await mkdirp(
|
|
7512
|
+
await mkdirp(join37(projectRoot, ANTIGRAVITY_CANONICAL_RULES_DIR));
|
|
7112
7513
|
await writeFileAtomic(destPath, output);
|
|
7113
7514
|
results.push({
|
|
7114
7515
|
fromTool: ANTIGRAVITY_TARGET,
|
|
@@ -7118,8 +7519,8 @@ async function importRootRule(projectRoot, results, normalize) {
|
|
|
7118
7519
|
});
|
|
7119
7520
|
}
|
|
7120
7521
|
async function importNonRootRules2(projectRoot, results, normalize) {
|
|
7121
|
-
const srcDir =
|
|
7122
|
-
const destDir =
|
|
7522
|
+
const srcDir = join37(projectRoot, ANTIGRAVITY_RULES_DIR);
|
|
7523
|
+
const destDir = join37(projectRoot, ANTIGRAVITY_CANONICAL_RULES_DIR);
|
|
7123
7524
|
results.push(
|
|
7124
7525
|
...await importFileDirectory({
|
|
7125
7526
|
srcDir,
|
|
@@ -7128,9 +7529,9 @@ async function importNonRootRules2(projectRoot, results, normalize) {
|
|
|
7128
7529
|
fromTool: ANTIGRAVITY_TARGET,
|
|
7129
7530
|
normalize,
|
|
7130
7531
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7131
|
-
if (
|
|
7532
|
+
if (basename25(relativePath) === "general.md" || basename25(relativePath) === "_root.md")
|
|
7132
7533
|
return null;
|
|
7133
|
-
const destPath =
|
|
7534
|
+
const destPath = join37(destDir, relativePath);
|
|
7134
7535
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7135
7536
|
const output = await serializeImportedRuleWithFallback(
|
|
7136
7537
|
destPath,
|
|
@@ -7152,8 +7553,8 @@ async function importNonRootRules2(projectRoot, results, normalize) {
|
|
|
7152
7553
|
);
|
|
7153
7554
|
}
|
|
7154
7555
|
async function importWorkflows2(projectRoot, results, normalize) {
|
|
7155
|
-
const srcDir =
|
|
7156
|
-
const destDir =
|
|
7556
|
+
const srcDir = join37(projectRoot, ANTIGRAVITY_WORKFLOWS_DIR);
|
|
7557
|
+
const destDir = join37(projectRoot, ANTIGRAVITY_CANONICAL_COMMANDS_DIR);
|
|
7157
7558
|
results.push(
|
|
7158
7559
|
...await importFileDirectory({
|
|
7159
7560
|
srcDir,
|
|
@@ -7162,7 +7563,7 @@ async function importWorkflows2(projectRoot, results, normalize) {
|
|
|
7162
7563
|
fromTool: ANTIGRAVITY_TARGET,
|
|
7163
7564
|
normalize,
|
|
7164
7565
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7165
|
-
const destPath =
|
|
7566
|
+
const destPath = join37(destDir, relativePath);
|
|
7166
7567
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7167
7568
|
const normalized = await serializeImportedCommandWithFallback(
|
|
7168
7569
|
destPath,
|
|
@@ -7201,7 +7602,7 @@ async function importFromAntigravity(projectRoot) {
|
|
|
7201
7602
|
}
|
|
7202
7603
|
|
|
7203
7604
|
// src/targets/antigravity/linter.ts
|
|
7204
|
-
function
|
|
7605
|
+
function lintRules11(canonical, projectRoot, projectFiles) {
|
|
7205
7606
|
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
7206
7607
|
...diagnostic,
|
|
7207
7608
|
target: ANTIGRAVITY_TARGET
|
|
@@ -7209,17 +7610,17 @@ function lintRules10(canonical, projectRoot, projectFiles) {
|
|
|
7209
7610
|
}
|
|
7210
7611
|
|
|
7211
7612
|
// src/targets/antigravity/index.ts
|
|
7212
|
-
var
|
|
7613
|
+
var target11 = {
|
|
7213
7614
|
name: "antigravity",
|
|
7214
7615
|
primaryRootInstructionPath: ANTIGRAVITY_RULES_ROOT,
|
|
7215
|
-
generateRules:
|
|
7616
|
+
generateRules: generateRules11,
|
|
7216
7617
|
generateCommands: generateWorkflows3,
|
|
7217
|
-
generateSkills:
|
|
7618
|
+
generateSkills: generateSkills11,
|
|
7218
7619
|
importFrom: importFromAntigravity
|
|
7219
7620
|
};
|
|
7220
|
-
var
|
|
7621
|
+
var descriptor11 = {
|
|
7221
7622
|
id: "antigravity",
|
|
7222
|
-
generators:
|
|
7623
|
+
generators: target11,
|
|
7223
7624
|
capabilities: {
|
|
7224
7625
|
rules: "native",
|
|
7225
7626
|
commands: "partial",
|
|
@@ -7231,7 +7632,7 @@ var descriptor10 = {
|
|
|
7231
7632
|
permissions: "none"
|
|
7232
7633
|
},
|
|
7233
7634
|
emptyImportMessage: "No Antigravity config found (.agents/rules/, .agents/skills/, or .agents/workflows/).",
|
|
7234
|
-
lintRules:
|
|
7635
|
+
lintRules: lintRules11,
|
|
7235
7636
|
skillDir: ".agents/skills",
|
|
7236
7637
|
paths: {
|
|
7237
7638
|
rulePath(slug, _rule) {
|
|
@@ -7254,8 +7655,8 @@ var descriptor10 = {
|
|
|
7254
7655
|
};
|
|
7255
7656
|
|
|
7256
7657
|
// src/targets/roo-code/generator.ts
|
|
7257
|
-
import { basename as
|
|
7258
|
-
function
|
|
7658
|
+
import { basename as basename26 } from "path";
|
|
7659
|
+
function generateRules12(canonical) {
|
|
7259
7660
|
const outputs = [];
|
|
7260
7661
|
const root = canonical.rules.find((rule) => rule.root);
|
|
7261
7662
|
if (root) {
|
|
@@ -7267,7 +7668,7 @@ function generateRules11(canonical) {
|
|
|
7267
7668
|
for (const rule of canonical.rules) {
|
|
7268
7669
|
if (rule.root) continue;
|
|
7269
7670
|
if (rule.targets.length > 0 && !rule.targets.includes(ROO_CODE_TARGET)) continue;
|
|
7270
|
-
const slug =
|
|
7671
|
+
const slug = basename26(rule.source, ".md");
|
|
7271
7672
|
outputs.push({
|
|
7272
7673
|
path: `${ROO_CODE_RULES_DIR}/${slug}.md`,
|
|
7273
7674
|
content: rule.body.trim() || ""
|
|
@@ -7285,7 +7686,7 @@ function generateCommands8(canonical) {
|
|
|
7285
7686
|
};
|
|
7286
7687
|
});
|
|
7287
7688
|
}
|
|
7288
|
-
function
|
|
7689
|
+
function generateMcp9(canonical) {
|
|
7289
7690
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
7290
7691
|
return [
|
|
7291
7692
|
{
|
|
@@ -7294,18 +7695,18 @@ function generateMcp8(canonical) {
|
|
|
7294
7695
|
}
|
|
7295
7696
|
];
|
|
7296
7697
|
}
|
|
7297
|
-
function
|
|
7698
|
+
function generateIgnore8(canonical) {
|
|
7298
7699
|
if (canonical.ignore.length === 0) return [];
|
|
7299
7700
|
return [{ path: ROO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
7300
7701
|
}
|
|
7301
|
-
function
|
|
7702
|
+
function generateSkills12(canonical) {
|
|
7302
7703
|
return generateEmbeddedSkills(canonical, ROO_CODE_SKILLS_DIR);
|
|
7303
7704
|
}
|
|
7304
7705
|
|
|
7305
7706
|
// src/targets/roo-code/importer.ts
|
|
7306
7707
|
import { readdir as readdir9 } from "fs/promises";
|
|
7307
|
-
import { join as
|
|
7308
|
-
function
|
|
7708
|
+
import { join as join38 } from "path";
|
|
7709
|
+
function readMcpServers4(content) {
|
|
7309
7710
|
const parsed = JSON.parse(content);
|
|
7310
7711
|
const rawServers = parsed.mcpServers;
|
|
7311
7712
|
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) return {};
|
|
@@ -7336,10 +7737,10 @@ function readMcpServers3(content) {
|
|
|
7336
7737
|
return servers;
|
|
7337
7738
|
}
|
|
7338
7739
|
async function importRootRule2(projectRoot, results, normalize) {
|
|
7339
|
-
const destPath =
|
|
7740
|
+
const destPath = join38(projectRoot, ROO_CODE_CANONICAL_ROOT_RULE);
|
|
7340
7741
|
const sources = [ROO_CODE_ROOT_RULE, ROO_CODE_ROOT_RULE_FALLBACK];
|
|
7341
7742
|
for (const relPath of sources) {
|
|
7342
|
-
const srcPath =
|
|
7743
|
+
const srcPath = join38(projectRoot, relPath);
|
|
7343
7744
|
const content = await readFileSafe(srcPath);
|
|
7344
7745
|
if (content === null) continue;
|
|
7345
7746
|
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
@@ -7363,8 +7764,8 @@ async function importRootRule2(projectRoot, results, normalize) {
|
|
|
7363
7764
|
}
|
|
7364
7765
|
}
|
|
7365
7766
|
async function importNonRootRules3(projectRoot, results, normalize) {
|
|
7366
|
-
const srcDir =
|
|
7367
|
-
const destDir =
|
|
7767
|
+
const srcDir = join38(projectRoot, ROO_CODE_RULES_DIR);
|
|
7768
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7368
7769
|
const rootRuleName = "00-root.md";
|
|
7369
7770
|
results.push(
|
|
7370
7771
|
...await importFileDirectory({
|
|
@@ -7375,7 +7776,7 @@ async function importNonRootRules3(projectRoot, results, normalize) {
|
|
|
7375
7776
|
normalize,
|
|
7376
7777
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7377
7778
|
if (relativePath === rootRuleName) return null;
|
|
7378
|
-
const destPath =
|
|
7779
|
+
const destPath = join38(destDir, relativePath);
|
|
7379
7780
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7380
7781
|
const output = await serializeImportedRuleWithFallback(
|
|
7381
7782
|
destPath,
|
|
@@ -7397,7 +7798,7 @@ async function importNonRootRules3(projectRoot, results, normalize) {
|
|
|
7397
7798
|
);
|
|
7398
7799
|
}
|
|
7399
7800
|
async function importPerModeRules(projectRoot, results, normalize) {
|
|
7400
|
-
const rooDir =
|
|
7801
|
+
const rooDir = join38(projectRoot, ROO_CODE_DIR);
|
|
7401
7802
|
let entries;
|
|
7402
7803
|
try {
|
|
7403
7804
|
entries = await readdir9(rooDir, { withFileTypes: true });
|
|
@@ -7406,8 +7807,8 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7406
7807
|
}
|
|
7407
7808
|
const modeRuleDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("rules-")).map((e) => e.name);
|
|
7408
7809
|
for (const dirName of modeRuleDirs) {
|
|
7409
|
-
const srcDir =
|
|
7410
|
-
const destDir =
|
|
7810
|
+
const srcDir = join38(rooDir, dirName);
|
|
7811
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7411
7812
|
results.push(
|
|
7412
7813
|
...await importFileDirectory({
|
|
7413
7814
|
srcDir,
|
|
@@ -7416,7 +7817,7 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7416
7817
|
fromTool: ROO_CODE_TARGET,
|
|
7417
7818
|
normalize,
|
|
7418
7819
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7419
|
-
const destPath =
|
|
7820
|
+
const destPath = join38(destDir, relativePath);
|
|
7420
7821
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7421
7822
|
const output = await serializeImportedRuleWithFallback(
|
|
7422
7823
|
destPath,
|
|
@@ -7439,8 +7840,8 @@ async function importPerModeRules(projectRoot, results, normalize) {
|
|
|
7439
7840
|
}
|
|
7440
7841
|
}
|
|
7441
7842
|
async function importCommands5(projectRoot, results, normalize) {
|
|
7442
|
-
const srcDir =
|
|
7443
|
-
const destDir =
|
|
7843
|
+
const srcDir = join38(projectRoot, ROO_CODE_COMMANDS_DIR);
|
|
7844
|
+
const destDir = join38(projectRoot, ROO_CODE_CANONICAL_COMMANDS_DIR);
|
|
7444
7845
|
results.push(
|
|
7445
7846
|
...await importFileDirectory({
|
|
7446
7847
|
srcDir,
|
|
@@ -7449,7 +7850,7 @@ async function importCommands5(projectRoot, results, normalize) {
|
|
|
7449
7850
|
fromTool: ROO_CODE_TARGET,
|
|
7450
7851
|
normalize,
|
|
7451
7852
|
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7452
|
-
const destPath =
|
|
7853
|
+
const destPath = join38(destDir, relativePath);
|
|
7453
7854
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7454
7855
|
const output = await serializeImportedCommandWithFallback(
|
|
7455
7856
|
destPath,
|
|
@@ -7471,14 +7872,14 @@ async function importCommands5(projectRoot, results, normalize) {
|
|
|
7471
7872
|
})
|
|
7472
7873
|
);
|
|
7473
7874
|
}
|
|
7474
|
-
async function
|
|
7475
|
-
const srcPath =
|
|
7875
|
+
async function importMcp7(projectRoot, results) {
|
|
7876
|
+
const srcPath = join38(projectRoot, ROO_CODE_MCP_FILE);
|
|
7476
7877
|
const content = await readFileSafe(srcPath);
|
|
7477
7878
|
if (content === null) return;
|
|
7478
|
-
const servers =
|
|
7879
|
+
const servers = readMcpServers4(content);
|
|
7479
7880
|
if (Object.keys(servers).length === 0) return;
|
|
7480
7881
|
await writeFileAtomic(
|
|
7481
|
-
|
|
7882
|
+
join38(projectRoot, ROO_CODE_CANONICAL_MCP),
|
|
7482
7883
|
JSON.stringify({ mcpServers: servers }, null, 2)
|
|
7483
7884
|
);
|
|
7484
7885
|
results.push({
|
|
@@ -7488,11 +7889,11 @@ async function importMcp6(projectRoot, results) {
|
|
|
7488
7889
|
feature: "mcp"
|
|
7489
7890
|
});
|
|
7490
7891
|
}
|
|
7491
|
-
async function
|
|
7492
|
-
const srcPath =
|
|
7892
|
+
async function importIgnore4(projectRoot, results) {
|
|
7893
|
+
const srcPath = join38(projectRoot, ROO_CODE_IGNORE);
|
|
7493
7894
|
const content = await readFileSafe(srcPath);
|
|
7494
7895
|
if (content === null) return;
|
|
7495
|
-
await writeFileAtomic(
|
|
7896
|
+
await writeFileAtomic(join38(projectRoot, ROO_CODE_CANONICAL_IGNORE), content.trimEnd());
|
|
7496
7897
|
results.push({
|
|
7497
7898
|
fromTool: ROO_CODE_TARGET,
|
|
7498
7899
|
fromPath: srcPath,
|
|
@@ -7508,13 +7909,13 @@ async function importFromRooCode(projectRoot) {
|
|
|
7508
7909
|
await importPerModeRules(projectRoot, results, normalize);
|
|
7509
7910
|
await importCommands5(projectRoot, results, normalize);
|
|
7510
7911
|
await importEmbeddedSkills(projectRoot, ROO_CODE_SKILLS_DIR, ROO_CODE_TARGET, results, normalize);
|
|
7511
|
-
await
|
|
7512
|
-
await
|
|
7912
|
+
await importMcp7(projectRoot, results);
|
|
7913
|
+
await importIgnore4(projectRoot, results);
|
|
7513
7914
|
return results;
|
|
7514
7915
|
}
|
|
7515
7916
|
|
|
7516
7917
|
// src/targets/roo-code/linter.ts
|
|
7517
|
-
function
|
|
7918
|
+
function lintRules12(canonical, projectRoot, projectFiles) {
|
|
7518
7919
|
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
7519
7920
|
...diagnostic,
|
|
7520
7921
|
target: ROO_CODE_TARGET
|
|
@@ -7522,19 +7923,19 @@ function lintRules11(canonical, projectRoot, projectFiles) {
|
|
|
7522
7923
|
}
|
|
7523
7924
|
|
|
7524
7925
|
// src/targets/roo-code/index.ts
|
|
7525
|
-
var
|
|
7926
|
+
var target12 = {
|
|
7526
7927
|
name: "roo-code",
|
|
7527
7928
|
primaryRootInstructionPath: ROO_CODE_ROOT_RULE,
|
|
7528
|
-
generateRules:
|
|
7929
|
+
generateRules: generateRules12,
|
|
7529
7930
|
generateCommands: generateCommands8,
|
|
7530
|
-
generateSkills:
|
|
7531
|
-
generateMcp:
|
|
7532
|
-
generateIgnore:
|
|
7931
|
+
generateSkills: generateSkills12,
|
|
7932
|
+
generateMcp: generateMcp9,
|
|
7933
|
+
generateIgnore: generateIgnore8,
|
|
7533
7934
|
importFrom: importFromRooCode
|
|
7534
7935
|
};
|
|
7535
|
-
var
|
|
7936
|
+
var descriptor12 = {
|
|
7536
7937
|
id: "roo-code",
|
|
7537
|
-
generators:
|
|
7938
|
+
generators: target12,
|
|
7538
7939
|
capabilities: {
|
|
7539
7940
|
rules: "native",
|
|
7540
7941
|
commands: "native",
|
|
@@ -7546,7 +7947,7 @@ var descriptor11 = {
|
|
|
7546
7947
|
permissions: "none"
|
|
7547
7948
|
},
|
|
7548
7949
|
emptyImportMessage: "No Roo Code config found (.roo/rules, .roo/commands, .roo/skills, .roo/mcp.json, .rooignore, or .roorules).",
|
|
7549
|
-
lintRules:
|
|
7950
|
+
lintRules: lintRules12,
|
|
7550
7951
|
skillDir: ".roo/skills",
|
|
7551
7952
|
paths: {
|
|
7552
7953
|
rulePath(slug, _rule) {
|
|
@@ -7582,39 +7983,40 @@ var BUILTIN_TARGETS = [
|
|
|
7582
7983
|
descriptor8,
|
|
7583
7984
|
descriptor9,
|
|
7584
7985
|
descriptor10,
|
|
7585
|
-
descriptor11
|
|
7986
|
+
descriptor11,
|
|
7987
|
+
descriptor12
|
|
7586
7988
|
];
|
|
7587
|
-
function getBuiltinTargetDefinition(
|
|
7588
|
-
return BUILTIN_TARGETS.find((candidate) => candidate.id ===
|
|
7989
|
+
function getBuiltinTargetDefinition(target13) {
|
|
7990
|
+
return BUILTIN_TARGETS.find((candidate) => candidate.id === target13);
|
|
7589
7991
|
}
|
|
7590
|
-
function getTargetSkillDir(
|
|
7591
|
-
return getBuiltinTargetDefinition(
|
|
7992
|
+
function getTargetSkillDir(target13) {
|
|
7993
|
+
return getBuiltinTargetDefinition(target13)?.skillDir;
|
|
7592
7994
|
}
|
|
7593
|
-
function getEffectiveTargetSupportLevel(
|
|
7594
|
-
const definition = getBuiltinTargetDefinition(
|
|
7995
|
+
function getEffectiveTargetSupportLevel(target13, feature, config) {
|
|
7996
|
+
const definition = getBuiltinTargetDefinition(target13);
|
|
7595
7997
|
const baseLevel = definition?.capabilities[feature] ?? "none";
|
|
7596
7998
|
if (baseLevel !== "embedded") return baseLevel;
|
|
7597
|
-
if (feature === "commands" &&
|
|
7598
|
-
return shouldConvertCommandsToSkills(config,
|
|
7999
|
+
if (feature === "commands" && target13 === "codex-cli") {
|
|
8000
|
+
return shouldConvertCommandsToSkills(config, target13) ? "embedded" : "none";
|
|
7599
8001
|
}
|
|
7600
|
-
if (feature === "agents" && (
|
|
7601
|
-
return shouldConvertAgentsToSkills(config,
|
|
8002
|
+
if (feature === "agents" && (target13 === "cline" || target13 === "windsurf")) {
|
|
8003
|
+
return shouldConvertAgentsToSkills(config, target13) ? "embedded" : "none";
|
|
7602
8004
|
}
|
|
7603
8005
|
return baseLevel;
|
|
7604
8006
|
}
|
|
7605
|
-
function resolveTargetFeatureGenerator(
|
|
7606
|
-
const generators = getBuiltinTargetDefinition(
|
|
8007
|
+
function resolveTargetFeatureGenerator(target13, feature, config) {
|
|
8008
|
+
const generators = getBuiltinTargetDefinition(target13)?.generators;
|
|
7607
8009
|
if (!generators) return void 0;
|
|
7608
8010
|
switch (feature) {
|
|
7609
8011
|
case "rules":
|
|
7610
8012
|
return generators.generateRules;
|
|
7611
8013
|
case "commands":
|
|
7612
|
-
if (
|
|
8014
|
+
if (target13 === "codex-cli" && config && !shouldConvertCommandsToSkills(config, target13)) {
|
|
7613
8015
|
return void 0;
|
|
7614
8016
|
}
|
|
7615
8017
|
return generators.generateWorkflows ?? generators.generateCommands;
|
|
7616
8018
|
case "agents":
|
|
7617
|
-
if (config && (
|
|
8019
|
+
if (config && (target13 === "cline" || target13 === "windsurf") && !shouldConvertAgentsToSkills(config, target13)) {
|
|
7618
8020
|
return void 0;
|
|
7619
8021
|
}
|
|
7620
8022
|
return generators.generateAgents;
|
|
@@ -7634,9 +8036,9 @@ function resolveTargetFeatureGenerator(target12, feature, config) {
|
|
|
7634
8036
|
}
|
|
7635
8037
|
|
|
7636
8038
|
// src/core/reference/import-map.ts
|
|
7637
|
-
async function buildImportReferenceMap(
|
|
8039
|
+
async function buildImportReferenceMap(target13, projectRoot) {
|
|
7638
8040
|
const refs = /* @__PURE__ */ new Map();
|
|
7639
|
-
const def = getBuiltinTargetDefinition(
|
|
8041
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
7640
8042
|
if (def) {
|
|
7641
8043
|
await def.buildImportPaths(refs, projectRoot);
|
|
7642
8044
|
}
|
|
@@ -7688,6 +8090,7 @@ var ROOT_RELATIVE_PREFIXES = [
|
|
|
7688
8090
|
".github/",
|
|
7689
8091
|
".continue/",
|
|
7690
8092
|
".junie/",
|
|
8093
|
+
".kiro/",
|
|
7691
8094
|
".gemini/",
|
|
7692
8095
|
".clinerules/",
|
|
7693
8096
|
".cline/",
|
|
@@ -7710,7 +8113,7 @@ var EXTERNAL_REF_PATTERNS = [
|
|
|
7710
8113
|
/\/\/[A-Za-z0-9][\w.-]*\.[A-Za-z]{2,}[^\s<>()\]]*/g
|
|
7711
8114
|
];
|
|
7712
8115
|
var FENCED_CODE_BLOCK = /^(?:```|~~~)[^\n]*\n[\s\S]*?^(?:```|~~~)/gm;
|
|
7713
|
-
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;
|
|
7714
8117
|
var LINE_NUMBER_SUFFIX = /(?::(\d+)){1,2}$/;
|
|
7715
8118
|
function resolveProjectPath(token, projectRoot, sourceFile) {
|
|
7716
8119
|
const api = pathApi(projectRoot);
|
|
@@ -7854,6 +8257,7 @@ var IMPORT_REFERENCE_TARGETS = [
|
|
|
7854
8257
|
"copilot",
|
|
7855
8258
|
"continue",
|
|
7856
8259
|
"junie",
|
|
8260
|
+
"kiro",
|
|
7857
8261
|
"gemini-cli",
|
|
7858
8262
|
"cline",
|
|
7859
8263
|
"codex-cli",
|
|
@@ -7873,9 +8277,9 @@ function pathVariants(path) {
|
|
|
7873
8277
|
}
|
|
7874
8278
|
return variants;
|
|
7875
8279
|
}
|
|
7876
|
-
async function createImportReferenceNormalizer(
|
|
8280
|
+
async function createImportReferenceNormalizer(target13, projectRoot) {
|
|
7877
8281
|
const refs = /* @__PURE__ */ new Map();
|
|
7878
|
-
const targets = Array.from(/* @__PURE__ */ new Set([
|
|
8282
|
+
const targets = Array.from(/* @__PURE__ */ new Set([target13, ...IMPORT_REFERENCE_TARGETS]));
|
|
7879
8283
|
for (const candidate of targets) {
|
|
7880
8284
|
const candidateRefs = await buildImportReferenceMap(candidate, projectRoot);
|
|
7881
8285
|
for (const [targetPath, canonicalPath] of candidateRefs.entries()) {
|
|
@@ -7884,8 +8288,8 @@ async function createImportReferenceNormalizer(target12, projectRoot) {
|
|
|
7884
8288
|
}
|
|
7885
8289
|
const artifactMap = /* @__PURE__ */ new Map();
|
|
7886
8290
|
for (const [targetPath, canonicalPath] of refs.entries()) {
|
|
7887
|
-
const canonicalAbsPath = normalizePath(
|
|
7888
|
-
for (const variant of pathVariants(
|
|
8291
|
+
const canonicalAbsPath = normalizePath(join39(projectRoot, canonicalPath));
|
|
8292
|
+
for (const variant of pathVariants(join39(projectRoot, targetPath))) {
|
|
7889
8293
|
artifactMap.set(variant, canonicalAbsPath);
|
|
7890
8294
|
}
|
|
7891
8295
|
}
|
|
@@ -7900,9 +8304,9 @@ async function createImportReferenceNormalizer(target12, projectRoot) {
|
|
|
7900
8304
|
}
|
|
7901
8305
|
|
|
7902
8306
|
// src/targets/claude-code/importer-mappers.ts
|
|
7903
|
-
import { join as
|
|
8307
|
+
import { join as join40 } from "path";
|
|
7904
8308
|
async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
7905
|
-
const destPath =
|
|
8309
|
+
const destPath = join40(destDir, relativePath);
|
|
7906
8310
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7907
8311
|
return {
|
|
7908
8312
|
destPath,
|
|
@@ -7916,7 +8320,7 @@ async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
7916
8320
|
};
|
|
7917
8321
|
}
|
|
7918
8322
|
async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo) {
|
|
7919
|
-
const destPath =
|
|
8323
|
+
const destPath = join40(destDir, relativePath);
|
|
7920
8324
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7921
8325
|
const basePath = feature === "commands" ? CLAUDE_CANONICAL_COMMANDS_DIR : CLAUDE_CANONICAL_AGENTS_DIR;
|
|
7922
8326
|
return {
|
|
@@ -7940,8 +8344,8 @@ async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo
|
|
|
7940
8344
|
}
|
|
7941
8345
|
|
|
7942
8346
|
// src/targets/claude-code/settings-helpers.ts
|
|
7943
|
-
import { join as
|
|
7944
|
-
import { stringify as
|
|
8347
|
+
import { join as join41, dirname as dirname17 } from "path";
|
|
8348
|
+
import { stringify as yamlStringify6 } from "yaml";
|
|
7945
8349
|
function claudeHooksToCanonical(hooks) {
|
|
7946
8350
|
const result = {};
|
|
7947
8351
|
for (const [event, entries] of Object.entries(hooks)) {
|
|
@@ -7967,7 +8371,7 @@ function claudeHooksToCanonical(hooks) {
|
|
|
7967
8371
|
return result;
|
|
7968
8372
|
}
|
|
7969
8373
|
async function importMcpJson(projectRoot, results) {
|
|
7970
|
-
const mcpPath =
|
|
8374
|
+
const mcpPath = join41(projectRoot, CLAUDE_MCP_JSON);
|
|
7971
8375
|
const content = await readFileSafe(mcpPath);
|
|
7972
8376
|
if (content === null) return;
|
|
7973
8377
|
let parsed;
|
|
@@ -7978,7 +8382,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7978
8382
|
}
|
|
7979
8383
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
7980
8384
|
const mcpContent = JSON.stringify({ mcpServers: parsed.mcpServers }, null, 2);
|
|
7981
|
-
const destPath =
|
|
8385
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
7982
8386
|
await mkdirp(dirname17(destPath));
|
|
7983
8387
|
await writeFileAtomic(destPath, mcpContent);
|
|
7984
8388
|
results.push({
|
|
@@ -7990,7 +8394,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7990
8394
|
}
|
|
7991
8395
|
}
|
|
7992
8396
|
async function importSettings2(projectRoot, results) {
|
|
7993
|
-
const settingsPath =
|
|
8397
|
+
const settingsPath = join41(projectRoot, CLAUDE_SETTINGS);
|
|
7994
8398
|
const content = await readFileSafe(settingsPath);
|
|
7995
8399
|
if (!content) return;
|
|
7996
8400
|
let settings;
|
|
@@ -8002,7 +8406,7 @@ async function importSettings2(projectRoot, results) {
|
|
|
8002
8406
|
const alreadyImportedMcp = results.some((r) => r.feature === "mcp");
|
|
8003
8407
|
if (!alreadyImportedMcp && settings.mcpServers && typeof settings.mcpServers === "object") {
|
|
8004
8408
|
const mcpContent = JSON.stringify({ mcpServers: settings.mcpServers }, null, 2);
|
|
8005
|
-
const destPath =
|
|
8409
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
8006
8410
|
await mkdirp(dirname17(destPath));
|
|
8007
8411
|
await writeFileAtomic(destPath, mcpContent);
|
|
8008
8412
|
results.push({
|
|
@@ -8018,8 +8422,8 @@ async function importSettings2(projectRoot, results) {
|
|
|
8018
8422
|
const allow = Array.isArray(perms.allow) ? perms.allow.filter((s) => typeof s === "string") : [];
|
|
8019
8423
|
const deny = Array.isArray(perms.deny) ? perms.deny.filter((s) => typeof s === "string") : [];
|
|
8020
8424
|
if (allow.length > 0 || deny.length > 0) {
|
|
8021
|
-
const permContent =
|
|
8022
|
-
const destPath =
|
|
8425
|
+
const permContent = yamlStringify6({ allow, deny });
|
|
8426
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_PERMISSIONS);
|
|
8023
8427
|
await mkdirp(dirname17(destPath));
|
|
8024
8428
|
await writeFileAtomic(destPath, permContent);
|
|
8025
8429
|
results.push({
|
|
@@ -8034,8 +8438,8 @@ async function importSettings2(projectRoot, results) {
|
|
|
8034
8438
|
if (rawHooks && typeof rawHooks === "object" && !Array.isArray(rawHooks)) {
|
|
8035
8439
|
const canonicalHooks = claudeHooksToCanonical(rawHooks);
|
|
8036
8440
|
if (Object.keys(canonicalHooks).length > 0) {
|
|
8037
|
-
const hooksContent =
|
|
8038
|
-
const destPath =
|
|
8441
|
+
const hooksContent = yamlStringify6(canonicalHooks);
|
|
8442
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_HOOKS);
|
|
8039
8443
|
await mkdirp(dirname17(destPath));
|
|
8040
8444
|
await writeFileAtomic(destPath, hooksContent);
|
|
8041
8445
|
results.push({
|
|
@@ -8052,26 +8456,26 @@ async function importSettings2(projectRoot, results) {
|
|
|
8052
8456
|
async function importFromClaudeCode(projectRoot) {
|
|
8053
8457
|
const results = [];
|
|
8054
8458
|
const normalize = await createImportReferenceNormalizer("claude-code", projectRoot);
|
|
8055
|
-
await
|
|
8459
|
+
await importRules6(projectRoot, results, normalize);
|
|
8056
8460
|
await importCommands6(projectRoot, results, normalize);
|
|
8057
8461
|
await importAgents5(projectRoot, results, normalize);
|
|
8058
8462
|
await importSkills5(projectRoot, results, normalize);
|
|
8059
8463
|
await importMcpJson(projectRoot, results);
|
|
8060
8464
|
await importSettings2(projectRoot, results);
|
|
8061
|
-
await
|
|
8465
|
+
await importIgnore5(projectRoot, results);
|
|
8062
8466
|
return results;
|
|
8063
8467
|
}
|
|
8064
|
-
async function
|
|
8065
|
-
const destDir =
|
|
8066
|
-
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);
|
|
8067
8471
|
const primaryContent = await readFileSafe(primaryClaudePath);
|
|
8068
|
-
const legacyClaudePath =
|
|
8472
|
+
const legacyClaudePath = join42(projectRoot, CLAUDE_LEGACY_ROOT);
|
|
8069
8473
|
const legacyContent = primaryContent === null ? await readFileSafe(legacyClaudePath) : null;
|
|
8070
8474
|
const claudeContent = primaryContent ?? legacyContent;
|
|
8071
8475
|
const claudePath = primaryContent !== null ? primaryClaudePath : legacyClaudePath;
|
|
8072
8476
|
if (claudeContent !== null) {
|
|
8073
8477
|
await mkdirp(destDir);
|
|
8074
|
-
const destPath =
|
|
8478
|
+
const destPath = join42(destDir, "_root.md");
|
|
8075
8479
|
const { frontmatter, body } = parseFrontmatter(normalize(claudeContent, claudePath, destPath));
|
|
8076
8480
|
const hasRoot = frontmatter.root === true;
|
|
8077
8481
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -8084,7 +8488,7 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
8084
8488
|
feature: "rules"
|
|
8085
8489
|
});
|
|
8086
8490
|
}
|
|
8087
|
-
const rulesDir =
|
|
8491
|
+
const rulesDir = join42(projectRoot, CLAUDE_RULES_DIR);
|
|
8088
8492
|
results.push(
|
|
8089
8493
|
...await importFileDirectory({
|
|
8090
8494
|
srcDir: rulesDir,
|
|
@@ -8097,8 +8501,8 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
8097
8501
|
);
|
|
8098
8502
|
}
|
|
8099
8503
|
async function importCommands6(projectRoot, results, normalize) {
|
|
8100
|
-
const destDir =
|
|
8101
|
-
const commandsDir =
|
|
8504
|
+
const destDir = join42(projectRoot, CLAUDE_CANONICAL_COMMANDS_DIR);
|
|
8505
|
+
const commandsDir = join42(projectRoot, CLAUDE_COMMANDS_DIR);
|
|
8102
8506
|
results.push(
|
|
8103
8507
|
...await importFileDirectory({
|
|
8104
8508
|
srcDir: commandsDir,
|
|
@@ -8111,8 +8515,8 @@ async function importCommands6(projectRoot, results, normalize) {
|
|
|
8111
8515
|
);
|
|
8112
8516
|
}
|
|
8113
8517
|
async function importAgents5(projectRoot, results, normalize) {
|
|
8114
|
-
const destDir =
|
|
8115
|
-
const agentsDir =
|
|
8518
|
+
const destDir = join42(projectRoot, CLAUDE_CANONICAL_AGENTS_DIR);
|
|
8519
|
+
const agentsDir = join42(projectRoot, CLAUDE_AGENTS_DIR);
|
|
8116
8520
|
results.push(
|
|
8117
8521
|
...await importFileDirectory({
|
|
8118
8522
|
srcDir: agentsDir,
|
|
@@ -8125,20 +8529,20 @@ async function importAgents5(projectRoot, results, normalize) {
|
|
|
8125
8529
|
);
|
|
8126
8530
|
}
|
|
8127
8531
|
async function importSkills5(projectRoot, results, normalize) {
|
|
8128
|
-
const skillsBaseDir =
|
|
8129
|
-
const destBase =
|
|
8532
|
+
const skillsBaseDir = join42(projectRoot, CLAUDE_SKILLS_DIR);
|
|
8533
|
+
const destBase = join42(projectRoot, CLAUDE_CANONICAL_SKILLS_DIR);
|
|
8130
8534
|
const allFiles = await readDirRecursive(skillsBaseDir);
|
|
8131
8535
|
const skillMdFiles = allFiles.filter((f) => f.endsWith("SKILL.md"));
|
|
8132
8536
|
for (const skillMdPath of skillMdFiles) {
|
|
8133
8537
|
const skillDir = dirname18(skillMdPath);
|
|
8134
|
-
const skillName =
|
|
8135
|
-
const destSkillDir =
|
|
8538
|
+
const skillName = basename27(skillDir);
|
|
8539
|
+
const destSkillDir = join42(destBase, skillName);
|
|
8136
8540
|
const skillFiles = await readDirRecursive(skillDir);
|
|
8137
8541
|
for (const filePath of skillFiles) {
|
|
8138
8542
|
const fileContent = await readFileSafe(filePath);
|
|
8139
8543
|
if (fileContent === null) continue;
|
|
8140
8544
|
const relPath = relative17(skillDir, filePath);
|
|
8141
|
-
const destPath =
|
|
8545
|
+
const destPath = join42(destSkillDir, relPath);
|
|
8142
8546
|
await mkdirp(dirname18(destPath));
|
|
8143
8547
|
const normalized = normalize(fileContent, filePath, destPath);
|
|
8144
8548
|
const parsed = relPath === "SKILL.md" ? parseFrontmatter(normalized) : null;
|
|
@@ -8160,11 +8564,11 @@ async function importSkills5(projectRoot, results, normalize) {
|
|
|
8160
8564
|
}
|
|
8161
8565
|
}
|
|
8162
8566
|
}
|
|
8163
|
-
async function
|
|
8164
|
-
const ignorePath =
|
|
8567
|
+
async function importIgnore5(projectRoot, results) {
|
|
8568
|
+
const ignorePath = join42(projectRoot, CLAUDE_IGNORE);
|
|
8165
8569
|
const content = await readFileSafe(ignorePath);
|
|
8166
8570
|
if (content === null) return;
|
|
8167
|
-
const destPath =
|
|
8571
|
+
const destPath = join42(projectRoot, CLAUDE_CANONICAL_IGNORE);
|
|
8168
8572
|
await mkdirp(dirname18(destPath));
|
|
8169
8573
|
await writeFileAtomic(destPath, content);
|
|
8170
8574
|
results.push({
|
|
@@ -8185,7 +8589,8 @@ var NATIVE_IMPORTERS = {
|
|
|
8185
8589
|
windsurf: importFromWindsurf,
|
|
8186
8590
|
cline: importFromCline,
|
|
8187
8591
|
continue: importFromContinue,
|
|
8188
|
-
junie: importFromJunie
|
|
8592
|
+
junie: importFromJunie,
|
|
8593
|
+
kiro: importFromKiro
|
|
8189
8594
|
};
|
|
8190
8595
|
async function importNativeToCanonical(repoPath, targetName) {
|
|
8191
8596
|
const importFn = NATIVE_IMPORTERS[targetName];
|
|
@@ -8196,17 +8601,17 @@ async function importNativeToCanonical(repoPath, targetName) {
|
|
|
8196
8601
|
}
|
|
8197
8602
|
|
|
8198
8603
|
// src/canonical/load/skill-pack-load.ts
|
|
8199
|
-
import { join as
|
|
8604
|
+
import { join as join43 } from "path";
|
|
8200
8605
|
import { readdir as readdir10 } from "fs/promises";
|
|
8201
8606
|
var SKILL = "SKILL.md";
|
|
8202
8607
|
async function isSkillPackLayout(root) {
|
|
8203
8608
|
if (!await exists(root)) return false;
|
|
8204
|
-
if (await exists(
|
|
8609
|
+
if (await exists(join43(root, SKILL))) return true;
|
|
8205
8610
|
try {
|
|
8206
8611
|
const ents = await readdir10(root, { withFileTypes: true });
|
|
8207
8612
|
for (const e of ents) {
|
|
8208
8613
|
if (!e.isDirectory() || e.name.startsWith(".")) continue;
|
|
8209
|
-
if (await exists(
|
|
8614
|
+
if (await exists(join43(root, e.name, SKILL))) return true;
|
|
8210
8615
|
}
|
|
8211
8616
|
} catch {
|
|
8212
8617
|
return false;
|
|
@@ -8215,7 +8620,7 @@ async function isSkillPackLayout(root) {
|
|
|
8215
8620
|
}
|
|
8216
8621
|
async function loadSkillsAtExtendPath(skillsRoot) {
|
|
8217
8622
|
if (!await exists(skillsRoot)) return [];
|
|
8218
|
-
if (await exists(
|
|
8623
|
+
if (await exists(join43(skillsRoot, SKILL))) {
|
|
8219
8624
|
const one = await parseSkillDirectory(skillsRoot);
|
|
8220
8625
|
return one ? [one] : [];
|
|
8221
8626
|
}
|
|
@@ -8223,7 +8628,7 @@ async function loadSkillsAtExtendPath(skillsRoot) {
|
|
|
8223
8628
|
}
|
|
8224
8629
|
|
|
8225
8630
|
// src/canonical/load/load-canonical-slice.ts
|
|
8226
|
-
import { basename as
|
|
8631
|
+
import { basename as basename28, dirname as dirname19, join as join44 } from "path";
|
|
8227
8632
|
import { stat as stat4 } from "fs/promises";
|
|
8228
8633
|
function emptyCanonical() {
|
|
8229
8634
|
return {
|
|
@@ -8254,8 +8659,8 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
8254
8659
|
);
|
|
8255
8660
|
}
|
|
8256
8661
|
const parent = dirname19(absolutePath);
|
|
8257
|
-
const parentBase =
|
|
8258
|
-
const fileBase =
|
|
8662
|
+
const parentBase = basename28(parent);
|
|
8663
|
+
const fileBase = basename28(absolutePath);
|
|
8259
8664
|
const slug = fileBase.replace(/\.md$/i, "");
|
|
8260
8665
|
if (parentBase === "rules") {
|
|
8261
8666
|
return { sliceRoot: parent, implicitPick: { rules: [slug] } };
|
|
@@ -8271,33 +8676,33 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
8271
8676
|
);
|
|
8272
8677
|
}
|
|
8273
8678
|
async function parseRulesAt(sliceRoot) {
|
|
8274
|
-
const base =
|
|
8679
|
+
const base = basename28(sliceRoot);
|
|
8275
8680
|
if (base === "rules") {
|
|
8276
8681
|
return parseRules(sliceRoot);
|
|
8277
8682
|
}
|
|
8278
|
-
const nested =
|
|
8683
|
+
const nested = join44(sliceRoot, "rules");
|
|
8279
8684
|
if (await exists(nested)) {
|
|
8280
8685
|
return parseRules(nested);
|
|
8281
8686
|
}
|
|
8282
8687
|
return [];
|
|
8283
8688
|
}
|
|
8284
8689
|
async function parseCommandsAt(sliceRoot) {
|
|
8285
|
-
const base =
|
|
8690
|
+
const base = basename28(sliceRoot);
|
|
8286
8691
|
if (base === "commands") {
|
|
8287
8692
|
return parseCommands(sliceRoot);
|
|
8288
8693
|
}
|
|
8289
|
-
const nested =
|
|
8694
|
+
const nested = join44(sliceRoot, "commands");
|
|
8290
8695
|
if (await exists(nested)) {
|
|
8291
8696
|
return parseCommands(nested);
|
|
8292
8697
|
}
|
|
8293
8698
|
return [];
|
|
8294
8699
|
}
|
|
8295
8700
|
async function parseAgentsAt(sliceRoot) {
|
|
8296
|
-
const base =
|
|
8701
|
+
const base = basename28(sliceRoot);
|
|
8297
8702
|
if (base === "agents") {
|
|
8298
8703
|
return parseAgents(sliceRoot);
|
|
8299
8704
|
}
|
|
8300
|
-
const nested =
|
|
8705
|
+
const nested = join44(sliceRoot, "agents");
|
|
8301
8706
|
if (await exists(nested)) {
|
|
8302
8707
|
return parseAgents(nested);
|
|
8303
8708
|
}
|
|
@@ -8307,15 +8712,15 @@ async function loadSkillsForPartialSlice(sliceRoot) {
|
|
|
8307
8712
|
if (await isSkillPackLayout(sliceRoot)) {
|
|
8308
8713
|
return loadSkillsAtExtendPath(sliceRoot);
|
|
8309
8714
|
}
|
|
8310
|
-
const nestedSkills =
|
|
8715
|
+
const nestedSkills = join44(sliceRoot, "skills");
|
|
8311
8716
|
if (await isSkillPackLayout(nestedSkills)) {
|
|
8312
8717
|
return loadSkillsAtExtendPath(nestedSkills);
|
|
8313
8718
|
}
|
|
8314
8719
|
return [];
|
|
8315
8720
|
}
|
|
8316
8721
|
async function loadCanonicalSliceAtPath(sliceRoot) {
|
|
8317
|
-
const
|
|
8318
|
-
if (await exists(
|
|
8722
|
+
const ab2 = join44(sliceRoot, ".agentsmesh");
|
|
8723
|
+
if (await exists(ab2)) {
|
|
8319
8724
|
return loadCanonicalFiles(sliceRoot);
|
|
8320
8725
|
}
|
|
8321
8726
|
const partial = emptyCanonical();
|
|
@@ -8347,7 +8752,7 @@ function emptyCanonical2() {
|
|
|
8347
8752
|
async function loadCanonicalForExtend(ext) {
|
|
8348
8753
|
const base = ext.resolvedPath;
|
|
8349
8754
|
if (!ext.path) {
|
|
8350
|
-
const agentsmeshDir =
|
|
8755
|
+
const agentsmeshDir = join45(base, ".agentsmesh");
|
|
8351
8756
|
if (!await exists(agentsmeshDir)) {
|
|
8352
8757
|
if (await isSkillPackLayout(base)) {
|
|
8353
8758
|
const skills = await loadSkillsAtExtendPath(base);
|
|
@@ -8367,12 +8772,12 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8367
8772
|
}
|
|
8368
8773
|
return loadCanonicalFiles(base);
|
|
8369
8774
|
}
|
|
8370
|
-
const rawRoot =
|
|
8775
|
+
const rawRoot = join45(base, ext.path);
|
|
8371
8776
|
if (!await exists(rawRoot)) {
|
|
8372
8777
|
throw new Error(`Extend "${ext.name}": path does not exist: ${rawRoot}`);
|
|
8373
8778
|
}
|
|
8374
8779
|
if (ext.target) {
|
|
8375
|
-
const agentsmeshDir =
|
|
8780
|
+
const agentsmeshDir = join45(base, ".agentsmesh");
|
|
8376
8781
|
if (!await exists(agentsmeshDir)) {
|
|
8377
8782
|
logger.info(
|
|
8378
8783
|
`[agentsmesh] Extend "${ext.name}": path "${ext.path}" with target "${ext.target}" \u2014 importing at extend root, then loading canonical.`
|
|
@@ -8393,7 +8798,7 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8393
8798
|
}
|
|
8394
8799
|
|
|
8395
8800
|
// src/canonical/extends/extend-pick.ts
|
|
8396
|
-
import { basename as
|
|
8801
|
+
import { basename as basename29 } from "path";
|
|
8397
8802
|
function applyExtendPick(canonical, features, pick, extendName) {
|
|
8398
8803
|
if (!pick) return canonical;
|
|
8399
8804
|
let next = { ...canonical };
|
|
@@ -8436,7 +8841,7 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8436
8841
|
if (pick.rules?.length && features.includes("rules")) {
|
|
8437
8842
|
const wanted = new Set(pick.rules);
|
|
8438
8843
|
const prev = next.rules;
|
|
8439
|
-
const stem = (src) =>
|
|
8844
|
+
const stem = (src) => basename29(src).replace(/\.md$/i, "");
|
|
8440
8845
|
next = {
|
|
8441
8846
|
...next,
|
|
8442
8847
|
rules: prev.filter((r) => wanted.has(stem(r.source)))
|
|
@@ -8453,10 +8858,10 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8453
8858
|
}
|
|
8454
8859
|
|
|
8455
8860
|
// src/canonical/load/pack-load.ts
|
|
8456
|
-
import { join as
|
|
8861
|
+
import { join as join47 } from "path";
|
|
8457
8862
|
|
|
8458
8863
|
// src/install/pack/pack-reader.ts
|
|
8459
|
-
import { join as
|
|
8864
|
+
import { join as join46 } from "path";
|
|
8460
8865
|
import { readdir as readdir11 } from "fs/promises";
|
|
8461
8866
|
import { parse as parseYaml5 } from "yaml";
|
|
8462
8867
|
|
|
@@ -8503,7 +8908,7 @@ function sameFeatures(a, b) {
|
|
|
8503
8908
|
return a.length === b.length && [...a].sort().every((feature, index) => feature === [...b].sort()[index]);
|
|
8504
8909
|
}
|
|
8505
8910
|
async function readPackMetadata(packDir) {
|
|
8506
|
-
const metaPath =
|
|
8911
|
+
const metaPath = join46(packDir, "pack.yaml");
|
|
8507
8912
|
const content = await readFileSafe(metaPath);
|
|
8508
8913
|
if (content === null) return null;
|
|
8509
8914
|
try {
|
|
@@ -8524,7 +8929,7 @@ async function findExistingPack(packsDir, source, scope) {
|
|
|
8524
8929
|
}
|
|
8525
8930
|
for (const entry of entries) {
|
|
8526
8931
|
if (!entry.isDirectory()) continue;
|
|
8527
|
-
const packDir =
|
|
8932
|
+
const packDir = join46(packsDir, entry.name);
|
|
8528
8933
|
const meta = await readPackMetadata(packDir);
|
|
8529
8934
|
if (meta && sourceIdentity(meta.source) === requestedIdentity && meta.target === scope.target && meta.as === scope.as && sameFeatures(meta.features, scope.features)) {
|
|
8530
8935
|
return { meta, packDir, name: meta.name };
|
|
@@ -8543,7 +8948,7 @@ async function listPacks(packsDir) {
|
|
|
8543
8948
|
const result = [];
|
|
8544
8949
|
for (const entry of entries) {
|
|
8545
8950
|
if (!entry.isDirectory()) continue;
|
|
8546
|
-
const packDir =
|
|
8951
|
+
const packDir = join46(packsDir, entry.name);
|
|
8547
8952
|
const meta = await readPackMetadata(packDir);
|
|
8548
8953
|
if (meta) {
|
|
8549
8954
|
result.push({ meta, packDir, name: meta.name });
|
|
@@ -8567,19 +8972,19 @@ function emptyCanonical3() {
|
|
|
8567
8972
|
}
|
|
8568
8973
|
async function loadPackCanonical(packDir) {
|
|
8569
8974
|
const [rules, commands, agents, skills, mcp, permissions, hooks, ignore] = await Promise.all([
|
|
8570
|
-
parseRules(
|
|
8571
|
-
parseCommands(
|
|
8572
|
-
parseAgents(
|
|
8573
|
-
parseSkills(
|
|
8574
|
-
parseMcp(
|
|
8575
|
-
parsePermissions(
|
|
8576
|
-
parseHooks(
|
|
8577
|
-
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"))
|
|
8578
8983
|
]);
|
|
8579
8984
|
return { ...emptyCanonical3(), rules, commands, agents, skills, mcp, permissions, hooks, ignore };
|
|
8580
8985
|
}
|
|
8581
8986
|
async function loadPacksCanonical(abDir) {
|
|
8582
|
-
const packsDir =
|
|
8987
|
+
const packsDir = join47(abDir, "packs");
|
|
8583
8988
|
const packs = await listPacks(packsDir);
|
|
8584
8989
|
let merged = emptyCanonical3();
|
|
8585
8990
|
for (const { meta, packDir } of packs) {
|
|
@@ -8641,7 +9046,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8641
9046
|
const picked = applyExtendPick(filtered, ext.features, ext.pick, ext.name);
|
|
8642
9047
|
merged = mergeCanonicalFiles(merged, picked);
|
|
8643
9048
|
}
|
|
8644
|
-
const packsCanonical = await loadPacksCanonical(
|
|
9049
|
+
const packsCanonical = await loadPacksCanonical(join48(configDir, ".agentsmesh"));
|
|
8645
9050
|
merged = mergeCanonicalFiles(merged, packsCanonical);
|
|
8646
9051
|
const localCanonical = await loadCanonicalFiles(configDir);
|
|
8647
9052
|
merged = mergeCanonicalFiles(merged, localCanonical);
|
|
@@ -8650,7 +9055,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8650
9055
|
|
|
8651
9056
|
// src/config/core/lock.ts
|
|
8652
9057
|
import { parse as parseYaml6, stringify as stringifyYaml3 } from "yaml";
|
|
8653
|
-
import { join as
|
|
9058
|
+
import { join as join49, relative as relative18 } from "path";
|
|
8654
9059
|
|
|
8655
9060
|
// src/utils/crypto/hash.ts
|
|
8656
9061
|
import { createHash } from "crypto";
|
|
@@ -8697,7 +9102,7 @@ var FEATURE_PATTERNS = {
|
|
|
8697
9102
|
ignore: (path) => path === "ignore"
|
|
8698
9103
|
};
|
|
8699
9104
|
async function readLock(abDir) {
|
|
8700
|
-
const lockPath =
|
|
9105
|
+
const lockPath = join49(abDir, LOCK_FILENAME);
|
|
8701
9106
|
const content = await readFileSafe(lockPath);
|
|
8702
9107
|
if (content === null) return null;
|
|
8703
9108
|
try {
|
|
@@ -8716,7 +9121,7 @@ async function readLock(abDir) {
|
|
|
8716
9121
|
}
|
|
8717
9122
|
}
|
|
8718
9123
|
async function writeLock(abDir, lock) {
|
|
8719
|
-
const lockPath =
|
|
9124
|
+
const lockPath = join49(abDir, LOCK_FILENAME);
|
|
8720
9125
|
const raw = {
|
|
8721
9126
|
generated_at: lock.generatedAt,
|
|
8722
9127
|
generated_by: lock.generatedBy,
|
|
@@ -8770,7 +9175,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8770
9175
|
result[ext.name] = ext.version;
|
|
8771
9176
|
continue;
|
|
8772
9177
|
}
|
|
8773
|
-
const abDir =
|
|
9178
|
+
const abDir = join49(ext.resolvedPath, ".agentsmesh");
|
|
8774
9179
|
const checksums = await buildChecksums(abDir);
|
|
8775
9180
|
const fingerprint = Object.keys(checksums).sort().map((p) => `${p}:${checksums[p]}`).join("\n");
|
|
8776
9181
|
const h = hashContent(fingerprint);
|
|
@@ -8781,7 +9186,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8781
9186
|
}
|
|
8782
9187
|
|
|
8783
9188
|
// src/core/reference/map.ts
|
|
8784
|
-
import { basename as
|
|
9189
|
+
import { basename as basename31 } from "path";
|
|
8785
9190
|
|
|
8786
9191
|
// src/core/reference/map-directories.ts
|
|
8787
9192
|
import { posix as posix2 } from "path";
|
|
@@ -8800,29 +9205,29 @@ function addSkillDirectoryMappings(refs, canonicalPath, targetPath) {
|
|
|
8800
9205
|
}
|
|
8801
9206
|
|
|
8802
9207
|
// src/core/reference/map-targets.ts
|
|
8803
|
-
import { basename as
|
|
9208
|
+
import { basename as basename30 } from "path";
|
|
8804
9209
|
var SKILL_DIRS = Object.fromEntries(
|
|
8805
|
-
TARGET_IDS.map((
|
|
9210
|
+
TARGET_IDS.map((target13) => [target13, getTargetSkillDir(target13)]).filter(
|
|
8806
9211
|
(entry) => typeof entry[1] === "string"
|
|
8807
9212
|
)
|
|
8808
9213
|
);
|
|
8809
|
-
function ruleTargetPath(
|
|
8810
|
-
const def = getBuiltinTargetDefinition(
|
|
9214
|
+
function ruleTargetPath(target13, rule) {
|
|
9215
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8811
9216
|
if (!def) return null;
|
|
8812
9217
|
if (rule.root) {
|
|
8813
9218
|
return def.generators.primaryRootInstructionPath ?? null;
|
|
8814
9219
|
}
|
|
8815
|
-
if (rule.targets.length > 0 && !rule.targets.includes(
|
|
8816
|
-
const slug =
|
|
9220
|
+
if (rule.targets.length > 0 && !rule.targets.includes(target13)) return null;
|
|
9221
|
+
const slug = basename30(rule.source, ".md");
|
|
8817
9222
|
return def.paths.rulePath(slug, rule);
|
|
8818
9223
|
}
|
|
8819
|
-
function commandTargetPath(
|
|
8820
|
-
const def = getBuiltinTargetDefinition(
|
|
9224
|
+
function commandTargetPath(target13, name, config) {
|
|
9225
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8821
9226
|
if (!def) return null;
|
|
8822
9227
|
return def.paths.commandPath(name, config);
|
|
8823
9228
|
}
|
|
8824
|
-
function agentTargetPath(
|
|
8825
|
-
const def = getBuiltinTargetDefinition(
|
|
9229
|
+
function agentTargetPath(target13, name, config) {
|
|
9230
|
+
const def = getBuiltinTargetDefinition(target13);
|
|
8826
9231
|
if (!def) return null;
|
|
8827
9232
|
return def.paths.agentPath(name, config);
|
|
8828
9233
|
}
|
|
@@ -8832,21 +9237,21 @@ function addDirectoryMapping3(refs, from, to) {
|
|
|
8832
9237
|
refs.set(from, to);
|
|
8833
9238
|
refs.set(`${from}/`, `${to}/`);
|
|
8834
9239
|
}
|
|
8835
|
-
function buildReferenceMap(
|
|
9240
|
+
function buildReferenceMap(target13, canonical, config) {
|
|
8836
9241
|
const refs = /* @__PURE__ */ new Map();
|
|
8837
9242
|
for (const rule of canonical.rules) {
|
|
8838
|
-
const path = ruleTargetPath(
|
|
8839
|
-
if (path) refs.set(`.agentsmesh/rules/${
|
|
9243
|
+
const path = ruleTargetPath(target13, rule);
|
|
9244
|
+
if (path) refs.set(`.agentsmesh/rules/${basename31(rule.source)}`, path);
|
|
8840
9245
|
}
|
|
8841
9246
|
for (const command of canonical.commands) {
|
|
8842
|
-
const path = commandTargetPath(
|
|
9247
|
+
const path = commandTargetPath(target13, command.name, config);
|
|
8843
9248
|
if (path) refs.set(`.agentsmesh/commands/${command.name}.md`, path);
|
|
8844
9249
|
}
|
|
8845
9250
|
for (const agent of canonical.agents) {
|
|
8846
|
-
const path = agentTargetPath(
|
|
9251
|
+
const path = agentTargetPath(target13, agent.name, config);
|
|
8847
9252
|
if (path) refs.set(`.agentsmesh/agents/${agent.name}.md`, path);
|
|
8848
9253
|
}
|
|
8849
|
-
const skillDir = SKILL_DIRS[
|
|
9254
|
+
const skillDir = SKILL_DIRS[target13];
|
|
8850
9255
|
if (!skillDir) return refs;
|
|
8851
9256
|
for (const skill of canonical.skills) {
|
|
8852
9257
|
addDirectoryMapping3(refs, `.agentsmesh/skills/${skill.name}`, `${skillDir}/${skill.name}`);
|
|
@@ -8879,17 +9284,20 @@ function isCursorAgents(result) {
|
|
|
8879
9284
|
function isGeminiAgents(result) {
|
|
8880
9285
|
return result.target === "gemini-cli" && result.path.endsWith(AGENTS_SUFFIX);
|
|
8881
9286
|
}
|
|
9287
|
+
function isKiroAgents(result) {
|
|
9288
|
+
return result.target === "kiro" && result.path.endsWith(AGENTS_SUFFIX);
|
|
9289
|
+
}
|
|
8882
9290
|
function isCompatibilityAgents(result) {
|
|
8883
9291
|
return isCursorAgents(result) || isGeminiAgents(result);
|
|
8884
9292
|
}
|
|
8885
|
-
function reverseReferenceMap(
|
|
8886
|
-
const cached = cache.get(
|
|
9293
|
+
function reverseReferenceMap(target13, canonical, config, cache) {
|
|
9294
|
+
const cached = cache.get(target13);
|
|
8887
9295
|
if (cached) return cached;
|
|
8888
9296
|
const reversed = /* @__PURE__ */ new Map();
|
|
8889
|
-
for (const [canonicalPath, targetPath] of buildReferenceMap(
|
|
9297
|
+
for (const [canonicalPath, targetPath] of buildReferenceMap(target13, canonical, config)) {
|
|
8890
9298
|
if (!reversed.has(targetPath)) reversed.set(targetPath, canonicalPath);
|
|
8891
9299
|
}
|
|
8892
|
-
cache.set(
|
|
9300
|
+
cache.set(target13, reversed);
|
|
8893
9301
|
return reversed;
|
|
8894
9302
|
}
|
|
8895
9303
|
function normalizeContent(content, refs) {
|
|
@@ -8905,6 +9313,13 @@ function hasEquivalentCanonicalContent(left, right, canonical, config, cache) {
|
|
|
8905
9313
|
const rightRefs = reverseReferenceMap(right.target, canonical, config, cache);
|
|
8906
9314
|
return normalizeContent(left.content, leftRefs) === normalizeContent(right.content, rightRefs);
|
|
8907
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
|
+
}
|
|
8908
9323
|
function preferEquivalentCodexAgents(results, canonical, config) {
|
|
8909
9324
|
const overlapTargetsByPath = /* @__PURE__ */ new Map();
|
|
8910
9325
|
for (const result of results) {
|
|
@@ -8921,15 +9336,15 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8921
9336
|
return results.filter((result) => {
|
|
8922
9337
|
if (isCursorAgents(result)) {
|
|
8923
9338
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8924
|
-
if (targets && [...targets].some((
|
|
9339
|
+
if (targets && [...targets].some((target13) => target13 !== "cursor")) return false;
|
|
8925
9340
|
}
|
|
8926
9341
|
if (isGeminiAgents(result)) {
|
|
8927
9342
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8928
|
-
if (targets && [...targets].some((
|
|
9343
|
+
if (targets && [...targets].some((target13) => target13 !== "cursor" && target13 !== "gemini-cli")) {
|
|
8929
9344
|
return false;
|
|
8930
9345
|
}
|
|
8931
9346
|
}
|
|
8932
|
-
if (!isWindsurfAgents(result) && !isClineAgents(result) && !isCursorAgents(result) && !isGeminiAgents(result)) {
|
|
9347
|
+
if (!isWindsurfAgents(result) && !isClineAgents(result) && !isCursorAgents(result) && !isGeminiAgents(result) && !isKiroAgents(result)) {
|
|
8933
9348
|
return true;
|
|
8934
9349
|
}
|
|
8935
9350
|
const codexResult = codexByPath.get(result.path);
|
|
@@ -8937,16 +9352,16 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8937
9352
|
if (isCompatibilityAgents(result) || isWindsurfAgents(result) || isClineAgents(result)) {
|
|
8938
9353
|
return false;
|
|
8939
9354
|
}
|
|
8940
|
-
return !hasEquivalentCanonicalContent(codexResult, result, canonical, config, reverseCache);
|
|
9355
|
+
return !(hasEquivalentCanonicalContent(codexResult, result, canonical, config, reverseCache) || hasCanonicalSupersetContent(codexResult, result, canonical, config, reverseCache));
|
|
8941
9356
|
});
|
|
8942
9357
|
}
|
|
8943
9358
|
|
|
8944
9359
|
// src/core/reference/rewriter.ts
|
|
8945
9360
|
import { existsSync as existsSync3 } from "fs";
|
|
8946
|
-
import { dirname as dirname21, join as
|
|
9361
|
+
import { dirname as dirname21, join as join51 } from "path";
|
|
8947
9362
|
|
|
8948
9363
|
// src/core/reference/output-source-map.ts
|
|
8949
|
-
import { dirname as dirname20, join as
|
|
9364
|
+
import { dirname as dirname20, join as join50, normalize as normalizePath2 } from "path";
|
|
8950
9365
|
function canonicalRulePath(rule) {
|
|
8951
9366
|
return `.agentsmesh/rules/${rule.source.split("/").pop()}`;
|
|
8952
9367
|
}
|
|
@@ -8969,17 +9384,17 @@ function copilotInstructionsPath(rule) {
|
|
|
8969
9384
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
8970
9385
|
return `.github/instructions/${slug}.instructions.md`;
|
|
8971
9386
|
}
|
|
8972
|
-
function ruleOutputPaths(
|
|
9387
|
+
function ruleOutputPaths(target13, rule, refs) {
|
|
8973
9388
|
const paths = [];
|
|
8974
9389
|
const targetPath = refs.get(canonicalRulePath(rule));
|
|
8975
9390
|
if (targetPath) paths.push(targetPath);
|
|
8976
|
-
if (
|
|
9391
|
+
if (target13 === "copilot" && !rule.root && rule.globs.length > 0) {
|
|
8977
9392
|
paths.push(copilotInstructionsPath(rule));
|
|
8978
9393
|
}
|
|
8979
|
-
if ((
|
|
9394
|
+
if ((target13 === "cline" || target13 === "cursor") && rule.root) {
|
|
8980
9395
|
paths.push("AGENTS.md");
|
|
8981
9396
|
}
|
|
8982
|
-
if (
|
|
9397
|
+
if (target13 === "windsurf") {
|
|
8983
9398
|
if (rule.root) {
|
|
8984
9399
|
paths.push("AGENTS.md");
|
|
8985
9400
|
} else {
|
|
@@ -8987,10 +9402,10 @@ function ruleOutputPaths(target12, rule, refs) {
|
|
|
8987
9402
|
if (dir) paths.push(`${dir}/AGENTS.md`);
|
|
8988
9403
|
}
|
|
8989
9404
|
}
|
|
8990
|
-
if (
|
|
9405
|
+
if (target13 === "gemini-cli") {
|
|
8991
9406
|
paths.push(GEMINI_COMPAT_AGENTS);
|
|
8992
9407
|
}
|
|
8993
|
-
if (
|
|
9408
|
+
if (target13 === "codex-cli") {
|
|
8994
9409
|
if (!rule.root && rule.codexEmit === "execution") {
|
|
8995
9410
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
8996
9411
|
paths.push(`${CODEX_RULES_DIR}/${slug}.rules`);
|
|
@@ -8998,46 +9413,46 @@ function ruleOutputPaths(target12, rule, refs) {
|
|
|
8998
9413
|
}
|
|
8999
9414
|
return paths;
|
|
9000
9415
|
}
|
|
9001
|
-
function addPackSkillPaths(refs,
|
|
9002
|
-
const skillDir = SKILL_DIRS[
|
|
9416
|
+
function addPackSkillPaths(refs, target13, canonical, projectRoot) {
|
|
9417
|
+
const skillDir = SKILL_DIRS[target13];
|
|
9003
9418
|
if (!skillDir) return;
|
|
9004
|
-
const packsPrefix =
|
|
9419
|
+
const packsPrefix = join50(projectRoot, ".agentsmesh", "packs");
|
|
9005
9420
|
for (const skill of canonical.skills) {
|
|
9006
9421
|
const skillSourceDir = dirname20(skill.source);
|
|
9007
9422
|
if (!skillSourceDir.startsWith(packsPrefix)) continue;
|
|
9008
|
-
const targetSkillDir = normalizePath2(
|
|
9423
|
+
const targetSkillDir = normalizePath2(join50(projectRoot, skillDir, skill.name));
|
|
9009
9424
|
refs.set(normalizePath2(skillSourceDir), targetSkillDir);
|
|
9010
|
-
refs.set(normalizePath2(skill.source), normalizePath2(
|
|
9425
|
+
refs.set(normalizePath2(skill.source), normalizePath2(join50(targetSkillDir, "SKILL.md")));
|
|
9011
9426
|
for (const file of skill.supportingFiles) {
|
|
9012
|
-
const targetFilePath = normalizePath2(
|
|
9427
|
+
const targetFilePath = normalizePath2(join50(targetSkillDir, file.relativePath));
|
|
9013
9428
|
refs.set(normalizePath2(file.absolutePath), targetFilePath);
|
|
9014
9429
|
}
|
|
9015
9430
|
}
|
|
9016
9431
|
}
|
|
9017
|
-
function buildArtifactPathMap(
|
|
9432
|
+
function buildArtifactPathMap(target13, canonical, config, projectRoot, destinationPath) {
|
|
9018
9433
|
const refs = new Map(
|
|
9019
|
-
[...buildReferenceMap(
|
|
9020
|
-
normalizePath2(
|
|
9021
|
-
normalizePath2(
|
|
9434
|
+
[...buildReferenceMap(target13, canonical, config)].map(([canonicalPath, targetPath]) => [
|
|
9435
|
+
normalizePath2(join50(projectRoot, canonicalPath)),
|
|
9436
|
+
normalizePath2(join50(projectRoot, targetPath))
|
|
9022
9437
|
])
|
|
9023
9438
|
);
|
|
9024
|
-
if (
|
|
9439
|
+
if (target13 === "copilot" && destinationPath?.startsWith(".github/instructions/")) {
|
|
9025
9440
|
for (const rule of canonical.rules) {
|
|
9026
9441
|
if (rule.root || rule.globs.length === 0) continue;
|
|
9027
9442
|
refs.set(
|
|
9028
|
-
normalizePath2(
|
|
9029
|
-
normalizePath2(
|
|
9443
|
+
normalizePath2(join50(projectRoot, canonicalRulePath(rule))),
|
|
9444
|
+
normalizePath2(join50(projectRoot, copilotInstructionsPath(rule)))
|
|
9030
9445
|
);
|
|
9031
9446
|
}
|
|
9032
9447
|
}
|
|
9033
|
-
addPackSkillPaths(refs,
|
|
9448
|
+
addPackSkillPaths(refs, target13, canonical, projectRoot);
|
|
9034
9449
|
return refs;
|
|
9035
9450
|
}
|
|
9036
|
-
function buildOutputSourceMap(
|
|
9037
|
-
const refs = buildReferenceMap(
|
|
9451
|
+
function buildOutputSourceMap(target13, canonical, config) {
|
|
9452
|
+
const refs = buildReferenceMap(target13, canonical, config);
|
|
9038
9453
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
9039
9454
|
for (const rule of canonical.rules) {
|
|
9040
|
-
for (const targetPath of ruleOutputPaths(
|
|
9455
|
+
for (const targetPath of ruleOutputPaths(target13, rule, refs)) {
|
|
9041
9456
|
sourceMap.set(targetPath, rule.source);
|
|
9042
9457
|
}
|
|
9043
9458
|
}
|
|
@@ -9065,7 +9480,7 @@ function buildOutputSourceMap(target12, canonical, config) {
|
|
|
9065
9480
|
function collectPlannedPaths(projectRoot, results) {
|
|
9066
9481
|
const planned = /* @__PURE__ */ new Set();
|
|
9067
9482
|
for (const result of results) {
|
|
9068
|
-
const absolutePath =
|
|
9483
|
+
const absolutePath = join51(projectRoot, result.path);
|
|
9069
9484
|
planned.add(absolutePath);
|
|
9070
9485
|
let current = dirname21(absolutePath);
|
|
9071
9486
|
while (current.startsWith(projectRoot) && !planned.has(current)) {
|
|
@@ -9107,7 +9522,7 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot) {
|
|
|
9107
9522
|
content: result.content,
|
|
9108
9523
|
projectRoot,
|
|
9109
9524
|
sourceFile,
|
|
9110
|
-
destinationFile:
|
|
9525
|
+
destinationFile: join51(projectRoot, result.path),
|
|
9111
9526
|
translatePath: (absolutePath) => artifactMap.get(absolutePath) ?? absolutePath,
|
|
9112
9527
|
pathExists: (absolutePath) => plannedPaths.has(absolutePath) || existsSync3(absolutePath)
|
|
9113
9528
|
});
|
|
@@ -9116,6 +9531,8 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot) {
|
|
|
9116
9531
|
}
|
|
9117
9532
|
|
|
9118
9533
|
// src/core/generate/collision.ts
|
|
9534
|
+
var AGENTS_SUFFIX2 = "AGENTS.md";
|
|
9535
|
+
var CODEX_TARGET2 = "codex-cli";
|
|
9119
9536
|
function statusRank(status) {
|
|
9120
9537
|
switch (status) {
|
|
9121
9538
|
case "created":
|
|
@@ -9128,6 +9545,34 @@ function statusRank(status) {
|
|
|
9128
9545
|
return 0;
|
|
9129
9546
|
}
|
|
9130
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
|
+
}
|
|
9131
9576
|
function resolveOutputCollisions(results) {
|
|
9132
9577
|
const deduped = [];
|
|
9133
9578
|
for (const result of results) {
|
|
@@ -9138,17 +9583,21 @@ function resolveOutputCollisions(results) {
|
|
|
9138
9583
|
}
|
|
9139
9584
|
const existing = deduped[existingIdx];
|
|
9140
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
|
+
}
|
|
9141
9596
|
throw new Error(
|
|
9142
9597
|
`Conflicting generated outputs for ${result.path}: ${existing.target} and ${result.target} produce different content.`
|
|
9143
9598
|
);
|
|
9144
9599
|
}
|
|
9145
|
-
|
|
9146
|
-
deduped[existingIdx] = {
|
|
9147
|
-
...existing,
|
|
9148
|
-
status: result.status,
|
|
9149
|
-
currentContent: result.currentContent ?? existing.currentContent
|
|
9150
|
-
};
|
|
9151
|
-
}
|
|
9600
|
+
deduped[existingIdx] = mergeDuplicateMetadata(existing, result);
|
|
9152
9601
|
}
|
|
9153
9602
|
return deduped;
|
|
9154
9603
|
}
|
|
@@ -9158,7 +9607,7 @@ function refreshResultStatus(result) {
|
|
|
9158
9607
|
}
|
|
9159
9608
|
|
|
9160
9609
|
// src/core/generate/feature-loop.ts
|
|
9161
|
-
import { join as
|
|
9610
|
+
import { join as join52 } from "path";
|
|
9162
9611
|
function computeStatus(existing, content) {
|
|
9163
9612
|
if (existing === null) return "created";
|
|
9164
9613
|
if (existing !== content) return "updated";
|
|
@@ -9166,13 +9615,13 @@ function computeStatus(existing, content) {
|
|
|
9166
9615
|
}
|
|
9167
9616
|
async function generateFeature(results, targets, canonical, projectRoot, enabled, getGen) {
|
|
9168
9617
|
if (!enabled) return;
|
|
9169
|
-
for (const
|
|
9170
|
-
const gen = getGen(
|
|
9618
|
+
for (const target13 of targets) {
|
|
9619
|
+
const gen = getGen(target13);
|
|
9171
9620
|
if (!gen) continue;
|
|
9172
9621
|
for (const out of gen(canonical)) {
|
|
9173
|
-
const existing = await readFileSafe(
|
|
9622
|
+
const existing = await readFileSafe(join52(projectRoot, out.path));
|
|
9174
9623
|
results.push({
|
|
9175
|
-
target:
|
|
9624
|
+
target: target13,
|
|
9176
9625
|
path: out.path,
|
|
9177
9626
|
content: out.content,
|
|
9178
9627
|
currentContent: existing ?? void 0,
|
|
@@ -9190,8 +9639,8 @@ function getDescriptor(name) {
|
|
|
9190
9639
|
return descriptorRegistry.get(name) ?? builtinDescriptors.get(name);
|
|
9191
9640
|
}
|
|
9192
9641
|
function getTarget(name) {
|
|
9193
|
-
const
|
|
9194
|
-
if (
|
|
9642
|
+
const descriptor13 = getDescriptor(name);
|
|
9643
|
+
if (descriptor13) return descriptor13.generators;
|
|
9195
9644
|
const legacy = legacyRegistry.get(name);
|
|
9196
9645
|
if (legacy) return legacy;
|
|
9197
9646
|
throw new Error(`Unknown target: ${name}`);
|
|
@@ -9215,10 +9664,10 @@ function decoratePrimaryRootInstructions(results) {
|
|
|
9215
9664
|
}
|
|
9216
9665
|
|
|
9217
9666
|
// src/core/generate/optional-features.ts
|
|
9218
|
-
import { join as
|
|
9667
|
+
import { join as join54 } from "path";
|
|
9219
9668
|
|
|
9220
9669
|
// src/targets/copilot/hook-assets.ts
|
|
9221
|
-
import { join as
|
|
9670
|
+
import { join as join53, relative as relative19 } from "path";
|
|
9222
9671
|
var SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
|
|
9223
9672
|
function safePhaseName(phase) {
|
|
9224
9673
|
return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
@@ -9239,7 +9688,7 @@ async function buildAssetOutput(projectRoot, command) {
|
|
|
9239
9688
|
const match = command.match(SCRIPT_PREFIX_RE);
|
|
9240
9689
|
const sourceToken = match?.groups?.["path"];
|
|
9241
9690
|
if (!sourceToken) return null;
|
|
9242
|
-
const sourcePath =
|
|
9691
|
+
const sourcePath = join53(projectRoot, sourceToken);
|
|
9243
9692
|
const assetContent = await readFileSafe(sourcePath);
|
|
9244
9693
|
if (assetContent === null) return null;
|
|
9245
9694
|
const repoRelative = toRepoRelative(projectRoot, sourcePath);
|
|
@@ -9327,14 +9776,14 @@ function mergeGeminiSettingsJson(existing, newContent) {
|
|
|
9327
9776
|
|
|
9328
9777
|
// src/core/generate/optional-features.ts
|
|
9329
9778
|
async function generatePermissionsFeature(results, targets, canonical, projectRoot) {
|
|
9330
|
-
for (const
|
|
9331
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9779
|
+
for (const target13 of targets) {
|
|
9780
|
+
const gen = resolveTargetFeatureGenerator(target13, "permissions");
|
|
9332
9781
|
if (!gen) continue;
|
|
9333
9782
|
for (const out of gen(canonical)) {
|
|
9334
|
-
const existing = await readFileSafe(
|
|
9783
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9335
9784
|
const content = existing !== null && SETTINGS_JSON_PATHS.includes(out.path) ? mergeSettingsJson(existing, out.content) : out.content;
|
|
9336
9785
|
results.push({
|
|
9337
|
-
target:
|
|
9786
|
+
target: target13,
|
|
9338
9787
|
path: out.path,
|
|
9339
9788
|
content,
|
|
9340
9789
|
currentContent: existing ?? void 0,
|
|
@@ -9344,15 +9793,15 @@ async function generatePermissionsFeature(results, targets, canonical, projectRo
|
|
|
9344
9793
|
}
|
|
9345
9794
|
}
|
|
9346
9795
|
async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
9347
|
-
for (const
|
|
9348
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9796
|
+
for (const target13 of targets) {
|
|
9797
|
+
const gen = resolveTargetFeatureGenerator(target13, "hooks");
|
|
9349
9798
|
if (!gen) continue;
|
|
9350
|
-
const outputs =
|
|
9799
|
+
const outputs = target13 === "copilot" ? await addHookScriptAssets(projectRoot, canonical, gen(canonical)) : gen(canonical);
|
|
9351
9800
|
for (const out of outputs) {
|
|
9352
|
-
const existing = await readFileSafe(
|
|
9801
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9353
9802
|
let content = out.content;
|
|
9354
9803
|
if (SETTINGS_JSON_PATHS.includes(out.path)) {
|
|
9355
|
-
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target ===
|
|
9804
|
+
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target === target13);
|
|
9356
9805
|
const pendingResult = pendingIdx >= 0 ? results[pendingIdx] : void 0;
|
|
9357
9806
|
const base = pendingResult?.content ?? existing;
|
|
9358
9807
|
if (base !== null) {
|
|
@@ -9363,7 +9812,7 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9363
9812
|
}
|
|
9364
9813
|
}
|
|
9365
9814
|
results.push({
|
|
9366
|
-
target:
|
|
9815
|
+
target: target13,
|
|
9367
9816
|
path: out.path,
|
|
9368
9817
|
content,
|
|
9369
9818
|
currentContent: existing ?? void 0,
|
|
@@ -9373,17 +9822,17 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9373
9822
|
}
|
|
9374
9823
|
}
|
|
9375
9824
|
async function generateGeminiSettingsFeature(results, targets, canonical, projectRoot) {
|
|
9376
|
-
for (const
|
|
9377
|
-
if (
|
|
9378
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9825
|
+
for (const target13 of targets) {
|
|
9826
|
+
if (target13 !== "gemini-cli") continue;
|
|
9827
|
+
const gen = resolveTargetFeatureGenerator(target13, "settings");
|
|
9379
9828
|
if (!gen) continue;
|
|
9380
9829
|
const outputs = gen(canonical);
|
|
9381
9830
|
if (outputs.length === 0) continue;
|
|
9382
9831
|
for (const out of outputs) {
|
|
9383
|
-
const existing = await readFileSafe(
|
|
9832
|
+
const existing = await readFileSafe(join54(projectRoot, out.path));
|
|
9384
9833
|
const content = existing !== null && out.path === GEMINI_SETTINGS ? mergeGeminiSettingsJson(existing, out.content) : out.content;
|
|
9385
9834
|
results.push({
|
|
9386
|
-
target:
|
|
9835
|
+
target: target13,
|
|
9387
9836
|
path: out.path,
|
|
9388
9837
|
content,
|
|
9389
9838
|
currentContent: existing ?? void 0,
|
|
@@ -9412,7 +9861,7 @@ async function generate(ctx) {
|
|
|
9412
9861
|
canonical,
|
|
9413
9862
|
projectRoot,
|
|
9414
9863
|
hasRules,
|
|
9415
|
-
(
|
|
9864
|
+
(target13) => resolveTargetFeatureGenerator(target13, "rules", config)
|
|
9416
9865
|
);
|
|
9417
9866
|
await generateFeature(
|
|
9418
9867
|
results,
|
|
@@ -9420,7 +9869,7 @@ async function generate(ctx) {
|
|
|
9420
9869
|
canonical,
|
|
9421
9870
|
projectRoot,
|
|
9422
9871
|
hasCommands,
|
|
9423
|
-
(
|
|
9872
|
+
(target13) => resolveTargetFeatureGenerator(target13, "commands", config)
|
|
9424
9873
|
);
|
|
9425
9874
|
await generateFeature(
|
|
9426
9875
|
results,
|
|
@@ -9428,7 +9877,7 @@ async function generate(ctx) {
|
|
|
9428
9877
|
canonical,
|
|
9429
9878
|
projectRoot,
|
|
9430
9879
|
hasAgents,
|
|
9431
|
-
(
|
|
9880
|
+
(target13) => resolveTargetFeatureGenerator(target13, "agents", config)
|
|
9432
9881
|
);
|
|
9433
9882
|
await generateFeature(
|
|
9434
9883
|
results,
|
|
@@ -9436,7 +9885,7 @@ async function generate(ctx) {
|
|
|
9436
9885
|
canonical,
|
|
9437
9886
|
projectRoot,
|
|
9438
9887
|
hasSkills,
|
|
9439
|
-
(
|
|
9888
|
+
(target13) => resolveTargetFeatureGenerator(target13, "skills", config)
|
|
9440
9889
|
);
|
|
9441
9890
|
await generateFeature(
|
|
9442
9891
|
results,
|
|
@@ -9444,7 +9893,7 @@ async function generate(ctx) {
|
|
|
9444
9893
|
canonical,
|
|
9445
9894
|
projectRoot,
|
|
9446
9895
|
hasMcp,
|
|
9447
|
-
(
|
|
9896
|
+
(target13) => resolveTargetFeatureGenerator(target13, "mcp", config)
|
|
9448
9897
|
);
|
|
9449
9898
|
if (hasPermissions) await generatePermissionsFeature(results, targets, canonical, projectRoot);
|
|
9450
9899
|
if (hasHooks) await generateHooksFeature(results, targets, canonical, projectRoot);
|
|
@@ -9454,7 +9903,7 @@ async function generate(ctx) {
|
|
|
9454
9903
|
canonical,
|
|
9455
9904
|
projectRoot,
|
|
9456
9905
|
hasIgnore,
|
|
9457
|
-
(
|
|
9906
|
+
(target13) => resolveTargetFeatureGenerator(target13, "ignore", config)
|
|
9458
9907
|
);
|
|
9459
9908
|
if (hasMcp || hasIgnore || hasHooks || hasAgents) {
|
|
9460
9909
|
await generateGeminiSettingsFeature(results, targets, canonical, projectRoot);
|
|
@@ -9466,7 +9915,7 @@ async function generate(ctx) {
|
|
|
9466
9915
|
|
|
9467
9916
|
// src/core/generate/stale-cleanup.ts
|
|
9468
9917
|
import { readdir as readdir12, rm as rm6 } from "fs/promises";
|
|
9469
|
-
import { join as
|
|
9918
|
+
import { join as join55, relative as relative20 } from "path";
|
|
9470
9919
|
var TARGET_MANAGED_OUTPUTS = {
|
|
9471
9920
|
"claude-code": {
|
|
9472
9921
|
dirs: [".claude/agents", ".claude/commands", ".claude/rules", ".claude/skills"],
|
|
@@ -9494,6 +9943,10 @@ var TARGET_MANAGED_OUTPUTS = {
|
|
|
9494
9943
|
dirs: [".junie/agents", ".junie/commands", ".junie/rules", ".junie/skills"],
|
|
9495
9944
|
files: [".aiignore", ".junie/AGENTS.md", ".junie/mcp/mcp.json"]
|
|
9496
9945
|
},
|
|
9946
|
+
kiro: {
|
|
9947
|
+
dirs: [".kiro/hooks", ".kiro/skills", ".kiro/steering"],
|
|
9948
|
+
files: ["AGENTS.md", ".kiro/settings/mcp.json", ".kiroignore"]
|
|
9949
|
+
},
|
|
9497
9950
|
"gemini-cli": {
|
|
9498
9951
|
dirs: [".gemini/agents", ".gemini/commands", ".gemini/skills"],
|
|
9499
9952
|
files: [
|
|
@@ -9532,7 +9985,7 @@ async function listFiles2(root, base = root) {
|
|
|
9532
9985
|
const entries = await readdir12(root, { withFileTypes: true });
|
|
9533
9986
|
const files = [];
|
|
9534
9987
|
for (const entry of entries) {
|
|
9535
|
-
const abs =
|
|
9988
|
+
const abs = join55(root, entry.name);
|
|
9536
9989
|
if (entry.isDirectory()) {
|
|
9537
9990
|
files.push(...await listFiles2(abs, base));
|
|
9538
9991
|
continue;
|
|
@@ -9543,18 +9996,18 @@ async function listFiles2(root, base = root) {
|
|
|
9543
9996
|
}
|
|
9544
9997
|
async function removeIfStale(projectRoot, relPath, expected) {
|
|
9545
9998
|
if (expected.has(relPath)) return;
|
|
9546
|
-
const abs =
|
|
9999
|
+
const abs = join55(projectRoot, relPath);
|
|
9547
10000
|
if (await exists(abs)) await rm6(abs, { recursive: true, force: true });
|
|
9548
10001
|
}
|
|
9549
10002
|
async function cleanupStaleGeneratedOutputs(args) {
|
|
9550
10003
|
const expected = new Set(args.expectedPaths);
|
|
9551
10004
|
const stale = /* @__PURE__ */ new Set();
|
|
9552
|
-
for (const
|
|
9553
|
-
const managed = TARGET_MANAGED_OUTPUTS[
|
|
10005
|
+
for (const target13 of args.targets) {
|
|
10006
|
+
const managed = TARGET_MANAGED_OUTPUTS[target13];
|
|
9554
10007
|
if (!managed) continue;
|
|
9555
10008
|
for (const file of managed.files) stale.add(file);
|
|
9556
10009
|
for (const dir of managed.dirs) {
|
|
9557
|
-
const absDir =
|
|
10010
|
+
const absDir = join55(args.projectRoot, dir);
|
|
9558
10011
|
if (!await exists(absDir)) continue;
|
|
9559
10012
|
for (const file of await listFiles2(absDir)) {
|
|
9560
10013
|
stale.add(`${dir}/${file}`.replace(/\/+/g, "/"));
|
|
@@ -9567,17 +10020,17 @@ async function cleanupStaleGeneratedOutputs(args) {
|
|
|
9567
10020
|
}
|
|
9568
10021
|
|
|
9569
10022
|
// src/core/matrix/matrix.ts
|
|
9570
|
-
import { basename as
|
|
10023
|
+
import { basename as basename32 } from "path";
|
|
9571
10024
|
|
|
9572
10025
|
// src/targets/catalog/target-catalog.ts
|
|
9573
10026
|
var TARGET_CATALOG = Object.fromEntries(
|
|
9574
|
-
BUILTIN_TARGETS.map((
|
|
9575
|
-
|
|
10027
|
+
BUILTIN_TARGETS.map((target13) => [
|
|
10028
|
+
target13.id,
|
|
9576
10029
|
{
|
|
9577
|
-
importFrom:
|
|
9578
|
-
emptyImportMessage:
|
|
9579
|
-
lintRules:
|
|
9580
|
-
capabilities:
|
|
10030
|
+
importFrom: target13.generators.importFrom,
|
|
10031
|
+
emptyImportMessage: target13.emptyImportMessage,
|
|
10032
|
+
lintRules: target13.lintRules,
|
|
10033
|
+
capabilities: target13.capabilities
|
|
9581
10034
|
}
|
|
9582
10035
|
])
|
|
9583
10036
|
);
|
|
@@ -9604,7 +10057,7 @@ var SUPPORT_MATRIX = Object.fromEntries(
|
|
|
9604
10057
|
FEATURE_IDS.map((feature) => [
|
|
9605
10058
|
feature,
|
|
9606
10059
|
Object.fromEntries(
|
|
9607
|
-
TARGET_IDS.map((
|
|
10060
|
+
TARGET_IDS.map((target13) => [target13, TARGET_CATALOG[target13].capabilities[feature]])
|
|
9608
10061
|
)
|
|
9609
10062
|
])
|
|
9610
10063
|
);
|
|
@@ -9710,13 +10163,13 @@ function formatMatrix(rows, targets) {
|
|
|
9710
10163
|
function formatVerboseDetails(canonical) {
|
|
9711
10164
|
const lines = [];
|
|
9712
10165
|
if (canonical.rules.length > 0) {
|
|
9713
|
-
lines.push(`rules: ${canonical.rules.map((r) =>
|
|
10166
|
+
lines.push(`rules: ${canonical.rules.map((r) => basename32(r.source)).join(", ")}`);
|
|
9714
10167
|
}
|
|
9715
10168
|
if (canonical.commands.length > 0) {
|
|
9716
|
-
lines.push(`commands: ${canonical.commands.map((c2) =>
|
|
10169
|
+
lines.push(`commands: ${canonical.commands.map((c2) => basename32(c2.source)).join(", ")}`);
|
|
9717
10170
|
}
|
|
9718
10171
|
if (canonical.agents.length > 0) {
|
|
9719
|
-
lines.push(`agents: ${canonical.agents.map((a) =>
|
|
10172
|
+
lines.push(`agents: ${canonical.agents.map((a) => basename32(a.source)).join(", ")}`);
|
|
9720
10173
|
}
|
|
9721
10174
|
if (canonical.skills.length > 0) {
|
|
9722
10175
|
lines.push(`skills: ${canonical.skills.map((s) => s.name).join(", ")}`);
|
|
@@ -9768,11 +10221,11 @@ async function runMatrix(flags, projectRoot) {
|
|
|
9768
10221
|
}
|
|
9769
10222
|
|
|
9770
10223
|
// src/cli/commands/generate.ts
|
|
9771
|
-
function ensurePathInsideRoot(rootDir, relativePath,
|
|
10224
|
+
function ensurePathInsideRoot(rootDir, relativePath, target13) {
|
|
9772
10225
|
const rootAbs = resolve4(rootDir);
|
|
9773
10226
|
const outputAbs = resolve4(rootDir, relativePath);
|
|
9774
10227
|
if (outputAbs === rootAbs || outputAbs.startsWith(`${rootAbs}${sep}`)) return outputAbs;
|
|
9775
|
-
throw new Error(`Unsafe generated output path for ${
|
|
10228
|
+
throw new Error(`Unsafe generated output path for ${target13}: ${relativePath}`);
|
|
9776
10229
|
}
|
|
9777
10230
|
async function runGenerate(flags, projectRoot, options = {}) {
|
|
9778
10231
|
if (flags.features !== void 0) {
|
|
@@ -9788,7 +10241,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9788
10241
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
9789
10242
|
const lockFeatures = config.collaboration?.lock_features ?? [];
|
|
9790
10243
|
if (config.collaboration?.strategy === "lock" && !force && lockFeatures.length > 0) {
|
|
9791
|
-
const abDir =
|
|
10244
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9792
10245
|
const existingLock = await readLock(abDir);
|
|
9793
10246
|
if (existingLock !== null) {
|
|
9794
10247
|
const currentChecksums = await buildChecksums(abDir);
|
|
@@ -9824,10 +10277,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9824
10277
|
return 0;
|
|
9825
10278
|
}
|
|
9826
10279
|
if (!dryRun) {
|
|
9827
|
-
const abDir =
|
|
10280
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9828
10281
|
const checksums = await buildChecksums(abDir);
|
|
9829
10282
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9830
|
-
const packChecksums = await buildPackChecksums(
|
|
10283
|
+
const packChecksums = await buildPackChecksums(join56(abDir, "packs"));
|
|
9831
10284
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9832
10285
|
await writeLock(abDir, {
|
|
9833
10286
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9838,7 +10291,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9838
10291
|
packs: packChecksums
|
|
9839
10292
|
});
|
|
9840
10293
|
try {
|
|
9841
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
10294
|
+
await ensureCacheSymlink(getCacheDir(), join56(configDir, ".agentsmeshcache"));
|
|
9842
10295
|
} catch (err) {
|
|
9843
10296
|
logger.warn(
|
|
9844
10297
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9885,10 +10338,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9885
10338
|
} else {
|
|
9886
10339
|
logger.info(`Nothing changed. (${unchanged} unchanged)`);
|
|
9887
10340
|
}
|
|
9888
|
-
const abDir =
|
|
10341
|
+
const abDir = join56(configDir, ".agentsmesh");
|
|
9889
10342
|
const checksums = await buildChecksums(abDir);
|
|
9890
10343
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9891
|
-
const packChecksums = await buildPackChecksums(
|
|
10344
|
+
const packChecksums = await buildPackChecksums(join56(abDir, "packs"));
|
|
9892
10345
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9893
10346
|
await writeLock(abDir, {
|
|
9894
10347
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9899,7 +10352,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9899
10352
|
packs: packChecksums
|
|
9900
10353
|
});
|
|
9901
10354
|
try {
|
|
9902
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
10355
|
+
await ensureCacheSymlink(getCacheDir(), join56(configDir, ".agentsmeshcache"));
|
|
9903
10356
|
} catch (err) {
|
|
9904
10357
|
logger.warn(
|
|
9905
10358
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9913,7 +10366,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9913
10366
|
}
|
|
9914
10367
|
|
|
9915
10368
|
// src/cli/commands/init.ts
|
|
9916
|
-
import { join as
|
|
10369
|
+
import { join as join59 } from "path";
|
|
9917
10370
|
|
|
9918
10371
|
// src/cli/commands/init-templates.ts
|
|
9919
10372
|
var ALL_FEATURES = [
|
|
@@ -9926,8 +10379,9 @@ var ALL_FEATURES = [
|
|
|
9926
10379
|
"ignore",
|
|
9927
10380
|
"permissions"
|
|
9928
10381
|
];
|
|
10382
|
+
var DEFAULT_INIT_TARGETS = TARGET_IDS.filter((target13) => target13 !== "codex-cli");
|
|
9929
10383
|
function buildConfig(targets) {
|
|
9930
|
-
const targetList = (targets.length > 0 ? targets :
|
|
10384
|
+
const targetList = (targets.length > 0 ? targets : DEFAULT_INIT_TARGETS).map((t) => ` - ${t}`).join("\n");
|
|
9931
10385
|
const featureList = ALL_FEATURES.map((f) => ` - ${f}`).join("\n");
|
|
9932
10386
|
return `version: 1
|
|
9933
10387
|
targets:
|
|
@@ -10058,7 +10512,7 @@ var LOCAL_TEMPLATE = `# Personal overrides \u2014 NOT committed to git
|
|
|
10058
10512
|
`;
|
|
10059
10513
|
|
|
10060
10514
|
// src/cli/commands/init-detect.ts
|
|
10061
|
-
import { join as
|
|
10515
|
+
import { join as join57 } from "path";
|
|
10062
10516
|
var TOOL_INDICATORS = BUILTIN_TARGETS.map((d) => ({
|
|
10063
10517
|
id: d.id,
|
|
10064
10518
|
paths: [...d.detectionPaths]
|
|
@@ -10067,7 +10521,7 @@ async function detectExistingConfigs(projectRoot) {
|
|
|
10067
10521
|
const found = [];
|
|
10068
10522
|
for (const { id, paths } of TOOL_INDICATORS) {
|
|
10069
10523
|
for (const p of paths) {
|
|
10070
|
-
const full =
|
|
10524
|
+
const full = join57(projectRoot, p);
|
|
10071
10525
|
if (await exists(full)) {
|
|
10072
10526
|
found.push(id);
|
|
10073
10527
|
break;
|
|
@@ -10077,6 +10531,110 @@ async function detectExistingConfigs(projectRoot) {
|
|
|
10077
10531
|
return [...new Set(found)];
|
|
10078
10532
|
}
|
|
10079
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
|
+
|
|
10080
10638
|
// src/cli/commands/init.ts
|
|
10081
10639
|
var CONFIG_FILENAME2 = "agentsmesh.yaml";
|
|
10082
10640
|
var LOCAL_CONFIG_FILENAME2 = "agentsmesh.local.yaml";
|
|
@@ -10085,7 +10643,7 @@ var IMPORTERS = Object.fromEntries(
|
|
|
10085
10643
|
BUILTIN_TARGETS.map((d) => [d.id, (root) => d.generators.importFrom(root)])
|
|
10086
10644
|
);
|
|
10087
10645
|
async function appendToGitignore(projectRoot) {
|
|
10088
|
-
const gitignorePath =
|
|
10646
|
+
const gitignorePath = join59(projectRoot, ".gitignore");
|
|
10089
10647
|
const current = await readFileSafe(gitignorePath) ?? "";
|
|
10090
10648
|
const lines = new Set(current.split("\n").map((s) => s.trim()));
|
|
10091
10649
|
const toAdd = GITIGNORE_ENTRIES.filter((e) => !lines.has(e));
|
|
@@ -10093,33 +10651,8 @@ async function appendToGitignore(projectRoot) {
|
|
|
10093
10651
|
const suffix = current.endsWith("\n") || current === "" ? "" : "\n";
|
|
10094
10652
|
await writeFileAtomic(gitignorePath, current + suffix + toAdd.join("\n") + "\n");
|
|
10095
10653
|
}
|
|
10096
|
-
async function writeScaffold(projectRoot) {
|
|
10097
|
-
const ab = (rel2) => join57(projectRoot, ".agentsmesh", rel2);
|
|
10098
|
-
await mkdirp(ab("rules"));
|
|
10099
|
-
await writeFileAtomic(ab("rules/_root.md"), TEMPLATE_ROOT_RULE);
|
|
10100
|
-
logger.success("Created .agentsmesh/rules/_root.md");
|
|
10101
|
-
await writeFileAtomic(ab("rules/example.md"), TEMPLATE_EXAMPLE_RULE);
|
|
10102
|
-
logger.success("Created .agentsmesh/rules/example.md");
|
|
10103
|
-
await mkdirp(ab("commands"));
|
|
10104
|
-
await writeFileAtomic(ab("commands/example.md"), TEMPLATE_EXAMPLE_COMMAND);
|
|
10105
|
-
logger.success("Created .agentsmesh/commands/example.md");
|
|
10106
|
-
await mkdirp(ab("agents"));
|
|
10107
|
-
await writeFileAtomic(ab("agents/example.md"), TEMPLATE_EXAMPLE_AGENT);
|
|
10108
|
-
logger.success("Created .agentsmesh/agents/example.md");
|
|
10109
|
-
await mkdirp(ab("skills/example"));
|
|
10110
|
-
await writeFileAtomic(ab("skills/example/SKILL.md"), TEMPLATE_EXAMPLE_SKILL);
|
|
10111
|
-
logger.success("Created .agentsmesh/skills/example/SKILL.md");
|
|
10112
|
-
await writeFileAtomic(ab("mcp.json"), TEMPLATE_MCP);
|
|
10113
|
-
logger.success("Created .agentsmesh/mcp.json");
|
|
10114
|
-
await writeFileAtomic(ab("hooks.yaml"), TEMPLATE_HOOKS);
|
|
10115
|
-
logger.success("Created .agentsmesh/hooks.yaml");
|
|
10116
|
-
await writeFileAtomic(ab("permissions.yaml"), TEMPLATE_PERMISSIONS);
|
|
10117
|
-
logger.success("Created .agentsmesh/permissions.yaml");
|
|
10118
|
-
await writeFileAtomic(ab("ignore"), TEMPLATE_IGNORE);
|
|
10119
|
-
logger.success("Created .agentsmesh/ignore");
|
|
10120
|
-
}
|
|
10121
10654
|
async function runInit(projectRoot, options = {}) {
|
|
10122
|
-
const configPath =
|
|
10655
|
+
const configPath = join59(projectRoot, CONFIG_FILENAME2);
|
|
10123
10656
|
if (await exists(configPath)) {
|
|
10124
10657
|
throw new Error(`Already initialized. ${CONFIG_FILENAME2} exists. Remove it first to re-init.`);
|
|
10125
10658
|
}
|
|
@@ -10141,22 +10674,23 @@ async function runInit(projectRoot, options = {}) {
|
|
|
10141
10674
|
if (totalImported > 0) {
|
|
10142
10675
|
logger.info(`Imported ${totalImported} file(s) from ${existing.length} tool(s).`);
|
|
10143
10676
|
}
|
|
10677
|
+
await writeScaffoldGapFill(projectRoot);
|
|
10144
10678
|
await writeFileAtomic(configPath, buildConfig(existing));
|
|
10145
10679
|
logger.success(`Created ${CONFIG_FILENAME2} (targets: ${existing.join(", ")})`);
|
|
10146
10680
|
} else {
|
|
10147
10681
|
logger.info(
|
|
10148
10682
|
`Run 'agentsmesh init --yes' to auto-import, or 'agentsmesh import --from <tool>' manually.`
|
|
10149
10683
|
);
|
|
10150
|
-
await
|
|
10684
|
+
await writeScaffoldFull(projectRoot);
|
|
10151
10685
|
await writeFileAtomic(configPath, buildConfig([]));
|
|
10152
10686
|
logger.success(`Created ${CONFIG_FILENAME2}`);
|
|
10153
10687
|
}
|
|
10154
10688
|
} else {
|
|
10155
|
-
await
|
|
10689
|
+
await writeScaffoldFull(projectRoot);
|
|
10156
10690
|
await writeFileAtomic(configPath, buildConfig([]));
|
|
10157
10691
|
logger.success(`Created ${CONFIG_FILENAME2}`);
|
|
10158
10692
|
}
|
|
10159
|
-
const localPath =
|
|
10693
|
+
const localPath = join59(projectRoot, LOCAL_CONFIG_FILENAME2);
|
|
10160
10694
|
await writeFileAtomic(localPath, LOCAL_TEMPLATE);
|
|
10161
10695
|
logger.success(`Created ${LOCAL_CONFIG_FILENAME2}`);
|
|
10162
10696
|
await appendToGitignore(projectRoot);
|
|
@@ -10175,10 +10709,10 @@ async function runImport(flags, projectRoot) {
|
|
|
10175
10709
|
if (!isBuiltinTargetId(normalized)) {
|
|
10176
10710
|
throw new Error(`Unknown --from "${from}". Supported: ${TARGET_IDS.join(", ")}.`);
|
|
10177
10711
|
}
|
|
10178
|
-
const
|
|
10179
|
-
const results = await
|
|
10712
|
+
const target13 = getTargetCatalogEntry(normalized);
|
|
10713
|
+
const results = await target13.importFrom(root);
|
|
10180
10714
|
if (results.length === 0) {
|
|
10181
|
-
logger.info(
|
|
10715
|
+
logger.info(target13.emptyImportMessage);
|
|
10182
10716
|
return;
|
|
10183
10717
|
}
|
|
10184
10718
|
for (const r of results) {
|
|
@@ -10263,56 +10797,56 @@ async function runDiff(flags, projectRoot) {
|
|
|
10263
10797
|
import { relative as relative22 } from "path";
|
|
10264
10798
|
|
|
10265
10799
|
// src/core/lint/commands.ts
|
|
10266
|
-
function lintCommands(canonical,
|
|
10800
|
+
function lintCommands(canonical, target13) {
|
|
10267
10801
|
if (canonical.commands.length === 0) return [];
|
|
10268
10802
|
return canonical.commands.flatMap((command) => {
|
|
10269
|
-
if (
|
|
10803
|
+
if (target13 === "copilot" && command.allowedTools.length > 0) {
|
|
10270
10804
|
return [
|
|
10271
10805
|
{
|
|
10272
10806
|
level: "warning",
|
|
10273
10807
|
file: command.source,
|
|
10274
|
-
target:
|
|
10808
|
+
target: target13,
|
|
10275
10809
|
message: "Copilot prompt files do not enforce canonical allowed-tools natively."
|
|
10276
10810
|
}
|
|
10277
10811
|
];
|
|
10278
10812
|
}
|
|
10279
|
-
if (
|
|
10813
|
+
if (target13 === "cursor" && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
10280
10814
|
return [
|
|
10281
10815
|
{
|
|
10282
10816
|
level: "warning",
|
|
10283
10817
|
file: command.source,
|
|
10284
|
-
target:
|
|
10818
|
+
target: target13,
|
|
10285
10819
|
message: "Cursor command files are plain Markdown; command description and allowed-tools metadata are not projected."
|
|
10286
10820
|
}
|
|
10287
10821
|
];
|
|
10288
10822
|
}
|
|
10289
|
-
if (
|
|
10823
|
+
if (target13 === "gemini-cli" && command.allowedTools.length > 0) {
|
|
10290
10824
|
return [
|
|
10291
10825
|
{
|
|
10292
10826
|
level: "warning",
|
|
10293
10827
|
file: command.source,
|
|
10294
|
-
target:
|
|
10828
|
+
target: target13,
|
|
10295
10829
|
message: "Gemini TOML command files do not project canonical allowed-tools metadata."
|
|
10296
10830
|
}
|
|
10297
10831
|
];
|
|
10298
10832
|
}
|
|
10299
|
-
if (
|
|
10833
|
+
if (target13 === "continue" && command.allowedTools.length > 0) {
|
|
10300
10834
|
return [
|
|
10301
10835
|
{
|
|
10302
10836
|
level: "warning",
|
|
10303
10837
|
file: command.source,
|
|
10304
|
-
target:
|
|
10838
|
+
target: target13,
|
|
10305
10839
|
message: "Continue invokable prompt rules do not natively enforce canonical allowed-tools metadata."
|
|
10306
10840
|
}
|
|
10307
10841
|
];
|
|
10308
10842
|
}
|
|
10309
|
-
if (["cline", "windsurf"].includes(
|
|
10843
|
+
if (["cline", "windsurf"].includes(target13) && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
10310
10844
|
return [
|
|
10311
10845
|
{
|
|
10312
10846
|
level: "warning",
|
|
10313
10847
|
file: command.source,
|
|
10314
|
-
target:
|
|
10315
|
-
message: `${
|
|
10848
|
+
target: target13,
|
|
10849
|
+
message: `${target13} workflow files are plain Markdown; command description and allowed-tools metadata are not projected.`
|
|
10316
10850
|
}
|
|
10317
10851
|
];
|
|
10318
10852
|
}
|
|
@@ -10321,48 +10855,48 @@ function lintCommands(canonical, target12) {
|
|
|
10321
10855
|
}
|
|
10322
10856
|
|
|
10323
10857
|
// src/core/lint/mcp.ts
|
|
10324
|
-
function lintMcp(canonical,
|
|
10858
|
+
function lintMcp(canonical, target13) {
|
|
10325
10859
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
10326
10860
|
const diagnostics = [];
|
|
10327
10861
|
for (const [name, server] of Object.entries(canonical.mcp.mcpServers)) {
|
|
10328
|
-
if (
|
|
10862
|
+
if (target13 === "cursor" && usesCursorSensitiveInterpolation(server)) {
|
|
10329
10863
|
diagnostics.push({
|
|
10330
10864
|
level: "warning",
|
|
10331
10865
|
file: ".agentsmesh/mcp.json",
|
|
10332
|
-
target:
|
|
10866
|
+
target: target13,
|
|
10333
10867
|
message: `MCP server "${name}" uses env vars or URL/header interpolation; Cursor handling may differ from canonical MCP.`
|
|
10334
10868
|
});
|
|
10335
10869
|
}
|
|
10336
|
-
if (
|
|
10870
|
+
if (target13 === "codex-cli" && typeof server.description === "string" && server.description) {
|
|
10337
10871
|
diagnostics.push({
|
|
10338
10872
|
level: "warning",
|
|
10339
10873
|
file: ".agentsmesh/mcp.json",
|
|
10340
|
-
target:
|
|
10874
|
+
target: target13,
|
|
10341
10875
|
message: `MCP server "${name}" has a description, but codex-cli does not project MCP descriptions into .codex/config.toml.`
|
|
10342
10876
|
});
|
|
10343
10877
|
}
|
|
10344
|
-
if (
|
|
10878
|
+
if (target13 === "codex-cli" && isUrlMcpServer(server)) {
|
|
10345
10879
|
diagnostics.push({
|
|
10346
10880
|
level: "warning",
|
|
10347
10881
|
file: ".agentsmesh/mcp.json",
|
|
10348
|
-
target:
|
|
10882
|
+
target: target13,
|
|
10349
10883
|
message: `MCP server "${name}" uses ${server.type} transport; codex-cli only generates stdio MCP servers.`
|
|
10350
10884
|
});
|
|
10351
10885
|
}
|
|
10352
|
-
if (
|
|
10886
|
+
if (target13 === "junie" && isUrlMcpServer(server)) {
|
|
10353
10887
|
diagnostics.push({
|
|
10354
10888
|
level: "warning",
|
|
10355
10889
|
file: ".agentsmesh/mcp.json",
|
|
10356
|
-
target:
|
|
10890
|
+
target: target13,
|
|
10357
10891
|
message: `MCP server "${name}" uses ${server.type} transport; Junie project mcp.json currently documents stdio MCP servers only.`
|
|
10358
10892
|
});
|
|
10359
10893
|
}
|
|
10360
10894
|
}
|
|
10361
|
-
if (
|
|
10895
|
+
if (target13 === "windsurf") {
|
|
10362
10896
|
diagnostics.push({
|
|
10363
10897
|
level: "warning",
|
|
10364
10898
|
file: ".agentsmesh/mcp.json",
|
|
10365
|
-
target:
|
|
10899
|
+
target: target13,
|
|
10366
10900
|
message: "Windsurf MCP is partial; generated .windsurf/mcp_config.example.json is a reference artifact and may require manual setup."
|
|
10367
10901
|
});
|
|
10368
10902
|
}
|
|
@@ -10370,42 +10904,51 @@ function lintMcp(canonical, target12) {
|
|
|
10370
10904
|
}
|
|
10371
10905
|
|
|
10372
10906
|
// src/core/lint/permissions.ts
|
|
10373
|
-
function lintPermissions(canonical,
|
|
10907
|
+
function lintPermissions(canonical, target13) {
|
|
10374
10908
|
if (!canonical.permissions) return [];
|
|
10375
|
-
if (
|
|
10909
|
+
if (target13 !== "cursor") return [];
|
|
10376
10910
|
const hasEntries = canonical.permissions.allow.length > 0 || canonical.permissions.deny.length > 0;
|
|
10377
10911
|
if (!hasEntries) return [];
|
|
10378
10912
|
return [
|
|
10379
10913
|
{
|
|
10380
10914
|
level: "warning",
|
|
10381
10915
|
file: ".agentsmesh/permissions.yaml",
|
|
10382
|
-
target:
|
|
10916
|
+
target: target13,
|
|
10383
10917
|
message: "Cursor permissions are partial; tool-level allow/deny may lose fidelity."
|
|
10384
10918
|
}
|
|
10385
10919
|
];
|
|
10386
10920
|
}
|
|
10387
10921
|
|
|
10388
10922
|
// src/core/lint/hooks.ts
|
|
10389
|
-
function lintHooks(canonical,
|
|
10923
|
+
function lintHooks(canonical, target13) {
|
|
10390
10924
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
10391
|
-
if (
|
|
10925
|
+
if (target13 === "gemini-cli") {
|
|
10392
10926
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification"]);
|
|
10393
10927
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10394
10928
|
level: "warning",
|
|
10395
10929
|
file: ".agentsmesh/hooks.yaml",
|
|
10396
|
-
target:
|
|
10930
|
+
target: target13,
|
|
10397
10931
|
message: `${event} is not supported by gemini-cli; only PreToolUse, PostToolUse, and Notification are projected.`
|
|
10398
10932
|
}));
|
|
10399
10933
|
}
|
|
10400
|
-
if (
|
|
10934
|
+
if (target13 === "copilot") {
|
|
10401
10935
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit"]);
|
|
10402
10936
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10403
10937
|
level: "warning",
|
|
10404
10938
|
file: ".agentsmesh/hooks.yaml",
|
|
10405
|
-
target:
|
|
10939
|
+
target: target13,
|
|
10406
10940
|
message: `${event} is not supported by Copilot hooks; only PreToolUse, PostToolUse, Notification, and UserPromptSubmit are projected.`
|
|
10407
10941
|
}));
|
|
10408
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
|
+
}
|
|
10409
10952
|
return [];
|
|
10410
10953
|
}
|
|
10411
10954
|
|
|
@@ -10428,22 +10971,22 @@ async function runLint(config, canonical, projectRoot, targetFilter) {
|
|
|
10428
10971
|
const hasHooks = config.features.includes("hooks");
|
|
10429
10972
|
const diagnostics = [];
|
|
10430
10973
|
const projectFiles = await getProjectFiles(projectRoot);
|
|
10431
|
-
for (const
|
|
10432
|
-
const linter = isBuiltinTargetId(
|
|
10974
|
+
for (const target13 of targets) {
|
|
10975
|
+
const linter = isBuiltinTargetId(target13) ? getTargetCatalogEntry(target13).lintRules : null;
|
|
10433
10976
|
if (hasRules && linter) {
|
|
10434
10977
|
diagnostics.push(...linter(canonical, projectRoot, projectFiles));
|
|
10435
10978
|
}
|
|
10436
10979
|
if (hasCommands) {
|
|
10437
|
-
diagnostics.push(...lintCommands(canonical,
|
|
10980
|
+
diagnostics.push(...lintCommands(canonical, target13));
|
|
10438
10981
|
}
|
|
10439
10982
|
if (hasMcp) {
|
|
10440
|
-
diagnostics.push(...lintMcp(canonical,
|
|
10983
|
+
diagnostics.push(...lintMcp(canonical, target13));
|
|
10441
10984
|
}
|
|
10442
10985
|
if (hasPermissions) {
|
|
10443
|
-
diagnostics.push(...lintPermissions(canonical,
|
|
10986
|
+
diagnostics.push(...lintPermissions(canonical, target13));
|
|
10444
10987
|
}
|
|
10445
10988
|
if (hasHooks) {
|
|
10446
|
-
diagnostics.push(...lintHooks(canonical,
|
|
10989
|
+
diagnostics.push(...lintHooks(canonical, target13));
|
|
10447
10990
|
}
|
|
10448
10991
|
}
|
|
10449
10992
|
const hasErrors = diagnostics.some((d) => d.level === "error");
|
|
@@ -10483,7 +11026,7 @@ async function runLintCmd(flags, projectRoot) {
|
|
|
10483
11026
|
}
|
|
10484
11027
|
|
|
10485
11028
|
// src/cli/commands/watch.ts
|
|
10486
|
-
import { join as
|
|
11029
|
+
import { join as join60, relative as relative23 } from "path";
|
|
10487
11030
|
import chokidar from "chokidar";
|
|
10488
11031
|
var DEBOUNCE_MS = 300;
|
|
10489
11032
|
function normalizeWatchPath(path) {
|
|
@@ -10510,9 +11053,9 @@ async function runWatch(flags, projectRoot) {
|
|
|
10510
11053
|
const root = projectRoot ?? process.cwd();
|
|
10511
11054
|
const { configDir } = await loadConfigFromDir(root);
|
|
10512
11055
|
const paths = [
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
11056
|
+
join60(configDir, ".agentsmesh"),
|
|
11057
|
+
join60(configDir, "agentsmesh.yaml"),
|
|
11058
|
+
join60(configDir, "agentsmesh.local.yaml")
|
|
10516
11059
|
];
|
|
10517
11060
|
let debounceTimer = null;
|
|
10518
11061
|
let lastFingerprint = null;
|
|
@@ -10598,12 +11141,12 @@ async function runWatch(flags, projectRoot) {
|
|
|
10598
11141
|
}
|
|
10599
11142
|
|
|
10600
11143
|
// src/cli/commands/check.ts
|
|
10601
|
-
import { join as
|
|
11144
|
+
import { join as join61 } from "path";
|
|
10602
11145
|
async function runCheck(flags, projectRoot) {
|
|
10603
11146
|
void flags;
|
|
10604
11147
|
const root = projectRoot ?? process.cwd();
|
|
10605
11148
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10606
|
-
const abDir =
|
|
11149
|
+
const abDir = join61(configDir, ".agentsmesh");
|
|
10607
11150
|
const lock = await readLock(abDir);
|
|
10608
11151
|
if (lock === null) {
|
|
10609
11152
|
logger.error("Not initialized for collaboration. Run 'agentsmesh generate' first.");
|
|
@@ -10673,14 +11216,14 @@ async function runCheck(flags, projectRoot) {
|
|
|
10673
11216
|
}
|
|
10674
11217
|
|
|
10675
11218
|
// src/cli/commands/merge.ts
|
|
10676
|
-
import { join as
|
|
11219
|
+
import { join as join63 } from "path";
|
|
10677
11220
|
|
|
10678
11221
|
// src/core/merger.ts
|
|
10679
|
-
import { dirname as dirname22, join as
|
|
11222
|
+
import { dirname as dirname22, join as join62 } from "path";
|
|
10680
11223
|
var LOCK_FILENAME2 = ".lock";
|
|
10681
11224
|
var CONFLICT_MARKER = "<<<<<<<";
|
|
10682
11225
|
async function hasLockConflict(abDir) {
|
|
10683
|
-
const lockPath =
|
|
11226
|
+
const lockPath = join62(abDir, LOCK_FILENAME2);
|
|
10684
11227
|
const content = await readFileSafe(lockPath);
|
|
10685
11228
|
if (content === null) return false;
|
|
10686
11229
|
return content.includes(CONFLICT_MARKER);
|
|
@@ -10694,7 +11237,7 @@ async function resolveLockConflict(abDir, libVersion, config) {
|
|
|
10694
11237
|
const configDir = dirname22(abDir);
|
|
10695
11238
|
const resolvedExtends = config ? await resolveExtendPaths(config, configDir) : [];
|
|
10696
11239
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
10697
|
-
const packChecksums = await buildPackChecksums(
|
|
11240
|
+
const packChecksums = await buildPackChecksums(join62(abDir, "packs"));
|
|
10698
11241
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
10699
11242
|
await writeLock(abDir, {
|
|
10700
11243
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -10711,7 +11254,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10711
11254
|
void flags;
|
|
10712
11255
|
const root = projectRoot ?? process.cwd();
|
|
10713
11256
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10714
|
-
const abDir =
|
|
11257
|
+
const abDir = join63(configDir, ".agentsmesh");
|
|
10715
11258
|
const hasConflict = await hasLockConflict(abDir);
|
|
10716
11259
|
if (!hasConflict) {
|
|
10717
11260
|
logger.info("No conflicts to resolve.");
|
|
@@ -10722,7 +11265,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10722
11265
|
}
|
|
10723
11266
|
|
|
10724
11267
|
// src/install/run/run-install.ts
|
|
10725
|
-
import { join as
|
|
11268
|
+
import { join as join77 } from "path";
|
|
10726
11269
|
|
|
10727
11270
|
// src/install/source/git-pin.ts
|
|
10728
11271
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -10856,7 +11399,7 @@ async function confirm(message) {
|
|
|
10856
11399
|
}
|
|
10857
11400
|
|
|
10858
11401
|
// src/install/core/validate-resources.ts
|
|
10859
|
-
import { basename as
|
|
11402
|
+
import { basename as basename33 } from "path";
|
|
10860
11403
|
function validateSkill(skill) {
|
|
10861
11404
|
if (!skill.description.trim()) {
|
|
10862
11405
|
return { skill, ok: false, reason: "missing description in frontmatter" };
|
|
@@ -10882,7 +11425,7 @@ function validateAgent(agent) {
|
|
|
10882
11425
|
return { agent, ok: true };
|
|
10883
11426
|
}
|
|
10884
11427
|
function ruleSlug6(rule) {
|
|
10885
|
-
return
|
|
11428
|
+
return basename33(rule.source).replace(/\.md$/i, "");
|
|
10886
11429
|
}
|
|
10887
11430
|
|
|
10888
11431
|
// src/install/core/pool-resolution.ts
|
|
@@ -11376,7 +11919,7 @@ function ensureInstallSelection(args) {
|
|
|
11376
11919
|
}
|
|
11377
11920
|
|
|
11378
11921
|
// src/install/core/install-extend-entry.ts
|
|
11379
|
-
import { join as
|
|
11922
|
+
import { join as join64 } from "path";
|
|
11380
11923
|
|
|
11381
11924
|
// src/install/core/merge-extend-entry.ts
|
|
11382
11925
|
function assertExtendNameAvailable(extendsList, entry) {
|
|
@@ -11465,7 +12008,7 @@ async function writeInstallAsExtend(args) {
|
|
|
11465
12008
|
${JSON.stringify(entry, null, 2)}`);
|
|
11466
12009
|
return;
|
|
11467
12010
|
}
|
|
11468
|
-
const configPath =
|
|
12011
|
+
const configPath = join64(configDir, "agentsmesh.yaml");
|
|
11469
12012
|
await writeAgentsmeshWithNewExtend(configPath, config, entry);
|
|
11470
12013
|
logger.success(`Wrote extends entry "${entry.name}" to agentsmesh.yaml.`);
|
|
11471
12014
|
}
|
|
@@ -11482,13 +12025,13 @@ function toNewExtendEntry(args) {
|
|
|
11482
12025
|
}
|
|
11483
12026
|
|
|
11484
12027
|
// src/install/run/run-install-pack.ts
|
|
11485
|
-
import { join as
|
|
12028
|
+
import { join as join68 } from "path";
|
|
11486
12029
|
import { rename as rename4 } from "fs/promises";
|
|
11487
12030
|
|
|
11488
12031
|
// src/install/pack/pack-writer.ts
|
|
11489
|
-
import { join as
|
|
12032
|
+
import { join as join65, basename as basename34, dirname as dirname23 } from "path";
|
|
11490
12033
|
import { rm as rm7, rename as rename3, mkdir as mkdir5, copyFile as copyFile2 } from "fs/promises";
|
|
11491
|
-
import { stringify as
|
|
12034
|
+
import { stringify as yamlStringify7 } from "yaml";
|
|
11492
12035
|
|
|
11493
12036
|
// src/install/pack/pack-hash.ts
|
|
11494
12037
|
import { relative as relative25 } from "path";
|
|
@@ -11512,41 +12055,41 @@ async function hashPackContent(packDir) {
|
|
|
11512
12055
|
// src/install/pack/pack-writer.ts
|
|
11513
12056
|
async function writeRules(canonical, packDir) {
|
|
11514
12057
|
if (canonical.rules.length === 0) return;
|
|
11515
|
-
const rulesDir =
|
|
12058
|
+
const rulesDir = join65(packDir, "rules");
|
|
11516
12059
|
await mkdirp(rulesDir);
|
|
11517
12060
|
for (const rule of canonical.rules) {
|
|
11518
|
-
const dest =
|
|
12061
|
+
const dest = join65(rulesDir, basename34(rule.source));
|
|
11519
12062
|
await copyFile2(rule.source, dest);
|
|
11520
12063
|
}
|
|
11521
12064
|
}
|
|
11522
12065
|
async function writeCommands(canonical, packDir) {
|
|
11523
12066
|
if (canonical.commands.length === 0) return;
|
|
11524
|
-
const dir =
|
|
12067
|
+
const dir = join65(packDir, "commands");
|
|
11525
12068
|
await mkdirp(dir);
|
|
11526
12069
|
for (const cmd of canonical.commands) {
|
|
11527
|
-
const dest =
|
|
12070
|
+
const dest = join65(dir, basename34(cmd.source));
|
|
11528
12071
|
await copyFile2(cmd.source, dest);
|
|
11529
12072
|
}
|
|
11530
12073
|
}
|
|
11531
12074
|
async function writeAgents(canonical, packDir) {
|
|
11532
12075
|
if (canonical.agents.length === 0) return;
|
|
11533
|
-
const dir =
|
|
12076
|
+
const dir = join65(packDir, "agents");
|
|
11534
12077
|
await mkdirp(dir);
|
|
11535
12078
|
for (const agent of canonical.agents) {
|
|
11536
|
-
const dest =
|
|
12079
|
+
const dest = join65(dir, basename34(agent.source));
|
|
11537
12080
|
await copyFile2(agent.source, dest);
|
|
11538
12081
|
}
|
|
11539
12082
|
}
|
|
11540
12083
|
async function writeSkills(canonical, packDir) {
|
|
11541
12084
|
if (canonical.skills.length === 0) return;
|
|
11542
|
-
const skillsDir =
|
|
12085
|
+
const skillsDir = join65(packDir, "skills");
|
|
11543
12086
|
await mkdirp(skillsDir);
|
|
11544
12087
|
for (const skill of canonical.skills) {
|
|
11545
|
-
const skillDestDir =
|
|
12088
|
+
const skillDestDir = join65(skillsDir, skill.name);
|
|
11546
12089
|
await mkdirp(skillDestDir);
|
|
11547
|
-
await copyFile2(skill.source,
|
|
12090
|
+
await copyFile2(skill.source, join65(skillDestDir, "SKILL.md"));
|
|
11548
12091
|
for (const sf of skill.supportingFiles) {
|
|
11549
|
-
const destPath =
|
|
12092
|
+
const destPath = join65(skillDestDir, sf.relativePath);
|
|
11550
12093
|
await mkdirp(dirname23(destPath));
|
|
11551
12094
|
await copyFile2(sf.absolutePath, destPath);
|
|
11552
12095
|
}
|
|
@@ -11554,23 +12097,23 @@ async function writeSkills(canonical, packDir) {
|
|
|
11554
12097
|
}
|
|
11555
12098
|
async function writeSettings(canonical, packDir) {
|
|
11556
12099
|
if (canonical.mcp !== null) {
|
|
11557
|
-
await writeFileAtomic(
|
|
12100
|
+
await writeFileAtomic(join65(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11558
12101
|
`);
|
|
11559
12102
|
}
|
|
11560
12103
|
if (canonical.permissions !== null) {
|
|
11561
|
-
await writeFileAtomic(
|
|
12104
|
+
await writeFileAtomic(join65(packDir, "permissions.yaml"), yamlStringify7(canonical.permissions));
|
|
11562
12105
|
}
|
|
11563
12106
|
if (canonical.hooks !== null) {
|
|
11564
|
-
await writeFileAtomic(
|
|
12107
|
+
await writeFileAtomic(join65(packDir, "hooks.yaml"), yamlStringify7(canonical.hooks));
|
|
11565
12108
|
}
|
|
11566
12109
|
if (canonical.ignore.length > 0) {
|
|
11567
|
-
await writeFileAtomic(
|
|
12110
|
+
await writeFileAtomic(join65(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11568
12111
|
`);
|
|
11569
12112
|
}
|
|
11570
12113
|
}
|
|
11571
12114
|
async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
11572
|
-
const tmpDir =
|
|
11573
|
-
const finalDir =
|
|
12115
|
+
const tmpDir = join65(packsDir, `${packName}.tmp`);
|
|
12116
|
+
const finalDir = join65(packsDir, packName);
|
|
11574
12117
|
if (await exists(tmpDir)) {
|
|
11575
12118
|
await rm7(tmpDir, { recursive: true, force: true });
|
|
11576
12119
|
}
|
|
@@ -11582,7 +12125,7 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11582
12125
|
await writeSettings(canonical, tmpDir);
|
|
11583
12126
|
const contentHash = await hashPackContent(tmpDir);
|
|
11584
12127
|
const metadata = { ...metadataInput, content_hash: contentHash };
|
|
11585
|
-
await writeFileAtomic(
|
|
12128
|
+
await writeFileAtomic(join65(tmpDir, "pack.yaml"), yamlStringify7(metadata));
|
|
11586
12129
|
if (await exists(finalDir)) {
|
|
11587
12130
|
await rm7(finalDir, { recursive: true, force: true });
|
|
11588
12131
|
}
|
|
@@ -11592,9 +12135,9 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11592
12135
|
}
|
|
11593
12136
|
|
|
11594
12137
|
// src/install/pack/pack-merge.ts
|
|
11595
|
-
import { join as
|
|
12138
|
+
import { join as join66, basename as basename35, dirname as dirname24 } from "path";
|
|
11596
12139
|
import { copyFile as copyFile3 } from "fs/promises";
|
|
11597
|
-
import { stringify as
|
|
12140
|
+
import { stringify as yamlStringify8 } from "yaml";
|
|
11598
12141
|
function union(a, b) {
|
|
11599
12142
|
return [.../* @__PURE__ */ new Set([...a, ...b])];
|
|
11600
12143
|
}
|
|
@@ -11623,38 +12166,38 @@ function mergePick2(existing, newFeatures, newPick) {
|
|
|
11623
12166
|
}
|
|
11624
12167
|
async function mergeRules(canonical, packDir) {
|
|
11625
12168
|
if (canonical.rules.length === 0) return;
|
|
11626
|
-
const dir =
|
|
12169
|
+
const dir = join66(packDir, "rules");
|
|
11627
12170
|
await mkdirp(dir);
|
|
11628
12171
|
for (const rule of canonical.rules) {
|
|
11629
|
-
await copyFile3(rule.source,
|
|
12172
|
+
await copyFile3(rule.source, join66(dir, basename35(rule.source)));
|
|
11630
12173
|
}
|
|
11631
12174
|
}
|
|
11632
12175
|
async function mergeCommands(canonical, packDir) {
|
|
11633
12176
|
if (canonical.commands.length === 0) return;
|
|
11634
|
-
const dir =
|
|
12177
|
+
const dir = join66(packDir, "commands");
|
|
11635
12178
|
await mkdirp(dir);
|
|
11636
12179
|
for (const cmd of canonical.commands) {
|
|
11637
|
-
await copyFile3(cmd.source,
|
|
12180
|
+
await copyFile3(cmd.source, join66(dir, basename35(cmd.source)));
|
|
11638
12181
|
}
|
|
11639
12182
|
}
|
|
11640
12183
|
async function mergeAgents(canonical, packDir) {
|
|
11641
12184
|
if (canonical.agents.length === 0) return;
|
|
11642
|
-
const dir =
|
|
12185
|
+
const dir = join66(packDir, "agents");
|
|
11643
12186
|
await mkdirp(dir);
|
|
11644
12187
|
for (const agent of canonical.agents) {
|
|
11645
|
-
await copyFile3(agent.source,
|
|
12188
|
+
await copyFile3(agent.source, join66(dir, basename35(agent.source)));
|
|
11646
12189
|
}
|
|
11647
12190
|
}
|
|
11648
12191
|
async function mergeSkills(canonical, packDir) {
|
|
11649
12192
|
if (canonical.skills.length === 0) return;
|
|
11650
|
-
const skillsDir =
|
|
12193
|
+
const skillsDir = join66(packDir, "skills");
|
|
11651
12194
|
await mkdirp(skillsDir);
|
|
11652
12195
|
for (const skill of canonical.skills) {
|
|
11653
|
-
const destDir =
|
|
12196
|
+
const destDir = join66(skillsDir, skill.name);
|
|
11654
12197
|
await mkdirp(destDir);
|
|
11655
|
-
await copyFile3(skill.source,
|
|
12198
|
+
await copyFile3(skill.source, join66(destDir, "SKILL.md"));
|
|
11656
12199
|
for (const sf of skill.supportingFiles) {
|
|
11657
|
-
const destPath =
|
|
12200
|
+
const destPath = join66(destDir, sf.relativePath);
|
|
11658
12201
|
await mkdirp(dirname24(destPath));
|
|
11659
12202
|
await copyFile3(sf.absolutePath, destPath);
|
|
11660
12203
|
}
|
|
@@ -11662,17 +12205,17 @@ async function mergeSkills(canonical, packDir) {
|
|
|
11662
12205
|
}
|
|
11663
12206
|
async function mergeSettings(canonical, packDir) {
|
|
11664
12207
|
if (canonical.mcp !== null) {
|
|
11665
|
-
await writeFileAtomic(
|
|
12208
|
+
await writeFileAtomic(join66(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11666
12209
|
`);
|
|
11667
12210
|
}
|
|
11668
12211
|
if (canonical.permissions !== null) {
|
|
11669
|
-
await writeFileAtomic(
|
|
12212
|
+
await writeFileAtomic(join66(packDir, "permissions.yaml"), yamlStringify8(canonical.permissions));
|
|
11670
12213
|
}
|
|
11671
12214
|
if (canonical.hooks !== null) {
|
|
11672
|
-
await writeFileAtomic(
|
|
12215
|
+
await writeFileAtomic(join66(packDir, "hooks.yaml"), yamlStringify8(canonical.hooks));
|
|
11673
12216
|
}
|
|
11674
12217
|
if (canonical.ignore.length > 0) {
|
|
11675
|
-
await writeFileAtomic(
|
|
12218
|
+
await writeFileAtomic(join66(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11676
12219
|
`);
|
|
11677
12220
|
}
|
|
11678
12221
|
}
|
|
@@ -11699,13 +12242,13 @@ async function mergeIntoPack(packDir, existingMeta, newCanonical, newFeatures, n
|
|
|
11699
12242
|
updated_at: updatedAt,
|
|
11700
12243
|
content_hash: contentHash
|
|
11701
12244
|
};
|
|
11702
|
-
await writeFileAtomic(
|
|
12245
|
+
await writeFileAtomic(join66(packDir, "pack.yaml"), yamlStringify8(updatedMeta));
|
|
11703
12246
|
return updatedMeta;
|
|
11704
12247
|
}
|
|
11705
12248
|
|
|
11706
12249
|
// src/install/core/install-manifest.ts
|
|
11707
|
-
import { join as
|
|
11708
|
-
import { parse as parseYaml8, stringify as
|
|
12250
|
+
import { join as join67 } from "path";
|
|
12251
|
+
import { parse as parseYaml8, stringify as yamlStringify9 } from "yaml";
|
|
11709
12252
|
import { z as z4 } from "zod";
|
|
11710
12253
|
var installManifestEntrySchema = z4.object({
|
|
11711
12254
|
name: z4.string().min(1),
|
|
@@ -11730,7 +12273,7 @@ function sameInstallIdentity(a, b) {
|
|
|
11730
12273
|
return a.source === b.source && a.target === b.target && a.as === b.as && sameFeatures2(a.features, b.features);
|
|
11731
12274
|
}
|
|
11732
12275
|
function manifestPath(configDir) {
|
|
11733
|
-
return
|
|
12276
|
+
return join67(configDir, ".agentsmesh", "installs.yaml");
|
|
11734
12277
|
}
|
|
11735
12278
|
async function readInstallManifest(configDir) {
|
|
11736
12279
|
const content = await readFileSafe(manifestPath(configDir));
|
|
@@ -11749,7 +12292,7 @@ async function upsertInstallManifestEntry(configDir, entry) {
|
|
|
11749
12292
|
next.push(entry);
|
|
11750
12293
|
await writeFileAtomic(
|
|
11751
12294
|
manifestPath(configDir),
|
|
11752
|
-
|
|
12295
|
+
yamlStringify9({ version: 1, installs: next.sort((a, b) => a.name.localeCompare(b.name)) })
|
|
11753
12296
|
);
|
|
11754
12297
|
}
|
|
11755
12298
|
function buildInstallManifestEntry(args) {
|
|
@@ -11803,7 +12346,7 @@ async function installAsPack(args) {
|
|
|
11803
12346
|
manualAs,
|
|
11804
12347
|
renameExistingPack
|
|
11805
12348
|
} = args;
|
|
11806
|
-
const packsDir =
|
|
12349
|
+
const packsDir = join68(configDir, ".agentsmesh", "packs");
|
|
11807
12350
|
const selectedCanonical = applySelection(narrowed, selected);
|
|
11808
12351
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11809
12352
|
const parsedTarget = yamlTarget !== void 0 ? targetSchema.parse(yamlTarget) : void 0;
|
|
@@ -11821,7 +12364,7 @@ async function installAsPack(args) {
|
|
|
11821
12364
|
let packDir = existingPack.packDir;
|
|
11822
12365
|
let packMeta = existingPack.meta;
|
|
11823
12366
|
if (renameExistingPack && existingPack.name !== packName) {
|
|
11824
|
-
const nextDir =
|
|
12367
|
+
const nextDir = join68(packsDir, packName);
|
|
11825
12368
|
if (await exists(nextDir)) {
|
|
11826
12369
|
throw new Error(
|
|
11827
12370
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11852,7 +12395,7 @@ async function installAsPack(args) {
|
|
|
11852
12395
|
persistedPaths = mergedMeta.paths;
|
|
11853
12396
|
logger.success(`Updated pack "${mergedMeta.name}" in .agentsmesh/packs/.`);
|
|
11854
12397
|
} else {
|
|
11855
|
-
const collidingMeta = await readPackMetadata(
|
|
12398
|
+
const collidingMeta = await readPackMetadata(join68(packsDir, packName));
|
|
11856
12399
|
if (collidingMeta) {
|
|
11857
12400
|
throw new Error(
|
|
11858
12401
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11894,7 +12437,7 @@ async function installAsPack(args) {
|
|
|
11894
12437
|
}
|
|
11895
12438
|
|
|
11896
12439
|
// src/install/run/install-sync.ts
|
|
11897
|
-
import { join as
|
|
12440
|
+
import { join as join69 } from "path";
|
|
11898
12441
|
async function syncInstalledPacks(args) {
|
|
11899
12442
|
const installs = await readInstallManifest(args.configDir);
|
|
11900
12443
|
if (installs.length === 0) {
|
|
@@ -11903,7 +12446,7 @@ async function syncInstalledPacks(args) {
|
|
|
11903
12446
|
}
|
|
11904
12447
|
const missing = [];
|
|
11905
12448
|
for (const entry of installs) {
|
|
11906
|
-
const packDir =
|
|
12449
|
+
const packDir = join69(args.configDir, ".agentsmesh", "packs", entry.name);
|
|
11907
12450
|
if (!await exists(packDir)) {
|
|
11908
12451
|
missing.push(entry);
|
|
11909
12452
|
}
|
|
@@ -12081,7 +12624,7 @@ function narrowDiscoveredForInstallScope(canonical, options) {
|
|
|
12081
12624
|
}
|
|
12082
12625
|
|
|
12083
12626
|
// src/install/manual/manual-install-scope.ts
|
|
12084
|
-
import { basename as
|
|
12627
|
+
import { basename as basename36, dirname as dirname25, join as join70, relative as relative27 } from "path";
|
|
12085
12628
|
import { cp as cp2, mkdtemp, stat as stat5, rm as rm8 } from "fs/promises";
|
|
12086
12629
|
import { tmpdir } from "os";
|
|
12087
12630
|
|
|
@@ -12141,9 +12684,9 @@ async function cpFilteredSkill(sourceRoot, destDir) {
|
|
|
12141
12684
|
|
|
12142
12685
|
// src/install/manual/manual-install-scope.ts
|
|
12143
12686
|
async function createStageRoot() {
|
|
12144
|
-
const stageBase = await mkdtemp(
|
|
12145
|
-
const discoveryRoot =
|
|
12146
|
-
await mkdirp(
|
|
12687
|
+
const stageBase = await mkdtemp(join70(tmpdir(), "am-install-manual-"));
|
|
12688
|
+
const discoveryRoot = join70(stageBase, "repo");
|
|
12689
|
+
await mkdirp(join70(discoveryRoot, ".agentsmesh"));
|
|
12147
12690
|
return {
|
|
12148
12691
|
discoveryRoot,
|
|
12149
12692
|
cleanup: async () => {
|
|
@@ -12158,7 +12701,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12158
12701
|
throw new Error(`Manual install only supports .md files for this collection: ${sourceRoot}`);
|
|
12159
12702
|
}
|
|
12160
12703
|
await mkdirp(destinationDir);
|
|
12161
|
-
await cp2(sourceRoot,
|
|
12704
|
+
await cp2(sourceRoot, join70(destinationDir, basename36(sourceRoot)));
|
|
12162
12705
|
return;
|
|
12163
12706
|
}
|
|
12164
12707
|
const files = (await readDirRecursive(sourceRoot)).filter(
|
|
@@ -12170,7 +12713,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12170
12713
|
const usedNames = /* @__PURE__ */ new Map();
|
|
12171
12714
|
await mkdirp(destinationDir);
|
|
12172
12715
|
for (const file of files) {
|
|
12173
|
-
const name =
|
|
12716
|
+
const name = basename36(file);
|
|
12174
12717
|
const previous = usedNames.get(name);
|
|
12175
12718
|
if (previous) {
|
|
12176
12719
|
throw new Error(
|
|
@@ -12178,7 +12721,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
12178
12721
|
);
|
|
12179
12722
|
}
|
|
12180
12723
|
usedNames.set(name, file);
|
|
12181
|
-
await cp2(file,
|
|
12724
|
+
await cp2(file, join70(destinationDir, name));
|
|
12182
12725
|
}
|
|
12183
12726
|
}
|
|
12184
12727
|
async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNames) {
|
|
@@ -12190,7 +12733,7 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
12190
12733
|
for (const file of await readDirRecursive(sourceRoot)) {
|
|
12191
12734
|
if (!file.endsWith("/SKILL.md") && !file.endsWith("\\SKILL.md")) continue;
|
|
12192
12735
|
const skillDir = dirname25(file);
|
|
12193
|
-
const skillName =
|
|
12736
|
+
const skillName = basename36(skillDir);
|
|
12194
12737
|
if (!wanted.has(skillName)) continue;
|
|
12195
12738
|
const previous = matches.get(skillName);
|
|
12196
12739
|
if (previous && previous !== skillDir) {
|
|
@@ -12203,30 +12746,30 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
12203
12746
|
if (matches.size !== preferredSkillNames.length) return false;
|
|
12204
12747
|
await mkdirp(destinationDir);
|
|
12205
12748
|
for (const skillName of preferredSkillNames) {
|
|
12206
|
-
await cp2(matches.get(skillName),
|
|
12749
|
+
await cp2(matches.get(skillName), join70(destinationDir, skillName), { recursive: true });
|
|
12207
12750
|
}
|
|
12208
12751
|
return true;
|
|
12209
12752
|
}
|
|
12210
12753
|
async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
12211
12754
|
const info = await stat5(sourceRoot);
|
|
12212
12755
|
if (info.isFile()) {
|
|
12213
|
-
if (
|
|
12756
|
+
if (basename36(sourceRoot) !== "SKILL.md") {
|
|
12214
12757
|
throw new Error(`Manual skill install expects SKILL.md or a skill directory: ${sourceRoot}`);
|
|
12215
12758
|
}
|
|
12216
|
-
const skillName =
|
|
12217
|
-
const skillDir =
|
|
12759
|
+
const skillName = basename36(dirname25(sourceRoot));
|
|
12760
|
+
const skillDir = join70(destinationDir, skillName);
|
|
12218
12761
|
await mkdirp(skillDir);
|
|
12219
12762
|
await cp2(dirname25(sourceRoot), skillDir, { recursive: true });
|
|
12220
12763
|
return;
|
|
12221
12764
|
}
|
|
12222
12765
|
if (await isSkillPackLayout(sourceRoot)) {
|
|
12223
|
-
if ((await stat5(
|
|
12766
|
+
if ((await stat5(join70(sourceRoot, "SKILL.md")).catch(() => null))?.isFile()) {
|
|
12224
12767
|
if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
|
|
12225
12768
|
return;
|
|
12226
12769
|
}
|
|
12227
|
-
const fmName = await readSkillFrontmatterName(
|
|
12228
|
-
const skillName = fmName ||
|
|
12229
|
-
const skillDir =
|
|
12770
|
+
const fmName = await readSkillFrontmatterName(join70(sourceRoot, "SKILL.md"));
|
|
12771
|
+
const skillName = fmName || basename36(sourceRoot);
|
|
12772
|
+
const skillDir = join70(destinationDir, skillName);
|
|
12230
12773
|
await mkdirp(destinationDir);
|
|
12231
12774
|
await cpFilteredSkill(sourceRoot, skillDir);
|
|
12232
12775
|
return;
|
|
@@ -12243,7 +12786,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
12243
12786
|
roots.add(relative27(sourceRoot, dirname25(file)).split(/[\\/]/)[0]);
|
|
12244
12787
|
}
|
|
12245
12788
|
for (const root of roots) {
|
|
12246
|
-
await cp2(
|
|
12789
|
+
await cp2(join70(sourceRoot, root), join70(destinationDir, root), { recursive: true });
|
|
12247
12790
|
}
|
|
12248
12791
|
return;
|
|
12249
12792
|
}
|
|
@@ -12254,7 +12797,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
12254
12797
|
async function stageManualInstallScope(sourceRoot, as, options = {}) {
|
|
12255
12798
|
const staged = await createStageRoot();
|
|
12256
12799
|
try {
|
|
12257
|
-
const destDir =
|
|
12800
|
+
const destDir = join70(staged.discoveryRoot, ".agentsmesh", as);
|
|
12258
12801
|
if (as === "skills") {
|
|
12259
12802
|
await stageSkills(sourceRoot, destDir, options);
|
|
12260
12803
|
} else {
|
|
@@ -12288,7 +12831,7 @@ async function resolveManualDiscoveredForInstall(sourceRoot, explicitAs, explici
|
|
|
12288
12831
|
}
|
|
12289
12832
|
|
|
12290
12833
|
// src/install/core/prepare-install-discovery.ts
|
|
12291
|
-
import { join as
|
|
12834
|
+
import { join as join75 } from "path";
|
|
12292
12835
|
|
|
12293
12836
|
// src/install/native/native-path-pick.ts
|
|
12294
12837
|
var PATH_PREFIX_TO_TARGET = [
|
|
@@ -12315,6 +12858,8 @@ var PATH_PREFIX_TO_TARGET = [
|
|
|
12315
12858
|
{ prefix: ".junie/rules", target: "junie" },
|
|
12316
12859
|
{ prefix: ".junie/agents", target: "junie" },
|
|
12317
12860
|
{ prefix: ".junie/skills", target: "junie" },
|
|
12861
|
+
{ prefix: ".kiro/steering", target: "kiro" },
|
|
12862
|
+
{ prefix: ".kiro/skills", target: "kiro" },
|
|
12318
12863
|
{ prefix: ".cline/skills", target: "cline" },
|
|
12319
12864
|
{ prefix: ".clinerules/workflows", target: "cline" },
|
|
12320
12865
|
{ prefix: ".windsurf/rules", target: "windsurf" },
|
|
@@ -12326,14 +12871,14 @@ function norm(p) {
|
|
|
12326
12871
|
function targetHintFromNativePath(pathInRepoPosix) {
|
|
12327
12872
|
const p = norm(pathInRepoPosix);
|
|
12328
12873
|
const sorted = [...PATH_PREFIX_TO_TARGET].sort((a, b) => b.prefix.length - a.prefix.length);
|
|
12329
|
-
for (const { prefix, target:
|
|
12330
|
-
if (p === prefix || p.startsWith(`${prefix}/`)) return
|
|
12874
|
+
for (const { prefix, target: target13 } of sorted) {
|
|
12875
|
+
if (p === prefix || p.startsWith(`${prefix}/`)) return target13;
|
|
12331
12876
|
}
|
|
12332
12877
|
return void 0;
|
|
12333
12878
|
}
|
|
12334
|
-
function pathSupportsNativePick(pathInRepoPosix,
|
|
12879
|
+
function pathSupportsNativePick(pathInRepoPosix, target13) {
|
|
12335
12880
|
const hint = targetHintFromNativePath(pathInRepoPosix);
|
|
12336
|
-
return hint ===
|
|
12881
|
+
return hint === target13;
|
|
12337
12882
|
}
|
|
12338
12883
|
function validateTargetMatchesPath(explicitTarget, pathInRepoPosix) {
|
|
12339
12884
|
if (!explicitTarget || !pathInRepoPosix) return;
|
|
@@ -12349,13 +12894,13 @@ function extendPickHasArrays(p) {
|
|
|
12349
12894
|
}
|
|
12350
12895
|
|
|
12351
12896
|
// src/install/native/native-path-pick-infer.ts
|
|
12352
|
-
import { basename as
|
|
12897
|
+
import { basename as basename39, join as join73 } from "path";
|
|
12353
12898
|
|
|
12354
12899
|
// src/install/native/gemini-install-commands.ts
|
|
12355
|
-
import { join as
|
|
12900
|
+
import { join as join71, relative as relative28 } from "path";
|
|
12356
12901
|
async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
12357
|
-
const commandsRoot =
|
|
12358
|
-
const scanDir =
|
|
12902
|
+
const commandsRoot = join71(repoRoot, ...GEMINI_COMMANDS_DIR.split("/"));
|
|
12903
|
+
const scanDir = join71(repoRoot, ...pathInRepoPosix.split("/"));
|
|
12359
12904
|
const files = await readDirRecursive(scanDir);
|
|
12360
12905
|
const names = [];
|
|
12361
12906
|
for (const f of files) {
|
|
@@ -12370,32 +12915,32 @@ async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
|
12370
12915
|
}
|
|
12371
12916
|
|
|
12372
12917
|
// src/install/native/native-skill-scan.ts
|
|
12373
|
-
import { basename as
|
|
12918
|
+
import { basename as basename37, dirname as dirname26, relative as relative29 } from "path";
|
|
12374
12919
|
async function skillNamesFromNativeSkillDir(scanRoot) {
|
|
12375
12920
|
const files = await readDirRecursive(scanRoot);
|
|
12376
12921
|
const names = /* @__PURE__ */ new Set();
|
|
12377
12922
|
for (const f of files) {
|
|
12378
|
-
if (
|
|
12379
|
-
names.add(
|
|
12923
|
+
if (basename37(f) === "SKILL.md") {
|
|
12924
|
+
names.add(basename37(dirname26(f)));
|
|
12380
12925
|
continue;
|
|
12381
12926
|
}
|
|
12382
12927
|
const rel2 = relative29(scanRoot, f).replace(/\\/g, "/");
|
|
12383
12928
|
if (!rel2.includes("/") && f.toLowerCase().endsWith(".md")) {
|
|
12384
|
-
names.add(
|
|
12929
|
+
names.add(basename37(f, ".md"));
|
|
12385
12930
|
}
|
|
12386
12931
|
}
|
|
12387
12932
|
return [...names].filter(Boolean).sort();
|
|
12388
12933
|
}
|
|
12389
12934
|
|
|
12390
12935
|
// src/install/native/native-path-pick-infer-copilot.ts
|
|
12391
|
-
import { basename as
|
|
12936
|
+
import { basename as basename38, join as join72 } from "path";
|
|
12392
12937
|
async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
12393
|
-
const scan =
|
|
12938
|
+
const scan = join72(repoRoot, ...posixPath.split("/"));
|
|
12394
12939
|
if (posixPath.startsWith(COPILOT_PROMPTS_DIR)) {
|
|
12395
12940
|
const files = await readDirRecursive(scan);
|
|
12396
12941
|
const commands = [
|
|
12397
12942
|
...new Set(
|
|
12398
|
-
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"))
|
|
12399
12944
|
)
|
|
12400
12945
|
].sort();
|
|
12401
12946
|
return commands.length ? { commands } : {};
|
|
@@ -12404,7 +12949,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12404
12949
|
const files = await readDirRecursive(scan);
|
|
12405
12950
|
const rules = [
|
|
12406
12951
|
...new Set(
|
|
12407
|
-
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, ""))
|
|
12408
12953
|
)
|
|
12409
12954
|
].sort();
|
|
12410
12955
|
return rules.length ? { rules } : {};
|
|
@@ -12413,10 +12958,10 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12413
12958
|
const files = await readDirRecursive(scan);
|
|
12414
12959
|
const names = /* @__PURE__ */ new Set();
|
|
12415
12960
|
for (const f of files) {
|
|
12416
|
-
const b =
|
|
12961
|
+
const b = basename38(f);
|
|
12417
12962
|
if (b.toLowerCase().endsWith(".instructions.md"))
|
|
12418
12963
|
names.add(b.replace(/\.instructions\.md$/i, ""));
|
|
12419
|
-
else if (b.toLowerCase().endsWith(".md")) names.add(
|
|
12964
|
+
else if (b.toLowerCase().endsWith(".md")) names.add(basename38(f, ".md"));
|
|
12420
12965
|
}
|
|
12421
12966
|
const rules = [...names].sort();
|
|
12422
12967
|
return rules.length ? { rules } : {};
|
|
@@ -12429,7 +12974,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12429
12974
|
const files = await readDirRecursive(scan);
|
|
12430
12975
|
const agents = [
|
|
12431
12976
|
...new Set(
|
|
12432
|
-
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"))
|
|
12433
12978
|
)
|
|
12434
12979
|
].sort();
|
|
12435
12980
|
return agents.length ? { agents } : {};
|
|
@@ -12442,20 +12987,20 @@ async function mdNames(dir, ext) {
|
|
|
12442
12987
|
const files = await readDirRecursive(dir);
|
|
12443
12988
|
const e = ext.toLowerCase();
|
|
12444
12989
|
return [
|
|
12445
|
-
...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)))
|
|
12446
12991
|
].sort();
|
|
12447
12992
|
}
|
|
12448
|
-
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix,
|
|
12993
|
+
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target13) {
|
|
12449
12994
|
const posixPath = pathInRepoPosix.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12450
|
-
const scan =
|
|
12451
|
-
if (
|
|
12995
|
+
const scan = join73(repoRoot, ...posixPath.split("/"));
|
|
12996
|
+
if (target13 === "gemini-cli") {
|
|
12452
12997
|
if (posixPath === GEMINI_COMMANDS_DIR || posixPath.startsWith(`${GEMINI_COMMANDS_DIR}/`)) {
|
|
12453
12998
|
const commands = await inferGeminiCommandNamesFromFiles(repoRoot, posixPath);
|
|
12454
12999
|
return commands.length ? { commands } : {};
|
|
12455
13000
|
}
|
|
12456
13001
|
return {};
|
|
12457
13002
|
}
|
|
12458
|
-
if (
|
|
13003
|
+
if (target13 === "claude-code") {
|
|
12459
13004
|
if (posixPath.startsWith(".claude/commands")) {
|
|
12460
13005
|
const commands = await mdNames(scan, ".md");
|
|
12461
13006
|
return commands.length ? { commands } : {};
|
|
@@ -12475,7 +13020,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12475
13020
|
}
|
|
12476
13021
|
return {};
|
|
12477
13022
|
}
|
|
12478
|
-
if (
|
|
13023
|
+
if (target13 === "cursor") {
|
|
12479
13024
|
if (posixPath.startsWith(".cursor/rules")) {
|
|
12480
13025
|
const rules = await mdNames(scan, ".mdc");
|
|
12481
13026
|
return rules.length ? { rules } : {};
|
|
@@ -12494,14 +13039,14 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12494
13039
|
}
|
|
12495
13040
|
return {};
|
|
12496
13041
|
}
|
|
12497
|
-
if (
|
|
13042
|
+
if (target13 === "copilot") {
|
|
12498
13043
|
return inferCopilotPickFromPath(repoRoot, posixPath);
|
|
12499
13044
|
}
|
|
12500
|
-
if (
|
|
13045
|
+
if (target13 === "windsurf" && posixPath.startsWith(".windsurf/rules")) {
|
|
12501
13046
|
const rules = await mdNames(scan, ".md");
|
|
12502
13047
|
return rules.length ? { rules } : {};
|
|
12503
13048
|
}
|
|
12504
|
-
if (
|
|
13049
|
+
if (target13 === "cline") {
|
|
12505
13050
|
if (posixPath.startsWith(CLINE_SKILLS_DIR)) {
|
|
12506
13051
|
const skills = await skillNamesFromNativeSkillDir(scan);
|
|
12507
13052
|
return skills.length ? { skills } : {};
|
|
@@ -12512,7 +13057,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12512
13057
|
}
|
|
12513
13058
|
return {};
|
|
12514
13059
|
}
|
|
12515
|
-
if (
|
|
13060
|
+
if (target13 === "continue") {
|
|
12516
13061
|
if (posixPath.startsWith(".continue/rules")) {
|
|
12517
13062
|
const rules = await mdNames(scan, ".md");
|
|
12518
13063
|
return rules.length ? { rules } : {};
|
|
@@ -12527,7 +13072,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12527
13072
|
}
|
|
12528
13073
|
return {};
|
|
12529
13074
|
}
|
|
12530
|
-
if (
|
|
13075
|
+
if (target13 === "junie") {
|
|
12531
13076
|
if (posixPath.startsWith(".junie/commands")) {
|
|
12532
13077
|
const commands = await mdNames(scan, ".md");
|
|
12533
13078
|
return commands.length ? { commands } : {};
|
|
@@ -12546,11 +13091,11 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12546
13091
|
}
|
|
12547
13092
|
return {};
|
|
12548
13093
|
}
|
|
12549
|
-
if (
|
|
13094
|
+
if (target13 === "codex-cli" && posixPath.startsWith(".codex")) {
|
|
12550
13095
|
const files = await readDirRecursive(scan);
|
|
12551
13096
|
const rules = [
|
|
12552
13097
|
...new Set(
|
|
12553
|
-
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) =>
|
|
13098
|
+
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) => basename39(f, ".md"))
|
|
12554
13099
|
)
|
|
12555
13100
|
].sort();
|
|
12556
13101
|
return rules.length ? { rules } : {};
|
|
@@ -12562,7 +13107,7 @@ function isImplicitPickEmpty(p) {
|
|
|
12562
13107
|
}
|
|
12563
13108
|
|
|
12564
13109
|
// src/install/native/native-install-scope.ts
|
|
12565
|
-
import { basename as
|
|
13110
|
+
import { basename as basename40, join as join74, relative as relative30 } from "path";
|
|
12566
13111
|
import { cp as cp3, mkdtemp as mkdtemp2, rm as rm9 } from "fs/promises";
|
|
12567
13112
|
import { tmpdir as tmpdir2 } from "os";
|
|
12568
13113
|
function normalizePath3(path) {
|
|
@@ -12573,14 +13118,14 @@ function overlapsPath(requested, imported) {
|
|
|
12573
13118
|
const b = normalizePath3(imported);
|
|
12574
13119
|
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
12575
13120
|
}
|
|
12576
|
-
function addUnique(
|
|
12577
|
-
const next =
|
|
13121
|
+
function addUnique(target13, value) {
|
|
13122
|
+
const next = target13 ?? [];
|
|
12578
13123
|
if (!next.includes(value)) next.push(value);
|
|
12579
13124
|
return next;
|
|
12580
13125
|
}
|
|
12581
13126
|
async function makeStageRoot(repoRoot) {
|
|
12582
|
-
const stageBase = await mkdtemp2(
|
|
12583
|
-
const stageRoot =
|
|
13127
|
+
const stageBase = await mkdtemp2(join74(tmpdir2(), "am-install-native-"));
|
|
13128
|
+
const stageRoot = join74(stageBase, "repo");
|
|
12584
13129
|
const cleanup = async () => {
|
|
12585
13130
|
await rm9(stageBase, { recursive: true, force: true });
|
|
12586
13131
|
};
|
|
@@ -12598,13 +13143,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12598
13143
|
if (result.feature === "rules" && result.toPath.startsWith(".agentsmesh/rules/")) {
|
|
12599
13144
|
pick = {
|
|
12600
13145
|
...pick,
|
|
12601
|
-
rules: addUnique(pick?.rules,
|
|
13146
|
+
rules: addUnique(pick?.rules, basename40(result.toPath, ".md"))
|
|
12602
13147
|
};
|
|
12603
13148
|
continue;
|
|
12604
13149
|
}
|
|
12605
13150
|
if (result.feature === "commands" && result.toPath.startsWith(".agentsmesh/commands/")) {
|
|
12606
13151
|
const rel2 = normalizePath3(
|
|
12607
|
-
relative30(
|
|
13152
|
+
relative30(join74(stageRoot, ".agentsmesh", "commands"), join74(stageRoot, result.toPath))
|
|
12608
13153
|
);
|
|
12609
13154
|
pick = {
|
|
12610
13155
|
...pick,
|
|
@@ -12618,13 +13163,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12618
13163
|
if (result.feature === "agents" && result.toPath.startsWith(".agentsmesh/agents/")) {
|
|
12619
13164
|
pick = {
|
|
12620
13165
|
...pick,
|
|
12621
|
-
agents: addUnique(pick?.agents,
|
|
13166
|
+
agents: addUnique(pick?.agents, basename40(result.toPath, ".md"))
|
|
12622
13167
|
};
|
|
12623
13168
|
continue;
|
|
12624
13169
|
}
|
|
12625
13170
|
if (result.feature === "skills" && result.toPath.startsWith(".agentsmesh/skills/")) {
|
|
12626
13171
|
const rel2 = normalizePath3(
|
|
12627
|
-
relative30(
|
|
13172
|
+
relative30(join74(stageRoot, ".agentsmesh", "skills"), join74(stageRoot, result.toPath))
|
|
12628
13173
|
);
|
|
12629
13174
|
const skillName = rel2.split("/")[0];
|
|
12630
13175
|
if (skillName) {
|
|
@@ -12639,12 +13184,12 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12639
13184
|
const hasAny = (pick.rules?.length ?? 0) + (pick.commands?.length ?? 0) + (pick.agents?.length ?? 0) + (pick.skills?.length ?? 0) > 0;
|
|
12640
13185
|
return hasAny ? pick : void 0;
|
|
12641
13186
|
}
|
|
12642
|
-
function scopeImportedResults(pathInRepoPosix, stageRoot, results,
|
|
12643
|
-
const requestedPath =
|
|
13187
|
+
function scopeImportedResults(pathInRepoPosix, stageRoot, results, target13) {
|
|
13188
|
+
const requestedPath = join74(stageRoot, ...normalizePath3(pathInRepoPosix).split("/"));
|
|
12644
13189
|
const filtered = results.filter((result) => overlapsPath(requestedPath, result.fromPath));
|
|
12645
13190
|
if (filtered.length === 0) {
|
|
12646
13191
|
throw new Error(
|
|
12647
|
-
`No installable native resources found under "${pathInRepoPosix}" for target "${
|
|
13192
|
+
`No installable native resources found under "${pathInRepoPosix}" for target "${target13}".`
|
|
12648
13193
|
);
|
|
12649
13194
|
}
|
|
12650
13195
|
return {
|
|
@@ -12652,23 +13197,23 @@ function scopeImportedResults(pathInRepoPosix, stageRoot, results, target12) {
|
|
|
12652
13197
|
pick: buildPickFromResults(filtered, stageRoot)
|
|
12653
13198
|
};
|
|
12654
13199
|
}
|
|
12655
|
-
async function stageImportedNativeRepo(repoRoot,
|
|
13200
|
+
async function stageImportedNativeRepo(repoRoot, target13) {
|
|
12656
13201
|
const { stageRoot, cleanup } = await makeStageRoot(repoRoot);
|
|
12657
13202
|
try {
|
|
12658
|
-
const results = await importNativeToCanonical(stageRoot,
|
|
13203
|
+
const results = await importNativeToCanonical(stageRoot, target13);
|
|
12659
13204
|
return { stageRoot, results, cleanup };
|
|
12660
13205
|
} catch (error) {
|
|
12661
13206
|
await cleanup();
|
|
12662
13207
|
throw error;
|
|
12663
13208
|
}
|
|
12664
13209
|
}
|
|
12665
|
-
async function stageNativeInstallScope(repoRoot, pathInRepoPosix,
|
|
12666
|
-
const staged = await stageImportedNativeRepo(repoRoot,
|
|
13210
|
+
async function stageNativeInstallScope(repoRoot, pathInRepoPosix, target13) {
|
|
13211
|
+
const staged = await stageImportedNativeRepo(repoRoot, target13);
|
|
12667
13212
|
try {
|
|
12668
13213
|
return {
|
|
12669
13214
|
stageRoot: staged.stageRoot,
|
|
12670
13215
|
cleanup: staged.cleanup,
|
|
12671
|
-
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results,
|
|
13216
|
+
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results, target13)
|
|
12672
13217
|
};
|
|
12673
13218
|
} catch (error) {
|
|
12674
13219
|
await staged.cleanup();
|
|
@@ -12684,7 +13229,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12684
13229
|
}
|
|
12685
13230
|
const posixPath = pathInRepo.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12686
13231
|
validateTargetMatchesPath(explicitTarget, posixPath);
|
|
12687
|
-
const agentsmeshAtRoot =
|
|
13232
|
+
const agentsmeshAtRoot = join75(repoRoot, ".agentsmesh");
|
|
12688
13233
|
const hasAbRoot = await exists(agentsmeshAtRoot);
|
|
12689
13234
|
const pathHint = posixPath ? targetHintFromNativePath(posixPath) : void 0;
|
|
12690
13235
|
const detectedTarget = !hasAbRoot && !explicitTarget ? await detectNativeFormat(repoRoot) ?? void 0 : void 0;
|
|
@@ -12709,7 +13254,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12709
13254
|
}
|
|
12710
13255
|
const staged = await stageImportedNativeRepo(repoRoot, effectiveTarget);
|
|
12711
13256
|
return {
|
|
12712
|
-
discoveryRoot: posixPath ?
|
|
13257
|
+
discoveryRoot: posixPath ? join75(staged.stageRoot, posixPath) : staged.stageRoot,
|
|
12713
13258
|
yamlTarget: effectiveTarget,
|
|
12714
13259
|
importHappened: true,
|
|
12715
13260
|
cleanup: staged.cleanup
|
|
@@ -12812,13 +13357,13 @@ function applyReplayInstallScope(narrowed, discoveredFeatures, replay) {
|
|
|
12812
13357
|
}
|
|
12813
13358
|
|
|
12814
13359
|
// src/install/manual/manual-install-persistence.ts
|
|
12815
|
-
import { basename as
|
|
13360
|
+
import { basename as basename41, dirname as dirname27, join as join76 } from "path";
|
|
12816
13361
|
import { stat as stat6 } from "fs/promises";
|
|
12817
13362
|
function trimDot(pathInRepo) {
|
|
12818
13363
|
return pathInRepo === "." || pathInRepo === "" ? void 0 : pathInRepo;
|
|
12819
13364
|
}
|
|
12820
13365
|
function markdownPick(as, pathValue) {
|
|
12821
|
-
const name =
|
|
13366
|
+
const name = basename41(pathValue).replace(/\.md$/i, "");
|
|
12822
13367
|
if (as === "agents") return { agents: [name] };
|
|
12823
13368
|
if (as === "commands") return { commands: [name] };
|
|
12824
13369
|
return { rules: [name] };
|
|
@@ -12836,23 +13381,23 @@ async function resolveManualInstallPersistence(args) {
|
|
|
12836
13381
|
};
|
|
12837
13382
|
}
|
|
12838
13383
|
if (args.as === "skills") {
|
|
12839
|
-
if (info.isFile() &&
|
|
13384
|
+
if (info.isFile() && basename41(args.contentRoot) === "SKILL.md") {
|
|
12840
13385
|
const skillDir = normalizedPath ? dirname27(normalizedPath) : dirname27(args.contentRoot);
|
|
12841
13386
|
return {
|
|
12842
13387
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12843
|
-
pick: { skills: [
|
|
13388
|
+
pick: { skills: [basename41(skillDir)] }
|
|
12844
13389
|
};
|
|
12845
13390
|
}
|
|
12846
13391
|
if (info.isDirectory()) {
|
|
12847
|
-
const skillDir = normalizedPath ||
|
|
12848
|
-
const skillFile =
|
|
13392
|
+
const skillDir = normalizedPath || basename41(args.contentRoot);
|
|
13393
|
+
const skillFile = join76(args.contentRoot.replace(/\/+$/g, ""), "SKILL.md");
|
|
12849
13394
|
try {
|
|
12850
13395
|
const skillStat = await stat6(skillFile);
|
|
12851
13396
|
if (skillStat.isFile()) {
|
|
12852
13397
|
const fmName = await readSkillFrontmatterName(skillFile);
|
|
12853
13398
|
return {
|
|
12854
13399
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12855
|
-
pick: { skills: [fmName ||
|
|
13400
|
+
pick: { skills: [fmName || basename41(skillDir)] }
|
|
12856
13401
|
};
|
|
12857
13402
|
}
|
|
12858
13403
|
} catch {
|
|
@@ -12920,7 +13465,7 @@ async function runInstall(flags, args, projectRoot, replay) {
|
|
|
12920
13465
|
sourceArg
|
|
12921
13466
|
);
|
|
12922
13467
|
const pathInRepo = parsed.pathInRepo.replace(/^\/+|\/+$/g, "");
|
|
12923
|
-
const contentRoot = pathInRepo ?
|
|
13468
|
+
const contentRoot = pathInRepo ? join77(resolvedPath, pathInRepo) : resolvedPath;
|
|
12924
13469
|
if (!await exists(contentRoot)) {
|
|
12925
13470
|
throw new Error(`Install path does not exist: ${contentRoot}`);
|
|
12926
13471
|
}
|