agentsmesh 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/canonical.js +103 -129
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +130 -130
- package/dist/engine.js +103 -129
- package/dist/engine.js.map +1 -1
- package/dist/index.js +103 -129
- package/dist/index.js.map +1 -1
- package/dist/targets.js +103 -129
- package/dist/targets.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.18.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d7e3a19: Internal refactor of the skill-import dispatch path and watch-test determinism — no user-visible behavior change.
|
|
8
|
+
|
|
9
|
+
**`agentsmesh import` (Cline / Windsurf / Codex CLI)**
|
|
10
|
+
|
|
11
|
+
The per-target `readdir → readFileSafe(SKILL.md) → try recognizer → fall back to skill import` loops, which had drifted independently and kept causing the same class of bug (lessons L132), are consolidated behind one shared orchestrator: `importSkillsDirectory(sourceSkillsDirs, options, recognizers)` plus `projectedAgentRecognizer({ canonicalAgentsDir })` and `commandSkillRecognizer({ canonicalCommandsDir })` factories. Each adapter now collapses to a config object plus a recognizer list. A minor side-effect of the consolidation: Cline now performs the same stale-skill-dir cleanup on re-import that Windsurf and Codex already did, so previously orphaned `.agentsmesh/skills/am-agent-<name>/` directories from buggy earlier runs are removed when a Cline projected-agent skill is re-imported.
|
|
12
|
+
|
|
13
|
+
**`agentsmesh watch`**
|
|
14
|
+
|
|
15
|
+
`runWatch` now accepts an optional `onCycle({ featuresChanged })` callback fired once per completed generate cycle (initial + each debounced regen). This is a deterministic synchronization signal for tests/integrations that previously relied on scraping `'Regenerated.'` log lines. The unrelated, dead `_suppressAgentsmeshDirUntil` parameter is removed from `shouldIgnoreWatchPath`. Watch-test budget bumped from 45s → 60s base (×1.5 under coverage = 90s) to survive full-suite scheduler load on macOS FSEvents.
|
|
16
|
+
|
|
17
|
+
**Developer tooling**
|
|
18
|
+
|
|
19
|
+
New `pnpm flake:watch` script (`scripts/flake-check-watch.ts`) runs the watch unit suite N times under `COVERAGE=1` to validate stability whenever the watch loop or scheduler envelope changes.
|
|
20
|
+
|
|
21
|
+
**Internal**
|
|
22
|
+
- New file: `src/targets/import/shared/skill-import-pipeline.ts` gains `importSkillsDirectory`, `projectedAgentRecognizer`, `commandSkillRecognizer`, `SkillRecognizer`, `SkillRecognizerContext` exports. The dead `SkillImportOptions.sourceSkillsDir` field is removed; `sourceSkillsDirs` is now a required first argument to the orchestrator.
|
|
23
|
+
- Adapter migrations: `cline/skills-adapter.ts`, `windsurf/skills-adapter.ts`, `codex-cli/skills-adapter.ts` reduced to thin wrappers. `cursor/skills-adapter.ts` and `copilot/skills-adapter.ts` shed the now-dead option field.
|
|
24
|
+
- 17 new unit tests; touched-scope branch coverage at 100% (25/25).
|
|
25
|
+
- `runWatch` adds `RunWatchOptions` + `WatchCycleInfo` types. The new third parameter is optional and backwards-compatible.
|
|
26
|
+
|
|
3
27
|
## 0.18.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/dist/canonical.js
CHANGED
|
@@ -5890,55 +5890,117 @@ async function findDirectorySkills(skillsDir) {
|
|
|
5890
5890
|
}
|
|
5891
5891
|
return skills;
|
|
5892
5892
|
}
|
|
5893
|
+
async function importSkillsDirectory(sourceSkillsDirs, options, recognizers = []) {
|
|
5894
|
+
for (const sourceDir of sourceSkillsDirs) {
|
|
5895
|
+
const absSkillsDir = join(options.projectRoot, sourceDir);
|
|
5896
|
+
const directorySkills = await findDirectorySkills(absSkillsDir);
|
|
5897
|
+
if (directorySkills.size === 0) continue;
|
|
5898
|
+
let importedAny = false;
|
|
5899
|
+
for (const [skillName, skillDir] of directorySkills) {
|
|
5900
|
+
const skillMdPath = join(skillDir, "SKILL.md");
|
|
5901
|
+
const rawContent = await readFileSafe(skillMdPath);
|
|
5902
|
+
if (rawContent === null) continue;
|
|
5903
|
+
importedAny = true;
|
|
5904
|
+
const { frontmatter, body: rawBody } = parseFrontmatter(rawContent);
|
|
5905
|
+
const ctx = {
|
|
5906
|
+
skillName,
|
|
5907
|
+
skillDir,
|
|
5908
|
+
skillMdPath,
|
|
5909
|
+
rawContent,
|
|
5910
|
+
frontmatter,
|
|
5911
|
+
rawBody,
|
|
5912
|
+
options
|
|
5913
|
+
};
|
|
5914
|
+
let handled = false;
|
|
5915
|
+
for (const recognizer of recognizers) {
|
|
5916
|
+
const claimed = await recognizer.recognize(ctx);
|
|
5917
|
+
if (claimed) {
|
|
5918
|
+
handled = true;
|
|
5919
|
+
break;
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
if (!handled) {
|
|
5923
|
+
await importDirectorySkill(skillName, skillDir, options);
|
|
5924
|
+
}
|
|
5925
|
+
}
|
|
5926
|
+
if (importedAny) return;
|
|
5927
|
+
}
|
|
5928
|
+
}
|
|
5929
|
+
function projectedAgentRecognizer(config) {
|
|
5930
|
+
return {
|
|
5931
|
+
async recognize(ctx) {
|
|
5932
|
+
const projectedAgent = parseProjectedAgentSkillFrontmatter(ctx.frontmatter, ctx.skillName);
|
|
5933
|
+
if (!projectedAgent) return false;
|
|
5934
|
+
const { options } = ctx;
|
|
5935
|
+
await removePathIfExists(
|
|
5936
|
+
join(options.projectRoot, options.destCanonicalSkillsDir, ctx.skillName)
|
|
5937
|
+
);
|
|
5938
|
+
const destAgentsDir = join(options.projectRoot, config.canonicalAgentsDir);
|
|
5939
|
+
await mkdirp(destAgentsDir);
|
|
5940
|
+
const agentPath = join(destAgentsDir, `${projectedAgent.name}.md`);
|
|
5941
|
+
const normalizedBody = options.normalize(ctx.rawBody, ctx.skillMdPath, agentPath);
|
|
5942
|
+
await writeFileAtomic(agentPath, serializeImportedAgent(projectedAgent, normalizedBody));
|
|
5943
|
+
options.results.push({
|
|
5944
|
+
fromTool: options.targetName,
|
|
5945
|
+
fromPath: ctx.skillMdPath,
|
|
5946
|
+
toPath: `${config.canonicalAgentsDir}/${projectedAgent.name}.md`,
|
|
5947
|
+
feature: "agents"
|
|
5948
|
+
});
|
|
5949
|
+
return true;
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
}
|
|
5953
|
+
function commandSkillRecognizer(config) {
|
|
5954
|
+
return {
|
|
5955
|
+
async recognize(ctx) {
|
|
5956
|
+
const command = parseCommandSkillFrontmatter(ctx.frontmatter, ctx.skillName);
|
|
5957
|
+
if (!command) return false;
|
|
5958
|
+
const { options } = ctx;
|
|
5959
|
+
await removePathIfExists(
|
|
5960
|
+
join(options.projectRoot, options.destCanonicalSkillsDir, ctx.skillName)
|
|
5961
|
+
);
|
|
5962
|
+
const destCommandsDir = join(options.projectRoot, config.canonicalCommandsDir);
|
|
5963
|
+
await mkdirp(destCommandsDir);
|
|
5964
|
+
const commandPath = join(destCommandsDir, `${command.name}.md`);
|
|
5965
|
+
const normalizedBody = options.normalize(ctx.rawBody, ctx.skillMdPath, commandPath);
|
|
5966
|
+
await writeFileAtomic(commandPath, serializeImportedCommand(command, normalizedBody));
|
|
5967
|
+
options.results.push({
|
|
5968
|
+
fromTool: options.targetName,
|
|
5969
|
+
fromPath: ctx.skillMdPath,
|
|
5970
|
+
toPath: `${config.canonicalCommandsDir}/${command.name}.md`,
|
|
5971
|
+
feature: "commands"
|
|
5972
|
+
});
|
|
5973
|
+
return true;
|
|
5974
|
+
}
|
|
5975
|
+
};
|
|
5976
|
+
}
|
|
5893
5977
|
var init_skill_import_pipeline = __esm({
|
|
5894
5978
|
"src/targets/import/shared/skill-import-pipeline.ts"() {
|
|
5895
5979
|
init_fs();
|
|
5896
5980
|
init_markdown();
|
|
5897
5981
|
init_import_metadata();
|
|
5898
5982
|
init_reserved();
|
|
5983
|
+
init_projected_agent_skill();
|
|
5984
|
+
init_command_skill();
|
|
5985
|
+
init_scoped_agents_import();
|
|
5899
5986
|
}
|
|
5900
5987
|
});
|
|
5988
|
+
|
|
5989
|
+
// src/targets/cline/skills-adapter.ts
|
|
5901
5990
|
async function importClineSkills(projectRoot, results, normalize, skillsRelDir = CLINE_SKILLS_DIR) {
|
|
5902
|
-
const skillsDir = join(projectRoot, skillsRelDir);
|
|
5903
|
-
const directorySkills = await findDirectorySkills(skillsDir);
|
|
5904
5991
|
const options = {
|
|
5905
5992
|
projectRoot,
|
|
5906
|
-
sourceSkillsDir: skillsRelDir,
|
|
5907
5993
|
destCanonicalSkillsDir: CLINE_CANONICAL_SKILLS_DIR,
|
|
5908
5994
|
targetName: "cline",
|
|
5909
5995
|
normalize,
|
|
5910
5996
|
results
|
|
5911
5997
|
};
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
if (!content) continue;
|
|
5916
|
-
const rawParsed = parseFrontmatter(content);
|
|
5917
|
-
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, skillName);
|
|
5918
|
-
if (projectedAgent) {
|
|
5919
|
-
const destAgentsDir = join(projectRoot, CLINE_CANONICAL_AGENTS_DIR);
|
|
5920
|
-
await mkdirp(destAgentsDir);
|
|
5921
|
-
const agentPath = join(destAgentsDir, `${projectedAgent.name}.md`);
|
|
5922
|
-
await writeFileAtomic(
|
|
5923
|
-
agentPath,
|
|
5924
|
-
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
5925
|
-
);
|
|
5926
|
-
results.push({
|
|
5927
|
-
fromTool: "cline",
|
|
5928
|
-
fromPath: skillMdPath,
|
|
5929
|
-
toPath: `${CLINE_CANONICAL_AGENTS_DIR}/${projectedAgent.name}.md`,
|
|
5930
|
-
feature: "agents"
|
|
5931
|
-
});
|
|
5932
|
-
continue;
|
|
5933
|
-
}
|
|
5934
|
-
await importDirectorySkill(skillName, skillDir, options);
|
|
5935
|
-
}
|
|
5998
|
+
await importSkillsDirectory([skillsRelDir], options, [
|
|
5999
|
+
projectedAgentRecognizer({ canonicalAgentsDir: CLINE_CANONICAL_AGENTS_DIR })
|
|
6000
|
+
]);
|
|
5936
6001
|
}
|
|
5937
6002
|
var init_skills_adapter = __esm({
|
|
5938
6003
|
"src/targets/cline/skills-adapter.ts"() {
|
|
5939
|
-
init_fs();
|
|
5940
|
-
init_markdown();
|
|
5941
|
-
init_projected_agent_skill();
|
|
5942
6004
|
init_skill_import_pipeline();
|
|
5943
6005
|
init_constants8();
|
|
5944
6006
|
}
|
|
@@ -6601,82 +6663,23 @@ var init_mcp_helpers = __esm({
|
|
|
6601
6663
|
init_constants28();
|
|
6602
6664
|
}
|
|
6603
6665
|
});
|
|
6666
|
+
|
|
6667
|
+
// src/targets/codex-cli/skills-adapter.ts
|
|
6604
6668
|
async function importSkills(projectRoot, results, normalize) {
|
|
6605
6669
|
const options = {
|
|
6606
6670
|
projectRoot,
|
|
6607
|
-
sourceSkillsDir: CODEX_SKILLS_DIR,
|
|
6608
6671
|
destCanonicalSkillsDir: CODEX_CANONICAL_SKILLS_DIR,
|
|
6609
6672
|
targetName: CODEX_TARGET,
|
|
6610
6673
|
normalize,
|
|
6611
6674
|
results
|
|
6612
6675
|
};
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
withFileTypes: true
|
|
6618
|
-
}).catch(() => null);
|
|
6619
|
-
if (entries === null) continue;
|
|
6620
|
-
let importedAny = false;
|
|
6621
|
-
for (const ent of entries) {
|
|
6622
|
-
if (!ent.isDirectory() && !ent.isSymbolicLink()) continue;
|
|
6623
|
-
const skillPath = join(skillsDir, ent.name);
|
|
6624
|
-
const skillMdPath = join(skillPath, "SKILL.md");
|
|
6625
|
-
const skillMdContent = await readFileSafe(skillMdPath);
|
|
6626
|
-
if (!skillMdContent) continue;
|
|
6627
|
-
importedAny = true;
|
|
6628
|
-
const skillName = ent.name;
|
|
6629
|
-
const destSkillPath = join(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName, "SKILL.md");
|
|
6630
|
-
const normalized = normalize(skillMdContent, skillMdPath, destSkillPath);
|
|
6631
|
-
const { frontmatter, body } = parseFrontmatter(normalized);
|
|
6632
|
-
const command = parseCommandSkillFrontmatter(frontmatter, ent.name);
|
|
6633
|
-
if (command) {
|
|
6634
|
-
await removePathIfExists(join(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6635
|
-
const destCommandsDir = join(projectRoot, CODEX_CANONICAL_COMMANDS_DIR);
|
|
6636
|
-
await mkdirp(destCommandsDir);
|
|
6637
|
-
const commandPath = join(destCommandsDir, `${command.name}.md`);
|
|
6638
|
-
await writeFileAtomic(
|
|
6639
|
-
commandPath,
|
|
6640
|
-
serializeImportedCommand(command, normalize(body, skillMdPath, commandPath))
|
|
6641
|
-
);
|
|
6642
|
-
results.push({
|
|
6643
|
-
fromTool: CODEX_TARGET,
|
|
6644
|
-
fromPath: skillMdPath,
|
|
6645
|
-
toPath: `${CODEX_CANONICAL_COMMANDS_DIR}/${command.name}.md`,
|
|
6646
|
-
feature: "commands"
|
|
6647
|
-
});
|
|
6648
|
-
continue;
|
|
6649
|
-
}
|
|
6650
|
-
const projectedAgent = parseProjectedAgentSkillFrontmatter(frontmatter, ent.name);
|
|
6651
|
-
if (projectedAgent) {
|
|
6652
|
-
await removePathIfExists(join(projectRoot, CODEX_CANONICAL_SKILLS_DIR, skillName));
|
|
6653
|
-
const destAgentsDir = join(projectRoot, CODEX_CANONICAL_AGENTS_DIR);
|
|
6654
|
-
await mkdirp(destAgentsDir);
|
|
6655
|
-
const agentPath = join(destAgentsDir, `${projectedAgent.name}.md`);
|
|
6656
|
-
await writeFileAtomic(
|
|
6657
|
-
agentPath,
|
|
6658
|
-
serializeImportedAgent(projectedAgent, normalize(body, skillMdPath, agentPath))
|
|
6659
|
-
);
|
|
6660
|
-
results.push({
|
|
6661
|
-
fromTool: CODEX_TARGET,
|
|
6662
|
-
fromPath: skillMdPath,
|
|
6663
|
-
toPath: `${CODEX_CANONICAL_AGENTS_DIR}/${projectedAgent.name}.md`,
|
|
6664
|
-
feature: "agents"
|
|
6665
|
-
});
|
|
6666
|
-
continue;
|
|
6667
|
-
}
|
|
6668
|
-
await importDirectorySkill(skillName, skillPath, options);
|
|
6669
|
-
}
|
|
6670
|
-
if (importedAny) return;
|
|
6671
|
-
}
|
|
6676
|
+
await importSkillsDirectory([CODEX_SKILLS_DIR, CODEX_SKILLS_FALLBACK_DIR], options, [
|
|
6677
|
+
commandSkillRecognizer({ canonicalCommandsDir: CODEX_CANONICAL_COMMANDS_DIR }),
|
|
6678
|
+
projectedAgentRecognizer({ canonicalAgentsDir: CODEX_CANONICAL_AGENTS_DIR })
|
|
6679
|
+
]);
|
|
6672
6680
|
}
|
|
6673
6681
|
var init_skills_adapter2 = __esm({
|
|
6674
6682
|
"src/targets/codex-cli/skills-adapter.ts"() {
|
|
6675
|
-
init_fs();
|
|
6676
|
-
init_markdown();
|
|
6677
|
-
init_command_skill();
|
|
6678
|
-
init_projected_agent_skill();
|
|
6679
|
-
init_scoped_agents_import();
|
|
6680
6683
|
init_skill_import_pipeline();
|
|
6681
6684
|
init_constants28();
|
|
6682
6685
|
}
|
|
@@ -8030,7 +8033,6 @@ async function importSkills2(projectRoot, results, normalize, skillsDirRel = COP
|
|
|
8030
8033
|
const directorySkills = await findDirectorySkills(skillsDir);
|
|
8031
8034
|
const options = {
|
|
8032
8035
|
projectRoot,
|
|
8033
|
-
sourceSkillsDir: skillsDirRel,
|
|
8034
8036
|
destCanonicalSkillsDir: COPILOT_CANONICAL_SKILLS_DIR,
|
|
8035
8037
|
targetName: COPILOT_TARGET,
|
|
8036
8038
|
normalize,
|
|
@@ -9549,7 +9551,6 @@ async function importSkills3(projectRoot, results, normalize, skillsRelDir = CUR
|
|
|
9549
9551
|
const directorySkills = await findDirectorySkills(skillsDir);
|
|
9550
9552
|
const options = {
|
|
9551
9553
|
projectRoot,
|
|
9552
|
-
sourceSkillsDir: skillsRelDir,
|
|
9553
9554
|
destCanonicalSkillsDir: CURSOR_CANONICAL_SKILLS_DIR,
|
|
9554
9555
|
targetName: "cursor",
|
|
9555
9556
|
normalize,
|
|
@@ -16484,49 +16485,22 @@ var init_importer_workflows = __esm({
|
|
|
16484
16485
|
init_constants31();
|
|
16485
16486
|
}
|
|
16486
16487
|
});
|
|
16488
|
+
|
|
16489
|
+
// src/targets/windsurf/skills-adapter.ts
|
|
16487
16490
|
async function importSkills4(projectRoot, results, normalize, skillsRelDir = WINDSURF_SKILLS_DIR) {
|
|
16488
|
-
const skillsDir = join(projectRoot, skillsRelDir);
|
|
16489
|
-
const directorySkills = await findDirectorySkills(skillsDir);
|
|
16490
16491
|
const options = {
|
|
16491
16492
|
projectRoot,
|
|
16492
|
-
sourceSkillsDir: skillsRelDir,
|
|
16493
16493
|
destCanonicalSkillsDir: WINDSURF_CANONICAL_SKILLS_DIR,
|
|
16494
16494
|
targetName: "windsurf",
|
|
16495
16495
|
normalize,
|
|
16496
16496
|
results
|
|
16497
16497
|
};
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
if (!content) continue;
|
|
16502
|
-
const rawParsed = parseFrontmatter(content);
|
|
16503
|
-
const projectedAgent = parseProjectedAgentSkillFrontmatter(rawParsed.frontmatter, skillName);
|
|
16504
|
-
if (projectedAgent) {
|
|
16505
|
-
await removePathIfExists(join(projectRoot, WINDSURF_CANONICAL_SKILLS_DIR, skillName));
|
|
16506
|
-
const destAgentsDir = join(projectRoot, WINDSURF_CANONICAL_AGENTS_DIR);
|
|
16507
|
-
await mkdirp(destAgentsDir);
|
|
16508
|
-
const agentPath = join(destAgentsDir, `${projectedAgent.name}.md`);
|
|
16509
|
-
await writeFileAtomic(
|
|
16510
|
-
agentPath,
|
|
16511
|
-
serializeImportedAgent(projectedAgent, normalize(rawParsed.body, skillMdPath, agentPath))
|
|
16512
|
-
);
|
|
16513
|
-
results.push({
|
|
16514
|
-
fromTool: "windsurf",
|
|
16515
|
-
fromPath: skillMdPath,
|
|
16516
|
-
toPath: `${WINDSURF_CANONICAL_AGENTS_DIR}/${projectedAgent.name}.md`,
|
|
16517
|
-
feature: "agents"
|
|
16518
|
-
});
|
|
16519
|
-
continue;
|
|
16520
|
-
}
|
|
16521
|
-
await importDirectorySkill(skillName, skillDir, options);
|
|
16522
|
-
}
|
|
16498
|
+
await importSkillsDirectory([skillsRelDir], options, [
|
|
16499
|
+
projectedAgentRecognizer({ canonicalAgentsDir: WINDSURF_CANONICAL_AGENTS_DIR })
|
|
16500
|
+
]);
|
|
16523
16501
|
}
|
|
16524
16502
|
var init_skills_adapter5 = __esm({
|
|
16525
16503
|
"src/targets/windsurf/skills-adapter.ts"() {
|
|
16526
|
-
init_fs();
|
|
16527
|
-
init_markdown();
|
|
16528
|
-
init_projected_agent_skill();
|
|
16529
|
-
init_scoped_agents_import();
|
|
16530
16504
|
init_skill_import_pipeline();
|
|
16531
16505
|
init_constants31();
|
|
16532
16506
|
}
|