@skillkit/core 1.6.1 → 1.6.3

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.js CHANGED
@@ -3913,8 +3913,8 @@ async function buildSkillIndex(repos = KNOWN_SKILL_REPOS, onProgress) {
3913
3913
  onProgress?.("No skills fetched, using sample index...");
3914
3914
  allSkills.push(...getSampleSkills());
3915
3915
  sources.push({
3916
- name: "skillkit-samples",
3917
- url: "https://github.com/skillkit/samples",
3916
+ name: "built-in",
3917
+ url: "https://github.com/rohitg00/skillkit",
3918
3918
  lastFetched: (/* @__PURE__ */ new Date()).toISOString(),
3919
3919
  skillCount: allSkills.length
3920
3920
  });
@@ -3960,7 +3960,7 @@ function getSampleSkills() {
3960
3960
  {
3961
3961
  name: "react-best-practices",
3962
3962
  description: "Modern React patterns including Server Components, hooks best practices, and performance optimization",
3963
- source: "skillkit/samples",
3963
+ source: "built-in",
3964
3964
  tags: ["react", "frontend", "typescript", "nextjs", "performance"],
3965
3965
  compatibility: {
3966
3966
  frameworks: ["react", "nextjs"],
@@ -3975,7 +3975,7 @@ function getSampleSkills() {
3975
3975
  {
3976
3976
  name: "tailwind-patterns",
3977
3977
  description: "Tailwind CSS utility patterns, responsive design, and component styling best practices",
3978
- source: "skillkit/samples",
3978
+ source: "built-in",
3979
3979
  tags: ["tailwind", "css", "styling", "frontend", "responsive"],
3980
3980
  compatibility: {
3981
3981
  frameworks: [],
@@ -3990,7 +3990,7 @@ function getSampleSkills() {
3990
3990
  {
3991
3991
  name: "typescript-strict-patterns",
3992
3992
  description: "TypeScript strict mode patterns, type safety, and advanced type utilities",
3993
- source: "skillkit/samples",
3993
+ source: "built-in",
3994
3994
  tags: ["typescript", "types", "safety", "patterns"],
3995
3995
  compatibility: {
3996
3996
  frameworks: [],
@@ -4005,7 +4005,7 @@ function getSampleSkills() {
4005
4005
  {
4006
4006
  name: "security-best-practices",
4007
4007
  description: "Security patterns for web applications including XSS prevention, CSRF, and secure headers",
4008
- source: "skillkit/samples",
4008
+ source: "built-in",
4009
4009
  tags: ["security", "xss", "csrf", "headers", "owasp"],
4010
4010
  compatibility: {
4011
4011
  frameworks: [],
@@ -4020,7 +4020,7 @@ function getSampleSkills() {
4020
4020
  {
4021
4021
  name: "testing-patterns",
4022
4022
  description: "Testing patterns with Vitest/Jest including mocking, assertions, and test organization",
4023
- source: "skillkit/samples",
4023
+ source: "built-in",
4024
4024
  tags: ["vitest", "jest", "testing", "typescript", "mocking", "tdd"],
4025
4025
  compatibility: {
4026
4026
  frameworks: [],
@@ -15782,13 +15782,939 @@ var AuditLogger = class {
15782
15782
  }).join("\n\n");
15783
15783
  }
15784
15784
  };
15785
+
15786
+ // src/agents/types.ts
15787
+ import { z as z5 } from "zod";
15788
+ var AgentPermissionMode = z5.enum([
15789
+ "default",
15790
+ // Normal permission prompts
15791
+ "plan",
15792
+ // Plan mode - ask before executing
15793
+ "auto-edit",
15794
+ // Auto-accept edits
15795
+ "full-auto",
15796
+ // Auto-accept everything (dangerous)
15797
+ "bypassPermissions"
15798
+ // Skip all permission checks
15799
+ ]);
15800
+ var AgentHook = z5.object({
15801
+ /** Hook event type */
15802
+ type: z5.enum([
15803
+ "PreToolUse",
15804
+ "PostToolUse",
15805
+ "Stop",
15806
+ "SubagentStop",
15807
+ "SessionStart",
15808
+ "SessionEnd"
15809
+ ]),
15810
+ /** Command to run */
15811
+ command: z5.string(),
15812
+ /** Timeout in milliseconds */
15813
+ timeout: z5.number().optional(),
15814
+ /** Run only once */
15815
+ once: z5.boolean().optional(),
15816
+ /** Tool matcher (for PreToolUse/PostToolUse) */
15817
+ matcher: z5.string().optional()
15818
+ });
15819
+ var AgentFrontmatter = z5.object({
15820
+ /** Agent name (kebab-case) */
15821
+ name: z5.string().min(1).max(64).regex(/^[a-z0-9]+(-[a-z0-9]+)*$/, "Agent name must be lowercase alphanumeric with hyphens"),
15822
+ /** Description of what this agent does */
15823
+ description: z5.string().min(1).max(1024),
15824
+ /** Model to use (e.g., 'opus', 'sonnet', 'haiku') */
15825
+ model: z5.string().optional(),
15826
+ /** Permission mode for this agent */
15827
+ permissionMode: AgentPermissionMode.optional(),
15828
+ /** Tools this agent cannot use */
15829
+ disallowedTools: z5.array(z5.string()).optional(),
15830
+ /** Allowed tools for this agent */
15831
+ allowedTools: z5.union([
15832
+ z5.array(z5.string()),
15833
+ z5.string()
15834
+ // YAML-style list in frontmatter
15835
+ ]).optional(),
15836
+ /** Agent-scoped hooks */
15837
+ hooks: z5.array(AgentHook).optional(),
15838
+ /** Skills to auto-load for this agent */
15839
+ skills: z5.array(z5.string()).optional(),
15840
+ /** Run in forked sub-agent context */
15841
+ context: z5.enum(["fork", "inline"]).optional(),
15842
+ /** Version */
15843
+ version: z5.string().optional(),
15844
+ /** Author */
15845
+ author: z5.string().optional(),
15846
+ /** Tags for categorization */
15847
+ tags: z5.array(z5.string()).optional(),
15848
+ /** Whether agent is user-invocable via @mention */
15849
+ "user-invocable": z5.boolean().optional(),
15850
+ /** Argument hint for agent invocation */
15851
+ "argument-hint": z5.string().optional()
15852
+ });
15853
+ var AgentLocation = z5.enum(["project", "global"]);
15854
+ var AgentMetadata = z5.object({
15855
+ name: z5.string(),
15856
+ description: z5.string(),
15857
+ source: z5.string(),
15858
+ sourceType: z5.enum(["github", "gitlab", "bitbucket", "local"]),
15859
+ subpath: z5.string().optional(),
15860
+ installedAt: z5.string().datetime(),
15861
+ updatedAt: z5.string().datetime().optional(),
15862
+ enabled: z5.boolean().default(true),
15863
+ version: z5.string().optional(),
15864
+ checksum: z5.string().optional()
15865
+ });
15866
+ var AGENT_DISCOVERY_PATHS = {
15867
+ "claude-code": [".claude/agents"],
15868
+ "cursor": [".cursor/agents"],
15869
+ "codex": [".codex/agents"],
15870
+ "gemini-cli": [".gemini/agents"],
15871
+ "opencode": [".opencode/agents"],
15872
+ "antigravity": [".antigravity/agents"],
15873
+ "amp": [".amp/agents"],
15874
+ "clawdbot": [".clawdbot/agents", "agents"],
15875
+ "droid": [".factory/agents"],
15876
+ "github-copilot": [".github/agents", ".github/copilot/agents"],
15877
+ "goose": [".goose/agents"],
15878
+ "kilo": [".kilocode/agents"],
15879
+ "kiro-cli": [".kiro/agents"],
15880
+ "roo": [".roo/agents"],
15881
+ "trae": [".trae/agents"],
15882
+ "windsurf": [".windsurf/agents"],
15883
+ "universal": ["agents", ".agents"]
15884
+ };
15885
+ var ALL_AGENT_DISCOVERY_PATHS = [
15886
+ "agents",
15887
+ ".agents",
15888
+ ".claude/agents",
15889
+ ".cursor/agents",
15890
+ ".codex/agents",
15891
+ ".gemini/agents",
15892
+ ".opencode/agents",
15893
+ ".antigravity/agents",
15894
+ ".amp/agents",
15895
+ ".clawdbot/agents",
15896
+ ".factory/agents",
15897
+ ".github/agents",
15898
+ ".github/copilot/agents",
15899
+ ".goose/agents",
15900
+ ".kilocode/agents",
15901
+ ".kiro/agents",
15902
+ ".roo/agents",
15903
+ ".trae/agents",
15904
+ ".windsurf/agents"
15905
+ ];
15906
+ var CUSTOM_AGENT_FORMAT_MAP = {
15907
+ "claude-code": "claude-agent",
15908
+ "cursor": "cursor-agent",
15909
+ "codex": "claude-agent",
15910
+ "gemini-cli": "claude-agent",
15911
+ "opencode": "claude-agent",
15912
+ "antigravity": "claude-agent",
15913
+ "amp": "claude-agent",
15914
+ "clawdbot": "claude-agent",
15915
+ "droid": "claude-agent",
15916
+ "github-copilot": "universal",
15917
+ "goose": "claude-agent",
15918
+ "kilo": "claude-agent",
15919
+ "kiro-cli": "claude-agent",
15920
+ "roo": "claude-agent",
15921
+ "trae": "claude-agent",
15922
+ "windsurf": "universal",
15923
+ "universal": "universal"
15924
+ };
15925
+
15926
+ // src/agents/parser.ts
15927
+ import { existsSync as existsSync30, readFileSync as readFileSync23, statSync as statSync7 } from "fs";
15928
+ import { join as join30, basename as basename10, extname as extname2 } from "path";
15929
+ import { parse as parseYaml10 } from "yaml";
15930
+ function extractAgentFrontmatter(content) {
15931
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
15932
+ if (!match) {
15933
+ return null;
15934
+ }
15935
+ try {
15936
+ return parseYaml10(match[1]);
15937
+ } catch {
15938
+ return null;
15939
+ }
15940
+ }
15941
+ function extractAgentContent(content) {
15942
+ const withoutFrontmatter = content.replace(/^---\s*\n[\s\S]*?\n---\s*\n?/, "");
15943
+ return withoutFrontmatter.trim();
15944
+ }
15945
+ function parseAgentFile(filePath, location = "project") {
15946
+ if (!existsSync30(filePath)) {
15947
+ return null;
15948
+ }
15949
+ if (extname2(filePath) !== ".md") {
15950
+ return null;
15951
+ }
15952
+ try {
15953
+ const content = readFileSync23(filePath, "utf-8");
15954
+ const rawFrontmatter = extractAgentFrontmatter(content);
15955
+ const agentContent = extractAgentContent(content);
15956
+ if (!rawFrontmatter) {
15957
+ const name = basename10(filePath, ".md");
15958
+ return {
15959
+ name,
15960
+ description: "No description available",
15961
+ path: filePath,
15962
+ location,
15963
+ frontmatter: {
15964
+ name,
15965
+ description: "No description available"
15966
+ },
15967
+ content: agentContent,
15968
+ enabled: true
15969
+ };
15970
+ }
15971
+ const parsed = AgentFrontmatter.safeParse(rawFrontmatter);
15972
+ if (!parsed.success) {
15973
+ const name = rawFrontmatter.name || basename10(filePath, ".md");
15974
+ return {
15975
+ name,
15976
+ description: rawFrontmatter.description || "No description available",
15977
+ path: filePath,
15978
+ location,
15979
+ frontmatter: {
15980
+ name,
15981
+ description: rawFrontmatter.description || "No description available",
15982
+ ...rawFrontmatter
15983
+ },
15984
+ content: agentContent,
15985
+ enabled: true
15986
+ };
15987
+ }
15988
+ const metadataPath = filePath.replace(/\.md$/, ".skillkit-agent.json");
15989
+ const metadata = loadAgentMetadata(metadataPath);
15990
+ return {
15991
+ name: parsed.data.name,
15992
+ description: parsed.data.description,
15993
+ path: filePath,
15994
+ location,
15995
+ frontmatter: parsed.data,
15996
+ content: agentContent,
15997
+ metadata: metadata ?? void 0,
15998
+ enabled: metadata?.enabled ?? true
15999
+ };
16000
+ } catch {
16001
+ return null;
16002
+ }
16003
+ }
16004
+ function parseAgentDir(dirPath, location = "project") {
16005
+ const agentMdPath = join30(dirPath, "AGENT.md");
16006
+ if (existsSync30(agentMdPath)) {
16007
+ const agent = parseAgentFile(agentMdPath, location);
16008
+ if (agent) {
16009
+ agent.path = dirPath;
16010
+ }
16011
+ return agent;
16012
+ }
16013
+ const indexMdPath = join30(dirPath, "index.md");
16014
+ if (existsSync30(indexMdPath)) {
16015
+ const agent = parseAgentFile(indexMdPath, location);
16016
+ if (agent) {
16017
+ agent.path = dirPath;
16018
+ }
16019
+ return agent;
16020
+ }
16021
+ return null;
16022
+ }
16023
+ function loadAgentMetadata(metadataPath) {
16024
+ if (!existsSync30(metadataPath)) {
16025
+ return null;
16026
+ }
16027
+ try {
16028
+ const content = readFileSync23(metadataPath, "utf-8");
16029
+ const data = JSON.parse(content);
16030
+ const parsed = AgentMetadata.safeParse(data);
16031
+ return parsed.success ? parsed.data : null;
16032
+ } catch {
16033
+ return null;
16034
+ }
16035
+ }
16036
+ function toCanonicalAgent(agent, sourceAgent) {
16037
+ const fm = agent.frontmatter;
16038
+ let allowedTools;
16039
+ if (fm.allowedTools) {
16040
+ if (typeof fm.allowedTools === "string") {
16041
+ allowedTools = fm.allowedTools.split(/[,\n]/).map((t) => t.trim()).filter(Boolean);
16042
+ } else {
16043
+ allowedTools = fm.allowedTools;
16044
+ }
16045
+ }
16046
+ return {
16047
+ name: agent.name,
16048
+ description: agent.description,
16049
+ model: fm.model,
16050
+ permissionMode: fm.permissionMode,
16051
+ disallowedTools: fm.disallowedTools,
16052
+ allowedTools,
16053
+ hooks: fm.hooks,
16054
+ skills: fm.skills,
16055
+ context: fm.context,
16056
+ version: fm.version,
16057
+ author: fm.author,
16058
+ tags: fm.tags,
16059
+ userInvocable: fm["user-invocable"],
16060
+ argumentHint: fm["argument-hint"],
16061
+ content: agent.content,
16062
+ sourceFormat: "claude-agent",
16063
+ sourceAgent
16064
+ };
16065
+ }
16066
+ function fromCanonicalAgent(canonical, _targetFormat = "claude-agent") {
16067
+ const lines = [];
16068
+ lines.push("---");
16069
+ lines.push(`name: ${canonical.name}`);
16070
+ lines.push(`description: ${canonical.description}`);
16071
+ if (canonical.model) {
16072
+ lines.push(`model: ${canonical.model}`);
16073
+ }
16074
+ if (canonical.permissionMode) {
16075
+ lines.push(`permissionMode: ${canonical.permissionMode}`);
16076
+ }
16077
+ if (canonical.disallowedTools && canonical.disallowedTools.length > 0) {
16078
+ lines.push("disallowedTools:");
16079
+ for (const tool of canonical.disallowedTools) {
16080
+ lines.push(` - ${tool}`);
16081
+ }
16082
+ }
16083
+ if (canonical.allowedTools && canonical.allowedTools.length > 0) {
16084
+ lines.push("allowed-tools:");
16085
+ for (const tool of canonical.allowedTools) {
16086
+ lines.push(` - ${tool}`);
16087
+ }
16088
+ }
16089
+ if (canonical.hooks && canonical.hooks.length > 0) {
16090
+ lines.push("hooks:");
16091
+ for (const hook of canonical.hooks) {
16092
+ lines.push(` - type: ${hook.type}`);
16093
+ lines.push(` command: ${hook.command}`);
16094
+ if (hook.timeout) lines.push(` timeout: ${hook.timeout}`);
16095
+ if (hook.once) lines.push(` once: ${hook.once}`);
16096
+ if (hook.matcher) lines.push(` matcher: ${hook.matcher}`);
16097
+ }
16098
+ }
16099
+ if (canonical.skills && canonical.skills.length > 0) {
16100
+ lines.push("skills:");
16101
+ for (const skill of canonical.skills) {
16102
+ lines.push(` - ${skill}`);
16103
+ }
16104
+ }
16105
+ if (canonical.context) {
16106
+ lines.push(`context: ${canonical.context}`);
16107
+ }
16108
+ if (canonical.version) {
16109
+ lines.push(`version: "${canonical.version}"`);
16110
+ }
16111
+ if (canonical.author) {
16112
+ lines.push(`author: ${canonical.author}`);
16113
+ }
16114
+ if (canonical.tags && canonical.tags.length > 0) {
16115
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16116
+ }
16117
+ if (canonical.userInvocable !== void 0) {
16118
+ lines.push(`user-invocable: ${canonical.userInvocable}`);
16119
+ }
16120
+ if (canonical.argumentHint) {
16121
+ lines.push(`argument-hint: "${canonical.argumentHint}"`);
16122
+ }
16123
+ lines.push("---");
16124
+ lines.push("");
16125
+ lines.push(canonical.content);
16126
+ return lines.join("\n");
16127
+ }
16128
+ function readAgentContent(agentPath) {
16129
+ if (existsSync30(agentPath) && extname2(agentPath) === ".md") {
16130
+ try {
16131
+ return readFileSync23(agentPath, "utf-8");
16132
+ } catch {
16133
+ return null;
16134
+ }
16135
+ }
16136
+ const agentMdPath = join30(agentPath, "AGENT.md");
16137
+ if (existsSync30(agentMdPath)) {
16138
+ try {
16139
+ return readFileSync23(agentMdPath, "utf-8");
16140
+ } catch {
16141
+ return null;
16142
+ }
16143
+ }
16144
+ const indexMdPath = join30(agentPath, "index.md");
16145
+ if (existsSync30(indexMdPath)) {
16146
+ try {
16147
+ return readFileSync23(indexMdPath, "utf-8");
16148
+ } catch {
16149
+ return null;
16150
+ }
16151
+ }
16152
+ return null;
16153
+ }
16154
+ function validateAgent(agentPath) {
16155
+ const errors = [];
16156
+ const warnings = [];
16157
+ let filePath = agentPath;
16158
+ if (!existsSync30(agentPath)) {
16159
+ errors.push(`Agent file not found: ${agentPath}`);
16160
+ return { valid: false, errors, warnings };
16161
+ }
16162
+ const stats = statSync7(agentPath);
16163
+ if (stats.isDirectory()) {
16164
+ const agentMd = join30(agentPath, "AGENT.md");
16165
+ const indexMd = join30(agentPath, "index.md");
16166
+ if (existsSync30(agentMd)) {
16167
+ filePath = agentMd;
16168
+ } else if (existsSync30(indexMd)) {
16169
+ filePath = indexMd;
16170
+ } else {
16171
+ errors.push("Directory must contain AGENT.md or index.md");
16172
+ return { valid: false, errors, warnings };
16173
+ }
16174
+ }
16175
+ let content;
16176
+ try {
16177
+ content = readFileSync23(filePath, "utf-8");
16178
+ } catch {
16179
+ errors.push(`Cannot read file: ${filePath}`);
16180
+ return { valid: false, errors, warnings };
16181
+ }
16182
+ const frontmatter = extractAgentFrontmatter(content);
16183
+ if (!frontmatter) {
16184
+ errors.push("Missing YAML frontmatter");
16185
+ return { valid: false, errors, warnings };
16186
+ }
16187
+ const parsed = AgentFrontmatter.safeParse(frontmatter);
16188
+ if (!parsed.success) {
16189
+ for (const issue of parsed.error.issues) {
16190
+ errors.push(`${issue.path.join(".") || "frontmatter"}: ${issue.message}`);
16191
+ }
16192
+ }
16193
+ if (parsed.success) {
16194
+ const data = parsed.data;
16195
+ const fileName = basename10(filePath, ".md");
16196
+ if (data.name !== fileName && fileName !== "AGENT" && fileName !== "index") {
16197
+ warnings.push(`name "${data.name}" does not match filename "${fileName}"`);
16198
+ }
16199
+ if (data.description && data.description.length < 20) {
16200
+ warnings.push("description is short; consider adding more detail");
16201
+ }
16202
+ if (data.permissionMode === "full-auto" || data.permissionMode === "bypassPermissions") {
16203
+ warnings.push(`permissionMode "${data.permissionMode}" is potentially dangerous`);
16204
+ }
16205
+ }
16206
+ const agentContent = extractAgentContent(content);
16207
+ if (agentContent.length < 50) {
16208
+ warnings.push("Agent system prompt is very short");
16209
+ }
16210
+ return { valid: errors.length === 0, errors, warnings };
16211
+ }
16212
+
16213
+ // src/agents/discovery.ts
16214
+ import { existsSync as existsSync31, readdirSync as readdirSync9, statSync as statSync8 } from "fs";
16215
+ import { join as join31, extname as extname3 } from "path";
16216
+ import { homedir as homedir9 } from "os";
16217
+ function discoverAgentsInDir(dir, location) {
16218
+ const agents = [];
16219
+ if (!existsSync31(dir)) {
16220
+ return agents;
16221
+ }
16222
+ try {
16223
+ const entries = readdirSync9(dir, { withFileTypes: true });
16224
+ for (const entry of entries) {
16225
+ const entryPath = join31(dir, entry.name);
16226
+ if (entry.isFile() && extname3(entry.name) === ".md") {
16227
+ const agent = parseAgentFile(entryPath, location);
16228
+ if (agent) {
16229
+ agents.push(agent);
16230
+ }
16231
+ } else if (entry.isDirectory()) {
16232
+ const agent = parseAgentDir(entryPath, location);
16233
+ if (agent) {
16234
+ agents.push(agent);
16235
+ }
16236
+ }
16237
+ }
16238
+ } catch {
16239
+ }
16240
+ return agents;
16241
+ }
16242
+ function discoverAgents(rootDir) {
16243
+ const agents = [];
16244
+ const seen = /* @__PURE__ */ new Set();
16245
+ for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
16246
+ const fullPath = join31(rootDir, searchPath);
16247
+ if (existsSync31(fullPath)) {
16248
+ for (const agent of discoverAgentsInDir(fullPath, "project")) {
16249
+ if (!seen.has(agent.name)) {
16250
+ seen.add(agent.name);
16251
+ agents.push(agent);
16252
+ }
16253
+ }
16254
+ }
16255
+ }
16256
+ return agents;
16257
+ }
16258
+ function discoverAgentsForAgent(rootDir, agentType) {
16259
+ const agents = [];
16260
+ const seen = /* @__PURE__ */ new Set();
16261
+ const paths = AGENT_DISCOVERY_PATHS[agentType] || [];
16262
+ for (const searchPath of paths) {
16263
+ const fullPath = join31(rootDir, searchPath);
16264
+ if (existsSync31(fullPath)) {
16265
+ for (const agent of discoverAgentsInDir(fullPath, "project")) {
16266
+ if (!seen.has(agent.name)) {
16267
+ seen.add(agent.name);
16268
+ agents.push(agent);
16269
+ }
16270
+ }
16271
+ }
16272
+ }
16273
+ return agents;
16274
+ }
16275
+ function discoverGlobalAgents() {
16276
+ const agents = [];
16277
+ const seen = /* @__PURE__ */ new Set();
16278
+ const home = homedir9();
16279
+ const globalPaths = [
16280
+ join31(home, ".claude", "agents"),
16281
+ join31(home, ".skillkit", "agents"),
16282
+ join31(home, ".config", "skillkit", "agents")
16283
+ ];
16284
+ for (const searchPath of globalPaths) {
16285
+ if (existsSync31(searchPath)) {
16286
+ for (const agent of discoverAgentsInDir(searchPath, "global")) {
16287
+ if (!seen.has(agent.name)) {
16288
+ seen.add(agent.name);
16289
+ agents.push(agent);
16290
+ }
16291
+ }
16292
+ }
16293
+ }
16294
+ return agents;
16295
+ }
16296
+ function findAllAgents(searchDirs) {
16297
+ const agents = [];
16298
+ const seen = /* @__PURE__ */ new Set();
16299
+ for (const dir of searchDirs) {
16300
+ if (!existsSync31(dir)) continue;
16301
+ const discovered = discoverAgents(dir);
16302
+ for (const agent of discovered) {
16303
+ if (!seen.has(agent.name)) {
16304
+ seen.add(agent.name);
16305
+ agents.push(agent);
16306
+ }
16307
+ }
16308
+ }
16309
+ for (const agent of discoverGlobalAgents()) {
16310
+ if (!seen.has(agent.name)) {
16311
+ seen.add(agent.name);
16312
+ agents.push(agent);
16313
+ }
16314
+ }
16315
+ return agents;
16316
+ }
16317
+ function findAgent(name, searchDirs) {
16318
+ for (const dir of searchDirs) {
16319
+ if (!existsSync31(dir)) continue;
16320
+ for (const searchPath of ALL_AGENT_DISCOVERY_PATHS) {
16321
+ const agentsDir = join31(dir, searchPath);
16322
+ if (!existsSync31(agentsDir)) continue;
16323
+ const agentFile = join31(agentsDir, `${name}.md`);
16324
+ if (existsSync31(agentFile)) {
16325
+ return parseAgentFile(agentFile, "project");
16326
+ }
16327
+ const agentDir = join31(agentsDir, name);
16328
+ if (existsSync31(agentDir) && statSync8(agentDir).isDirectory()) {
16329
+ return parseAgentDir(agentDir, "project");
16330
+ }
16331
+ }
16332
+ }
16333
+ const home = homedir9();
16334
+ const globalPaths = [
16335
+ join31(home, ".claude", "agents"),
16336
+ join31(home, ".skillkit", "agents")
16337
+ ];
16338
+ for (const agentsDir of globalPaths) {
16339
+ if (!existsSync31(agentsDir)) continue;
16340
+ const agentFile = join31(agentsDir, `${name}.md`);
16341
+ if (existsSync31(agentFile)) {
16342
+ return parseAgentFile(agentFile, "global");
16343
+ }
16344
+ const agentDir = join31(agentsDir, name);
16345
+ if (existsSync31(agentDir) && statSync8(agentDir).isDirectory()) {
16346
+ return parseAgentDir(agentDir, "global");
16347
+ }
16348
+ }
16349
+ return null;
16350
+ }
16351
+ function getAgentsDirectory(rootDir, agentType) {
16352
+ const paths = AGENT_DISCOVERY_PATHS[agentType];
16353
+ if (paths && paths.length > 0) {
16354
+ return join31(rootDir, paths[0]);
16355
+ }
16356
+ return join31(rootDir, "agents");
16357
+ }
16358
+ function agentExists(name, searchDirs) {
16359
+ return findAgent(name, searchDirs) !== null;
16360
+ }
16361
+ function getAgentStats(searchDirs) {
16362
+ const allAgents = findAllAgents(searchDirs);
16363
+ return {
16364
+ total: allAgents.length,
16365
+ project: allAgents.filter((a) => a.location === "project").length,
16366
+ global: allAgents.filter((a) => a.location === "global").length,
16367
+ enabled: allAgents.filter((a) => a.enabled).length,
16368
+ disabled: allAgents.filter((a) => !a.enabled).length
16369
+ };
16370
+ }
16371
+ function discoverAgentsRecursive(rootDir, location = "project") {
16372
+ const agents = [];
16373
+ const seen = /* @__PURE__ */ new Set();
16374
+ if (!existsSync31(rootDir)) {
16375
+ return agents;
16376
+ }
16377
+ function scanDirectory(dir) {
16378
+ try {
16379
+ const entries = readdirSync9(dir, { withFileTypes: true });
16380
+ for (const entry of entries) {
16381
+ const entryPath = join31(dir, entry.name);
16382
+ if (entry.isFile() && extname3(entry.name) === ".md") {
16383
+ const agent = parseAgentFile(entryPath, location);
16384
+ if (agent && !seen.has(agent.name)) {
16385
+ seen.add(agent.name);
16386
+ agents.push(agent);
16387
+ }
16388
+ } else if (entry.isDirectory()) {
16389
+ if (entry.name.startsWith(".") && !entry.name.startsWith(".claude") && !entry.name.startsWith(".cursor") && !entry.name.startsWith(".codex")) {
16390
+ continue;
16391
+ }
16392
+ const agent = parseAgentDir(entryPath, location);
16393
+ if (agent && !seen.has(agent.name)) {
16394
+ seen.add(agent.name);
16395
+ agents.push(agent);
16396
+ } else {
16397
+ scanDirectory(entryPath);
16398
+ }
16399
+ }
16400
+ }
16401
+ } catch {
16402
+ }
16403
+ }
16404
+ scanDirectory(rootDir);
16405
+ return agents;
16406
+ }
16407
+ function discoverAgentsFromPath(sourcePath, recursive = false, location = "project") {
16408
+ if (!existsSync31(sourcePath)) {
16409
+ return [];
16410
+ }
16411
+ const stats = statSync8(sourcePath);
16412
+ if (stats.isFile()) {
16413
+ if (extname3(sourcePath) === ".md") {
16414
+ const agent = parseAgentFile(sourcePath, location);
16415
+ return agent ? [agent] : [];
16416
+ }
16417
+ return [];
16418
+ }
16419
+ if (stats.isDirectory()) {
16420
+ if (recursive) {
16421
+ return discoverAgentsRecursive(sourcePath, location);
16422
+ }
16423
+ const agent = parseAgentDir(sourcePath, location);
16424
+ if (agent) {
16425
+ return [agent];
16426
+ }
16427
+ const agents = [];
16428
+ try {
16429
+ const entries = readdirSync9(sourcePath, { withFileTypes: true });
16430
+ for (const entry of entries) {
16431
+ const entryPath = join31(sourcePath, entry.name);
16432
+ if (entry.isFile() && extname3(entry.name) === ".md") {
16433
+ const a = parseAgentFile(entryPath, location);
16434
+ if (a) agents.push(a);
16435
+ } else if (entry.isDirectory()) {
16436
+ const a = parseAgentDir(entryPath, location);
16437
+ if (a) agents.push(a);
16438
+ }
16439
+ }
16440
+ } catch {
16441
+ }
16442
+ return agents;
16443
+ }
16444
+ return [];
16445
+ }
16446
+
16447
+ // src/agents/translator.ts
16448
+ import { join as join32 } from "path";
16449
+ function translateAgent(agent, targetAgent, options) {
16450
+ const canonical = toCanonicalAgent(agent);
16451
+ return translateCanonicalAgent(canonical, targetAgent, options);
16452
+ }
16453
+ function translateCanonicalAgent(canonical, targetAgent, options) {
16454
+ const targetFormat = CUSTOM_AGENT_FORMAT_MAP[targetAgent];
16455
+ const warnings = [];
16456
+ const incompatible = [];
16457
+ if (targetFormat === "universal") {
16458
+ if (canonical.hooks && canonical.hooks.length > 0) {
16459
+ incompatible.push("hooks (not supported in universal format)");
16460
+ }
16461
+ if (canonical.permissionMode) {
16462
+ incompatible.push("permissionMode (not supported in universal format)");
16463
+ }
16464
+ }
16465
+ if (targetFormat === "cursor-agent") {
16466
+ if (canonical.hooks && canonical.hooks.length > 0) {
16467
+ warnings.push("Hooks may require manual adjustment for Cursor");
16468
+ }
16469
+ }
16470
+ let content;
16471
+ switch (targetFormat) {
16472
+ case "claude-agent":
16473
+ content = generateClaudeAgent(canonical, options);
16474
+ break;
16475
+ case "cursor-agent":
16476
+ content = generateCursorAgent(canonical, options);
16477
+ break;
16478
+ case "universal":
16479
+ content = generateUniversalAgent(canonical, options);
16480
+ break;
16481
+ default:
16482
+ content = fromCanonicalAgent(canonical, targetFormat);
16483
+ }
16484
+ const filename = options?.outputFilename || getAgentFilename(canonical.name, targetAgent);
16485
+ return {
16486
+ success: true,
16487
+ content,
16488
+ filename,
16489
+ warnings,
16490
+ incompatible,
16491
+ targetFormat,
16492
+ targetAgent
16493
+ };
16494
+ }
16495
+ function translateAgentContent(content, _sourceAgent, targetAgent, options) {
16496
+ const agent = parseAgentFromContent(content);
16497
+ if (!agent) {
16498
+ return {
16499
+ success: false,
16500
+ content: "",
16501
+ filename: "",
16502
+ warnings: ["Failed to parse agent content"],
16503
+ incompatible: [],
16504
+ targetFormat: CUSTOM_AGENT_FORMAT_MAP[targetAgent],
16505
+ targetAgent
16506
+ };
16507
+ }
16508
+ return translateAgent(agent, targetAgent, options);
16509
+ }
16510
+ function parseAgentFromContent(content) {
16511
+ const rawFrontmatter = extractAgentFrontmatter(content);
16512
+ const agentContent = extractAgentContent(content);
16513
+ if (!rawFrontmatter) {
16514
+ return null;
16515
+ }
16516
+ const parsed = AgentFrontmatter.safeParse(rawFrontmatter);
16517
+ const frontmatter = parsed.success ? parsed.data : {
16518
+ name: rawFrontmatter.name || "unnamed-agent",
16519
+ description: rawFrontmatter.description || "No description",
16520
+ ...rawFrontmatter
16521
+ };
16522
+ return {
16523
+ name: frontmatter.name,
16524
+ description: frontmatter.description,
16525
+ path: "",
16526
+ location: "project",
16527
+ frontmatter,
16528
+ content: agentContent,
16529
+ enabled: true
16530
+ };
16531
+ }
16532
+ function generateClaudeAgent(canonical, options) {
16533
+ const lines = [];
16534
+ lines.push("---");
16535
+ lines.push(`name: ${canonical.name}`);
16536
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16537
+ if (canonical.model) {
16538
+ lines.push(`model: ${canonical.model}`);
16539
+ }
16540
+ if (canonical.permissionMode) {
16541
+ lines.push(`permissionMode: ${canonical.permissionMode}`);
16542
+ }
16543
+ if (canonical.disallowedTools && canonical.disallowedTools.length > 0) {
16544
+ lines.push("disallowedTools:");
16545
+ for (const tool of canonical.disallowedTools) {
16546
+ lines.push(` - ${tool}`);
16547
+ }
16548
+ }
16549
+ if (canonical.allowedTools && canonical.allowedTools.length > 0) {
16550
+ lines.push("allowed-tools:");
16551
+ for (const tool of canonical.allowedTools) {
16552
+ lines.push(` - ${tool}`);
16553
+ }
16554
+ }
16555
+ if (canonical.hooks && canonical.hooks.length > 0) {
16556
+ lines.push("hooks:");
16557
+ for (const hook of canonical.hooks) {
16558
+ lines.push(` - type: ${hook.type}`);
16559
+ lines.push(` command: "${escapeYamlString(hook.command)}"`);
16560
+ if (hook.timeout) lines.push(` timeout: ${hook.timeout}`);
16561
+ if (hook.once) lines.push(` once: true`);
16562
+ if (hook.matcher) lines.push(` matcher: "${hook.matcher}"`);
16563
+ }
16564
+ }
16565
+ if (canonical.skills && canonical.skills.length > 0) {
16566
+ lines.push("skills:");
16567
+ for (const skill of canonical.skills) {
16568
+ lines.push(` - ${skill}`);
16569
+ }
16570
+ }
16571
+ if (canonical.context) {
16572
+ lines.push(`context: ${canonical.context}`);
16573
+ }
16574
+ if (canonical.version) {
16575
+ lines.push(`version: "${canonical.version}"`);
16576
+ }
16577
+ if (canonical.author) {
16578
+ lines.push(`author: ${canonical.author}`);
16579
+ }
16580
+ if (canonical.tags && canonical.tags.length > 0) {
16581
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16582
+ }
16583
+ if (canonical.userInvocable !== void 0) {
16584
+ lines.push(`user-invocable: ${canonical.userInvocable}`);
16585
+ }
16586
+ if (canonical.argumentHint) {
16587
+ lines.push(`argument-hint: "${escapeYamlString(canonical.argumentHint)}"`);
16588
+ }
16589
+ if (options?.addMetadata) {
16590
+ lines.push(`# Translated by SkillKit from ${canonical.sourceAgent || "unknown"}`);
16591
+ }
16592
+ lines.push("---");
16593
+ lines.push("");
16594
+ lines.push(canonical.content);
16595
+ return lines.join("\n");
16596
+ }
16597
+ function generateCursorAgent(canonical, options) {
16598
+ const lines = [];
16599
+ lines.push("---");
16600
+ lines.push(`name: ${canonical.name}`);
16601
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16602
+ if (canonical.model) {
16603
+ lines.push(`model: ${canonical.model}`);
16604
+ }
16605
+ if (canonical.allowedTools && canonical.allowedTools.length > 0) {
16606
+ lines.push(`tools: [${canonical.allowedTools.join(", ")}]`);
16607
+ }
16608
+ if (canonical.version) {
16609
+ lines.push(`version: "${canonical.version}"`);
16610
+ }
16611
+ if (canonical.tags && canonical.tags.length > 0) {
16612
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16613
+ }
16614
+ if (options?.addMetadata) {
16615
+ lines.push(`# Translated by SkillKit from ${canonical.sourceAgent || "unknown"}`);
16616
+ }
16617
+ lines.push("---");
16618
+ lines.push("");
16619
+ lines.push(canonical.content);
16620
+ if (canonical.hooks && canonical.hooks.length > 0) {
16621
+ lines.push("");
16622
+ lines.push("<!-- Note: Hooks from original agent may need manual configuration -->");
16623
+ }
16624
+ return lines.join("\n");
16625
+ }
16626
+ function generateUniversalAgent(canonical, options) {
16627
+ const lines = [];
16628
+ lines.push("---");
16629
+ lines.push(`name: ${canonical.name}`);
16630
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16631
+ if (canonical.model) {
16632
+ lines.push(`model: ${canonical.model}`);
16633
+ }
16634
+ if (canonical.version) {
16635
+ lines.push(`version: "${canonical.version}"`);
16636
+ }
16637
+ if (canonical.author) {
16638
+ lines.push(`author: ${canonical.author}`);
16639
+ }
16640
+ if (canonical.tags && canonical.tags.length > 0) {
16641
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16642
+ }
16643
+ if (options?.addMetadata) {
16644
+ lines.push(`# Translated by SkillKit`);
16645
+ if (canonical.sourceAgent) {
16646
+ lines.push(`# Original format: ${canonical.sourceAgent}`);
16647
+ }
16648
+ }
16649
+ lines.push("---");
16650
+ lines.push("");
16651
+ lines.push(`# ${canonical.name}`);
16652
+ lines.push("");
16653
+ lines.push(canonical.content);
16654
+ return lines.join("\n");
16655
+ }
16656
+ function getAgentFilename(agentName, targetAgent) {
16657
+ const format = CUSTOM_AGENT_FORMAT_MAP[targetAgent];
16658
+ switch (format) {
16659
+ case "cursor-agent":
16660
+ return `${agentName}.md`;
16661
+ // Or .mdc if Cursor uses that for agents
16662
+ default:
16663
+ return `${agentName}.md`;
16664
+ }
16665
+ }
16666
+ function getAgentTargetDirectory(rootDir, targetAgent) {
16667
+ const paths = AGENT_DISCOVERY_PATHS[targetAgent];
16668
+ if (paths && paths.length > 0) {
16669
+ return join32(rootDir, paths[0]);
16670
+ }
16671
+ return join32(rootDir, "agents");
16672
+ }
16673
+ function escapeYamlString(str) {
16674
+ if (/[:\{\}\[\],&*#?|\-<>=!%@`]/.test(str) || str.includes("\n")) {
16675
+ return `"${str.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
16676
+ }
16677
+ return str;
16678
+ }
16679
+ function translateAgents(agents, targetAgent, options) {
16680
+ return agents.map((agent) => translateAgent(agent, targetAgent, options));
16681
+ }
16682
+ function isAgentCompatible(sourceFormat, targetFormat) {
16683
+ const warnings = [];
16684
+ if (sourceFormat === targetFormat) {
16685
+ return { compatible: true, warnings };
16686
+ }
16687
+ if (targetFormat === "claude-agent") {
16688
+ return { compatible: true, warnings };
16689
+ }
16690
+ if (targetFormat === "universal") {
16691
+ if (sourceFormat === "claude-agent") {
16692
+ warnings.push("Hooks, permissionMode, and disallowedTools will be lost");
16693
+ }
16694
+ return { compatible: true, warnings };
16695
+ }
16696
+ if (targetFormat === "cursor-agent") {
16697
+ if (sourceFormat === "claude-agent") {
16698
+ warnings.push("Some Claude-specific features may not translate perfectly");
16699
+ }
16700
+ return { compatible: true, warnings };
16701
+ }
16702
+ return { compatible: true, warnings };
16703
+ }
15785
16704
  export {
15786
16705
  AGENT_CLI_CONFIGS,
16706
+ AGENT_DISCOVERY_PATHS,
15787
16707
  AGENT_FORMAT_MAP,
15788
16708
  AIManager,
15789
16709
  AISearch,
15790
16710
  AISkillGenerator,
16711
+ ALL_AGENT_DISCOVERY_PATHS,
15791
16712
  APIBasedCompressor,
16713
+ AgentFrontmatter,
16714
+ AgentHook,
16715
+ AgentLocation,
16716
+ AgentMetadata,
16717
+ AgentPermissionMode,
15792
16718
  AgentType,
15793
16719
  AuditLogger,
15794
16720
  BaseAIProvider,
@@ -15796,6 +16722,7 @@ export {
15796
16722
  CIRCLECI_CONFIG_TEMPLATE,
15797
16723
  CONTEXT_DIR,
15798
16724
  CONTEXT_FILE,
16725
+ CUSTOM_AGENT_FORMAT_MAP,
15799
16726
  CommandGenerator,
15800
16727
  CommandRegistry,
15801
16728
  ContextLoader,
@@ -15867,6 +16794,7 @@ export {
15867
16794
  WORKFLOW_EXTENSION,
15868
16795
  WindsurfTranslator,
15869
16796
  WorkflowOrchestrator,
16797
+ agentExists,
15870
16798
  analyzeProject,
15871
16799
  buildSkillIndex,
15872
16800
  canTranslate,
@@ -15908,21 +16836,35 @@ export {
15908
16836
  cursorTranslator,
15909
16837
  detectProvider,
15910
16838
  detectSkillFormat,
16839
+ discoverAgents,
16840
+ discoverAgentsForAgent,
16841
+ discoverAgentsFromPath,
16842
+ discoverAgentsRecursive,
16843
+ discoverGlobalAgents,
15911
16844
  discoverSkills,
15912
16845
  dryRunExecutor,
15913
16846
  estimateTokens,
15914
16847
  executeWithAgent,
15915
16848
  exportBundle,
16849
+ extractAgentContent,
16850
+ extractAgentFrontmatter,
15916
16851
  extractField,
15917
16852
  extractFrontmatter,
15918
16853
  extractSkillMetadata,
15919
16854
  fetchSkillsFromRepo,
16855
+ findAgent,
16856
+ findAllAgents,
15920
16857
  findAllSkills,
15921
16858
  findSkill,
15922
16859
  formatSkillAsPrompt,
16860
+ fromCanonicalAgent,
15923
16861
  getAgentCLIConfig,
15924
16862
  getAgentConfigPath,
16863
+ getAgentFilename,
15925
16864
  getAgentFormat,
16865
+ getAgentStats,
16866
+ getAgentTargetDirectory,
16867
+ getAgentsDirectory,
15926
16868
  getAllProviders,
15927
16869
  getAvailableCLIAgents,
15928
16870
  getBuiltinPacksDir,
@@ -15946,12 +16888,14 @@ export {
15946
16888
  initProject,
15947
16889
  initializeMemoryDirectory,
15948
16890
  isAgentCLIAvailable,
16891
+ isAgentCompatible,
15949
16892
  isGitUrl,
15950
16893
  isIndexStale,
15951
16894
  isLocalPath,
15952
16895
  isPathInside,
15953
16896
  listCICDTemplates,
15954
16897
  listWorkflows,
16898
+ loadAgentMetadata,
15955
16899
  loadConfig,
15956
16900
  loadContext,
15957
16901
  loadIndex,
@@ -15962,11 +16906,14 @@ export {
15962
16906
  loadWorkflow,
15963
16907
  loadWorkflowByName,
15964
16908
  memoryDirectoryExists,
16909
+ parseAgentDir,
16910
+ parseAgentFile,
15965
16911
  parseShorthand,
15966
16912
  parseSkill,
15967
16913
  parseSkillContent,
15968
16914
  parseSource,
15969
16915
  parseWorkflow,
16916
+ readAgentContent,
15970
16917
  readSkillContent,
15971
16918
  runTestSuite,
15972
16919
  saveConfig,
@@ -15980,9 +16927,15 @@ export {
15980
16927
  supportsSlashCommands,
15981
16928
  syncToAgent,
15982
16929
  syncToAllAgents,
16930
+ toCanonicalAgent,
16931
+ translateAgent,
16932
+ translateAgentContent,
16933
+ translateAgents,
16934
+ translateCanonicalAgent,
15983
16935
  translateSkill,
15984
16936
  translateSkillFile,
15985
16937
  translatorRegistry,
16938
+ validateAgent,
15986
16939
  validateBuiltinPacks,
15987
16940
  validatePackDirectory,
15988
16941
  validatePackManifest,