@skillkit/core 1.10.0 → 1.12.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.
- package/dist/index.d.ts +166 -1
- package/dist/index.js +519 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -284,7 +284,7 @@ var init_local_models = __esm({
|
|
|
284
284
|
if (done) break;
|
|
285
285
|
const canContinue = fileStream.write(Buffer.from(value));
|
|
286
286
|
if (!canContinue) {
|
|
287
|
-
await new Promise((
|
|
287
|
+
await new Promise((resolve6) => fileStream.once("drain", resolve6));
|
|
288
288
|
}
|
|
289
289
|
downloaded += value.length;
|
|
290
290
|
onProgress?.({
|
|
@@ -295,8 +295,8 @@ var init_local_models = __esm({
|
|
|
295
295
|
});
|
|
296
296
|
}
|
|
297
297
|
fileStream.end();
|
|
298
|
-
await new Promise((
|
|
299
|
-
fileStream.on("finish",
|
|
298
|
+
await new Promise((resolve6, reject) => {
|
|
299
|
+
fileStream.on("finish", resolve6);
|
|
300
300
|
fileStream.on("error", reject);
|
|
301
301
|
});
|
|
302
302
|
await fs.promises.rename(tempPath, modelPath);
|
|
@@ -3658,7 +3658,7 @@ function getConfigFormat(agent) {
|
|
|
3658
3658
|
|
|
3659
3659
|
// src/skills.ts
|
|
3660
3660
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
3661
|
-
import { join, basename } from "path";
|
|
3661
|
+
import { join, basename, resolve, sep } from "path";
|
|
3662
3662
|
import { parse as parseYaml } from "yaml";
|
|
3663
3663
|
var SKILL_DISCOVERY_PATHS = [
|
|
3664
3664
|
"skills",
|
|
@@ -3971,8 +3971,9 @@ function validateSkill(skillPath) {
|
|
|
3971
3971
|
return { valid: errors.length === 0, errors, warnings };
|
|
3972
3972
|
}
|
|
3973
3973
|
function isPathInside(child, parent) {
|
|
3974
|
-
const
|
|
3975
|
-
|
|
3974
|
+
const resolved = resolve(child);
|
|
3975
|
+
const resolvedParent = resolve(parent);
|
|
3976
|
+
return resolved === resolvedParent || resolved.startsWith(resolvedParent + sep);
|
|
3976
3977
|
}
|
|
3977
3978
|
|
|
3978
3979
|
// src/config.ts
|
|
@@ -4368,7 +4369,7 @@ var BitbucketProvider = class {
|
|
|
4368
4369
|
|
|
4369
4370
|
// src/providers/local.ts
|
|
4370
4371
|
import { existsSync as existsSync6, statSync, realpathSync } from "fs";
|
|
4371
|
-
import { join as join6, resolve, basename as basename5 } from "path";
|
|
4372
|
+
import { join as join6, resolve as resolve2, basename as basename5 } from "path";
|
|
4372
4373
|
import { homedir as homedir2 } from "os";
|
|
4373
4374
|
var LocalProvider = class {
|
|
4374
4375
|
type = "local";
|
|
@@ -4382,7 +4383,7 @@ var LocalProvider = class {
|
|
|
4382
4383
|
if (source.startsWith("~/")) {
|
|
4383
4384
|
expandedPath = join6(homedir2(), source.slice(2));
|
|
4384
4385
|
}
|
|
4385
|
-
const absolutePath =
|
|
4386
|
+
const absolutePath = resolve2(expandedPath);
|
|
4386
4387
|
const dirName = basename5(absolutePath);
|
|
4387
4388
|
return {
|
|
4388
4389
|
owner: "local",
|
|
@@ -4438,7 +4439,7 @@ var LocalProvider = class {
|
|
|
4438
4439
|
|
|
4439
4440
|
// src/providers/wellknown.ts
|
|
4440
4441
|
import { existsSync as existsSync7, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, rmSync as rmSync4 } from "fs";
|
|
4441
|
-
import { join as join7, basename as basename6, resolve as
|
|
4442
|
+
import { join as join7, basename as basename6, resolve as resolve3, sep as sep2 } from "path";
|
|
4442
4443
|
import { tmpdir as tmpdir4 } from "os";
|
|
4443
4444
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
4444
4445
|
function sanitizeSkillName(name) {
|
|
@@ -4521,9 +4522,9 @@ var WellKnownProvider = class {
|
|
|
4521
4522
|
continue;
|
|
4522
4523
|
}
|
|
4523
4524
|
const skillDir = join7(tempDir, safeName);
|
|
4524
|
-
const resolvedSkillDir =
|
|
4525
|
-
const resolvedTempDir =
|
|
4526
|
-
if (!resolvedSkillDir.startsWith(resolvedTempDir +
|
|
4525
|
+
const resolvedSkillDir = resolve3(skillDir);
|
|
4526
|
+
const resolvedTempDir = resolve3(tempDir);
|
|
4527
|
+
if (!resolvedSkillDir.startsWith(resolvedTempDir + sep2) && resolvedSkillDir !== resolvedTempDir) {
|
|
4527
4528
|
continue;
|
|
4528
4529
|
}
|
|
4529
4530
|
mkdirSync2(skillDir, { recursive: true });
|
|
@@ -4591,7 +4592,7 @@ function generateWellKnownIndex(skills) {
|
|
|
4591
4592
|
}
|
|
4592
4593
|
function generateWellKnownStructure(outputDir, skills) {
|
|
4593
4594
|
const wellKnownDir = join7(outputDir, ".well-known", "skills");
|
|
4594
|
-
const resolvedWellKnownDir =
|
|
4595
|
+
const resolvedWellKnownDir = resolve3(wellKnownDir);
|
|
4595
4596
|
mkdirSync2(wellKnownDir, { recursive: true });
|
|
4596
4597
|
const indexSkills = [];
|
|
4597
4598
|
const skillPaths = [];
|
|
@@ -4601,8 +4602,8 @@ function generateWellKnownStructure(outputDir, skills) {
|
|
|
4601
4602
|
continue;
|
|
4602
4603
|
}
|
|
4603
4604
|
const skillDir = join7(wellKnownDir, safeName);
|
|
4604
|
-
const resolvedSkillDir =
|
|
4605
|
-
if (!resolvedSkillDir.startsWith(resolvedWellKnownDir +
|
|
4605
|
+
const resolvedSkillDir = resolve3(skillDir);
|
|
4606
|
+
if (!resolvedSkillDir.startsWith(resolvedWellKnownDir + sep2) && resolvedSkillDir !== resolvedWellKnownDir) {
|
|
4606
4607
|
continue;
|
|
4607
4608
|
}
|
|
4608
4609
|
mkdirSync2(skillDir, { recursive: true });
|
|
@@ -8402,7 +8403,7 @@ var SkillExecutionEngine = class {
|
|
|
8402
8403
|
const startTime = /* @__PURE__ */ new Date();
|
|
8403
8404
|
const taskId = task.id || randomUUID7();
|
|
8404
8405
|
try {
|
|
8405
|
-
await new Promise((
|
|
8406
|
+
await new Promise((resolve6) => setTimeout(resolve6, 100));
|
|
8406
8407
|
const endTime = /* @__PURE__ */ new Date();
|
|
8407
8408
|
return {
|
|
8408
8409
|
taskId,
|
|
@@ -8739,7 +8740,7 @@ async function executeWithAgent(agentType, prompt, options = {}) {
|
|
|
8739
8740
|
});
|
|
8740
8741
|
}
|
|
8741
8742
|
async function executeCommand(command, args, options = {}) {
|
|
8742
|
-
return new Promise((
|
|
8743
|
+
return new Promise((resolve6) => {
|
|
8743
8744
|
const startTime = Date.now();
|
|
8744
8745
|
let stdout = "";
|
|
8745
8746
|
let stderr = "";
|
|
@@ -8762,7 +8763,7 @@ async function executeCommand(command, args, options = {}) {
|
|
|
8762
8763
|
});
|
|
8763
8764
|
child.on("error", (error) => {
|
|
8764
8765
|
if (timeoutId) clearTimeout(timeoutId);
|
|
8765
|
-
|
|
8766
|
+
resolve6({
|
|
8766
8767
|
success: false,
|
|
8767
8768
|
output: stdout,
|
|
8768
8769
|
error: error.message,
|
|
@@ -8772,7 +8773,7 @@ async function executeCommand(command, args, options = {}) {
|
|
|
8772
8773
|
});
|
|
8773
8774
|
child.on("close", (code) => {
|
|
8774
8775
|
if (timeoutId) clearTimeout(timeoutId);
|
|
8775
|
-
|
|
8776
|
+
resolve6({
|
|
8776
8777
|
success: code === 0 && !timedOut,
|
|
8777
8778
|
output: stdout,
|
|
8778
8779
|
error: timedOut ? "Execution timed out" : stderr || void 0,
|
|
@@ -8967,7 +8968,7 @@ function createSimulatedSkillExecutor(options = {}) {
|
|
|
8967
8968
|
const { delay = 100, shouldFail, onExecute } = options;
|
|
8968
8969
|
return async (skillName, _config) => {
|
|
8969
8970
|
onExecute?.(skillName);
|
|
8970
|
-
await new Promise((
|
|
8971
|
+
await new Promise((resolve6) => setTimeout(resolve6, delay));
|
|
8971
8972
|
const failed = shouldFail?.(skillName) ?? false;
|
|
8972
8973
|
return {
|
|
8973
8974
|
success: !failed,
|
|
@@ -9416,12 +9417,12 @@ function assertEnvVarSet(assertion, startTime) {
|
|
|
9416
9417
|
};
|
|
9417
9418
|
}
|
|
9418
9419
|
async function checkPortAvailable(port) {
|
|
9419
|
-
return new Promise((
|
|
9420
|
+
return new Promise((resolve6) => {
|
|
9420
9421
|
const server = createServer();
|
|
9421
|
-
server.once("error", () =>
|
|
9422
|
+
server.once("error", () => resolve6(false));
|
|
9422
9423
|
server.once("listening", () => {
|
|
9423
9424
|
server.close();
|
|
9424
|
-
|
|
9425
|
+
resolve6(true);
|
|
9425
9426
|
});
|
|
9426
9427
|
server.listen(port, "127.0.0.1");
|
|
9427
9428
|
});
|
|
@@ -13195,7 +13196,7 @@ function createTeamManager(projectPath) {
|
|
|
13195
13196
|
|
|
13196
13197
|
// src/team/bundle.ts
|
|
13197
13198
|
import { existsSync as existsSync27, readFileSync as readFileSync17, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
|
|
13198
|
-
import { join as join26, basename as basename9, resolve as
|
|
13199
|
+
import { join as join26, basename as basename9, resolve as resolve4, relative, dirname as dirname8, sep as sep3 } from "path";
|
|
13199
13200
|
import { createHash } from "crypto";
|
|
13200
13201
|
var BUNDLE_VERSION = 1;
|
|
13201
13202
|
var SkillBundle = class {
|
|
@@ -13360,7 +13361,7 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
13360
13361
|
try {
|
|
13361
13362
|
const content = readFileSync17(bundlePath, "utf-8");
|
|
13362
13363
|
const data = JSON.parse(content);
|
|
13363
|
-
const absoluteTargetDir =
|
|
13364
|
+
const absoluteTargetDir = resolve4(targetDir);
|
|
13364
13365
|
for (const skill of data.manifest.skills) {
|
|
13365
13366
|
if (!skill.name || skill.name.includes("/") || skill.name.includes("\\") || skill.name === ".." || skill.name === "." || skill.name.startsWith(".")) {
|
|
13366
13367
|
errors.push(`Skill has invalid name: ${skill.name}`);
|
|
@@ -13372,9 +13373,9 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
13372
13373
|
continue;
|
|
13373
13374
|
}
|
|
13374
13375
|
const skillDir = join26(absoluteTargetDir, skill.name);
|
|
13375
|
-
const resolvedSkillDir =
|
|
13376
|
+
const resolvedSkillDir = resolve4(skillDir);
|
|
13376
13377
|
const relativeToTarget = relative(absoluteTargetDir, resolvedSkillDir);
|
|
13377
|
-
if (relativeToTarget.startsWith("..") || relativeToTarget.startsWith(
|
|
13378
|
+
if (relativeToTarget.startsWith("..") || relativeToTarget.startsWith(sep3)) {
|
|
13378
13379
|
errors.push(`Skill "${skill.name}" would escape target directory`);
|
|
13379
13380
|
continue;
|
|
13380
13381
|
}
|
|
@@ -13387,9 +13388,9 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
13387
13388
|
}
|
|
13388
13389
|
const files = parseSkillContent2(skillContent);
|
|
13389
13390
|
for (const [filePath, fileContent] of Object.entries(files)) {
|
|
13390
|
-
const fullPath =
|
|
13391
|
+
const fullPath = resolve4(skillDir, filePath);
|
|
13391
13392
|
const relativeToSkill = relative(skillDir, fullPath);
|
|
13392
|
-
if (relativeToSkill.startsWith("..") || relativeToSkill.startsWith(
|
|
13393
|
+
if (relativeToSkill.startsWith("..") || relativeToSkill.startsWith(sep3)) {
|
|
13393
13394
|
errors.push(`Skill "${skill.name}" contains invalid file path: ${filePath}`);
|
|
13394
13395
|
continue;
|
|
13395
13396
|
}
|
|
@@ -17856,8 +17857,8 @@ var PlanExecutor = class {
|
|
|
17856
17857
|
pause() {
|
|
17857
17858
|
if (!this.isPaused) {
|
|
17858
17859
|
this.isPaused = true;
|
|
17859
|
-
this.resumePromise = new Promise((
|
|
17860
|
-
this.resumeResolve =
|
|
17860
|
+
this.resumePromise = new Promise((resolve6) => {
|
|
17861
|
+
this.resumeResolve = resolve6;
|
|
17861
17862
|
});
|
|
17862
17863
|
this.emit("plan:paused", {});
|
|
17863
17864
|
}
|
|
@@ -20541,7 +20542,7 @@ function loadAndConvertSkill(skill, options) {
|
|
|
20541
20542
|
|
|
20542
20543
|
// src/skill-translator.ts
|
|
20543
20544
|
import { readFileSync as readFileSync25, existsSync as existsSync36, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
|
|
20544
|
-
import { join as join37, basename as basename12, dirname as dirname12, resolve as
|
|
20545
|
+
import { join as join37, basename as basename12, dirname as dirname12, resolve as resolve5, relative as relative3, isAbsolute as isAbsolute2 } from "path";
|
|
20545
20546
|
import { parse as parseYaml11, stringify as stringifyYaml8 } from "yaml";
|
|
20546
20547
|
var AGENT_SKILL_FORMATS = Object.fromEntries(
|
|
20547
20548
|
Object.entries(AGENT_CONFIG).map(([agent, config]) => [
|
|
@@ -20780,8 +20781,8 @@ function writeTranslatedSkill(result, rootDir, options) {
|
|
|
20780
20781
|
};
|
|
20781
20782
|
}
|
|
20782
20783
|
try {
|
|
20783
|
-
const rootPath =
|
|
20784
|
-
const filePath =
|
|
20784
|
+
const rootPath = resolve5(rootDir);
|
|
20785
|
+
const filePath = resolve5(rootDir, result.targetDir, result.filename);
|
|
20785
20786
|
const targetPath = dirname12(filePath);
|
|
20786
20787
|
const relPath = relative3(rootPath, filePath);
|
|
20787
20788
|
if (relPath.startsWith("..") || isAbsolute2(relPath)) {
|
|
@@ -21930,7 +21931,7 @@ var AGENT_INSTRUCTION_TEMPLATES = {
|
|
|
21930
21931
|
|
|
21931
21932
|
// src/primer/analyzer.ts
|
|
21932
21933
|
import { existsSync as existsSync39, readFileSync as readFileSync28, readdirSync as readdirSync11 } from "fs";
|
|
21933
|
-
import { join as join40, basename as basename14, relative as relative4, sep as
|
|
21934
|
+
import { join as join40, basename as basename14, relative as relative4, sep as sep4 } from "path";
|
|
21934
21935
|
var PACKAGE_MANAGER_FILES = {
|
|
21935
21936
|
"package-lock.json": "npm",
|
|
21936
21937
|
"pnpm-lock.yaml": "pnpm",
|
|
@@ -22418,7 +22419,7 @@ var PrimerAnalyzer = class {
|
|
|
22418
22419
|
let files = 0;
|
|
22419
22420
|
let directories = 0;
|
|
22420
22421
|
for (const file of this.files) {
|
|
22421
|
-
if (file.includes(
|
|
22422
|
+
if (file.includes(sep4)) {
|
|
22422
22423
|
directories++;
|
|
22423
22424
|
}
|
|
22424
22425
|
files++;
|
|
@@ -25458,7 +25459,7 @@ var ExecutionManager = class {
|
|
|
25458
25459
|
this.metrics.stepMetrics.set(stepName, existing);
|
|
25459
25460
|
}
|
|
25460
25461
|
delay(ms) {
|
|
25461
|
-
return new Promise((
|
|
25462
|
+
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
25462
25463
|
}
|
|
25463
25464
|
};
|
|
25464
25465
|
function createExecutionManager(config) {
|
|
@@ -25657,6 +25658,477 @@ init_vector_store();
|
|
|
25657
25658
|
init_rrf();
|
|
25658
25659
|
init_expansion();
|
|
25659
25660
|
init_hybrid();
|
|
25661
|
+
|
|
25662
|
+
// src/registry/community.ts
|
|
25663
|
+
import { readFileSync as readFileSync34, existsSync as existsSync48 } from "fs";
|
|
25664
|
+
import { join as join48, dirname as dirname19 } from "path";
|
|
25665
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
25666
|
+
var CommunityRegistry = class {
|
|
25667
|
+
constructor(skillsMdPath) {
|
|
25668
|
+
this.skillsMdPath = skillsMdPath;
|
|
25669
|
+
}
|
|
25670
|
+
name = "community";
|
|
25671
|
+
entries = [];
|
|
25672
|
+
loaded = false;
|
|
25673
|
+
load() {
|
|
25674
|
+
if (this.loaded) return;
|
|
25675
|
+
this.loaded = true;
|
|
25676
|
+
const paths = this.skillsMdPath ? [this.skillsMdPath] : [
|
|
25677
|
+
join48(process.cwd(), "registry", "SKILLS.md"),
|
|
25678
|
+
join48(dirname19(fileURLToPath2(import.meta.url)), "..", "..", "..", "..", "registry", "SKILLS.md")
|
|
25679
|
+
];
|
|
25680
|
+
for (const path4 of paths) {
|
|
25681
|
+
if (!existsSync48(path4)) continue;
|
|
25682
|
+
try {
|
|
25683
|
+
const content = readFileSync34(path4, "utf-8");
|
|
25684
|
+
this.entries = this.parse(content);
|
|
25685
|
+
return;
|
|
25686
|
+
} catch {
|
|
25687
|
+
continue;
|
|
25688
|
+
}
|
|
25689
|
+
}
|
|
25690
|
+
}
|
|
25691
|
+
parse(content) {
|
|
25692
|
+
const results = [];
|
|
25693
|
+
let currentCategory = "";
|
|
25694
|
+
for (const line of content.split("\n")) {
|
|
25695
|
+
const headerMatch = line.match(/^##\s+(.+)/);
|
|
25696
|
+
if (headerMatch) {
|
|
25697
|
+
currentCategory = headerMatch[1].trim();
|
|
25698
|
+
continue;
|
|
25699
|
+
}
|
|
25700
|
+
const entryMatch = line.match(/^-\s+\[([^\]]+)\]\(([^)]+)\)\s*-\s*(.+)/);
|
|
25701
|
+
if (entryMatch) {
|
|
25702
|
+
results.push({
|
|
25703
|
+
name: entryMatch[1].trim(),
|
|
25704
|
+
url: entryMatch[2].trim(),
|
|
25705
|
+
description: entryMatch[3].trim(),
|
|
25706
|
+
category: currentCategory
|
|
25707
|
+
});
|
|
25708
|
+
}
|
|
25709
|
+
}
|
|
25710
|
+
return results;
|
|
25711
|
+
}
|
|
25712
|
+
async search(query, options) {
|
|
25713
|
+
this.load();
|
|
25714
|
+
const limit = options?.limit ?? 20;
|
|
25715
|
+
const q = query.toLowerCase();
|
|
25716
|
+
const matched = this.entries.filter(
|
|
25717
|
+
(e) => e.name.toLowerCase().includes(q) || e.description.toLowerCase().includes(q) || e.category.toLowerCase().includes(q)
|
|
25718
|
+
);
|
|
25719
|
+
return matched.slice(0, limit).map((e) => ({
|
|
25720
|
+
name: e.name,
|
|
25721
|
+
description: e.description,
|
|
25722
|
+
source: e.url,
|
|
25723
|
+
registry: this.name
|
|
25724
|
+
}));
|
|
25725
|
+
}
|
|
25726
|
+
getAll() {
|
|
25727
|
+
this.load();
|
|
25728
|
+
return [...this.entries];
|
|
25729
|
+
}
|
|
25730
|
+
getCategories() {
|
|
25731
|
+
this.load();
|
|
25732
|
+
return [...new Set(this.entries.map((e) => e.category))];
|
|
25733
|
+
}
|
|
25734
|
+
};
|
|
25735
|
+
|
|
25736
|
+
// src/registry/index.ts
|
|
25737
|
+
var RateLimitError = class extends Error {
|
|
25738
|
+
constructor(registry) {
|
|
25739
|
+
super(`Rate limited by ${registry} API. Authenticate with a token or wait before retrying.`);
|
|
25740
|
+
this.name = "RateLimitError";
|
|
25741
|
+
}
|
|
25742
|
+
};
|
|
25743
|
+
var GitHubSkillRegistry = class {
|
|
25744
|
+
name = "github";
|
|
25745
|
+
baseUrl = "https://api.github.com";
|
|
25746
|
+
async search(query, options) {
|
|
25747
|
+
const limit = options?.limit ?? 20;
|
|
25748
|
+
const timeoutMs = options?.timeoutMs ?? 1e4;
|
|
25749
|
+
const searchQuery = `SKILL.md ${query} in:path,file`;
|
|
25750
|
+
const controller = new AbortController();
|
|
25751
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
25752
|
+
try {
|
|
25753
|
+
const headers = {
|
|
25754
|
+
Accept: "application/vnd.github.v3+json",
|
|
25755
|
+
"User-Agent": "skillkit-cli"
|
|
25756
|
+
};
|
|
25757
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
25758
|
+
if (token) {
|
|
25759
|
+
headers.Authorization = `Bearer ${token}`;
|
|
25760
|
+
}
|
|
25761
|
+
const response = await fetch(
|
|
25762
|
+
`${this.baseUrl}/search/code?q=${encodeURIComponent(searchQuery)}&per_page=${limit}`,
|
|
25763
|
+
{
|
|
25764
|
+
headers,
|
|
25765
|
+
signal: controller.signal
|
|
25766
|
+
}
|
|
25767
|
+
);
|
|
25768
|
+
clearTimeout(timer);
|
|
25769
|
+
if (!response.ok) {
|
|
25770
|
+
if (response.status === 403) {
|
|
25771
|
+
throw new RateLimitError(this.name);
|
|
25772
|
+
}
|
|
25773
|
+
return [];
|
|
25774
|
+
}
|
|
25775
|
+
const data = await response.json();
|
|
25776
|
+
if (!data.items) return [];
|
|
25777
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25778
|
+
const skills = [];
|
|
25779
|
+
for (const item of data.items) {
|
|
25780
|
+
const repo = item.repository.full_name;
|
|
25781
|
+
if (seen.has(repo)) continue;
|
|
25782
|
+
seen.add(repo);
|
|
25783
|
+
const pathParts = item.path.split("/");
|
|
25784
|
+
const skillName = pathParts.length > 1 ? pathParts[pathParts.length - 2] : repo.split("/").pop() || repo;
|
|
25785
|
+
skills.push({
|
|
25786
|
+
name: skillName,
|
|
25787
|
+
description: item.repository.description || "",
|
|
25788
|
+
source: item.repository.html_url,
|
|
25789
|
+
registry: this.name,
|
|
25790
|
+
path: item.path,
|
|
25791
|
+
stars: item.repository.stargazers_count,
|
|
25792
|
+
updatedAt: item.repository.updated_at
|
|
25793
|
+
});
|
|
25794
|
+
}
|
|
25795
|
+
return skills;
|
|
25796
|
+
} catch (err) {
|
|
25797
|
+
clearTimeout(timer);
|
|
25798
|
+
if (err instanceof RateLimitError) throw err;
|
|
25799
|
+
return [];
|
|
25800
|
+
}
|
|
25801
|
+
}
|
|
25802
|
+
};
|
|
25803
|
+
var FederatedSearch = class {
|
|
25804
|
+
registries = [];
|
|
25805
|
+
addRegistry(registry) {
|
|
25806
|
+
this.registries.push(registry);
|
|
25807
|
+
}
|
|
25808
|
+
async search(query, options) {
|
|
25809
|
+
const limit = options?.limit ?? 20;
|
|
25810
|
+
const results = await Promise.allSettled(
|
|
25811
|
+
this.registries.map((r) => r.search(query, { limit }))
|
|
25812
|
+
);
|
|
25813
|
+
const allSkills = [];
|
|
25814
|
+
const activeRegistries = [];
|
|
25815
|
+
for (let i = 0; i < results.length; i++) {
|
|
25816
|
+
const result = results[i];
|
|
25817
|
+
if (result.status === "fulfilled" && result.value.length > 0) {
|
|
25818
|
+
allSkills.push(...result.value);
|
|
25819
|
+
activeRegistries.push(this.registries[i].name);
|
|
25820
|
+
} else if (result.status === "rejected" && result.reason instanceof RateLimitError) {
|
|
25821
|
+
throw result.reason;
|
|
25822
|
+
}
|
|
25823
|
+
}
|
|
25824
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25825
|
+
const deduplicated = [];
|
|
25826
|
+
for (const skill of allSkills) {
|
|
25827
|
+
const key = `${skill.source}:${skill.name}`;
|
|
25828
|
+
if (!seen.has(key)) {
|
|
25829
|
+
seen.add(key);
|
|
25830
|
+
deduplicated.push(skill);
|
|
25831
|
+
}
|
|
25832
|
+
}
|
|
25833
|
+
deduplicated.sort((a, b) => (b.stars ?? 0) - (a.stars ?? 0));
|
|
25834
|
+
return {
|
|
25835
|
+
skills: deduplicated.slice(0, limit),
|
|
25836
|
+
registries: activeRegistries,
|
|
25837
|
+
total: deduplicated.length,
|
|
25838
|
+
query
|
|
25839
|
+
};
|
|
25840
|
+
}
|
|
25841
|
+
};
|
|
25842
|
+
|
|
25843
|
+
// src/cache/memory.ts
|
|
25844
|
+
var DEFAULT_MAX_SIZE = 1e3;
|
|
25845
|
+
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
25846
|
+
var MemoryCache = class {
|
|
25847
|
+
store = /* @__PURE__ */ new Map();
|
|
25848
|
+
maxSize;
|
|
25849
|
+
ttlMs;
|
|
25850
|
+
hitCount = 0;
|
|
25851
|
+
missCount = 0;
|
|
25852
|
+
constructor(options) {
|
|
25853
|
+
this.maxSize = options?.maxSize ?? DEFAULT_MAX_SIZE;
|
|
25854
|
+
this.ttlMs = options?.ttlMs ?? DEFAULT_TTL_MS;
|
|
25855
|
+
}
|
|
25856
|
+
get(key) {
|
|
25857
|
+
const entry = this.store.get(key);
|
|
25858
|
+
if (!entry) {
|
|
25859
|
+
this.missCount++;
|
|
25860
|
+
return void 0;
|
|
25861
|
+
}
|
|
25862
|
+
if (Date.now() > entry.expiresAt) {
|
|
25863
|
+
this.store.delete(key);
|
|
25864
|
+
this.missCount++;
|
|
25865
|
+
return void 0;
|
|
25866
|
+
}
|
|
25867
|
+
entry.lastAccessed = Date.now();
|
|
25868
|
+
this.hitCount++;
|
|
25869
|
+
return entry.value;
|
|
25870
|
+
}
|
|
25871
|
+
set(key, value) {
|
|
25872
|
+
if (this.store.size >= this.maxSize && !this.store.has(key)) {
|
|
25873
|
+
this.evictLRU();
|
|
25874
|
+
}
|
|
25875
|
+
const now = Date.now();
|
|
25876
|
+
this.store.set(key, {
|
|
25877
|
+
value,
|
|
25878
|
+
expiresAt: now + this.ttlMs,
|
|
25879
|
+
lastAccessed: now
|
|
25880
|
+
});
|
|
25881
|
+
}
|
|
25882
|
+
delete(key) {
|
|
25883
|
+
return this.store.delete(key);
|
|
25884
|
+
}
|
|
25885
|
+
has(key) {
|
|
25886
|
+
const entry = this.store.get(key);
|
|
25887
|
+
if (!entry) return false;
|
|
25888
|
+
if (Date.now() > entry.expiresAt) {
|
|
25889
|
+
this.store.delete(key);
|
|
25890
|
+
return false;
|
|
25891
|
+
}
|
|
25892
|
+
return true;
|
|
25893
|
+
}
|
|
25894
|
+
clear() {
|
|
25895
|
+
this.store.clear();
|
|
25896
|
+
this.hitCount = 0;
|
|
25897
|
+
this.missCount = 0;
|
|
25898
|
+
}
|
|
25899
|
+
stats() {
|
|
25900
|
+
const total = this.hitCount + this.missCount;
|
|
25901
|
+
return {
|
|
25902
|
+
hits: this.hitCount,
|
|
25903
|
+
misses: this.missCount,
|
|
25904
|
+
size: this.store.size,
|
|
25905
|
+
maxSize: this.maxSize,
|
|
25906
|
+
hitRate: total > 0 ? this.hitCount / total : 0
|
|
25907
|
+
};
|
|
25908
|
+
}
|
|
25909
|
+
evictLRU() {
|
|
25910
|
+
let oldestKey = null;
|
|
25911
|
+
let oldestTime = Infinity;
|
|
25912
|
+
for (const [key, entry] of this.store) {
|
|
25913
|
+
if (entry.lastAccessed < oldestTime) {
|
|
25914
|
+
oldestTime = entry.lastAccessed;
|
|
25915
|
+
oldestKey = key;
|
|
25916
|
+
}
|
|
25917
|
+
}
|
|
25918
|
+
if (oldestKey) {
|
|
25919
|
+
this.store.delete(oldestKey);
|
|
25920
|
+
}
|
|
25921
|
+
}
|
|
25922
|
+
};
|
|
25923
|
+
|
|
25924
|
+
// src/ranking/relevance.ts
|
|
25925
|
+
var WEIGHTS = {
|
|
25926
|
+
contentAvailability: 40,
|
|
25927
|
+
queryMatch: 30,
|
|
25928
|
+
popularity: 15,
|
|
25929
|
+
references: 15
|
|
25930
|
+
};
|
|
25931
|
+
var RelevanceRanker = class {
|
|
25932
|
+
rank(skills, query) {
|
|
25933
|
+
const results = skills.map((skill) => {
|
|
25934
|
+
const breakdown = this.score(skill, query);
|
|
25935
|
+
const score = breakdown.contentAvailability + breakdown.queryMatch + breakdown.popularity + breakdown.referenceScore;
|
|
25936
|
+
return { skill, score, breakdown };
|
|
25937
|
+
});
|
|
25938
|
+
results.sort((a, b) => b.score - a.score);
|
|
25939
|
+
return results;
|
|
25940
|
+
}
|
|
25941
|
+
score(skill, query) {
|
|
25942
|
+
return {
|
|
25943
|
+
contentAvailability: this.scoreContent(skill),
|
|
25944
|
+
queryMatch: query ? this.scoreQuery(skill, query) : 0,
|
|
25945
|
+
popularity: this.scorePopularity(skill),
|
|
25946
|
+
referenceScore: this.scoreReferences(skill)
|
|
25947
|
+
};
|
|
25948
|
+
}
|
|
25949
|
+
scoreContent(skill) {
|
|
25950
|
+
let score = 0;
|
|
25951
|
+
if (skill.description && skill.description.length > 0) score += 20;
|
|
25952
|
+
if (skill.content && skill.content.length > 0) score += 20;
|
|
25953
|
+
return score;
|
|
25954
|
+
}
|
|
25955
|
+
scoreQuery(skill, query) {
|
|
25956
|
+
const q = query.toLowerCase();
|
|
25957
|
+
const name = skill.name.toLowerCase();
|
|
25958
|
+
if (name === q) return WEIGHTS.queryMatch;
|
|
25959
|
+
if (name.includes(q) || q.includes(name)) {
|
|
25960
|
+
return WEIGHTS.queryMatch * 0.7;
|
|
25961
|
+
}
|
|
25962
|
+
const desc = (skill.description || "").toLowerCase();
|
|
25963
|
+
const content = (skill.content || "").toLowerCase();
|
|
25964
|
+
const searchable = `${name} ${desc} ${content}`;
|
|
25965
|
+
const words = q.split(/\s+/).filter(Boolean);
|
|
25966
|
+
const matched = words.filter((w) => searchable.includes(w)).length;
|
|
25967
|
+
if (words.length === 0) return 0;
|
|
25968
|
+
return Math.round(WEIGHTS.queryMatch * (matched / words.length) * 0.6);
|
|
25969
|
+
}
|
|
25970
|
+
scorePopularity(skill) {
|
|
25971
|
+
const count = (skill.stars ?? 0) + (skill.installs ?? 0);
|
|
25972
|
+
if (count <= 0) return 0;
|
|
25973
|
+
return Math.min(WEIGHTS.popularity, Math.round(Math.log10(count + 1) * 5));
|
|
25974
|
+
}
|
|
25975
|
+
scoreReferences(skill) {
|
|
25976
|
+
if (!skill.references || skill.references.length === 0) return 0;
|
|
25977
|
+
return Math.min(WEIGHTS.references, skill.references.length * 5);
|
|
25978
|
+
}
|
|
25979
|
+
};
|
|
25980
|
+
|
|
25981
|
+
// src/parser/references.ts
|
|
25982
|
+
import { readdirSync as readdirSync12, statSync as statSync9, existsSync as existsSync49 } from "fs";
|
|
25983
|
+
import { join as join49 } from "path";
|
|
25984
|
+
var REFERENCE_DIRS = ["references", "resources", "docs", "examples", "assets", "scripts"];
|
|
25985
|
+
var DIR_TYPE_MAP = {
|
|
25986
|
+
references: "resource",
|
|
25987
|
+
resources: "resource",
|
|
25988
|
+
docs: "doc",
|
|
25989
|
+
examples: "example",
|
|
25990
|
+
assets: "asset",
|
|
25991
|
+
scripts: "resource"
|
|
25992
|
+
};
|
|
25993
|
+
function discoverReferences(skillDir) {
|
|
25994
|
+
const refs = [];
|
|
25995
|
+
for (const dir of REFERENCE_DIRS) {
|
|
25996
|
+
const fullPath = join49(skillDir, dir);
|
|
25997
|
+
if (!existsSync49(fullPath)) continue;
|
|
25998
|
+
try {
|
|
25999
|
+
const stat = statSync9(fullPath);
|
|
26000
|
+
if (!stat.isDirectory()) continue;
|
|
26001
|
+
} catch {
|
|
26002
|
+
continue;
|
|
26003
|
+
}
|
|
26004
|
+
const type = DIR_TYPE_MAP[dir] || "resource";
|
|
26005
|
+
try {
|
|
26006
|
+
const entries = readdirSync12(fullPath);
|
|
26007
|
+
for (const entry of entries) {
|
|
26008
|
+
const entryPath = join49(fullPath, entry);
|
|
26009
|
+
try {
|
|
26010
|
+
const entryStat = statSync9(entryPath);
|
|
26011
|
+
if (entryStat.isFile()) {
|
|
26012
|
+
refs.push({
|
|
26013
|
+
path: join49(dir, entry),
|
|
26014
|
+
type,
|
|
26015
|
+
name: entry
|
|
26016
|
+
});
|
|
26017
|
+
}
|
|
26018
|
+
} catch {
|
|
26019
|
+
continue;
|
|
26020
|
+
}
|
|
26021
|
+
}
|
|
26022
|
+
} catch {
|
|
26023
|
+
continue;
|
|
26024
|
+
}
|
|
26025
|
+
}
|
|
26026
|
+
return refs;
|
|
26027
|
+
}
|
|
26028
|
+
function stripFrontmatter(raw) {
|
|
26029
|
+
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
|
|
26030
|
+
if (!match) {
|
|
26031
|
+
const emptyMatch = raw.match(/^---\r?\n---\r?\n?([\s\S]*)$/);
|
|
26032
|
+
if (emptyMatch) {
|
|
26033
|
+
return { frontmatter: {}, body: emptyMatch[1] };
|
|
26034
|
+
}
|
|
26035
|
+
return { frontmatter: {}, body: raw };
|
|
26036
|
+
}
|
|
26037
|
+
const fmBlock = match[1];
|
|
26038
|
+
const body = match[2];
|
|
26039
|
+
const frontmatter = {};
|
|
26040
|
+
for (const line of fmBlock.split("\n")) {
|
|
26041
|
+
const colonIdx = line.indexOf(":");
|
|
26042
|
+
if (colonIdx === -1) continue;
|
|
26043
|
+
const key = line.slice(0, colonIdx).trim();
|
|
26044
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
26045
|
+
if (key) {
|
|
26046
|
+
frontmatter[key] = value;
|
|
26047
|
+
}
|
|
26048
|
+
}
|
|
26049
|
+
return { frontmatter, body };
|
|
26050
|
+
}
|
|
26051
|
+
function parseSkillMd(raw, skillDir) {
|
|
26052
|
+
const { frontmatter, body } = stripFrontmatter(raw);
|
|
26053
|
+
const references = skillDir ? discoverReferences(skillDir) : [];
|
|
26054
|
+
return {
|
|
26055
|
+
frontmatter,
|
|
26056
|
+
body,
|
|
26057
|
+
references,
|
|
26058
|
+
raw
|
|
26059
|
+
};
|
|
26060
|
+
}
|
|
26061
|
+
|
|
26062
|
+
// src/runtime/injector.ts
|
|
26063
|
+
function parseSource2(source) {
|
|
26064
|
+
const parts = source.replace(/^https?:\/\/github\.com\//, "").split("/");
|
|
26065
|
+
if (parts.length < 2) {
|
|
26066
|
+
throw new Error(`Invalid source format: "${source}". Expected "owner/repo".`);
|
|
26067
|
+
}
|
|
26068
|
+
return { owner: parts[0], repo: parts[1] };
|
|
26069
|
+
}
|
|
26070
|
+
var SkillInjector = class {
|
|
26071
|
+
cache;
|
|
26072
|
+
constructor(cacheTtlMs) {
|
|
26073
|
+
this.cache = new MemoryCache({
|
|
26074
|
+
maxSize: 200,
|
|
26075
|
+
ttlMs: cacheTtlMs ?? 24 * 60 * 60 * 1e3
|
|
26076
|
+
});
|
|
26077
|
+
}
|
|
26078
|
+
async fetch(source, skillId) {
|
|
26079
|
+
const cacheKey = `${source}:${skillId}`;
|
|
26080
|
+
const cached = this.cache.get(cacheKey);
|
|
26081
|
+
if (cached) return cached;
|
|
26082
|
+
const { owner, repo } = parseSource2(source);
|
|
26083
|
+
const raw = await this.fetchRawSkillMd(owner, repo, skillId);
|
|
26084
|
+
const parsed = parseSkillMd(raw);
|
|
26085
|
+
const result = {
|
|
26086
|
+
source: { owner, repo },
|
|
26087
|
+
skillId,
|
|
26088
|
+
parsed,
|
|
26089
|
+
fetchedAt: Date.now()
|
|
26090
|
+
};
|
|
26091
|
+
this.cache.set(cacheKey, result);
|
|
26092
|
+
return result;
|
|
26093
|
+
}
|
|
26094
|
+
async inject(source, skillId) {
|
|
26095
|
+
const fetched = await this.fetch(source, skillId);
|
|
26096
|
+
return fetched.parsed.body;
|
|
26097
|
+
}
|
|
26098
|
+
async fetchRawSkillMd(owner, repo, skillId) {
|
|
26099
|
+
const paths = [
|
|
26100
|
+
`${skillId}/SKILL.md`,
|
|
26101
|
+
`skills/${skillId}/SKILL.md`,
|
|
26102
|
+
`SKILL.md`
|
|
26103
|
+
];
|
|
26104
|
+
const headers = {
|
|
26105
|
+
Accept: "application/vnd.github.v3.raw",
|
|
26106
|
+
"User-Agent": "skillkit-runtime"
|
|
26107
|
+
};
|
|
26108
|
+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
26109
|
+
if (token) {
|
|
26110
|
+
headers.Authorization = `Bearer ${token}`;
|
|
26111
|
+
}
|
|
26112
|
+
for (const path4 of paths) {
|
|
26113
|
+
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path4}`;
|
|
26114
|
+
try {
|
|
26115
|
+
const response = await fetch(url, { headers });
|
|
26116
|
+
if (response.ok) {
|
|
26117
|
+
return await response.text();
|
|
26118
|
+
}
|
|
26119
|
+
} catch {
|
|
26120
|
+
continue;
|
|
26121
|
+
}
|
|
26122
|
+
}
|
|
26123
|
+
throw new Error(`SKILL.md not found in ${owner}/${repo} for skill "${skillId}"`);
|
|
26124
|
+
}
|
|
26125
|
+
clearCache() {
|
|
26126
|
+
this.cache.clear();
|
|
26127
|
+
}
|
|
26128
|
+
cacheStats() {
|
|
26129
|
+
return this.cache.stats();
|
|
26130
|
+
}
|
|
26131
|
+
};
|
|
25660
26132
|
export {
|
|
25661
26133
|
AGENT_CLI_CONFIGS,
|
|
25662
26134
|
AGENT_CONFIG,
|
|
@@ -25687,6 +26159,7 @@ export {
|
|
|
25687
26159
|
CUSTOM_AGENT_FORMAT_MAP,
|
|
25688
26160
|
CommandGenerator,
|
|
25689
26161
|
CommandRegistry,
|
|
26162
|
+
CommunityRegistry,
|
|
25690
26163
|
ConnectorCategorySchema,
|
|
25691
26164
|
ConnectorConfigSchema,
|
|
25692
26165
|
ConnectorMappingSchema,
|
|
@@ -25713,9 +26186,11 @@ export {
|
|
|
25713
26186
|
ExecutionManager,
|
|
25714
26187
|
ExecutionStepSchema,
|
|
25715
26188
|
ExecutionStepStatusSchema,
|
|
26189
|
+
FederatedSearch,
|
|
25716
26190
|
GITHUB_ACTION_TEMPLATE,
|
|
25717
26191
|
GITLAB_CI_TEMPLATE,
|
|
25718
26192
|
GitHubProvider,
|
|
26193
|
+
GitHubSkillRegistry,
|
|
25719
26194
|
GitLabProvider,
|
|
25720
26195
|
GitProvider,
|
|
25721
26196
|
HookManager,
|
|
@@ -25731,6 +26206,7 @@ export {
|
|
|
25731
26206
|
MARKETPLACE_CACHE_FILE,
|
|
25732
26207
|
MODEL_REGISTRY,
|
|
25733
26208
|
MarketplaceAggregator,
|
|
26209
|
+
MemoryCache,
|
|
25734
26210
|
MemoryCompressor,
|
|
25735
26211
|
MemoryEnabledEngine,
|
|
25736
26212
|
MemoryIndexStore,
|
|
@@ -25753,10 +26229,12 @@ export {
|
|
|
25753
26229
|
PrimerGenerator,
|
|
25754
26230
|
ProjectDetector,
|
|
25755
26231
|
QueryExpander,
|
|
26232
|
+
RateLimitError,
|
|
25756
26233
|
ReasoningEngine,
|
|
25757
26234
|
ReasoningProviderSchema,
|
|
25758
26235
|
ReasoningRecommendationEngine,
|
|
25759
26236
|
RecommendationEngine,
|
|
26237
|
+
RelevanceRanker,
|
|
25760
26238
|
RuleBasedCompressor,
|
|
25761
26239
|
SEARCH_PLANNING_PROMPT,
|
|
25762
26240
|
SESSION_FILE,
|
|
@@ -25769,6 +26247,7 @@ export {
|
|
|
25769
26247
|
SkillChunkSchema,
|
|
25770
26248
|
SkillExecutionEngine,
|
|
25771
26249
|
SkillFrontmatter,
|
|
26250
|
+
SkillInjector,
|
|
25772
26251
|
SkillLocation,
|
|
25773
26252
|
SkillMdTranslator,
|
|
25774
26253
|
SkillMetadata,
|
|
@@ -25878,6 +26357,7 @@ export {
|
|
|
25878
26357
|
discoverAgentsFromPath,
|
|
25879
26358
|
discoverAgentsRecursive,
|
|
25880
26359
|
discoverGlobalAgents,
|
|
26360
|
+
discoverReferences,
|
|
25881
26361
|
discoverSkills,
|
|
25882
26362
|
dryRunExecutor,
|
|
25883
26363
|
enableGuideline,
|
|
@@ -26044,6 +26524,7 @@ export {
|
|
|
26044
26524
|
parseSkill,
|
|
26045
26525
|
parseSkillContent,
|
|
26046
26526
|
parseSkillContentToCanonical,
|
|
26527
|
+
parseSkillMd,
|
|
26047
26528
|
parseSkillToCanonical,
|
|
26048
26529
|
parseSource,
|
|
26049
26530
|
parseWorkflow,
|
|
@@ -26080,6 +26561,7 @@ export {
|
|
|
26080
26561
|
shellExecutor,
|
|
26081
26562
|
skillMdTranslator,
|
|
26082
26563
|
skillToSubagent,
|
|
26564
|
+
stripFrontmatter,
|
|
26083
26565
|
suggestMappingsFromMcp,
|
|
26084
26566
|
supportsAutoDiscovery,
|
|
26085
26567
|
supportsSlashCommands,
|