agentsmesh 0.2.1 → 0.2.2
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 +6 -0
- package/README.md +1 -1
- package/dist/cli.js +206 -55
- package/dist/cli.js.map +1 -1
- package/package.json +22 -24
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- d42b374: Support installing standalone skill repos (bare GitHub/GitLab URLs), use SKILL.md frontmatter name for skill identity, filter repo boilerplate from installed skills, and fix pack skill reference paths in generated output.
|
|
8
|
+
|
|
3
9
|
All notable changes to this project will be documented in this file.
|
|
4
10
|
|
|
5
11
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/sampleXbro/agentsmesh/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/agentsmesh)
|
|
5
|
-
[](https://codecov.io/gh/sampleXbro/agentsmesh)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://nodejs.org/)
|
package/dist/cli.js
CHANGED
|
@@ -5455,6 +5455,10 @@ async function readContent(path) {
|
|
|
5455
5455
|
return c2 ?? "";
|
|
5456
5456
|
}
|
|
5457
5457
|
var SKILL_FILE = "SKILL.md";
|
|
5458
|
+
var EXCLUDED_DIR_PREFIXES = [".git", "node_modules"];
|
|
5459
|
+
function sanitizeSkillName(raw) {
|
|
5460
|
+
return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
5461
|
+
}
|
|
5458
5462
|
async function listSupportingFiles(skillDir) {
|
|
5459
5463
|
const files = await readDirRecursive(skillDir);
|
|
5460
5464
|
const result = [];
|
|
@@ -5462,6 +5466,9 @@ async function listSupportingFiles(skillDir) {
|
|
|
5462
5466
|
const raw = absPath.slice(skillDir.length + 1);
|
|
5463
5467
|
const name = raw.replace(/\\/g, "/");
|
|
5464
5468
|
if (name === SKILL_FILE || name.endsWith(`/${SKILL_FILE}`)) continue;
|
|
5469
|
+
const firstSegment = name.split("/")[0];
|
|
5470
|
+
if (EXCLUDED_DIR_PREFIXES.some((p) => firstSegment === p)) continue;
|
|
5471
|
+
if (name === ".DS_Store" || name.endsWith("/.DS_Store")) continue;
|
|
5465
5472
|
const content = await readContent(absPath);
|
|
5466
5473
|
result.push({ relativePath: name, absolutePath: absPath, content });
|
|
5467
5474
|
}
|
|
@@ -5473,9 +5480,10 @@ async function parseSkillDirectory(skillDir) {
|
|
|
5473
5480
|
if (!content) return null;
|
|
5474
5481
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
5475
5482
|
const supportingFiles = await listSupportingFiles(skillDir);
|
|
5483
|
+
const fmName = typeof frontmatter.name === "string" ? sanitizeSkillName(frontmatter.name) : "";
|
|
5476
5484
|
return {
|
|
5477
5485
|
source: skillPath,
|
|
5478
|
-
name: basename25(skillDir),
|
|
5486
|
+
name: fmName || basename25(skillDir),
|
|
5479
5487
|
description: typeof frontmatter.description === "string" ? frontmatter.description : "",
|
|
5480
5488
|
body,
|
|
5481
5489
|
supportingFiles
|
|
@@ -7976,10 +7984,10 @@ function preferEquivalentCodexAgents(results, canonical, config) {
|
|
|
7976
7984
|
|
|
7977
7985
|
// src/core/reference-rewriter.ts
|
|
7978
7986
|
import { existsSync as existsSync3 } from "fs";
|
|
7979
|
-
import { dirname as
|
|
7987
|
+
import { dirname as dirname20, join as join48 } from "path";
|
|
7980
7988
|
|
|
7981
7989
|
// src/core/output-source-map.ts
|
|
7982
|
-
import { join as join47, normalize as normalizePath2 } from "path";
|
|
7990
|
+
import { dirname as dirname19, join as join47, normalize as normalizePath2 } from "path";
|
|
7983
7991
|
function canonicalRulePath(rule) {
|
|
7984
7992
|
return `.agentsmesh/rules/${rule.source.split("/").pop()}`;
|
|
7985
7993
|
}
|
|
@@ -8025,6 +8033,22 @@ function ruleOutputPaths(target10, rule, refs) {
|
|
|
8025
8033
|
}
|
|
8026
8034
|
return paths;
|
|
8027
8035
|
}
|
|
8036
|
+
function addPackSkillPaths(refs, target10, canonical, projectRoot) {
|
|
8037
|
+
const skillDir = SKILL_DIRS[target10];
|
|
8038
|
+
if (!skillDir) return;
|
|
8039
|
+
const packsPrefix = join47(projectRoot, ".agentsmesh", "packs");
|
|
8040
|
+
for (const skill of canonical.skills) {
|
|
8041
|
+
const skillSourceDir = dirname19(skill.source);
|
|
8042
|
+
if (!skillSourceDir.startsWith(packsPrefix)) continue;
|
|
8043
|
+
const targetSkillDir = normalizePath2(join47(projectRoot, skillDir, skill.name));
|
|
8044
|
+
refs.set(normalizePath2(skillSourceDir), targetSkillDir);
|
|
8045
|
+
refs.set(normalizePath2(skill.source), normalizePath2(join47(targetSkillDir, "SKILL.md")));
|
|
8046
|
+
for (const file of skill.supportingFiles) {
|
|
8047
|
+
const targetFilePath = normalizePath2(join47(targetSkillDir, file.relativePath));
|
|
8048
|
+
refs.set(normalizePath2(file.absolutePath), targetFilePath);
|
|
8049
|
+
}
|
|
8050
|
+
}
|
|
8051
|
+
}
|
|
8028
8052
|
function buildArtifactPathMap(target10, canonical, config, projectRoot, destinationPath) {
|
|
8029
8053
|
const refs = new Map(
|
|
8030
8054
|
[...buildReferenceMap(target10, canonical, config)].map(([canonicalPath, targetPath]) => [
|
|
@@ -8041,6 +8065,7 @@ function buildArtifactPathMap(target10, canonical, config, projectRoot, destinat
|
|
|
8041
8065
|
);
|
|
8042
8066
|
}
|
|
8043
8067
|
}
|
|
8068
|
+
addPackSkillPaths(refs, target10, canonical, projectRoot);
|
|
8044
8069
|
return refs;
|
|
8045
8070
|
}
|
|
8046
8071
|
function buildOutputSourceMap(target10, canonical, config) {
|
|
@@ -8077,11 +8102,11 @@ function collectPlannedPaths(projectRoot, results) {
|
|
|
8077
8102
|
for (const result of results) {
|
|
8078
8103
|
const absolutePath = join48(projectRoot, result.path);
|
|
8079
8104
|
planned.add(absolutePath);
|
|
8080
|
-
let current =
|
|
8105
|
+
let current = dirname20(absolutePath);
|
|
8081
8106
|
while (current.startsWith(projectRoot) && !planned.has(current)) {
|
|
8082
8107
|
planned.add(current);
|
|
8083
8108
|
if (current === projectRoot) break;
|
|
8084
|
-
current =
|
|
8109
|
+
current = dirname20(current);
|
|
8085
8110
|
}
|
|
8086
8111
|
}
|
|
8087
8112
|
return planned;
|
|
@@ -9580,7 +9605,7 @@ async function runCheck(flags, projectRoot) {
|
|
|
9580
9605
|
import { join as join58 } from "path";
|
|
9581
9606
|
|
|
9582
9607
|
// src/core/merger.ts
|
|
9583
|
-
import { dirname as
|
|
9608
|
+
import { dirname as dirname21, join as join57 } from "path";
|
|
9584
9609
|
var LOCK_FILENAME2 = ".lock";
|
|
9585
9610
|
var CONFLICT_MARKER = "<<<<<<<";
|
|
9586
9611
|
async function hasLockConflict(abDir) {
|
|
@@ -9595,7 +9620,7 @@ async function resolveLockConflict(abDir, libVersion, config) {
|
|
|
9595
9620
|
throw new Error("No conflict to resolve.");
|
|
9596
9621
|
}
|
|
9597
9622
|
const checksums = await buildChecksums(abDir);
|
|
9598
|
-
const configDir =
|
|
9623
|
+
const configDir = dirname21(abDir);
|
|
9599
9624
|
const resolvedExtends = config ? await resolveExtendPaths(config, configDir) : [];
|
|
9600
9625
|
const extendChecksums = resolvedExtends.length > 0 ? await buildExtendChecksums(resolvedExtends) : {};
|
|
9601
9626
|
const packChecksums = await buildPackChecksums(join57(abDir, "packs"));
|
|
@@ -9626,7 +9651,7 @@ async function runMerge(flags, projectRoot) {
|
|
|
9626
9651
|
}
|
|
9627
9652
|
|
|
9628
9653
|
// src/install/run-install.ts
|
|
9629
|
-
import { join as
|
|
9654
|
+
import { join as join72 } from "path";
|
|
9630
9655
|
|
|
9631
9656
|
// src/install/git-pin.ts
|
|
9632
9657
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -10001,6 +10026,50 @@ function parseGitlabBlobUrl(urlStr) {
|
|
|
10001
10026
|
return null;
|
|
10002
10027
|
}
|
|
10003
10028
|
}
|
|
10029
|
+
var GITHUB_ROUTE_WORDS = /* @__PURE__ */ new Set([
|
|
10030
|
+
"tree",
|
|
10031
|
+
"blob",
|
|
10032
|
+
"commit",
|
|
10033
|
+
"releases",
|
|
10034
|
+
"actions",
|
|
10035
|
+
"issues",
|
|
10036
|
+
"pulls",
|
|
10037
|
+
"settings",
|
|
10038
|
+
"wiki",
|
|
10039
|
+
"discussions",
|
|
10040
|
+
"security",
|
|
10041
|
+
"projects",
|
|
10042
|
+
"packages"
|
|
10043
|
+
]);
|
|
10044
|
+
function parseGithubRepoUrl(urlStr) {
|
|
10045
|
+
try {
|
|
10046
|
+
const u = new URL3(urlStr);
|
|
10047
|
+
if (u.hostname !== "github.com") return null;
|
|
10048
|
+
const parts = u.pathname.split("/").filter(Boolean).map((s) => s.replace(/\.git$/i, ""));
|
|
10049
|
+
if (parts.length < 2) return null;
|
|
10050
|
+
if (parts.length > 2 || GITHUB_ROUTE_WORDS.has(parts[1])) return null;
|
|
10051
|
+
const org = parts[0];
|
|
10052
|
+
const repo = parts[1];
|
|
10053
|
+
return { org, repo };
|
|
10054
|
+
} catch {
|
|
10055
|
+
return null;
|
|
10056
|
+
}
|
|
10057
|
+
}
|
|
10058
|
+
function parseGitlabRepoUrl(urlStr) {
|
|
10059
|
+
try {
|
|
10060
|
+
const u = new URL3(urlStr);
|
|
10061
|
+
if (u.hostname !== "gitlab.com") return null;
|
|
10062
|
+
const parts = u.pathname.split("/").filter(Boolean).map((s) => s.replace(/\.git$/i, ""));
|
|
10063
|
+
if (parts.length < 2) return null;
|
|
10064
|
+
if (parts.includes("-")) return null;
|
|
10065
|
+
const project = parts[parts.length - 1];
|
|
10066
|
+
const namespace = parts.slice(0, -1).join("/");
|
|
10067
|
+
if (!namespace || !project) return null;
|
|
10068
|
+
return { namespace, project };
|
|
10069
|
+
} catch {
|
|
10070
|
+
return null;
|
|
10071
|
+
}
|
|
10072
|
+
}
|
|
10004
10073
|
function parseGitSshGithub(ssh) {
|
|
10005
10074
|
const m = ssh.match(/^git@github\.com:([^/]+)\/(.+?)(?:\.git)?$/i);
|
|
10006
10075
|
if (!m) return null;
|
|
@@ -10038,26 +10107,48 @@ async function parseInstallSource(raw, configDir, explicitPath) {
|
|
|
10038
10107
|
};
|
|
10039
10108
|
}
|
|
10040
10109
|
if (trimmed.startsWith("https://") || trimmed.startsWith("http://")) {
|
|
10041
|
-
const
|
|
10042
|
-
if (
|
|
10110
|
+
const ghDetailed = parseGithubTreeUrl(trimmed) ?? parseGithubBlobUrl(trimmed);
|
|
10111
|
+
if (ghDetailed) {
|
|
10112
|
+
return {
|
|
10113
|
+
kind: "github",
|
|
10114
|
+
rawRef: ghDetailed.ref,
|
|
10115
|
+
org: ghDetailed.org,
|
|
10116
|
+
repo: ghDetailed.repo,
|
|
10117
|
+
gitRemoteUrl: `https://github.com/${ghDetailed.org}/${ghDetailed.repo}.git`,
|
|
10118
|
+
pathInRepo: pathFlag || ghDetailed.path
|
|
10119
|
+
};
|
|
10120
|
+
}
|
|
10121
|
+
const ghBare = parseGithubRepoUrl(trimmed);
|
|
10122
|
+
if (ghBare) {
|
|
10043
10123
|
return {
|
|
10044
10124
|
kind: "github",
|
|
10045
|
-
rawRef:
|
|
10046
|
-
org:
|
|
10047
|
-
repo:
|
|
10048
|
-
gitRemoteUrl: `https://github.com/${
|
|
10049
|
-
pathInRepo: pathFlag
|
|
10125
|
+
rawRef: "HEAD",
|
|
10126
|
+
org: ghBare.org,
|
|
10127
|
+
repo: ghBare.repo,
|
|
10128
|
+
gitRemoteUrl: `https://github.com/${ghBare.org}/${ghBare.repo}.git`,
|
|
10129
|
+
pathInRepo: pathFlag
|
|
10050
10130
|
};
|
|
10051
10131
|
}
|
|
10052
|
-
const
|
|
10053
|
-
if (
|
|
10132
|
+
const glDetailed = parseGitlabTreeUrl(trimmed) ?? parseGitlabBlobUrl(trimmed);
|
|
10133
|
+
if (glDetailed) {
|
|
10054
10134
|
return {
|
|
10055
10135
|
kind: "gitlab",
|
|
10056
|
-
rawRef:
|
|
10057
|
-
org:
|
|
10058
|
-
repo:
|
|
10059
|
-
gitRemoteUrl: `https://gitlab.com/${
|
|
10060
|
-
pathInRepo: pathFlag ||
|
|
10136
|
+
rawRef: glDetailed.ref,
|
|
10137
|
+
org: glDetailed.namespace,
|
|
10138
|
+
repo: glDetailed.project,
|
|
10139
|
+
gitRemoteUrl: `https://gitlab.com/${glDetailed.namespace}/${glDetailed.project}.git`,
|
|
10140
|
+
pathInRepo: pathFlag || glDetailed.path
|
|
10141
|
+
};
|
|
10142
|
+
}
|
|
10143
|
+
const glBare = parseGitlabRepoUrl(trimmed);
|
|
10144
|
+
if (glBare) {
|
|
10145
|
+
return {
|
|
10146
|
+
kind: "gitlab",
|
|
10147
|
+
rawRef: "HEAD",
|
|
10148
|
+
org: glBare.namespace,
|
|
10149
|
+
repo: glBare.project,
|
|
10150
|
+
gitRemoteUrl: `https://gitlab.com/${glBare.namespace}/${glBare.project}.git`,
|
|
10151
|
+
pathInRepo: pathFlag
|
|
10061
10152
|
};
|
|
10062
10153
|
}
|
|
10063
10154
|
}
|
|
@@ -10324,7 +10415,7 @@ import { join as join63 } from "path";
|
|
|
10324
10415
|
import { rename as rename4 } from "fs/promises";
|
|
10325
10416
|
|
|
10326
10417
|
// src/install/pack-writer.ts
|
|
10327
|
-
import { join as join60, basename as basename39, dirname as
|
|
10418
|
+
import { join as join60, basename as basename39, dirname as dirname22 } from "path";
|
|
10328
10419
|
import { rm as rm6, rename as rename3, mkdir as mkdir5, copyFile as copyFile2 } from "fs/promises";
|
|
10329
10420
|
import { stringify as yamlStringify6 } from "yaml";
|
|
10330
10421
|
|
|
@@ -10385,7 +10476,7 @@ async function writeSkills(canonical, packDir) {
|
|
|
10385
10476
|
await copyFile2(skill.source, join60(skillDestDir, "SKILL.md"));
|
|
10386
10477
|
for (const sf of skill.supportingFiles) {
|
|
10387
10478
|
const destPath = join60(skillDestDir, sf.relativePath);
|
|
10388
|
-
await mkdirp(
|
|
10479
|
+
await mkdirp(dirname22(destPath));
|
|
10389
10480
|
await copyFile2(sf.absolutePath, destPath);
|
|
10390
10481
|
}
|
|
10391
10482
|
}
|
|
@@ -10430,7 +10521,7 @@ async function materializePack(packsDir, packName, canonical, metadataInput) {
|
|
|
10430
10521
|
}
|
|
10431
10522
|
|
|
10432
10523
|
// src/install/pack-merge.ts
|
|
10433
|
-
import { join as join61, basename as basename40, dirname as
|
|
10524
|
+
import { join as join61, basename as basename40, dirname as dirname23 } from "path";
|
|
10434
10525
|
import { copyFile as copyFile3 } from "fs/promises";
|
|
10435
10526
|
import { stringify as yamlStringify7 } from "yaml";
|
|
10436
10527
|
function union(a, b) {
|
|
@@ -10493,7 +10584,7 @@ async function mergeSkills(canonical, packDir) {
|
|
|
10493
10584
|
await copyFile3(skill.source, join61(destDir, "SKILL.md"));
|
|
10494
10585
|
for (const sf of skill.supportingFiles) {
|
|
10495
10586
|
const destPath = join61(destDir, sf.relativePath);
|
|
10496
|
-
await mkdirp(
|
|
10587
|
+
await mkdirp(dirname23(destPath));
|
|
10497
10588
|
await copyFile3(sf.absolutePath, destPath);
|
|
10498
10589
|
}
|
|
10499
10590
|
}
|
|
@@ -10919,9 +11010,66 @@ function narrowDiscoveredForInstallScope(canonical, options) {
|
|
|
10919
11010
|
}
|
|
10920
11011
|
|
|
10921
11012
|
// src/install/manual-install-scope.ts
|
|
10922
|
-
import { basename as basename41, dirname as
|
|
10923
|
-
import { cp, mkdtemp, stat as stat5, rm as rm7 } from "fs/promises";
|
|
11013
|
+
import { basename as basename41, dirname as dirname24, join as join65, relative as relative22 } from "path";
|
|
11014
|
+
import { cp as cp2, mkdtemp, stat as stat5, rm as rm7 } from "fs/promises";
|
|
10924
11015
|
import { tmpdir } from "os";
|
|
11016
|
+
|
|
11017
|
+
// src/install/skill-repo-filter.ts
|
|
11018
|
+
import { relative as relative21 } from "path";
|
|
11019
|
+
import { cp } from "fs/promises";
|
|
11020
|
+
init_markdown();
|
|
11021
|
+
var REPO_BOILERPLATE_FILES = /* @__PURE__ */ new Set([
|
|
11022
|
+
"README.md",
|
|
11023
|
+
"README.rst",
|
|
11024
|
+
"README.txt",
|
|
11025
|
+
"README",
|
|
11026
|
+
"LICENSE",
|
|
11027
|
+
"LICENSE.md",
|
|
11028
|
+
"LICENSE.txt",
|
|
11029
|
+
"LICENSE-MIT",
|
|
11030
|
+
"LICENSE-APACHE",
|
|
11031
|
+
"CONTRIBUTING.md",
|
|
11032
|
+
"CHANGELOG.md",
|
|
11033
|
+
"CODE_OF_CONDUCT.md",
|
|
11034
|
+
"package.json",
|
|
11035
|
+
"package-lock.json",
|
|
11036
|
+
"pnpm-lock.yaml",
|
|
11037
|
+
"yarn.lock",
|
|
11038
|
+
".gitignore",
|
|
11039
|
+
".gitattributes",
|
|
11040
|
+
".editorconfig",
|
|
11041
|
+
".DS_Store"
|
|
11042
|
+
]);
|
|
11043
|
+
var REPO_BOILERPLATE_DIRS = /* @__PURE__ */ new Set([
|
|
11044
|
+
".git",
|
|
11045
|
+
".github",
|
|
11046
|
+
".gitlab",
|
|
11047
|
+
"node_modules",
|
|
11048
|
+
".vscode",
|
|
11049
|
+
".idea"
|
|
11050
|
+
]);
|
|
11051
|
+
async function readSkillFrontmatterName(skillMdPath) {
|
|
11052
|
+
const content = await readFileSafe(skillMdPath);
|
|
11053
|
+
if (!content) return "";
|
|
11054
|
+
const { frontmatter } = parseFrontmatter(content);
|
|
11055
|
+
if (typeof frontmatter.name !== "string") return "";
|
|
11056
|
+
return frontmatter.name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
11057
|
+
}
|
|
11058
|
+
async function cpFilteredSkill(sourceRoot, destDir) {
|
|
11059
|
+
await cp(sourceRoot, destDir, {
|
|
11060
|
+
recursive: true,
|
|
11061
|
+
filter: (src) => {
|
|
11062
|
+
const rel2 = relative21(sourceRoot, src).replace(/\\/g, "/");
|
|
11063
|
+
if (rel2 === "") return true;
|
|
11064
|
+
const first = rel2.split("/")[0];
|
|
11065
|
+
if (REPO_BOILERPLATE_DIRS.has(first)) return false;
|
|
11066
|
+
if (!rel2.includes("/") && REPO_BOILERPLATE_FILES.has(rel2)) return false;
|
|
11067
|
+
return true;
|
|
11068
|
+
}
|
|
11069
|
+
});
|
|
11070
|
+
}
|
|
11071
|
+
|
|
11072
|
+
// src/install/manual-install-scope.ts
|
|
10925
11073
|
async function createStageRoot() {
|
|
10926
11074
|
const stageBase = await mkdtemp(join65(tmpdir(), "am-install-manual-"));
|
|
10927
11075
|
const discoveryRoot = join65(stageBase, "repo");
|
|
@@ -10940,7 +11088,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
10940
11088
|
throw new Error(`Manual install only supports .md files for this collection: ${sourceRoot}`);
|
|
10941
11089
|
}
|
|
10942
11090
|
await mkdirp(destinationDir);
|
|
10943
|
-
await
|
|
11091
|
+
await cp2(sourceRoot, join65(destinationDir, basename41(sourceRoot)));
|
|
10944
11092
|
return;
|
|
10945
11093
|
}
|
|
10946
11094
|
const files = (await readDirRecursive(sourceRoot)).filter(
|
|
@@ -10960,7 +11108,7 @@ async function stageMarkdownCollection(sourceRoot, destinationDir) {
|
|
|
10960
11108
|
);
|
|
10961
11109
|
}
|
|
10962
11110
|
usedNames.set(name, file);
|
|
10963
|
-
await
|
|
11111
|
+
await cp2(file, join65(destinationDir, name));
|
|
10964
11112
|
}
|
|
10965
11113
|
}
|
|
10966
11114
|
async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNames) {
|
|
@@ -10971,7 +11119,7 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
10971
11119
|
const matches = /* @__PURE__ */ new Map();
|
|
10972
11120
|
for (const file of await readDirRecursive(sourceRoot)) {
|
|
10973
11121
|
if (!file.endsWith("/SKILL.md") && !file.endsWith("\\SKILL.md")) continue;
|
|
10974
|
-
const skillDir =
|
|
11122
|
+
const skillDir = dirname24(file);
|
|
10975
11123
|
const skillName = basename41(skillDir);
|
|
10976
11124
|
if (!wanted.has(skillName)) continue;
|
|
10977
11125
|
const previous = matches.get(skillName);
|
|
@@ -10985,7 +11133,7 @@ async function stagePreferredSkills(sourceRoot, destinationDir, preferredSkillNa
|
|
|
10985
11133
|
if (matches.size !== preferredSkillNames.length) return false;
|
|
10986
11134
|
await mkdirp(destinationDir);
|
|
10987
11135
|
for (const skillName of preferredSkillNames) {
|
|
10988
|
-
await
|
|
11136
|
+
await cp2(matches.get(skillName), join65(destinationDir, skillName), { recursive: true });
|
|
10989
11137
|
}
|
|
10990
11138
|
return true;
|
|
10991
11139
|
}
|
|
@@ -10995,10 +11143,10 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
10995
11143
|
if (basename41(sourceRoot) !== "SKILL.md") {
|
|
10996
11144
|
throw new Error(`Manual skill install expects SKILL.md or a skill directory: ${sourceRoot}`);
|
|
10997
11145
|
}
|
|
10998
|
-
const skillName = basename41(
|
|
11146
|
+
const skillName = basename41(dirname24(sourceRoot));
|
|
10999
11147
|
const skillDir = join65(destinationDir, skillName);
|
|
11000
11148
|
await mkdirp(skillDir);
|
|
11001
|
-
await
|
|
11149
|
+
await cp2(dirname24(sourceRoot), skillDir, { recursive: true });
|
|
11002
11150
|
return;
|
|
11003
11151
|
}
|
|
11004
11152
|
if (await isSkillPackLayout(sourceRoot)) {
|
|
@@ -11006,9 +11154,11 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
11006
11154
|
if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
|
|
11007
11155
|
return;
|
|
11008
11156
|
}
|
|
11009
|
-
const
|
|
11157
|
+
const fmName = await readSkillFrontmatterName(join65(sourceRoot, "SKILL.md"));
|
|
11158
|
+
const skillName = fmName || basename41(sourceRoot);
|
|
11159
|
+
const skillDir = join65(destinationDir, skillName);
|
|
11010
11160
|
await mkdirp(destinationDir);
|
|
11011
|
-
await
|
|
11161
|
+
await cpFilteredSkill(sourceRoot, skillDir);
|
|
11012
11162
|
return;
|
|
11013
11163
|
}
|
|
11014
11164
|
if (await stagePreferredSkills(sourceRoot, destinationDir, options.preferredSkillNames ?? [])) {
|
|
@@ -11020,10 +11170,10 @@ async function stageSkills(sourceRoot, destinationDir, options = {}) {
|
|
|
11020
11170
|
for (const file of entries.filter(
|
|
11021
11171
|
(entry) => entry.endsWith("/SKILL.md") || entry.endsWith("\\SKILL.md")
|
|
11022
11172
|
)) {
|
|
11023
|
-
roots.add(
|
|
11173
|
+
roots.add(relative22(sourceRoot, dirname24(file)).split(/[\\/]/)[0]);
|
|
11024
11174
|
}
|
|
11025
11175
|
for (const root of roots) {
|
|
11026
|
-
await
|
|
11176
|
+
await cp2(join65(sourceRoot, root), join65(destinationDir, root), { recursive: true });
|
|
11027
11177
|
}
|
|
11028
11178
|
return;
|
|
11029
11179
|
}
|
|
@@ -11132,7 +11282,7 @@ function extendPickHasArrays(p) {
|
|
|
11132
11282
|
import { basename as basename44, join as join68 } from "path";
|
|
11133
11283
|
|
|
11134
11284
|
// src/install/gemini-install-commands.ts
|
|
11135
|
-
import { join as join66, relative as
|
|
11285
|
+
import { join as join66, relative as relative23 } from "path";
|
|
11136
11286
|
async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
11137
11287
|
const commandsRoot = join66(repoRoot, ...GEMINI_COMMANDS_DIR.split("/"));
|
|
11138
11288
|
const scanDir = join66(repoRoot, ...pathInRepoPosix.split("/"));
|
|
@@ -11140,7 +11290,7 @@ async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
|
11140
11290
|
const names = [];
|
|
11141
11291
|
for (const f of files) {
|
|
11142
11292
|
if (!/\.(toml|md)$/i.test(f)) continue;
|
|
11143
|
-
const rel2 =
|
|
11293
|
+
const rel2 = relative23(commandsRoot, f).replace(/\\/g, "/");
|
|
11144
11294
|
if (rel2.startsWith("..") || rel2 === "") continue;
|
|
11145
11295
|
const noExt = rel2.replace(/\.(toml|md)$/i, "");
|
|
11146
11296
|
const name = noExt.split("/").filter(Boolean).join(":");
|
|
@@ -11150,16 +11300,16 @@ async function inferGeminiCommandNamesFromFiles(repoRoot, pathInRepoPosix) {
|
|
|
11150
11300
|
}
|
|
11151
11301
|
|
|
11152
11302
|
// src/install/native-skill-scan.ts
|
|
11153
|
-
import { basename as basename42, dirname as
|
|
11303
|
+
import { basename as basename42, dirname as dirname25, relative as relative24 } from "path";
|
|
11154
11304
|
async function skillNamesFromNativeSkillDir(scanRoot) {
|
|
11155
11305
|
const files = await readDirRecursive(scanRoot);
|
|
11156
11306
|
const names = /* @__PURE__ */ new Set();
|
|
11157
11307
|
for (const f of files) {
|
|
11158
11308
|
if (basename42(f) === "SKILL.md") {
|
|
11159
|
-
names.add(basename42(
|
|
11309
|
+
names.add(basename42(dirname25(f)));
|
|
11160
11310
|
continue;
|
|
11161
11311
|
}
|
|
11162
|
-
const rel2 =
|
|
11312
|
+
const rel2 = relative24(scanRoot, f).replace(/\\/g, "/");
|
|
11163
11313
|
if (!rel2.includes("/") && f.toLowerCase().endsWith(".md")) {
|
|
11164
11314
|
names.add(basename42(f, ".md"));
|
|
11165
11315
|
}
|
|
@@ -11342,8 +11492,8 @@ function isImplicitPickEmpty(p) {
|
|
|
11342
11492
|
}
|
|
11343
11493
|
|
|
11344
11494
|
// src/install/native-install-scope.ts
|
|
11345
|
-
import { basename as basename45, join as join69, relative as
|
|
11346
|
-
import { cp as
|
|
11495
|
+
import { basename as basename45, join as join69, relative as relative25 } from "path";
|
|
11496
|
+
import { cp as cp3, mkdtemp as mkdtemp2, rm as rm8 } from "fs/promises";
|
|
11347
11497
|
import { tmpdir as tmpdir2 } from "os";
|
|
11348
11498
|
function normalizePath3(path) {
|
|
11349
11499
|
return path.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
@@ -11365,7 +11515,7 @@ async function makeStageRoot(repoRoot) {
|
|
|
11365
11515
|
await rm8(stageBase, { recursive: true, force: true });
|
|
11366
11516
|
};
|
|
11367
11517
|
try {
|
|
11368
|
-
await
|
|
11518
|
+
await cp3(repoRoot, stageRoot, { recursive: true });
|
|
11369
11519
|
return { stageRoot, cleanup };
|
|
11370
11520
|
} catch (error) {
|
|
11371
11521
|
await cleanup();
|
|
@@ -11398,7 +11548,7 @@ function buildPickFromResults(results, stageRoot) {
|
|
|
11398
11548
|
}
|
|
11399
11549
|
if (result.feature === "skills" && result.toPath.startsWith(".agentsmesh/skills/")) {
|
|
11400
11550
|
const rel2 = normalizePath3(
|
|
11401
|
-
|
|
11551
|
+
relative25(join69(stageRoot, ".agentsmesh", "skills"), join69(stageRoot, result.toPath))
|
|
11402
11552
|
);
|
|
11403
11553
|
const skillName = rel2.split("/")[0];
|
|
11404
11554
|
if (skillName) {
|
|
@@ -11586,7 +11736,7 @@ function applyReplayInstallScope(narrowed, discoveredFeatures, replay) {
|
|
|
11586
11736
|
}
|
|
11587
11737
|
|
|
11588
11738
|
// src/install/manual-install-persistence.ts
|
|
11589
|
-
import { basename as basename46, dirname as
|
|
11739
|
+
import { basename as basename46, dirname as dirname26, join as join71 } from "path";
|
|
11590
11740
|
import { stat as stat6 } from "fs/promises";
|
|
11591
11741
|
function trimDot(pathInRepo) {
|
|
11592
11742
|
return pathInRepo === "." || pathInRepo === "" ? void 0 : pathInRepo;
|
|
@@ -11605,27 +11755,28 @@ async function resolveManualInstallPersistence(args) {
|
|
|
11605
11755
|
const info = await stat6(args.contentRoot);
|
|
11606
11756
|
if (args.as !== "skills" && info.isFile() && args.contentRoot.toLowerCase().endsWith(".md")) {
|
|
11607
11757
|
return {
|
|
11608
|
-
pathInRepo: trimDot(
|
|
11758
|
+
pathInRepo: trimDot(dirname26(normalizedPath)),
|
|
11609
11759
|
pick: markdownPick(args.as, normalizedPath || args.contentRoot)
|
|
11610
11760
|
};
|
|
11611
11761
|
}
|
|
11612
11762
|
if (args.as === "skills") {
|
|
11613
11763
|
if (info.isFile() && basename46(args.contentRoot) === "SKILL.md") {
|
|
11614
|
-
const skillDir = normalizedPath ?
|
|
11764
|
+
const skillDir = normalizedPath ? dirname26(normalizedPath) : dirname26(args.contentRoot);
|
|
11615
11765
|
return {
|
|
11616
|
-
pathInRepo: trimDot(
|
|
11766
|
+
pathInRepo: trimDot(dirname26(skillDir)),
|
|
11617
11767
|
pick: { skills: [basename46(skillDir)] }
|
|
11618
11768
|
};
|
|
11619
11769
|
}
|
|
11620
11770
|
if (info.isDirectory()) {
|
|
11621
11771
|
const skillDir = normalizedPath || basename46(args.contentRoot);
|
|
11622
|
-
const skillFile =
|
|
11772
|
+
const skillFile = join71(args.contentRoot.replace(/\/+$/g, ""), "SKILL.md");
|
|
11623
11773
|
try {
|
|
11624
11774
|
const skillStat = await stat6(skillFile);
|
|
11625
11775
|
if (skillStat.isFile()) {
|
|
11776
|
+
const fmName = await readSkillFrontmatterName(skillFile);
|
|
11626
11777
|
return {
|
|
11627
|
-
pathInRepo: trimDot(
|
|
11628
|
-
pick: { skills: [basename46(skillDir)] }
|
|
11778
|
+
pathInRepo: trimDot(dirname26(skillDir)),
|
|
11779
|
+
pick: { skills: [fmName || basename46(skillDir)] }
|
|
11629
11780
|
};
|
|
11630
11781
|
}
|
|
11631
11782
|
} catch {
|
|
@@ -11693,7 +11844,7 @@ async function runInstall(flags, args, projectRoot, replay) {
|
|
|
11693
11844
|
sourceArg
|
|
11694
11845
|
);
|
|
11695
11846
|
const pathInRepo = parsed.pathInRepo.replace(/^\/+|\/+$/g, "");
|
|
11696
|
-
const contentRoot = pathInRepo ?
|
|
11847
|
+
const contentRoot = pathInRepo ? join72(resolvedPath, pathInRepo) : resolvedPath;
|
|
11697
11848
|
if (!await exists(contentRoot)) {
|
|
11698
11849
|
throw new Error(`Install path does not exist: ${contentRoot}`);
|
|
11699
11850
|
}
|