@skild/core 0.10.22 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +84 -0
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -331,6 +331,7 @@ import fs6 from "fs";
331
331
  import os2 from "os";
332
332
  import path7 from "path";
333
333
  import degit from "degit";
334
+ import simpleGit from "simple-git";
334
335
 
335
336
  // src/source.ts
336
337
  import path6 from "path";
@@ -491,6 +492,81 @@ function resetTargetDir(targetPath) {
491
492
  removeDir(targetPath);
492
493
  fs6.mkdirSync(targetPath, { recursive: true });
493
494
  }
495
+ function splitSourceRef(source) {
496
+ const [base, ref] = source.split("#", 2);
497
+ return { base, ref: ref?.trim() || void 0 };
498
+ }
499
+ function parseGitCloneSpec(source) {
500
+ const trimmed = source.trim();
501
+ if (!trimmed) return null;
502
+ if (resolveLocalPath(trimmed)) return null;
503
+ const { base, ref } = splitSourceRef(trimmed);
504
+ const githubTreeWithPathMatch = base.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/);
505
+ if (githubTreeWithPathMatch) {
506
+ const [, owner, repo, branch, subpath] = githubTreeWithPathMatch;
507
+ return { url: `https://github.com/${owner}/${repo}.git`, ref: branch, subpath };
508
+ }
509
+ const githubTreeMatch = base.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)$/);
510
+ if (githubTreeMatch) {
511
+ const [, owner, repo, branch] = githubTreeMatch;
512
+ return { url: `https://github.com/${owner}/${repo}.git`, ref: branch };
513
+ }
514
+ const githubRepoMatch = base.match(/github\.com\/([^/]+)\/([^/]+)/);
515
+ if (githubRepoMatch) {
516
+ const [, owner, repoRaw] = githubRepoMatch;
517
+ const repo = repoRaw.replace(/\.git$/, "");
518
+ return { url: `https://github.com/${owner}/${repo}.git`, ref };
519
+ }
520
+ const gitlabTreeWithPathMatch = base.match(/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)\/(.+)/);
521
+ if (gitlabTreeWithPathMatch) {
522
+ const [, owner, repo, branch, subpath] = gitlabTreeWithPathMatch;
523
+ return { url: `https://gitlab.com/${owner}/${repo}.git`, ref: branch, subpath };
524
+ }
525
+ const gitlabTreeMatch = base.match(/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)$/);
526
+ if (gitlabTreeMatch) {
527
+ const [, owner, repo, branch] = gitlabTreeMatch;
528
+ return { url: `https://gitlab.com/${owner}/${repo}.git`, ref: branch };
529
+ }
530
+ const gitlabRepoMatch = base.match(/gitlab\.com\/([^/]+)\/([^/]+)/);
531
+ if (gitlabRepoMatch) {
532
+ const [, owner, repoRaw] = gitlabRepoMatch;
533
+ const repo = repoRaw.replace(/\.git$/, "");
534
+ return { url: `https://gitlab.com/${owner}/${repo}.git`, ref };
535
+ }
536
+ const shorthandMatch = base.match(/^([^/]+)\/([^/]+)(?:\/(.+))?$/);
537
+ if (shorthandMatch && !base.includes(":") && !base.startsWith(".") && !base.startsWith("/")) {
538
+ const [, owner, repo, subpath] = shorthandMatch;
539
+ return { url: `https://github.com/${owner}/${repo}.git`, ref, subpath };
540
+ }
541
+ if (/^(https?:|git@|ssh:)/i.test(base)) {
542
+ return { url: base, ref };
543
+ }
544
+ return null;
545
+ }
546
+ async function cloneWithGit(spec, targetPath) {
547
+ const cloneOptions = spec.ref ? ["--depth", "1", "--branch", spec.ref] : ["--depth", "1"];
548
+ const git = simpleGit();
549
+ if (!spec.subpath) {
550
+ resetTargetDir(targetPath);
551
+ await git.clone(spec.url, targetPath, cloneOptions);
552
+ return spec.url;
553
+ }
554
+ const tempRoot = createTempDir(path7.join(os2.tmpdir(), "skild-git"), extractSkillName(spec.url));
555
+ try {
556
+ await git.clone(spec.url, tempRoot, cloneOptions);
557
+ const resolvedSubpath = path7.resolve(tempRoot, spec.subpath);
558
+ const resolvedRoot = path7.resolve(tempRoot);
559
+ if (!resolvedSubpath.startsWith(`${resolvedRoot}${path7.sep}`)) {
560
+ throw new SkildError("INVALID_SOURCE", `Subpath escapes repository root: ${spec.subpath}`, { subpath: spec.subpath });
561
+ }
562
+ ensureInstallableDir(resolvedSubpath);
563
+ resetTargetDir(targetPath);
564
+ copyDir(resolvedSubpath, targetPath);
565
+ return spec.url;
566
+ } finally {
567
+ removeDir(tempRoot);
568
+ }
569
+ }
494
570
  async function cloneRemote(degitSrc, targetPath, mode) {
495
571
  const emitter = degit(degitSrc, { force: true, verbose: false, mode });
496
572
  await emitter.clone(targetPath);
@@ -543,6 +619,14 @@ async function materializeSourceToDir(input) {
543
619
  copyDir(localPath, targetDir);
544
620
  return { sourceType: "local", materializedFrom: localPath };
545
621
  }
622
+ const gitSpec = parseGitCloneSpec(input.source);
623
+ if (gitSpec) {
624
+ try {
625
+ const materializedFrom2 = await cloneWithGit(gitSpec, targetDir);
626
+ return { sourceType, materializedFrom: materializedFrom2 };
627
+ } catch {
628
+ }
629
+ }
546
630
  const degitPath = toDegitPath(input.source);
547
631
  const materializedFrom = await cloneRemoteWithFallback(degitPath, targetDir);
548
632
  return { sourceType, materializedFrom };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skild/core",
3
- "version": "0.10.22",
3
+ "version": "0.11.0",
4
4
  "description": "Skild core library (headless) for installing, validating, and managing Agent Skills locally.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,6 +20,7 @@
20
20
  "degit": "^2.8.4",
21
21
  "js-yaml": "^4.1.0",
22
22
  "semver": "^7.6.3",
23
+ "simple-git": "^3.27.0",
23
24
  "tar": "^7.4.3"
24
25
  },
25
26
  "devDependencies": {