@skillkit/core 1.7.11 → 1.8.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/dist/index.d.ts +295 -1
- package/dist/index.js +2118 -401
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -4697,13 +4697,255 @@ function createSessionManager(projectPath) {
|
|
|
4697
4697
|
return new SessionManager(projectPath);
|
|
4698
4698
|
}
|
|
4699
4699
|
|
|
4700
|
+
// src/session/state-file.ts
|
|
4701
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, readdirSync as readdirSync4 } from "fs";
|
|
4702
|
+
import { join as join13 } from "path";
|
|
4703
|
+
import { homedir as homedir4 } from "os";
|
|
4704
|
+
function getSessionsDir() {
|
|
4705
|
+
return join13(homedir4(), ".skillkit", "sessions");
|
|
4706
|
+
}
|
|
4707
|
+
function getSessionFilePath(date) {
|
|
4708
|
+
const d = date || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
4709
|
+
return join13(getSessionsDir(), `${d}-session.md`);
|
|
4710
|
+
}
|
|
4711
|
+
function loadSessionFile(date) {
|
|
4712
|
+
const filepath = getSessionFilePath(date);
|
|
4713
|
+
if (!existsSync14(filepath)) {
|
|
4714
|
+
return null;
|
|
4715
|
+
}
|
|
4716
|
+
try {
|
|
4717
|
+
const content = readFileSync9(filepath, "utf-8");
|
|
4718
|
+
return parseSessionFile(content);
|
|
4719
|
+
} catch {
|
|
4720
|
+
return null;
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
function saveSessionFile(session) {
|
|
4724
|
+
const dir = getSessionsDir();
|
|
4725
|
+
if (!existsSync14(dir)) {
|
|
4726
|
+
mkdirSync7(dir, { recursive: true });
|
|
4727
|
+
}
|
|
4728
|
+
const filepath = getSessionFilePath(session.date);
|
|
4729
|
+
const content = formatSessionFile(session);
|
|
4730
|
+
writeFileSync7(filepath, content);
|
|
4731
|
+
return filepath;
|
|
4732
|
+
}
|
|
4733
|
+
function createSessionFile(agent, projectPath) {
|
|
4734
|
+
const now = /* @__PURE__ */ new Date();
|
|
4735
|
+
return {
|
|
4736
|
+
date: now.toISOString().split("T")[0],
|
|
4737
|
+
agent,
|
|
4738
|
+
projectPath,
|
|
4739
|
+
startedAt: now.toISOString(),
|
|
4740
|
+
lastUpdated: now.toISOString(),
|
|
4741
|
+
completed: [],
|
|
4742
|
+
inProgress: [],
|
|
4743
|
+
notes: [],
|
|
4744
|
+
contextToLoad: []
|
|
4745
|
+
};
|
|
4746
|
+
}
|
|
4747
|
+
function updateSessionFile(session, updates) {
|
|
4748
|
+
const updated = {
|
|
4749
|
+
...session,
|
|
4750
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
4751
|
+
};
|
|
4752
|
+
if (updates.completed) {
|
|
4753
|
+
updated.completed = [.../* @__PURE__ */ new Set([...session.completed, ...updates.completed])];
|
|
4754
|
+
}
|
|
4755
|
+
if (updates.inProgress) {
|
|
4756
|
+
updated.inProgress = updates.inProgress;
|
|
4757
|
+
}
|
|
4758
|
+
if (updates.notes) {
|
|
4759
|
+
updated.notes = [...session.notes, ...updates.notes];
|
|
4760
|
+
}
|
|
4761
|
+
if (updates.contextToLoad) {
|
|
4762
|
+
updated.contextToLoad = [.../* @__PURE__ */ new Set([...session.contextToLoad, ...updates.contextToLoad])];
|
|
4763
|
+
}
|
|
4764
|
+
return updated;
|
|
4765
|
+
}
|
|
4766
|
+
function parseSessionFile(content) {
|
|
4767
|
+
const lines = content.split("\n");
|
|
4768
|
+
const session = {
|
|
4769
|
+
date: "",
|
|
4770
|
+
agent: "",
|
|
4771
|
+
projectPath: "",
|
|
4772
|
+
startedAt: "",
|
|
4773
|
+
lastUpdated: "",
|
|
4774
|
+
completed: [],
|
|
4775
|
+
inProgress: [],
|
|
4776
|
+
notes: [],
|
|
4777
|
+
contextToLoad: []
|
|
4778
|
+
};
|
|
4779
|
+
let currentSection = "";
|
|
4780
|
+
for (const line of lines) {
|
|
4781
|
+
const trimmed = line.trim();
|
|
4782
|
+
if (trimmed.startsWith("# Session:")) {
|
|
4783
|
+
session.date = trimmed.replace("# Session:", "").trim();
|
|
4784
|
+
} else if (trimmed.startsWith("**Date:**")) {
|
|
4785
|
+
session.date = trimmed.replace("**Date:**", "").trim();
|
|
4786
|
+
} else if (trimmed.startsWith("**Started:**")) {
|
|
4787
|
+
session.startedAt = trimmed.replace("**Started:**", "").trim();
|
|
4788
|
+
} else if (trimmed.startsWith("**Last Updated:**")) {
|
|
4789
|
+
session.lastUpdated = trimmed.replace("**Last Updated:**", "").trim();
|
|
4790
|
+
} else if (trimmed.startsWith("**Agent:**")) {
|
|
4791
|
+
session.agent = trimmed.replace("**Agent:**", "").trim();
|
|
4792
|
+
} else if (trimmed.startsWith("**Project:**")) {
|
|
4793
|
+
session.projectPath = trimmed.replace("**Project:**", "").trim();
|
|
4794
|
+
} else if (trimmed === "### Completed") {
|
|
4795
|
+
currentSection = "completed";
|
|
4796
|
+
} else if (trimmed === "### In Progress") {
|
|
4797
|
+
currentSection = "inProgress";
|
|
4798
|
+
} else if (trimmed === "### Notes for Next Session") {
|
|
4799
|
+
currentSection = "notes";
|
|
4800
|
+
} else if (trimmed === "### Context to Load") {
|
|
4801
|
+
currentSection = "contextToLoad";
|
|
4802
|
+
} else if (trimmed.startsWith("- [x]")) {
|
|
4803
|
+
if (currentSection === "completed") {
|
|
4804
|
+
session.completed.push(trimmed.replace("- [x]", "").trim());
|
|
4805
|
+
}
|
|
4806
|
+
} else if (trimmed.startsWith("- [ ]")) {
|
|
4807
|
+
if (currentSection === "inProgress") {
|
|
4808
|
+
session.inProgress.push(trimmed.replace("- [ ]", "").trim());
|
|
4809
|
+
}
|
|
4810
|
+
} else if (trimmed.startsWith("- ")) {
|
|
4811
|
+
const item = trimmed.replace("- ", "").trim();
|
|
4812
|
+
if (currentSection === "notes") {
|
|
4813
|
+
session.notes.push(item);
|
|
4814
|
+
} else if (currentSection === "contextToLoad") {
|
|
4815
|
+
session.contextToLoad.push(item);
|
|
4816
|
+
}
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
return session;
|
|
4820
|
+
}
|
|
4821
|
+
function formatSessionFile(session) {
|
|
4822
|
+
const lines = [];
|
|
4823
|
+
lines.push(`# Session: ${session.date}`);
|
|
4824
|
+
lines.push(`**Date:** ${session.date}`);
|
|
4825
|
+
lines.push(`**Started:** ${session.startedAt}`);
|
|
4826
|
+
lines.push(`**Last Updated:** ${session.lastUpdated}`);
|
|
4827
|
+
lines.push(`**Agent:** ${session.agent}`);
|
|
4828
|
+
lines.push(`**Project:** ${session.projectPath}`);
|
|
4829
|
+
lines.push("");
|
|
4830
|
+
lines.push("## Current State");
|
|
4831
|
+
lines.push("");
|
|
4832
|
+
lines.push("### Completed");
|
|
4833
|
+
for (const task of session.completed) {
|
|
4834
|
+
lines.push(`- [x] ${task}`);
|
|
4835
|
+
}
|
|
4836
|
+
lines.push("");
|
|
4837
|
+
lines.push("### In Progress");
|
|
4838
|
+
for (const task of session.inProgress) {
|
|
4839
|
+
lines.push(`- [ ] ${task}`);
|
|
4840
|
+
}
|
|
4841
|
+
lines.push("");
|
|
4842
|
+
lines.push("### Notes for Next Session");
|
|
4843
|
+
for (const note of session.notes) {
|
|
4844
|
+
lines.push(`- ${note}`);
|
|
4845
|
+
}
|
|
4846
|
+
lines.push("");
|
|
4847
|
+
lines.push("### Context to Load");
|
|
4848
|
+
for (const ctx of session.contextToLoad) {
|
|
4849
|
+
lines.push(`- ${ctx}`);
|
|
4850
|
+
}
|
|
4851
|
+
lines.push("");
|
|
4852
|
+
return lines.join("\n");
|
|
4853
|
+
}
|
|
4854
|
+
function listSessions(limit = 10) {
|
|
4855
|
+
const dir = getSessionsDir();
|
|
4856
|
+
if (!existsSync14(dir)) {
|
|
4857
|
+
return [];
|
|
4858
|
+
}
|
|
4859
|
+
const files = readdirSync4(dir).filter((f) => f.endsWith("-session.md")).sort().reverse().slice(0, limit);
|
|
4860
|
+
const summaries = [];
|
|
4861
|
+
for (const file of files) {
|
|
4862
|
+
const date = file.replace("-session.md", "");
|
|
4863
|
+
const session = loadSessionFile(date);
|
|
4864
|
+
if (session) {
|
|
4865
|
+
summaries.push({
|
|
4866
|
+
date: session.date,
|
|
4867
|
+
projectPath: session.projectPath,
|
|
4868
|
+
agent: session.agent,
|
|
4869
|
+
taskCount: session.completed.length + session.inProgress.length,
|
|
4870
|
+
completedCount: session.completed.length,
|
|
4871
|
+
hasNotes: session.notes.length > 0
|
|
4872
|
+
});
|
|
4873
|
+
}
|
|
4874
|
+
}
|
|
4875
|
+
return summaries;
|
|
4876
|
+
}
|
|
4877
|
+
function getMostRecentSession() {
|
|
4878
|
+
const summaries = listSessions(1);
|
|
4879
|
+
if (summaries.length === 0) {
|
|
4880
|
+
return null;
|
|
4881
|
+
}
|
|
4882
|
+
return loadSessionFile(summaries[0].date);
|
|
4883
|
+
}
|
|
4884
|
+
|
|
4700
4885
|
// src/workflow/types.ts
|
|
4701
4886
|
var WORKFLOWS_DIR = "workflows";
|
|
4702
4887
|
var WORKFLOW_EXTENSION = ".yaml";
|
|
4888
|
+
var BUILTIN_PIPELINES = [
|
|
4889
|
+
{
|
|
4890
|
+
id: "feature",
|
|
4891
|
+
name: "Feature Development",
|
|
4892
|
+
description: "Plan \u2192 TDD \u2192 Review \u2192 Security",
|
|
4893
|
+
stages: [
|
|
4894
|
+
{ agent: "planner", name: "Planning", description: "Design implementation approach" },
|
|
4895
|
+
{ agent: "tdd-guide", name: "TDD", description: "Write tests first, then implement" },
|
|
4896
|
+
{ agent: "code-reviewer", name: "Review", description: "Quality and best practices check" },
|
|
4897
|
+
{ agent: "security-reviewer", name: "Security", description: "Security audit" }
|
|
4898
|
+
]
|
|
4899
|
+
},
|
|
4900
|
+
{
|
|
4901
|
+
id: "bugfix",
|
|
4902
|
+
name: "Bug Fix",
|
|
4903
|
+
description: "TDD \u2192 Review",
|
|
4904
|
+
stages: [
|
|
4905
|
+
{ agent: "tdd-guide", name: "Fix", description: "Test-first bug fix" },
|
|
4906
|
+
{ agent: "code-reviewer", name: "Review", description: "Verify fix quality" }
|
|
4907
|
+
]
|
|
4908
|
+
},
|
|
4909
|
+
{
|
|
4910
|
+
id: "refactor",
|
|
4911
|
+
name: "Refactoring",
|
|
4912
|
+
description: "Architect \u2192 Review \u2192 TDD",
|
|
4913
|
+
stages: [
|
|
4914
|
+
{ agent: "architect", name: "Design", description: "Plan refactoring approach" },
|
|
4915
|
+
{ agent: "code-reviewer", name: "Review", description: "Review proposed changes" },
|
|
4916
|
+
{ agent: "tdd-guide", name: "Verify", description: "Ensure tests pass after refactor" }
|
|
4917
|
+
]
|
|
4918
|
+
},
|
|
4919
|
+
{
|
|
4920
|
+
id: "security-audit",
|
|
4921
|
+
name: "Security Audit",
|
|
4922
|
+
description: "Security \u2192 Review \u2192 Fix",
|
|
4923
|
+
stages: [
|
|
4924
|
+
{ agent: "security-reviewer", name: "Audit", description: "Identify vulnerabilities" },
|
|
4925
|
+
{ agent: "code-reviewer", name: "Review", description: "Review security findings" },
|
|
4926
|
+
{ agent: "build-error-resolver", name: "Fix", description: "Apply security fixes" }
|
|
4927
|
+
]
|
|
4928
|
+
},
|
|
4929
|
+
{
|
|
4930
|
+
id: "documentation",
|
|
4931
|
+
name: "Documentation",
|
|
4932
|
+
description: "Planner \u2192 Doc Updater",
|
|
4933
|
+
stages: [
|
|
4934
|
+
{ agent: "planner", name: "Plan", description: "Identify documentation needs" },
|
|
4935
|
+
{ agent: "doc-updater", name: "Update", description: "Update documentation" }
|
|
4936
|
+
]
|
|
4937
|
+
}
|
|
4938
|
+
];
|
|
4939
|
+
function getBuiltinPipeline(id) {
|
|
4940
|
+
return BUILTIN_PIPELINES.find((p) => p.id === id) || null;
|
|
4941
|
+
}
|
|
4942
|
+
function getBuiltinPipelines() {
|
|
4943
|
+
return BUILTIN_PIPELINES;
|
|
4944
|
+
}
|
|
4703
4945
|
|
|
4704
4946
|
// src/workflow/parser.ts
|
|
4705
|
-
import { existsSync as
|
|
4706
|
-
import { join as
|
|
4947
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, readdirSync as readdirSync5, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
|
|
4948
|
+
import { join as join14 } from "path";
|
|
4707
4949
|
import { parse as parse2, stringify as stringify2 } from "yaml";
|
|
4708
4950
|
function parseWorkflow(content) {
|
|
4709
4951
|
const data = parse2(content);
|
|
@@ -4755,25 +4997,25 @@ function parseWorkflow(content) {
|
|
|
4755
4997
|
};
|
|
4756
4998
|
}
|
|
4757
4999
|
function loadWorkflow(filePath) {
|
|
4758
|
-
if (!
|
|
5000
|
+
if (!existsSync15(filePath)) {
|
|
4759
5001
|
throw new Error(`Workflow file not found: ${filePath}`);
|
|
4760
5002
|
}
|
|
4761
|
-
const content =
|
|
5003
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
4762
5004
|
return parseWorkflow(content);
|
|
4763
5005
|
}
|
|
4764
5006
|
function loadWorkflowByName(projectPath, name) {
|
|
4765
|
-
const workflowsDir =
|
|
4766
|
-
if (!
|
|
5007
|
+
const workflowsDir = join14(projectPath, ".skillkit", WORKFLOWS_DIR);
|
|
5008
|
+
if (!existsSync15(workflowsDir)) {
|
|
4767
5009
|
return null;
|
|
4768
5010
|
}
|
|
4769
|
-
const exactPath =
|
|
4770
|
-
if (
|
|
5011
|
+
const exactPath = join14(workflowsDir, `${name}${WORKFLOW_EXTENSION}`);
|
|
5012
|
+
if (existsSync15(exactPath)) {
|
|
4771
5013
|
return loadWorkflow(exactPath);
|
|
4772
5014
|
}
|
|
4773
|
-
const files =
|
|
5015
|
+
const files = readdirSync5(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
4774
5016
|
for (const file of files) {
|
|
4775
5017
|
try {
|
|
4776
|
-
const workflow = loadWorkflow(
|
|
5018
|
+
const workflow = loadWorkflow(join14(workflowsDir, file));
|
|
4777
5019
|
if (workflow.name === name) {
|
|
4778
5020
|
return workflow;
|
|
4779
5021
|
}
|
|
@@ -4783,15 +5025,15 @@ function loadWorkflowByName(projectPath, name) {
|
|
|
4783
5025
|
return null;
|
|
4784
5026
|
}
|
|
4785
5027
|
function listWorkflows(projectPath) {
|
|
4786
|
-
const workflowsDir =
|
|
4787
|
-
if (!
|
|
5028
|
+
const workflowsDir = join14(projectPath, ".skillkit", WORKFLOWS_DIR);
|
|
5029
|
+
if (!existsSync15(workflowsDir)) {
|
|
4788
5030
|
return [];
|
|
4789
5031
|
}
|
|
4790
|
-
const files =
|
|
5032
|
+
const files = readdirSync5(workflowsDir).filter((f) => f.endsWith(WORKFLOW_EXTENSION));
|
|
4791
5033
|
const workflows = [];
|
|
4792
5034
|
for (const file of files) {
|
|
4793
5035
|
try {
|
|
4794
|
-
const workflow = loadWorkflow(
|
|
5036
|
+
const workflow = loadWorkflow(join14(workflowsDir, file));
|
|
4795
5037
|
workflows.push(workflow);
|
|
4796
5038
|
} catch {
|
|
4797
5039
|
}
|
|
@@ -4799,13 +5041,13 @@ function listWorkflows(projectPath) {
|
|
|
4799
5041
|
return workflows;
|
|
4800
5042
|
}
|
|
4801
5043
|
function saveWorkflow(projectPath, workflow) {
|
|
4802
|
-
const workflowsDir =
|
|
4803
|
-
if (!
|
|
4804
|
-
|
|
5044
|
+
const workflowsDir = join14(projectPath, ".skillkit", WORKFLOWS_DIR);
|
|
5045
|
+
if (!existsSync15(workflowsDir)) {
|
|
5046
|
+
mkdirSync8(workflowsDir, { recursive: true });
|
|
4805
5047
|
}
|
|
4806
5048
|
const fileName = `${workflow.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}${WORKFLOW_EXTENSION}`;
|
|
4807
|
-
const filePath =
|
|
4808
|
-
|
|
5049
|
+
const filePath = join14(workflowsDir, fileName);
|
|
5050
|
+
writeFileSync8(filePath, stringify2(workflow));
|
|
4809
5051
|
return filePath;
|
|
4810
5052
|
}
|
|
4811
5053
|
function serializeWorkflow(workflow) {
|
|
@@ -5725,26 +5967,26 @@ To execute this skill manually:
|
|
|
5725
5967
|
}
|
|
5726
5968
|
|
|
5727
5969
|
// src/executor/skill-executor.ts
|
|
5728
|
-
import { existsSync as
|
|
5729
|
-
import { join as
|
|
5730
|
-
import { homedir as
|
|
5970
|
+
import { existsSync as existsSync16 } from "fs";
|
|
5971
|
+
import { join as join15 } from "path";
|
|
5972
|
+
import { homedir as homedir5 } from "os";
|
|
5731
5973
|
function getSearchDirs2(projectPath) {
|
|
5732
5974
|
const dirs = [];
|
|
5733
5975
|
for (const searchPath of SKILL_DISCOVERY_PATHS) {
|
|
5734
|
-
const fullPath =
|
|
5735
|
-
if (
|
|
5976
|
+
const fullPath = join15(projectPath, searchPath);
|
|
5977
|
+
if (existsSync16(fullPath)) {
|
|
5736
5978
|
dirs.push(fullPath);
|
|
5737
5979
|
}
|
|
5738
5980
|
}
|
|
5739
|
-
const home =
|
|
5981
|
+
const home = homedir5();
|
|
5740
5982
|
const globalPaths = [
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5983
|
+
join15(home, ".claude", "skills"),
|
|
5984
|
+
join15(home, ".cursor", "skills"),
|
|
5985
|
+
join15(home, ".codex", "skills"),
|
|
5986
|
+
join15(home, ".skillkit", "skills")
|
|
5745
5987
|
];
|
|
5746
5988
|
for (const globalPath of globalPaths) {
|
|
5747
|
-
if (
|
|
5989
|
+
if (existsSync16(globalPath)) {
|
|
5748
5990
|
dirs.push(globalPath);
|
|
5749
5991
|
}
|
|
5750
5992
|
}
|
|
@@ -5874,8 +6116,8 @@ function createSimulatedSkillExecutor(options = {}) {
|
|
|
5874
6116
|
}
|
|
5875
6117
|
|
|
5876
6118
|
// src/testing/runner.ts
|
|
5877
|
-
import { existsSync as
|
|
5878
|
-
import { join as
|
|
6119
|
+
import { existsSync as existsSync17, readFileSync as readFileSync11 } from "fs";
|
|
6120
|
+
import { join as join16 } from "path";
|
|
5879
6121
|
import { exec } from "child_process";
|
|
5880
6122
|
import { createServer } from "net";
|
|
5881
6123
|
import { promisify } from "util";
|
|
@@ -5940,8 +6182,8 @@ async function runAssertion(assertion, cwd, timeout) {
|
|
|
5940
6182
|
}
|
|
5941
6183
|
}
|
|
5942
6184
|
function assertFileExists(assertion, cwd, startTime) {
|
|
5943
|
-
const filePath =
|
|
5944
|
-
const exists =
|
|
6185
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6186
|
+
const exists = existsSync17(filePath);
|
|
5945
6187
|
return {
|
|
5946
6188
|
assertion,
|
|
5947
6189
|
passed: exists,
|
|
@@ -5952,8 +6194,8 @@ function assertFileExists(assertion, cwd, startTime) {
|
|
|
5952
6194
|
};
|
|
5953
6195
|
}
|
|
5954
6196
|
function assertFileNotExists(assertion, cwd, startTime) {
|
|
5955
|
-
const filePath =
|
|
5956
|
-
const exists =
|
|
6197
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6198
|
+
const exists = existsSync17(filePath);
|
|
5957
6199
|
return {
|
|
5958
6200
|
assertion,
|
|
5959
6201
|
passed: !exists,
|
|
@@ -5964,8 +6206,8 @@ function assertFileNotExists(assertion, cwd, startTime) {
|
|
|
5964
6206
|
};
|
|
5965
6207
|
}
|
|
5966
6208
|
function assertFileContains(assertion, cwd, startTime) {
|
|
5967
|
-
const filePath =
|
|
5968
|
-
if (!
|
|
6209
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6210
|
+
if (!existsSync17(filePath)) {
|
|
5969
6211
|
return {
|
|
5970
6212
|
assertion,
|
|
5971
6213
|
passed: false,
|
|
@@ -5973,7 +6215,7 @@ function assertFileContains(assertion, cwd, startTime) {
|
|
|
5973
6215
|
duration: Date.now() - startTime
|
|
5974
6216
|
};
|
|
5975
6217
|
}
|
|
5976
|
-
const content =
|
|
6218
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
5977
6219
|
const expected = String(assertion.expected || "");
|
|
5978
6220
|
const contains = content.includes(expected);
|
|
5979
6221
|
return {
|
|
@@ -5986,8 +6228,8 @@ function assertFileContains(assertion, cwd, startTime) {
|
|
|
5986
6228
|
};
|
|
5987
6229
|
}
|
|
5988
6230
|
function assertFileNotContains(assertion, cwd, startTime) {
|
|
5989
|
-
const filePath =
|
|
5990
|
-
if (!
|
|
6231
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6232
|
+
if (!existsSync17(filePath)) {
|
|
5991
6233
|
return {
|
|
5992
6234
|
assertion,
|
|
5993
6235
|
passed: true,
|
|
@@ -5995,7 +6237,7 @@ function assertFileNotContains(assertion, cwd, startTime) {
|
|
|
5995
6237
|
duration: Date.now() - startTime
|
|
5996
6238
|
};
|
|
5997
6239
|
}
|
|
5998
|
-
const content =
|
|
6240
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
5999
6241
|
const expected = String(assertion.expected || "");
|
|
6000
6242
|
const contains = content.includes(expected);
|
|
6001
6243
|
return {
|
|
@@ -6008,8 +6250,8 @@ function assertFileNotContains(assertion, cwd, startTime) {
|
|
|
6008
6250
|
};
|
|
6009
6251
|
}
|
|
6010
6252
|
function assertFileMatches(assertion, cwd, startTime) {
|
|
6011
|
-
const filePath =
|
|
6012
|
-
if (!
|
|
6253
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6254
|
+
if (!existsSync17(filePath)) {
|
|
6013
6255
|
return {
|
|
6014
6256
|
assertion,
|
|
6015
6257
|
passed: false,
|
|
@@ -6017,7 +6259,7 @@ function assertFileMatches(assertion, cwd, startTime) {
|
|
|
6017
6259
|
duration: Date.now() - startTime
|
|
6018
6260
|
};
|
|
6019
6261
|
}
|
|
6020
|
-
const content =
|
|
6262
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
6021
6263
|
const pattern = new RegExp(String(assertion.expected || ""));
|
|
6022
6264
|
const matches = pattern.test(content);
|
|
6023
6265
|
return {
|
|
@@ -6104,8 +6346,8 @@ async function assertCommandOutputContains(assertion, cwd, timeout, startTime) {
|
|
|
6104
6346
|
}
|
|
6105
6347
|
}
|
|
6106
6348
|
function assertJsonValid(assertion, cwd, startTime) {
|
|
6107
|
-
const filePath =
|
|
6108
|
-
if (!
|
|
6349
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6350
|
+
if (!existsSync17(filePath)) {
|
|
6109
6351
|
return {
|
|
6110
6352
|
assertion,
|
|
6111
6353
|
passed: false,
|
|
@@ -6114,7 +6356,7 @@ function assertJsonValid(assertion, cwd, startTime) {
|
|
|
6114
6356
|
};
|
|
6115
6357
|
}
|
|
6116
6358
|
try {
|
|
6117
|
-
const content =
|
|
6359
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
6118
6360
|
JSON.parse(content);
|
|
6119
6361
|
return {
|
|
6120
6362
|
assertion,
|
|
@@ -6135,8 +6377,8 @@ function assertJsonValid(assertion, cwd, startTime) {
|
|
|
6135
6377
|
}
|
|
6136
6378
|
}
|
|
6137
6379
|
function assertJsonHasKey(assertion, cwd, startTime) {
|
|
6138
|
-
const filePath =
|
|
6139
|
-
if (!
|
|
6380
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6381
|
+
if (!existsSync17(filePath)) {
|
|
6140
6382
|
return {
|
|
6141
6383
|
assertion,
|
|
6142
6384
|
passed: false,
|
|
@@ -6145,7 +6387,7 @@ function assertJsonHasKey(assertion, cwd, startTime) {
|
|
|
6145
6387
|
};
|
|
6146
6388
|
}
|
|
6147
6389
|
try {
|
|
6148
|
-
const content =
|
|
6390
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
6149
6391
|
const json = JSON.parse(content);
|
|
6150
6392
|
const key = String(assertion.expected || "");
|
|
6151
6393
|
const keys = key.split(".");
|
|
@@ -6180,8 +6422,8 @@ function assertJsonHasKey(assertion, cwd, startTime) {
|
|
|
6180
6422
|
}
|
|
6181
6423
|
}
|
|
6182
6424
|
function assertYamlValid(assertion, cwd, startTime) {
|
|
6183
|
-
const filePath =
|
|
6184
|
-
if (!
|
|
6425
|
+
const filePath = join16(cwd, assertion.target || "");
|
|
6426
|
+
if (!existsSync17(filePath)) {
|
|
6185
6427
|
return {
|
|
6186
6428
|
assertion,
|
|
6187
6429
|
passed: false,
|
|
@@ -6190,7 +6432,7 @@ function assertYamlValid(assertion, cwd, startTime) {
|
|
|
6190
6432
|
};
|
|
6191
6433
|
}
|
|
6192
6434
|
try {
|
|
6193
|
-
const content =
|
|
6435
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
6194
6436
|
parseYaml6(content);
|
|
6195
6437
|
return {
|
|
6196
6438
|
assertion,
|
|
@@ -6713,9 +6955,9 @@ var MARKETPLACE_CACHE_FILE = "marketplace-index.json";
|
|
|
6713
6955
|
var DEFAULT_CACHE_TTL = 60 * 60 * 1e3;
|
|
6714
6956
|
|
|
6715
6957
|
// src/marketplace/aggregator.ts
|
|
6716
|
-
import { existsSync as
|
|
6717
|
-
import { join as
|
|
6718
|
-
import { homedir as
|
|
6958
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, unlinkSync as unlinkSync2 } from "fs";
|
|
6959
|
+
import { join as join17 } from "path";
|
|
6960
|
+
import { homedir as homedir6 } from "os";
|
|
6719
6961
|
var MarketplaceAggregator = class {
|
|
6720
6962
|
config;
|
|
6721
6963
|
cacheDir;
|
|
@@ -6723,10 +6965,10 @@ var MarketplaceAggregator = class {
|
|
|
6723
6965
|
index = null;
|
|
6724
6966
|
constructor(config = {}) {
|
|
6725
6967
|
this.config = config;
|
|
6726
|
-
this.cacheDir = config.cacheDir ||
|
|
6727
|
-
this.cachePath =
|
|
6728
|
-
if (!
|
|
6729
|
-
|
|
6968
|
+
this.cacheDir = config.cacheDir || join17(homedir6(), ".skillkit", "marketplace");
|
|
6969
|
+
this.cachePath = join17(this.cacheDir, MARKETPLACE_CACHE_FILE);
|
|
6970
|
+
if (!existsSync18(this.cacheDir)) {
|
|
6971
|
+
mkdirSync9(this.cacheDir, { recursive: true });
|
|
6730
6972
|
}
|
|
6731
6973
|
}
|
|
6732
6974
|
/**
|
|
@@ -6739,11 +6981,11 @@ var MarketplaceAggregator = class {
|
|
|
6739
6981
|
* Load cached index
|
|
6740
6982
|
*/
|
|
6741
6983
|
loadCache() {
|
|
6742
|
-
if (!
|
|
6984
|
+
if (!existsSync18(this.cachePath)) {
|
|
6743
6985
|
return null;
|
|
6744
6986
|
}
|
|
6745
6987
|
try {
|
|
6746
|
-
const content =
|
|
6988
|
+
const content = readFileSync12(this.cachePath, "utf-8");
|
|
6747
6989
|
const index = JSON.parse(content);
|
|
6748
6990
|
const cacheAge = Date.now() - new Date(index.updatedAt).getTime();
|
|
6749
6991
|
const ttl = this.config.cacheTTL || DEFAULT_CACHE_TTL;
|
|
@@ -6760,7 +7002,7 @@ var MarketplaceAggregator = class {
|
|
|
6760
7002
|
* Save index to cache
|
|
6761
7003
|
*/
|
|
6762
7004
|
saveCache(index) {
|
|
6763
|
-
|
|
7005
|
+
writeFileSync9(this.cachePath, JSON.stringify(index, null, 2));
|
|
6764
7006
|
this.index = index;
|
|
6765
7007
|
}
|
|
6766
7008
|
/**
|
|
@@ -7084,7 +7326,7 @@ var MarketplaceAggregator = class {
|
|
|
7084
7326
|
* Clear cache
|
|
7085
7327
|
*/
|
|
7086
7328
|
clearCache() {
|
|
7087
|
-
if (
|
|
7329
|
+
if (existsSync18(this.cachePath)) {
|
|
7088
7330
|
unlinkSync2(this.cachePath);
|
|
7089
7331
|
}
|
|
7090
7332
|
this.index = null;
|
|
@@ -7310,8 +7552,8 @@ var DEFAULT_MEMORY_CONFIG = {
|
|
|
7310
7552
|
};
|
|
7311
7553
|
|
|
7312
7554
|
// src/memory/observation-store.ts
|
|
7313
|
-
import { existsSync as
|
|
7314
|
-
import { dirname as dirname3, join as
|
|
7555
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, readFileSync as readFileSync13, writeFileSync as writeFileSync10 } from "fs";
|
|
7556
|
+
import { dirname as dirname3, join as join18 } from "path";
|
|
7315
7557
|
import { parse as parseYaml7, stringify as stringifyYaml5 } from "yaml";
|
|
7316
7558
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
7317
7559
|
var ObservationStore = class {
|
|
@@ -7319,20 +7561,20 @@ var ObservationStore = class {
|
|
|
7319
7561
|
data = null;
|
|
7320
7562
|
sessionId;
|
|
7321
7563
|
constructor(projectPath, sessionId) {
|
|
7322
|
-
this.filePath =
|
|
7564
|
+
this.filePath = join18(projectPath, ".skillkit", "memory", "observations.yaml");
|
|
7323
7565
|
this.sessionId = sessionId || randomUUID7();
|
|
7324
7566
|
}
|
|
7325
7567
|
ensureDir() {
|
|
7326
7568
|
const dir = dirname3(this.filePath);
|
|
7327
|
-
if (!
|
|
7328
|
-
|
|
7569
|
+
if (!existsSync19(dir)) {
|
|
7570
|
+
mkdirSync10(dir, { recursive: true });
|
|
7329
7571
|
}
|
|
7330
7572
|
}
|
|
7331
7573
|
load() {
|
|
7332
7574
|
if (this.data) return this.data;
|
|
7333
|
-
if (
|
|
7575
|
+
if (existsSync19(this.filePath)) {
|
|
7334
7576
|
try {
|
|
7335
|
-
const content =
|
|
7577
|
+
const content = readFileSync13(this.filePath, "utf-8");
|
|
7336
7578
|
this.data = parseYaml7(content);
|
|
7337
7579
|
if (this.data.sessionId !== this.sessionId) {
|
|
7338
7580
|
this.data.sessionId = this.sessionId;
|
|
@@ -7356,7 +7598,7 @@ var ObservationStore = class {
|
|
|
7356
7598
|
save() {
|
|
7357
7599
|
this.ensureDir();
|
|
7358
7600
|
const content = stringifyYaml5(this.data, { lineWidth: 0 });
|
|
7359
|
-
|
|
7601
|
+
writeFileSync10(this.filePath, content, "utf-8");
|
|
7360
7602
|
}
|
|
7361
7603
|
add(type, content, agent, relevance = 50) {
|
|
7362
7604
|
const data = this.load();
|
|
@@ -7414,7 +7656,7 @@ var ObservationStore = class {
|
|
|
7414
7656
|
}
|
|
7415
7657
|
}
|
|
7416
7658
|
exists() {
|
|
7417
|
-
return
|
|
7659
|
+
return existsSync19(this.filePath);
|
|
7418
7660
|
}
|
|
7419
7661
|
delete(id) {
|
|
7420
7662
|
const data = this.load();
|
|
@@ -7437,9 +7679,9 @@ var ObservationStore = class {
|
|
|
7437
7679
|
};
|
|
7438
7680
|
|
|
7439
7681
|
// src/memory/learning-store.ts
|
|
7440
|
-
import { existsSync as
|
|
7441
|
-
import { dirname as dirname4, join as
|
|
7442
|
-
import { homedir as
|
|
7682
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "fs";
|
|
7683
|
+
import { dirname as dirname4, join as join19 } from "path";
|
|
7684
|
+
import { homedir as homedir7 } from "os";
|
|
7443
7685
|
import { parse as parseYaml8, stringify as stringifyYaml6 } from "yaml";
|
|
7444
7686
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
7445
7687
|
var LearningStore = class {
|
|
@@ -7451,22 +7693,22 @@ var LearningStore = class {
|
|
|
7451
7693
|
this.scope = scope;
|
|
7452
7694
|
this.projectName = projectName;
|
|
7453
7695
|
if (scope === "project" && projectPath) {
|
|
7454
|
-
this.filePath =
|
|
7696
|
+
this.filePath = join19(projectPath, ".skillkit", "memory", "learnings.yaml");
|
|
7455
7697
|
} else {
|
|
7456
|
-
this.filePath =
|
|
7698
|
+
this.filePath = join19(homedir7(), ".skillkit", "memory", "global.yaml");
|
|
7457
7699
|
}
|
|
7458
7700
|
}
|
|
7459
7701
|
ensureDir() {
|
|
7460
7702
|
const dir = dirname4(this.filePath);
|
|
7461
|
-
if (!
|
|
7462
|
-
|
|
7703
|
+
if (!existsSync20(dir)) {
|
|
7704
|
+
mkdirSync11(dir, { recursive: true });
|
|
7463
7705
|
}
|
|
7464
7706
|
}
|
|
7465
7707
|
load() {
|
|
7466
7708
|
if (this.data) return this.data;
|
|
7467
|
-
if (
|
|
7709
|
+
if (existsSync20(this.filePath)) {
|
|
7468
7710
|
try {
|
|
7469
|
-
const content =
|
|
7711
|
+
const content = readFileSync14(this.filePath, "utf-8");
|
|
7470
7712
|
this.data = parseYaml8(content);
|
|
7471
7713
|
} catch {
|
|
7472
7714
|
this.data = this.createEmpty();
|
|
@@ -7485,7 +7727,7 @@ var LearningStore = class {
|
|
|
7485
7727
|
save() {
|
|
7486
7728
|
this.ensureDir();
|
|
7487
7729
|
const content = stringifyYaml6(this.data, { lineWidth: 0 });
|
|
7488
|
-
|
|
7730
|
+
writeFileSync11(this.filePath, content, "utf-8");
|
|
7489
7731
|
}
|
|
7490
7732
|
add(learning) {
|
|
7491
7733
|
const data = this.load();
|
|
@@ -7592,7 +7834,7 @@ var LearningStore = class {
|
|
|
7592
7834
|
this.save();
|
|
7593
7835
|
}
|
|
7594
7836
|
exists() {
|
|
7595
|
-
return
|
|
7837
|
+
return existsSync20(this.filePath);
|
|
7596
7838
|
}
|
|
7597
7839
|
getScope() {
|
|
7598
7840
|
return this.scope;
|
|
@@ -7600,26 +7842,26 @@ var LearningStore = class {
|
|
|
7600
7842
|
};
|
|
7601
7843
|
|
|
7602
7844
|
// src/memory/memory-index.ts
|
|
7603
|
-
import { existsSync as
|
|
7604
|
-
import { dirname as dirname5, join as
|
|
7845
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync12, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
7846
|
+
import { dirname as dirname5, join as join20 } from "path";
|
|
7605
7847
|
import { parse as parseYaml9, stringify as stringifyYaml7 } from "yaml";
|
|
7606
7848
|
var MemoryIndexStore = class {
|
|
7607
7849
|
filePath;
|
|
7608
7850
|
data = null;
|
|
7609
7851
|
constructor(basePath, _isGlobal = false) {
|
|
7610
|
-
this.filePath =
|
|
7852
|
+
this.filePath = join20(basePath, ".skillkit", "memory", "index.yaml");
|
|
7611
7853
|
}
|
|
7612
7854
|
ensureDir() {
|
|
7613
7855
|
const dir = dirname5(this.filePath);
|
|
7614
|
-
if (!
|
|
7615
|
-
|
|
7856
|
+
if (!existsSync21(dir)) {
|
|
7857
|
+
mkdirSync12(dir, { recursive: true });
|
|
7616
7858
|
}
|
|
7617
7859
|
}
|
|
7618
7860
|
load() {
|
|
7619
7861
|
if (this.data) return this.data;
|
|
7620
|
-
if (
|
|
7862
|
+
if (existsSync21(this.filePath)) {
|
|
7621
7863
|
try {
|
|
7622
|
-
const content =
|
|
7864
|
+
const content = readFileSync15(this.filePath, "utf-8");
|
|
7623
7865
|
this.data = parseYaml9(content);
|
|
7624
7866
|
} catch {
|
|
7625
7867
|
this.data = this.createEmpty();
|
|
@@ -7643,7 +7885,7 @@ var MemoryIndexStore = class {
|
|
|
7643
7885
|
this.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
7644
7886
|
}
|
|
7645
7887
|
const content = stringifyYaml7(this.data, { lineWidth: 0 });
|
|
7646
|
-
|
|
7888
|
+
writeFileSync12(this.filePath, content, "utf-8");
|
|
7647
7889
|
}
|
|
7648
7890
|
extractKeywords(text) {
|
|
7649
7891
|
const stopWords = /* @__PURE__ */ new Set([
|
|
@@ -7837,7 +8079,7 @@ var MemoryIndexStore = class {
|
|
|
7837
8079
|
this.save();
|
|
7838
8080
|
}
|
|
7839
8081
|
exists() {
|
|
7840
|
-
return
|
|
8082
|
+
return existsSync21(this.filePath);
|
|
7841
8083
|
}
|
|
7842
8084
|
getStats() {
|
|
7843
8085
|
const data = this.load();
|
|
@@ -7850,50 +8092,50 @@ var MemoryIndexStore = class {
|
|
|
7850
8092
|
};
|
|
7851
8093
|
|
|
7852
8094
|
// src/memory/initializer.ts
|
|
7853
|
-
import { existsSync as
|
|
7854
|
-
import { join as
|
|
7855
|
-
import { homedir as
|
|
8095
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync13 } from "fs";
|
|
8096
|
+
import { join as join21 } from "path";
|
|
8097
|
+
import { homedir as homedir8 } from "os";
|
|
7856
8098
|
function getMemoryPaths(projectPath) {
|
|
7857
|
-
const projectMemoryDir =
|
|
7858
|
-
const globalMemoryDir =
|
|
8099
|
+
const projectMemoryDir = join21(projectPath, ".skillkit", "memory");
|
|
8100
|
+
const globalMemoryDir = join21(homedir8(), ".skillkit", "memory");
|
|
7859
8101
|
return {
|
|
7860
8102
|
projectMemoryDir,
|
|
7861
8103
|
globalMemoryDir,
|
|
7862
|
-
observationsFile:
|
|
7863
|
-
learningsFile:
|
|
7864
|
-
indexFile:
|
|
7865
|
-
globalLearningsFile:
|
|
7866
|
-
globalIndexFile:
|
|
8104
|
+
observationsFile: join21(projectMemoryDir, "observations.yaml"),
|
|
8105
|
+
learningsFile: join21(projectMemoryDir, "learnings.yaml"),
|
|
8106
|
+
indexFile: join21(projectMemoryDir, "index.yaml"),
|
|
8107
|
+
globalLearningsFile: join21(globalMemoryDir, "global.yaml"),
|
|
8108
|
+
globalIndexFile: join21(globalMemoryDir, "index.yaml")
|
|
7867
8109
|
};
|
|
7868
8110
|
}
|
|
7869
8111
|
function initializeMemoryDirectory(projectPath) {
|
|
7870
8112
|
const paths = getMemoryPaths(projectPath);
|
|
7871
|
-
if (!
|
|
7872
|
-
|
|
8113
|
+
if (!existsSync22(paths.projectMemoryDir)) {
|
|
8114
|
+
mkdirSync13(paths.projectMemoryDir, { recursive: true });
|
|
7873
8115
|
}
|
|
7874
|
-
if (!
|
|
7875
|
-
|
|
8116
|
+
if (!existsSync22(paths.globalMemoryDir)) {
|
|
8117
|
+
mkdirSync13(paths.globalMemoryDir, { recursive: true });
|
|
7876
8118
|
}
|
|
7877
8119
|
return paths;
|
|
7878
8120
|
}
|
|
7879
8121
|
function memoryDirectoryExists(projectPath) {
|
|
7880
8122
|
const paths = getMemoryPaths(projectPath);
|
|
7881
|
-
return
|
|
8123
|
+
return existsSync22(paths.projectMemoryDir);
|
|
7882
8124
|
}
|
|
7883
8125
|
function globalMemoryDirectoryExists() {
|
|
7884
|
-
const globalMemoryDir =
|
|
7885
|
-
return
|
|
8126
|
+
const globalMemoryDir = join21(homedir8(), ".skillkit", "memory");
|
|
8127
|
+
return existsSync22(globalMemoryDir);
|
|
7886
8128
|
}
|
|
7887
8129
|
function getMemoryStatus(projectPath) {
|
|
7888
8130
|
const paths = getMemoryPaths(projectPath);
|
|
7889
8131
|
return {
|
|
7890
|
-
projectMemoryExists:
|
|
7891
|
-
globalMemoryExists:
|
|
7892
|
-
hasObservations:
|
|
7893
|
-
hasLearnings:
|
|
7894
|
-
hasGlobalLearnings:
|
|
7895
|
-
hasIndex:
|
|
7896
|
-
hasGlobalIndex:
|
|
8132
|
+
projectMemoryExists: existsSync22(paths.projectMemoryDir),
|
|
8133
|
+
globalMemoryExists: existsSync22(paths.globalMemoryDir),
|
|
8134
|
+
hasObservations: existsSync22(paths.observationsFile),
|
|
8135
|
+
hasLearnings: existsSync22(paths.learningsFile),
|
|
8136
|
+
hasGlobalLearnings: existsSync22(paths.globalLearningsFile),
|
|
8137
|
+
hasIndex: existsSync22(paths.indexFile),
|
|
8138
|
+
hasGlobalIndex: existsSync22(paths.globalIndexFile)
|
|
7897
8139
|
};
|
|
7898
8140
|
}
|
|
7899
8141
|
|
|
@@ -8495,7 +8737,7 @@ function wrapProgressCallbackWithMemory(projectPath, existingCallback, memoryCon
|
|
|
8495
8737
|
}
|
|
8496
8738
|
|
|
8497
8739
|
// src/memory/compressor.ts
|
|
8498
|
-
import { homedir as
|
|
8740
|
+
import { homedir as homedir9 } from "os";
|
|
8499
8741
|
var DEFAULT_COMPRESSION_OPTIONS = {
|
|
8500
8742
|
minObservations: 3,
|
|
8501
8743
|
maxLearnings: 10,
|
|
@@ -9090,7 +9332,7 @@ var MemoryCompressor = class {
|
|
|
9090
9332
|
projectPath,
|
|
9091
9333
|
options?.projectName
|
|
9092
9334
|
);
|
|
9093
|
-
const indexBasePath = options?.scope === "global" ?
|
|
9335
|
+
const indexBasePath = options?.scope === "global" ? homedir9() : projectPath;
|
|
9094
9336
|
this.indexStore = new MemoryIndexStore(indexBasePath, options?.scope === "global");
|
|
9095
9337
|
this.projectName = options?.projectName;
|
|
9096
9338
|
}
|
|
@@ -9773,8 +10015,8 @@ function createMemoryInjector(projectPath, projectName, projectContext) {
|
|
|
9773
10015
|
}
|
|
9774
10016
|
|
|
9775
10017
|
// src/team/manager.ts
|
|
9776
|
-
import { existsSync as
|
|
9777
|
-
import { join as
|
|
10018
|
+
import { existsSync as existsSync23, readFileSync as readFileSync16, writeFileSync as writeFileSync13, mkdirSync as mkdirSync14 } from "fs";
|
|
10019
|
+
import { join as join22, dirname as dirname6 } from "path";
|
|
9778
10020
|
import { execSync as execSync6 } from "child_process";
|
|
9779
10021
|
import { parse as yamlParse, stringify as yamlStringify } from "yaml";
|
|
9780
10022
|
var TEAM_CONFIG_FILE = "team.yaml";
|
|
@@ -9795,9 +10037,9 @@ var TeamManager = class {
|
|
|
9795
10037
|
...config,
|
|
9796
10038
|
teamId
|
|
9797
10039
|
};
|
|
9798
|
-
const teamDir =
|
|
9799
|
-
if (!
|
|
9800
|
-
|
|
10040
|
+
const teamDir = join22(this.projectPath, TEAM_DIR);
|
|
10041
|
+
if (!existsSync23(teamDir)) {
|
|
10042
|
+
mkdirSync14(teamDir, { recursive: true });
|
|
9801
10043
|
}
|
|
9802
10044
|
this.saveConfig(fullConfig);
|
|
9803
10045
|
this.config = fullConfig;
|
|
@@ -9817,12 +10059,12 @@ var TeamManager = class {
|
|
|
9817
10059
|
* Load existing team configuration
|
|
9818
10060
|
*/
|
|
9819
10061
|
load() {
|
|
9820
|
-
const configPath =
|
|
9821
|
-
if (!
|
|
10062
|
+
const configPath = join22(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
|
|
10063
|
+
if (!existsSync23(configPath)) {
|
|
9822
10064
|
return null;
|
|
9823
10065
|
}
|
|
9824
10066
|
try {
|
|
9825
|
-
const content =
|
|
10067
|
+
const content = readFileSync16(configPath, "utf-8");
|
|
9826
10068
|
this.config = this.parseYaml(content);
|
|
9827
10069
|
this.loadRegistry();
|
|
9828
10070
|
return this.config;
|
|
@@ -9853,8 +10095,8 @@ var TeamManager = class {
|
|
|
9853
10095
|
if (!skillPath) {
|
|
9854
10096
|
throw new Error(`Skill "${options.skillName}" not found locally.`);
|
|
9855
10097
|
}
|
|
9856
|
-
const skillMdPath =
|
|
9857
|
-
const skillContent =
|
|
10098
|
+
const skillMdPath = join22(skillPath, "SKILL.md");
|
|
10099
|
+
const skillContent = existsSync23(skillMdPath) ? readFileSync16(skillMdPath, "utf-8") : "";
|
|
9858
10100
|
const metadata = this.extractFrontmatter(skillContent);
|
|
9859
10101
|
const shared = {
|
|
9860
10102
|
name: options.skillName,
|
|
@@ -9919,7 +10161,7 @@ var TeamManager = class {
|
|
|
9919
10161
|
if (options.dryRun) {
|
|
9920
10162
|
return {
|
|
9921
10163
|
success: true,
|
|
9922
|
-
path:
|
|
10164
|
+
path: join22(this.projectPath, ".skillkit", "skills", skillName)
|
|
9923
10165
|
};
|
|
9924
10166
|
}
|
|
9925
10167
|
try {
|
|
@@ -9969,9 +10211,9 @@ var TeamManager = class {
|
|
|
9969
10211
|
if (!fetchResult.success || !fetchResult.path) {
|
|
9970
10212
|
throw new Error(fetchResult.error || "Failed to fetch remote registry");
|
|
9971
10213
|
}
|
|
9972
|
-
const remoteRegistryPath =
|
|
9973
|
-
if (
|
|
9974
|
-
const remoteContent =
|
|
10214
|
+
const remoteRegistryPath = join22(fetchResult.path, TEAM_DIR, "registry.yaml");
|
|
10215
|
+
if (existsSync23(remoteRegistryPath)) {
|
|
10216
|
+
const remoteContent = readFileSync16(remoteRegistryPath, "utf-8");
|
|
9975
10217
|
const remoteRegistry = this.parseYaml(remoteContent);
|
|
9976
10218
|
const localSkillNames = new Set(this.registry?.skills.map((s) => s.name) || []);
|
|
9977
10219
|
for (const skill of remoteRegistry.skills) {
|
|
@@ -10017,32 +10259,32 @@ var TeamManager = class {
|
|
|
10017
10259
|
return `team-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
10018
10260
|
}
|
|
10019
10261
|
saveConfig(config) {
|
|
10020
|
-
const configPath =
|
|
10262
|
+
const configPath = join22(this.projectPath, TEAM_DIR, TEAM_CONFIG_FILE);
|
|
10021
10263
|
const dir = dirname6(configPath);
|
|
10022
|
-
if (!
|
|
10023
|
-
|
|
10264
|
+
if (!existsSync23(dir)) {
|
|
10265
|
+
mkdirSync14(dir, { recursive: true });
|
|
10024
10266
|
}
|
|
10025
|
-
|
|
10267
|
+
writeFileSync13(configPath, this.toYaml(config), "utf-8");
|
|
10026
10268
|
}
|
|
10027
10269
|
loadRegistry() {
|
|
10028
|
-
const registryPath =
|
|
10029
|
-
if (
|
|
10030
|
-
const content =
|
|
10270
|
+
const registryPath = join22(this.projectPath, TEAM_DIR, "registry.yaml");
|
|
10271
|
+
if (existsSync23(registryPath)) {
|
|
10272
|
+
const content = readFileSync16(registryPath, "utf-8");
|
|
10031
10273
|
this.registry = this.parseYaml(content);
|
|
10032
10274
|
}
|
|
10033
10275
|
}
|
|
10034
10276
|
saveRegistry(registry) {
|
|
10035
|
-
const registryPath =
|
|
10036
|
-
|
|
10277
|
+
const registryPath = join22(this.projectPath, TEAM_DIR, "registry.yaml");
|
|
10278
|
+
writeFileSync13(registryPath, this.toYaml(registry), "utf-8");
|
|
10037
10279
|
}
|
|
10038
10280
|
findLocalSkill(skillName) {
|
|
10039
10281
|
const possiblePaths = [
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10282
|
+
join22(this.projectPath, ".skillkit", "skills", skillName),
|
|
10283
|
+
join22(this.projectPath, "skills", skillName),
|
|
10284
|
+
join22(this.projectPath, ".claude", "skills", skillName)
|
|
10043
10285
|
];
|
|
10044
10286
|
for (const p of possiblePaths) {
|
|
10045
|
-
if (
|
|
10287
|
+
if (existsSync23(p)) {
|
|
10046
10288
|
return p;
|
|
10047
10289
|
}
|
|
10048
10290
|
}
|
|
@@ -10059,13 +10301,13 @@ var TeamManager = class {
|
|
|
10059
10301
|
}
|
|
10060
10302
|
detectCompatibleAgents(skillPath) {
|
|
10061
10303
|
const agents = [];
|
|
10062
|
-
if (
|
|
10304
|
+
if (existsSync23(join22(skillPath, "SKILL.md"))) {
|
|
10063
10305
|
agents.push("claude-code", "codex", "gemini-cli", "universal");
|
|
10064
10306
|
}
|
|
10065
|
-
if (
|
|
10307
|
+
if (existsSync23(join22(skillPath, "skill.mdc"))) {
|
|
10066
10308
|
agents.push("cursor");
|
|
10067
10309
|
}
|
|
10068
|
-
if (
|
|
10310
|
+
if (existsSync23(join22(skillPath, "rules.md"))) {
|
|
10069
10311
|
agents.push("windsurf");
|
|
10070
10312
|
}
|
|
10071
10313
|
return agents.length > 0 ? agents : ["universal"];
|
|
@@ -10091,8 +10333,8 @@ function createTeamManager(projectPath) {
|
|
|
10091
10333
|
}
|
|
10092
10334
|
|
|
10093
10335
|
// src/team/bundle.ts
|
|
10094
|
-
import { existsSync as
|
|
10095
|
-
import { join as
|
|
10336
|
+
import { existsSync as existsSync24, readFileSync as readFileSync17, writeFileSync as writeFileSync14, mkdirSync as mkdirSync15, readdirSync as readdirSync6, statSync as statSync3 } from "fs";
|
|
10337
|
+
import { join as join23, basename as basename8, resolve as resolve2, relative, dirname as dirname7, sep } from "path";
|
|
10096
10338
|
import { createHash } from "crypto";
|
|
10097
10339
|
var BUNDLE_VERSION = 1;
|
|
10098
10340
|
var SkillBundle = class {
|
|
@@ -10174,15 +10416,15 @@ var SkillBundle = class {
|
|
|
10174
10416
|
readSkillContent(skillPath) {
|
|
10175
10417
|
const contents = [];
|
|
10176
10418
|
const readDir = (dir, prefix = "") => {
|
|
10177
|
-
const entries =
|
|
10419
|
+
const entries = readdirSync6(dir);
|
|
10178
10420
|
for (const entry of entries) {
|
|
10179
|
-
const fullPath =
|
|
10421
|
+
const fullPath = join23(dir, entry);
|
|
10180
10422
|
const relativePath = prefix ? `${prefix}/${entry}` : entry;
|
|
10181
10423
|
const stat = statSync3(fullPath);
|
|
10182
10424
|
if (stat.isDirectory()) {
|
|
10183
10425
|
readDir(fullPath, relativePath);
|
|
10184
10426
|
} else if (stat.isFile()) {
|
|
10185
|
-
const content =
|
|
10427
|
+
const content = readFileSync17(fullPath, "utf-8");
|
|
10186
10428
|
contents.push(`--- ${relativePath} ---
|
|
10187
10429
|
${content}`);
|
|
10188
10430
|
}
|
|
@@ -10191,13 +10433,13 @@ ${content}`);
|
|
|
10191
10433
|
if (statSync3(skillPath).isDirectory()) {
|
|
10192
10434
|
readDir(skillPath);
|
|
10193
10435
|
} else {
|
|
10194
|
-
contents.push(
|
|
10436
|
+
contents.push(readFileSync17(skillPath, "utf-8"));
|
|
10195
10437
|
}
|
|
10196
10438
|
return contents.join("\n\n");
|
|
10197
10439
|
}
|
|
10198
10440
|
detectAgents(skillPath) {
|
|
10199
10441
|
const agents = [];
|
|
10200
|
-
if (
|
|
10442
|
+
if (existsSync24(skillPath) && statSync3(skillPath).isFile()) {
|
|
10201
10443
|
const fileName = basename8(skillPath).toLowerCase();
|
|
10202
10444
|
if (fileName === "skill.md") {
|
|
10203
10445
|
return ["claude-code", "codex", "gemini-cli", "universal"];
|
|
@@ -10210,13 +10452,13 @@ ${content}`);
|
|
|
10210
10452
|
}
|
|
10211
10453
|
return ["universal"];
|
|
10212
10454
|
}
|
|
10213
|
-
if (
|
|
10455
|
+
if (existsSync24(join23(skillPath, "SKILL.md"))) {
|
|
10214
10456
|
agents.push("claude-code", "codex", "gemini-cli", "universal");
|
|
10215
10457
|
}
|
|
10216
|
-
if (
|
|
10458
|
+
if (existsSync24(join23(skillPath, "skill.mdc"))) {
|
|
10217
10459
|
agents.push("cursor");
|
|
10218
10460
|
}
|
|
10219
|
-
if (
|
|
10461
|
+
if (existsSync24(join23(skillPath, "rules.md"))) {
|
|
10220
10462
|
agents.push("windsurf");
|
|
10221
10463
|
}
|
|
10222
10464
|
return agents.length > 0 ? agents : ["universal"];
|
|
@@ -10239,10 +10481,10 @@ function exportBundle(bundle, outputPath) {
|
|
|
10239
10481
|
}
|
|
10240
10482
|
}
|
|
10241
10483
|
const dir = dirname7(outputPath);
|
|
10242
|
-
if (dir && !
|
|
10243
|
-
|
|
10484
|
+
if (dir && !existsSync24(dir)) {
|
|
10485
|
+
mkdirSync15(dir, { recursive: true });
|
|
10244
10486
|
}
|
|
10245
|
-
|
|
10487
|
+
writeFileSync14(outputPath, JSON.stringify(exportData, null, 2), "utf-8");
|
|
10246
10488
|
return { success: true, path: outputPath };
|
|
10247
10489
|
} catch (err) {
|
|
10248
10490
|
return {
|
|
@@ -10255,7 +10497,7 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
10255
10497
|
const imported = [];
|
|
10256
10498
|
const errors = [];
|
|
10257
10499
|
try {
|
|
10258
|
-
const content =
|
|
10500
|
+
const content = readFileSync17(bundlePath, "utf-8");
|
|
10259
10501
|
const data = JSON.parse(content);
|
|
10260
10502
|
const absoluteTargetDir = resolve2(targetDir);
|
|
10261
10503
|
for (const skill of data.manifest.skills) {
|
|
@@ -10268,19 +10510,19 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
10268
10510
|
errors.push(`Skill "${skill.name}" has no content in bundle`);
|
|
10269
10511
|
continue;
|
|
10270
10512
|
}
|
|
10271
|
-
const skillDir =
|
|
10513
|
+
const skillDir = join23(absoluteTargetDir, skill.name);
|
|
10272
10514
|
const resolvedSkillDir = resolve2(skillDir);
|
|
10273
10515
|
const relativeToTarget = relative(absoluteTargetDir, resolvedSkillDir);
|
|
10274
10516
|
if (relativeToTarget.startsWith("..") || relativeToTarget.startsWith(sep)) {
|
|
10275
10517
|
errors.push(`Skill "${skill.name}" would escape target directory`);
|
|
10276
10518
|
continue;
|
|
10277
10519
|
}
|
|
10278
|
-
if (
|
|
10520
|
+
if (existsSync24(skillDir) && !options.overwrite) {
|
|
10279
10521
|
errors.push(`Skill "${skill.name}" already exists (use --overwrite)`);
|
|
10280
10522
|
continue;
|
|
10281
10523
|
}
|
|
10282
|
-
if (!
|
|
10283
|
-
|
|
10524
|
+
if (!existsSync24(skillDir)) {
|
|
10525
|
+
mkdirSync15(skillDir, { recursive: true });
|
|
10284
10526
|
}
|
|
10285
10527
|
const files = parseSkillContent2(skillContent);
|
|
10286
10528
|
for (const [filePath, fileContent] of Object.entries(files)) {
|
|
@@ -10291,10 +10533,10 @@ function importBundle(bundlePath, targetDir, options = {}) {
|
|
|
10291
10533
|
continue;
|
|
10292
10534
|
}
|
|
10293
10535
|
const fileDir = dirname7(fullPath);
|
|
10294
|
-
if (!
|
|
10295
|
-
|
|
10536
|
+
if (!existsSync24(fileDir)) {
|
|
10537
|
+
mkdirSync15(fileDir, { recursive: true });
|
|
10296
10538
|
}
|
|
10297
|
-
|
|
10539
|
+
writeFileSync14(fullPath, fileContent, "utf-8");
|
|
10298
10540
|
}
|
|
10299
10541
|
imported.push(skill.name);
|
|
10300
10542
|
}
|
|
@@ -10323,8 +10565,8 @@ function parseSkillContent2(content) {
|
|
|
10323
10565
|
}
|
|
10324
10566
|
|
|
10325
10567
|
// src/plugins/manager.ts
|
|
10326
|
-
import { existsSync as
|
|
10327
|
-
import { join as
|
|
10568
|
+
import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync15, mkdirSync as mkdirSync16 } from "fs";
|
|
10569
|
+
import { join as join24 } from "path";
|
|
10328
10570
|
var PLUGINS_DIR = ".skillkit/plugins";
|
|
10329
10571
|
var PLUGINS_CONFIG_FILE = "plugins.json";
|
|
10330
10572
|
var PluginManager = class {
|
|
@@ -10565,22 +10807,22 @@ var PluginManager = class {
|
|
|
10565
10807
|
}
|
|
10566
10808
|
// Private helpers
|
|
10567
10809
|
loadState() {
|
|
10568
|
-
const statePath =
|
|
10569
|
-
if (
|
|
10810
|
+
const statePath = join24(this.projectPath, PLUGINS_DIR, PLUGINS_CONFIG_FILE);
|
|
10811
|
+
if (existsSync25(statePath)) {
|
|
10570
10812
|
try {
|
|
10571
|
-
return JSON.parse(
|
|
10813
|
+
return JSON.parse(readFileSync18(statePath, "utf-8"));
|
|
10572
10814
|
} catch {
|
|
10573
10815
|
}
|
|
10574
10816
|
}
|
|
10575
10817
|
return { version: 1, plugins: {} };
|
|
10576
10818
|
}
|
|
10577
10819
|
saveState() {
|
|
10578
|
-
const pluginsDir =
|
|
10579
|
-
if (!
|
|
10580
|
-
|
|
10820
|
+
const pluginsDir = join24(this.projectPath, PLUGINS_DIR);
|
|
10821
|
+
if (!existsSync25(pluginsDir)) {
|
|
10822
|
+
mkdirSync16(pluginsDir, { recursive: true });
|
|
10581
10823
|
}
|
|
10582
|
-
const statePath =
|
|
10583
|
-
|
|
10824
|
+
const statePath = join24(pluginsDir, PLUGINS_CONFIG_FILE);
|
|
10825
|
+
writeFileSync15(statePath, JSON.stringify(this.state, null, 2), "utf-8");
|
|
10584
10826
|
}
|
|
10585
10827
|
createContext() {
|
|
10586
10828
|
return {
|
|
@@ -10605,15 +10847,15 @@ function createPluginManager(projectPath) {
|
|
|
10605
10847
|
}
|
|
10606
10848
|
|
|
10607
10849
|
// src/plugins/loader.ts
|
|
10608
|
-
import { existsSync as
|
|
10609
|
-
import { join as
|
|
10850
|
+
import { existsSync as existsSync26, readFileSync as readFileSync19, readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
10851
|
+
import { join as join25, extname, basename as basename9, isAbsolute } from "path";
|
|
10610
10852
|
import { pathToFileURL } from "url";
|
|
10611
10853
|
var PluginLoader = class {
|
|
10612
10854
|
/**
|
|
10613
10855
|
* Load a plugin from a file path
|
|
10614
10856
|
*/
|
|
10615
10857
|
async loadFromFile(filePath) {
|
|
10616
|
-
if (!
|
|
10858
|
+
if (!existsSync26(filePath)) {
|
|
10617
10859
|
throw new Error(`Plugin file not found: ${filePath}`);
|
|
10618
10860
|
}
|
|
10619
10861
|
const ext = extname(filePath);
|
|
@@ -10655,11 +10897,11 @@ var PluginLoader = class {
|
|
|
10655
10897
|
* Load a plugin from a JSON definition (for simple plugins)
|
|
10656
10898
|
*/
|
|
10657
10899
|
loadFromJson(jsonPath) {
|
|
10658
|
-
if (!
|
|
10900
|
+
if (!existsSync26(jsonPath)) {
|
|
10659
10901
|
throw new Error(`Plugin JSON not found: ${jsonPath}`);
|
|
10660
10902
|
}
|
|
10661
10903
|
try {
|
|
10662
|
-
const content =
|
|
10904
|
+
const content = readFileSync19(jsonPath, "utf-8");
|
|
10663
10905
|
const data = JSON.parse(content);
|
|
10664
10906
|
if (!data.metadata) {
|
|
10665
10907
|
throw new Error("Invalid plugin JSON: missing metadata");
|
|
@@ -10678,13 +10920,13 @@ var PluginLoader = class {
|
|
|
10678
10920
|
* Scan a directory for plugins
|
|
10679
10921
|
*/
|
|
10680
10922
|
async scanDirectory(dirPath) {
|
|
10681
|
-
if (!
|
|
10923
|
+
if (!existsSync26(dirPath)) {
|
|
10682
10924
|
return [];
|
|
10683
10925
|
}
|
|
10684
10926
|
const plugins = [];
|
|
10685
|
-
const entries =
|
|
10927
|
+
const entries = readdirSync7(dirPath);
|
|
10686
10928
|
for (const entry of entries) {
|
|
10687
|
-
const fullPath =
|
|
10929
|
+
const fullPath = join25(dirPath, entry);
|
|
10688
10930
|
let stat;
|
|
10689
10931
|
try {
|
|
10690
10932
|
stat = statSync4(fullPath);
|
|
@@ -10692,11 +10934,11 @@ var PluginLoader = class {
|
|
|
10692
10934
|
continue;
|
|
10693
10935
|
}
|
|
10694
10936
|
if (stat.isDirectory()) {
|
|
10695
|
-
const pkgPath =
|
|
10696
|
-
const pluginPath =
|
|
10697
|
-
if (
|
|
10937
|
+
const pkgPath = join25(fullPath, "package.json");
|
|
10938
|
+
const pluginPath = join25(fullPath, "plugin.json");
|
|
10939
|
+
if (existsSync26(pkgPath)) {
|
|
10698
10940
|
try {
|
|
10699
|
-
const pkg = JSON.parse(
|
|
10941
|
+
const pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
|
|
10700
10942
|
if ((pkg.skillkitPlugin || pkg.keywords?.includes("skillkit-plugin")) && pkg.name && typeof pkg.name === "string" && pkg.version && typeof pkg.version === "string") {
|
|
10701
10943
|
plugins.push({
|
|
10702
10944
|
name: pkg.name,
|
|
@@ -10708,9 +10950,9 @@ var PluginLoader = class {
|
|
|
10708
10950
|
}
|
|
10709
10951
|
} catch {
|
|
10710
10952
|
}
|
|
10711
|
-
} else if (
|
|
10953
|
+
} else if (existsSync26(pluginPath)) {
|
|
10712
10954
|
try {
|
|
10713
|
-
const data = JSON.parse(
|
|
10955
|
+
const data = JSON.parse(readFileSync19(pluginPath, "utf-8"));
|
|
10714
10956
|
if (data.metadata && data.metadata.name && typeof data.metadata.name === "string" && data.metadata.version && typeof data.metadata.version === "string") {
|
|
10715
10957
|
plugins.push(data.metadata);
|
|
10716
10958
|
}
|
|
@@ -10798,12 +11040,12 @@ async function loadPlugin(source) {
|
|
|
10798
11040
|
async function loadPluginsFromDirectory(dirPath) {
|
|
10799
11041
|
const loader = new PluginLoader();
|
|
10800
11042
|
const plugins = [];
|
|
10801
|
-
if (!
|
|
11043
|
+
if (!existsSync26(dirPath)) {
|
|
10802
11044
|
return plugins;
|
|
10803
11045
|
}
|
|
10804
|
-
const entries =
|
|
11046
|
+
const entries = readdirSync7(dirPath);
|
|
10805
11047
|
for (const entry of entries) {
|
|
10806
|
-
const fullPath =
|
|
11048
|
+
const fullPath = join25(dirPath, entry);
|
|
10807
11049
|
let stat;
|
|
10808
11050
|
try {
|
|
10809
11051
|
stat = statSync4(fullPath);
|
|
@@ -10812,20 +11054,20 @@ async function loadPluginsFromDirectory(dirPath) {
|
|
|
10812
11054
|
}
|
|
10813
11055
|
try {
|
|
10814
11056
|
if (stat.isDirectory()) {
|
|
10815
|
-
const indexMjsPath =
|
|
10816
|
-
const indexPath =
|
|
10817
|
-
const mainMjsPath =
|
|
10818
|
-
const mainPath =
|
|
10819
|
-
const jsonPath =
|
|
10820
|
-
if (
|
|
11057
|
+
const indexMjsPath = join25(fullPath, "index.mjs");
|
|
11058
|
+
const indexPath = join25(fullPath, "index.js");
|
|
11059
|
+
const mainMjsPath = join25(fullPath, "plugin.mjs");
|
|
11060
|
+
const mainPath = join25(fullPath, "plugin.js");
|
|
11061
|
+
const jsonPath = join25(fullPath, "plugin.json");
|
|
11062
|
+
if (existsSync26(indexMjsPath)) {
|
|
10821
11063
|
plugins.push(await loader.loadFromFile(indexMjsPath));
|
|
10822
|
-
} else if (
|
|
11064
|
+
} else if (existsSync26(indexPath)) {
|
|
10823
11065
|
plugins.push(await loader.loadFromFile(indexPath));
|
|
10824
|
-
} else if (
|
|
11066
|
+
} else if (existsSync26(mainMjsPath)) {
|
|
10825
11067
|
plugins.push(await loader.loadFromFile(mainMjsPath));
|
|
10826
|
-
} else if (
|
|
11068
|
+
} else if (existsSync26(mainPath)) {
|
|
10827
11069
|
plugins.push(await loader.loadFromFile(mainPath));
|
|
10828
|
-
} else if (
|
|
11070
|
+
} else if (existsSync26(jsonPath)) {
|
|
10829
11071
|
plugins.push(loader.loadFromJson(jsonPath));
|
|
10830
11072
|
}
|
|
10831
11073
|
} else if (stat.isFile()) {
|
|
@@ -10844,17 +11086,17 @@ async function loadPluginsFromDirectory(dirPath) {
|
|
|
10844
11086
|
}
|
|
10845
11087
|
|
|
10846
11088
|
// src/methodology/manager.ts
|
|
10847
|
-
import { existsSync as
|
|
10848
|
-
import { join as
|
|
11089
|
+
import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync16, mkdirSync as mkdirSync17 } from "fs";
|
|
11090
|
+
import { join as join28, dirname as dirname9 } from "path";
|
|
10849
11091
|
|
|
10850
11092
|
// src/methodology/loader.ts
|
|
10851
|
-
import { existsSync as
|
|
10852
|
-
import { join as
|
|
11093
|
+
import { existsSync as existsSync28, readFileSync as readFileSync21, readdirSync as readdirSync9, statSync as statSync6 } from "fs";
|
|
11094
|
+
import { join as join27, dirname as dirname8 } from "path";
|
|
10853
11095
|
import { fileURLToPath } from "url";
|
|
10854
11096
|
|
|
10855
11097
|
// src/methodology/validator.ts
|
|
10856
|
-
import { existsSync as
|
|
10857
|
-
import { join as
|
|
11098
|
+
import { existsSync as existsSync27, readFileSync as readFileSync20, readdirSync as readdirSync8, statSync as statSync5 } from "fs";
|
|
11099
|
+
import { join as join26 } from "path";
|
|
10858
11100
|
function validatePackManifest(pack) {
|
|
10859
11101
|
const errors = [];
|
|
10860
11102
|
const warnings = [];
|
|
@@ -11004,15 +11246,15 @@ function validateSkillContent(content) {
|
|
|
11004
11246
|
function validatePackDirectory(packPath) {
|
|
11005
11247
|
const errors = [];
|
|
11006
11248
|
const warnings = [];
|
|
11007
|
-
if (!
|
|
11249
|
+
if (!existsSync27(packPath)) {
|
|
11008
11250
|
errors.push({
|
|
11009
11251
|
code: "DIR_NOT_FOUND",
|
|
11010
11252
|
message: `Pack directory not found: ${packPath}`
|
|
11011
11253
|
});
|
|
11012
11254
|
return { valid: false, errors, warnings };
|
|
11013
11255
|
}
|
|
11014
|
-
const manifestPath =
|
|
11015
|
-
if (!
|
|
11256
|
+
const manifestPath = join26(packPath, "pack.json");
|
|
11257
|
+
if (!existsSync27(manifestPath)) {
|
|
11016
11258
|
errors.push({
|
|
11017
11259
|
code: "MANIFEST_NOT_FOUND",
|
|
11018
11260
|
message: "Pack must have a pack.json manifest",
|
|
@@ -11022,7 +11264,7 @@ function validatePackDirectory(packPath) {
|
|
|
11022
11264
|
}
|
|
11023
11265
|
let manifest;
|
|
11024
11266
|
try {
|
|
11025
|
-
const raw =
|
|
11267
|
+
const raw = readFileSync20(manifestPath, "utf-8");
|
|
11026
11268
|
manifest = JSON.parse(raw);
|
|
11027
11269
|
const manifestResult = validatePackManifest(manifest);
|
|
11028
11270
|
errors.push(...manifestResult.errors);
|
|
@@ -11037,8 +11279,8 @@ function validatePackDirectory(packPath) {
|
|
|
11037
11279
|
}
|
|
11038
11280
|
if (manifest.skills) {
|
|
11039
11281
|
for (const skillName of manifest.skills) {
|
|
11040
|
-
const skillDir =
|
|
11041
|
-
if (!
|
|
11282
|
+
const skillDir = join26(packPath, skillName);
|
|
11283
|
+
if (!existsSync27(skillDir)) {
|
|
11042
11284
|
errors.push({
|
|
11043
11285
|
code: "SKILL_DIR_NOT_FOUND",
|
|
11044
11286
|
message: `Skill directory not found: ${skillName}`,
|
|
@@ -11054,8 +11296,8 @@ function validatePackDirectory(packPath) {
|
|
|
11054
11296
|
});
|
|
11055
11297
|
continue;
|
|
11056
11298
|
}
|
|
11057
|
-
const skillFile =
|
|
11058
|
-
if (!
|
|
11299
|
+
const skillFile = join26(skillDir, "SKILL.md");
|
|
11300
|
+
if (!existsSync27(skillFile)) {
|
|
11059
11301
|
errors.push({
|
|
11060
11302
|
code: "SKILL_FILE_NOT_FOUND",
|
|
11061
11303
|
message: `Skill must have a SKILL.md file: ${skillName}`,
|
|
@@ -11063,7 +11305,7 @@ function validatePackDirectory(packPath) {
|
|
|
11063
11305
|
});
|
|
11064
11306
|
continue;
|
|
11065
11307
|
}
|
|
11066
|
-
const skillContent =
|
|
11308
|
+
const skillContent = readFileSync20(skillFile, "utf-8");
|
|
11067
11309
|
const skillResult = validateSkillContent(skillContent);
|
|
11068
11310
|
for (const err of skillResult.errors) {
|
|
11069
11311
|
errors.push({
|
|
@@ -11087,15 +11329,15 @@ function validatePackDirectory(packPath) {
|
|
|
11087
11329
|
}
|
|
11088
11330
|
function validateBuiltinPacks(packsDir) {
|
|
11089
11331
|
const results = /* @__PURE__ */ new Map();
|
|
11090
|
-
if (!
|
|
11332
|
+
if (!existsSync27(packsDir)) {
|
|
11091
11333
|
return results;
|
|
11092
11334
|
}
|
|
11093
|
-
const packDirs =
|
|
11094
|
-
const packPath =
|
|
11335
|
+
const packDirs = readdirSync8(packsDir).filter((name) => {
|
|
11336
|
+
const packPath = join26(packsDir, name);
|
|
11095
11337
|
return statSync5(packPath).isDirectory();
|
|
11096
11338
|
});
|
|
11097
11339
|
for (const packName of packDirs) {
|
|
11098
|
-
const packPath =
|
|
11340
|
+
const packPath = join26(packsDir, packName);
|
|
11099
11341
|
results.set(packName, validatePackDirectory(packPath));
|
|
11100
11342
|
}
|
|
11101
11343
|
return results;
|
|
@@ -11154,7 +11396,7 @@ function extractSkillMetadata(content) {
|
|
|
11154
11396
|
// src/methodology/loader.ts
|
|
11155
11397
|
var __filename = fileURLToPath(import.meta.url);
|
|
11156
11398
|
var __dirname = dirname8(__filename);
|
|
11157
|
-
var BUILTIN_PACKS_DIR =
|
|
11399
|
+
var BUILTIN_PACKS_DIR = join27(__dirname, "packs");
|
|
11158
11400
|
var MethodologyLoader = class {
|
|
11159
11401
|
packsDir;
|
|
11160
11402
|
loadedPacks = /* @__PURE__ */ new Map();
|
|
@@ -11167,11 +11409,11 @@ var MethodologyLoader = class {
|
|
|
11167
11409
|
*/
|
|
11168
11410
|
async loadAllPacks() {
|
|
11169
11411
|
const packs = [];
|
|
11170
|
-
if (!
|
|
11412
|
+
if (!existsSync28(this.packsDir)) {
|
|
11171
11413
|
return packs;
|
|
11172
11414
|
}
|
|
11173
|
-
const packDirs =
|
|
11174
|
-
const packPath =
|
|
11415
|
+
const packDirs = readdirSync9(this.packsDir).filter((name) => {
|
|
11416
|
+
const packPath = join27(this.packsDir, name);
|
|
11175
11417
|
return statSync6(packPath).isDirectory();
|
|
11176
11418
|
});
|
|
11177
11419
|
for (const packName of packDirs) {
|
|
@@ -11192,9 +11434,9 @@ var MethodologyLoader = class {
|
|
|
11192
11434
|
if (this.loadedPacks.has(packName)) {
|
|
11193
11435
|
return this.loadedPacks.get(packName);
|
|
11194
11436
|
}
|
|
11195
|
-
const packPath =
|
|
11196
|
-
const manifestPath =
|
|
11197
|
-
if (!
|
|
11437
|
+
const packPath = join27(this.packsDir, packName);
|
|
11438
|
+
const manifestPath = join27(packPath, "pack.json");
|
|
11439
|
+
if (!existsSync28(manifestPath)) {
|
|
11198
11440
|
return null;
|
|
11199
11441
|
}
|
|
11200
11442
|
const validation = validatePackDirectory(packPath);
|
|
@@ -11204,7 +11446,7 @@ var MethodologyLoader = class {
|
|
|
11204
11446
|
);
|
|
11205
11447
|
}
|
|
11206
11448
|
const manifest = JSON.parse(
|
|
11207
|
-
|
|
11449
|
+
readFileSync21(manifestPath, "utf-8")
|
|
11208
11450
|
);
|
|
11209
11451
|
this.loadedPacks.set(packName, manifest);
|
|
11210
11452
|
return manifest;
|
|
@@ -11234,11 +11476,11 @@ var MethodologyLoader = class {
|
|
|
11234
11476
|
if (this.loadedSkills.has(skillId)) {
|
|
11235
11477
|
return this.loadedSkills.get(skillId);
|
|
11236
11478
|
}
|
|
11237
|
-
const skillPath =
|
|
11238
|
-
if (!
|
|
11479
|
+
const skillPath = join27(this.packsDir, packName, skillName, "SKILL.md");
|
|
11480
|
+
if (!existsSync28(skillPath)) {
|
|
11239
11481
|
return null;
|
|
11240
11482
|
}
|
|
11241
|
-
const content =
|
|
11483
|
+
const content = readFileSync21(skillPath, "utf-8");
|
|
11242
11484
|
const rawMetadata = extractSkillMetadata(content);
|
|
11243
11485
|
const metadata = {
|
|
11244
11486
|
triggers: rawMetadata.triggers,
|
|
@@ -11317,9 +11559,9 @@ var MethodologyLoader = class {
|
|
|
11317
11559
|
* Check if a pack exists
|
|
11318
11560
|
*/
|
|
11319
11561
|
packExists(packName) {
|
|
11320
|
-
const packPath =
|
|
11321
|
-
const manifestPath =
|
|
11322
|
-
return
|
|
11562
|
+
const packPath = join27(this.packsDir, packName);
|
|
11563
|
+
const manifestPath = join27(packPath, "pack.json");
|
|
11564
|
+
return existsSync28(manifestPath);
|
|
11323
11565
|
}
|
|
11324
11566
|
/**
|
|
11325
11567
|
* Clear cache
|
|
@@ -11685,10 +11927,10 @@ var MethodologyManager = class {
|
|
|
11685
11927
|
}
|
|
11686
11928
|
// Private helpers
|
|
11687
11929
|
loadState() {
|
|
11688
|
-
const statePath =
|
|
11689
|
-
if (
|
|
11930
|
+
const statePath = join28(this.projectPath, METHODOLOGY_STATE_FILE);
|
|
11931
|
+
if (existsSync29(statePath)) {
|
|
11690
11932
|
try {
|
|
11691
|
-
return JSON.parse(
|
|
11933
|
+
return JSON.parse(readFileSync22(statePath, "utf-8"));
|
|
11692
11934
|
} catch {
|
|
11693
11935
|
}
|
|
11694
11936
|
}
|
|
@@ -11699,21 +11941,21 @@ var MethodologyManager = class {
|
|
|
11699
11941
|
};
|
|
11700
11942
|
}
|
|
11701
11943
|
saveState() {
|
|
11702
|
-
const statePath =
|
|
11944
|
+
const statePath = join28(this.projectPath, METHODOLOGY_STATE_FILE);
|
|
11703
11945
|
const dir = dirname9(statePath);
|
|
11704
|
-
if (!
|
|
11705
|
-
|
|
11946
|
+
if (!existsSync29(dir)) {
|
|
11947
|
+
mkdirSync17(dir, { recursive: true });
|
|
11706
11948
|
}
|
|
11707
|
-
|
|
11949
|
+
writeFileSync16(statePath, JSON.stringify(this.state, null, 2), "utf-8");
|
|
11708
11950
|
}
|
|
11709
11951
|
async installSkillLocally(skill) {
|
|
11710
|
-
const skillsDir =
|
|
11711
|
-
const skillDir =
|
|
11712
|
-
if (!
|
|
11713
|
-
|
|
11952
|
+
const skillsDir = join28(this.projectPath, ".skillkit", "methodology", "skills");
|
|
11953
|
+
const skillDir = join28(skillsDir, skill.pack, skill.id.split("/")[1]);
|
|
11954
|
+
if (!existsSync29(skillDir)) {
|
|
11955
|
+
mkdirSync17(skillDir, { recursive: true });
|
|
11714
11956
|
}
|
|
11715
|
-
const targetPath =
|
|
11716
|
-
|
|
11957
|
+
const targetPath = join28(skillDir, "SKILL.md");
|
|
11958
|
+
writeFileSync16(targetPath, skill.content, "utf-8");
|
|
11717
11959
|
}
|
|
11718
11960
|
async removeSkillLocally(_skillId) {
|
|
11719
11961
|
}
|
|
@@ -11741,9 +11983,9 @@ var MethodologyManager = class {
|
|
|
11741
11983
|
if (!agentDir) {
|
|
11742
11984
|
throw new Error(`Unknown agent: ${agent}`);
|
|
11743
11985
|
}
|
|
11744
|
-
const skillsDir =
|
|
11745
|
-
if (!
|
|
11746
|
-
|
|
11986
|
+
const skillsDir = join28(this.projectPath, agentDir);
|
|
11987
|
+
if (!existsSync29(skillsDir)) {
|
|
11988
|
+
mkdirSync17(skillsDir, { recursive: true });
|
|
11747
11989
|
}
|
|
11748
11990
|
const skillName = skillId.split("/")[1];
|
|
11749
11991
|
let filename;
|
|
@@ -11754,8 +11996,8 @@ var MethodologyManager = class {
|
|
|
11754
11996
|
} else {
|
|
11755
11997
|
filename = `${skillName}.md`;
|
|
11756
11998
|
}
|
|
11757
|
-
const targetPath =
|
|
11758
|
-
|
|
11999
|
+
const targetPath = join28(skillsDir, filename);
|
|
12000
|
+
writeFileSync16(targetPath, content, "utf-8");
|
|
11759
12001
|
}
|
|
11760
12002
|
detectAgents() {
|
|
11761
12003
|
const agents = [];
|
|
@@ -11778,7 +12020,7 @@ var MethodologyManager = class {
|
|
|
11778
12020
|
["windsurf", ".windsurf"]
|
|
11779
12021
|
];
|
|
11780
12022
|
for (const [agent, dir] of agentDirs) {
|
|
11781
|
-
if (
|
|
12023
|
+
if (existsSync29(join28(this.projectPath, dir))) {
|
|
11782
12024
|
agents.push(agent);
|
|
11783
12025
|
}
|
|
11784
12026
|
}
|
|
@@ -11791,8 +12033,8 @@ function createMethodologyManager(options) {
|
|
|
11791
12033
|
}
|
|
11792
12034
|
|
|
11793
12035
|
// src/hooks/manager.ts
|
|
11794
|
-
import { existsSync as
|
|
11795
|
-
import { join as
|
|
12036
|
+
import { existsSync as existsSync30, readFileSync as readFileSync23, writeFileSync as writeFileSync17, mkdirSync as mkdirSync18 } from "fs";
|
|
12037
|
+
import { join as join29, dirname as dirname10 } from "path";
|
|
11796
12038
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
11797
12039
|
import { minimatch } from "minimatch";
|
|
11798
12040
|
var DEFAULT_CONFIG_PATH = ".skillkit/hooks.json";
|
|
@@ -11803,7 +12045,7 @@ var HookManager = class {
|
|
|
11803
12045
|
constructor(options) {
|
|
11804
12046
|
this.options = {
|
|
11805
12047
|
projectPath: options.projectPath,
|
|
11806
|
-
configPath: options.configPath ||
|
|
12048
|
+
configPath: options.configPath || join29(options.projectPath, DEFAULT_CONFIG_PATH),
|
|
11807
12049
|
autoLoad: options.autoLoad ?? true,
|
|
11808
12050
|
defaultInjectionMode: options.defaultInjectionMode || "reference"
|
|
11809
12051
|
};
|
|
@@ -11943,11 +12185,11 @@ var HookManager = class {
|
|
|
11943
12185
|
* Load hooks from config file
|
|
11944
12186
|
*/
|
|
11945
12187
|
load() {
|
|
11946
|
-
if (!
|
|
12188
|
+
if (!existsSync30(this.options.configPath)) {
|
|
11947
12189
|
return;
|
|
11948
12190
|
}
|
|
11949
12191
|
try {
|
|
11950
|
-
const content =
|
|
12192
|
+
const content = readFileSync23(this.options.configPath, "utf-8");
|
|
11951
12193
|
const config = JSON.parse(content);
|
|
11952
12194
|
this.hooks.clear();
|
|
11953
12195
|
for (const hook of config.hooks) {
|
|
@@ -11975,10 +12217,10 @@ var HookManager = class {
|
|
|
11975
12217
|
}
|
|
11976
12218
|
};
|
|
11977
12219
|
const dir = dirname10(this.options.configPath);
|
|
11978
|
-
if (!
|
|
11979
|
-
|
|
12220
|
+
if (!existsSync30(dir)) {
|
|
12221
|
+
mkdirSync18(dir, { recursive: true });
|
|
11980
12222
|
}
|
|
11981
|
-
|
|
12223
|
+
writeFileSync17(this.options.configPath, JSON.stringify(config, null, 2));
|
|
11982
12224
|
}
|
|
11983
12225
|
/**
|
|
11984
12226
|
* Generate agent-specific hook configuration
|
|
@@ -12220,7 +12462,7 @@ function createHookManager(options) {
|
|
|
12220
12462
|
|
|
12221
12463
|
// src/hooks/triggers.ts
|
|
12222
12464
|
import { watch } from "fs";
|
|
12223
|
-
import { join as
|
|
12465
|
+
import { join as join30, relative as relative2 } from "path";
|
|
12224
12466
|
function debounce(fn, delay) {
|
|
12225
12467
|
let timeoutId = null;
|
|
12226
12468
|
return (...args) => {
|
|
@@ -12405,7 +12647,7 @@ var SkillTriggerEngine = class {
|
|
|
12405
12647
|
{ recursive: true },
|
|
12406
12648
|
debounce((eventType, filename) => {
|
|
12407
12649
|
if (!filename) return;
|
|
12408
|
-
const relativePath = relative2(this.options.projectPath,
|
|
12650
|
+
const relativePath = relative2(this.options.projectPath, join30(this.options.projectPath, filename));
|
|
12409
12651
|
if (this.shouldIgnore(relativePath)) return;
|
|
12410
12652
|
if (eventType === "rename") {
|
|
12411
12653
|
this.triggerFileCreate(relativePath);
|
|
@@ -14839,8 +15081,8 @@ var shellExecutor = async (step, _task, _plan) => {
|
|
|
14839
15081
|
return { success: true, output: "No command to execute" };
|
|
14840
15082
|
}
|
|
14841
15083
|
try {
|
|
14842
|
-
const { execSync:
|
|
14843
|
-
const output =
|
|
15084
|
+
const { execSync: execSync8 } = await import("child_process");
|
|
15085
|
+
const output = execSync8(step.command, { encoding: "utf-8", timeout: 6e4 });
|
|
14844
15086
|
if (step.expectedOutput && !output.includes(step.expectedOutput)) {
|
|
14845
15087
|
return {
|
|
14846
15088
|
success: false,
|
|
@@ -16502,8 +16744,8 @@ var CUSTOM_AGENT_FORMAT_MAP = {
|
|
|
16502
16744
|
};
|
|
16503
16745
|
|
|
16504
16746
|
// src/agents/parser.ts
|
|
16505
|
-
import { existsSync as
|
|
16506
|
-
import { join as
|
|
16747
|
+
import { existsSync as existsSync31, readFileSync as readFileSync24, statSync as statSync7 } from "fs";
|
|
16748
|
+
import { join as join31, basename as basename10, extname as extname2 } from "path";
|
|
16507
16749
|
import { parse as parseYaml10 } from "yaml";
|
|
16508
16750
|
function extractAgentFrontmatter(content) {
|
|
16509
16751
|
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
@@ -16521,14 +16763,14 @@ function extractAgentContent(content) {
|
|
|
16521
16763
|
return withoutFrontmatter.trim();
|
|
16522
16764
|
}
|
|
16523
16765
|
function parseAgentFile(filePath, location = "project") {
|
|
16524
|
-
if (!
|
|
16766
|
+
if (!existsSync31(filePath)) {
|
|
16525
16767
|
return null;
|
|
16526
16768
|
}
|
|
16527
16769
|
if (extname2(filePath) !== ".md") {
|
|
16528
16770
|
return null;
|
|
16529
16771
|
}
|
|
16530
16772
|
try {
|
|
16531
|
-
const content =
|
|
16773
|
+
const content = readFileSync24(filePath, "utf-8");
|
|
16532
16774
|
const rawFrontmatter = extractAgentFrontmatter(content);
|
|
16533
16775
|
const agentContent = extractAgentContent(content);
|
|
16534
16776
|
if (!rawFrontmatter) {
|
|
@@ -16580,16 +16822,16 @@ function parseAgentFile(filePath, location = "project") {
|
|
|
16580
16822
|
}
|
|
16581
16823
|
}
|
|
16582
16824
|
function parseAgentDir(dirPath, location = "project") {
|
|
16583
|
-
const agentMdPath =
|
|
16584
|
-
if (
|
|
16825
|
+
const agentMdPath = join31(dirPath, "AGENT.md");
|
|
16826
|
+
if (existsSync31(agentMdPath)) {
|
|
16585
16827
|
const agent = parseAgentFile(agentMdPath, location);
|
|
16586
16828
|
if (agent) {
|
|
16587
16829
|
agent.path = dirPath;
|
|
16588
16830
|
}
|
|
16589
16831
|
return agent;
|
|
16590
16832
|
}
|
|
16591
|
-
const indexMdPath =
|
|
16592
|
-
if (
|
|
16833
|
+
const indexMdPath = join31(dirPath, "index.md");
|
|
16834
|
+
if (existsSync31(indexMdPath)) {
|
|
16593
16835
|
const agent = parseAgentFile(indexMdPath, location);
|
|
16594
16836
|
if (agent) {
|
|
16595
16837
|
agent.path = dirPath;
|
|
@@ -16599,11 +16841,11 @@ function parseAgentDir(dirPath, location = "project") {
|
|
|
16599
16841
|
return null;
|
|
16600
16842
|
}
|
|
16601
16843
|
function loadAgentMetadata(metadataPath) {
|
|
16602
|
-
if (!
|
|
16844
|
+
if (!existsSync31(metadataPath)) {
|
|
16603
16845
|
return null;
|
|
16604
16846
|
}
|
|
16605
16847
|
try {
|
|
16606
|
-
const content =
|
|
16848
|
+
const content = readFileSync24(metadataPath, "utf-8");
|
|
16607
16849
|
const data = JSON.parse(content);
|
|
16608
16850
|
const parsed = AgentMetadata.safeParse(data);
|
|
16609
16851
|
return parsed.success ? parsed.data : null;
|
|
@@ -16704,25 +16946,25 @@ function fromCanonicalAgent(canonical, _targetFormat = "claude-agent") {
|
|
|
16704
16946
|
return lines.join("\n");
|
|
16705
16947
|
}
|
|
16706
16948
|
function readAgentContent(agentPath) {
|
|
16707
|
-
if (
|
|
16949
|
+
if (existsSync31(agentPath) && extname2(agentPath) === ".md") {
|
|
16708
16950
|
try {
|
|
16709
|
-
return
|
|
16951
|
+
return readFileSync24(agentPath, "utf-8");
|
|
16710
16952
|
} catch {
|
|
16711
16953
|
return null;
|
|
16712
16954
|
}
|
|
16713
16955
|
}
|
|
16714
|
-
const agentMdPath =
|
|
16715
|
-
if (
|
|
16956
|
+
const agentMdPath = join31(agentPath, "AGENT.md");
|
|
16957
|
+
if (existsSync31(agentMdPath)) {
|
|
16716
16958
|
try {
|
|
16717
|
-
return
|
|
16959
|
+
return readFileSync24(agentMdPath, "utf-8");
|
|
16718
16960
|
} catch {
|
|
16719
16961
|
return null;
|
|
16720
16962
|
}
|
|
16721
16963
|
}
|
|
16722
|
-
const indexMdPath =
|
|
16723
|
-
if (
|
|
16964
|
+
const indexMdPath = join31(agentPath, "index.md");
|
|
16965
|
+
if (existsSync31(indexMdPath)) {
|
|
16724
16966
|
try {
|
|
16725
|
-
return
|
|
16967
|
+
return readFileSync24(indexMdPath, "utf-8");
|
|
16726
16968
|
} catch {
|
|
16727
16969
|
return null;
|
|
16728
16970
|
}
|
|
@@ -16733,17 +16975,17 @@ function validateAgent(agentPath) {
|
|
|
16733
16975
|
const errors = [];
|
|
16734
16976
|
const warnings = [];
|
|
16735
16977
|
let filePath = agentPath;
|
|
16736
|
-
if (!
|
|
16978
|
+
if (!existsSync31(agentPath)) {
|
|
16737
16979
|
errors.push(`Agent file not found: ${agentPath}`);
|
|
16738
16980
|
return { valid: false, errors, warnings };
|
|
16739
16981
|
}
|
|
16740
16982
|
const stats = statSync7(agentPath);
|
|
16741
16983
|
if (stats.isDirectory()) {
|
|
16742
|
-
const agentMd =
|
|
16743
|
-
const indexMd =
|
|
16744
|
-
if (
|
|
16984
|
+
const agentMd = join31(agentPath, "AGENT.md");
|
|
16985
|
+
const indexMd = join31(agentPath, "index.md");
|
|
16986
|
+
if (existsSync31(agentMd)) {
|
|
16745
16987
|
filePath = agentMd;
|
|
16746
|
-
} else if (
|
|
16988
|
+
} else if (existsSync31(indexMd)) {
|
|
16747
16989
|
filePath = indexMd;
|
|
16748
16990
|
} else {
|
|
16749
16991
|
errors.push("Directory must contain AGENT.md or index.md");
|
|
@@ -16752,7 +16994,7 @@ function validateAgent(agentPath) {
|
|
|
16752
16994
|
}
|
|
16753
16995
|
let content;
|
|
16754
16996
|
try {
|
|
16755
|
-
content =
|
|
16997
|
+
content = readFileSync24(filePath, "utf-8");
|
|
16756
16998
|
} catch {
|
|
16757
16999
|
errors.push(`Cannot read file: ${filePath}`);
|
|
16758
17000
|
return { valid: false, errors, warnings };
|
|
@@ -16789,18 +17031,18 @@ function validateAgent(agentPath) {
|
|
|
16789
17031
|
}
|
|
16790
17032
|
|
|
16791
17033
|
// src/agents/discovery.ts
|
|
16792
|
-
import { existsSync as
|
|
16793
|
-
import { join as
|
|
16794
|
-
import { homedir as
|
|
17034
|
+
import { existsSync as existsSync32, readdirSync as readdirSync10, statSync as statSync8 } from "fs";
|
|
17035
|
+
import { join as join32, extname as extname3 } from "path";
|
|
17036
|
+
import { homedir as homedir10 } from "os";
|
|
16795
17037
|
function discoverAgentsInDir(dir, location) {
|
|
16796
17038
|
const agents = [];
|
|
16797
|
-
if (!
|
|
17039
|
+
if (!existsSync32(dir)) {
|
|
16798
17040
|
return agents;
|
|
16799
17041
|
}
|
|
16800
17042
|
try {
|
|
16801
|
-
const entries =
|
|
17043
|
+
const entries = readdirSync10(dir, { withFileTypes: true });
|
|
16802
17044
|
for (const entry of entries) {
|
|
16803
|
-
const entryPath =
|
|
17045
|
+
const entryPath = join32(dir, entry.name);
|
|
16804
17046
|
if (entry.isFile() && extname3(entry.name) === ".md") {
|
|
16805
17047
|
const agent = parseAgentFile(entryPath, location);
|
|
16806
17048
|
if (agent) {
|
|
@@ -16821,8 +17063,8 @@ function discoverAgents(rootDir) {
|
|
|
16821
17063
|
const agents = [];
|
|
16822
17064
|
const seen = /* @__PURE__ */ new Set();
|
|
16823
17065
|
for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
|
|
16824
|
-
const fullPath =
|
|
16825
|
-
if (
|
|
17066
|
+
const fullPath = join32(rootDir, searchPath);
|
|
17067
|
+
if (existsSync32(fullPath)) {
|
|
16826
17068
|
for (const agent of discoverAgentsInDir(fullPath, "project")) {
|
|
16827
17069
|
if (!seen.has(agent.name)) {
|
|
16828
17070
|
seen.add(agent.name);
|
|
@@ -16838,8 +17080,8 @@ function discoverAgentsForAgent(rootDir, agentType) {
|
|
|
16838
17080
|
const seen = /* @__PURE__ */ new Set();
|
|
16839
17081
|
const paths = AGENT_DISCOVERY_PATHS[agentType] || [];
|
|
16840
17082
|
for (const searchPath of paths) {
|
|
16841
|
-
const fullPath =
|
|
16842
|
-
if (
|
|
17083
|
+
const fullPath = join32(rootDir, searchPath);
|
|
17084
|
+
if (existsSync32(fullPath)) {
|
|
16843
17085
|
for (const agent of discoverAgentsInDir(fullPath, "project")) {
|
|
16844
17086
|
if (!seen.has(agent.name)) {
|
|
16845
17087
|
seen.add(agent.name);
|
|
@@ -16853,14 +17095,14 @@ function discoverAgentsForAgent(rootDir, agentType) {
|
|
|
16853
17095
|
function discoverGlobalAgents() {
|
|
16854
17096
|
const agents = [];
|
|
16855
17097
|
const seen = /* @__PURE__ */ new Set();
|
|
16856
|
-
const home =
|
|
17098
|
+
const home = homedir10();
|
|
16857
17099
|
const globalPaths = [
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
17100
|
+
join32(home, ".claude", "agents"),
|
|
17101
|
+
join32(home, ".skillkit", "agents"),
|
|
17102
|
+
join32(home, ".config", "skillkit", "agents")
|
|
16861
17103
|
];
|
|
16862
17104
|
for (const searchPath of globalPaths) {
|
|
16863
|
-
if (
|
|
17105
|
+
if (existsSync32(searchPath)) {
|
|
16864
17106
|
for (const agent of discoverAgentsInDir(searchPath, "global")) {
|
|
16865
17107
|
if (!seen.has(agent.name)) {
|
|
16866
17108
|
seen.add(agent.name);
|
|
@@ -16875,7 +17117,7 @@ function findAllAgents(searchDirs) {
|
|
|
16875
17117
|
const agents = [];
|
|
16876
17118
|
const seen = /* @__PURE__ */ new Set();
|
|
16877
17119
|
for (const dir of searchDirs) {
|
|
16878
|
-
if (!
|
|
17120
|
+
if (!existsSync32(dir)) continue;
|
|
16879
17121
|
const discovered = discoverAgents(dir);
|
|
16880
17122
|
for (const agent of discovered) {
|
|
16881
17123
|
if (!seen.has(agent.name)) {
|
|
@@ -16894,33 +17136,33 @@ function findAllAgents(searchDirs) {
|
|
|
16894
17136
|
}
|
|
16895
17137
|
function findAgent(name, searchDirs) {
|
|
16896
17138
|
for (const dir of searchDirs) {
|
|
16897
|
-
if (!
|
|
17139
|
+
if (!existsSync32(dir)) continue;
|
|
16898
17140
|
for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
|
|
16899
|
-
const agentsDir =
|
|
16900
|
-
if (!
|
|
16901
|
-
const agentFile =
|
|
16902
|
-
if (
|
|
17141
|
+
const agentsDir = join32(dir, searchPath);
|
|
17142
|
+
if (!existsSync32(agentsDir)) continue;
|
|
17143
|
+
const agentFile = join32(agentsDir, `${name}.md`);
|
|
17144
|
+
if (existsSync32(agentFile)) {
|
|
16903
17145
|
return parseAgentFile(agentFile, "project");
|
|
16904
17146
|
}
|
|
16905
|
-
const agentDir =
|
|
16906
|
-
if (
|
|
17147
|
+
const agentDir = join32(agentsDir, name);
|
|
17148
|
+
if (existsSync32(agentDir) && statSync8(agentDir).isDirectory()) {
|
|
16907
17149
|
return parseAgentDir(agentDir, "project");
|
|
16908
17150
|
}
|
|
16909
17151
|
}
|
|
16910
17152
|
}
|
|
16911
|
-
const home =
|
|
17153
|
+
const home = homedir10();
|
|
16912
17154
|
const globalPaths = [
|
|
16913
|
-
|
|
16914
|
-
|
|
17155
|
+
join32(home, ".claude", "agents"),
|
|
17156
|
+
join32(home, ".skillkit", "agents")
|
|
16915
17157
|
];
|
|
16916
17158
|
for (const agentsDir of globalPaths) {
|
|
16917
|
-
if (!
|
|
16918
|
-
const agentFile =
|
|
16919
|
-
if (
|
|
17159
|
+
if (!existsSync32(agentsDir)) continue;
|
|
17160
|
+
const agentFile = join32(agentsDir, `${name}.md`);
|
|
17161
|
+
if (existsSync32(agentFile)) {
|
|
16920
17162
|
return parseAgentFile(agentFile, "global");
|
|
16921
17163
|
}
|
|
16922
|
-
const agentDir =
|
|
16923
|
-
if (
|
|
17164
|
+
const agentDir = join32(agentsDir, name);
|
|
17165
|
+
if (existsSync32(agentDir) && statSync8(agentDir).isDirectory()) {
|
|
16924
17166
|
return parseAgentDir(agentDir, "global");
|
|
16925
17167
|
}
|
|
16926
17168
|
}
|
|
@@ -16929,9 +17171,9 @@ function findAgent(name, searchDirs) {
|
|
|
16929
17171
|
function getAgentsDirectory(rootDir, agentType) {
|
|
16930
17172
|
const paths = AGENT_DISCOVERY_PATHS[agentType];
|
|
16931
17173
|
if (paths && paths.length > 0) {
|
|
16932
|
-
return
|
|
17174
|
+
return join32(rootDir, paths[0]);
|
|
16933
17175
|
}
|
|
16934
|
-
return
|
|
17176
|
+
return join32(rootDir, "agents");
|
|
16935
17177
|
}
|
|
16936
17178
|
function agentExists(name, searchDirs) {
|
|
16937
17179
|
return findAgent(name, searchDirs) !== null;
|
|
@@ -16949,14 +17191,14 @@ function getAgentStats(searchDirs) {
|
|
|
16949
17191
|
function discoverAgentsRecursive(rootDir, location = "project") {
|
|
16950
17192
|
const agents = [];
|
|
16951
17193
|
const seen = /* @__PURE__ */ new Set();
|
|
16952
|
-
if (!
|
|
17194
|
+
if (!existsSync32(rootDir)) {
|
|
16953
17195
|
return agents;
|
|
16954
17196
|
}
|
|
16955
17197
|
function scanDirectory(dir) {
|
|
16956
17198
|
try {
|
|
16957
|
-
const entries =
|
|
17199
|
+
const entries = readdirSync10(dir, { withFileTypes: true });
|
|
16958
17200
|
for (const entry of entries) {
|
|
16959
|
-
const entryPath =
|
|
17201
|
+
const entryPath = join32(dir, entry.name);
|
|
16960
17202
|
if (entry.isFile() && extname3(entry.name) === ".md") {
|
|
16961
17203
|
const agent = parseAgentFile(entryPath, location);
|
|
16962
17204
|
if (agent && !seen.has(agent.name)) {
|
|
@@ -16983,7 +17225,7 @@ function discoverAgentsRecursive(rootDir, location = "project") {
|
|
|
16983
17225
|
return agents;
|
|
16984
17226
|
}
|
|
16985
17227
|
function discoverAgentsFromPath(sourcePath, recursive = false, location = "project") {
|
|
16986
|
-
if (!
|
|
17228
|
+
if (!existsSync32(sourcePath)) {
|
|
16987
17229
|
return [];
|
|
16988
17230
|
}
|
|
16989
17231
|
const stats = statSync8(sourcePath);
|
|
@@ -17004,9 +17246,9 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
|
|
|
17004
17246
|
}
|
|
17005
17247
|
const agents = [];
|
|
17006
17248
|
try {
|
|
17007
|
-
const entries =
|
|
17249
|
+
const entries = readdirSync10(sourcePath, { withFileTypes: true });
|
|
17008
17250
|
for (const entry of entries) {
|
|
17009
|
-
const entryPath =
|
|
17251
|
+
const entryPath = join32(sourcePath, entry.name);
|
|
17010
17252
|
if (entry.isFile() && extname3(entry.name) === ".md") {
|
|
17011
17253
|
const a = parseAgentFile(entryPath, location);
|
|
17012
17254
|
if (a) agents.push(a);
|
|
@@ -17023,7 +17265,7 @@ function discoverAgentsFromPath(sourcePath, recursive = false, location = "proje
|
|
|
17023
17265
|
}
|
|
17024
17266
|
|
|
17025
17267
|
// src/agents/translator.ts
|
|
17026
|
-
import { join as
|
|
17268
|
+
import { join as join33 } from "path";
|
|
17027
17269
|
function translateAgent(agent, targetAgent, options) {
|
|
17028
17270
|
const canonical = toCanonicalAgent(agent);
|
|
17029
17271
|
return translateCanonicalAgent(canonical, targetAgent, options);
|
|
@@ -17244,9 +17486,9 @@ function getAgentFilename(agentName, targetAgent) {
|
|
|
17244
17486
|
function getAgentTargetDirectory(rootDir, targetAgent) {
|
|
17245
17487
|
const paths = AGENT_DISCOVERY_PATHS[targetAgent];
|
|
17246
17488
|
if (paths && paths.length > 0) {
|
|
17247
|
-
return
|
|
17489
|
+
return join33(rootDir, paths[0]);
|
|
17248
17490
|
}
|
|
17249
|
-
return
|
|
17491
|
+
return join33(rootDir, "agents");
|
|
17250
17492
|
}
|
|
17251
17493
|
function escapeYamlString(str) {
|
|
17252
17494
|
if (/[:\{\}\[\],&*#?|\-<>=!%@`]/.test(str) || str.includes("\n")) {
|
|
@@ -17281,8 +17523,8 @@ function isAgentCompatible(sourceFormat, targetFormat) {
|
|
|
17281
17523
|
}
|
|
17282
17524
|
|
|
17283
17525
|
// src/skill-translator.ts
|
|
17284
|
-
import { readFileSync as
|
|
17285
|
-
import { join as
|
|
17526
|
+
import { readFileSync as readFileSync25, existsSync as existsSync33, writeFileSync as writeFileSync18, mkdirSync as mkdirSync19 } from "fs";
|
|
17527
|
+
import { join as join34, basename as basename11, dirname as dirname11, resolve as resolve3, relative as relative3, isAbsolute as isAbsolute2 } from "path";
|
|
17286
17528
|
import { parse as parseYaml11, stringify as stringifyYaml8 } from "yaml";
|
|
17287
17529
|
var AGENT_SKILL_FORMATS = Object.fromEntries(
|
|
17288
17530
|
Object.entries(AGENT_CONFIG).map(([agent, config]) => [
|
|
@@ -17291,12 +17533,12 @@ var AGENT_SKILL_FORMATS = Object.fromEntries(
|
|
|
17291
17533
|
])
|
|
17292
17534
|
);
|
|
17293
17535
|
function parseSkillToCanonical(skillPath, sourceAgent) {
|
|
17294
|
-
const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath :
|
|
17295
|
-
if (!
|
|
17536
|
+
const skillMdPath = skillPath.endsWith("SKILL.md") ? skillPath : join34(skillPath, "SKILL.md");
|
|
17537
|
+
if (!existsSync33(skillMdPath)) {
|
|
17296
17538
|
return null;
|
|
17297
17539
|
}
|
|
17298
17540
|
try {
|
|
17299
|
-
const content =
|
|
17541
|
+
const content = readFileSync25(skillMdPath, "utf-8");
|
|
17300
17542
|
return parseSkillContentToCanonical(content, skillPath, sourceAgent);
|
|
17301
17543
|
} catch {
|
|
17302
17544
|
return null;
|
|
@@ -17384,7 +17626,7 @@ function translateSkillToAgent(canonical, targetAgent, options) {
|
|
|
17384
17626
|
}
|
|
17385
17627
|
const content = generateSkillContent(canonical, targetAgent, format, options);
|
|
17386
17628
|
const filename = options?.outputFilename || "SKILL.md";
|
|
17387
|
-
const targetDir = options?.outputDir ||
|
|
17629
|
+
const targetDir = options?.outputDir || join34(format.skillsDir, canonical.name);
|
|
17388
17630
|
return {
|
|
17389
17631
|
success: true,
|
|
17390
17632
|
content,
|
|
@@ -17532,7 +17774,7 @@ function writeTranslatedSkill(result, rootDir, options) {
|
|
|
17532
17774
|
error: "Resolved output path escapes rootDir"
|
|
17533
17775
|
};
|
|
17534
17776
|
}
|
|
17535
|
-
if (
|
|
17777
|
+
if (existsSync33(filePath) && options?.overwrite === false) {
|
|
17536
17778
|
return {
|
|
17537
17779
|
success: false,
|
|
17538
17780
|
path: filePath,
|
|
@@ -17540,10 +17782,10 @@ function writeTranslatedSkill(result, rootDir, options) {
|
|
|
17540
17782
|
skipped: true
|
|
17541
17783
|
};
|
|
17542
17784
|
}
|
|
17543
|
-
if (!
|
|
17544
|
-
|
|
17785
|
+
if (!existsSync33(targetPath)) {
|
|
17786
|
+
mkdirSync19(targetPath, { recursive: true });
|
|
17545
17787
|
}
|
|
17546
|
-
|
|
17788
|
+
writeFileSync18(filePath, result.content, "utf-8");
|
|
17547
17789
|
return { success: true, path: filePath };
|
|
17548
17790
|
} catch (error) {
|
|
17549
17791
|
return {
|
|
@@ -17726,16 +17968,16 @@ var getAgentSkillsDir = getSkillsDir;
|
|
|
17726
17968
|
var getAgentConfigFile = getConfigFile;
|
|
17727
17969
|
|
|
17728
17970
|
// src/manifest/index.ts
|
|
17729
|
-
import { readFileSync as
|
|
17730
|
-
import { join as
|
|
17971
|
+
import { readFileSync as readFileSync26, writeFileSync as writeFileSync19, existsSync as existsSync34 } from "fs";
|
|
17972
|
+
import { join as join35, dirname as dirname12 } from "path";
|
|
17731
17973
|
import { parse as parseYaml12, stringify as stringifyYaml9 } from "yaml";
|
|
17732
17974
|
var MANIFEST_FILENAMES = [".skills", ".skills.yaml", ".skills.yml", "skills.yaml"];
|
|
17733
17975
|
function findManifestPath(startDir = process.cwd()) {
|
|
17734
17976
|
let dir = startDir;
|
|
17735
17977
|
while (dir !== dirname12(dir)) {
|
|
17736
17978
|
for (const filename of MANIFEST_FILENAMES) {
|
|
17737
|
-
const manifestPath =
|
|
17738
|
-
if (
|
|
17979
|
+
const manifestPath = join35(dir, filename);
|
|
17980
|
+
if (existsSync34(manifestPath)) {
|
|
17739
17981
|
return manifestPath;
|
|
17740
17982
|
}
|
|
17741
17983
|
}
|
|
@@ -17745,11 +17987,11 @@ function findManifestPath(startDir = process.cwd()) {
|
|
|
17745
17987
|
}
|
|
17746
17988
|
function loadManifest(manifestPath) {
|
|
17747
17989
|
const path2 = manifestPath || findManifestPath();
|
|
17748
|
-
if (!path2 || !
|
|
17990
|
+
if (!path2 || !existsSync34(path2)) {
|
|
17749
17991
|
return null;
|
|
17750
17992
|
}
|
|
17751
17993
|
try {
|
|
17752
|
-
const content =
|
|
17994
|
+
const content = readFileSync26(path2, "utf-8");
|
|
17753
17995
|
const parsed = parseYaml12(content);
|
|
17754
17996
|
if (!parsed || typeof parsed !== "object") {
|
|
17755
17997
|
return null;
|
|
@@ -17791,7 +18033,7 @@ function normalizeSkills(skills) {
|
|
|
17791
18033
|
}).filter((s) => s.source);
|
|
17792
18034
|
}
|
|
17793
18035
|
function saveManifest(manifest, manifestPath) {
|
|
17794
|
-
const path2 = manifestPath ||
|
|
18036
|
+
const path2 = manifestPath || join35(process.cwd(), ".skills");
|
|
17795
18037
|
const content = stringifyYaml9({
|
|
17796
18038
|
version: manifest.version || 1,
|
|
17797
18039
|
skills: manifest.skills.map((s) => {
|
|
@@ -17804,7 +18046,7 @@ function saveManifest(manifest, manifestPath) {
|
|
|
17804
18046
|
...manifest.installMethod && { installMethod: manifest.installMethod },
|
|
17805
18047
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
17806
18048
|
});
|
|
17807
|
-
|
|
18049
|
+
writeFileSync19(path2, content, "utf-8");
|
|
17808
18050
|
}
|
|
17809
18051
|
function addToManifest(source, options, manifestPath) {
|
|
17810
18052
|
const existing = loadManifest(manifestPath) || {
|
|
@@ -17881,8 +18123,8 @@ function generateManifestFromInstalled(installedSkills) {
|
|
|
17881
18123
|
}
|
|
17882
18124
|
|
|
17883
18125
|
// src/quality/index.ts
|
|
17884
|
-
import { readFileSync as
|
|
17885
|
-
import { join as
|
|
18126
|
+
import { readFileSync as readFileSync27, existsSync as existsSync35 } from "fs";
|
|
18127
|
+
import { join as join36, basename as basename12 } from "path";
|
|
17886
18128
|
|
|
17887
18129
|
// src/quality/benchmark.ts
|
|
17888
18130
|
var CATEGORY_BENCHMARKS = {
|
|
@@ -18484,23 +18726,23 @@ function evaluateSkillContent(content) {
|
|
|
18484
18726
|
};
|
|
18485
18727
|
}
|
|
18486
18728
|
function evaluateSkillFile(filePath) {
|
|
18487
|
-
if (!
|
|
18729
|
+
if (!existsSync35(filePath)) return null;
|
|
18488
18730
|
try {
|
|
18489
|
-
const content =
|
|
18731
|
+
const content = readFileSync27(filePath, "utf-8");
|
|
18490
18732
|
return evaluateSkillContent(content);
|
|
18491
18733
|
} catch {
|
|
18492
18734
|
return null;
|
|
18493
18735
|
}
|
|
18494
18736
|
}
|
|
18495
18737
|
function evaluateSkillDirectory(dirPath) {
|
|
18496
|
-
const skillMdPath =
|
|
18497
|
-
if (
|
|
18738
|
+
const skillMdPath = join36(dirPath, "SKILL.md");
|
|
18739
|
+
if (existsSync35(skillMdPath)) {
|
|
18498
18740
|
return evaluateSkillFile(skillMdPath);
|
|
18499
18741
|
}
|
|
18500
18742
|
const mdcFiles = ["index.mdc", `${basename12(dirPath)}.mdc`];
|
|
18501
18743
|
for (const file of mdcFiles) {
|
|
18502
|
-
const mdcPath =
|
|
18503
|
-
if (
|
|
18744
|
+
const mdcPath = join36(dirPath, file);
|
|
18745
|
+
if (existsSync35(mdcPath)) {
|
|
18504
18746
|
return evaluateSkillFile(mdcPath);
|
|
18505
18747
|
}
|
|
18506
18748
|
}
|
|
@@ -18670,8 +18912,8 @@ var AGENT_INSTRUCTION_TEMPLATES = {
|
|
|
18670
18912
|
};
|
|
18671
18913
|
|
|
18672
18914
|
// src/primer/analyzer.ts
|
|
18673
|
-
import { existsSync as
|
|
18674
|
-
import { join as
|
|
18915
|
+
import { existsSync as existsSync36, readFileSync as readFileSync28, readdirSync as readdirSync11 } from "fs";
|
|
18916
|
+
import { join as join37, basename as basename13, relative as relative4, sep as sep2 } from "path";
|
|
18675
18917
|
var PACKAGE_MANAGER_FILES = {
|
|
18676
18918
|
"package-lock.json": "npm",
|
|
18677
18919
|
"pnpm-lock.yaml": "pnpm",
|
|
@@ -18759,10 +19001,10 @@ var PrimerAnalyzer = class {
|
|
|
18759
19001
|
return analysis;
|
|
18760
19002
|
}
|
|
18761
19003
|
loadPackageJson() {
|
|
18762
|
-
const packageJsonPath =
|
|
18763
|
-
if (
|
|
19004
|
+
const packageJsonPath = join37(this.projectPath, "package.json");
|
|
19005
|
+
if (existsSync36(packageJsonPath)) {
|
|
18764
19006
|
try {
|
|
18765
|
-
const content =
|
|
19007
|
+
const content = readFileSync28(packageJsonPath, "utf-8");
|
|
18766
19008
|
this.packageJson = JSON.parse(content);
|
|
18767
19009
|
} catch {
|
|
18768
19010
|
this.packageJson = null;
|
|
@@ -18773,9 +19015,9 @@ var PrimerAnalyzer = class {
|
|
|
18773
19015
|
const scan = (dir, depth) => {
|
|
18774
19016
|
if (depth > maxDepth) return;
|
|
18775
19017
|
try {
|
|
18776
|
-
const entries =
|
|
19018
|
+
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
18777
19019
|
for (const entry of entries) {
|
|
18778
|
-
const fullPath =
|
|
19020
|
+
const fullPath = join37(dir, entry.name);
|
|
18779
19021
|
const relativePath = relative4(this.projectPath, fullPath);
|
|
18780
19022
|
if (entry.name.startsWith(".") && entry.name !== ".github" && entry.name !== ".env.example") {
|
|
18781
19023
|
if (!entry.isDirectory()) {
|
|
@@ -18820,10 +19062,10 @@ var PrimerAnalyzer = class {
|
|
|
18820
19062
|
info.repository = String(repo.url);
|
|
18821
19063
|
}
|
|
18822
19064
|
}
|
|
18823
|
-
const pyprojectPath =
|
|
18824
|
-
if (!this.packageJson &&
|
|
19065
|
+
const pyprojectPath = join37(this.projectPath, "pyproject.toml");
|
|
19066
|
+
if (!this.packageJson && existsSync36(pyprojectPath)) {
|
|
18825
19067
|
try {
|
|
18826
|
-
const content =
|
|
19068
|
+
const content = readFileSync28(pyprojectPath, "utf-8");
|
|
18827
19069
|
const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
|
|
18828
19070
|
const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
|
|
18829
19071
|
const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
|
|
@@ -18833,10 +19075,10 @@ var PrimerAnalyzer = class {
|
|
|
18833
19075
|
} catch {
|
|
18834
19076
|
}
|
|
18835
19077
|
}
|
|
18836
|
-
const cargoPath =
|
|
18837
|
-
if (!this.packageJson &&
|
|
19078
|
+
const cargoPath = join37(this.projectPath, "Cargo.toml");
|
|
19079
|
+
if (!this.packageJson && existsSync36(cargoPath)) {
|
|
18838
19080
|
try {
|
|
18839
|
-
const content =
|
|
19081
|
+
const content = readFileSync28(cargoPath, "utf-8");
|
|
18840
19082
|
const nameMatch = content.match(/name\s*=\s*["']([^"']+)["']/);
|
|
18841
19083
|
const versionMatch = content.match(/version\s*=\s*["']([^"']+)["']/);
|
|
18842
19084
|
const descMatch = content.match(/description\s*=\s*["']([^"']+)["']/);
|
|
@@ -19016,8 +19258,8 @@ var PrimerAnalyzer = class {
|
|
|
19016
19258
|
}
|
|
19017
19259
|
if (this.hasFile("tsconfig.json")) {
|
|
19018
19260
|
try {
|
|
19019
|
-
const tsconfigPath =
|
|
19020
|
-
const content =
|
|
19261
|
+
const tsconfigPath = join37(this.projectPath, "tsconfig.json");
|
|
19262
|
+
const content = readFileSync28(tsconfigPath, "utf-8");
|
|
19021
19263
|
const tsconfig = JSON.parse(content.replace(/\/\/.*$/gm, "").replace(/,\s*}/g, "}"));
|
|
19022
19264
|
const paths = tsconfig.compilerOptions?.paths;
|
|
19023
19265
|
if (paths && Object.keys(paths).some((k) => k.startsWith("@"))) {
|
|
@@ -19046,8 +19288,8 @@ var PrimerAnalyzer = class {
|
|
|
19046
19288
|
ci.provider = "github-actions";
|
|
19047
19289
|
ci.configFile = ".github/workflows";
|
|
19048
19290
|
try {
|
|
19049
|
-
const workflowsDir =
|
|
19050
|
-
const workflows =
|
|
19291
|
+
const workflowsDir = join37(this.projectPath, ".github/workflows");
|
|
19292
|
+
const workflows = readdirSync11(workflowsDir);
|
|
19051
19293
|
const deployWorkflows = workflows.filter(
|
|
19052
19294
|
(f) => f.includes("deploy") || f.includes("release") || f.includes("publish")
|
|
19053
19295
|
);
|
|
@@ -19067,12 +19309,12 @@ var PrimerAnalyzer = class {
|
|
|
19067
19309
|
env.hasEnvFile = this.hasFile(".env");
|
|
19068
19310
|
env.hasEnvExample = this.hasFile(".env.example") || this.hasFile(".env.template") || this.hasFile(".env.sample");
|
|
19069
19311
|
if (env.hasEnvExample) {
|
|
19070
|
-
const envExamplePath =
|
|
19312
|
+
const envExamplePath = join37(
|
|
19071
19313
|
this.projectPath,
|
|
19072
19314
|
this.hasFile(".env.example") ? ".env.example" : this.hasFile(".env.template") ? ".env.template" : ".env.sample"
|
|
19073
19315
|
);
|
|
19074
19316
|
try {
|
|
19075
|
-
const content =
|
|
19317
|
+
const content = readFileSync28(envExamplePath, "utf-8");
|
|
19076
19318
|
const variables = content.split("\n").filter((line) => line.trim() && !line.startsWith("#")).map((line) => line.split("=")[0].trim()).filter((v) => v);
|
|
19077
19319
|
env.envVariables = variables;
|
|
19078
19320
|
} catch {
|
|
@@ -19089,8 +19331,8 @@ var PrimerAnalyzer = class {
|
|
|
19089
19331
|
docker.hasCompose = this.hasFile("docker-compose.yml") || this.hasFile("docker-compose.yaml") || this.hasFile("compose.yml");
|
|
19090
19332
|
if (docker.hasDockerfile) {
|
|
19091
19333
|
try {
|
|
19092
|
-
const dockerfilePath =
|
|
19093
|
-
const content =
|
|
19334
|
+
const dockerfilePath = join37(this.projectPath, "Dockerfile");
|
|
19335
|
+
const content = readFileSync28(dockerfilePath, "utf-8");
|
|
19094
19336
|
const fromMatch = content.match(/^FROM\s+(\S+)/m);
|
|
19095
19337
|
if (fromMatch) {
|
|
19096
19338
|
docker.baseImage = fromMatch[1];
|
|
@@ -19179,7 +19421,7 @@ var PrimerAnalyzer = class {
|
|
|
19179
19421
|
}
|
|
19180
19422
|
return false;
|
|
19181
19423
|
}
|
|
19182
|
-
return this.files.has(name) ||
|
|
19424
|
+
return this.files.has(name) || existsSync36(join37(this.projectPath, name));
|
|
19183
19425
|
}
|
|
19184
19426
|
getDepVersion(dep) {
|
|
19185
19427
|
if (!this.packageJson) return void 0;
|
|
@@ -19201,10 +19443,10 @@ var PrimerAnalyzer = class {
|
|
|
19201
19443
|
}
|
|
19202
19444
|
readConfigFile(files) {
|
|
19203
19445
|
for (const file of files) {
|
|
19204
|
-
const filePath =
|
|
19205
|
-
if (
|
|
19446
|
+
const filePath = join37(this.projectPath, file);
|
|
19447
|
+
if (existsSync36(filePath)) {
|
|
19206
19448
|
try {
|
|
19207
|
-
const content =
|
|
19449
|
+
const content = readFileSync28(filePath, "utf-8");
|
|
19208
19450
|
if (file.endsWith(".json")) {
|
|
19209
19451
|
return JSON.parse(content);
|
|
19210
19452
|
}
|
|
@@ -19222,8 +19464,8 @@ function analyzePrimer(projectPath) {
|
|
|
19222
19464
|
}
|
|
19223
19465
|
|
|
19224
19466
|
// src/primer/generator.ts
|
|
19225
|
-
import { existsSync as
|
|
19226
|
-
import { join as
|
|
19467
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync20, writeFileSync as writeFileSync20 } from "fs";
|
|
19468
|
+
import { join as join38, dirname as dirname13 } from "path";
|
|
19227
19469
|
var ALL_AGENTS = Object.keys(AGENT_CONFIG);
|
|
19228
19470
|
var markdownRenderer = {
|
|
19229
19471
|
h1: (text) => `# ${text}`,
|
|
@@ -19255,9 +19497,9 @@ ${code}
|
|
|
19255
19497
|
separator: () => "",
|
|
19256
19498
|
wrap: (content, metadata) => {
|
|
19257
19499
|
if (metadata && Object.keys(metadata).length > 0) {
|
|
19258
|
-
const
|
|
19500
|
+
const yaml4 = Object.entries(metadata).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join("\n");
|
|
19259
19501
|
return `---
|
|
19260
|
-
${
|
|
19502
|
+
${yaml4}
|
|
19261
19503
|
---
|
|
19262
19504
|
|
|
19263
19505
|
${content}`;
|
|
@@ -19387,14 +19629,14 @@ var PrimerGenerator = class {
|
|
|
19387
19629
|
detectInstalledAgents() {
|
|
19388
19630
|
const detected = [];
|
|
19389
19631
|
for (const [agent, config] of Object.entries(AGENT_CONFIG)) {
|
|
19390
|
-
const configPath =
|
|
19391
|
-
const skillsPath =
|
|
19392
|
-
if (
|
|
19632
|
+
const configPath = join38(this.projectPath, config.configFile);
|
|
19633
|
+
const skillsPath = join38(this.projectPath, config.skillsDir);
|
|
19634
|
+
if (existsSync37(configPath) || existsSync37(skillsPath)) {
|
|
19393
19635
|
detected.push(agent);
|
|
19394
19636
|
}
|
|
19395
19637
|
if (config.altSkillsDirs) {
|
|
19396
19638
|
for (const altDir of config.altSkillsDirs) {
|
|
19397
|
-
if (
|
|
19639
|
+
if (existsSync37(join38(this.projectPath, altDir))) {
|
|
19398
19640
|
if (!detected.includes(agent)) {
|
|
19399
19641
|
detected.push(agent);
|
|
19400
19642
|
}
|
|
@@ -19414,7 +19656,7 @@ var PrimerGenerator = class {
|
|
|
19414
19656
|
const template = AGENT_INSTRUCTION_TEMPLATES[agent] || this.getDefaultTemplate(agent, config);
|
|
19415
19657
|
const content = this.generateContent(template);
|
|
19416
19658
|
const outputDir = this.options.outputDir || this.projectPath;
|
|
19417
|
-
const filepath =
|
|
19659
|
+
const filepath = join38(outputDir, template.filename);
|
|
19418
19660
|
return {
|
|
19419
19661
|
agent,
|
|
19420
19662
|
filename: template.filename,
|
|
@@ -19787,10 +20029,10 @@ var PrimerGenerator = class {
|
|
|
19787
20029
|
}
|
|
19788
20030
|
writeInstruction(instruction) {
|
|
19789
20031
|
const dir = dirname13(instruction.filepath);
|
|
19790
|
-
if (!
|
|
19791
|
-
|
|
20032
|
+
if (!existsSync37(dir)) {
|
|
20033
|
+
mkdirSync20(dir, { recursive: true });
|
|
19792
20034
|
}
|
|
19793
|
-
|
|
20035
|
+
writeFileSync20(instruction.filepath, instruction.content, "utf-8");
|
|
19794
20036
|
}
|
|
19795
20037
|
formatProjectType(type) {
|
|
19796
20038
|
const typeMap = {
|
|
@@ -19820,6 +20062,1408 @@ function analyzeForPrimer(projectPath) {
|
|
|
19820
20062
|
const result = generator.generate();
|
|
19821
20063
|
return result.analysis;
|
|
19822
20064
|
}
|
|
20065
|
+
|
|
20066
|
+
// src/learning/types.ts
|
|
20067
|
+
var DEFAULT_LEARNING_CONFIG = {
|
|
20068
|
+
minSessionLength: 10,
|
|
20069
|
+
sensitivity: "medium",
|
|
20070
|
+
autoApprove: false,
|
|
20071
|
+
outputPath: "~/.skillkit/learned/",
|
|
20072
|
+
categories: ["error_fix", "refactor", "workaround", "debugging", "convention"],
|
|
20073
|
+
ignorePatterns: ["trivial_typo", "one_off_fix", "wip", "merge"]
|
|
20074
|
+
};
|
|
20075
|
+
|
|
20076
|
+
// src/learning/config.ts
|
|
20077
|
+
import { existsSync as existsSync38, readFileSync as readFileSync29, writeFileSync as writeFileSync21, mkdirSync as mkdirSync21 } from "fs";
|
|
20078
|
+
import { join as join39, dirname as dirname14 } from "path";
|
|
20079
|
+
import { homedir as homedir11 } from "os";
|
|
20080
|
+
import yaml from "yaml";
|
|
20081
|
+
function getDefaultConfigPath() {
|
|
20082
|
+
return join39(homedir11(), ".skillkit", "learning.yaml");
|
|
20083
|
+
}
|
|
20084
|
+
function getDefaultStorePath() {
|
|
20085
|
+
return join39(homedir11(), ".skillkit", "learned", "patterns.json");
|
|
20086
|
+
}
|
|
20087
|
+
function loadLearningConfig(configPath) {
|
|
20088
|
+
const path2 = configPath || getDefaultConfigPath();
|
|
20089
|
+
if (!existsSync38(path2)) {
|
|
20090
|
+
return DEFAULT_LEARNING_CONFIG;
|
|
20091
|
+
}
|
|
20092
|
+
try {
|
|
20093
|
+
const content = readFileSync29(path2, "utf-8");
|
|
20094
|
+
const config = yaml.parse(content);
|
|
20095
|
+
return { ...DEFAULT_LEARNING_CONFIG, ...config };
|
|
20096
|
+
} catch {
|
|
20097
|
+
return DEFAULT_LEARNING_CONFIG;
|
|
20098
|
+
}
|
|
20099
|
+
}
|
|
20100
|
+
function saveLearningConfig(config, configPath) {
|
|
20101
|
+
const path2 = configPath || getDefaultConfigPath();
|
|
20102
|
+
const dir = dirname14(path2);
|
|
20103
|
+
if (!existsSync38(dir)) {
|
|
20104
|
+
mkdirSync21(dir, { recursive: true });
|
|
20105
|
+
}
|
|
20106
|
+
const content = yaml.stringify(config);
|
|
20107
|
+
writeFileSync21(path2, content);
|
|
20108
|
+
}
|
|
20109
|
+
function loadPatternStore(storePath) {
|
|
20110
|
+
const path2 = storePath || getDefaultStorePath();
|
|
20111
|
+
if (!existsSync38(path2)) {
|
|
20112
|
+
return {
|
|
20113
|
+
version: 1,
|
|
20114
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20115
|
+
patterns: [],
|
|
20116
|
+
evolvingPatterns: []
|
|
20117
|
+
};
|
|
20118
|
+
}
|
|
20119
|
+
try {
|
|
20120
|
+
const content = readFileSync29(path2, "utf-8");
|
|
20121
|
+
return JSON.parse(content);
|
|
20122
|
+
} catch {
|
|
20123
|
+
return {
|
|
20124
|
+
version: 1,
|
|
20125
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20126
|
+
patterns: [],
|
|
20127
|
+
evolvingPatterns: []
|
|
20128
|
+
};
|
|
20129
|
+
}
|
|
20130
|
+
}
|
|
20131
|
+
function savePatternStore(store, storePath) {
|
|
20132
|
+
const path2 = storePath || getDefaultStorePath();
|
|
20133
|
+
const dir = dirname14(path2);
|
|
20134
|
+
if (!existsSync38(dir)) {
|
|
20135
|
+
mkdirSync21(dir, { recursive: true });
|
|
20136
|
+
}
|
|
20137
|
+
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20138
|
+
const content = JSON.stringify(store, null, 2);
|
|
20139
|
+
writeFileSync21(path2, content);
|
|
20140
|
+
}
|
|
20141
|
+
function addPattern(pattern, storePath) {
|
|
20142
|
+
const store = loadPatternStore(storePath);
|
|
20143
|
+
const existingIndex = store.patterns.findIndex((p) => p.id === pattern.id);
|
|
20144
|
+
if (existingIndex >= 0) {
|
|
20145
|
+
store.patterns[existingIndex] = pattern;
|
|
20146
|
+
} else {
|
|
20147
|
+
store.patterns.push(pattern);
|
|
20148
|
+
}
|
|
20149
|
+
savePatternStore(store, storePath);
|
|
20150
|
+
return store;
|
|
20151
|
+
}
|
|
20152
|
+
function removePattern(patternId, storePath) {
|
|
20153
|
+
const store = loadPatternStore(storePath);
|
|
20154
|
+
store.patterns = store.patterns.filter((p) => p.id !== patternId);
|
|
20155
|
+
store.evolvingPatterns = store.evolvingPatterns.filter((p) => p.id !== patternId);
|
|
20156
|
+
savePatternStore(store, storePath);
|
|
20157
|
+
return store;
|
|
20158
|
+
}
|
|
20159
|
+
function getPattern(patternId, storePath) {
|
|
20160
|
+
const store = loadPatternStore(storePath);
|
|
20161
|
+
return store.patterns.find((p) => p.id === patternId) || null;
|
|
20162
|
+
}
|
|
20163
|
+
function getEvolvingPattern(patternId, storePath) {
|
|
20164
|
+
const store = loadPatternStore(storePath);
|
|
20165
|
+
return store.evolvingPatterns.find((p) => p.id === patternId) || null;
|
|
20166
|
+
}
|
|
20167
|
+
function getAllPatterns(storePath) {
|
|
20168
|
+
const store = loadPatternStore(storePath);
|
|
20169
|
+
return store.patterns;
|
|
20170
|
+
}
|
|
20171
|
+
function getPatternsByCategory(category, storePath) {
|
|
20172
|
+
const store = loadPatternStore(storePath);
|
|
20173
|
+
return store.patterns.filter((p) => p.category === category);
|
|
20174
|
+
}
|
|
20175
|
+
function getApprovedPatterns(storePath) {
|
|
20176
|
+
const store = loadPatternStore(storePath);
|
|
20177
|
+
return store.patterns.filter((p) => p.approved);
|
|
20178
|
+
}
|
|
20179
|
+
|
|
20180
|
+
// src/learning/git-analyzer.ts
|
|
20181
|
+
import { execSync as execSync7 } from "child_process";
|
|
20182
|
+
import { existsSync as existsSync39 } from "fs";
|
|
20183
|
+
import { join as join40 } from "path";
|
|
20184
|
+
function runGitCommand(command, cwd) {
|
|
20185
|
+
try {
|
|
20186
|
+
return execSync7(command, { cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
|
|
20187
|
+
} catch {
|
|
20188
|
+
return "";
|
|
20189
|
+
}
|
|
20190
|
+
}
|
|
20191
|
+
function isGitRepository(path2) {
|
|
20192
|
+
return existsSync39(join40(path2, ".git"));
|
|
20193
|
+
}
|
|
20194
|
+
function getGitCommits(repoPath, options = {}) {
|
|
20195
|
+
if (!isGitRepository(repoPath)) {
|
|
20196
|
+
return [];
|
|
20197
|
+
}
|
|
20198
|
+
const limit = options.commits || 100;
|
|
20199
|
+
const args = [
|
|
20200
|
+
"log",
|
|
20201
|
+
`--max-count=${limit}`,
|
|
20202
|
+
"--format=%H|||%h|||%an|||%aI|||%s|||%b|||END_COMMIT",
|
|
20203
|
+
"--name-status"
|
|
20204
|
+
];
|
|
20205
|
+
if (options.since) {
|
|
20206
|
+
args.push(`--since="${options.since}"`);
|
|
20207
|
+
}
|
|
20208
|
+
if (options.until) {
|
|
20209
|
+
args.push(`--until="${options.until}"`);
|
|
20210
|
+
}
|
|
20211
|
+
if (options.branch) {
|
|
20212
|
+
args.push(options.branch);
|
|
20213
|
+
}
|
|
20214
|
+
if (options.author) {
|
|
20215
|
+
args.push(`--author="${options.author}"`);
|
|
20216
|
+
}
|
|
20217
|
+
const output = runGitCommand(`git ${args.join(" ")}`, repoPath);
|
|
20218
|
+
if (!output) return [];
|
|
20219
|
+
const commits = [];
|
|
20220
|
+
const commitBlocks = output.split("END_COMMIT").filter((b) => b.trim());
|
|
20221
|
+
for (const block of commitBlocks) {
|
|
20222
|
+
const lines = block.trim().split("\n");
|
|
20223
|
+
if (lines.length === 0) continue;
|
|
20224
|
+
const headerLine = lines[0];
|
|
20225
|
+
const parts = headerLine.split("|||");
|
|
20226
|
+
if (parts.length < 5) continue;
|
|
20227
|
+
const [hash, shortHash, author, date, message, body] = parts;
|
|
20228
|
+
const files = [];
|
|
20229
|
+
for (let i = 1; i < lines.length; i++) {
|
|
20230
|
+
const line = lines[i].trim();
|
|
20231
|
+
if (!line) continue;
|
|
20232
|
+
const match = line.match(/^([AMDRT])\d*\t(.+?)(?:\t(.+))?$/);
|
|
20233
|
+
if (match) {
|
|
20234
|
+
const [, status, path2, oldPath] = match;
|
|
20235
|
+
files.push({
|
|
20236
|
+
path: path2,
|
|
20237
|
+
status: parseFileStatus(status),
|
|
20238
|
+
additions: 0,
|
|
20239
|
+
deletions: 0,
|
|
20240
|
+
oldPath: oldPath || void 0
|
|
20241
|
+
});
|
|
20242
|
+
}
|
|
20243
|
+
}
|
|
20244
|
+
commits.push({
|
|
20245
|
+
hash,
|
|
20246
|
+
shortHash,
|
|
20247
|
+
author,
|
|
20248
|
+
date,
|
|
20249
|
+
message,
|
|
20250
|
+
body: body || void 0,
|
|
20251
|
+
files
|
|
20252
|
+
});
|
|
20253
|
+
}
|
|
20254
|
+
return commits;
|
|
20255
|
+
}
|
|
20256
|
+
function parseFileStatus(status) {
|
|
20257
|
+
switch (status) {
|
|
20258
|
+
case "A":
|
|
20259
|
+
return "added";
|
|
20260
|
+
case "D":
|
|
20261
|
+
return "deleted";
|
|
20262
|
+
case "R":
|
|
20263
|
+
return "renamed";
|
|
20264
|
+
default:
|
|
20265
|
+
return "modified";
|
|
20266
|
+
}
|
|
20267
|
+
}
|
|
20268
|
+
function categorizeCommit(message, body) {
|
|
20269
|
+
const text = `${message} ${body || ""}`.toLowerCase();
|
|
20270
|
+
if (text.includes("fix") || text.includes("bug") || text.includes("error") || text.includes("issue")) {
|
|
20271
|
+
return "error_fix";
|
|
20272
|
+
}
|
|
20273
|
+
if (text.includes("refactor") || text.includes("clean") || text.includes("simplify")) {
|
|
20274
|
+
return "refactor";
|
|
20275
|
+
}
|
|
20276
|
+
if (text.includes("workaround") || text.includes("hack") || text.includes("temporary")) {
|
|
20277
|
+
return "workaround";
|
|
20278
|
+
}
|
|
20279
|
+
if (text.includes("debug") || text.includes("log") || text.includes("trace")) {
|
|
20280
|
+
return "debugging";
|
|
20281
|
+
}
|
|
20282
|
+
return null;
|
|
20283
|
+
}
|
|
20284
|
+
function shouldSkipCommit(commit, ignorePatterns) {
|
|
20285
|
+
const message = commit.message.toLowerCase();
|
|
20286
|
+
for (const pattern of ignorePatterns) {
|
|
20287
|
+
if (message.includes(pattern.toLowerCase())) {
|
|
20288
|
+
return true;
|
|
20289
|
+
}
|
|
20290
|
+
}
|
|
20291
|
+
if (message.startsWith("merge ") || message.startsWith("wip")) {
|
|
20292
|
+
return true;
|
|
20293
|
+
}
|
|
20294
|
+
if (commit.files.length === 0) {
|
|
20295
|
+
return true;
|
|
20296
|
+
}
|
|
20297
|
+
return false;
|
|
20298
|
+
}
|
|
20299
|
+
function extractPatternFromCommit(commit) {
|
|
20300
|
+
const category = categorizeCommit(commit.message, commit.body);
|
|
20301
|
+
if (!category) return null;
|
|
20302
|
+
const id = `git-${commit.shortHash}`;
|
|
20303
|
+
const title = formatTitle(commit.message);
|
|
20304
|
+
const problem = extractProblem(commit);
|
|
20305
|
+
const solution = extractSolution(commit);
|
|
20306
|
+
const context = extractContext(commit);
|
|
20307
|
+
if (!problem || !solution) return null;
|
|
20308
|
+
return {
|
|
20309
|
+
id,
|
|
20310
|
+
category,
|
|
20311
|
+
title,
|
|
20312
|
+
problem,
|
|
20313
|
+
solution,
|
|
20314
|
+
context,
|
|
20315
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20316
|
+
source: "git",
|
|
20317
|
+
commitRange: { from: commit.hash, to: commit.hash },
|
|
20318
|
+
approved: false,
|
|
20319
|
+
confidence: calculateConfidence(commit, category)
|
|
20320
|
+
};
|
|
20321
|
+
}
|
|
20322
|
+
function formatTitle(message) {
|
|
20323
|
+
return message.charAt(0).toUpperCase() + message.slice(1);
|
|
20324
|
+
}
|
|
20325
|
+
function extractProblem(commit) {
|
|
20326
|
+
const message = commit.message.toLowerCase();
|
|
20327
|
+
if (message.includes("fix:") || message.includes("fix(")) {
|
|
20328
|
+
const match = commit.message.match(/fix[:(]\s*([^)]+)/i);
|
|
20329
|
+
if (match) {
|
|
20330
|
+
return `Issue: ${match[1]}`;
|
|
20331
|
+
}
|
|
20332
|
+
}
|
|
20333
|
+
if (commit.body) {
|
|
20334
|
+
const problemMatch = commit.body.match(/problem:?\s*(.+)/i);
|
|
20335
|
+
if (problemMatch) {
|
|
20336
|
+
return problemMatch[1].trim();
|
|
20337
|
+
}
|
|
20338
|
+
}
|
|
20339
|
+
return `${commit.message} (from commit ${commit.shortHash})`;
|
|
20340
|
+
}
|
|
20341
|
+
function extractSolution(commit) {
|
|
20342
|
+
if (commit.body) {
|
|
20343
|
+
const solutionMatch = commit.body.match(/solution:?\s*(.+)/i);
|
|
20344
|
+
if (solutionMatch) {
|
|
20345
|
+
return solutionMatch[1].trim();
|
|
20346
|
+
}
|
|
20347
|
+
}
|
|
20348
|
+
const files = commit.files.map((f) => f.path).join(", ");
|
|
20349
|
+
return `Modified: ${files}`;
|
|
20350
|
+
}
|
|
20351
|
+
function extractContext(commit) {
|
|
20352
|
+
const files = commit.files;
|
|
20353
|
+
const extensions = new Set(files.map((f) => f.path.split(".").pop() || ""));
|
|
20354
|
+
const directories = new Set(files.map((f) => f.path.split("/")[0]));
|
|
20355
|
+
const parts = [];
|
|
20356
|
+
if (extensions.size > 0) {
|
|
20357
|
+
parts.push(`Files: ${Array.from(extensions).filter((e) => e).join(", ")}`);
|
|
20358
|
+
}
|
|
20359
|
+
if (directories.size > 0 && directories.size <= 3) {
|
|
20360
|
+
parts.push(`Areas: ${Array.from(directories).join(", ")}`);
|
|
20361
|
+
}
|
|
20362
|
+
return parts.join(". ") || "General codebase";
|
|
20363
|
+
}
|
|
20364
|
+
function calculateConfidence(commit, category) {
|
|
20365
|
+
let confidence = 0.5;
|
|
20366
|
+
if (commit.body && commit.body.length > 50) {
|
|
20367
|
+
confidence += 0.1;
|
|
20368
|
+
}
|
|
20369
|
+
if (commit.message.match(/^(fix|feat|refactor|docs|test|chore)(\(.+\))?:/)) {
|
|
20370
|
+
confidence += 0.1;
|
|
20371
|
+
}
|
|
20372
|
+
if (commit.files.length > 0 && commit.files.length < 10) {
|
|
20373
|
+
confidence += 0.1;
|
|
20374
|
+
}
|
|
20375
|
+
if (category === "error_fix" || category === "workaround") {
|
|
20376
|
+
confidence += 0.05;
|
|
20377
|
+
}
|
|
20378
|
+
return Math.min(0.9, confidence);
|
|
20379
|
+
}
|
|
20380
|
+
function analyzeGitHistory(repoPath, options = {}) {
|
|
20381
|
+
const commits = getGitCommits(repoPath, options);
|
|
20382
|
+
const ignorePatterns = ["merge", "wip", "typo"];
|
|
20383
|
+
const patterns = [];
|
|
20384
|
+
const summary = {
|
|
20385
|
+
totalCommits: commits.length,
|
|
20386
|
+
totalFilesChanged: 0,
|
|
20387
|
+
errorFixes: 0,
|
|
20388
|
+
refactors: 0,
|
|
20389
|
+
features: 0,
|
|
20390
|
+
documentation: 0,
|
|
20391
|
+
tests: 0
|
|
20392
|
+
};
|
|
20393
|
+
const languages = /* @__PURE__ */ new Set();
|
|
20394
|
+
const frameworks = /* @__PURE__ */ new Set();
|
|
20395
|
+
for (const commit of commits) {
|
|
20396
|
+
if (shouldSkipCommit(commit, ignorePatterns)) {
|
|
20397
|
+
continue;
|
|
20398
|
+
}
|
|
20399
|
+
summary.totalFilesChanged += commit.files.length;
|
|
20400
|
+
for (const file of commit.files) {
|
|
20401
|
+
const ext = file.path.split(".").pop()?.toLowerCase();
|
|
20402
|
+
if (ext) {
|
|
20403
|
+
if (["ts", "tsx"].includes(ext)) languages.add("TypeScript");
|
|
20404
|
+
else if (["js", "jsx"].includes(ext)) languages.add("JavaScript");
|
|
20405
|
+
else if (ext === "py") languages.add("Python");
|
|
20406
|
+
else if (ext === "go") languages.add("Go");
|
|
20407
|
+
else if (ext === "rs") languages.add("Rust");
|
|
20408
|
+
else if (ext === "java") languages.add("Java");
|
|
20409
|
+
}
|
|
20410
|
+
if (file.path.includes("next")) frameworks.add("Next.js");
|
|
20411
|
+
if (file.path.includes("react")) frameworks.add("React");
|
|
20412
|
+
if (file.path.includes("vue")) frameworks.add("Vue");
|
|
20413
|
+
}
|
|
20414
|
+
const category = categorizeCommit(commit.message, commit.body);
|
|
20415
|
+
if (category === "error_fix") summary.errorFixes++;
|
|
20416
|
+
else if (category === "refactor") summary.refactors++;
|
|
20417
|
+
if (commit.message.toLowerCase().includes("feat")) summary.features++;
|
|
20418
|
+
if (commit.message.toLowerCase().includes("doc")) summary.documentation++;
|
|
20419
|
+
if (commit.message.toLowerCase().includes("test")) summary.tests++;
|
|
20420
|
+
const pattern = extractPatternFromCommit(commit);
|
|
20421
|
+
if (pattern) {
|
|
20422
|
+
patterns.push(pattern);
|
|
20423
|
+
}
|
|
20424
|
+
}
|
|
20425
|
+
const dates = commits.map((c) => c.date).sort();
|
|
20426
|
+
return {
|
|
20427
|
+
patterns,
|
|
20428
|
+
commitCount: commits.length,
|
|
20429
|
+
dateRange: {
|
|
20430
|
+
from: dates[0] || "",
|
|
20431
|
+
to: dates[dates.length - 1] || ""
|
|
20432
|
+
},
|
|
20433
|
+
languages: Array.from(languages),
|
|
20434
|
+
frameworks: Array.from(frameworks),
|
|
20435
|
+
summary
|
|
20436
|
+
};
|
|
20437
|
+
}
|
|
20438
|
+
function getRecentBugFixes(repoPath, limit = 20) {
|
|
20439
|
+
const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
|
|
20440
|
+
return result.patterns.filter((p) => p.category === "error_fix").slice(0, limit);
|
|
20441
|
+
}
|
|
20442
|
+
function getRecentRefactors(repoPath, limit = 20) {
|
|
20443
|
+
const result = analyzeGitHistory(repoPath, { commits: limit * 3 });
|
|
20444
|
+
return result.patterns.filter((p) => p.category === "refactor").slice(0, limit);
|
|
20445
|
+
}
|
|
20446
|
+
|
|
20447
|
+
// src/learning/extractor.ts
|
|
20448
|
+
function extractPatternsFromSession(session) {
|
|
20449
|
+
const patterns = [];
|
|
20450
|
+
const skipped = [];
|
|
20451
|
+
const errors = [];
|
|
20452
|
+
if (session.messages.length < 5) {
|
|
20453
|
+
skipped.push({ reason: "Session too short for pattern extraction" });
|
|
20454
|
+
return { patterns, skipped, errors };
|
|
20455
|
+
}
|
|
20456
|
+
try {
|
|
20457
|
+
const errorFixPatterns = findErrorFixPatterns(session);
|
|
20458
|
+
patterns.push(...errorFixPatterns);
|
|
20459
|
+
const workaroundPatterns = findWorkaroundPatterns(session);
|
|
20460
|
+
patterns.push(...workaroundPatterns);
|
|
20461
|
+
const conventionPatterns = findConventionPatterns(session);
|
|
20462
|
+
patterns.push(...conventionPatterns);
|
|
20463
|
+
const debuggingPatterns = findDebuggingPatterns(session);
|
|
20464
|
+
patterns.push(...debuggingPatterns);
|
|
20465
|
+
} catch (error) {
|
|
20466
|
+
errors.push(error instanceof Error ? error.message : "Unknown extraction error");
|
|
20467
|
+
}
|
|
20468
|
+
return { patterns, skipped, errors };
|
|
20469
|
+
}
|
|
20470
|
+
function findErrorFixPatterns(session) {
|
|
20471
|
+
const patterns = [];
|
|
20472
|
+
const messages = session.messages;
|
|
20473
|
+
for (let i = 0; i < messages.length - 1; i++) {
|
|
20474
|
+
const current = messages[i];
|
|
20475
|
+
const next = messages[i + 1];
|
|
20476
|
+
if (isErrorDescription(current.content) && isSolution(next.content)) {
|
|
20477
|
+
const pattern = createPatternFromErrorFix(
|
|
20478
|
+
current.content,
|
|
20479
|
+
next.content,
|
|
20480
|
+
session,
|
|
20481
|
+
i
|
|
20482
|
+
);
|
|
20483
|
+
if (pattern) {
|
|
20484
|
+
patterns.push(pattern);
|
|
20485
|
+
}
|
|
20486
|
+
}
|
|
20487
|
+
}
|
|
20488
|
+
return patterns;
|
|
20489
|
+
}
|
|
20490
|
+
function findWorkaroundPatterns(session) {
|
|
20491
|
+
const patterns = [];
|
|
20492
|
+
const messages = session.messages;
|
|
20493
|
+
const workaroundKeywords = [
|
|
20494
|
+
"workaround",
|
|
20495
|
+
"instead of",
|
|
20496
|
+
"alternative",
|
|
20497
|
+
"hack",
|
|
20498
|
+
"temporary fix",
|
|
20499
|
+
"for now",
|
|
20500
|
+
"until"
|
|
20501
|
+
];
|
|
20502
|
+
for (let i = 0; i < messages.length; i++) {
|
|
20503
|
+
const message = messages[i];
|
|
20504
|
+
if (message.role !== "assistant") continue;
|
|
20505
|
+
const content = message.content.toLowerCase();
|
|
20506
|
+
if (workaroundKeywords.some((kw) => content.includes(kw))) {
|
|
20507
|
+
const problem = findPrecedingProblem(messages, i);
|
|
20508
|
+
if (problem) {
|
|
20509
|
+
const pattern = createPattern(
|
|
20510
|
+
"workaround",
|
|
20511
|
+
problem,
|
|
20512
|
+
message.content,
|
|
20513
|
+
session,
|
|
20514
|
+
i
|
|
20515
|
+
);
|
|
20516
|
+
if (pattern) {
|
|
20517
|
+
patterns.push(pattern);
|
|
20518
|
+
}
|
|
20519
|
+
}
|
|
20520
|
+
}
|
|
20521
|
+
}
|
|
20522
|
+
return patterns;
|
|
20523
|
+
}
|
|
20524
|
+
function findConventionPatterns(session) {
|
|
20525
|
+
const patterns = [];
|
|
20526
|
+
const messages = session.messages;
|
|
20527
|
+
const conventionKeywords = [
|
|
20528
|
+
"naming convention",
|
|
20529
|
+
"pattern we use",
|
|
20530
|
+
"standard",
|
|
20531
|
+
"best practice",
|
|
20532
|
+
"we always",
|
|
20533
|
+
"convention",
|
|
20534
|
+
"style guide"
|
|
20535
|
+
];
|
|
20536
|
+
for (let i = 0; i < messages.length; i++) {
|
|
20537
|
+
const message = messages[i];
|
|
20538
|
+
if (message.role !== "assistant") continue;
|
|
20539
|
+
const content = message.content.toLowerCase();
|
|
20540
|
+
if (conventionKeywords.some((kw) => content.includes(kw))) {
|
|
20541
|
+
const pattern = createPattern(
|
|
20542
|
+
"convention",
|
|
20543
|
+
"Project convention discovered",
|
|
20544
|
+
message.content,
|
|
20545
|
+
session,
|
|
20546
|
+
i
|
|
20547
|
+
);
|
|
20548
|
+
if (pattern) {
|
|
20549
|
+
patterns.push(pattern);
|
|
20550
|
+
}
|
|
20551
|
+
}
|
|
20552
|
+
}
|
|
20553
|
+
return patterns;
|
|
20554
|
+
}
|
|
20555
|
+
function findDebuggingPatterns(session) {
|
|
20556
|
+
const patterns = [];
|
|
20557
|
+
const messages = session.messages;
|
|
20558
|
+
const debugKeywords = [
|
|
20559
|
+
"to debug this",
|
|
20560
|
+
"debugging",
|
|
20561
|
+
"to find the issue",
|
|
20562
|
+
"trace",
|
|
20563
|
+
"breakpoint",
|
|
20564
|
+
"logging",
|
|
20565
|
+
"to diagnose"
|
|
20566
|
+
];
|
|
20567
|
+
for (let i = 0; i < messages.length; i++) {
|
|
20568
|
+
const message = messages[i];
|
|
20569
|
+
if (message.role !== "assistant") continue;
|
|
20570
|
+
const content = message.content.toLowerCase();
|
|
20571
|
+
if (debugKeywords.some((kw) => content.includes(kw))) {
|
|
20572
|
+
const problem = findPrecedingProblem(messages, i);
|
|
20573
|
+
if (problem) {
|
|
20574
|
+
const pattern = createPattern(
|
|
20575
|
+
"debugging",
|
|
20576
|
+
problem,
|
|
20577
|
+
message.content,
|
|
20578
|
+
session,
|
|
20579
|
+
i
|
|
20580
|
+
);
|
|
20581
|
+
if (pattern) {
|
|
20582
|
+
patterns.push(pattern);
|
|
20583
|
+
}
|
|
20584
|
+
}
|
|
20585
|
+
}
|
|
20586
|
+
}
|
|
20587
|
+
return patterns;
|
|
20588
|
+
}
|
|
20589
|
+
function isErrorDescription(content) {
|
|
20590
|
+
const errorKeywords = [
|
|
20591
|
+
"error",
|
|
20592
|
+
"fail",
|
|
20593
|
+
"exception",
|
|
20594
|
+
"crash",
|
|
20595
|
+
"not working",
|
|
20596
|
+
"broken",
|
|
20597
|
+
"bug",
|
|
20598
|
+
"issue",
|
|
20599
|
+
"problem",
|
|
20600
|
+
"does not",
|
|
20601
|
+
"doesn't",
|
|
20602
|
+
"can't",
|
|
20603
|
+
"cannot"
|
|
20604
|
+
];
|
|
20605
|
+
const lower = content.toLowerCase();
|
|
20606
|
+
return errorKeywords.some((kw) => lower.includes(kw));
|
|
20607
|
+
}
|
|
20608
|
+
function isSolution(content) {
|
|
20609
|
+
const solutionKeywords = [
|
|
20610
|
+
"fix",
|
|
20611
|
+
"solution",
|
|
20612
|
+
"resolve",
|
|
20613
|
+
"change",
|
|
20614
|
+
"update",
|
|
20615
|
+
"modify",
|
|
20616
|
+
"replace",
|
|
20617
|
+
"should be",
|
|
20618
|
+
"try this",
|
|
20619
|
+
"use instead"
|
|
20620
|
+
];
|
|
20621
|
+
const lower = content.toLowerCase();
|
|
20622
|
+
return solutionKeywords.some((kw) => lower.includes(kw));
|
|
20623
|
+
}
|
|
20624
|
+
function findPrecedingProblem(messages, currentIndex) {
|
|
20625
|
+
for (let i = currentIndex - 1; i >= 0 && i > currentIndex - 5; i--) {
|
|
20626
|
+
const message = messages[i];
|
|
20627
|
+
if (message.role === "user" && message.content.length > 20) {
|
|
20628
|
+
return message.content;
|
|
20629
|
+
}
|
|
20630
|
+
}
|
|
20631
|
+
return null;
|
|
20632
|
+
}
|
|
20633
|
+
function createPatternFromErrorFix(errorDescription, solution, session, messageIndex) {
|
|
20634
|
+
return createPattern("error_fix", errorDescription, solution, session, messageIndex);
|
|
20635
|
+
}
|
|
20636
|
+
function createPattern(category, problem, solution, session, messageIndex) {
|
|
20637
|
+
if (problem.length < 20 || solution.length < 20) {
|
|
20638
|
+
return null;
|
|
20639
|
+
}
|
|
20640
|
+
const id = `session-${Date.now()}-${messageIndex}`;
|
|
20641
|
+
const title = extractTitle(problem, category);
|
|
20642
|
+
return {
|
|
20643
|
+
id,
|
|
20644
|
+
category,
|
|
20645
|
+
title,
|
|
20646
|
+
problem: truncate(problem, 500),
|
|
20647
|
+
solution: truncate(solution, 1e3),
|
|
20648
|
+
context: session.projectPath,
|
|
20649
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20650
|
+
source: "session",
|
|
20651
|
+
approved: false,
|
|
20652
|
+
confidence: calculateSessionConfidence(problem, solution, session)
|
|
20653
|
+
};
|
|
20654
|
+
}
|
|
20655
|
+
function extractTitle(problem, category) {
|
|
20656
|
+
const firstSentence = problem.split(/[.!?]/)[0].trim();
|
|
20657
|
+
if (firstSentence.length > 80) {
|
|
20658
|
+
return `${category.charAt(0).toUpperCase() + category.slice(1).replace("_", " ")} pattern`;
|
|
20659
|
+
}
|
|
20660
|
+
return firstSentence;
|
|
20661
|
+
}
|
|
20662
|
+
function truncate(str, maxLen) {
|
|
20663
|
+
if (str.length <= maxLen) return str;
|
|
20664
|
+
return str.slice(0, maxLen - 3) + "...";
|
|
20665
|
+
}
|
|
20666
|
+
function calculateSessionConfidence(problem, solution, _session) {
|
|
20667
|
+
let confidence = 0.4;
|
|
20668
|
+
if (problem.length > 50 && problem.length < 500) {
|
|
20669
|
+
confidence += 0.1;
|
|
20670
|
+
}
|
|
20671
|
+
if (solution.length > 100 && solution.length < 1e3) {
|
|
20672
|
+
confidence += 0.1;
|
|
20673
|
+
}
|
|
20674
|
+
if (solution.includes("```")) {
|
|
20675
|
+
confidence += 0.15;
|
|
20676
|
+
}
|
|
20677
|
+
return Math.min(0.85, confidence);
|
|
20678
|
+
}
|
|
20679
|
+
function mergePatterns(existing, newPatterns) {
|
|
20680
|
+
const merged = [...existing];
|
|
20681
|
+
for (const pattern of newPatterns) {
|
|
20682
|
+
const existingIndex = merged.findIndex(
|
|
20683
|
+
(p) => p.problem === pattern.problem || p.id === pattern.id
|
|
20684
|
+
);
|
|
20685
|
+
if (existingIndex >= 0) {
|
|
20686
|
+
if (pattern.confidence > merged[existingIndex].confidence) {
|
|
20687
|
+
merged[existingIndex] = pattern;
|
|
20688
|
+
}
|
|
20689
|
+
} else {
|
|
20690
|
+
merged.push(pattern);
|
|
20691
|
+
}
|
|
20692
|
+
}
|
|
20693
|
+
return merged;
|
|
20694
|
+
}
|
|
20695
|
+
|
|
20696
|
+
// src/learning/generator.ts
|
|
20697
|
+
import { writeFileSync as writeFileSync22, mkdirSync as mkdirSync22, existsSync as existsSync40 } from "fs";
|
|
20698
|
+
import { join as join41 } from "path";
|
|
20699
|
+
import { homedir as homedir12 } from "os";
|
|
20700
|
+
function generateSkillFromPatterns(patterns, options = {}) {
|
|
20701
|
+
const minConfidence = options.minConfidence ?? 0.5;
|
|
20702
|
+
const minPatterns = options.minPatterns ?? 1;
|
|
20703
|
+
const eligiblePatterns = patterns.filter((p) => p.confidence >= minConfidence);
|
|
20704
|
+
if (eligiblePatterns.length < minPatterns) {
|
|
20705
|
+
return null;
|
|
20706
|
+
}
|
|
20707
|
+
const category = getMostCommonCategory(eligiblePatterns);
|
|
20708
|
+
const id = `learned-${category}-${Date.now()}`;
|
|
20709
|
+
const name = formatSkillName2(category, eligiblePatterns);
|
|
20710
|
+
const content = generateSkillContent2(name, eligiblePatterns, category);
|
|
20711
|
+
const filename = `${id}.md`;
|
|
20712
|
+
return {
|
|
20713
|
+
id,
|
|
20714
|
+
name,
|
|
20715
|
+
filename,
|
|
20716
|
+
content,
|
|
20717
|
+
patterns: eligiblePatterns
|
|
20718
|
+
};
|
|
20719
|
+
}
|
|
20720
|
+
function getMostCommonCategory(patterns) {
|
|
20721
|
+
const counts = /* @__PURE__ */ new Map();
|
|
20722
|
+
for (const pattern of patterns) {
|
|
20723
|
+
counts.set(pattern.category, (counts.get(pattern.category) || 0) + 1);
|
|
20724
|
+
}
|
|
20725
|
+
let maxCategory = "error_fix";
|
|
20726
|
+
let maxCount = 0;
|
|
20727
|
+
for (const [category, count] of counts) {
|
|
20728
|
+
if (count > maxCount) {
|
|
20729
|
+
maxCount = count;
|
|
20730
|
+
maxCategory = category;
|
|
20731
|
+
}
|
|
20732
|
+
}
|
|
20733
|
+
return maxCategory;
|
|
20734
|
+
}
|
|
20735
|
+
function formatSkillName2(category, patterns) {
|
|
20736
|
+
const categoryNames = {
|
|
20737
|
+
error_fix: "Error Fixes",
|
|
20738
|
+
refactor: "Refactoring Patterns",
|
|
20739
|
+
workaround: "Workarounds",
|
|
20740
|
+
debugging: "Debugging Techniques",
|
|
20741
|
+
convention: "Project Conventions"
|
|
20742
|
+
};
|
|
20743
|
+
const baseName = categoryNames[category];
|
|
20744
|
+
const context = patterns[0]?.context || "Project";
|
|
20745
|
+
return `${baseName} - ${context}`;
|
|
20746
|
+
}
|
|
20747
|
+
function generateSkillContent2(name, patterns, category) {
|
|
20748
|
+
const lines = [];
|
|
20749
|
+
lines.push("---");
|
|
20750
|
+
lines.push(`name: ${name.toLowerCase().replace(/\s+/g, "-")}`);
|
|
20751
|
+
lines.push(`description: Learned ${category.replace("_", " ")} patterns from project history`);
|
|
20752
|
+
lines.push(`category: learned`);
|
|
20753
|
+
lines.push(`source: automated`);
|
|
20754
|
+
lines.push(`generated: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
20755
|
+
lines.push(`pattern_count: ${patterns.length}`);
|
|
20756
|
+
lines.push("---");
|
|
20757
|
+
lines.push("");
|
|
20758
|
+
lines.push(`# ${name}`);
|
|
20759
|
+
lines.push("");
|
|
20760
|
+
lines.push("> This skill was automatically generated from learned patterns.");
|
|
20761
|
+
lines.push("");
|
|
20762
|
+
lines.push("## Patterns");
|
|
20763
|
+
lines.push("");
|
|
20764
|
+
for (const pattern of patterns) {
|
|
20765
|
+
lines.push(`### ${pattern.title}`);
|
|
20766
|
+
lines.push("");
|
|
20767
|
+
lines.push(`**Category:** ${pattern.category.replace("_", " ")}`);
|
|
20768
|
+
lines.push(`**Confidence:** ${(pattern.confidence * 100).toFixed(0)}%`);
|
|
20769
|
+
lines.push("");
|
|
20770
|
+
lines.push("**Problem:**");
|
|
20771
|
+
lines.push(pattern.problem);
|
|
20772
|
+
lines.push("");
|
|
20773
|
+
lines.push("**Solution:**");
|
|
20774
|
+
lines.push(pattern.solution);
|
|
20775
|
+
lines.push("");
|
|
20776
|
+
if (pattern.example) {
|
|
20777
|
+
lines.push("**Example:**");
|
|
20778
|
+
lines.push("```");
|
|
20779
|
+
lines.push(pattern.example);
|
|
20780
|
+
lines.push("```");
|
|
20781
|
+
lines.push("");
|
|
20782
|
+
}
|
|
20783
|
+
lines.push("---");
|
|
20784
|
+
lines.push("");
|
|
20785
|
+
}
|
|
20786
|
+
return lines.join("\n");
|
|
20787
|
+
}
|
|
20788
|
+
function saveGeneratedSkill(skill, outputDir) {
|
|
20789
|
+
const dir = outputDir || join41(homedir12(), ".skillkit", "skills", "learned");
|
|
20790
|
+
if (!existsSync40(dir)) {
|
|
20791
|
+
mkdirSync22(dir, { recursive: true });
|
|
20792
|
+
}
|
|
20793
|
+
const filepath = join41(dir, skill.filename);
|
|
20794
|
+
writeFileSync22(filepath, skill.content);
|
|
20795
|
+
return filepath;
|
|
20796
|
+
}
|
|
20797
|
+
function generatePatternReport(patterns) {
|
|
20798
|
+
const lines = [];
|
|
20799
|
+
lines.push("# Learned Patterns Report");
|
|
20800
|
+
lines.push("");
|
|
20801
|
+
lines.push(`Generated: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
20802
|
+
lines.push(`Total Patterns: ${patterns.length}`);
|
|
20803
|
+
lines.push("");
|
|
20804
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
20805
|
+
for (const pattern of patterns) {
|
|
20806
|
+
if (!byCategory.has(pattern.category)) {
|
|
20807
|
+
byCategory.set(pattern.category, []);
|
|
20808
|
+
}
|
|
20809
|
+
byCategory.get(pattern.category).push(pattern);
|
|
20810
|
+
}
|
|
20811
|
+
lines.push("## Summary by Category");
|
|
20812
|
+
lines.push("");
|
|
20813
|
+
lines.push("| Category | Count | Avg Confidence |");
|
|
20814
|
+
lines.push("|----------|-------|----------------|");
|
|
20815
|
+
for (const [category, catPatterns] of byCategory) {
|
|
20816
|
+
const avgConfidence = catPatterns.reduce((sum, p) => sum + p.confidence, 0) / catPatterns.length;
|
|
20817
|
+
lines.push(`| ${category.replace("_", " ")} | ${catPatterns.length} | ${(avgConfidence * 100).toFixed(0)}% |`);
|
|
20818
|
+
}
|
|
20819
|
+
lines.push("");
|
|
20820
|
+
lines.push("## Patterns");
|
|
20821
|
+
lines.push("");
|
|
20822
|
+
const approved = patterns.filter((p) => p.approved);
|
|
20823
|
+
const pending = patterns.filter((p) => !p.approved);
|
|
20824
|
+
if (approved.length > 0) {
|
|
20825
|
+
lines.push("### Approved Patterns");
|
|
20826
|
+
lines.push("");
|
|
20827
|
+
for (const pattern of approved) {
|
|
20828
|
+
lines.push(`- **${pattern.title}** (${pattern.category}, ${(pattern.confidence * 100).toFixed(0)}%)`);
|
|
20829
|
+
}
|
|
20830
|
+
lines.push("");
|
|
20831
|
+
}
|
|
20832
|
+
if (pending.length > 0) {
|
|
20833
|
+
lines.push("### Pending Approval");
|
|
20834
|
+
lines.push("");
|
|
20835
|
+
for (const pattern of pending) {
|
|
20836
|
+
lines.push(`- **${pattern.title}** (${pattern.category}, ${(pattern.confidence * 100).toFixed(0)}%)`);
|
|
20837
|
+
}
|
|
20838
|
+
lines.push("");
|
|
20839
|
+
}
|
|
20840
|
+
return lines.join("\n");
|
|
20841
|
+
}
|
|
20842
|
+
function exportPatternsAsJson(patterns) {
|
|
20843
|
+
return JSON.stringify(
|
|
20844
|
+
{
|
|
20845
|
+
version: 1,
|
|
20846
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20847
|
+
count: patterns.length,
|
|
20848
|
+
patterns
|
|
20849
|
+
},
|
|
20850
|
+
null,
|
|
20851
|
+
2
|
|
20852
|
+
);
|
|
20853
|
+
}
|
|
20854
|
+
function importPatternsFromJson(jsonContent) {
|
|
20855
|
+
try {
|
|
20856
|
+
const data = JSON.parse(jsonContent);
|
|
20857
|
+
if (Array.isArray(data.patterns)) {
|
|
20858
|
+
return data.patterns;
|
|
20859
|
+
}
|
|
20860
|
+
if (Array.isArray(data)) {
|
|
20861
|
+
return data;
|
|
20862
|
+
}
|
|
20863
|
+
return [];
|
|
20864
|
+
} catch {
|
|
20865
|
+
return [];
|
|
20866
|
+
}
|
|
20867
|
+
}
|
|
20868
|
+
|
|
20869
|
+
// src/learning/feedback.ts
|
|
20870
|
+
function recordSuccess(patternId, storePath) {
|
|
20871
|
+
const store = loadPatternStore(storePath);
|
|
20872
|
+
const evolving = findOrCreateEvolvingPattern(store, patternId);
|
|
20873
|
+
if (!evolving) return null;
|
|
20874
|
+
const previousConfidence = evolving.confidence;
|
|
20875
|
+
evolving.useCount++;
|
|
20876
|
+
evolving.successCount++;
|
|
20877
|
+
evolving.lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
20878
|
+
evolving.confidence = Math.min(0.95, evolving.confidence + 0.05);
|
|
20879
|
+
updateEvolvingPattern(store, evolving);
|
|
20880
|
+
savePatternStore(store, storePath);
|
|
20881
|
+
return {
|
|
20882
|
+
pattern: evolving,
|
|
20883
|
+
previousConfidence,
|
|
20884
|
+
newConfidence: evolving.confidence,
|
|
20885
|
+
change: "increased"
|
|
20886
|
+
};
|
|
20887
|
+
}
|
|
20888
|
+
function recordFailure(patternId, storePath) {
|
|
20889
|
+
const store = loadPatternStore(storePath);
|
|
20890
|
+
const evolving = findOrCreateEvolvingPattern(store, patternId);
|
|
20891
|
+
if (!evolving) return null;
|
|
20892
|
+
const previousConfidence = evolving.confidence;
|
|
20893
|
+
evolving.useCount++;
|
|
20894
|
+
evolving.failureCount++;
|
|
20895
|
+
evolving.lastUsed = (/* @__PURE__ */ new Date()).toISOString();
|
|
20896
|
+
evolving.confidence = Math.max(0.1, evolving.confidence - 0.1);
|
|
20897
|
+
updateEvolvingPattern(store, evolving);
|
|
20898
|
+
savePatternStore(store, storePath);
|
|
20899
|
+
return {
|
|
20900
|
+
pattern: evolving,
|
|
20901
|
+
previousConfidence,
|
|
20902
|
+
newConfidence: evolving.confidence,
|
|
20903
|
+
change: "decreased"
|
|
20904
|
+
};
|
|
20905
|
+
}
|
|
20906
|
+
function findOrCreateEvolvingPattern(store, patternId) {
|
|
20907
|
+
let evolving = store.evolvingPatterns.find((p) => p.id === patternId);
|
|
20908
|
+
if (!evolving) {
|
|
20909
|
+
const basePattern = store.patterns.find((p) => p.id === patternId);
|
|
20910
|
+
if (!basePattern) return null;
|
|
20911
|
+
evolving = {
|
|
20912
|
+
...basePattern,
|
|
20913
|
+
trigger: inferTrigger(basePattern),
|
|
20914
|
+
action: inferAction(basePattern),
|
|
20915
|
+
useCount: 0,
|
|
20916
|
+
successCount: 0,
|
|
20917
|
+
failureCount: 0
|
|
20918
|
+
};
|
|
20919
|
+
store.evolvingPatterns.push(evolving);
|
|
20920
|
+
}
|
|
20921
|
+
return evolving;
|
|
20922
|
+
}
|
|
20923
|
+
function updateEvolvingPattern(store, evolving) {
|
|
20924
|
+
const index = store.evolvingPatterns.findIndex((p) => p.id === evolving.id);
|
|
20925
|
+
if (index >= 0) {
|
|
20926
|
+
store.evolvingPatterns[index] = evolving;
|
|
20927
|
+
} else {
|
|
20928
|
+
store.evolvingPatterns.push(evolving);
|
|
20929
|
+
}
|
|
20930
|
+
}
|
|
20931
|
+
function inferTrigger(pattern) {
|
|
20932
|
+
const problem = pattern.problem.toLowerCase();
|
|
20933
|
+
if (problem.includes("error") || problem.includes("exception")) {
|
|
20934
|
+
return "When encountering similar errors";
|
|
20935
|
+
}
|
|
20936
|
+
if (problem.includes("build") || problem.includes("compile")) {
|
|
20937
|
+
return "During build/compilation issues";
|
|
20938
|
+
}
|
|
20939
|
+
if (problem.includes("test")) {
|
|
20940
|
+
return "When tests fail in similar ways";
|
|
20941
|
+
}
|
|
20942
|
+
return `When facing: ${pattern.title}`;
|
|
20943
|
+
}
|
|
20944
|
+
function inferAction(pattern) {
|
|
20945
|
+
return pattern.solution.split("\n")[0] || "Apply learned solution";
|
|
20946
|
+
}
|
|
20947
|
+
function getEvolvingPatternsByDomain(domain, storePath) {
|
|
20948
|
+
const store = loadPatternStore(storePath);
|
|
20949
|
+
return store.evolvingPatterns.filter((p) => p.domain === domain);
|
|
20950
|
+
}
|
|
20951
|
+
function getHighConfidencePatterns(minConfidence = 0.7, storePath) {
|
|
20952
|
+
const store = loadPatternStore(storePath);
|
|
20953
|
+
return store.evolvingPatterns.filter((p) => p.confidence >= minConfidence).sort((a, b) => b.confidence - a.confidence);
|
|
20954
|
+
}
|
|
20955
|
+
function getLowConfidencePatterns(maxConfidence = 0.3, storePath) {
|
|
20956
|
+
const store = loadPatternStore(storePath);
|
|
20957
|
+
return store.evolvingPatterns.filter((p) => p.confidence <= maxConfidence).sort((a, b) => a.confidence - b.confidence);
|
|
20958
|
+
}
|
|
20959
|
+
function getMostUsedPatterns(limit = 10, storePath) {
|
|
20960
|
+
const store = loadPatternStore(storePath);
|
|
20961
|
+
return store.evolvingPatterns.sort((a, b) => b.useCount - a.useCount).slice(0, limit);
|
|
20962
|
+
}
|
|
20963
|
+
function getPatternStats(storePath) {
|
|
20964
|
+
const store = loadPatternStore(storePath);
|
|
20965
|
+
const patterns = store.evolvingPatterns;
|
|
20966
|
+
const byDomain = /* @__PURE__ */ new Map();
|
|
20967
|
+
let high = 0, medium = 0, low = 0;
|
|
20968
|
+
for (const pattern of patterns) {
|
|
20969
|
+
const domain = pattern.domain || "unknown";
|
|
20970
|
+
byDomain.set(domain, (byDomain.get(domain) || 0) + 1);
|
|
20971
|
+
if (pattern.confidence >= 0.7) high++;
|
|
20972
|
+
else if (pattern.confidence >= 0.4) medium++;
|
|
20973
|
+
else low++;
|
|
20974
|
+
}
|
|
20975
|
+
const mostUsed = patterns.length > 0 ? patterns.reduce((max, p) => p.useCount > max.useCount ? p : max) : null;
|
|
20976
|
+
const leastConfident = patterns.length > 0 ? patterns.reduce((min, p) => p.confidence < min.confidence ? p : min) : null;
|
|
20977
|
+
return {
|
|
20978
|
+
total: patterns.length,
|
|
20979
|
+
byDomain,
|
|
20980
|
+
byConfidenceRange: { high, medium, low },
|
|
20981
|
+
mostUsed,
|
|
20982
|
+
leastConfident
|
|
20983
|
+
};
|
|
20984
|
+
}
|
|
20985
|
+
function approvePattern(patternId, storePath) {
|
|
20986
|
+
const store = loadPatternStore(storePath);
|
|
20987
|
+
const pattern = store.patterns.find((p) => p.id === patternId);
|
|
20988
|
+
if (!pattern) return null;
|
|
20989
|
+
pattern.approved = true;
|
|
20990
|
+
savePatternStore(store, storePath);
|
|
20991
|
+
return pattern;
|
|
20992
|
+
}
|
|
20993
|
+
function rejectPattern(patternId, storePath) {
|
|
20994
|
+
const store = loadPatternStore(storePath);
|
|
20995
|
+
const index = store.patterns.findIndex((p) => p.id === patternId);
|
|
20996
|
+
if (index < 0) return false;
|
|
20997
|
+
store.patterns.splice(index, 1);
|
|
20998
|
+
const evolvingIndex = store.evolvingPatterns.findIndex((p) => p.id === patternId);
|
|
20999
|
+
if (evolvingIndex >= 0) {
|
|
21000
|
+
store.evolvingPatterns.splice(evolvingIndex, 1);
|
|
21001
|
+
}
|
|
21002
|
+
savePatternStore(store, storePath);
|
|
21003
|
+
return true;
|
|
21004
|
+
}
|
|
21005
|
+
function clusterPatterns(patterns) {
|
|
21006
|
+
const clusters = /* @__PURE__ */ new Map();
|
|
21007
|
+
for (const pattern of patterns) {
|
|
21008
|
+
const key = pattern.category;
|
|
21009
|
+
if (!clusters.has(key)) {
|
|
21010
|
+
clusters.set(key, []);
|
|
21011
|
+
}
|
|
21012
|
+
clusters.get(key).push(pattern);
|
|
21013
|
+
}
|
|
21014
|
+
return clusters;
|
|
21015
|
+
}
|
|
21016
|
+
|
|
21017
|
+
// src/profiles/types.ts
|
|
21018
|
+
var DEFAULT_PROFILE_CONFIG = {
|
|
21019
|
+
activeProfile: "dev",
|
|
21020
|
+
customProfiles: []
|
|
21021
|
+
};
|
|
21022
|
+
|
|
21023
|
+
// src/profiles/manager.ts
|
|
21024
|
+
import { existsSync as existsSync41, readFileSync as readFileSync30, writeFileSync as writeFileSync23, mkdirSync as mkdirSync23 } from "fs";
|
|
21025
|
+
import { join as join42, dirname as dirname15 } from "path";
|
|
21026
|
+
import { homedir as homedir13 } from "os";
|
|
21027
|
+
import yaml2 from "yaml";
|
|
21028
|
+
var BUILTIN_PROFILES = [
|
|
21029
|
+
{
|
|
21030
|
+
name: "dev",
|
|
21031
|
+
description: "Active development mode",
|
|
21032
|
+
focus: "Implementation speed and working solutions",
|
|
21033
|
+
behaviors: [
|
|
21034
|
+
"Prefer working code over perfect code",
|
|
21035
|
+
"Quick iterations with frequent testing",
|
|
21036
|
+
"Minimize context switching",
|
|
21037
|
+
"Focus on the current task"
|
|
21038
|
+
],
|
|
21039
|
+
priorities: ["Functionality", "Simplicity", "Testability", "Speed"],
|
|
21040
|
+
preferredTools: ["Edit", "Write", "Bash", "Read"],
|
|
21041
|
+
injectedContext: `You are in DEVELOPMENT mode. Focus on:
|
|
21042
|
+
- Getting working code quickly
|
|
21043
|
+
- Writing minimal tests for new functionality
|
|
21044
|
+
- Keeping changes small and focused
|
|
21045
|
+
- Committing frequently`
|
|
21046
|
+
},
|
|
21047
|
+
{
|
|
21048
|
+
name: "review",
|
|
21049
|
+
description: "Code review mode",
|
|
21050
|
+
focus: "Quality, security, and maintainability",
|
|
21051
|
+
behaviors: [
|
|
21052
|
+
"Thorough analysis before suggesting changes",
|
|
21053
|
+
"Security-first mindset",
|
|
21054
|
+
"Consider edge cases and failure modes",
|
|
21055
|
+
"Provide constructive feedback"
|
|
21056
|
+
],
|
|
21057
|
+
priorities: ["Security", "Code quality", "Best practices", "Maintainability"],
|
|
21058
|
+
preferredTools: ["Read", "Grep", "Glob"],
|
|
21059
|
+
avoidTools: ["Edit", "Write"],
|
|
21060
|
+
injectedContext: `You are in REVIEW mode. Focus on:
|
|
21061
|
+
- Identifying potential bugs and security issues
|
|
21062
|
+
- Checking code against best practices
|
|
21063
|
+
- Verifying test coverage
|
|
21064
|
+
- Suggesting improvements without making changes`
|
|
21065
|
+
},
|
|
21066
|
+
{
|
|
21067
|
+
name: "research",
|
|
21068
|
+
description: "Exploration and discovery mode",
|
|
21069
|
+
focus: "Understanding and analysis",
|
|
21070
|
+
behaviors: [
|
|
21071
|
+
"Deep exploration of codebase",
|
|
21072
|
+
"Document findings thoroughly",
|
|
21073
|
+
"Consider multiple approaches",
|
|
21074
|
+
"Ask clarifying questions"
|
|
21075
|
+
],
|
|
21076
|
+
priorities: ["Understanding", "Documentation", "Options analysis", "Learning"],
|
|
21077
|
+
preferredTools: ["Read", "Grep", "Glob", "WebSearch", "WebFetch"],
|
|
21078
|
+
avoidTools: ["Edit", "Write"],
|
|
21079
|
+
injectedContext: `You are in RESEARCH mode. Focus on:
|
|
21080
|
+
- Understanding the codebase structure
|
|
21081
|
+
- Finding relevant documentation
|
|
21082
|
+
- Exploring different approaches
|
|
21083
|
+
- Creating summaries of findings`
|
|
21084
|
+
},
|
|
21085
|
+
{
|
|
21086
|
+
name: "security",
|
|
21087
|
+
description: "Security audit mode",
|
|
21088
|
+
focus: "Vulnerability detection and hardening",
|
|
21089
|
+
behaviors: [
|
|
21090
|
+
"Assume hostile input",
|
|
21091
|
+
"Check all authentication and authorization",
|
|
21092
|
+
"Look for common vulnerability patterns",
|
|
21093
|
+
"Verify encryption and data protection"
|
|
21094
|
+
],
|
|
21095
|
+
priorities: ["Security", "Data protection", "Authentication", "Authorization"],
|
|
21096
|
+
preferredTools: ["Read", "Grep", "Glob", "Bash"],
|
|
21097
|
+
injectedContext: `You are in SECURITY AUDIT mode. Focus on:
|
|
21098
|
+
- OWASP Top 10 vulnerabilities
|
|
21099
|
+
- Authentication and authorization flaws
|
|
21100
|
+
- Data exposure risks
|
|
21101
|
+
- Injection vulnerabilities
|
|
21102
|
+
- Secrets and credentials in code`
|
|
21103
|
+
}
|
|
21104
|
+
];
|
|
21105
|
+
function getConfigPath() {
|
|
21106
|
+
return join42(homedir13(), ".skillkit", "profiles.yaml");
|
|
21107
|
+
}
|
|
21108
|
+
function loadProfileConfig() {
|
|
21109
|
+
const path2 = getConfigPath();
|
|
21110
|
+
if (!existsSync41(path2)) {
|
|
21111
|
+
return DEFAULT_PROFILE_CONFIG;
|
|
21112
|
+
}
|
|
21113
|
+
try {
|
|
21114
|
+
const content = readFileSync30(path2, "utf-8");
|
|
21115
|
+
return { ...DEFAULT_PROFILE_CONFIG, ...yaml2.parse(content) };
|
|
21116
|
+
} catch {
|
|
21117
|
+
return DEFAULT_PROFILE_CONFIG;
|
|
21118
|
+
}
|
|
21119
|
+
}
|
|
21120
|
+
function saveProfileConfig(config) {
|
|
21121
|
+
const path2 = getConfigPath();
|
|
21122
|
+
const dir = dirname15(path2);
|
|
21123
|
+
if (!existsSync41(dir)) {
|
|
21124
|
+
mkdirSync23(dir, { recursive: true });
|
|
21125
|
+
}
|
|
21126
|
+
writeFileSync23(path2, yaml2.stringify(config));
|
|
21127
|
+
}
|
|
21128
|
+
function getActiveProfile() {
|
|
21129
|
+
const config = loadProfileConfig();
|
|
21130
|
+
return config.activeProfile;
|
|
21131
|
+
}
|
|
21132
|
+
function setActiveProfile(name) {
|
|
21133
|
+
const config = loadProfileConfig();
|
|
21134
|
+
config.activeProfile = name;
|
|
21135
|
+
saveProfileConfig(config);
|
|
21136
|
+
}
|
|
21137
|
+
function getProfile(name) {
|
|
21138
|
+
const builtin = BUILTIN_PROFILES.find((p) => p.name === name);
|
|
21139
|
+
if (builtin) return builtin;
|
|
21140
|
+
const config = loadProfileConfig();
|
|
21141
|
+
return config.customProfiles.find((p) => p.name === name) || null;
|
|
21142
|
+
}
|
|
21143
|
+
function getAllProfiles() {
|
|
21144
|
+
const config = loadProfileConfig();
|
|
21145
|
+
return [...BUILTIN_PROFILES, ...config.customProfiles];
|
|
21146
|
+
}
|
|
21147
|
+
function getBuiltinProfiles() {
|
|
21148
|
+
return BUILTIN_PROFILES;
|
|
21149
|
+
}
|
|
21150
|
+
function getProfileNames() {
|
|
21151
|
+
const config = loadProfileConfig();
|
|
21152
|
+
const builtinNames = BUILTIN_PROFILES.map((p) => p.name);
|
|
21153
|
+
const customNames = config.customProfiles.map((p) => p.name);
|
|
21154
|
+
return [...builtinNames, ...customNames];
|
|
21155
|
+
}
|
|
21156
|
+
function addCustomProfile(profile) {
|
|
21157
|
+
const config = loadProfileConfig();
|
|
21158
|
+
const existing = config.customProfiles.findIndex((p) => p.name === profile.name);
|
|
21159
|
+
if (existing >= 0) {
|
|
21160
|
+
config.customProfiles[existing] = profile;
|
|
21161
|
+
} else {
|
|
21162
|
+
config.customProfiles.push(profile);
|
|
21163
|
+
}
|
|
21164
|
+
saveProfileConfig(config);
|
|
21165
|
+
}
|
|
21166
|
+
function removeCustomProfile(name) {
|
|
21167
|
+
const config = loadProfileConfig();
|
|
21168
|
+
const index = config.customProfiles.findIndex((p) => p.name === name);
|
|
21169
|
+
if (index < 0) return false;
|
|
21170
|
+
config.customProfiles.splice(index, 1);
|
|
21171
|
+
if (config.activeProfile === name) {
|
|
21172
|
+
config.activeProfile = "dev";
|
|
21173
|
+
}
|
|
21174
|
+
saveProfileConfig(config);
|
|
21175
|
+
return true;
|
|
21176
|
+
}
|
|
21177
|
+
function getProfileContext(name) {
|
|
21178
|
+
const profileName = name || getActiveProfile();
|
|
21179
|
+
const profile = getProfile(profileName);
|
|
21180
|
+
return profile?.injectedContext || null;
|
|
21181
|
+
}
|
|
21182
|
+
function isBuiltinProfile(name) {
|
|
21183
|
+
return BUILTIN_PROFILES.some((p) => p.name === name);
|
|
21184
|
+
}
|
|
21185
|
+
|
|
21186
|
+
// src/guidelines/types.ts
|
|
21187
|
+
var DEFAULT_GUIDELINE_CONFIG = {
|
|
21188
|
+
enabledGuidelines: ["security", "code-style", "testing", "git"],
|
|
21189
|
+
customGuidelines: []
|
|
21190
|
+
};
|
|
21191
|
+
|
|
21192
|
+
// src/guidelines/manager.ts
|
|
21193
|
+
import { existsSync as existsSync42, readFileSync as readFileSync31, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24 } from "fs";
|
|
21194
|
+
import { join as join43, dirname as dirname16 } from "path";
|
|
21195
|
+
import { homedir as homedir14 } from "os";
|
|
21196
|
+
import yaml3 from "yaml";
|
|
21197
|
+
var BUILTIN_GUIDELINES = [
|
|
21198
|
+
{
|
|
21199
|
+
id: "security",
|
|
21200
|
+
name: "Security Guidelines",
|
|
21201
|
+
description: "Security best practices and vulnerability prevention",
|
|
21202
|
+
category: "security",
|
|
21203
|
+
priority: 10,
|
|
21204
|
+
enabled: true,
|
|
21205
|
+
scope: "global",
|
|
21206
|
+
content: `## Security Guidelines
|
|
21207
|
+
|
|
21208
|
+
### Input Validation
|
|
21209
|
+
- Validate all user input on the server side
|
|
21210
|
+
- Use allowlists over denylists when possible
|
|
21211
|
+
- Sanitize data before use in queries, commands, or output
|
|
21212
|
+
|
|
21213
|
+
### Authentication & Authorization
|
|
21214
|
+
- Never store passwords in plain text
|
|
21215
|
+
- Use secure session management
|
|
21216
|
+
- Implement proper authorization checks on every endpoint
|
|
21217
|
+
- Use HTTPS for all communications
|
|
21218
|
+
|
|
21219
|
+
### Data Protection
|
|
21220
|
+
- Encrypt sensitive data at rest and in transit
|
|
21221
|
+
- Never log sensitive information
|
|
21222
|
+
- Use environment variables for secrets
|
|
21223
|
+
- Implement proper access controls
|
|
21224
|
+
|
|
21225
|
+
### Common Vulnerabilities to Prevent
|
|
21226
|
+
- SQL Injection: Use parameterized queries
|
|
21227
|
+
- XSS: Encode output, use CSP headers
|
|
21228
|
+
- CSRF: Use anti-CSRF tokens
|
|
21229
|
+
- Command Injection: Avoid shell commands with user input`
|
|
21230
|
+
},
|
|
21231
|
+
{
|
|
21232
|
+
id: "code-style",
|
|
21233
|
+
name: "Code Style Guidelines",
|
|
21234
|
+
description: "Code formatting and style conventions",
|
|
21235
|
+
category: "code-style",
|
|
21236
|
+
priority: 7,
|
|
21237
|
+
enabled: true,
|
|
21238
|
+
scope: "global",
|
|
21239
|
+
content: `## Code Style Guidelines
|
|
21240
|
+
|
|
21241
|
+
### Naming Conventions
|
|
21242
|
+
- Use descriptive, meaningful names
|
|
21243
|
+
- camelCase for variables and functions
|
|
21244
|
+
- PascalCase for classes and types
|
|
21245
|
+
- SCREAMING_SNAKE_CASE for constants
|
|
21246
|
+
|
|
21247
|
+
### Code Organization
|
|
21248
|
+
- One concept per file
|
|
21249
|
+
- Group related code together
|
|
21250
|
+
- Keep files under 300 lines when practical
|
|
21251
|
+
- Use barrel exports (index.ts) for public APIs
|
|
21252
|
+
|
|
21253
|
+
### Functions
|
|
21254
|
+
- Single responsibility principle
|
|
21255
|
+
- Keep functions under 30 lines when practical
|
|
21256
|
+
- Use early returns to reduce nesting
|
|
21257
|
+
- Avoid side effects in pure functions
|
|
21258
|
+
|
|
21259
|
+
### Comments
|
|
21260
|
+
- Don't comment obvious code
|
|
21261
|
+
- Explain "why" not "what"
|
|
21262
|
+
- Keep comments up to date
|
|
21263
|
+
- Use JSDoc for public APIs`
|
|
21264
|
+
},
|
|
21265
|
+
{
|
|
21266
|
+
id: "testing",
|
|
21267
|
+
name: "Testing Guidelines",
|
|
21268
|
+
description: "Testing best practices and coverage requirements",
|
|
21269
|
+
category: "testing",
|
|
21270
|
+
priority: 8,
|
|
21271
|
+
enabled: true,
|
|
21272
|
+
scope: "global",
|
|
21273
|
+
content: `## Testing Guidelines
|
|
21274
|
+
|
|
21275
|
+
### Test Coverage
|
|
21276
|
+
- Aim for 80%+ code coverage
|
|
21277
|
+
- 100% coverage for critical paths
|
|
21278
|
+
- Don't sacrifice quality for coverage metrics
|
|
21279
|
+
|
|
21280
|
+
### Test Structure
|
|
21281
|
+
- Arrange, Act, Assert (AAA) pattern
|
|
21282
|
+
- One concept per test
|
|
21283
|
+
- Descriptive test names that explain behavior
|
|
21284
|
+
- Independent tests (no shared state)
|
|
21285
|
+
|
|
21286
|
+
### Test Types
|
|
21287
|
+
- Unit tests for business logic
|
|
21288
|
+
- Integration tests for component interactions
|
|
21289
|
+
- E2E tests for critical user flows
|
|
21290
|
+
|
|
21291
|
+
### Test Quality
|
|
21292
|
+
- Tests should be deterministic
|
|
21293
|
+
- Fast execution (< 100ms for unit tests)
|
|
21294
|
+
- Easy to understand and maintain
|
|
21295
|
+
- Test behavior, not implementation`
|
|
21296
|
+
},
|
|
21297
|
+
{
|
|
21298
|
+
id: "git",
|
|
21299
|
+
name: "Git Workflow Guidelines",
|
|
21300
|
+
description: "Version control best practices",
|
|
21301
|
+
category: "git",
|
|
21302
|
+
priority: 6,
|
|
21303
|
+
enabled: true,
|
|
21304
|
+
scope: "global",
|
|
21305
|
+
content: `## Git Workflow Guidelines
|
|
21306
|
+
|
|
21307
|
+
### Commits
|
|
21308
|
+
- Write clear, concise commit messages
|
|
21309
|
+
- Use conventional commits format
|
|
21310
|
+
- One logical change per commit
|
|
21311
|
+
- Don't commit generated files or secrets
|
|
21312
|
+
|
|
21313
|
+
### Branches
|
|
21314
|
+
- Use feature branches
|
|
21315
|
+
- Keep branches short-lived
|
|
21316
|
+
- Delete branches after merge
|
|
21317
|
+
- Protect main/master branch
|
|
21318
|
+
|
|
21319
|
+
### Pull Requests
|
|
21320
|
+
- Keep PRs focused and small
|
|
21321
|
+
- Write meaningful descriptions
|
|
21322
|
+
- Request reviews from appropriate people
|
|
21323
|
+
- Address all review comments
|
|
21324
|
+
|
|
21325
|
+
### Commit Message Format
|
|
21326
|
+
\`\`\`
|
|
21327
|
+
<type>(<scope>): <description>
|
|
21328
|
+
|
|
21329
|
+
[optional body]
|
|
21330
|
+
|
|
21331
|
+
[optional footer]
|
|
21332
|
+
\`\`\`
|
|
21333
|
+
|
|
21334
|
+
Types: feat, fix, docs, style, refactor, test, chore`
|
|
21335
|
+
},
|
|
21336
|
+
{
|
|
21337
|
+
id: "performance",
|
|
21338
|
+
name: "Performance Guidelines",
|
|
21339
|
+
description: "Performance optimization best practices",
|
|
21340
|
+
category: "performance",
|
|
21341
|
+
priority: 5,
|
|
21342
|
+
enabled: false,
|
|
21343
|
+
scope: "global",
|
|
21344
|
+
content: `## Performance Guidelines
|
|
21345
|
+
|
|
21346
|
+
### General Principles
|
|
21347
|
+
- Measure before optimizing
|
|
21348
|
+
- Optimize critical paths first
|
|
21349
|
+
- Consider time/space tradeoffs
|
|
21350
|
+
- Profile in production-like environments
|
|
21351
|
+
|
|
21352
|
+
### Database
|
|
21353
|
+
- Use indexes appropriately
|
|
21354
|
+
- Avoid N+1 queries
|
|
21355
|
+
- Paginate large result sets
|
|
21356
|
+
- Cache frequently accessed data
|
|
21357
|
+
|
|
21358
|
+
### Frontend
|
|
21359
|
+
- Minimize bundle size
|
|
21360
|
+
- Lazy load when appropriate
|
|
21361
|
+
- Optimize images and assets
|
|
21362
|
+
- Use efficient rendering patterns
|
|
21363
|
+
|
|
21364
|
+
### Backend
|
|
21365
|
+
- Use connection pooling
|
|
21366
|
+
- Implement appropriate caching
|
|
21367
|
+
- Async operations where beneficial
|
|
21368
|
+
- Monitor and alert on performance`
|
|
21369
|
+
}
|
|
21370
|
+
];
|
|
21371
|
+
function getConfigPath2() {
|
|
21372
|
+
return join43(homedir14(), ".skillkit", "guidelines.yaml");
|
|
21373
|
+
}
|
|
21374
|
+
function loadGuidelineConfig() {
|
|
21375
|
+
const path2 = getConfigPath2();
|
|
21376
|
+
if (!existsSync42(path2)) {
|
|
21377
|
+
return DEFAULT_GUIDELINE_CONFIG;
|
|
21378
|
+
}
|
|
21379
|
+
try {
|
|
21380
|
+
const content = readFileSync31(path2, "utf-8");
|
|
21381
|
+
return { ...DEFAULT_GUIDELINE_CONFIG, ...yaml3.parse(content) };
|
|
21382
|
+
} catch {
|
|
21383
|
+
return DEFAULT_GUIDELINE_CONFIG;
|
|
21384
|
+
}
|
|
21385
|
+
}
|
|
21386
|
+
function saveGuidelineConfig(config) {
|
|
21387
|
+
const path2 = getConfigPath2();
|
|
21388
|
+
const dir = dirname16(path2);
|
|
21389
|
+
if (!existsSync42(dir)) {
|
|
21390
|
+
mkdirSync24(dir, { recursive: true });
|
|
21391
|
+
}
|
|
21392
|
+
writeFileSync24(path2, yaml3.stringify(config));
|
|
21393
|
+
}
|
|
21394
|
+
function getGuideline(id) {
|
|
21395
|
+
const builtin = BUILTIN_GUIDELINES.find((g) => g.id === id);
|
|
21396
|
+
if (builtin) return builtin;
|
|
21397
|
+
const config = loadGuidelineConfig();
|
|
21398
|
+
return config.customGuidelines.find((g) => g.id === id) || null;
|
|
21399
|
+
}
|
|
21400
|
+
function getAllGuidelines() {
|
|
21401
|
+
const config = loadGuidelineConfig();
|
|
21402
|
+
return [...BUILTIN_GUIDELINES, ...config.customGuidelines];
|
|
21403
|
+
}
|
|
21404
|
+
function getBuiltinGuidelines() {
|
|
21405
|
+
return BUILTIN_GUIDELINES;
|
|
21406
|
+
}
|
|
21407
|
+
function getEnabledGuidelines() {
|
|
21408
|
+
const config = loadGuidelineConfig();
|
|
21409
|
+
const all = getAllGuidelines();
|
|
21410
|
+
return all.filter((g) => config.enabledGuidelines.includes(g.id));
|
|
21411
|
+
}
|
|
21412
|
+
function getGuidelinesByCategory(category) {
|
|
21413
|
+
return getAllGuidelines().filter((g) => g.category === category);
|
|
21414
|
+
}
|
|
21415
|
+
function enableGuideline(id) {
|
|
21416
|
+
const guideline = getGuideline(id);
|
|
21417
|
+
if (!guideline) return false;
|
|
21418
|
+
const config = loadGuidelineConfig();
|
|
21419
|
+
if (!config.enabledGuidelines.includes(id)) {
|
|
21420
|
+
config.enabledGuidelines.push(id);
|
|
21421
|
+
saveGuidelineConfig(config);
|
|
21422
|
+
}
|
|
21423
|
+
return true;
|
|
21424
|
+
}
|
|
21425
|
+
function disableGuideline(id) {
|
|
21426
|
+
const config = loadGuidelineConfig();
|
|
21427
|
+
const index = config.enabledGuidelines.indexOf(id);
|
|
21428
|
+
if (index < 0) return false;
|
|
21429
|
+
config.enabledGuidelines.splice(index, 1);
|
|
21430
|
+
saveGuidelineConfig(config);
|
|
21431
|
+
return true;
|
|
21432
|
+
}
|
|
21433
|
+
function isGuidelineEnabled(id) {
|
|
21434
|
+
const config = loadGuidelineConfig();
|
|
21435
|
+
return config.enabledGuidelines.includes(id);
|
|
21436
|
+
}
|
|
21437
|
+
function addCustomGuideline(guideline) {
|
|
21438
|
+
const config = loadGuidelineConfig();
|
|
21439
|
+
const existing = config.customGuidelines.findIndex((g) => g.id === guideline.id);
|
|
21440
|
+
if (existing >= 0) {
|
|
21441
|
+
config.customGuidelines[existing] = guideline;
|
|
21442
|
+
} else {
|
|
21443
|
+
config.customGuidelines.push(guideline);
|
|
21444
|
+
}
|
|
21445
|
+
saveGuidelineConfig(config);
|
|
21446
|
+
}
|
|
21447
|
+
function removeCustomGuideline(id) {
|
|
21448
|
+
const config = loadGuidelineConfig();
|
|
21449
|
+
const index = config.customGuidelines.findIndex((g) => g.id === id);
|
|
21450
|
+
if (index < 0) return false;
|
|
21451
|
+
config.customGuidelines.splice(index, 1);
|
|
21452
|
+
config.enabledGuidelines = config.enabledGuidelines.filter((g) => g !== id);
|
|
21453
|
+
saveGuidelineConfig(config);
|
|
21454
|
+
return true;
|
|
21455
|
+
}
|
|
21456
|
+
function getGuidelineContent(id) {
|
|
21457
|
+
const guideline = getGuideline(id);
|
|
21458
|
+
return guideline?.content || null;
|
|
21459
|
+
}
|
|
21460
|
+
function getEnabledGuidelineContent() {
|
|
21461
|
+
const enabled = getEnabledGuidelines();
|
|
21462
|
+
return enabled.map((g) => g.content).join("\n\n---\n\n");
|
|
21463
|
+
}
|
|
21464
|
+
function isBuiltinGuideline(id) {
|
|
21465
|
+
return BUILTIN_GUIDELINES.some((g) => g.id === id);
|
|
21466
|
+
}
|
|
19823
21467
|
export {
|
|
19824
21468
|
AGENT_CLI_CONFIGS,
|
|
19825
21469
|
AGENT_CONFIG,
|
|
@@ -19839,6 +21483,7 @@ export {
|
|
|
19839
21483
|
AgentPermissionMode,
|
|
19840
21484
|
AgentType,
|
|
19841
21485
|
AuditLogger,
|
|
21486
|
+
BUILTIN_PIPELINES,
|
|
19842
21487
|
BaseAIProvider,
|
|
19843
21488
|
BitbucketProvider,
|
|
19844
21489
|
CIRCLECI_CONFIG_TEMPLATE,
|
|
@@ -19854,7 +21499,10 @@ export {
|
|
|
19854
21499
|
CursorTranslator,
|
|
19855
21500
|
DEFAULT_CACHE_TTL,
|
|
19856
21501
|
DEFAULT_CONTEXT_CATEGORIES,
|
|
21502
|
+
DEFAULT_GUIDELINE_CONFIG,
|
|
21503
|
+
DEFAULT_LEARNING_CONFIG,
|
|
19857
21504
|
DEFAULT_MEMORY_CONFIG,
|
|
21505
|
+
DEFAULT_PROFILE_CONFIG,
|
|
19858
21506
|
DEFAULT_SCORING_WEIGHTS,
|
|
19859
21507
|
DEFAULT_SKILL_SOURCES,
|
|
19860
21508
|
GITHUB_ACTION_TEMPLATE,
|
|
@@ -19918,15 +21566,21 @@ export {
|
|
|
19918
21566
|
WORKFLOW_EXTENSION,
|
|
19919
21567
|
WindsurfTranslator,
|
|
19920
21568
|
WorkflowOrchestrator,
|
|
21569
|
+
addCustomGuideline,
|
|
21570
|
+
addCustomProfile,
|
|
21571
|
+
addPattern,
|
|
19921
21572
|
addToManifest,
|
|
19922
21573
|
agentExists,
|
|
19923
21574
|
analyzeForPrimer,
|
|
21575
|
+
analyzeGitHistory,
|
|
19924
21576
|
analyzePrimer,
|
|
19925
21577
|
analyzeProject,
|
|
21578
|
+
approvePattern,
|
|
19926
21579
|
benchmarkSkill,
|
|
19927
21580
|
buildSkillIndex,
|
|
19928
21581
|
calculatePercentile,
|
|
19929
21582
|
canTranslate,
|
|
21583
|
+
clusterPatterns,
|
|
19930
21584
|
copilotTranslator,
|
|
19931
21585
|
createAPIBasedCompressor,
|
|
19932
21586
|
createCommandGenerator,
|
|
@@ -19951,6 +21605,7 @@ export {
|
|
|
19951
21605
|
createPluginManager,
|
|
19952
21606
|
createRecommendationEngine,
|
|
19953
21607
|
createRuleBasedCompressor,
|
|
21608
|
+
createSessionFile,
|
|
19954
21609
|
createSessionManager,
|
|
19955
21610
|
createSimulatedSkillExecutor,
|
|
19956
21611
|
createSkillBundle,
|
|
@@ -19966,6 +21621,7 @@ export {
|
|
|
19966
21621
|
detectCategory,
|
|
19967
21622
|
detectProvider,
|
|
19968
21623
|
detectSkillFormat,
|
|
21624
|
+
disableGuideline,
|
|
19969
21625
|
discoverAgents,
|
|
19970
21626
|
discoverAgentsForAgent,
|
|
19971
21627
|
discoverAgentsFromPath,
|
|
@@ -19973,16 +21629,19 @@ export {
|
|
|
19973
21629
|
discoverGlobalAgents,
|
|
19974
21630
|
discoverSkills,
|
|
19975
21631
|
dryRunExecutor,
|
|
21632
|
+
enableGuideline,
|
|
19976
21633
|
estimateTokens,
|
|
19977
21634
|
evaluateSkillContent,
|
|
19978
21635
|
evaluateSkillDirectory,
|
|
19979
21636
|
evaluateSkillFile,
|
|
19980
21637
|
executeWithAgent,
|
|
19981
21638
|
exportBundle,
|
|
21639
|
+
exportPatternsAsJson,
|
|
19982
21640
|
extractAgentContent,
|
|
19983
21641
|
extractAgentFrontmatter,
|
|
19984
21642
|
extractField,
|
|
19985
21643
|
extractFrontmatter,
|
|
21644
|
+
extractPatternsFromSession,
|
|
19986
21645
|
extractSkillMetadata,
|
|
19987
21646
|
fetchSkillsFromRepo,
|
|
19988
21647
|
findAgent,
|
|
@@ -19994,10 +21653,13 @@ export {
|
|
|
19994
21653
|
fromCanonicalAgent,
|
|
19995
21654
|
generateComparisonNotes,
|
|
19996
21655
|
generateManifestFromInstalled,
|
|
21656
|
+
generatePatternReport,
|
|
19997
21657
|
generatePrimer,
|
|
19998
21658
|
generatePrimerForAgent,
|
|
19999
21659
|
generateRecommendations,
|
|
21660
|
+
generateSkillFromPatterns,
|
|
20000
21661
|
generateSkillsConfig,
|
|
21662
|
+
getActiveProfile,
|
|
20001
21663
|
getAgentCLIConfig,
|
|
20002
21664
|
getAgentConfigFile,
|
|
20003
21665
|
getAgentConfigPath,
|
|
@@ -20009,26 +21671,56 @@ export {
|
|
|
20009
21671
|
getAgentTargetDirectory,
|
|
20010
21672
|
getAgentsDirectory,
|
|
20011
21673
|
getAllCategories,
|
|
21674
|
+
getAllGuidelines,
|
|
21675
|
+
getAllPatterns,
|
|
21676
|
+
getAllProfiles,
|
|
20012
21677
|
getAllProviders,
|
|
20013
21678
|
getAllSkillsDirs,
|
|
21679
|
+
getApprovedPatterns,
|
|
20014
21680
|
getAvailableCLIAgents,
|
|
21681
|
+
getBuiltinGuidelines,
|
|
20015
21682
|
getBuiltinPacksDir,
|
|
21683
|
+
getBuiltinPipeline,
|
|
21684
|
+
getBuiltinPipelines,
|
|
21685
|
+
getBuiltinProfiles,
|
|
20016
21686
|
getCICDTemplate,
|
|
20017
21687
|
getCategoryStats,
|
|
20018
21688
|
getConfigFile,
|
|
20019
21689
|
getConfigFormat,
|
|
21690
|
+
getDefaultConfigPath,
|
|
21691
|
+
getDefaultStorePath,
|
|
21692
|
+
getEnabledGuidelineContent,
|
|
21693
|
+
getEnabledGuidelines,
|
|
21694
|
+
getEvolvingPattern,
|
|
21695
|
+
getEvolvingPatternsByDomain,
|
|
20020
21696
|
getExecutionStrategy,
|
|
21697
|
+
getGitCommits,
|
|
20021
21698
|
getGlobalConfigPath,
|
|
20022
21699
|
getGlobalSkillsDir,
|
|
20023
21700
|
getGrade,
|
|
21701
|
+
getGuideline,
|
|
21702
|
+
getGuidelineContent,
|
|
21703
|
+
getGuidelinesByCategory,
|
|
21704
|
+
getHighConfidencePatterns,
|
|
20024
21705
|
getIndexStatus,
|
|
20025
21706
|
getInstallDir,
|
|
21707
|
+
getLowConfidencePatterns,
|
|
20026
21708
|
getManualExecutionInstructions,
|
|
20027
21709
|
getMemoryPaths,
|
|
20028
21710
|
getMemoryStatus,
|
|
21711
|
+
getMostRecentSession,
|
|
21712
|
+
getMostUsedPatterns,
|
|
21713
|
+
getPattern,
|
|
21714
|
+
getPatternStats,
|
|
21715
|
+
getPatternsByCategory,
|
|
21716
|
+
getProfile,
|
|
21717
|
+
getProfileContext,
|
|
21718
|
+
getProfileNames,
|
|
20029
21719
|
getProjectConfigPath,
|
|
20030
21720
|
getProvider,
|
|
20031
21721
|
getQualityGrade,
|
|
21722
|
+
getRecentBugFixes,
|
|
21723
|
+
getRecentRefactors,
|
|
20032
21724
|
getSearchDirs,
|
|
20033
21725
|
getSkillsDir,
|
|
20034
21726
|
getStackTags,
|
|
@@ -20036,31 +21728,42 @@ export {
|
|
|
20036
21728
|
getTechTags,
|
|
20037
21729
|
globalMemoryDirectoryExists,
|
|
20038
21730
|
importBundle,
|
|
21731
|
+
importPatternsFromJson,
|
|
20039
21732
|
initContext,
|
|
20040
21733
|
initManifest,
|
|
20041
21734
|
initProject,
|
|
20042
21735
|
initializeMemoryDirectory,
|
|
20043
21736
|
isAgentCLIAvailable,
|
|
20044
21737
|
isAgentCompatible,
|
|
21738
|
+
isBuiltinGuideline,
|
|
21739
|
+
isBuiltinProfile,
|
|
20045
21740
|
isGitUrl,
|
|
21741
|
+
isGuidelineEnabled,
|
|
20046
21742
|
isHighQuality,
|
|
20047
21743
|
isIndexStale,
|
|
20048
21744
|
isLocalPath,
|
|
20049
21745
|
isPathInside,
|
|
20050
21746
|
listCICDTemplates,
|
|
21747
|
+
listSessions,
|
|
20051
21748
|
listWorkflows,
|
|
20052
21749
|
loadAgentMetadata,
|
|
20053
21750
|
loadConfig,
|
|
20054
21751
|
loadContext,
|
|
21752
|
+
loadGuidelineConfig,
|
|
20055
21753
|
loadIndex,
|
|
21754
|
+
loadLearningConfig,
|
|
20056
21755
|
loadManifest,
|
|
20057
21756
|
loadMetadata,
|
|
21757
|
+
loadPatternStore,
|
|
20058
21758
|
loadPlugin,
|
|
20059
21759
|
loadPluginsFromDirectory,
|
|
21760
|
+
loadProfileConfig,
|
|
21761
|
+
loadSessionFile,
|
|
20060
21762
|
loadSkillMetadata,
|
|
20061
21763
|
loadWorkflow,
|
|
20062
21764
|
loadWorkflowByName,
|
|
20063
21765
|
memoryDirectoryExists,
|
|
21766
|
+
mergePatterns,
|
|
20064
21767
|
parseAgentDir,
|
|
20065
21768
|
parseAgentFile,
|
|
20066
21769
|
parseShorthand,
|
|
@@ -20072,14 +21775,27 @@ export {
|
|
|
20072
21775
|
parseWorkflow,
|
|
20073
21776
|
readAgentContent,
|
|
20074
21777
|
readSkillContent,
|
|
21778
|
+
recordFailure,
|
|
21779
|
+
recordSuccess,
|
|
21780
|
+
rejectPattern,
|
|
21781
|
+
removeCustomGuideline,
|
|
21782
|
+
removeCustomProfile,
|
|
20075
21783
|
removeFromManifest,
|
|
21784
|
+
removePattern,
|
|
20076
21785
|
runTestSuite,
|
|
20077
21786
|
saveConfig,
|
|
21787
|
+
saveGeneratedSkill,
|
|
21788
|
+
saveGuidelineConfig,
|
|
20078
21789
|
saveIndex,
|
|
21790
|
+
saveLearningConfig,
|
|
20079
21791
|
saveManifest,
|
|
21792
|
+
savePatternStore,
|
|
21793
|
+
saveProfileConfig,
|
|
21794
|
+
saveSessionFile,
|
|
20080
21795
|
saveSkillMetadata,
|
|
20081
21796
|
saveWorkflow,
|
|
20082
21797
|
serializeWorkflow,
|
|
21798
|
+
setActiveProfile,
|
|
20083
21799
|
setSkillEnabled,
|
|
20084
21800
|
shellExecutor,
|
|
20085
21801
|
skillMdTranslator,
|
|
@@ -20097,6 +21813,7 @@ export {
|
|
|
20097
21813
|
translateSkillToAgent,
|
|
20098
21814
|
translateSkillToAll,
|
|
20099
21815
|
translatorRegistry,
|
|
21816
|
+
updateSessionFile,
|
|
20100
21817
|
validateAgent,
|
|
20101
21818
|
validateBuiltinPacks,
|
|
20102
21819
|
validatePackDirectory,
|