agentsmesh 0.2.8 → 0.2.10
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 +12 -0
- package/README.md +11 -11
- package/dist/cli.js +800 -459
- package/dist/cli.js.map +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -247,7 +247,7 @@ function handleError(err, options) {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
// src/cli/commands/generate.ts
|
|
250
|
-
import { join as
|
|
250
|
+
import { join as join55, resolve as resolve4, sep } from "path";
|
|
251
251
|
|
|
252
252
|
// src/config/core/loader.ts
|
|
253
253
|
import { parse as parseYaml } from "yaml";
|
|
@@ -359,7 +359,8 @@ var TARGET_IDS = [
|
|
|
359
359
|
"cline",
|
|
360
360
|
"codex-cli",
|
|
361
361
|
"windsurf",
|
|
362
|
-
"antigravity"
|
|
362
|
+
"antigravity",
|
|
363
|
+
"roo-code"
|
|
363
364
|
];
|
|
364
365
|
function isBuiltinTargetId(value) {
|
|
365
366
|
return TARGET_IDS.includes(value);
|
|
@@ -524,7 +525,7 @@ async function loadConfigFromDir(startDir) {
|
|
|
524
525
|
}
|
|
525
526
|
|
|
526
527
|
// src/canonical/extends/extends.ts
|
|
527
|
-
import { join as
|
|
528
|
+
import { join as join47 } from "path";
|
|
528
529
|
|
|
529
530
|
// src/config/resolve/resolver.ts
|
|
530
531
|
import { mkdir as mkdir4, rm as rm4 } from "fs/promises";
|
|
@@ -1464,7 +1465,7 @@ function mergeIgnore(base, overlay) {
|
|
|
1464
1465
|
}
|
|
1465
1466
|
|
|
1466
1467
|
// src/canonical/extends/extend-load.ts
|
|
1467
|
-
import { join as
|
|
1468
|
+
import { join as join44 } from "path";
|
|
1468
1469
|
|
|
1469
1470
|
// src/config/resolve/native-format-detector.ts
|
|
1470
1471
|
import { join as join10 } from "path";
|
|
@@ -1542,11 +1543,11 @@ var KNOWN_NATIVE_PATHS = TARGET_SIGNATURES.map((sig) => sig.paths[0]).filter(
|
|
|
1542
1543
|
);
|
|
1543
1544
|
|
|
1544
1545
|
// src/targets/claude-code/importer.ts
|
|
1545
|
-
import { join as
|
|
1546
|
+
import { join as join41, basename as basename26, relative as relative17, dirname as dirname18 } from "path";
|
|
1546
1547
|
|
|
1547
1548
|
// src/core/reference/import-rewriter.ts
|
|
1548
1549
|
import { existsSync as existsSync2, realpathSync as realpathSync3 } from "fs";
|
|
1549
|
-
import { join as
|
|
1550
|
+
import { join as join38 } from "path";
|
|
1550
1551
|
import { normalize as normalizePath } from "path";
|
|
1551
1552
|
|
|
1552
1553
|
// src/config/core/conversions.ts
|
|
@@ -1561,22 +1562,22 @@ var DEFAULT_AGENTS_TO_SKILLS = {
|
|
|
1561
1562
|
// native .codex/agents/*.toml per agent-structures
|
|
1562
1563
|
windsurf: true
|
|
1563
1564
|
};
|
|
1564
|
-
function hasOwnTarget(map,
|
|
1565
|
-
return Object.prototype.hasOwnProperty.call(map,
|
|
1565
|
+
function hasOwnTarget(map, target12) {
|
|
1566
|
+
return Object.prototype.hasOwnProperty.call(map, target12);
|
|
1566
1567
|
}
|
|
1567
|
-
function usesCommandSkillProjection(
|
|
1568
|
-
return hasOwnTarget(DEFAULT_COMMANDS_TO_SKILLS,
|
|
1568
|
+
function usesCommandSkillProjection(target12) {
|
|
1569
|
+
return hasOwnTarget(DEFAULT_COMMANDS_TO_SKILLS, target12);
|
|
1569
1570
|
}
|
|
1570
|
-
function usesAgentSkillProjection(
|
|
1571
|
-
return hasOwnTarget(DEFAULT_AGENTS_TO_SKILLS,
|
|
1571
|
+
function usesAgentSkillProjection(target12) {
|
|
1572
|
+
return hasOwnTarget(DEFAULT_AGENTS_TO_SKILLS, target12);
|
|
1572
1573
|
}
|
|
1573
|
-
function shouldConvertCommandsToSkills(config,
|
|
1574
|
-
if (!usesCommandSkillProjection(
|
|
1575
|
-
return config.conversions?.commands_to_skills?.[
|
|
1574
|
+
function shouldConvertCommandsToSkills(config, target12) {
|
|
1575
|
+
if (!usesCommandSkillProjection(target12)) return false;
|
|
1576
|
+
return config.conversions?.commands_to_skills?.[target12] ?? DEFAULT_COMMANDS_TO_SKILLS[target12];
|
|
1576
1577
|
}
|
|
1577
|
-
function shouldConvertAgentsToSkills(config,
|
|
1578
|
-
if (!usesAgentSkillProjection(
|
|
1579
|
-
return config.conversions?.agents_to_skills?.[
|
|
1578
|
+
function shouldConvertAgentsToSkills(config, target12) {
|
|
1579
|
+
if (!usesAgentSkillProjection(target12)) return false;
|
|
1580
|
+
return config.conversions?.agents_to_skills?.[target12] ?? DEFAULT_AGENTS_TO_SKILLS[target12];
|
|
1580
1581
|
}
|
|
1581
1582
|
|
|
1582
1583
|
// src/targets/claude-code/constants.ts
|
|
@@ -1873,6 +1874,22 @@ var JUNIE_CANONICAL_AGENTS_DIR = ".agentsmesh/agents";
|
|
|
1873
1874
|
var JUNIE_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
1874
1875
|
var JUNIE_CANONICAL_IGNORE = ".agentsmesh/ignore";
|
|
1875
1876
|
|
|
1877
|
+
// src/targets/roo-code/constants.ts
|
|
1878
|
+
var ROO_CODE_TARGET = "roo-code";
|
|
1879
|
+
var ROO_CODE_DIR = ".roo";
|
|
1880
|
+
var ROO_CODE_ROOT_RULE = `${ROO_CODE_DIR}/rules/00-root.md`;
|
|
1881
|
+
var ROO_CODE_ROOT_RULE_FALLBACK = ".roorules";
|
|
1882
|
+
var ROO_CODE_RULES_DIR = `${ROO_CODE_DIR}/rules`;
|
|
1883
|
+
var ROO_CODE_COMMANDS_DIR = `${ROO_CODE_DIR}/commands`;
|
|
1884
|
+
var ROO_CODE_SKILLS_DIR = `${ROO_CODE_DIR}/skills`;
|
|
1885
|
+
var ROO_CODE_MCP_FILE = `${ROO_CODE_DIR}/mcp.json`;
|
|
1886
|
+
var ROO_CODE_IGNORE = ".rooignore";
|
|
1887
|
+
var ROO_CODE_CANONICAL_ROOT_RULE = ".agentsmesh/rules/_root.md";
|
|
1888
|
+
var ROO_CODE_CANONICAL_RULES_DIR = ".agentsmesh/rules";
|
|
1889
|
+
var ROO_CODE_CANONICAL_COMMANDS_DIR = ".agentsmesh/commands";
|
|
1890
|
+
var ROO_CODE_CANONICAL_MCP = ".agentsmesh/mcp.json";
|
|
1891
|
+
var ROO_CODE_CANONICAL_IGNORE = ".agentsmesh/ignore";
|
|
1892
|
+
|
|
1876
1893
|
// src/targets/antigravity/constants.ts
|
|
1877
1894
|
var ANTIGRAVITY_TARGET = "antigravity";
|
|
1878
1895
|
var ANTIGRAVITY_DIR = ".agents";
|
|
@@ -2107,7 +2124,8 @@ var SCOPED_AGENTS_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
2107
2124
|
".gemini",
|
|
2108
2125
|
".github",
|
|
2109
2126
|
".junie",
|
|
2110
|
-
".windsurf"
|
|
2127
|
+
".windsurf",
|
|
2128
|
+
".roo"
|
|
2111
2129
|
]);
|
|
2112
2130
|
async function addScopedAgentsMappings(refs, projectRoot) {
|
|
2113
2131
|
const files = await listFiles(projectRoot, ".");
|
|
@@ -2303,6 +2321,27 @@ async function buildAntigravityImportPaths(refs, projectRoot) {
|
|
|
2303
2321
|
addSkillLikeMapping(refs, rel(projectRoot, absPath), ANTIGRAVITY_SKILLS_DIR);
|
|
2304
2322
|
}
|
|
2305
2323
|
}
|
|
2324
|
+
async function buildRooCodeImportPaths(refs, projectRoot) {
|
|
2325
|
+
refs.set(ROO_CODE_ROOT_RULE, `${AB_RULES2}/_root.md`);
|
|
2326
|
+
refs.set(ROO_CODE_ROOT_RULE_FALLBACK, `${AB_RULES2}/_root.md`);
|
|
2327
|
+
for (const absPath of await listFiles(projectRoot, ROO_CODE_RULES_DIR)) {
|
|
2328
|
+
const relPath = rel(projectRoot, absPath);
|
|
2329
|
+
if (relPath === ROO_CODE_ROOT_RULE) continue;
|
|
2330
|
+
addSimpleFileMapping(refs, relPath, AB_RULES2, ".md");
|
|
2331
|
+
}
|
|
2332
|
+
for (const absPath of await listFiles(projectRoot, ".roo")) {
|
|
2333
|
+
const relPath = rel(projectRoot, absPath);
|
|
2334
|
+
if (/^\.roo\/rules-[^/]+\/.+\.md$/.test(relPath)) {
|
|
2335
|
+
addSimpleFileMapping(refs, relPath, AB_RULES2, ".md");
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
for (const absPath of await listFiles(projectRoot, ROO_CODE_COMMANDS_DIR)) {
|
|
2339
|
+
addSimpleFileMapping(refs, rel(projectRoot, absPath), AB_COMMANDS2, ".md");
|
|
2340
|
+
}
|
|
2341
|
+
for (const absPath of await listFiles(projectRoot, ROO_CODE_SKILLS_DIR)) {
|
|
2342
|
+
addSkillLikeMapping(refs, rel(projectRoot, absPath), ROO_CODE_SKILLS_DIR);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2306
2345
|
|
|
2307
2346
|
// src/targets/claude-code/index.ts
|
|
2308
2347
|
var target = {
|
|
@@ -2495,64 +2534,57 @@ import { join as join15, dirname as dirname9 } from "path";
|
|
|
2495
2534
|
import { basename as basename8, dirname as dirname5 } from "path";
|
|
2496
2535
|
|
|
2497
2536
|
// src/targets/projection/root-instruction-paragraph.ts
|
|
2498
|
-
var
|
|
2499
|
-
var
|
|
2500
|
-
var
|
|
2537
|
+
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
|
+
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 ROOT_INSTRUCTION_BODY = "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.";
|
|
2540
|
+
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = ROOT_INSTRUCTION_BODY_V1;
|
|
2501
2541
|
var LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION = `## Project-Specific Rules
|
|
2502
2542
|
|
|
2503
|
-
${
|
|
2504
|
-
var
|
|
2543
|
+
${ROOT_INSTRUCTION_BODY_V1}`;
|
|
2544
|
+
var AGENTSMESH_CONTRACT_WITH_V1_BODY = `## AgentsMesh Generation Contract
|
|
2545
|
+
|
|
2546
|
+
${ROOT_INSTRUCTION_BODY_V1}`;
|
|
2547
|
+
var AGENTSMESH_CONTRACT_WITH_V2_BODY = `## AgentsMesh Generation Contract
|
|
2505
2548
|
|
|
2506
|
-
${
|
|
2549
|
+
${ROOT_INSTRUCTION_BODY_V2}`;
|
|
2507
2550
|
var AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = `## AgentsMesh Generation Contract
|
|
2508
2551
|
|
|
2509
2552
|
${ROOT_INSTRUCTION_BODY}`;
|
|
2510
2553
|
function normalizeWhitespace(value) {
|
|
2511
2554
|
return value.replace(/\s+/g, " ").trim();
|
|
2512
2555
|
}
|
|
2556
|
+
var LEGACY_FORMS = [
|
|
2557
|
+
AGENTSMESH_CONTRACT_WITH_V2_BODY,
|
|
2558
|
+
AGENTSMESH_CONTRACT_WITH_V1_BODY,
|
|
2559
|
+
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION,
|
|
2560
|
+
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2561
|
+
];
|
|
2513
2562
|
function appendAgentsmeshRootInstructionParagraph(content) {
|
|
2514
2563
|
const trimmed = content.trim();
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
)) {
|
|
2564
|
+
const norm2 = normalizeWhitespace(trimmed);
|
|
2565
|
+
if (norm2.includes(normalizeWhitespace(AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH))) {
|
|
2518
2566
|
return trimmed;
|
|
2519
2567
|
}
|
|
2520
|
-
|
|
2521
|
-
normalizeWhitespace(
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION,
|
|
2525
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2526
|
-
);
|
|
2527
|
-
}
|
|
2528
|
-
if (normalizeWhitespace(trimmed).includes(normalizeWhitespace(AGENTSMESH_CONTRACT_WITH_LEGACY_BODY))) {
|
|
2529
|
-
return trimmed.replace(
|
|
2530
|
-
AGENTSMESH_CONTRACT_WITH_LEGACY_BODY,
|
|
2531
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2532
|
-
);
|
|
2533
|
-
}
|
|
2534
|
-
if (normalizeWhitespace(trimmed).includes(
|
|
2535
|
-
normalizeWhitespace(LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH)
|
|
2536
|
-
)) {
|
|
2537
|
-
return trimmed.replace(
|
|
2538
|
-
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH,
|
|
2539
|
-
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH
|
|
2540
|
-
);
|
|
2568
|
+
for (const legacy of LEGACY_FORMS) {
|
|
2569
|
+
if (norm2.includes(normalizeWhitespace(legacy))) {
|
|
2570
|
+
return trimmed.replace(legacy, AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH);
|
|
2571
|
+
}
|
|
2541
2572
|
}
|
|
2542
2573
|
return trimmed ? `${trimmed}
|
|
2543
2574
|
|
|
2544
2575
|
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}` : AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH;
|
|
2545
2576
|
}
|
|
2546
2577
|
function stripAgentsmeshRootInstructionParagraph(content) {
|
|
2547
|
-
|
|
2578
|
+
let result = content;
|
|
2579
|
+
result = result.replace(`
|
|
2548
2580
|
|
|
2549
|
-
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "")
|
|
2581
|
+
${AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "");
|
|
2582
|
+
for (const legacy of LEGACY_FORMS) {
|
|
2583
|
+
result = result.replace(`
|
|
2550
2584
|
|
|
2551
|
-
${
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
${LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH}`, "").trim();
|
|
2585
|
+
${legacy}`, "");
|
|
2586
|
+
}
|
|
2587
|
+
return result.trim();
|
|
2556
2588
|
}
|
|
2557
2589
|
|
|
2558
2590
|
// src/targets/import/import-metadata.ts
|
|
@@ -5772,7 +5804,7 @@ function summarizeRule(rule) {
|
|
|
5772
5804
|
scopes.push(`Enforced in \`${CODEX_RULES_DIR}/${ruleSlug4(rule.source)}.rules\`.`);
|
|
5773
5805
|
}
|
|
5774
5806
|
if (rule.targets.length > 0) {
|
|
5775
|
-
scopes.push(`Targeted to ${rule.targets.map((
|
|
5807
|
+
scopes.push(`Targeted to ${rule.targets.map((target12) => `\`${target12}\``).join(", ")}.`);
|
|
5776
5808
|
}
|
|
5777
5809
|
return scopes.join(" ");
|
|
5778
5810
|
}
|
|
@@ -7221,6 +7253,323 @@ var descriptor10 = {
|
|
|
7221
7253
|
]
|
|
7222
7254
|
};
|
|
7223
7255
|
|
|
7256
|
+
// src/targets/roo-code/generator.ts
|
|
7257
|
+
import { basename as basename25 } from "path";
|
|
7258
|
+
function generateRules11(canonical) {
|
|
7259
|
+
const outputs = [];
|
|
7260
|
+
const root = canonical.rules.find((rule) => rule.root);
|
|
7261
|
+
if (root) {
|
|
7262
|
+
outputs.push({
|
|
7263
|
+
path: ROO_CODE_ROOT_RULE,
|
|
7264
|
+
content: root.body.trim() || ""
|
|
7265
|
+
});
|
|
7266
|
+
}
|
|
7267
|
+
for (const rule of canonical.rules) {
|
|
7268
|
+
if (rule.root) continue;
|
|
7269
|
+
if (rule.targets.length > 0 && !rule.targets.includes(ROO_CODE_TARGET)) continue;
|
|
7270
|
+
const slug = basename25(rule.source, ".md");
|
|
7271
|
+
outputs.push({
|
|
7272
|
+
path: `${ROO_CODE_RULES_DIR}/${slug}.md`,
|
|
7273
|
+
content: rule.body.trim() || ""
|
|
7274
|
+
});
|
|
7275
|
+
}
|
|
7276
|
+
return outputs;
|
|
7277
|
+
}
|
|
7278
|
+
function generateCommands8(canonical) {
|
|
7279
|
+
return canonical.commands.map((command) => {
|
|
7280
|
+
const frontmatter = {};
|
|
7281
|
+
if (command.description) frontmatter.description = command.description;
|
|
7282
|
+
return {
|
|
7283
|
+
path: `${ROO_CODE_COMMANDS_DIR}/${command.name}.md`,
|
|
7284
|
+
content: serializeFrontmatter(frontmatter, command.body.trim() || "")
|
|
7285
|
+
};
|
|
7286
|
+
});
|
|
7287
|
+
}
|
|
7288
|
+
function generateMcp8(canonical) {
|
|
7289
|
+
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
7290
|
+
return [
|
|
7291
|
+
{
|
|
7292
|
+
path: ROO_CODE_MCP_FILE,
|
|
7293
|
+
content: JSON.stringify({ mcpServers: canonical.mcp.mcpServers }, null, 2)
|
|
7294
|
+
}
|
|
7295
|
+
];
|
|
7296
|
+
}
|
|
7297
|
+
function generateIgnore7(canonical) {
|
|
7298
|
+
if (canonical.ignore.length === 0) return [];
|
|
7299
|
+
return [{ path: ROO_CODE_IGNORE, content: canonical.ignore.join("\n") }];
|
|
7300
|
+
}
|
|
7301
|
+
function generateSkills11(canonical) {
|
|
7302
|
+
return generateEmbeddedSkills(canonical, ROO_CODE_SKILLS_DIR);
|
|
7303
|
+
}
|
|
7304
|
+
|
|
7305
|
+
// src/targets/roo-code/importer.ts
|
|
7306
|
+
import { readdir as readdir9 } from "fs/promises";
|
|
7307
|
+
import { join as join37 } from "path";
|
|
7308
|
+
function readMcpServers3(content) {
|
|
7309
|
+
const parsed = JSON.parse(content);
|
|
7310
|
+
const rawServers = parsed.mcpServers;
|
|
7311
|
+
if (!rawServers || typeof rawServers !== "object" || Array.isArray(rawServers)) return {};
|
|
7312
|
+
const servers = {};
|
|
7313
|
+
for (const [name, value] of Object.entries(rawServers)) {
|
|
7314
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
7315
|
+
const server = value;
|
|
7316
|
+
if (typeof server.command === "string") {
|
|
7317
|
+
servers[name] = {
|
|
7318
|
+
type: typeof server.type === "string" ? server.type : "stdio",
|
|
7319
|
+
command: server.command,
|
|
7320
|
+
args: toStringArray4(server.args),
|
|
7321
|
+
env: toStringRecord(server.env),
|
|
7322
|
+
description: typeof server.description === "string" ? server.description : void 0
|
|
7323
|
+
};
|
|
7324
|
+
continue;
|
|
7325
|
+
}
|
|
7326
|
+
if (typeof server.url === "string") {
|
|
7327
|
+
servers[name] = {
|
|
7328
|
+
type: typeof server.type === "string" ? server.type : "http",
|
|
7329
|
+
url: server.url,
|
|
7330
|
+
headers: toStringRecord(server.headers),
|
|
7331
|
+
env: toStringRecord(server.env),
|
|
7332
|
+
description: typeof server.description === "string" ? server.description : void 0
|
|
7333
|
+
};
|
|
7334
|
+
}
|
|
7335
|
+
}
|
|
7336
|
+
return servers;
|
|
7337
|
+
}
|
|
7338
|
+
async function importRootRule2(projectRoot, results, normalize) {
|
|
7339
|
+
const destPath = join37(projectRoot, ROO_CODE_CANONICAL_ROOT_RULE);
|
|
7340
|
+
const sources = [ROO_CODE_ROOT_RULE, ROO_CODE_ROOT_RULE_FALLBACK];
|
|
7341
|
+
for (const relPath of sources) {
|
|
7342
|
+
const srcPath = join37(projectRoot, relPath);
|
|
7343
|
+
const content = await readFileSafe(srcPath);
|
|
7344
|
+
if (content === null) continue;
|
|
7345
|
+
const { frontmatter, body } = parseFrontmatter(normalize(content, srcPath, destPath));
|
|
7346
|
+
const output = await serializeImportedRuleWithFallback(
|
|
7347
|
+
destPath,
|
|
7348
|
+
{
|
|
7349
|
+
root: true,
|
|
7350
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : void 0,
|
|
7351
|
+
globs: Array.isArray(frontmatter.globs) ? frontmatter.globs : void 0
|
|
7352
|
+
},
|
|
7353
|
+
body
|
|
7354
|
+
);
|
|
7355
|
+
await writeFileAtomic(destPath, output);
|
|
7356
|
+
results.push({
|
|
7357
|
+
fromTool: ROO_CODE_TARGET,
|
|
7358
|
+
fromPath: srcPath,
|
|
7359
|
+
toPath: ROO_CODE_CANONICAL_ROOT_RULE,
|
|
7360
|
+
feature: "rules"
|
|
7361
|
+
});
|
|
7362
|
+
return;
|
|
7363
|
+
}
|
|
7364
|
+
}
|
|
7365
|
+
async function importNonRootRules3(projectRoot, results, normalize) {
|
|
7366
|
+
const srcDir = join37(projectRoot, ROO_CODE_RULES_DIR);
|
|
7367
|
+
const destDir = join37(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7368
|
+
const rootRuleName = "00-root.md";
|
|
7369
|
+
results.push(
|
|
7370
|
+
...await importFileDirectory({
|
|
7371
|
+
srcDir,
|
|
7372
|
+
destDir,
|
|
7373
|
+
extensions: [".md"],
|
|
7374
|
+
fromTool: ROO_CODE_TARGET,
|
|
7375
|
+
normalize,
|
|
7376
|
+
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7377
|
+
if (relativePath === rootRuleName) return null;
|
|
7378
|
+
const destPath = join37(destDir, relativePath);
|
|
7379
|
+
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7380
|
+
const output = await serializeImportedRuleWithFallback(
|
|
7381
|
+
destPath,
|
|
7382
|
+
{
|
|
7383
|
+
root: false,
|
|
7384
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : void 0,
|
|
7385
|
+
globs: Array.isArray(frontmatter.globs) ? frontmatter.globs : void 0
|
|
7386
|
+
},
|
|
7387
|
+
body
|
|
7388
|
+
);
|
|
7389
|
+
return {
|
|
7390
|
+
destPath,
|
|
7391
|
+
toPath: `${ROO_CODE_CANONICAL_RULES_DIR}/${relativePath}`,
|
|
7392
|
+
feature: "rules",
|
|
7393
|
+
content: output
|
|
7394
|
+
};
|
|
7395
|
+
}
|
|
7396
|
+
})
|
|
7397
|
+
);
|
|
7398
|
+
}
|
|
7399
|
+
async function importPerModeRules(projectRoot, results, normalize) {
|
|
7400
|
+
const rooDir = join37(projectRoot, ROO_CODE_DIR);
|
|
7401
|
+
let entries;
|
|
7402
|
+
try {
|
|
7403
|
+
entries = await readdir9(rooDir, { withFileTypes: true });
|
|
7404
|
+
} catch {
|
|
7405
|
+
return;
|
|
7406
|
+
}
|
|
7407
|
+
const modeRuleDirs = entries.filter((e) => e.isDirectory() && e.name.startsWith("rules-")).map((e) => e.name);
|
|
7408
|
+
for (const dirName of modeRuleDirs) {
|
|
7409
|
+
const srcDir = join37(rooDir, dirName);
|
|
7410
|
+
const destDir = join37(projectRoot, ROO_CODE_CANONICAL_RULES_DIR);
|
|
7411
|
+
results.push(
|
|
7412
|
+
...await importFileDirectory({
|
|
7413
|
+
srcDir,
|
|
7414
|
+
destDir,
|
|
7415
|
+
extensions: [".md"],
|
|
7416
|
+
fromTool: ROO_CODE_TARGET,
|
|
7417
|
+
normalize,
|
|
7418
|
+
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7419
|
+
const destPath = join37(destDir, relativePath);
|
|
7420
|
+
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7421
|
+
const output = await serializeImportedRuleWithFallback(
|
|
7422
|
+
destPath,
|
|
7423
|
+
{
|
|
7424
|
+
root: false,
|
|
7425
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : void 0,
|
|
7426
|
+
globs: Array.isArray(frontmatter.globs) ? frontmatter.globs : void 0
|
|
7427
|
+
},
|
|
7428
|
+
body
|
|
7429
|
+
);
|
|
7430
|
+
return {
|
|
7431
|
+
destPath,
|
|
7432
|
+
toPath: `${ROO_CODE_CANONICAL_RULES_DIR}/${relativePath}`,
|
|
7433
|
+
feature: "rules",
|
|
7434
|
+
content: output
|
|
7435
|
+
};
|
|
7436
|
+
}
|
|
7437
|
+
})
|
|
7438
|
+
);
|
|
7439
|
+
}
|
|
7440
|
+
}
|
|
7441
|
+
async function importCommands5(projectRoot, results, normalize) {
|
|
7442
|
+
const srcDir = join37(projectRoot, ROO_CODE_COMMANDS_DIR);
|
|
7443
|
+
const destDir = join37(projectRoot, ROO_CODE_CANONICAL_COMMANDS_DIR);
|
|
7444
|
+
results.push(
|
|
7445
|
+
...await importFileDirectory({
|
|
7446
|
+
srcDir,
|
|
7447
|
+
destDir,
|
|
7448
|
+
extensions: [".md"],
|
|
7449
|
+
fromTool: ROO_CODE_TARGET,
|
|
7450
|
+
normalize,
|
|
7451
|
+
mapEntry: async ({ relativePath, normalizeTo }) => {
|
|
7452
|
+
const destPath = join37(destDir, relativePath);
|
|
7453
|
+
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7454
|
+
const output = await serializeImportedCommandWithFallback(
|
|
7455
|
+
destPath,
|
|
7456
|
+
{
|
|
7457
|
+
hasDescription: true,
|
|
7458
|
+
description: typeof frontmatter.description === "string" ? frontmatter.description : void 0,
|
|
7459
|
+
hasAllowedTools: false,
|
|
7460
|
+
allowedTools: []
|
|
7461
|
+
},
|
|
7462
|
+
body
|
|
7463
|
+
);
|
|
7464
|
+
return {
|
|
7465
|
+
destPath,
|
|
7466
|
+
toPath: `${ROO_CODE_CANONICAL_COMMANDS_DIR}/${relativePath}`,
|
|
7467
|
+
feature: "commands",
|
|
7468
|
+
content: output
|
|
7469
|
+
};
|
|
7470
|
+
}
|
|
7471
|
+
})
|
|
7472
|
+
);
|
|
7473
|
+
}
|
|
7474
|
+
async function importMcp6(projectRoot, results) {
|
|
7475
|
+
const srcPath = join37(projectRoot, ROO_CODE_MCP_FILE);
|
|
7476
|
+
const content = await readFileSafe(srcPath);
|
|
7477
|
+
if (content === null) return;
|
|
7478
|
+
const servers = readMcpServers3(content);
|
|
7479
|
+
if (Object.keys(servers).length === 0) return;
|
|
7480
|
+
await writeFileAtomic(
|
|
7481
|
+
join37(projectRoot, ROO_CODE_CANONICAL_MCP),
|
|
7482
|
+
JSON.stringify({ mcpServers: servers }, null, 2)
|
|
7483
|
+
);
|
|
7484
|
+
results.push({
|
|
7485
|
+
fromTool: ROO_CODE_TARGET,
|
|
7486
|
+
fromPath: srcPath,
|
|
7487
|
+
toPath: ROO_CODE_CANONICAL_MCP,
|
|
7488
|
+
feature: "mcp"
|
|
7489
|
+
});
|
|
7490
|
+
}
|
|
7491
|
+
async function importIgnore3(projectRoot, results) {
|
|
7492
|
+
const srcPath = join37(projectRoot, ROO_CODE_IGNORE);
|
|
7493
|
+
const content = await readFileSafe(srcPath);
|
|
7494
|
+
if (content === null) return;
|
|
7495
|
+
await writeFileAtomic(join37(projectRoot, ROO_CODE_CANONICAL_IGNORE), content.trimEnd());
|
|
7496
|
+
results.push({
|
|
7497
|
+
fromTool: ROO_CODE_TARGET,
|
|
7498
|
+
fromPath: srcPath,
|
|
7499
|
+
toPath: ROO_CODE_CANONICAL_IGNORE,
|
|
7500
|
+
feature: "ignore"
|
|
7501
|
+
});
|
|
7502
|
+
}
|
|
7503
|
+
async function importFromRooCode(projectRoot) {
|
|
7504
|
+
const results = [];
|
|
7505
|
+
const normalize = await createImportReferenceNormalizer(ROO_CODE_TARGET, projectRoot);
|
|
7506
|
+
await importRootRule2(projectRoot, results, normalize);
|
|
7507
|
+
await importNonRootRules3(projectRoot, results, normalize);
|
|
7508
|
+
await importPerModeRules(projectRoot, results, normalize);
|
|
7509
|
+
await importCommands5(projectRoot, results, normalize);
|
|
7510
|
+
await importEmbeddedSkills(projectRoot, ROO_CODE_SKILLS_DIR, ROO_CODE_TARGET, results, normalize);
|
|
7511
|
+
await importMcp6(projectRoot, results);
|
|
7512
|
+
await importIgnore3(projectRoot, results);
|
|
7513
|
+
return results;
|
|
7514
|
+
}
|
|
7515
|
+
|
|
7516
|
+
// src/targets/roo-code/linter.ts
|
|
7517
|
+
function lintRules11(canonical, projectRoot, projectFiles) {
|
|
7518
|
+
return validateRules(canonical, projectRoot, projectFiles).map((diagnostic) => ({
|
|
7519
|
+
...diagnostic,
|
|
7520
|
+
target: ROO_CODE_TARGET
|
|
7521
|
+
}));
|
|
7522
|
+
}
|
|
7523
|
+
|
|
7524
|
+
// src/targets/roo-code/index.ts
|
|
7525
|
+
var target11 = {
|
|
7526
|
+
name: "roo-code",
|
|
7527
|
+
primaryRootInstructionPath: ROO_CODE_ROOT_RULE,
|
|
7528
|
+
generateRules: generateRules11,
|
|
7529
|
+
generateCommands: generateCommands8,
|
|
7530
|
+
generateSkills: generateSkills11,
|
|
7531
|
+
generateMcp: generateMcp8,
|
|
7532
|
+
generateIgnore: generateIgnore7,
|
|
7533
|
+
importFrom: importFromRooCode
|
|
7534
|
+
};
|
|
7535
|
+
var descriptor11 = {
|
|
7536
|
+
id: "roo-code",
|
|
7537
|
+
generators: target11,
|
|
7538
|
+
capabilities: {
|
|
7539
|
+
rules: "native",
|
|
7540
|
+
commands: "native",
|
|
7541
|
+
agents: "none",
|
|
7542
|
+
skills: "native",
|
|
7543
|
+
mcp: "native",
|
|
7544
|
+
hooks: "none",
|
|
7545
|
+
ignore: "native",
|
|
7546
|
+
permissions: "none"
|
|
7547
|
+
},
|
|
7548
|
+
emptyImportMessage: "No Roo Code config found (.roo/rules, .roo/commands, .roo/skills, .roo/mcp.json, .rooignore, or .roorules).",
|
|
7549
|
+
lintRules: lintRules11,
|
|
7550
|
+
skillDir: ".roo/skills",
|
|
7551
|
+
paths: {
|
|
7552
|
+
rulePath(slug, _rule) {
|
|
7553
|
+
return `${ROO_CODE_RULES_DIR}/${slug}.md`;
|
|
7554
|
+
},
|
|
7555
|
+
commandPath(name, _config) {
|
|
7556
|
+
return `${ROO_CODE_COMMANDS_DIR}/${name}.md`;
|
|
7557
|
+
},
|
|
7558
|
+
agentPath(_name, _config) {
|
|
7559
|
+
return null;
|
|
7560
|
+
}
|
|
7561
|
+
},
|
|
7562
|
+
buildImportPaths: buildRooCodeImportPaths,
|
|
7563
|
+
detectionPaths: [
|
|
7564
|
+
".roo/rules",
|
|
7565
|
+
".roo/commands",
|
|
7566
|
+
".roo/skills",
|
|
7567
|
+
".roo/mcp.json",
|
|
7568
|
+
".rooignore",
|
|
7569
|
+
".roorules"
|
|
7570
|
+
]
|
|
7571
|
+
};
|
|
7572
|
+
|
|
7224
7573
|
// src/targets/catalog/builtin-targets.ts
|
|
7225
7574
|
var BUILTIN_TARGETS = [
|
|
7226
7575
|
descriptor,
|
|
@@ -7232,39 +7581,40 @@ var BUILTIN_TARGETS = [
|
|
|
7232
7581
|
descriptor7,
|
|
7233
7582
|
descriptor8,
|
|
7234
7583
|
descriptor9,
|
|
7235
|
-
descriptor10
|
|
7584
|
+
descriptor10,
|
|
7585
|
+
descriptor11
|
|
7236
7586
|
];
|
|
7237
|
-
function getBuiltinTargetDefinition(
|
|
7238
|
-
return BUILTIN_TARGETS.find((candidate) => candidate.id ===
|
|
7587
|
+
function getBuiltinTargetDefinition(target12) {
|
|
7588
|
+
return BUILTIN_TARGETS.find((candidate) => candidate.id === target12);
|
|
7239
7589
|
}
|
|
7240
|
-
function getTargetSkillDir(
|
|
7241
|
-
return getBuiltinTargetDefinition(
|
|
7590
|
+
function getTargetSkillDir(target12) {
|
|
7591
|
+
return getBuiltinTargetDefinition(target12)?.skillDir;
|
|
7242
7592
|
}
|
|
7243
|
-
function getEffectiveTargetSupportLevel(
|
|
7244
|
-
const definition = getBuiltinTargetDefinition(
|
|
7593
|
+
function getEffectiveTargetSupportLevel(target12, feature, config) {
|
|
7594
|
+
const definition = getBuiltinTargetDefinition(target12);
|
|
7245
7595
|
const baseLevel = definition?.capabilities[feature] ?? "none";
|
|
7246
7596
|
if (baseLevel !== "embedded") return baseLevel;
|
|
7247
|
-
if (feature === "commands" &&
|
|
7248
|
-
return shouldConvertCommandsToSkills(config,
|
|
7597
|
+
if (feature === "commands" && target12 === "codex-cli") {
|
|
7598
|
+
return shouldConvertCommandsToSkills(config, target12) ? "embedded" : "none";
|
|
7249
7599
|
}
|
|
7250
|
-
if (feature === "agents" && (
|
|
7251
|
-
return shouldConvertAgentsToSkills(config,
|
|
7600
|
+
if (feature === "agents" && (target12 === "cline" || target12 === "windsurf")) {
|
|
7601
|
+
return shouldConvertAgentsToSkills(config, target12) ? "embedded" : "none";
|
|
7252
7602
|
}
|
|
7253
7603
|
return baseLevel;
|
|
7254
7604
|
}
|
|
7255
|
-
function resolveTargetFeatureGenerator(
|
|
7256
|
-
const generators = getBuiltinTargetDefinition(
|
|
7605
|
+
function resolveTargetFeatureGenerator(target12, feature, config) {
|
|
7606
|
+
const generators = getBuiltinTargetDefinition(target12)?.generators;
|
|
7257
7607
|
if (!generators) return void 0;
|
|
7258
7608
|
switch (feature) {
|
|
7259
7609
|
case "rules":
|
|
7260
7610
|
return generators.generateRules;
|
|
7261
7611
|
case "commands":
|
|
7262
|
-
if (
|
|
7612
|
+
if (target12 === "codex-cli" && config && !shouldConvertCommandsToSkills(config, target12)) {
|
|
7263
7613
|
return void 0;
|
|
7264
7614
|
}
|
|
7265
7615
|
return generators.generateWorkflows ?? generators.generateCommands;
|
|
7266
7616
|
case "agents":
|
|
7267
|
-
if (config && (
|
|
7617
|
+
if (config && (target12 === "cline" || target12 === "windsurf") && !shouldConvertAgentsToSkills(config, target12)) {
|
|
7268
7618
|
return void 0;
|
|
7269
7619
|
}
|
|
7270
7620
|
return generators.generateAgents;
|
|
@@ -7284,9 +7634,9 @@ function resolveTargetFeatureGenerator(target11, feature, config) {
|
|
|
7284
7634
|
}
|
|
7285
7635
|
|
|
7286
7636
|
// src/core/reference/import-map.ts
|
|
7287
|
-
async function buildImportReferenceMap(
|
|
7637
|
+
async function buildImportReferenceMap(target12, projectRoot) {
|
|
7288
7638
|
const refs = /* @__PURE__ */ new Map();
|
|
7289
|
-
const def = getBuiltinTargetDefinition(
|
|
7639
|
+
const def = getBuiltinTargetDefinition(target12);
|
|
7290
7640
|
if (def) {
|
|
7291
7641
|
await def.buildImportPaths(refs, projectRoot);
|
|
7292
7642
|
}
|
|
@@ -7342,7 +7692,8 @@ var ROOT_RELATIVE_PREFIXES = [
|
|
|
7342
7692
|
".clinerules/",
|
|
7343
7693
|
".cline/",
|
|
7344
7694
|
".agents/",
|
|
7345
|
-
".windsurf/"
|
|
7695
|
+
".windsurf/",
|
|
7696
|
+
".roo/"
|
|
7346
7697
|
];
|
|
7347
7698
|
var NON_REWRITABLE_BARE_FILES = /* @__PURE__ */ new Set([
|
|
7348
7699
|
"AGENTS.md",
|
|
@@ -7359,7 +7710,7 @@ var EXTERNAL_REF_PATTERNS = [
|
|
|
7359
7710
|
/\/\/[A-Za-z0-9][\w.-]*\.[A-Za-z]{2,}[^\s<>()\]]*/g
|
|
7360
7711
|
];
|
|
7361
7712
|
var FENCED_CODE_BLOCK = /^(?:```|~~~)[^\n]*\n[\s\S]*?^(?:```|~~~)/gm;
|
|
7362
|
-
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[\\/]|(?:[A-Za-z0-9._-]+[\\/])+|[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+)[A-Za-z0-9._@%+~:\\/-]*/g;
|
|
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;
|
|
7363
7714
|
var LINE_NUMBER_SUFFIX = /(?::(\d+)){1,2}$/;
|
|
7364
7715
|
function resolveProjectPath(token, projectRoot, sourceFile) {
|
|
7365
7716
|
const api = pathApi(projectRoot);
|
|
@@ -7506,7 +7857,8 @@ var IMPORT_REFERENCE_TARGETS = [
|
|
|
7506
7857
|
"gemini-cli",
|
|
7507
7858
|
"cline",
|
|
7508
7859
|
"codex-cli",
|
|
7509
|
-
"windsurf"
|
|
7860
|
+
"windsurf",
|
|
7861
|
+
"roo-code"
|
|
7510
7862
|
];
|
|
7511
7863
|
function pathVariants(path) {
|
|
7512
7864
|
const variants = [normalizePath(path)];
|
|
@@ -7521,9 +7873,9 @@ function pathVariants(path) {
|
|
|
7521
7873
|
}
|
|
7522
7874
|
return variants;
|
|
7523
7875
|
}
|
|
7524
|
-
async function createImportReferenceNormalizer(
|
|
7876
|
+
async function createImportReferenceNormalizer(target12, projectRoot) {
|
|
7525
7877
|
const refs = /* @__PURE__ */ new Map();
|
|
7526
|
-
const targets = Array.from(/* @__PURE__ */ new Set([
|
|
7878
|
+
const targets = Array.from(/* @__PURE__ */ new Set([target12, ...IMPORT_REFERENCE_TARGETS]));
|
|
7527
7879
|
for (const candidate of targets) {
|
|
7528
7880
|
const candidateRefs = await buildImportReferenceMap(candidate, projectRoot);
|
|
7529
7881
|
for (const [targetPath, canonicalPath] of candidateRefs.entries()) {
|
|
@@ -7532,8 +7884,8 @@ async function createImportReferenceNormalizer(target11, projectRoot) {
|
|
|
7532
7884
|
}
|
|
7533
7885
|
const artifactMap = /* @__PURE__ */ new Map();
|
|
7534
7886
|
for (const [targetPath, canonicalPath] of refs.entries()) {
|
|
7535
|
-
const canonicalAbsPath = normalizePath(
|
|
7536
|
-
for (const variant of pathVariants(
|
|
7887
|
+
const canonicalAbsPath = normalizePath(join38(projectRoot, canonicalPath));
|
|
7888
|
+
for (const variant of pathVariants(join38(projectRoot, targetPath))) {
|
|
7537
7889
|
artifactMap.set(variant, canonicalAbsPath);
|
|
7538
7890
|
}
|
|
7539
7891
|
}
|
|
@@ -7548,9 +7900,9 @@ async function createImportReferenceNormalizer(target11, projectRoot) {
|
|
|
7548
7900
|
}
|
|
7549
7901
|
|
|
7550
7902
|
// src/targets/claude-code/importer-mappers.ts
|
|
7551
|
-
import { join as
|
|
7903
|
+
import { join as join39 } from "path";
|
|
7552
7904
|
async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
7553
|
-
const destPath =
|
|
7905
|
+
const destPath = join39(destDir, relativePath);
|
|
7554
7906
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7555
7907
|
return {
|
|
7556
7908
|
destPath,
|
|
@@ -7564,7 +7916,7 @@ async function mapClaudeRuleFile(relativePath, destDir, normalizeTo) {
|
|
|
7564
7916
|
};
|
|
7565
7917
|
}
|
|
7566
7918
|
async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo) {
|
|
7567
|
-
const destPath =
|
|
7919
|
+
const destPath = join39(destDir, relativePath);
|
|
7568
7920
|
const { frontmatter, body } = parseFrontmatter(normalizeTo(destPath));
|
|
7569
7921
|
const basePath = feature === "commands" ? CLAUDE_CANONICAL_COMMANDS_DIR : CLAUDE_CANONICAL_AGENTS_DIR;
|
|
7570
7922
|
return {
|
|
@@ -7588,7 +7940,7 @@ async function mapClaudeMarkdownFile(relativePath, destDir, feature, normalizeTo
|
|
|
7588
7940
|
}
|
|
7589
7941
|
|
|
7590
7942
|
// src/targets/claude-code/settings-helpers.ts
|
|
7591
|
-
import { join as
|
|
7943
|
+
import { join as join40, dirname as dirname17 } from "path";
|
|
7592
7944
|
import { stringify as yamlStringify5 } from "yaml";
|
|
7593
7945
|
function claudeHooksToCanonical(hooks) {
|
|
7594
7946
|
const result = {};
|
|
@@ -7615,7 +7967,7 @@ function claudeHooksToCanonical(hooks) {
|
|
|
7615
7967
|
return result;
|
|
7616
7968
|
}
|
|
7617
7969
|
async function importMcpJson(projectRoot, results) {
|
|
7618
|
-
const mcpPath =
|
|
7970
|
+
const mcpPath = join40(projectRoot, CLAUDE_MCP_JSON);
|
|
7619
7971
|
const content = await readFileSafe(mcpPath);
|
|
7620
7972
|
if (content === null) return;
|
|
7621
7973
|
let parsed;
|
|
@@ -7626,7 +7978,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7626
7978
|
}
|
|
7627
7979
|
if (parsed.mcpServers && typeof parsed.mcpServers === "object") {
|
|
7628
7980
|
const mcpContent = JSON.stringify({ mcpServers: parsed.mcpServers }, null, 2);
|
|
7629
|
-
const destPath =
|
|
7981
|
+
const destPath = join40(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
7630
7982
|
await mkdirp(dirname17(destPath));
|
|
7631
7983
|
await writeFileAtomic(destPath, mcpContent);
|
|
7632
7984
|
results.push({
|
|
@@ -7638,7 +7990,7 @@ async function importMcpJson(projectRoot, results) {
|
|
|
7638
7990
|
}
|
|
7639
7991
|
}
|
|
7640
7992
|
async function importSettings2(projectRoot, results) {
|
|
7641
|
-
const settingsPath =
|
|
7993
|
+
const settingsPath = join40(projectRoot, CLAUDE_SETTINGS);
|
|
7642
7994
|
const content = await readFileSafe(settingsPath);
|
|
7643
7995
|
if (!content) return;
|
|
7644
7996
|
let settings;
|
|
@@ -7650,7 +8002,7 @@ async function importSettings2(projectRoot, results) {
|
|
|
7650
8002
|
const alreadyImportedMcp = results.some((r) => r.feature === "mcp");
|
|
7651
8003
|
if (!alreadyImportedMcp && settings.mcpServers && typeof settings.mcpServers === "object") {
|
|
7652
8004
|
const mcpContent = JSON.stringify({ mcpServers: settings.mcpServers }, null, 2);
|
|
7653
|
-
const destPath =
|
|
8005
|
+
const destPath = join40(projectRoot, CLAUDE_CANONICAL_MCP);
|
|
7654
8006
|
await mkdirp(dirname17(destPath));
|
|
7655
8007
|
await writeFileAtomic(destPath, mcpContent);
|
|
7656
8008
|
results.push({
|
|
@@ -7667,7 +8019,7 @@ async function importSettings2(projectRoot, results) {
|
|
|
7667
8019
|
const deny = Array.isArray(perms.deny) ? perms.deny.filter((s) => typeof s === "string") : [];
|
|
7668
8020
|
if (allow.length > 0 || deny.length > 0) {
|
|
7669
8021
|
const permContent = yamlStringify5({ allow, deny });
|
|
7670
|
-
const destPath =
|
|
8022
|
+
const destPath = join40(projectRoot, CLAUDE_CANONICAL_PERMISSIONS);
|
|
7671
8023
|
await mkdirp(dirname17(destPath));
|
|
7672
8024
|
await writeFileAtomic(destPath, permContent);
|
|
7673
8025
|
results.push({
|
|
@@ -7683,7 +8035,7 @@ async function importSettings2(projectRoot, results) {
|
|
|
7683
8035
|
const canonicalHooks = claudeHooksToCanonical(rawHooks);
|
|
7684
8036
|
if (Object.keys(canonicalHooks).length > 0) {
|
|
7685
8037
|
const hooksContent = yamlStringify5(canonicalHooks);
|
|
7686
|
-
const destPath =
|
|
8038
|
+
const destPath = join40(projectRoot, CLAUDE_CANONICAL_HOOKS);
|
|
7687
8039
|
await mkdirp(dirname17(destPath));
|
|
7688
8040
|
await writeFileAtomic(destPath, hooksContent);
|
|
7689
8041
|
results.push({
|
|
@@ -7701,25 +8053,25 @@ async function importFromClaudeCode(projectRoot) {
|
|
|
7701
8053
|
const results = [];
|
|
7702
8054
|
const normalize = await createImportReferenceNormalizer("claude-code", projectRoot);
|
|
7703
8055
|
await importRules5(projectRoot, results, normalize);
|
|
7704
|
-
await
|
|
8056
|
+
await importCommands6(projectRoot, results, normalize);
|
|
7705
8057
|
await importAgents5(projectRoot, results, normalize);
|
|
7706
8058
|
await importSkills5(projectRoot, results, normalize);
|
|
7707
8059
|
await importMcpJson(projectRoot, results);
|
|
7708
8060
|
await importSettings2(projectRoot, results);
|
|
7709
|
-
await
|
|
8061
|
+
await importIgnore4(projectRoot, results);
|
|
7710
8062
|
return results;
|
|
7711
8063
|
}
|
|
7712
8064
|
async function importRules5(projectRoot, results, normalize) {
|
|
7713
|
-
const destDir =
|
|
7714
|
-
const primaryClaudePath =
|
|
8065
|
+
const destDir = join41(projectRoot, CLAUDE_CANONICAL_RULES_DIR);
|
|
8066
|
+
const primaryClaudePath = join41(projectRoot, CLAUDE_ROOT);
|
|
7715
8067
|
const primaryContent = await readFileSafe(primaryClaudePath);
|
|
7716
|
-
const legacyClaudePath =
|
|
8068
|
+
const legacyClaudePath = join41(projectRoot, CLAUDE_LEGACY_ROOT);
|
|
7717
8069
|
const legacyContent = primaryContent === null ? await readFileSafe(legacyClaudePath) : null;
|
|
7718
8070
|
const claudeContent = primaryContent ?? legacyContent;
|
|
7719
8071
|
const claudePath = primaryContent !== null ? primaryClaudePath : legacyClaudePath;
|
|
7720
8072
|
if (claudeContent !== null) {
|
|
7721
8073
|
await mkdirp(destDir);
|
|
7722
|
-
const destPath =
|
|
8074
|
+
const destPath = join41(destDir, "_root.md");
|
|
7723
8075
|
const { frontmatter, body } = parseFrontmatter(normalize(claudeContent, claudePath, destPath));
|
|
7724
8076
|
const hasRoot = frontmatter.root === true;
|
|
7725
8077
|
const outFm = hasRoot ? frontmatter : { ...frontmatter, root: true };
|
|
@@ -7732,7 +8084,7 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
7732
8084
|
feature: "rules"
|
|
7733
8085
|
});
|
|
7734
8086
|
}
|
|
7735
|
-
const rulesDir =
|
|
8087
|
+
const rulesDir = join41(projectRoot, CLAUDE_RULES_DIR);
|
|
7736
8088
|
results.push(
|
|
7737
8089
|
...await importFileDirectory({
|
|
7738
8090
|
srcDir: rulesDir,
|
|
@@ -7744,9 +8096,9 @@ async function importRules5(projectRoot, results, normalize) {
|
|
|
7744
8096
|
})
|
|
7745
8097
|
);
|
|
7746
8098
|
}
|
|
7747
|
-
async function
|
|
7748
|
-
const destDir =
|
|
7749
|
-
const commandsDir =
|
|
8099
|
+
async function importCommands6(projectRoot, results, normalize) {
|
|
8100
|
+
const destDir = join41(projectRoot, CLAUDE_CANONICAL_COMMANDS_DIR);
|
|
8101
|
+
const commandsDir = join41(projectRoot, CLAUDE_COMMANDS_DIR);
|
|
7750
8102
|
results.push(
|
|
7751
8103
|
...await importFileDirectory({
|
|
7752
8104
|
srcDir: commandsDir,
|
|
@@ -7759,8 +8111,8 @@ async function importCommands5(projectRoot, results, normalize) {
|
|
|
7759
8111
|
);
|
|
7760
8112
|
}
|
|
7761
8113
|
async function importAgents5(projectRoot, results, normalize) {
|
|
7762
|
-
const destDir =
|
|
7763
|
-
const agentsDir =
|
|
8114
|
+
const destDir = join41(projectRoot, CLAUDE_CANONICAL_AGENTS_DIR);
|
|
8115
|
+
const agentsDir = join41(projectRoot, CLAUDE_AGENTS_DIR);
|
|
7764
8116
|
results.push(
|
|
7765
8117
|
...await importFileDirectory({
|
|
7766
8118
|
srcDir: agentsDir,
|
|
@@ -7773,20 +8125,20 @@ async function importAgents5(projectRoot, results, normalize) {
|
|
|
7773
8125
|
);
|
|
7774
8126
|
}
|
|
7775
8127
|
async function importSkills5(projectRoot, results, normalize) {
|
|
7776
|
-
const skillsBaseDir =
|
|
7777
|
-
const destBase =
|
|
8128
|
+
const skillsBaseDir = join41(projectRoot, CLAUDE_SKILLS_DIR);
|
|
8129
|
+
const destBase = join41(projectRoot, CLAUDE_CANONICAL_SKILLS_DIR);
|
|
7778
8130
|
const allFiles = await readDirRecursive(skillsBaseDir);
|
|
7779
8131
|
const skillMdFiles = allFiles.filter((f) => f.endsWith("SKILL.md"));
|
|
7780
8132
|
for (const skillMdPath of skillMdFiles) {
|
|
7781
8133
|
const skillDir = dirname18(skillMdPath);
|
|
7782
|
-
const skillName =
|
|
7783
|
-
const destSkillDir =
|
|
8134
|
+
const skillName = basename26(skillDir);
|
|
8135
|
+
const destSkillDir = join41(destBase, skillName);
|
|
7784
8136
|
const skillFiles = await readDirRecursive(skillDir);
|
|
7785
8137
|
for (const filePath of skillFiles) {
|
|
7786
8138
|
const fileContent = await readFileSafe(filePath);
|
|
7787
8139
|
if (fileContent === null) continue;
|
|
7788
8140
|
const relPath = relative17(skillDir, filePath);
|
|
7789
|
-
const destPath =
|
|
8141
|
+
const destPath = join41(destSkillDir, relPath);
|
|
7790
8142
|
await mkdirp(dirname18(destPath));
|
|
7791
8143
|
const normalized = normalize(fileContent, filePath, destPath);
|
|
7792
8144
|
const parsed = relPath === "SKILL.md" ? parseFrontmatter(normalized) : null;
|
|
@@ -7808,11 +8160,11 @@ async function importSkills5(projectRoot, results, normalize) {
|
|
|
7808
8160
|
}
|
|
7809
8161
|
}
|
|
7810
8162
|
}
|
|
7811
|
-
async function
|
|
7812
|
-
const ignorePath =
|
|
8163
|
+
async function importIgnore4(projectRoot, results) {
|
|
8164
|
+
const ignorePath = join41(projectRoot, CLAUDE_IGNORE);
|
|
7813
8165
|
const content = await readFileSafe(ignorePath);
|
|
7814
8166
|
if (content === null) return;
|
|
7815
|
-
const destPath =
|
|
8167
|
+
const destPath = join41(projectRoot, CLAUDE_CANONICAL_IGNORE);
|
|
7816
8168
|
await mkdirp(dirname18(destPath));
|
|
7817
8169
|
await writeFileAtomic(destPath, content);
|
|
7818
8170
|
results.push({
|
|
@@ -7844,17 +8196,17 @@ async function importNativeToCanonical(repoPath, targetName) {
|
|
|
7844
8196
|
}
|
|
7845
8197
|
|
|
7846
8198
|
// src/canonical/load/skill-pack-load.ts
|
|
7847
|
-
import { join as
|
|
7848
|
-
import { readdir as
|
|
8199
|
+
import { join as join42 } from "path";
|
|
8200
|
+
import { readdir as readdir10 } from "fs/promises";
|
|
7849
8201
|
var SKILL = "SKILL.md";
|
|
7850
8202
|
async function isSkillPackLayout(root) {
|
|
7851
8203
|
if (!await exists(root)) return false;
|
|
7852
|
-
if (await exists(
|
|
8204
|
+
if (await exists(join42(root, SKILL))) return true;
|
|
7853
8205
|
try {
|
|
7854
|
-
const ents = await
|
|
8206
|
+
const ents = await readdir10(root, { withFileTypes: true });
|
|
7855
8207
|
for (const e of ents) {
|
|
7856
8208
|
if (!e.isDirectory() || e.name.startsWith(".")) continue;
|
|
7857
|
-
if (await exists(
|
|
8209
|
+
if (await exists(join42(root, e.name, SKILL))) return true;
|
|
7858
8210
|
}
|
|
7859
8211
|
} catch {
|
|
7860
8212
|
return false;
|
|
@@ -7863,7 +8215,7 @@ async function isSkillPackLayout(root) {
|
|
|
7863
8215
|
}
|
|
7864
8216
|
async function loadSkillsAtExtendPath(skillsRoot) {
|
|
7865
8217
|
if (!await exists(skillsRoot)) return [];
|
|
7866
|
-
if (await exists(
|
|
8218
|
+
if (await exists(join42(skillsRoot, SKILL))) {
|
|
7867
8219
|
const one = await parseSkillDirectory(skillsRoot);
|
|
7868
8220
|
return one ? [one] : [];
|
|
7869
8221
|
}
|
|
@@ -7871,7 +8223,7 @@ async function loadSkillsAtExtendPath(skillsRoot) {
|
|
|
7871
8223
|
}
|
|
7872
8224
|
|
|
7873
8225
|
// src/canonical/load/load-canonical-slice.ts
|
|
7874
|
-
import { basename as
|
|
8226
|
+
import { basename as basename27, dirname as dirname19, join as join43 } from "path";
|
|
7875
8227
|
import { stat as stat4 } from "fs/promises";
|
|
7876
8228
|
function emptyCanonical() {
|
|
7877
8229
|
return {
|
|
@@ -7902,8 +8254,8 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
7902
8254
|
);
|
|
7903
8255
|
}
|
|
7904
8256
|
const parent = dirname19(absolutePath);
|
|
7905
|
-
const parentBase =
|
|
7906
|
-
const fileBase =
|
|
8257
|
+
const parentBase = basename27(parent);
|
|
8258
|
+
const fileBase = basename27(absolutePath);
|
|
7907
8259
|
const slug = fileBase.replace(/\.md$/i, "");
|
|
7908
8260
|
if (parentBase === "rules") {
|
|
7909
8261
|
return { sliceRoot: parent, implicitPick: { rules: [slug] } };
|
|
@@ -7919,33 +8271,33 @@ async function normalizeSlicePath(absolutePath) {
|
|
|
7919
8271
|
);
|
|
7920
8272
|
}
|
|
7921
8273
|
async function parseRulesAt(sliceRoot) {
|
|
7922
|
-
const base =
|
|
8274
|
+
const base = basename27(sliceRoot);
|
|
7923
8275
|
if (base === "rules") {
|
|
7924
8276
|
return parseRules(sliceRoot);
|
|
7925
8277
|
}
|
|
7926
|
-
const nested =
|
|
8278
|
+
const nested = join43(sliceRoot, "rules");
|
|
7927
8279
|
if (await exists(nested)) {
|
|
7928
8280
|
return parseRules(nested);
|
|
7929
8281
|
}
|
|
7930
8282
|
return [];
|
|
7931
8283
|
}
|
|
7932
8284
|
async function parseCommandsAt(sliceRoot) {
|
|
7933
|
-
const base =
|
|
8285
|
+
const base = basename27(sliceRoot);
|
|
7934
8286
|
if (base === "commands") {
|
|
7935
8287
|
return parseCommands(sliceRoot);
|
|
7936
8288
|
}
|
|
7937
|
-
const nested =
|
|
8289
|
+
const nested = join43(sliceRoot, "commands");
|
|
7938
8290
|
if (await exists(nested)) {
|
|
7939
8291
|
return parseCommands(nested);
|
|
7940
8292
|
}
|
|
7941
8293
|
return [];
|
|
7942
8294
|
}
|
|
7943
8295
|
async function parseAgentsAt(sliceRoot) {
|
|
7944
|
-
const base =
|
|
8296
|
+
const base = basename27(sliceRoot);
|
|
7945
8297
|
if (base === "agents") {
|
|
7946
8298
|
return parseAgents(sliceRoot);
|
|
7947
8299
|
}
|
|
7948
|
-
const nested =
|
|
8300
|
+
const nested = join43(sliceRoot, "agents");
|
|
7949
8301
|
if (await exists(nested)) {
|
|
7950
8302
|
return parseAgents(nested);
|
|
7951
8303
|
}
|
|
@@ -7955,14 +8307,14 @@ async function loadSkillsForPartialSlice(sliceRoot) {
|
|
|
7955
8307
|
if (await isSkillPackLayout(sliceRoot)) {
|
|
7956
8308
|
return loadSkillsAtExtendPath(sliceRoot);
|
|
7957
8309
|
}
|
|
7958
|
-
const nestedSkills =
|
|
8310
|
+
const nestedSkills = join43(sliceRoot, "skills");
|
|
7959
8311
|
if (await isSkillPackLayout(nestedSkills)) {
|
|
7960
8312
|
return loadSkillsAtExtendPath(nestedSkills);
|
|
7961
8313
|
}
|
|
7962
8314
|
return [];
|
|
7963
8315
|
}
|
|
7964
8316
|
async function loadCanonicalSliceAtPath(sliceRoot) {
|
|
7965
|
-
const ab =
|
|
8317
|
+
const ab = join43(sliceRoot, ".agentsmesh");
|
|
7966
8318
|
if (await exists(ab)) {
|
|
7967
8319
|
return loadCanonicalFiles(sliceRoot);
|
|
7968
8320
|
}
|
|
@@ -7995,7 +8347,7 @@ function emptyCanonical2() {
|
|
|
7995
8347
|
async function loadCanonicalForExtend(ext) {
|
|
7996
8348
|
const base = ext.resolvedPath;
|
|
7997
8349
|
if (!ext.path) {
|
|
7998
|
-
const agentsmeshDir =
|
|
8350
|
+
const agentsmeshDir = join44(base, ".agentsmesh");
|
|
7999
8351
|
if (!await exists(agentsmeshDir)) {
|
|
8000
8352
|
if (await isSkillPackLayout(base)) {
|
|
8001
8353
|
const skills = await loadSkillsAtExtendPath(base);
|
|
@@ -8015,12 +8367,12 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8015
8367
|
}
|
|
8016
8368
|
return loadCanonicalFiles(base);
|
|
8017
8369
|
}
|
|
8018
|
-
const rawRoot =
|
|
8370
|
+
const rawRoot = join44(base, ext.path);
|
|
8019
8371
|
if (!await exists(rawRoot)) {
|
|
8020
8372
|
throw new Error(`Extend "${ext.name}": path does not exist: ${rawRoot}`);
|
|
8021
8373
|
}
|
|
8022
8374
|
if (ext.target) {
|
|
8023
|
-
const agentsmeshDir =
|
|
8375
|
+
const agentsmeshDir = join44(base, ".agentsmesh");
|
|
8024
8376
|
if (!await exists(agentsmeshDir)) {
|
|
8025
8377
|
logger.info(
|
|
8026
8378
|
`[agentsmesh] Extend "${ext.name}": path "${ext.path}" with target "${ext.target}" \u2014 importing at extend root, then loading canonical.`
|
|
@@ -8041,7 +8393,7 @@ Expected one of: .agentsmesh/, ${KNOWN_NATIVE_PATHS.join(", ")}.`
|
|
|
8041
8393
|
}
|
|
8042
8394
|
|
|
8043
8395
|
// src/canonical/extends/extend-pick.ts
|
|
8044
|
-
import { basename as
|
|
8396
|
+
import { basename as basename28 } from "path";
|
|
8045
8397
|
function applyExtendPick(canonical, features, pick, extendName) {
|
|
8046
8398
|
if (!pick) return canonical;
|
|
8047
8399
|
let next = { ...canonical };
|
|
@@ -8084,7 +8436,7 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8084
8436
|
if (pick.rules?.length && features.includes("rules")) {
|
|
8085
8437
|
const wanted = new Set(pick.rules);
|
|
8086
8438
|
const prev = next.rules;
|
|
8087
|
-
const stem = (src) =>
|
|
8439
|
+
const stem = (src) => basename28(src).replace(/\.md$/i, "");
|
|
8088
8440
|
next = {
|
|
8089
8441
|
...next,
|
|
8090
8442
|
rules: prev.filter((r) => wanted.has(stem(r.source)))
|
|
@@ -8101,11 +8453,11 @@ function applyExtendPick(canonical, features, pick, extendName) {
|
|
|
8101
8453
|
}
|
|
8102
8454
|
|
|
8103
8455
|
// src/canonical/load/pack-load.ts
|
|
8104
|
-
import { join as
|
|
8456
|
+
import { join as join46 } from "path";
|
|
8105
8457
|
|
|
8106
8458
|
// src/install/pack/pack-reader.ts
|
|
8107
|
-
import { join as
|
|
8108
|
-
import { readdir as
|
|
8459
|
+
import { join as join45 } from "path";
|
|
8460
|
+
import { readdir as readdir11 } from "fs/promises";
|
|
8109
8461
|
import { parse as parseYaml5 } from "yaml";
|
|
8110
8462
|
|
|
8111
8463
|
// src/install/pack/pack-schema.ts
|
|
@@ -8151,7 +8503,7 @@ function sameFeatures(a, b) {
|
|
|
8151
8503
|
return a.length === b.length && [...a].sort().every((feature, index) => feature === [...b].sort()[index]);
|
|
8152
8504
|
}
|
|
8153
8505
|
async function readPackMetadata(packDir) {
|
|
8154
|
-
const metaPath =
|
|
8506
|
+
const metaPath = join45(packDir, "pack.yaml");
|
|
8155
8507
|
const content = await readFileSafe(metaPath);
|
|
8156
8508
|
if (content === null) return null;
|
|
8157
8509
|
try {
|
|
@@ -8166,13 +8518,13 @@ async function findExistingPack(packsDir, source, scope) {
|
|
|
8166
8518
|
const requestedIdentity = sourceIdentity(source);
|
|
8167
8519
|
let entries;
|
|
8168
8520
|
try {
|
|
8169
|
-
entries = await
|
|
8521
|
+
entries = await readdir11(packsDir, { withFileTypes: true });
|
|
8170
8522
|
} catch {
|
|
8171
8523
|
return null;
|
|
8172
8524
|
}
|
|
8173
8525
|
for (const entry of entries) {
|
|
8174
8526
|
if (!entry.isDirectory()) continue;
|
|
8175
|
-
const packDir =
|
|
8527
|
+
const packDir = join45(packsDir, entry.name);
|
|
8176
8528
|
const meta = await readPackMetadata(packDir);
|
|
8177
8529
|
if (meta && sourceIdentity(meta.source) === requestedIdentity && meta.target === scope.target && meta.as === scope.as && sameFeatures(meta.features, scope.features)) {
|
|
8178
8530
|
return { meta, packDir, name: meta.name };
|
|
@@ -8184,14 +8536,14 @@ async function listPacks(packsDir) {
|
|
|
8184
8536
|
if (!await exists(packsDir)) return [];
|
|
8185
8537
|
let entries;
|
|
8186
8538
|
try {
|
|
8187
|
-
entries = await
|
|
8539
|
+
entries = await readdir11(packsDir, { withFileTypes: true });
|
|
8188
8540
|
} catch {
|
|
8189
8541
|
return [];
|
|
8190
8542
|
}
|
|
8191
8543
|
const result = [];
|
|
8192
8544
|
for (const entry of entries) {
|
|
8193
8545
|
if (!entry.isDirectory()) continue;
|
|
8194
|
-
const packDir =
|
|
8546
|
+
const packDir = join45(packsDir, entry.name);
|
|
8195
8547
|
const meta = await readPackMetadata(packDir);
|
|
8196
8548
|
if (meta) {
|
|
8197
8549
|
result.push({ meta, packDir, name: meta.name });
|
|
@@ -8215,19 +8567,19 @@ function emptyCanonical3() {
|
|
|
8215
8567
|
}
|
|
8216
8568
|
async function loadPackCanonical(packDir) {
|
|
8217
8569
|
const [rules, commands, agents, skills, mcp, permissions, hooks, ignore] = await Promise.all([
|
|
8218
|
-
parseRules(
|
|
8219
|
-
parseCommands(
|
|
8220
|
-
parseAgents(
|
|
8221
|
-
parseSkills(
|
|
8222
|
-
parseMcp(
|
|
8223
|
-
parsePermissions(
|
|
8224
|
-
parseHooks(
|
|
8225
|
-
parseIgnore(
|
|
8570
|
+
parseRules(join46(packDir, "rules")),
|
|
8571
|
+
parseCommands(join46(packDir, "commands")),
|
|
8572
|
+
parseAgents(join46(packDir, "agents")),
|
|
8573
|
+
parseSkills(join46(packDir, "skills")),
|
|
8574
|
+
parseMcp(join46(packDir, "mcp.json")),
|
|
8575
|
+
parsePermissions(join46(packDir, "permissions.yaml")),
|
|
8576
|
+
parseHooks(join46(packDir, "hooks.yaml")),
|
|
8577
|
+
parseIgnore(join46(packDir, "ignore"))
|
|
8226
8578
|
]);
|
|
8227
8579
|
return { ...emptyCanonical3(), rules, commands, agents, skills, mcp, permissions, hooks, ignore };
|
|
8228
8580
|
}
|
|
8229
8581
|
async function loadPacksCanonical(abDir) {
|
|
8230
|
-
const packsDir =
|
|
8582
|
+
const packsDir = join46(abDir, "packs");
|
|
8231
8583
|
const packs = await listPacks(packsDir);
|
|
8232
8584
|
let merged = emptyCanonical3();
|
|
8233
8585
|
for (const { meta, packDir } of packs) {
|
|
@@ -8289,7 +8641,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8289
8641
|
const picked = applyExtendPick(filtered, ext.features, ext.pick, ext.name);
|
|
8290
8642
|
merged = mergeCanonicalFiles(merged, picked);
|
|
8291
8643
|
}
|
|
8292
|
-
const packsCanonical = await loadPacksCanonical(
|
|
8644
|
+
const packsCanonical = await loadPacksCanonical(join47(configDir, ".agentsmesh"));
|
|
8293
8645
|
merged = mergeCanonicalFiles(merged, packsCanonical);
|
|
8294
8646
|
const localCanonical = await loadCanonicalFiles(configDir);
|
|
8295
8647
|
merged = mergeCanonicalFiles(merged, localCanonical);
|
|
@@ -8298,7 +8650,7 @@ async function loadCanonicalWithExtends(config, configDir, options = {}) {
|
|
|
8298
8650
|
|
|
8299
8651
|
// src/config/core/lock.ts
|
|
8300
8652
|
import { parse as parseYaml6, stringify as stringifyYaml3 } from "yaml";
|
|
8301
|
-
import { join as
|
|
8653
|
+
import { join as join48, relative as relative18 } from "path";
|
|
8302
8654
|
|
|
8303
8655
|
// src/utils/crypto/hash.ts
|
|
8304
8656
|
import { createHash } from "crypto";
|
|
@@ -8345,7 +8697,7 @@ var FEATURE_PATTERNS = {
|
|
|
8345
8697
|
ignore: (path) => path === "ignore"
|
|
8346
8698
|
};
|
|
8347
8699
|
async function readLock(abDir) {
|
|
8348
|
-
const lockPath =
|
|
8700
|
+
const lockPath = join48(abDir, LOCK_FILENAME);
|
|
8349
8701
|
const content = await readFileSafe(lockPath);
|
|
8350
8702
|
if (content === null) return null;
|
|
8351
8703
|
try {
|
|
@@ -8364,7 +8716,7 @@ async function readLock(abDir) {
|
|
|
8364
8716
|
}
|
|
8365
8717
|
}
|
|
8366
8718
|
async function writeLock(abDir, lock) {
|
|
8367
|
-
const lockPath =
|
|
8719
|
+
const lockPath = join48(abDir, LOCK_FILENAME);
|
|
8368
8720
|
const raw = {
|
|
8369
8721
|
generated_at: lock.generatedAt,
|
|
8370
8722
|
generated_by: lock.generatedBy,
|
|
@@ -8418,7 +8770,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8418
8770
|
result[ext.name] = ext.version;
|
|
8419
8771
|
continue;
|
|
8420
8772
|
}
|
|
8421
|
-
const abDir =
|
|
8773
|
+
const abDir = join48(ext.resolvedPath, ".agentsmesh");
|
|
8422
8774
|
const checksums = await buildChecksums(abDir);
|
|
8423
8775
|
const fingerprint = Object.keys(checksums).sort().map((p) => `${p}:${checksums[p]}`).join("\n");
|
|
8424
8776
|
const h = hashContent(fingerprint);
|
|
@@ -8429,7 +8781,7 @@ async function buildExtendChecksums(resolvedExtends) {
|
|
|
8429
8781
|
}
|
|
8430
8782
|
|
|
8431
8783
|
// src/core/reference/map.ts
|
|
8432
|
-
import { basename as
|
|
8784
|
+
import { basename as basename30 } from "path";
|
|
8433
8785
|
|
|
8434
8786
|
// src/core/reference/map-directories.ts
|
|
8435
8787
|
import { posix as posix2 } from "path";
|
|
@@ -8448,29 +8800,29 @@ function addSkillDirectoryMappings(refs, canonicalPath, targetPath) {
|
|
|
8448
8800
|
}
|
|
8449
8801
|
|
|
8450
8802
|
// src/core/reference/map-targets.ts
|
|
8451
|
-
import { basename as
|
|
8803
|
+
import { basename as basename29 } from "path";
|
|
8452
8804
|
var SKILL_DIRS = Object.fromEntries(
|
|
8453
|
-
TARGET_IDS.map((
|
|
8805
|
+
TARGET_IDS.map((target12) => [target12, getTargetSkillDir(target12)]).filter(
|
|
8454
8806
|
(entry) => typeof entry[1] === "string"
|
|
8455
8807
|
)
|
|
8456
8808
|
);
|
|
8457
|
-
function ruleTargetPath(
|
|
8458
|
-
const def = getBuiltinTargetDefinition(
|
|
8809
|
+
function ruleTargetPath(target12, rule) {
|
|
8810
|
+
const def = getBuiltinTargetDefinition(target12);
|
|
8459
8811
|
if (!def) return null;
|
|
8460
8812
|
if (rule.root) {
|
|
8461
8813
|
return def.generators.primaryRootInstructionPath ?? null;
|
|
8462
8814
|
}
|
|
8463
|
-
if (rule.targets.length > 0 && !rule.targets.includes(
|
|
8464
|
-
const slug =
|
|
8815
|
+
if (rule.targets.length > 0 && !rule.targets.includes(target12)) return null;
|
|
8816
|
+
const slug = basename29(rule.source, ".md");
|
|
8465
8817
|
return def.paths.rulePath(slug, rule);
|
|
8466
8818
|
}
|
|
8467
|
-
function commandTargetPath(
|
|
8468
|
-
const def = getBuiltinTargetDefinition(
|
|
8819
|
+
function commandTargetPath(target12, name, config) {
|
|
8820
|
+
const def = getBuiltinTargetDefinition(target12);
|
|
8469
8821
|
if (!def) return null;
|
|
8470
8822
|
return def.paths.commandPath(name, config);
|
|
8471
8823
|
}
|
|
8472
|
-
function agentTargetPath(
|
|
8473
|
-
const def = getBuiltinTargetDefinition(
|
|
8824
|
+
function agentTargetPath(target12, name, config) {
|
|
8825
|
+
const def = getBuiltinTargetDefinition(target12);
|
|
8474
8826
|
if (!def) return null;
|
|
8475
8827
|
return def.paths.agentPath(name, config);
|
|
8476
8828
|
}
|
|
@@ -8480,21 +8832,21 @@ function addDirectoryMapping3(refs, from, to) {
|
|
|
8480
8832
|
refs.set(from, to);
|
|
8481
8833
|
refs.set(`${from}/`, `${to}/`);
|
|
8482
8834
|
}
|
|
8483
|
-
function buildReferenceMap(
|
|
8835
|
+
function buildReferenceMap(target12, canonical, config) {
|
|
8484
8836
|
const refs = /* @__PURE__ */ new Map();
|
|
8485
8837
|
for (const rule of canonical.rules) {
|
|
8486
|
-
const path = ruleTargetPath(
|
|
8487
|
-
if (path) refs.set(`.agentsmesh/rules/${
|
|
8838
|
+
const path = ruleTargetPath(target12, rule);
|
|
8839
|
+
if (path) refs.set(`.agentsmesh/rules/${basename30(rule.source)}`, path);
|
|
8488
8840
|
}
|
|
8489
8841
|
for (const command of canonical.commands) {
|
|
8490
|
-
const path = commandTargetPath(
|
|
8842
|
+
const path = commandTargetPath(target12, command.name, config);
|
|
8491
8843
|
if (path) refs.set(`.agentsmesh/commands/${command.name}.md`, path);
|
|
8492
8844
|
}
|
|
8493
8845
|
for (const agent of canonical.agents) {
|
|
8494
|
-
const path = agentTargetPath(
|
|
8846
|
+
const path = agentTargetPath(target12, agent.name, config);
|
|
8495
8847
|
if (path) refs.set(`.agentsmesh/agents/${agent.name}.md`, path);
|
|
8496
8848
|
}
|
|
8497
|
-
const skillDir = SKILL_DIRS[
|
|
8849
|
+
const skillDir = SKILL_DIRS[target12];
|
|
8498
8850
|
if (!skillDir) return refs;
|
|
8499
8851
|
for (const skill of canonical.skills) {
|
|
8500
8852
|
addDirectoryMapping3(refs, `.agentsmesh/skills/${skill.name}`, `${skillDir}/${skill.name}`);
|
|
@@ -8530,14 +8882,14 @@ function isGeminiAgents(result) {
|
|
|
8530
8882
|
function isCompatibilityAgents(result) {
|
|
8531
8883
|
return isCursorAgents(result) || isGeminiAgents(result);
|
|
8532
8884
|
}
|
|
8533
|
-
function reverseReferenceMap(
|
|
8534
|
-
const cached = cache.get(
|
|
8885
|
+
function reverseReferenceMap(target12, canonical, config, cache) {
|
|
8886
|
+
const cached = cache.get(target12);
|
|
8535
8887
|
if (cached) return cached;
|
|
8536
8888
|
const reversed = /* @__PURE__ */ new Map();
|
|
8537
|
-
for (const [canonicalPath, targetPath] of buildReferenceMap(
|
|
8889
|
+
for (const [canonicalPath, targetPath] of buildReferenceMap(target12, canonical, config)) {
|
|
8538
8890
|
if (!reversed.has(targetPath)) reversed.set(targetPath, canonicalPath);
|
|
8539
8891
|
}
|
|
8540
|
-
cache.set(
|
|
8892
|
+
cache.set(target12, reversed);
|
|
8541
8893
|
return reversed;
|
|
8542
8894
|
}
|
|
8543
8895
|
function normalizeContent(content, refs) {
|
|
@@ -8569,11 +8921,11 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8569
8921
|
return results.filter((result) => {
|
|
8570
8922
|
if (isCursorAgents(result)) {
|
|
8571
8923
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8572
|
-
if (targets && [...targets].some((
|
|
8924
|
+
if (targets && [...targets].some((target12) => target12 !== "cursor")) return false;
|
|
8573
8925
|
}
|
|
8574
8926
|
if (isGeminiAgents(result)) {
|
|
8575
8927
|
const targets = overlapTargetsByPath.get(result.path);
|
|
8576
|
-
if (targets && [...targets].some((
|
|
8928
|
+
if (targets && [...targets].some((target12) => target12 !== "cursor" && target12 !== "gemini-cli")) {
|
|
8577
8929
|
return false;
|
|
8578
8930
|
}
|
|
8579
8931
|
}
|
|
@@ -8591,10 +8943,10 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
8591
8943
|
|
|
8592
8944
|
// src/core/reference/rewriter.ts
|
|
8593
8945
|
import { existsSync as existsSync3 } from "fs";
|
|
8594
|
-
import { dirname as dirname21, join as
|
|
8946
|
+
import { dirname as dirname21, join as join50 } from "path";
|
|
8595
8947
|
|
|
8596
8948
|
// src/core/reference/output-source-map.ts
|
|
8597
|
-
import { dirname as dirname20, join as
|
|
8949
|
+
import { dirname as dirname20, join as join49, normalize as normalizePath2 } from "path";
|
|
8598
8950
|
function canonicalRulePath(rule) {
|
|
8599
8951
|
return `.agentsmesh/rules/${rule.source.split("/").pop()}`;
|
|
8600
8952
|
}
|
|
@@ -8617,17 +8969,17 @@ function copilotInstructionsPath(rule) {
|
|
|
8617
8969
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
8618
8970
|
return `.github/instructions/${slug}.instructions.md`;
|
|
8619
8971
|
}
|
|
8620
|
-
function ruleOutputPaths(
|
|
8972
|
+
function ruleOutputPaths(target12, rule, refs) {
|
|
8621
8973
|
const paths = [];
|
|
8622
8974
|
const targetPath = refs.get(canonicalRulePath(rule));
|
|
8623
8975
|
if (targetPath) paths.push(targetPath);
|
|
8624
|
-
if (
|
|
8976
|
+
if (target12 === "copilot" && !rule.root && rule.globs.length > 0) {
|
|
8625
8977
|
paths.push(copilotInstructionsPath(rule));
|
|
8626
8978
|
}
|
|
8627
|
-
if ((
|
|
8979
|
+
if ((target12 === "cline" || target12 === "cursor") && rule.root) {
|
|
8628
8980
|
paths.push("AGENTS.md");
|
|
8629
8981
|
}
|
|
8630
|
-
if (
|
|
8982
|
+
if (target12 === "windsurf") {
|
|
8631
8983
|
if (rule.root) {
|
|
8632
8984
|
paths.push("AGENTS.md");
|
|
8633
8985
|
} else {
|
|
@@ -8635,10 +8987,10 @@ function ruleOutputPaths(target11, rule, refs) {
|
|
|
8635
8987
|
if (dir) paths.push(`${dir}/AGENTS.md`);
|
|
8636
8988
|
}
|
|
8637
8989
|
}
|
|
8638
|
-
if (
|
|
8990
|
+
if (target12 === "gemini-cli") {
|
|
8639
8991
|
paths.push(GEMINI_COMPAT_AGENTS);
|
|
8640
8992
|
}
|
|
8641
|
-
if (
|
|
8993
|
+
if (target12 === "codex-cli") {
|
|
8642
8994
|
if (!rule.root && rule.codexEmit === "execution") {
|
|
8643
8995
|
const slug = rule.source.split("/").pop().replace(/\.md$/, "");
|
|
8644
8996
|
paths.push(`${CODEX_RULES_DIR}/${slug}.rules`);
|
|
@@ -8646,46 +8998,46 @@ function ruleOutputPaths(target11, rule, refs) {
|
|
|
8646
8998
|
}
|
|
8647
8999
|
return paths;
|
|
8648
9000
|
}
|
|
8649
|
-
function addPackSkillPaths(refs,
|
|
8650
|
-
const skillDir = SKILL_DIRS[
|
|
9001
|
+
function addPackSkillPaths(refs, target12, canonical, projectRoot) {
|
|
9002
|
+
const skillDir = SKILL_DIRS[target12];
|
|
8651
9003
|
if (!skillDir) return;
|
|
8652
|
-
const packsPrefix =
|
|
9004
|
+
const packsPrefix = join49(projectRoot, ".agentsmesh", "packs");
|
|
8653
9005
|
for (const skill of canonical.skills) {
|
|
8654
9006
|
const skillSourceDir = dirname20(skill.source);
|
|
8655
9007
|
if (!skillSourceDir.startsWith(packsPrefix)) continue;
|
|
8656
|
-
const targetSkillDir = normalizePath2(
|
|
9008
|
+
const targetSkillDir = normalizePath2(join49(projectRoot, skillDir, skill.name));
|
|
8657
9009
|
refs.set(normalizePath2(skillSourceDir), targetSkillDir);
|
|
8658
|
-
refs.set(normalizePath2(skill.source), normalizePath2(
|
|
9010
|
+
refs.set(normalizePath2(skill.source), normalizePath2(join49(targetSkillDir, "SKILL.md")));
|
|
8659
9011
|
for (const file of skill.supportingFiles) {
|
|
8660
|
-
const targetFilePath = normalizePath2(
|
|
9012
|
+
const targetFilePath = normalizePath2(join49(targetSkillDir, file.relativePath));
|
|
8661
9013
|
refs.set(normalizePath2(file.absolutePath), targetFilePath);
|
|
8662
9014
|
}
|
|
8663
9015
|
}
|
|
8664
9016
|
}
|
|
8665
|
-
function buildArtifactPathMap(
|
|
9017
|
+
function buildArtifactPathMap(target12, canonical, config, projectRoot, destinationPath) {
|
|
8666
9018
|
const refs = new Map(
|
|
8667
|
-
[...buildReferenceMap(
|
|
8668
|
-
normalizePath2(
|
|
8669
|
-
normalizePath2(
|
|
9019
|
+
[...buildReferenceMap(target12, canonical, config)].map(([canonicalPath, targetPath]) => [
|
|
9020
|
+
normalizePath2(join49(projectRoot, canonicalPath)),
|
|
9021
|
+
normalizePath2(join49(projectRoot, targetPath))
|
|
8670
9022
|
])
|
|
8671
9023
|
);
|
|
8672
|
-
if (
|
|
9024
|
+
if (target12 === "copilot" && destinationPath?.startsWith(".github/instructions/")) {
|
|
8673
9025
|
for (const rule of canonical.rules) {
|
|
8674
9026
|
if (rule.root || rule.globs.length === 0) continue;
|
|
8675
9027
|
refs.set(
|
|
8676
|
-
normalizePath2(
|
|
8677
|
-
normalizePath2(
|
|
9028
|
+
normalizePath2(join49(projectRoot, canonicalRulePath(rule))),
|
|
9029
|
+
normalizePath2(join49(projectRoot, copilotInstructionsPath(rule)))
|
|
8678
9030
|
);
|
|
8679
9031
|
}
|
|
8680
9032
|
}
|
|
8681
|
-
addPackSkillPaths(refs,
|
|
9033
|
+
addPackSkillPaths(refs, target12, canonical, projectRoot);
|
|
8682
9034
|
return refs;
|
|
8683
9035
|
}
|
|
8684
|
-
function buildOutputSourceMap(
|
|
8685
|
-
const refs = buildReferenceMap(
|
|
9036
|
+
function buildOutputSourceMap(target12, canonical, config) {
|
|
9037
|
+
const refs = buildReferenceMap(target12, canonical, config);
|
|
8686
9038
|
const sourceMap = /* @__PURE__ */ new Map();
|
|
8687
9039
|
for (const rule of canonical.rules) {
|
|
8688
|
-
for (const targetPath of ruleOutputPaths(
|
|
9040
|
+
for (const targetPath of ruleOutputPaths(target12, rule, refs)) {
|
|
8689
9041
|
sourceMap.set(targetPath, rule.source);
|
|
8690
9042
|
}
|
|
8691
9043
|
}
|
|
@@ -8713,7 +9065,7 @@ function buildOutputSourceMap(target11, canonical, config) {
|
|
|
8713
9065
|
function collectPlannedPaths(projectRoot, results) {
|
|
8714
9066
|
const planned = /* @__PURE__ */ new Set();
|
|
8715
9067
|
for (const result of results) {
|
|
8716
|
-
const absolutePath =
|
|
9068
|
+
const absolutePath = join50(projectRoot, result.path);
|
|
8717
9069
|
planned.add(absolutePath);
|
|
8718
9070
|
let current = dirname21(absolutePath);
|
|
8719
9071
|
while (current.startsWith(projectRoot) && !planned.has(current)) {
|
|
@@ -8755,7 +9107,7 @@ function rewriteGeneratedReferences(results, canonical, config, projectRoot) {
|
|
|
8755
9107
|
content: result.content,
|
|
8756
9108
|
projectRoot,
|
|
8757
9109
|
sourceFile,
|
|
8758
|
-
destinationFile:
|
|
9110
|
+
destinationFile: join50(projectRoot, result.path),
|
|
8759
9111
|
translatePath: (absolutePath) => artifactMap.get(absolutePath) ?? absolutePath,
|
|
8760
9112
|
pathExists: (absolutePath) => plannedPaths.has(absolutePath) || existsSync3(absolutePath)
|
|
8761
9113
|
});
|
|
@@ -8806,7 +9158,7 @@ function refreshResultStatus(result) {
|
|
|
8806
9158
|
}
|
|
8807
9159
|
|
|
8808
9160
|
// src/core/generate/feature-loop.ts
|
|
8809
|
-
import { join as
|
|
9161
|
+
import { join as join51 } from "path";
|
|
8810
9162
|
function computeStatus(existing, content) {
|
|
8811
9163
|
if (existing === null) return "created";
|
|
8812
9164
|
if (existing !== content) return "updated";
|
|
@@ -8814,13 +9166,13 @@ function computeStatus(existing, content) {
|
|
|
8814
9166
|
}
|
|
8815
9167
|
async function generateFeature(results, targets, canonical, projectRoot, enabled, getGen) {
|
|
8816
9168
|
if (!enabled) return;
|
|
8817
|
-
for (const
|
|
8818
|
-
const gen = getGen(
|
|
9169
|
+
for (const target12 of targets) {
|
|
9170
|
+
const gen = getGen(target12);
|
|
8819
9171
|
if (!gen) continue;
|
|
8820
9172
|
for (const out of gen(canonical)) {
|
|
8821
|
-
const existing = await readFileSafe(
|
|
9173
|
+
const existing = await readFileSafe(join51(projectRoot, out.path));
|
|
8822
9174
|
results.push({
|
|
8823
|
-
target:
|
|
9175
|
+
target: target12,
|
|
8824
9176
|
path: out.path,
|
|
8825
9177
|
content: out.content,
|
|
8826
9178
|
currentContent: existing ?? void 0,
|
|
@@ -8838,8 +9190,8 @@ function getDescriptor(name) {
|
|
|
8838
9190
|
return descriptorRegistry.get(name) ?? builtinDescriptors.get(name);
|
|
8839
9191
|
}
|
|
8840
9192
|
function getTarget(name) {
|
|
8841
|
-
const
|
|
8842
|
-
if (
|
|
9193
|
+
const descriptor12 = getDescriptor(name);
|
|
9194
|
+
if (descriptor12) return descriptor12.generators;
|
|
8843
9195
|
const legacy = legacyRegistry.get(name);
|
|
8844
9196
|
if (legacy) return legacy;
|
|
8845
9197
|
throw new Error(`Unknown target: ${name}`);
|
|
@@ -8863,10 +9215,10 @@ function decoratePrimaryRootInstructions(results) {
|
|
|
8863
9215
|
}
|
|
8864
9216
|
|
|
8865
9217
|
// src/core/generate/optional-features.ts
|
|
8866
|
-
import { join as
|
|
9218
|
+
import { join as join53 } from "path";
|
|
8867
9219
|
|
|
8868
9220
|
// src/targets/copilot/hook-assets.ts
|
|
8869
|
-
import { join as
|
|
9221
|
+
import { join as join52, relative as relative19 } from "path";
|
|
8870
9222
|
var SCRIPT_PREFIX_RE = /^(?<prefix>\s*(?:(?:bash|sh|zsh)\s+)?)["']?(?<path>(?:\.\.\/|\.\/|[^/\s"'`]+\/)[^\s"'`]+)["']?(?<suffix>(?:\s.*)?)$/;
|
|
8871
9223
|
function safePhaseName(phase) {
|
|
8872
9224
|
return phase.replace(/[^a-zA-Z0-9]/g, "-").toLowerCase();
|
|
@@ -8887,7 +9239,7 @@ async function buildAssetOutput(projectRoot, command) {
|
|
|
8887
9239
|
const match = command.match(SCRIPT_PREFIX_RE);
|
|
8888
9240
|
const sourceToken = match?.groups?.["path"];
|
|
8889
9241
|
if (!sourceToken) return null;
|
|
8890
|
-
const sourcePath =
|
|
9242
|
+
const sourcePath = join52(projectRoot, sourceToken);
|
|
8891
9243
|
const assetContent = await readFileSafe(sourcePath);
|
|
8892
9244
|
if (assetContent === null) return null;
|
|
8893
9245
|
const repoRelative = toRepoRelative(projectRoot, sourcePath);
|
|
@@ -8975,14 +9327,14 @@ function mergeGeminiSettingsJson(existing, newContent) {
|
|
|
8975
9327
|
|
|
8976
9328
|
// src/core/generate/optional-features.ts
|
|
8977
9329
|
async function generatePermissionsFeature(results, targets, canonical, projectRoot) {
|
|
8978
|
-
for (const
|
|
8979
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9330
|
+
for (const target12 of targets) {
|
|
9331
|
+
const gen = resolveTargetFeatureGenerator(target12, "permissions");
|
|
8980
9332
|
if (!gen) continue;
|
|
8981
9333
|
for (const out of gen(canonical)) {
|
|
8982
|
-
const existing = await readFileSafe(
|
|
9334
|
+
const existing = await readFileSafe(join53(projectRoot, out.path));
|
|
8983
9335
|
const content = existing !== null && SETTINGS_JSON_PATHS.includes(out.path) ? mergeSettingsJson(existing, out.content) : out.content;
|
|
8984
9336
|
results.push({
|
|
8985
|
-
target:
|
|
9337
|
+
target: target12,
|
|
8986
9338
|
path: out.path,
|
|
8987
9339
|
content,
|
|
8988
9340
|
currentContent: existing ?? void 0,
|
|
@@ -8992,15 +9344,15 @@ async function generatePermissionsFeature(results, targets, canonical, projectRo
|
|
|
8992
9344
|
}
|
|
8993
9345
|
}
|
|
8994
9346
|
async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
8995
|
-
for (const
|
|
8996
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9347
|
+
for (const target12 of targets) {
|
|
9348
|
+
const gen = resolveTargetFeatureGenerator(target12, "hooks");
|
|
8997
9349
|
if (!gen) continue;
|
|
8998
|
-
const outputs =
|
|
9350
|
+
const outputs = target12 === "copilot" ? await addHookScriptAssets(projectRoot, canonical, gen(canonical)) : gen(canonical);
|
|
8999
9351
|
for (const out of outputs) {
|
|
9000
|
-
const existing = await readFileSafe(
|
|
9352
|
+
const existing = await readFileSafe(join53(projectRoot, out.path));
|
|
9001
9353
|
let content = out.content;
|
|
9002
9354
|
if (SETTINGS_JSON_PATHS.includes(out.path)) {
|
|
9003
|
-
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target ===
|
|
9355
|
+
const pendingIdx = results.findIndex((r) => r.path === out.path && r.target === target12);
|
|
9004
9356
|
const pendingResult = pendingIdx >= 0 ? results[pendingIdx] : void 0;
|
|
9005
9357
|
const base = pendingResult?.content ?? existing;
|
|
9006
9358
|
if (base !== null) {
|
|
@@ -9011,7 +9363,7 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9011
9363
|
}
|
|
9012
9364
|
}
|
|
9013
9365
|
results.push({
|
|
9014
|
-
target:
|
|
9366
|
+
target: target12,
|
|
9015
9367
|
path: out.path,
|
|
9016
9368
|
content,
|
|
9017
9369
|
currentContent: existing ?? void 0,
|
|
@@ -9021,17 +9373,17 @@ async function generateHooksFeature(results, targets, canonical, projectRoot) {
|
|
|
9021
9373
|
}
|
|
9022
9374
|
}
|
|
9023
9375
|
async function generateGeminiSettingsFeature(results, targets, canonical, projectRoot) {
|
|
9024
|
-
for (const
|
|
9025
|
-
if (
|
|
9026
|
-
const gen = resolveTargetFeatureGenerator(
|
|
9376
|
+
for (const target12 of targets) {
|
|
9377
|
+
if (target12 !== "gemini-cli") continue;
|
|
9378
|
+
const gen = resolveTargetFeatureGenerator(target12, "settings");
|
|
9027
9379
|
if (!gen) continue;
|
|
9028
9380
|
const outputs = gen(canonical);
|
|
9029
9381
|
if (outputs.length === 0) continue;
|
|
9030
9382
|
for (const out of outputs) {
|
|
9031
|
-
const existing = await readFileSafe(
|
|
9383
|
+
const existing = await readFileSafe(join53(projectRoot, out.path));
|
|
9032
9384
|
const content = existing !== null && out.path === GEMINI_SETTINGS ? mergeGeminiSettingsJson(existing, out.content) : out.content;
|
|
9033
9385
|
results.push({
|
|
9034
|
-
target:
|
|
9386
|
+
target: target12,
|
|
9035
9387
|
path: out.path,
|
|
9036
9388
|
content,
|
|
9037
9389
|
currentContent: existing ?? void 0,
|
|
@@ -9060,7 +9412,7 @@ async function generate(ctx) {
|
|
|
9060
9412
|
canonical,
|
|
9061
9413
|
projectRoot,
|
|
9062
9414
|
hasRules,
|
|
9063
|
-
(
|
|
9415
|
+
(target12) => resolveTargetFeatureGenerator(target12, "rules", config)
|
|
9064
9416
|
);
|
|
9065
9417
|
await generateFeature(
|
|
9066
9418
|
results,
|
|
@@ -9068,7 +9420,7 @@ async function generate(ctx) {
|
|
|
9068
9420
|
canonical,
|
|
9069
9421
|
projectRoot,
|
|
9070
9422
|
hasCommands,
|
|
9071
|
-
(
|
|
9423
|
+
(target12) => resolveTargetFeatureGenerator(target12, "commands", config)
|
|
9072
9424
|
);
|
|
9073
9425
|
await generateFeature(
|
|
9074
9426
|
results,
|
|
@@ -9076,7 +9428,7 @@ async function generate(ctx) {
|
|
|
9076
9428
|
canonical,
|
|
9077
9429
|
projectRoot,
|
|
9078
9430
|
hasAgents,
|
|
9079
|
-
(
|
|
9431
|
+
(target12) => resolveTargetFeatureGenerator(target12, "agents", config)
|
|
9080
9432
|
);
|
|
9081
9433
|
await generateFeature(
|
|
9082
9434
|
results,
|
|
@@ -9084,7 +9436,7 @@ async function generate(ctx) {
|
|
|
9084
9436
|
canonical,
|
|
9085
9437
|
projectRoot,
|
|
9086
9438
|
hasSkills,
|
|
9087
|
-
(
|
|
9439
|
+
(target12) => resolveTargetFeatureGenerator(target12, "skills", config)
|
|
9088
9440
|
);
|
|
9089
9441
|
await generateFeature(
|
|
9090
9442
|
results,
|
|
@@ -9092,7 +9444,7 @@ async function generate(ctx) {
|
|
|
9092
9444
|
canonical,
|
|
9093
9445
|
projectRoot,
|
|
9094
9446
|
hasMcp,
|
|
9095
|
-
(
|
|
9447
|
+
(target12) => resolveTargetFeatureGenerator(target12, "mcp", config)
|
|
9096
9448
|
);
|
|
9097
9449
|
if (hasPermissions) await generatePermissionsFeature(results, targets, canonical, projectRoot);
|
|
9098
9450
|
if (hasHooks) await generateHooksFeature(results, targets, canonical, projectRoot);
|
|
@@ -9102,7 +9454,7 @@ async function generate(ctx) {
|
|
|
9102
9454
|
canonical,
|
|
9103
9455
|
projectRoot,
|
|
9104
9456
|
hasIgnore,
|
|
9105
|
-
(
|
|
9457
|
+
(target12) => resolveTargetFeatureGenerator(target12, "ignore", config)
|
|
9106
9458
|
);
|
|
9107
9459
|
if (hasMcp || hasIgnore || hasHooks || hasAgents) {
|
|
9108
9460
|
await generateGeminiSettingsFeature(results, targets, canonical, projectRoot);
|
|
@@ -9113,8 +9465,8 @@ async function generate(ctx) {
|
|
|
9113
9465
|
}
|
|
9114
9466
|
|
|
9115
9467
|
// src/core/generate/stale-cleanup.ts
|
|
9116
|
-
import { readdir as
|
|
9117
|
-
import { join as
|
|
9468
|
+
import { readdir as readdir12, rm as rm6 } from "fs/promises";
|
|
9469
|
+
import { join as join54, relative as relative20 } from "path";
|
|
9118
9470
|
var TARGET_MANAGED_OUTPUTS = {
|
|
9119
9471
|
"claude-code": {
|
|
9120
9472
|
dirs: [".claude/agents", ".claude/commands", ".claude/rules", ".claude/skills"],
|
|
@@ -9177,10 +9529,10 @@ var TARGET_MANAGED_OUTPUTS = {
|
|
|
9177
9529
|
}
|
|
9178
9530
|
};
|
|
9179
9531
|
async function listFiles2(root, base = root) {
|
|
9180
|
-
const entries = await
|
|
9532
|
+
const entries = await readdir12(root, { withFileTypes: true });
|
|
9181
9533
|
const files = [];
|
|
9182
9534
|
for (const entry of entries) {
|
|
9183
|
-
const abs =
|
|
9535
|
+
const abs = join54(root, entry.name);
|
|
9184
9536
|
if (entry.isDirectory()) {
|
|
9185
9537
|
files.push(...await listFiles2(abs, base));
|
|
9186
9538
|
continue;
|
|
@@ -9191,18 +9543,18 @@ async function listFiles2(root, base = root) {
|
|
|
9191
9543
|
}
|
|
9192
9544
|
async function removeIfStale(projectRoot, relPath, expected) {
|
|
9193
9545
|
if (expected.has(relPath)) return;
|
|
9194
|
-
const abs =
|
|
9546
|
+
const abs = join54(projectRoot, relPath);
|
|
9195
9547
|
if (await exists(abs)) await rm6(abs, { recursive: true, force: true });
|
|
9196
9548
|
}
|
|
9197
9549
|
async function cleanupStaleGeneratedOutputs(args) {
|
|
9198
9550
|
const expected = new Set(args.expectedPaths);
|
|
9199
9551
|
const stale = /* @__PURE__ */ new Set();
|
|
9200
|
-
for (const
|
|
9201
|
-
const managed = TARGET_MANAGED_OUTPUTS[
|
|
9552
|
+
for (const target12 of args.targets) {
|
|
9553
|
+
const managed = TARGET_MANAGED_OUTPUTS[target12];
|
|
9202
9554
|
if (!managed) continue;
|
|
9203
9555
|
for (const file of managed.files) stale.add(file);
|
|
9204
9556
|
for (const dir of managed.dirs) {
|
|
9205
|
-
const absDir =
|
|
9557
|
+
const absDir = join54(args.projectRoot, dir);
|
|
9206
9558
|
if (!await exists(absDir)) continue;
|
|
9207
9559
|
for (const file of await listFiles2(absDir)) {
|
|
9208
9560
|
stale.add(`${dir}/${file}`.replace(/\/+/g, "/"));
|
|
@@ -9215,17 +9567,17 @@ async function cleanupStaleGeneratedOutputs(args) {
|
|
|
9215
9567
|
}
|
|
9216
9568
|
|
|
9217
9569
|
// src/core/matrix/matrix.ts
|
|
9218
|
-
import { basename as
|
|
9570
|
+
import { basename as basename31 } from "path";
|
|
9219
9571
|
|
|
9220
9572
|
// src/targets/catalog/target-catalog.ts
|
|
9221
9573
|
var TARGET_CATALOG = Object.fromEntries(
|
|
9222
|
-
BUILTIN_TARGETS.map((
|
|
9223
|
-
|
|
9574
|
+
BUILTIN_TARGETS.map((target12) => [
|
|
9575
|
+
target12.id,
|
|
9224
9576
|
{
|
|
9225
|
-
importFrom:
|
|
9226
|
-
emptyImportMessage:
|
|
9227
|
-
lintRules:
|
|
9228
|
-
capabilities:
|
|
9577
|
+
importFrom: target12.generators.importFrom,
|
|
9578
|
+
emptyImportMessage: target12.emptyImportMessage,
|
|
9579
|
+
lintRules: target12.lintRules,
|
|
9580
|
+
capabilities: target12.capabilities
|
|
9229
9581
|
}
|
|
9230
9582
|
])
|
|
9231
9583
|
);
|
|
@@ -9252,7 +9604,7 @@ var SUPPORT_MATRIX = Object.fromEntries(
|
|
|
9252
9604
|
FEATURE_IDS.map((feature) => [
|
|
9253
9605
|
feature,
|
|
9254
9606
|
Object.fromEntries(
|
|
9255
|
-
TARGET_IDS.map((
|
|
9607
|
+
TARGET_IDS.map((target12) => [target12, TARGET_CATALOG[target12].capabilities[feature]])
|
|
9256
9608
|
)
|
|
9257
9609
|
])
|
|
9258
9610
|
);
|
|
@@ -9358,13 +9710,13 @@ function formatMatrix(rows, targets) {
|
|
|
9358
9710
|
function formatVerboseDetails(canonical) {
|
|
9359
9711
|
const lines = [];
|
|
9360
9712
|
if (canonical.rules.length > 0) {
|
|
9361
|
-
lines.push(`rules: ${canonical.rules.map((r) =>
|
|
9713
|
+
lines.push(`rules: ${canonical.rules.map((r) => basename31(r.source)).join(", ")}`);
|
|
9362
9714
|
}
|
|
9363
9715
|
if (canonical.commands.length > 0) {
|
|
9364
|
-
lines.push(`commands: ${canonical.commands.map((c2) =>
|
|
9716
|
+
lines.push(`commands: ${canonical.commands.map((c2) => basename31(c2.source)).join(", ")}`);
|
|
9365
9717
|
}
|
|
9366
9718
|
if (canonical.agents.length > 0) {
|
|
9367
|
-
lines.push(`agents: ${canonical.agents.map((a) =>
|
|
9719
|
+
lines.push(`agents: ${canonical.agents.map((a) => basename31(a.source)).join(", ")}`);
|
|
9368
9720
|
}
|
|
9369
9721
|
if (canonical.skills.length > 0) {
|
|
9370
9722
|
lines.push(`skills: ${canonical.skills.map((s) => s.name).join(", ")}`);
|
|
@@ -9416,11 +9768,11 @@ async function runMatrix(flags, projectRoot) {
|
|
|
9416
9768
|
}
|
|
9417
9769
|
|
|
9418
9770
|
// src/cli/commands/generate.ts
|
|
9419
|
-
function ensurePathInsideRoot(rootDir, relativePath,
|
|
9771
|
+
function ensurePathInsideRoot(rootDir, relativePath, target12) {
|
|
9420
9772
|
const rootAbs = resolve4(rootDir);
|
|
9421
9773
|
const outputAbs = resolve4(rootDir, relativePath);
|
|
9422
9774
|
if (outputAbs === rootAbs || outputAbs.startsWith(`${rootAbs}${sep}`)) return outputAbs;
|
|
9423
|
-
throw new Error(`Unsafe generated output path for ${
|
|
9775
|
+
throw new Error(`Unsafe generated output path for ${target12}: ${relativePath}`);
|
|
9424
9776
|
}
|
|
9425
9777
|
async function runGenerate(flags, projectRoot, options = {}) {
|
|
9426
9778
|
if (flags.features !== void 0) {
|
|
@@ -9436,7 +9788,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9436
9788
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
9437
9789
|
const lockFeatures = config.collaboration?.lock_features ?? [];
|
|
9438
9790
|
if (config.collaboration?.strategy === "lock" && !force && lockFeatures.length > 0) {
|
|
9439
|
-
const abDir =
|
|
9791
|
+
const abDir = join55(configDir, ".agentsmesh");
|
|
9440
9792
|
const existingLock = await readLock(abDir);
|
|
9441
9793
|
if (existingLock !== null) {
|
|
9442
9794
|
const currentChecksums = await buildChecksums(abDir);
|
|
@@ -9472,10 +9824,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9472
9824
|
return 0;
|
|
9473
9825
|
}
|
|
9474
9826
|
if (!dryRun) {
|
|
9475
|
-
const abDir =
|
|
9827
|
+
const abDir = join55(configDir, ".agentsmesh");
|
|
9476
9828
|
const checksums = await buildChecksums(abDir);
|
|
9477
9829
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9478
|
-
const packChecksums = await buildPackChecksums(
|
|
9830
|
+
const packChecksums = await buildPackChecksums(join55(abDir, "packs"));
|
|
9479
9831
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9480
9832
|
await writeLock(abDir, {
|
|
9481
9833
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9486,7 +9838,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9486
9838
|
packs: packChecksums
|
|
9487
9839
|
});
|
|
9488
9840
|
try {
|
|
9489
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
9841
|
+
await ensureCacheSymlink(getCacheDir(), join55(configDir, ".agentsmeshcache"));
|
|
9490
9842
|
} catch (err) {
|
|
9491
9843
|
logger.warn(
|
|
9492
9844
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9533,10 +9885,10 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9533
9885
|
} else {
|
|
9534
9886
|
logger.info(`Nothing changed. (${unchanged} unchanged)`);
|
|
9535
9887
|
}
|
|
9536
|
-
const abDir =
|
|
9888
|
+
const abDir = join55(configDir, ".agentsmesh");
|
|
9537
9889
|
const checksums = await buildChecksums(abDir);
|
|
9538
9890
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9539
|
-
const packChecksums = await buildPackChecksums(
|
|
9891
|
+
const packChecksums = await buildPackChecksums(join55(abDir, "packs"));
|
|
9540
9892
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
9541
9893
|
await writeLock(abDir, {
|
|
9542
9894
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -9547,7 +9899,7 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9547
9899
|
packs: packChecksums
|
|
9548
9900
|
});
|
|
9549
9901
|
try {
|
|
9550
|
-
await ensureCacheSymlink(getCacheDir(),
|
|
9902
|
+
await ensureCacheSymlink(getCacheDir(), join55(configDir, ".agentsmeshcache"));
|
|
9551
9903
|
} catch (err) {
|
|
9552
9904
|
logger.warn(
|
|
9553
9905
|
`Could not create .agentsmeshcache symlink: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9561,20 +9913,9 @@ async function runGenerate(flags, projectRoot, options = {}) {
|
|
|
9561
9913
|
}
|
|
9562
9914
|
|
|
9563
9915
|
// src/cli/commands/init.ts
|
|
9564
|
-
import { join as
|
|
9916
|
+
import { join as join57 } from "path";
|
|
9565
9917
|
|
|
9566
9918
|
// src/cli/commands/init-templates.ts
|
|
9567
|
-
var ALL_TARGETS = [
|
|
9568
|
-
"claude-code",
|
|
9569
|
-
"cursor",
|
|
9570
|
-
"copilot",
|
|
9571
|
-
"continue",
|
|
9572
|
-
"junie",
|
|
9573
|
-
"gemini-cli",
|
|
9574
|
-
"cline",
|
|
9575
|
-
"codex-cli",
|
|
9576
|
-
"windsurf"
|
|
9577
|
-
];
|
|
9578
9919
|
var ALL_FEATURES = [
|
|
9579
9920
|
"rules",
|
|
9580
9921
|
"commands",
|
|
@@ -9586,7 +9927,7 @@ var ALL_FEATURES = [
|
|
|
9586
9927
|
"permissions"
|
|
9587
9928
|
];
|
|
9588
9929
|
function buildConfig(targets) {
|
|
9589
|
-
const targetList = (targets.length > 0 ? targets :
|
|
9930
|
+
const targetList = (targets.length > 0 ? targets : TARGET_IDS).map((t) => ` - ${t}`).join("\n");
|
|
9590
9931
|
const featureList = ALL_FEATURES.map((f) => ` - ${f}`).join("\n");
|
|
9591
9932
|
return `version: 1
|
|
9592
9933
|
targets:
|
|
@@ -9717,7 +10058,7 @@ var LOCAL_TEMPLATE = `# Personal overrides \u2014 NOT committed to git
|
|
|
9717
10058
|
`;
|
|
9718
10059
|
|
|
9719
10060
|
// src/cli/commands/init-detect.ts
|
|
9720
|
-
import { join as
|
|
10061
|
+
import { join as join56 } from "path";
|
|
9721
10062
|
var TOOL_INDICATORS = BUILTIN_TARGETS.map((d) => ({
|
|
9722
10063
|
id: d.id,
|
|
9723
10064
|
paths: [...d.detectionPaths]
|
|
@@ -9726,7 +10067,7 @@ async function detectExistingConfigs(projectRoot) {
|
|
|
9726
10067
|
const found = [];
|
|
9727
10068
|
for (const { id, paths } of TOOL_INDICATORS) {
|
|
9728
10069
|
for (const p of paths) {
|
|
9729
|
-
const full =
|
|
10070
|
+
const full = join56(projectRoot, p);
|
|
9730
10071
|
if (await exists(full)) {
|
|
9731
10072
|
found.push(id);
|
|
9732
10073
|
break;
|
|
@@ -9744,7 +10085,7 @@ var IMPORTERS = Object.fromEntries(
|
|
|
9744
10085
|
BUILTIN_TARGETS.map((d) => [d.id, (root) => d.generators.importFrom(root)])
|
|
9745
10086
|
);
|
|
9746
10087
|
async function appendToGitignore(projectRoot) {
|
|
9747
|
-
const gitignorePath =
|
|
10088
|
+
const gitignorePath = join57(projectRoot, ".gitignore");
|
|
9748
10089
|
const current = await readFileSafe(gitignorePath) ?? "";
|
|
9749
10090
|
const lines = new Set(current.split("\n").map((s) => s.trim()));
|
|
9750
10091
|
const toAdd = GITIGNORE_ENTRIES.filter((e) => !lines.has(e));
|
|
@@ -9753,7 +10094,7 @@ async function appendToGitignore(projectRoot) {
|
|
|
9753
10094
|
await writeFileAtomic(gitignorePath, current + suffix + toAdd.join("\n") + "\n");
|
|
9754
10095
|
}
|
|
9755
10096
|
async function writeScaffold(projectRoot) {
|
|
9756
|
-
const ab = (rel2) =>
|
|
10097
|
+
const ab = (rel2) => join57(projectRoot, ".agentsmesh", rel2);
|
|
9757
10098
|
await mkdirp(ab("rules"));
|
|
9758
10099
|
await writeFileAtomic(ab("rules/_root.md"), TEMPLATE_ROOT_RULE);
|
|
9759
10100
|
logger.success("Created .agentsmesh/rules/_root.md");
|
|
@@ -9778,7 +10119,7 @@ async function writeScaffold(projectRoot) {
|
|
|
9778
10119
|
logger.success("Created .agentsmesh/ignore");
|
|
9779
10120
|
}
|
|
9780
10121
|
async function runInit(projectRoot, options = {}) {
|
|
9781
|
-
const configPath =
|
|
10122
|
+
const configPath = join57(projectRoot, CONFIG_FILENAME2);
|
|
9782
10123
|
if (await exists(configPath)) {
|
|
9783
10124
|
throw new Error(`Already initialized. ${CONFIG_FILENAME2} exists. Remove it first to re-init.`);
|
|
9784
10125
|
}
|
|
@@ -9815,7 +10156,7 @@ async function runInit(projectRoot, options = {}) {
|
|
|
9815
10156
|
await writeFileAtomic(configPath, buildConfig([]));
|
|
9816
10157
|
logger.success(`Created ${CONFIG_FILENAME2}`);
|
|
9817
10158
|
}
|
|
9818
|
-
const localPath =
|
|
10159
|
+
const localPath = join57(projectRoot, LOCAL_CONFIG_FILENAME2);
|
|
9819
10160
|
await writeFileAtomic(localPath, LOCAL_TEMPLATE);
|
|
9820
10161
|
logger.success(`Created ${LOCAL_CONFIG_FILENAME2}`);
|
|
9821
10162
|
await appendToGitignore(projectRoot);
|
|
@@ -9834,10 +10175,10 @@ async function runImport(flags, projectRoot) {
|
|
|
9834
10175
|
if (!isBuiltinTargetId(normalized)) {
|
|
9835
10176
|
throw new Error(`Unknown --from "${from}". Supported: ${TARGET_IDS.join(", ")}.`);
|
|
9836
10177
|
}
|
|
9837
|
-
const
|
|
9838
|
-
const results = await
|
|
10178
|
+
const target12 = getTargetCatalogEntry(normalized);
|
|
10179
|
+
const results = await target12.importFrom(root);
|
|
9839
10180
|
if (results.length === 0) {
|
|
9840
|
-
logger.info(
|
|
10181
|
+
logger.info(target12.emptyImportMessage);
|
|
9841
10182
|
return;
|
|
9842
10183
|
}
|
|
9843
10184
|
for (const r of results) {
|
|
@@ -9922,56 +10263,56 @@ async function runDiff(flags, projectRoot) {
|
|
|
9922
10263
|
import { relative as relative22 } from "path";
|
|
9923
10264
|
|
|
9924
10265
|
// src/core/lint/commands.ts
|
|
9925
|
-
function lintCommands(canonical,
|
|
10266
|
+
function lintCommands(canonical, target12) {
|
|
9926
10267
|
if (canonical.commands.length === 0) return [];
|
|
9927
10268
|
return canonical.commands.flatMap((command) => {
|
|
9928
|
-
if (
|
|
10269
|
+
if (target12 === "copilot" && command.allowedTools.length > 0) {
|
|
9929
10270
|
return [
|
|
9930
10271
|
{
|
|
9931
10272
|
level: "warning",
|
|
9932
10273
|
file: command.source,
|
|
9933
|
-
target:
|
|
10274
|
+
target: target12,
|
|
9934
10275
|
message: "Copilot prompt files do not enforce canonical allowed-tools natively."
|
|
9935
10276
|
}
|
|
9936
10277
|
];
|
|
9937
10278
|
}
|
|
9938
|
-
if (
|
|
10279
|
+
if (target12 === "cursor" && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
9939
10280
|
return [
|
|
9940
10281
|
{
|
|
9941
10282
|
level: "warning",
|
|
9942
10283
|
file: command.source,
|
|
9943
|
-
target:
|
|
10284
|
+
target: target12,
|
|
9944
10285
|
message: "Cursor command files are plain Markdown; command description and allowed-tools metadata are not projected."
|
|
9945
10286
|
}
|
|
9946
10287
|
];
|
|
9947
10288
|
}
|
|
9948
|
-
if (
|
|
10289
|
+
if (target12 === "gemini-cli" && command.allowedTools.length > 0) {
|
|
9949
10290
|
return [
|
|
9950
10291
|
{
|
|
9951
10292
|
level: "warning",
|
|
9952
10293
|
file: command.source,
|
|
9953
|
-
target:
|
|
10294
|
+
target: target12,
|
|
9954
10295
|
message: "Gemini TOML command files do not project canonical allowed-tools metadata."
|
|
9955
10296
|
}
|
|
9956
10297
|
];
|
|
9957
10298
|
}
|
|
9958
|
-
if (
|
|
10299
|
+
if (target12 === "continue" && command.allowedTools.length > 0) {
|
|
9959
10300
|
return [
|
|
9960
10301
|
{
|
|
9961
10302
|
level: "warning",
|
|
9962
10303
|
file: command.source,
|
|
9963
|
-
target:
|
|
10304
|
+
target: target12,
|
|
9964
10305
|
message: "Continue invokable prompt rules do not natively enforce canonical allowed-tools metadata."
|
|
9965
10306
|
}
|
|
9966
10307
|
];
|
|
9967
10308
|
}
|
|
9968
|
-
if (["cline", "windsurf"].includes(
|
|
10309
|
+
if (["cline", "windsurf"].includes(target12) && (command.description.length > 0 || command.allowedTools.length > 0)) {
|
|
9969
10310
|
return [
|
|
9970
10311
|
{
|
|
9971
10312
|
level: "warning",
|
|
9972
10313
|
file: command.source,
|
|
9973
|
-
target:
|
|
9974
|
-
message: `${
|
|
10314
|
+
target: target12,
|
|
10315
|
+
message: `${target12} workflow files are plain Markdown; command description and allowed-tools metadata are not projected.`
|
|
9975
10316
|
}
|
|
9976
10317
|
];
|
|
9977
10318
|
}
|
|
@@ -9980,48 +10321,48 @@ function lintCommands(canonical, target11) {
|
|
|
9980
10321
|
}
|
|
9981
10322
|
|
|
9982
10323
|
// src/core/lint/mcp.ts
|
|
9983
|
-
function lintMcp(canonical,
|
|
10324
|
+
function lintMcp(canonical, target12) {
|
|
9984
10325
|
if (!canonical.mcp || Object.keys(canonical.mcp.mcpServers).length === 0) return [];
|
|
9985
10326
|
const diagnostics = [];
|
|
9986
10327
|
for (const [name, server] of Object.entries(canonical.mcp.mcpServers)) {
|
|
9987
|
-
if (
|
|
10328
|
+
if (target12 === "cursor" && usesCursorSensitiveInterpolation(server)) {
|
|
9988
10329
|
diagnostics.push({
|
|
9989
10330
|
level: "warning",
|
|
9990
10331
|
file: ".agentsmesh/mcp.json",
|
|
9991
|
-
target:
|
|
10332
|
+
target: target12,
|
|
9992
10333
|
message: `MCP server "${name}" uses env vars or URL/header interpolation; Cursor handling may differ from canonical MCP.`
|
|
9993
10334
|
});
|
|
9994
10335
|
}
|
|
9995
|
-
if (
|
|
10336
|
+
if (target12 === "codex-cli" && typeof server.description === "string" && server.description) {
|
|
9996
10337
|
diagnostics.push({
|
|
9997
10338
|
level: "warning",
|
|
9998
10339
|
file: ".agentsmesh/mcp.json",
|
|
9999
|
-
target:
|
|
10340
|
+
target: target12,
|
|
10000
10341
|
message: `MCP server "${name}" has a description, but codex-cli does not project MCP descriptions into .codex/config.toml.`
|
|
10001
10342
|
});
|
|
10002
10343
|
}
|
|
10003
|
-
if (
|
|
10344
|
+
if (target12 === "codex-cli" && isUrlMcpServer(server)) {
|
|
10004
10345
|
diagnostics.push({
|
|
10005
10346
|
level: "warning",
|
|
10006
10347
|
file: ".agentsmesh/mcp.json",
|
|
10007
|
-
target:
|
|
10348
|
+
target: target12,
|
|
10008
10349
|
message: `MCP server "${name}" uses ${server.type} transport; codex-cli only generates stdio MCP servers.`
|
|
10009
10350
|
});
|
|
10010
10351
|
}
|
|
10011
|
-
if (
|
|
10352
|
+
if (target12 === "junie" && isUrlMcpServer(server)) {
|
|
10012
10353
|
diagnostics.push({
|
|
10013
10354
|
level: "warning",
|
|
10014
10355
|
file: ".agentsmesh/mcp.json",
|
|
10015
|
-
target:
|
|
10356
|
+
target: target12,
|
|
10016
10357
|
message: `MCP server "${name}" uses ${server.type} transport; Junie project mcp.json currently documents stdio MCP servers only.`
|
|
10017
10358
|
});
|
|
10018
10359
|
}
|
|
10019
10360
|
}
|
|
10020
|
-
if (
|
|
10361
|
+
if (target12 === "windsurf") {
|
|
10021
10362
|
diagnostics.push({
|
|
10022
10363
|
level: "warning",
|
|
10023
10364
|
file: ".agentsmesh/mcp.json",
|
|
10024
|
-
target:
|
|
10365
|
+
target: target12,
|
|
10025
10366
|
message: "Windsurf MCP is partial; generated .windsurf/mcp_config.example.json is a reference artifact and may require manual setup."
|
|
10026
10367
|
});
|
|
10027
10368
|
}
|
|
@@ -10029,39 +10370,39 @@ function lintMcp(canonical, target11) {
|
|
|
10029
10370
|
}
|
|
10030
10371
|
|
|
10031
10372
|
// src/core/lint/permissions.ts
|
|
10032
|
-
function lintPermissions(canonical,
|
|
10373
|
+
function lintPermissions(canonical, target12) {
|
|
10033
10374
|
if (!canonical.permissions) return [];
|
|
10034
|
-
if (
|
|
10375
|
+
if (target12 !== "cursor") return [];
|
|
10035
10376
|
const hasEntries = canonical.permissions.allow.length > 0 || canonical.permissions.deny.length > 0;
|
|
10036
10377
|
if (!hasEntries) return [];
|
|
10037
10378
|
return [
|
|
10038
10379
|
{
|
|
10039
10380
|
level: "warning",
|
|
10040
10381
|
file: ".agentsmesh/permissions.yaml",
|
|
10041
|
-
target:
|
|
10382
|
+
target: target12,
|
|
10042
10383
|
message: "Cursor permissions are partial; tool-level allow/deny may lose fidelity."
|
|
10043
10384
|
}
|
|
10044
10385
|
];
|
|
10045
10386
|
}
|
|
10046
10387
|
|
|
10047
10388
|
// src/core/lint/hooks.ts
|
|
10048
|
-
function lintHooks(canonical,
|
|
10389
|
+
function lintHooks(canonical, target12) {
|
|
10049
10390
|
if (!canonical.hooks || Object.keys(canonical.hooks).length === 0) return [];
|
|
10050
|
-
if (
|
|
10391
|
+
if (target12 === "gemini-cli") {
|
|
10051
10392
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification"]);
|
|
10052
10393
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10053
10394
|
level: "warning",
|
|
10054
10395
|
file: ".agentsmesh/hooks.yaml",
|
|
10055
|
-
target:
|
|
10396
|
+
target: target12,
|
|
10056
10397
|
message: `${event} is not supported by gemini-cli; only PreToolUse, PostToolUse, and Notification are projected.`
|
|
10057
10398
|
}));
|
|
10058
10399
|
}
|
|
10059
|
-
if (
|
|
10400
|
+
if (target12 === "copilot") {
|
|
10060
10401
|
const supported = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUse", "Notification", "UserPromptSubmit"]);
|
|
10061
10402
|
return Object.keys(canonical.hooks).filter((event) => !supported.has(event)).map((event) => ({
|
|
10062
10403
|
level: "warning",
|
|
10063
10404
|
file: ".agentsmesh/hooks.yaml",
|
|
10064
|
-
target:
|
|
10405
|
+
target: target12,
|
|
10065
10406
|
message: `${event} is not supported by Copilot hooks; only PreToolUse, PostToolUse, Notification, and UserPromptSubmit are projected.`
|
|
10066
10407
|
}));
|
|
10067
10408
|
}
|
|
@@ -10087,22 +10428,22 @@ async function runLint(config, canonical, projectRoot, targetFilter) {
|
|
|
10087
10428
|
const hasHooks = config.features.includes("hooks");
|
|
10088
10429
|
const diagnostics = [];
|
|
10089
10430
|
const projectFiles = await getProjectFiles(projectRoot);
|
|
10090
|
-
for (const
|
|
10091
|
-
const linter = isBuiltinTargetId(
|
|
10431
|
+
for (const target12 of targets) {
|
|
10432
|
+
const linter = isBuiltinTargetId(target12) ? getTargetCatalogEntry(target12).lintRules : null;
|
|
10092
10433
|
if (hasRules && linter) {
|
|
10093
10434
|
diagnostics.push(...linter(canonical, projectRoot, projectFiles));
|
|
10094
10435
|
}
|
|
10095
10436
|
if (hasCommands) {
|
|
10096
|
-
diagnostics.push(...lintCommands(canonical,
|
|
10437
|
+
diagnostics.push(...lintCommands(canonical, target12));
|
|
10097
10438
|
}
|
|
10098
10439
|
if (hasMcp) {
|
|
10099
|
-
diagnostics.push(...lintMcp(canonical,
|
|
10440
|
+
diagnostics.push(...lintMcp(canonical, target12));
|
|
10100
10441
|
}
|
|
10101
10442
|
if (hasPermissions) {
|
|
10102
|
-
diagnostics.push(...lintPermissions(canonical,
|
|
10443
|
+
diagnostics.push(...lintPermissions(canonical, target12));
|
|
10103
10444
|
}
|
|
10104
10445
|
if (hasHooks) {
|
|
10105
|
-
diagnostics.push(...lintHooks(canonical,
|
|
10446
|
+
diagnostics.push(...lintHooks(canonical, target12));
|
|
10106
10447
|
}
|
|
10107
10448
|
}
|
|
10108
10449
|
const hasErrors = diagnostics.some((d) => d.level === "error");
|
|
@@ -10142,7 +10483,7 @@ async function runLintCmd(flags, projectRoot) {
|
|
|
10142
10483
|
}
|
|
10143
10484
|
|
|
10144
10485
|
// src/cli/commands/watch.ts
|
|
10145
|
-
import { join as
|
|
10486
|
+
import { join as join58, relative as relative23 } from "path";
|
|
10146
10487
|
import chokidar from "chokidar";
|
|
10147
10488
|
var DEBOUNCE_MS = 300;
|
|
10148
10489
|
function normalizeWatchPath(path) {
|
|
@@ -10169,9 +10510,9 @@ async function runWatch(flags, projectRoot) {
|
|
|
10169
10510
|
const root = projectRoot ?? process.cwd();
|
|
10170
10511
|
const { configDir } = await loadConfigFromDir(root);
|
|
10171
10512
|
const paths = [
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10513
|
+
join58(configDir, ".agentsmesh"),
|
|
10514
|
+
join58(configDir, "agentsmesh.yaml"),
|
|
10515
|
+
join58(configDir, "agentsmesh.local.yaml")
|
|
10175
10516
|
];
|
|
10176
10517
|
let debounceTimer = null;
|
|
10177
10518
|
let lastFingerprint = null;
|
|
@@ -10257,12 +10598,12 @@ async function runWatch(flags, projectRoot) {
|
|
|
10257
10598
|
}
|
|
10258
10599
|
|
|
10259
10600
|
// src/cli/commands/check.ts
|
|
10260
|
-
import { join as
|
|
10601
|
+
import { join as join59 } from "path";
|
|
10261
10602
|
async function runCheck(flags, projectRoot) {
|
|
10262
10603
|
void flags;
|
|
10263
10604
|
const root = projectRoot ?? process.cwd();
|
|
10264
10605
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10265
|
-
const abDir =
|
|
10606
|
+
const abDir = join59(configDir, ".agentsmesh");
|
|
10266
10607
|
const lock = await readLock(abDir);
|
|
10267
10608
|
if (lock === null) {
|
|
10268
10609
|
logger.error("Not initialized for collaboration. Run 'agentsmesh generate' first.");
|
|
@@ -10332,14 +10673,14 @@ async function runCheck(flags, projectRoot) {
|
|
|
10332
10673
|
}
|
|
10333
10674
|
|
|
10334
10675
|
// src/cli/commands/merge.ts
|
|
10335
|
-
import { join as
|
|
10676
|
+
import { join as join61 } from "path";
|
|
10336
10677
|
|
|
10337
10678
|
// src/core/merger.ts
|
|
10338
|
-
import { dirname as dirname22, join as
|
|
10679
|
+
import { dirname as dirname22, join as join60 } from "path";
|
|
10339
10680
|
var LOCK_FILENAME2 = ".lock";
|
|
10340
10681
|
var CONFLICT_MARKER = "<<<<<<<";
|
|
10341
10682
|
async function hasLockConflict(abDir) {
|
|
10342
|
-
const lockPath =
|
|
10683
|
+
const lockPath = join60(abDir, LOCK_FILENAME2);
|
|
10343
10684
|
const content = await readFileSafe(lockPath);
|
|
10344
10685
|
if (content === null) return false;
|
|
10345
10686
|
return content.includes(CONFLICT_MARKER);
|
|
@@ -10353,7 +10694,7 @@ async function resolveLockConflict(abDir, libVersion, config) {
|
|
|
10353
10694
|
const configDir = dirname22(abDir);
|
|
10354
10695
|
const resolvedExtends = config ? await resolveExtendPaths(config, configDir) : [];
|
|
10355
10696
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
10356
|
-
const packChecksums = await buildPackChecksums(
|
|
10697
|
+
const packChecksums = await buildPackChecksums(join60(abDir, "packs"));
|
|
10357
10698
|
const generatedBy = process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
10358
10699
|
await writeLock(abDir, {
|
|
10359
10700
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -10370,7 +10711,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10370
10711
|
void flags;
|
|
10371
10712
|
const root = projectRoot ?? process.cwd();
|
|
10372
10713
|
const { config, configDir } = await loadConfigFromDir(root);
|
|
10373
|
-
const abDir =
|
|
10714
|
+
const abDir = join61(configDir, ".agentsmesh");
|
|
10374
10715
|
const hasConflict = await hasLockConflict(abDir);
|
|
10375
10716
|
if (!hasConflict) {
|
|
10376
10717
|
logger.info("No conflicts to resolve.");
|
|
@@ -10381,7 +10722,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
10381
10722
|
}
|
|
10382
10723
|
|
|
10383
10724
|
// src/install/run/run-install.ts
|
|
10384
|
-
import { join as
|
|
10725
|
+
import { join as join75 } from "path";
|
|
10385
10726
|
|
|
10386
10727
|
// src/install/source/git-pin.ts
|
|
10387
10728
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -10515,7 +10856,7 @@ async function confirm(message) {
|
|
|
10515
10856
|
}
|
|
10516
10857
|
|
|
10517
10858
|
// src/install/core/validate-resources.ts
|
|
10518
|
-
import { basename as
|
|
10859
|
+
import { basename as basename32 } from "path";
|
|
10519
10860
|
function validateSkill(skill) {
|
|
10520
10861
|
if (!skill.description.trim()) {
|
|
10521
10862
|
return { skill, ok: false, reason: "missing description in frontmatter" };
|
|
@@ -10541,7 +10882,7 @@ function validateAgent(agent) {
|
|
|
10541
10882
|
return { agent, ok: true };
|
|
10542
10883
|
}
|
|
10543
10884
|
function ruleSlug6(rule) {
|
|
10544
|
-
return
|
|
10885
|
+
return basename32(rule.source).replace(/\.md$/i, "");
|
|
10545
10886
|
}
|
|
10546
10887
|
|
|
10547
10888
|
// src/install/core/pool-resolution.ts
|
|
@@ -11035,7 +11376,7 @@ function ensureInstallSelection(args) {
|
|
|
11035
11376
|
}
|
|
11036
11377
|
|
|
11037
11378
|
// src/install/core/install-extend-entry.ts
|
|
11038
|
-
import { join as
|
|
11379
|
+
import { join as join62 } from "path";
|
|
11039
11380
|
|
|
11040
11381
|
// src/install/core/merge-extend-entry.ts
|
|
11041
11382
|
function assertExtendNameAvailable(extendsList, entry) {
|
|
@@ -11124,7 +11465,7 @@ async function writeInstallAsExtend(args) {
|
|
|
11124
11465
|
${JSON.stringify(entry, null, 2)}`);
|
|
11125
11466
|
return;
|
|
11126
11467
|
}
|
|
11127
|
-
const configPath =
|
|
11468
|
+
const configPath = join62(configDir, "agentsmesh.yaml");
|
|
11128
11469
|
await writeAgentsmeshWithNewExtend(configPath, config, entry);
|
|
11129
11470
|
logger.success(`Wrote extends entry "${entry.name}" to agentsmesh.yaml.`);
|
|
11130
11471
|
}
|
|
@@ -11141,11 +11482,11 @@ function toNewExtendEntry(args) {
|
|
|
11141
11482
|
}
|
|
11142
11483
|
|
|
11143
11484
|
// src/install/run/run-install-pack.ts
|
|
11144
|
-
import { join as
|
|
11485
|
+
import { join as join66 } from "path";
|
|
11145
11486
|
import { rename as rename4 } from "fs/promises";
|
|
11146
11487
|
|
|
11147
11488
|
// src/install/pack/pack-writer.ts
|
|
11148
|
-
import { join as
|
|
11489
|
+
import { join as join63, basename as basename33, dirname as dirname23 } from "path";
|
|
11149
11490
|
import { rm as rm7, rename as rename3, mkdir as mkdir5, copyFile as copyFile2 } from "fs/promises";
|
|
11150
11491
|
import { stringify as yamlStringify6 } from "yaml";
|
|
11151
11492
|
|
|
@@ -11171,41 +11512,41 @@ async function hashPackContent(packDir) {
|
|
|
11171
11512
|
// src/install/pack/pack-writer.ts
|
|
11172
11513
|
async function writeRules(canonical, packDir) {
|
|
11173
11514
|
if (canonical.rules.length === 0) return;
|
|
11174
|
-
const rulesDir =
|
|
11515
|
+
const rulesDir = join63(packDir, "rules");
|
|
11175
11516
|
await mkdirp(rulesDir);
|
|
11176
11517
|
for (const rule of canonical.rules) {
|
|
11177
|
-
const dest =
|
|
11518
|
+
const dest = join63(rulesDir, basename33(rule.source));
|
|
11178
11519
|
await copyFile2(rule.source, dest);
|
|
11179
11520
|
}
|
|
11180
11521
|
}
|
|
11181
11522
|
async function writeCommands(canonical, packDir) {
|
|
11182
11523
|
if (canonical.commands.length === 0) return;
|
|
11183
|
-
const dir =
|
|
11524
|
+
const dir = join63(packDir, "commands");
|
|
11184
11525
|
await mkdirp(dir);
|
|
11185
11526
|
for (const cmd of canonical.commands) {
|
|
11186
|
-
const dest =
|
|
11527
|
+
const dest = join63(dir, basename33(cmd.source));
|
|
11187
11528
|
await copyFile2(cmd.source, dest);
|
|
11188
11529
|
}
|
|
11189
11530
|
}
|
|
11190
11531
|
async function writeAgents(canonical, packDir) {
|
|
11191
11532
|
if (canonical.agents.length === 0) return;
|
|
11192
|
-
const dir =
|
|
11533
|
+
const dir = join63(packDir, "agents");
|
|
11193
11534
|
await mkdirp(dir);
|
|
11194
11535
|
for (const agent of canonical.agents) {
|
|
11195
|
-
const dest =
|
|
11536
|
+
const dest = join63(dir, basename33(agent.source));
|
|
11196
11537
|
await copyFile2(agent.source, dest);
|
|
11197
11538
|
}
|
|
11198
11539
|
}
|
|
11199
11540
|
async function writeSkills(canonical, packDir) {
|
|
11200
11541
|
if (canonical.skills.length === 0) return;
|
|
11201
|
-
const skillsDir =
|
|
11542
|
+
const skillsDir = join63(packDir, "skills");
|
|
11202
11543
|
await mkdirp(skillsDir);
|
|
11203
11544
|
for (const skill of canonical.skills) {
|
|
11204
|
-
const skillDestDir =
|
|
11545
|
+
const skillDestDir = join63(skillsDir, skill.name);
|
|
11205
11546
|
await mkdirp(skillDestDir);
|
|
11206
|
-
await copyFile2(skill.source,
|
|
11547
|
+
await copyFile2(skill.source, join63(skillDestDir, "SKILL.md"));
|
|
11207
11548
|
for (const sf of skill.supportingFiles) {
|
|
11208
|
-
const destPath =
|
|
11549
|
+
const destPath = join63(skillDestDir, sf.relativePath);
|
|
11209
11550
|
await mkdirp(dirname23(destPath));
|
|
11210
11551
|
await copyFile2(sf.absolutePath, destPath);
|
|
11211
11552
|
}
|
|
@@ -11213,23 +11554,23 @@ async function writeSkills(canonical, packDir) {
|
|
|
11213
11554
|
}
|
|
11214
11555
|
async function writeSettings(canonical, packDir) {
|
|
11215
11556
|
if (canonical.mcp !== null) {
|
|
11216
|
-
await writeFileAtomic(
|
|
11557
|
+
await writeFileAtomic(join63(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11217
11558
|
`);
|
|
11218
11559
|
}
|
|
11219
11560
|
if (canonical.permissions !== null) {
|
|
11220
|
-
await writeFileAtomic(
|
|
11561
|
+
await writeFileAtomic(join63(packDir, "permissions.yaml"), yamlStringify6(canonical.permissions));
|
|
11221
11562
|
}
|
|
11222
11563
|
if (canonical.hooks !== null) {
|
|
11223
|
-
await writeFileAtomic(
|
|
11564
|
+
await writeFileAtomic(join63(packDir, "hooks.yaml"), yamlStringify6(canonical.hooks));
|
|
11224
11565
|
}
|
|
11225
11566
|
if (canonical.ignore.length > 0) {
|
|
11226
|
-
await writeFileAtomic(
|
|
11567
|
+
await writeFileAtomic(join63(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11227
11568
|
`);
|
|
11228
11569
|
}
|
|
11229
11570
|
}
|
|
11230
11571
|
async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
11231
|
-
const tmpDir =
|
|
11232
|
-
const finalDir =
|
|
11572
|
+
const tmpDir = join63(packsDir, `${packName}.tmp`);
|
|
11573
|
+
const finalDir = join63(packsDir, packName);
|
|
11233
11574
|
if (await exists(tmpDir)) {
|
|
11234
11575
|
await rm7(tmpDir, { recursive: true, force: true });
|
|
11235
11576
|
}
|
|
@@ -11241,7 +11582,7 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11241
11582
|
await writeSettings(canonical, tmpDir);
|
|
11242
11583
|
const contentHash = await hashPackContent(tmpDir);
|
|
11243
11584
|
const metadata = { ...metadataInput, content_hash: contentHash };
|
|
11244
|
-
await writeFileAtomic(
|
|
11585
|
+
await writeFileAtomic(join63(tmpDir, "pack.yaml"), yamlStringify6(metadata));
|
|
11245
11586
|
if (await exists(finalDir)) {
|
|
11246
11587
|
await rm7(finalDir, { recursive: true, force: true });
|
|
11247
11588
|
}
|
|
@@ -11251,7 +11592,7 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
11251
11592
|
}
|
|
11252
11593
|
|
|
11253
11594
|
// src/install/pack/pack-merge.ts
|
|
11254
|
-
import { join as
|
|
11595
|
+
import { join as join64, basename as basename34, dirname as dirname24 } from "path";
|
|
11255
11596
|
import { copyFile as copyFile3 } from "fs/promises";
|
|
11256
11597
|
import { stringify as yamlStringify7 } from "yaml";
|
|
11257
11598
|
function union(a, b) {
|
|
@@ -11282,38 +11623,38 @@ function mergePick2(existing, newFeatures, newPick) {
|
|
|
11282
11623
|
}
|
|
11283
11624
|
async function mergeRules(canonical, packDir) {
|
|
11284
11625
|
if (canonical.rules.length === 0) return;
|
|
11285
|
-
const dir =
|
|
11626
|
+
const dir = join64(packDir, "rules");
|
|
11286
11627
|
await mkdirp(dir);
|
|
11287
11628
|
for (const rule of canonical.rules) {
|
|
11288
|
-
await copyFile3(rule.source,
|
|
11629
|
+
await copyFile3(rule.source, join64(dir, basename34(rule.source)));
|
|
11289
11630
|
}
|
|
11290
11631
|
}
|
|
11291
11632
|
async function mergeCommands(canonical, packDir) {
|
|
11292
11633
|
if (canonical.commands.length === 0) return;
|
|
11293
|
-
const dir =
|
|
11634
|
+
const dir = join64(packDir, "commands");
|
|
11294
11635
|
await mkdirp(dir);
|
|
11295
11636
|
for (const cmd of canonical.commands) {
|
|
11296
|
-
await copyFile3(cmd.source,
|
|
11637
|
+
await copyFile3(cmd.source, join64(dir, basename34(cmd.source)));
|
|
11297
11638
|
}
|
|
11298
11639
|
}
|
|
11299
11640
|
async function mergeAgents(canonical, packDir) {
|
|
11300
11641
|
if (canonical.agents.length === 0) return;
|
|
11301
|
-
const dir =
|
|
11642
|
+
const dir = join64(packDir, "agents");
|
|
11302
11643
|
await mkdirp(dir);
|
|
11303
11644
|
for (const agent of canonical.agents) {
|
|
11304
|
-
await copyFile3(agent.source,
|
|
11645
|
+
await copyFile3(agent.source, join64(dir, basename34(agent.source)));
|
|
11305
11646
|
}
|
|
11306
11647
|
}
|
|
11307
11648
|
async function mergeSkills(canonical, packDir) {
|
|
11308
11649
|
if (canonical.skills.length === 0) return;
|
|
11309
|
-
const skillsDir =
|
|
11650
|
+
const skillsDir = join64(packDir, "skills");
|
|
11310
11651
|
await mkdirp(skillsDir);
|
|
11311
11652
|
for (const skill of canonical.skills) {
|
|
11312
|
-
const destDir =
|
|
11653
|
+
const destDir = join64(skillsDir, skill.name);
|
|
11313
11654
|
await mkdirp(destDir);
|
|
11314
|
-
await copyFile3(skill.source,
|
|
11655
|
+
await copyFile3(skill.source, join64(destDir, "SKILL.md"));
|
|
11315
11656
|
for (const sf of skill.supportingFiles) {
|
|
11316
|
-
const destPath =
|
|
11657
|
+
const destPath = join64(destDir, sf.relativePath);
|
|
11317
11658
|
await mkdirp(dirname24(destPath));
|
|
11318
11659
|
await copyFile3(sf.absolutePath, destPath);
|
|
11319
11660
|
}
|
|
@@ -11321,17 +11662,17 @@ async function mergeSkills(canonical, packDir) {
|
|
|
11321
11662
|
}
|
|
11322
11663
|
async function mergeSettings(canonical, packDir) {
|
|
11323
11664
|
if (canonical.mcp !== null) {
|
|
11324
|
-
await writeFileAtomic(
|
|
11665
|
+
await writeFileAtomic(join64(packDir, "mcp.json"), `${JSON.stringify(canonical.mcp, null, 2)}
|
|
11325
11666
|
`);
|
|
11326
11667
|
}
|
|
11327
11668
|
if (canonical.permissions !== null) {
|
|
11328
|
-
await writeFileAtomic(
|
|
11669
|
+
await writeFileAtomic(join64(packDir, "permissions.yaml"), yamlStringify7(canonical.permissions));
|
|
11329
11670
|
}
|
|
11330
11671
|
if (canonical.hooks !== null) {
|
|
11331
|
-
await writeFileAtomic(
|
|
11672
|
+
await writeFileAtomic(join64(packDir, "hooks.yaml"), yamlStringify7(canonical.hooks));
|
|
11332
11673
|
}
|
|
11333
11674
|
if (canonical.ignore.length > 0) {
|
|
11334
|
-
await writeFileAtomic(
|
|
11675
|
+
await writeFileAtomic(join64(packDir, "ignore"), `${canonical.ignore.join("\n")}
|
|
11335
11676
|
`);
|
|
11336
11677
|
}
|
|
11337
11678
|
}
|
|
@@ -11358,12 +11699,12 @@ async function mergeIntoPack(packDir, existingMeta, newCanonical, newFeatures, n
|
|
|
11358
11699
|
updated_at: updatedAt,
|
|
11359
11700
|
content_hash: contentHash
|
|
11360
11701
|
};
|
|
11361
|
-
await writeFileAtomic(
|
|
11702
|
+
await writeFileAtomic(join64(packDir, "pack.yaml"), yamlStringify7(updatedMeta));
|
|
11362
11703
|
return updatedMeta;
|
|
11363
11704
|
}
|
|
11364
11705
|
|
|
11365
11706
|
// src/install/core/install-manifest.ts
|
|
11366
|
-
import { join as
|
|
11707
|
+
import { join as join65 } from "path";
|
|
11367
11708
|
import { parse as parseYaml8, stringify as yamlStringify8 } from "yaml";
|
|
11368
11709
|
import { z as z4 } from "zod";
|
|
11369
11710
|
var installManifestEntrySchema = z4.object({
|
|
@@ -11389,7 +11730,7 @@ function sameInstallIdentity(a, b) {
|
|
|
11389
11730
|
return a.source === b.source && a.target === b.target && a.as === b.as && sameFeatures2(a.features, b.features);
|
|
11390
11731
|
}
|
|
11391
11732
|
function manifestPath(configDir) {
|
|
11392
|
-
return
|
|
11733
|
+
return join65(configDir, ".agentsmesh", "installs.yaml");
|
|
11393
11734
|
}
|
|
11394
11735
|
async function readInstallManifest(configDir) {
|
|
11395
11736
|
const content = await readFileSafe(manifestPath(configDir));
|
|
@@ -11462,7 +11803,7 @@ async function installAsPack(args) {
|
|
|
11462
11803
|
manualAs,
|
|
11463
11804
|
renameExistingPack
|
|
11464
11805
|
} = args;
|
|
11465
|
-
const packsDir =
|
|
11806
|
+
const packsDir = join66(configDir, ".agentsmesh", "packs");
|
|
11466
11807
|
const selectedCanonical = applySelection(narrowed, selected);
|
|
11467
11808
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
11468
11809
|
const parsedTarget = yamlTarget !== void 0 ? targetSchema.parse(yamlTarget) : void 0;
|
|
@@ -11480,7 +11821,7 @@ async function installAsPack(args) {
|
|
|
11480
11821
|
let packDir = existingPack.packDir;
|
|
11481
11822
|
let packMeta = existingPack.meta;
|
|
11482
11823
|
if (renameExistingPack && existingPack.name !== packName) {
|
|
11483
|
-
const nextDir =
|
|
11824
|
+
const nextDir = join66(packsDir, packName);
|
|
11484
11825
|
if (await exists(nextDir)) {
|
|
11485
11826
|
throw new Error(
|
|
11486
11827
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11511,7 +11852,7 @@ async function installAsPack(args) {
|
|
|
11511
11852
|
persistedPaths = mergedMeta.paths;
|
|
11512
11853
|
logger.success(`Updated pack "${mergedMeta.name}" in .agentsmesh/packs/.`);
|
|
11513
11854
|
} else {
|
|
11514
|
-
const collidingMeta = await readPackMetadata(
|
|
11855
|
+
const collidingMeta = await readPackMetadata(join66(packsDir, packName));
|
|
11515
11856
|
if (collidingMeta) {
|
|
11516
11857
|
throw new Error(
|
|
11517
11858
|
`Auto-generated pack name "${packName}" collides with an existing incompatible pack. Use --name to choose a different pack name.`
|
|
@@ -11553,7 +11894,7 @@ async function installAsPack(args) {
|
|
|
11553
11894
|
}
|
|
11554
11895
|
|
|
11555
11896
|
// src/install/run/install-sync.ts
|
|
11556
|
-
import { join as
|
|
11897
|
+
import { join as join67 } from "path";
|
|
11557
11898
|
async function syncInstalledPacks(args) {
|
|
11558
11899
|
const installs = await readInstallManifest(args.configDir);
|
|
11559
11900
|
if (installs.length === 0) {
|
|
@@ -11562,7 +11903,7 @@ async function syncInstalledPacks(args) {
|
|
|
11562
11903
|
}
|
|
11563
11904
|
const missing = [];
|
|
11564
11905
|
for (const entry of installs) {
|
|
11565
|
-
const packDir =
|
|
11906
|
+
const packDir = join67(args.configDir, ".agentsmesh", "packs", entry.name);
|
|
11566
11907
|
if (!await exists(packDir)) {
|
|
11567
11908
|
missing.push(entry);
|
|
11568
11909
|
}
|
|
@@ -11740,7 +12081,7 @@ function narrowDiscoveredForInstallScope(canonical, options) {
|
|
|
11740
12081
|
}
|
|
11741
12082
|
|
|
11742
12083
|
// src/install/manual/manual-install-scope.ts
|
|
11743
|
-
import { basename as
|
|
12084
|
+
import { basename as basename35, dirname as dirname25, join as join68, relative as relative27 } from "path";
|
|
11744
12085
|
import { cp as cp2, mkdtemp, stat as stat5, rm as rm8 } from "fs/promises";
|
|
11745
12086
|
import { tmpdir } from "os";
|
|
11746
12087
|
|
|
@@ -11800,9 +12141,9 @@ async function cpFilteredSkill(sourceRoot, destDir) {
|
|
|
11800
12141
|
|
|
11801
12142
|
// src/install/manual/manual-install-scope.ts
|
|
11802
12143
|
async function createStageRoot() {
|
|
11803
|
-
const stageBase = await mkdtemp(
|
|
11804
|
-
const discoveryRoot =
|
|
11805
|
-
await mkdirp(
|
|
12144
|
+
const stageBase = await mkdtemp(join68(tmpdir(), "am-install-manual-"));
|
|
12145
|
+
const discoveryRoot = join68(stageBase, "repo");
|
|
12146
|
+
await mkdirp(join68(discoveryRoot, ".agentsmesh"));
|
|
11806
12147
|
return {
|
|
11807
12148
|
discoveryRoot,
|
|
11808
12149
|
cleanup: async () => {
|
|
@@ -11817,7 +12158,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
11817
12158
|
throw new Error(`Manual install only supports .md files for this collection: ${sourceRoot}`);
|
|
11818
12159
|
}
|
|
11819
12160
|
await mkdirp(destinationDir);
|
|
11820
|
-
await cp2(sourceRoot,
|
|
12161
|
+
await cp2(sourceRoot, join68(destinationDir, basename35(sourceRoot)));
|
|
11821
12162
|
return;
|
|
11822
12163
|
}
|
|
11823
12164
|
const files = (await readDirRecursive(sourceRoot)).filter(
|
|
@@ -11829,7 +12170,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
11829
12170
|
const usedNames = /* @__PURE__ */ new Map();
|
|
11830
12171
|
await mkdirp(destinationDir);
|
|
11831
12172
|
for (const file of files) {
|
|
11832
|
-
const name =
|
|
12173
|
+
const name = basename35(file);
|
|
11833
12174
|
const previous = usedNames.get(name);
|
|
11834
12175
|
if (previous) {
|
|
11835
12176
|
throw new Error(
|
|
@@ -11837,7 +12178,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
11837
12178
|
);
|
|
11838
12179
|
}
|
|
11839
12180
|
usedNames.set(name, file);
|
|
11840
|
-
await cp2(file,
|
|
12181
|
+
await cp2(file, join68(destinationDir, name));
|
|
11841
12182
|
}
|
|
11842
12183
|
}
|
|
11843
12184
|
async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNames) {
|
|
@@ -11849,7 +12190,7 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
11849
12190
|
for (const file of await readDirRecursive(sourceRoot)) {
|
|
11850
12191
|
if (!file.endsWith("/SKILL.md") && !file.endsWith("\\SKILL.md")) continue;
|
|
11851
12192
|
const skillDir = dirname25(file);
|
|
11852
|
-
const skillName =
|
|
12193
|
+
const skillName = basename35(skillDir);
|
|
11853
12194
|
if (!wanted.has(skillName)) continue;
|
|
11854
12195
|
const previous = matches.get(skillName);
|
|
11855
12196
|
if (previous && previous !== skillDir) {
|
|
@@ -11862,30 +12203,30 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
11862
12203
|
if (matches.size !== preferredSkillNames.length) return false;
|
|
11863
12204
|
await mkdirp(destinationDir);
|
|
11864
12205
|
for (const skillName of preferredSkillNames) {
|
|
11865
|
-
await cp2(matches.get(skillName),
|
|
12206
|
+
await cp2(matches.get(skillName), join68(destinationDir, skillName), { recursive: true });
|
|
11866
12207
|
}
|
|
11867
12208
|
return true;
|
|
11868
12209
|
}
|
|
11869
12210
|
async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
11870
12211
|
const info = await stat5(sourceRoot);
|
|
11871
12212
|
if (info.isFile()) {
|
|
11872
|
-
if (
|
|
12213
|
+
if (basename35(sourceRoot) !== "SKILL.md") {
|
|
11873
12214
|
throw new Error(`Manual skill install expects SKILL.md or a skill directory: ${sourceRoot}`);
|
|
11874
12215
|
}
|
|
11875
|
-
const skillName =
|
|
11876
|
-
const skillDir =
|
|
12216
|
+
const skillName = basename35(dirname25(sourceRoot));
|
|
12217
|
+
const skillDir = join68(destinationDir, skillName);
|
|
11877
12218
|
await mkdirp(skillDir);
|
|
11878
12219
|
await cp2(dirname25(sourceRoot), skillDir, { recursive: true });
|
|
11879
12220
|
return;
|
|
11880
12221
|
}
|
|
11881
12222
|
if (await isSkillPackLayout(sourceRoot)) {
|
|
11882
|
-
if ((await stat5(
|
|
12223
|
+
if ((await stat5(join68(sourceRoot, "SKILL.md")).catch(() => null))?.isFile()) {
|
|
11883
12224
|
if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
|
|
11884
12225
|
return;
|
|
11885
12226
|
}
|
|
11886
|
-
const fmName = await readSkillFrontmatterName(
|
|
11887
|
-
const skillName = fmName ||
|
|
11888
|
-
const skillDir =
|
|
12227
|
+
const fmName = await readSkillFrontmatterName(join68(sourceRoot, "SKILL.md"));
|
|
12228
|
+
const skillName = fmName || basename35(sourceRoot);
|
|
12229
|
+
const skillDir = join68(destinationDir, skillName);
|
|
11889
12230
|
await mkdirp(destinationDir);
|
|
11890
12231
|
await cpFilteredSkill(sourceRoot, skillDir);
|
|
11891
12232
|
return;
|
|
@@ -11902,7 +12243,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
11902
12243
|
roots.add(relative27(sourceRoot, dirname25(file)).split(/[\\/]/)[0]);
|
|
11903
12244
|
}
|
|
11904
12245
|
for (const root of roots) {
|
|
11905
|
-
await cp2(
|
|
12246
|
+
await cp2(join68(sourceRoot, root), join68(destinationDir, root), { recursive: true });
|
|
11906
12247
|
}
|
|
11907
12248
|
return;
|
|
11908
12249
|
}
|
|
@@ -11913,7 +12254,7 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
11913
12254
|
async function stageManualInstallScope(sourceRoot, as, options = {}) {
|
|
11914
12255
|
const staged = await createStageRoot();
|
|
11915
12256
|
try {
|
|
11916
|
-
const destDir =
|
|
12257
|
+
const destDir = join68(staged.discoveryRoot, ".agentsmesh", as);
|
|
11917
12258
|
if (as === "skills") {
|
|
11918
12259
|
await stageSkills(sourceRoot, destDir, options);
|
|
11919
12260
|
} else {
|
|
@@ -11947,7 +12288,7 @@ async function resolveManualDiscoveredForInstall(sourceRoot, explicitAs, explici
|
|
|
11947
12288
|
}
|
|
11948
12289
|
|
|
11949
12290
|
// src/install/core/prepare-install-discovery.ts
|
|
11950
|
-
import { join as
|
|
12291
|
+
import { join as join73 } from "path";
|
|
11951
12292
|
|
|
11952
12293
|
// src/install/native/native-path-pick.ts
|
|
11953
12294
|
var PATH_PREFIX_TO_TARGET = [
|
|
@@ -11985,14 +12326,14 @@ function norm(p) {
|
|
|
11985
12326
|
function targetHintFromNativePath(pathInRepoPosix) {
|
|
11986
12327
|
const p = norm(pathInRepoPosix);
|
|
11987
12328
|
const sorted = [...PATH_PREFIX_TO_TARGET].sort((a, b) => b.prefix.length - a.prefix.length);
|
|
11988
|
-
for (const { prefix, target:
|
|
11989
|
-
if (p === prefix || p.startsWith(`${prefix}/`)) return
|
|
12329
|
+
for (const { prefix, target: target12 } of sorted) {
|
|
12330
|
+
if (p === prefix || p.startsWith(`${prefix}/`)) return target12;
|
|
11990
12331
|
}
|
|
11991
12332
|
return void 0;
|
|
11992
12333
|
}
|
|
11993
|
-
function pathSupportsNativePick(pathInRepoPosix,
|
|
12334
|
+
function pathSupportsNativePick(pathInRepoPosix, target12) {
|
|
11994
12335
|
const hint = targetHintFromNativePath(pathInRepoPosix);
|
|
11995
|
-
return hint ===
|
|
12336
|
+
return hint === target12;
|
|
11996
12337
|
}
|
|
11997
12338
|
function validateTargetMatchesPath(explicitTarget, pathInRepoPosix) {
|
|
11998
12339
|
if (!explicitTarget || !pathInRepoPosix) return;
|
|
@@ -12008,13 +12349,13 @@ function extendPickHasArrays(p) {
|
|
|
12008
12349
|
}
|
|
12009
12350
|
|
|
12010
12351
|
// src/install/native/native-path-pick-infer.ts
|
|
12011
|
-
import { basename as
|
|
12352
|
+
import { basename as basename38, join as join71 } from "path";
|
|
12012
12353
|
|
|
12013
12354
|
// src/install/native/gemini-install-commands.ts
|
|
12014
|
-
import { join as
|
|
12355
|
+
import { join as join69, relative as relative28 } from "path";
|
|
12015
12356
|
async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
12016
|
-
const commandsRoot =
|
|
12017
|
-
const scanDir =
|
|
12357
|
+
const commandsRoot = join69(repoRoot, ...GEMINI_COMMANDS_DIR.split("/"));
|
|
12358
|
+
const scanDir = join69(repoRoot, ...pathInRepoPosix.split("/"));
|
|
12018
12359
|
const files = await readDirRecursive(scanDir);
|
|
12019
12360
|
const names = [];
|
|
12020
12361
|
for (const f of files) {
|
|
@@ -12029,32 +12370,32 @@ async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
|
12029
12370
|
}
|
|
12030
12371
|
|
|
12031
12372
|
// src/install/native/native-skill-scan.ts
|
|
12032
|
-
import { basename as
|
|
12373
|
+
import { basename as basename36, dirname as dirname26, relative as relative29 } from "path";
|
|
12033
12374
|
async function skillNamesFromNativeSkillDir(scanRoot) {
|
|
12034
12375
|
const files = await readDirRecursive(scanRoot);
|
|
12035
12376
|
const names = /* @__PURE__ */ new Set();
|
|
12036
12377
|
for (const f of files) {
|
|
12037
|
-
if (
|
|
12038
|
-
names.add(
|
|
12378
|
+
if (basename36(f) === "SKILL.md") {
|
|
12379
|
+
names.add(basename36(dirname26(f)));
|
|
12039
12380
|
continue;
|
|
12040
12381
|
}
|
|
12041
12382
|
const rel2 = relative29(scanRoot, f).replace(/\\/g, "/");
|
|
12042
12383
|
if (!rel2.includes("/") && f.toLowerCase().endsWith(".md")) {
|
|
12043
|
-
names.add(
|
|
12384
|
+
names.add(basename36(f, ".md"));
|
|
12044
12385
|
}
|
|
12045
12386
|
}
|
|
12046
12387
|
return [...names].filter(Boolean).sort();
|
|
12047
12388
|
}
|
|
12048
12389
|
|
|
12049
12390
|
// src/install/native/native-path-pick-infer-copilot.ts
|
|
12050
|
-
import { basename as
|
|
12391
|
+
import { basename as basename37, join as join70 } from "path";
|
|
12051
12392
|
async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
12052
|
-
const scan =
|
|
12393
|
+
const scan = join70(repoRoot, ...posixPath.split("/"));
|
|
12053
12394
|
if (posixPath.startsWith(COPILOT_PROMPTS_DIR)) {
|
|
12054
12395
|
const files = await readDirRecursive(scan);
|
|
12055
12396
|
const commands = [
|
|
12056
12397
|
...new Set(
|
|
12057
|
-
files.filter((f) => f.toLowerCase().endsWith(".prompt.md")).map((f) =>
|
|
12398
|
+
files.filter((f) => f.toLowerCase().endsWith(".prompt.md")).map((f) => basename37(f, ".prompt.md"))
|
|
12058
12399
|
)
|
|
12059
12400
|
].sort();
|
|
12060
12401
|
return commands.length ? { commands } : {};
|
|
@@ -12063,7 +12404,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12063
12404
|
const files = await readDirRecursive(scan);
|
|
12064
12405
|
const rules = [
|
|
12065
12406
|
...new Set(
|
|
12066
|
-
files.filter((f) => f.includes(".instructions.md")).map((f) =>
|
|
12407
|
+
files.filter((f) => f.includes(".instructions.md")).map((f) => basename37(f).replace(/\.instructions\.md$/i, ""))
|
|
12067
12408
|
)
|
|
12068
12409
|
].sort();
|
|
12069
12410
|
return rules.length ? { rules } : {};
|
|
@@ -12072,10 +12413,10 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12072
12413
|
const files = await readDirRecursive(scan);
|
|
12073
12414
|
const names = /* @__PURE__ */ new Set();
|
|
12074
12415
|
for (const f of files) {
|
|
12075
|
-
const b =
|
|
12416
|
+
const b = basename37(f);
|
|
12076
12417
|
if (b.toLowerCase().endsWith(".instructions.md"))
|
|
12077
12418
|
names.add(b.replace(/\.instructions\.md$/i, ""));
|
|
12078
|
-
else if (b.toLowerCase().endsWith(".md")) names.add(
|
|
12419
|
+
else if (b.toLowerCase().endsWith(".md")) names.add(basename37(f, ".md"));
|
|
12079
12420
|
}
|
|
12080
12421
|
const rules = [...names].sort();
|
|
12081
12422
|
return rules.length ? { rules } : {};
|
|
@@ -12088,7 +12429,7 @@ async function inferCopilotPickFromPath(repoRoot, posixPath) {
|
|
|
12088
12429
|
const files = await readDirRecursive(scan);
|
|
12089
12430
|
const agents = [
|
|
12090
12431
|
...new Set(
|
|
12091
|
-
files.filter((f) => f.toLowerCase().endsWith(".agent.md")).map((f) =>
|
|
12432
|
+
files.filter((f) => f.toLowerCase().endsWith(".agent.md")).map((f) => basename37(f, ".agent.md"))
|
|
12092
12433
|
)
|
|
12093
12434
|
].sort();
|
|
12094
12435
|
return agents.length ? { agents } : {};
|
|
@@ -12101,20 +12442,20 @@ async function mdNames(dir, ext) {
|
|
|
12101
12442
|
const files = await readDirRecursive(dir);
|
|
12102
12443
|
const e = ext.toLowerCase();
|
|
12103
12444
|
return [
|
|
12104
|
-
...new Set(files.filter((f) => f.toLowerCase().endsWith(e)).map((f) =>
|
|
12445
|
+
...new Set(files.filter((f) => f.toLowerCase().endsWith(e)).map((f) => basename38(f, ext)))
|
|
12105
12446
|
].sort();
|
|
12106
12447
|
}
|
|
12107
|
-
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix,
|
|
12448
|
+
async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target12) {
|
|
12108
12449
|
const posixPath = pathInRepoPosix.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12109
|
-
const scan =
|
|
12110
|
-
if (
|
|
12450
|
+
const scan = join71(repoRoot, ...posixPath.split("/"));
|
|
12451
|
+
if (target12 === "gemini-cli") {
|
|
12111
12452
|
if (posixPath === GEMINI_COMMANDS_DIR || posixPath.startsWith(`${GEMINI_COMMANDS_DIR}/`)) {
|
|
12112
12453
|
const commands = await inferGeminiCommandNamesFromFiles(repoRoot, posixPath);
|
|
12113
12454
|
return commands.length ? { commands } : {};
|
|
12114
12455
|
}
|
|
12115
12456
|
return {};
|
|
12116
12457
|
}
|
|
12117
|
-
if (
|
|
12458
|
+
if (target12 === "claude-code") {
|
|
12118
12459
|
if (posixPath.startsWith(".claude/commands")) {
|
|
12119
12460
|
const commands = await mdNames(scan, ".md");
|
|
12120
12461
|
return commands.length ? { commands } : {};
|
|
@@ -12134,7 +12475,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12134
12475
|
}
|
|
12135
12476
|
return {};
|
|
12136
12477
|
}
|
|
12137
|
-
if (
|
|
12478
|
+
if (target12 === "cursor") {
|
|
12138
12479
|
if (posixPath.startsWith(".cursor/rules")) {
|
|
12139
12480
|
const rules = await mdNames(scan, ".mdc");
|
|
12140
12481
|
return rules.length ? { rules } : {};
|
|
@@ -12153,14 +12494,14 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12153
12494
|
}
|
|
12154
12495
|
return {};
|
|
12155
12496
|
}
|
|
12156
|
-
if (
|
|
12497
|
+
if (target12 === "copilot") {
|
|
12157
12498
|
return inferCopilotPickFromPath(repoRoot, posixPath);
|
|
12158
12499
|
}
|
|
12159
|
-
if (
|
|
12500
|
+
if (target12 === "windsurf" && posixPath.startsWith(".windsurf/rules")) {
|
|
12160
12501
|
const rules = await mdNames(scan, ".md");
|
|
12161
12502
|
return rules.length ? { rules } : {};
|
|
12162
12503
|
}
|
|
12163
|
-
if (
|
|
12504
|
+
if (target12 === "cline") {
|
|
12164
12505
|
if (posixPath.startsWith(CLINE_SKILLS_DIR)) {
|
|
12165
12506
|
const skills = await skillNamesFromNativeSkillDir(scan);
|
|
12166
12507
|
return skills.length ? { skills } : {};
|
|
@@ -12171,7 +12512,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12171
12512
|
}
|
|
12172
12513
|
return {};
|
|
12173
12514
|
}
|
|
12174
|
-
if (
|
|
12515
|
+
if (target12 === "continue") {
|
|
12175
12516
|
if (posixPath.startsWith(".continue/rules")) {
|
|
12176
12517
|
const rules = await mdNames(scan, ".md");
|
|
12177
12518
|
return rules.length ? { rules } : {};
|
|
@@ -12186,7 +12527,7 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12186
12527
|
}
|
|
12187
12528
|
return {};
|
|
12188
12529
|
}
|
|
12189
|
-
if (
|
|
12530
|
+
if (target12 === "junie") {
|
|
12190
12531
|
if (posixPath.startsWith(".junie/commands")) {
|
|
12191
12532
|
const commands = await mdNames(scan, ".md");
|
|
12192
12533
|
return commands.length ? { commands } : {};
|
|
@@ -12205,11 +12546,11 @@ async function inferImplicitPickFromNativePath(repoRoot, pathInRepoPosix, target
|
|
|
12205
12546
|
}
|
|
12206
12547
|
return {};
|
|
12207
12548
|
}
|
|
12208
|
-
if (
|
|
12549
|
+
if (target12 === "codex-cli" && posixPath.startsWith(".codex")) {
|
|
12209
12550
|
const files = await readDirRecursive(scan);
|
|
12210
12551
|
const rules = [
|
|
12211
12552
|
...new Set(
|
|
12212
|
-
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) =>
|
|
12553
|
+
files.filter((f) => f.toLowerCase().endsWith(".md")).map((f) => basename38(f, ".md"))
|
|
12213
12554
|
)
|
|
12214
12555
|
].sort();
|
|
12215
12556
|
return rules.length ? { rules } : {};
|
|
@@ -12221,7 +12562,7 @@ function isImplicitPickEmpty(p) {
|
|
|
12221
12562
|
}
|
|
12222
12563
|
|
|
12223
12564
|
// src/install/native/native-install-scope.ts
|
|
12224
|
-
import { basename as
|
|
12565
|
+
import { basename as basename39, join as join72, relative as relative30 } from "path";
|
|
12225
12566
|
import { cp as cp3, mkdtemp as mkdtemp2, rm as rm9 } from "fs/promises";
|
|
12226
12567
|
import { tmpdir as tmpdir2 } from "os";
|
|
12227
12568
|
function normalizePath3(path) {
|
|
@@ -12232,14 +12573,14 @@ function overlapsPath(requested, imported) {
|
|
|
12232
12573
|
const b = normalizePath3(imported);
|
|
12233
12574
|
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
12234
12575
|
}
|
|
12235
|
-
function addUnique(
|
|
12236
|
-
const next =
|
|
12576
|
+
function addUnique(target12, value) {
|
|
12577
|
+
const next = target12 ?? [];
|
|
12237
12578
|
if (!next.includes(value)) next.push(value);
|
|
12238
12579
|
return next;
|
|
12239
12580
|
}
|
|
12240
12581
|
async function makeStageRoot(repoRoot) {
|
|
12241
|
-
const stageBase = await mkdtemp2(
|
|
12242
|
-
const stageRoot =
|
|
12582
|
+
const stageBase = await mkdtemp2(join72(tmpdir2(), "am-install-native-"));
|
|
12583
|
+
const stageRoot = join72(stageBase, "repo");
|
|
12243
12584
|
const cleanup = async () => {
|
|
12244
12585
|
await rm9(stageBase, { recursive: true, force: true });
|
|
12245
12586
|
};
|
|
@@ -12257,13 +12598,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12257
12598
|
if (result.feature === "rules" && result.toPath.startsWith(".agentsmesh/rules/")) {
|
|
12258
12599
|
pick = {
|
|
12259
12600
|
...pick,
|
|
12260
|
-
rules: addUnique(pick?.rules,
|
|
12601
|
+
rules: addUnique(pick?.rules, basename39(result.toPath, ".md"))
|
|
12261
12602
|
};
|
|
12262
12603
|
continue;
|
|
12263
12604
|
}
|
|
12264
12605
|
if (result.feature === "commands" && result.toPath.startsWith(".agentsmesh/commands/")) {
|
|
12265
12606
|
const rel2 = normalizePath3(
|
|
12266
|
-
relative30(
|
|
12607
|
+
relative30(join72(stageRoot, ".agentsmesh", "commands"), join72(stageRoot, result.toPath))
|
|
12267
12608
|
);
|
|
12268
12609
|
pick = {
|
|
12269
12610
|
...pick,
|
|
@@ -12277,13 +12618,13 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12277
12618
|
if (result.feature === "agents" && result.toPath.startsWith(".agentsmesh/agents/")) {
|
|
12278
12619
|
pick = {
|
|
12279
12620
|
...pick,
|
|
12280
|
-
agents: addUnique(pick?.agents,
|
|
12621
|
+
agents: addUnique(pick?.agents, basename39(result.toPath, ".md"))
|
|
12281
12622
|
};
|
|
12282
12623
|
continue;
|
|
12283
12624
|
}
|
|
12284
12625
|
if (result.feature === "skills" && result.toPath.startsWith(".agentsmesh/skills/")) {
|
|
12285
12626
|
const rel2 = normalizePath3(
|
|
12286
|
-
relative30(
|
|
12627
|
+
relative30(join72(stageRoot, ".agentsmesh", "skills"), join72(stageRoot, result.toPath))
|
|
12287
12628
|
);
|
|
12288
12629
|
const skillName = rel2.split("/")[0];
|
|
12289
12630
|
if (skillName) {
|
|
@@ -12298,12 +12639,12 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
12298
12639
|
const hasAny = (pick.rules?.length ?? 0) + (pick.commands?.length ?? 0) + (pick.agents?.length ?? 0) + (pick.skills?.length ?? 0) > 0;
|
|
12299
12640
|
return hasAny ? pick : void 0;
|
|
12300
12641
|
}
|
|
12301
|
-
function scopeImportedResults(pathInRepoPosix, stageRoot, results,
|
|
12302
|
-
const requestedPath =
|
|
12642
|
+
function scopeImportedResults(pathInRepoPosix, stageRoot, results, target12) {
|
|
12643
|
+
const requestedPath = join72(stageRoot, ...normalizePath3(pathInRepoPosix).split("/"));
|
|
12303
12644
|
const filtered = results.filter((result) => overlapsPath(requestedPath, result.fromPath));
|
|
12304
12645
|
if (filtered.length === 0) {
|
|
12305
12646
|
throw new Error(
|
|
12306
|
-
`No installable native resources found under "${pathInRepoPosix}" for target "${
|
|
12647
|
+
`No installable native resources found under "${pathInRepoPosix}" for target "${target12}".`
|
|
12307
12648
|
);
|
|
12308
12649
|
}
|
|
12309
12650
|
return {
|
|
@@ -12311,23 +12652,23 @@ function scopeImportedResults(pathInRepoPosix, stageRoot, results, target11) {
|
|
|
12311
12652
|
pick: buildPickFromResults(filtered, stageRoot)
|
|
12312
12653
|
};
|
|
12313
12654
|
}
|
|
12314
|
-
async function stageImportedNativeRepo(repoRoot,
|
|
12655
|
+
async function stageImportedNativeRepo(repoRoot, target12) {
|
|
12315
12656
|
const { stageRoot, cleanup } = await makeStageRoot(repoRoot);
|
|
12316
12657
|
try {
|
|
12317
|
-
const results = await importNativeToCanonical(stageRoot,
|
|
12658
|
+
const results = await importNativeToCanonical(stageRoot, target12);
|
|
12318
12659
|
return { stageRoot, results, cleanup };
|
|
12319
12660
|
} catch (error) {
|
|
12320
12661
|
await cleanup();
|
|
12321
12662
|
throw error;
|
|
12322
12663
|
}
|
|
12323
12664
|
}
|
|
12324
|
-
async function stageNativeInstallScope(repoRoot, pathInRepoPosix,
|
|
12325
|
-
const staged = await stageImportedNativeRepo(repoRoot,
|
|
12665
|
+
async function stageNativeInstallScope(repoRoot, pathInRepoPosix, target12) {
|
|
12666
|
+
const staged = await stageImportedNativeRepo(repoRoot, target12);
|
|
12326
12667
|
try {
|
|
12327
12668
|
return {
|
|
12328
12669
|
stageRoot: staged.stageRoot,
|
|
12329
12670
|
cleanup: staged.cleanup,
|
|
12330
|
-
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results,
|
|
12671
|
+
...scopeImportedResults(pathInRepoPosix, staged.stageRoot, staged.results, target12)
|
|
12331
12672
|
};
|
|
12332
12673
|
} catch (error) {
|
|
12333
12674
|
await staged.cleanup();
|
|
@@ -12343,7 +12684,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12343
12684
|
}
|
|
12344
12685
|
const posixPath = pathInRepo.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
12345
12686
|
validateTargetMatchesPath(explicitTarget, posixPath);
|
|
12346
|
-
const agentsmeshAtRoot =
|
|
12687
|
+
const agentsmeshAtRoot = join73(repoRoot, ".agentsmesh");
|
|
12347
12688
|
const hasAbRoot = await exists(agentsmeshAtRoot);
|
|
12348
12689
|
const pathHint = posixPath ? targetHintFromNativePath(posixPath) : void 0;
|
|
12349
12690
|
const detectedTarget = !hasAbRoot && !explicitTarget ? await detectNativeFormat(repoRoot) ?? void 0 : void 0;
|
|
@@ -12368,7 +12709,7 @@ async function prepareInstallDiscovery(repoRoot, contentRoot, pathInRepo, option
|
|
|
12368
12709
|
}
|
|
12369
12710
|
const staged = await stageImportedNativeRepo(repoRoot, effectiveTarget);
|
|
12370
12711
|
return {
|
|
12371
|
-
discoveryRoot: posixPath ?
|
|
12712
|
+
discoveryRoot: posixPath ? join73(staged.stageRoot, posixPath) : staged.stageRoot,
|
|
12372
12713
|
yamlTarget: effectiveTarget,
|
|
12373
12714
|
importHappened: true,
|
|
12374
12715
|
cleanup: staged.cleanup
|
|
@@ -12471,13 +12812,13 @@ function applyReplayInstallScope(narrowed, discoveredFeatures, replay) {
|
|
|
12471
12812
|
}
|
|
12472
12813
|
|
|
12473
12814
|
// src/install/manual/manual-install-persistence.ts
|
|
12474
|
-
import { basename as
|
|
12815
|
+
import { basename as basename40, dirname as dirname27, join as join74 } from "path";
|
|
12475
12816
|
import { stat as stat6 } from "fs/promises";
|
|
12476
12817
|
function trimDot(pathInRepo) {
|
|
12477
12818
|
return pathInRepo === "." || pathInRepo === "" ? void 0 : pathInRepo;
|
|
12478
12819
|
}
|
|
12479
12820
|
function markdownPick(as, pathValue) {
|
|
12480
|
-
const name =
|
|
12821
|
+
const name = basename40(pathValue).replace(/\.md$/i, "");
|
|
12481
12822
|
if (as === "agents") return { agents: [name] };
|
|
12482
12823
|
if (as === "commands") return { commands: [name] };
|
|
12483
12824
|
return { rules: [name] };
|
|
@@ -12495,23 +12836,23 @@ async function resolveManualInstallPersistence(args) {
|
|
|
12495
12836
|
};
|
|
12496
12837
|
}
|
|
12497
12838
|
if (args.as === "skills") {
|
|
12498
|
-
if (info.isFile() &&
|
|
12839
|
+
if (info.isFile() && basename40(args.contentRoot) === "SKILL.md") {
|
|
12499
12840
|
const skillDir = normalizedPath ? dirname27(normalizedPath) : dirname27(args.contentRoot);
|
|
12500
12841
|
return {
|
|
12501
12842
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12502
|
-
pick: { skills: [
|
|
12843
|
+
pick: { skills: [basename40(skillDir)] }
|
|
12503
12844
|
};
|
|
12504
12845
|
}
|
|
12505
12846
|
if (info.isDirectory()) {
|
|
12506
|
-
const skillDir = normalizedPath ||
|
|
12507
|
-
const skillFile =
|
|
12847
|
+
const skillDir = normalizedPath || basename40(args.contentRoot);
|
|
12848
|
+
const skillFile = join74(args.contentRoot.replace(/\/+$/g, ""), "SKILL.md");
|
|
12508
12849
|
try {
|
|
12509
12850
|
const skillStat = await stat6(skillFile);
|
|
12510
12851
|
if (skillStat.isFile()) {
|
|
12511
12852
|
const fmName = await readSkillFrontmatterName(skillFile);
|
|
12512
12853
|
return {
|
|
12513
12854
|
pathInRepo: trimDot(dirname27(skillDir)),
|
|
12514
|
-
pick: { skills: [fmName ||
|
|
12855
|
+
pick: { skills: [fmName || basename40(skillDir)] }
|
|
12515
12856
|
};
|
|
12516
12857
|
}
|
|
12517
12858
|
} catch {
|
|
@@ -12579,7 +12920,7 @@ async function runInstall(flags, args, projectRoot, replay) {
|
|
|
12579
12920
|
sourceArg
|
|
12580
12921
|
);
|
|
12581
12922
|
const pathInRepo = parsed.pathInRepo.replace(/^\/+|\/+$/g, "");
|
|
12582
|
-
const contentRoot = pathInRepo ?
|
|
12923
|
+
const contentRoot = pathInRepo ? join75(resolvedPath, pathInRepo) : resolvedPath;
|
|
12583
12924
|
if (!await exists(contentRoot)) {
|
|
12584
12925
|
throw new Error(`Install path does not exist: ${contentRoot}`);
|
|
12585
12926
|
}
|