@skillkit/core 1.6.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15782,13 +15782,864 @@ 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
+
16372
+ // src/agents/translator.ts
16373
+ import { join as join32 } from "path";
16374
+ function translateAgent(agent, targetAgent, options) {
16375
+ const canonical = toCanonicalAgent(agent);
16376
+ return translateCanonicalAgent(canonical, targetAgent, options);
16377
+ }
16378
+ function translateCanonicalAgent(canonical, targetAgent, options) {
16379
+ const targetFormat = CUSTOM_AGENT_FORMAT_MAP[targetAgent];
16380
+ const warnings = [];
16381
+ const incompatible = [];
16382
+ if (targetFormat === "universal") {
16383
+ if (canonical.hooks && canonical.hooks.length > 0) {
16384
+ incompatible.push("hooks (not supported in universal format)");
16385
+ }
16386
+ if (canonical.permissionMode) {
16387
+ incompatible.push("permissionMode (not supported in universal format)");
16388
+ }
16389
+ }
16390
+ if (targetFormat === "cursor-agent") {
16391
+ if (canonical.hooks && canonical.hooks.length > 0) {
16392
+ warnings.push("Hooks may require manual adjustment for Cursor");
16393
+ }
16394
+ }
16395
+ let content;
16396
+ switch (targetFormat) {
16397
+ case "claude-agent":
16398
+ content = generateClaudeAgent(canonical, options);
16399
+ break;
16400
+ case "cursor-agent":
16401
+ content = generateCursorAgent(canonical, options);
16402
+ break;
16403
+ case "universal":
16404
+ content = generateUniversalAgent(canonical, options);
16405
+ break;
16406
+ default:
16407
+ content = fromCanonicalAgent(canonical, targetFormat);
16408
+ }
16409
+ const filename = options?.outputFilename || getAgentFilename(canonical.name, targetAgent);
16410
+ return {
16411
+ success: true,
16412
+ content,
16413
+ filename,
16414
+ warnings,
16415
+ incompatible,
16416
+ targetFormat,
16417
+ targetAgent
16418
+ };
16419
+ }
16420
+ function translateAgentContent(content, _sourceAgent, targetAgent, options) {
16421
+ const agent = parseAgentFromContent(content);
16422
+ if (!agent) {
16423
+ return {
16424
+ success: false,
16425
+ content: "",
16426
+ filename: "",
16427
+ warnings: ["Failed to parse agent content"],
16428
+ incompatible: [],
16429
+ targetFormat: CUSTOM_AGENT_FORMAT_MAP[targetAgent],
16430
+ targetAgent
16431
+ };
16432
+ }
16433
+ return translateAgent(agent, targetAgent, options);
16434
+ }
16435
+ function parseAgentFromContent(content) {
16436
+ const rawFrontmatter = extractAgentFrontmatter(content);
16437
+ const agentContent = extractAgentContent(content);
16438
+ if (!rawFrontmatter) {
16439
+ return null;
16440
+ }
16441
+ const parsed = AgentFrontmatter.safeParse(rawFrontmatter);
16442
+ const frontmatter = parsed.success ? parsed.data : {
16443
+ name: rawFrontmatter.name || "unnamed-agent",
16444
+ description: rawFrontmatter.description || "No description",
16445
+ ...rawFrontmatter
16446
+ };
16447
+ return {
16448
+ name: frontmatter.name,
16449
+ description: frontmatter.description,
16450
+ path: "",
16451
+ location: "project",
16452
+ frontmatter,
16453
+ content: agentContent,
16454
+ enabled: true
16455
+ };
16456
+ }
16457
+ function generateClaudeAgent(canonical, options) {
16458
+ const lines = [];
16459
+ lines.push("---");
16460
+ lines.push(`name: ${canonical.name}`);
16461
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16462
+ if (canonical.model) {
16463
+ lines.push(`model: ${canonical.model}`);
16464
+ }
16465
+ if (canonical.permissionMode) {
16466
+ lines.push(`permissionMode: ${canonical.permissionMode}`);
16467
+ }
16468
+ if (canonical.disallowedTools && canonical.disallowedTools.length > 0) {
16469
+ lines.push("disallowedTools:");
16470
+ for (const tool of canonical.disallowedTools) {
16471
+ lines.push(` - ${tool}`);
16472
+ }
16473
+ }
16474
+ if (canonical.allowedTools && canonical.allowedTools.length > 0) {
16475
+ lines.push("allowed-tools:");
16476
+ for (const tool of canonical.allowedTools) {
16477
+ lines.push(` - ${tool}`);
16478
+ }
16479
+ }
16480
+ if (canonical.hooks && canonical.hooks.length > 0) {
16481
+ lines.push("hooks:");
16482
+ for (const hook of canonical.hooks) {
16483
+ lines.push(` - type: ${hook.type}`);
16484
+ lines.push(` command: "${escapeYamlString(hook.command)}"`);
16485
+ if (hook.timeout) lines.push(` timeout: ${hook.timeout}`);
16486
+ if (hook.once) lines.push(` once: true`);
16487
+ if (hook.matcher) lines.push(` matcher: "${hook.matcher}"`);
16488
+ }
16489
+ }
16490
+ if (canonical.skills && canonical.skills.length > 0) {
16491
+ lines.push("skills:");
16492
+ for (const skill of canonical.skills) {
16493
+ lines.push(` - ${skill}`);
16494
+ }
16495
+ }
16496
+ if (canonical.context) {
16497
+ lines.push(`context: ${canonical.context}`);
16498
+ }
16499
+ if (canonical.version) {
16500
+ lines.push(`version: "${canonical.version}"`);
16501
+ }
16502
+ if (canonical.author) {
16503
+ lines.push(`author: ${canonical.author}`);
16504
+ }
16505
+ if (canonical.tags && canonical.tags.length > 0) {
16506
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16507
+ }
16508
+ if (canonical.userInvocable !== void 0) {
16509
+ lines.push(`user-invocable: ${canonical.userInvocable}`);
16510
+ }
16511
+ if (canonical.argumentHint) {
16512
+ lines.push(`argument-hint: "${escapeYamlString(canonical.argumentHint)}"`);
16513
+ }
16514
+ if (options?.addMetadata) {
16515
+ lines.push(`# Translated by SkillKit from ${canonical.sourceAgent || "unknown"}`);
16516
+ }
16517
+ lines.push("---");
16518
+ lines.push("");
16519
+ lines.push(canonical.content);
16520
+ return lines.join("\n");
16521
+ }
16522
+ function generateCursorAgent(canonical, options) {
16523
+ const lines = [];
16524
+ lines.push("---");
16525
+ lines.push(`name: ${canonical.name}`);
16526
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16527
+ if (canonical.model) {
16528
+ lines.push(`model: ${canonical.model}`);
16529
+ }
16530
+ if (canonical.allowedTools && canonical.allowedTools.length > 0) {
16531
+ lines.push(`tools: [${canonical.allowedTools.join(", ")}]`);
16532
+ }
16533
+ if (canonical.version) {
16534
+ lines.push(`version: "${canonical.version}"`);
16535
+ }
16536
+ if (canonical.tags && canonical.tags.length > 0) {
16537
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16538
+ }
16539
+ if (options?.addMetadata) {
16540
+ lines.push(`# Translated by SkillKit from ${canonical.sourceAgent || "unknown"}`);
16541
+ }
16542
+ lines.push("---");
16543
+ lines.push("");
16544
+ lines.push(canonical.content);
16545
+ if (canonical.hooks && canonical.hooks.length > 0) {
16546
+ lines.push("");
16547
+ lines.push("<!-- Note: Hooks from original agent may need manual configuration -->");
16548
+ }
16549
+ return lines.join("\n");
16550
+ }
16551
+ function generateUniversalAgent(canonical, options) {
16552
+ const lines = [];
16553
+ lines.push("---");
16554
+ lines.push(`name: ${canonical.name}`);
16555
+ lines.push(`description: ${escapeYamlString(canonical.description)}`);
16556
+ if (canonical.model) {
16557
+ lines.push(`model: ${canonical.model}`);
16558
+ }
16559
+ if (canonical.version) {
16560
+ lines.push(`version: "${canonical.version}"`);
16561
+ }
16562
+ if (canonical.author) {
16563
+ lines.push(`author: ${canonical.author}`);
16564
+ }
16565
+ if (canonical.tags && canonical.tags.length > 0) {
16566
+ lines.push(`tags: [${canonical.tags.join(", ")}]`);
16567
+ }
16568
+ if (options?.addMetadata) {
16569
+ lines.push(`# Translated by SkillKit`);
16570
+ if (canonical.sourceAgent) {
16571
+ lines.push(`# Original format: ${canonical.sourceAgent}`);
16572
+ }
16573
+ }
16574
+ lines.push("---");
16575
+ lines.push("");
16576
+ lines.push(`# ${canonical.name}`);
16577
+ lines.push("");
16578
+ lines.push(canonical.content);
16579
+ return lines.join("\n");
16580
+ }
16581
+ function getAgentFilename(agentName, targetAgent) {
16582
+ const format = CUSTOM_AGENT_FORMAT_MAP[targetAgent];
16583
+ switch (format) {
16584
+ case "cursor-agent":
16585
+ return `${agentName}.md`;
16586
+ // Or .mdc if Cursor uses that for agents
16587
+ default:
16588
+ return `${agentName}.md`;
16589
+ }
16590
+ }
16591
+ function getAgentTargetDirectory(rootDir, targetAgent) {
16592
+ const paths = AGENT_DISCOVERY_PATHS[targetAgent];
16593
+ if (paths && paths.length > 0) {
16594
+ return join32(rootDir, paths[0]);
16595
+ }
16596
+ return join32(rootDir, "agents");
16597
+ }
16598
+ function escapeYamlString(str) {
16599
+ if (/[:\{\}\[\],&*#?|\-<>=!%@`]/.test(str) || str.includes("\n")) {
16600
+ return `"${str.replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
16601
+ }
16602
+ return str;
16603
+ }
16604
+ function translateAgents(agents, targetAgent, options) {
16605
+ return agents.map((agent) => translateAgent(agent, targetAgent, options));
16606
+ }
16607
+ function isAgentCompatible(sourceFormat, targetFormat) {
16608
+ const warnings = [];
16609
+ if (sourceFormat === targetFormat) {
16610
+ return { compatible: true, warnings };
16611
+ }
16612
+ if (targetFormat === "claude-agent") {
16613
+ return { compatible: true, warnings };
16614
+ }
16615
+ if (targetFormat === "universal") {
16616
+ if (sourceFormat === "claude-agent") {
16617
+ warnings.push("Hooks, permissionMode, and disallowedTools will be lost");
16618
+ }
16619
+ return { compatible: true, warnings };
16620
+ }
16621
+ if (targetFormat === "cursor-agent") {
16622
+ if (sourceFormat === "claude-agent") {
16623
+ warnings.push("Some Claude-specific features may not translate perfectly");
16624
+ }
16625
+ return { compatible: true, warnings };
16626
+ }
16627
+ return { compatible: true, warnings };
16628
+ }
15785
16629
  export {
15786
16630
  AGENT_CLI_CONFIGS,
16631
+ AGENT_DISCOVERY_PATHS,
15787
16632
  AGENT_FORMAT_MAP,
15788
16633
  AIManager,
15789
16634
  AISearch,
15790
16635
  AISkillGenerator,
16636
+ ALL_AGENT_DISCOVERY_PATHS,
15791
16637
  APIBasedCompressor,
16638
+ AgentFrontmatter,
16639
+ AgentHook,
16640
+ AgentLocation,
16641
+ AgentMetadata,
16642
+ AgentPermissionMode,
15792
16643
  AgentType,
15793
16644
  AuditLogger,
15794
16645
  BaseAIProvider,
@@ -15796,6 +16647,7 @@ export {
15796
16647
  CIRCLECI_CONFIG_TEMPLATE,
15797
16648
  CONTEXT_DIR,
15798
16649
  CONTEXT_FILE,
16650
+ CUSTOM_AGENT_FORMAT_MAP,
15799
16651
  CommandGenerator,
15800
16652
  CommandRegistry,
15801
16653
  ContextLoader,
@@ -15867,6 +16719,7 @@ export {
15867
16719
  WORKFLOW_EXTENSION,
15868
16720
  WindsurfTranslator,
15869
16721
  WorkflowOrchestrator,
16722
+ agentExists,
15870
16723
  analyzeProject,
15871
16724
  buildSkillIndex,
15872
16725
  canTranslate,
@@ -15908,21 +16761,33 @@ export {
15908
16761
  cursorTranslator,
15909
16762
  detectProvider,
15910
16763
  detectSkillFormat,
16764
+ discoverAgents,
16765
+ discoverAgentsForAgent,
16766
+ discoverGlobalAgents,
15911
16767
  discoverSkills,
15912
16768
  dryRunExecutor,
15913
16769
  estimateTokens,
15914
16770
  executeWithAgent,
15915
16771
  exportBundle,
16772
+ extractAgentContent,
16773
+ extractAgentFrontmatter,
15916
16774
  extractField,
15917
16775
  extractFrontmatter,
15918
16776
  extractSkillMetadata,
15919
16777
  fetchSkillsFromRepo,
16778
+ findAgent,
16779
+ findAllAgents,
15920
16780
  findAllSkills,
15921
16781
  findSkill,
15922
16782
  formatSkillAsPrompt,
16783
+ fromCanonicalAgent,
15923
16784
  getAgentCLIConfig,
15924
16785
  getAgentConfigPath,
16786
+ getAgentFilename,
15925
16787
  getAgentFormat,
16788
+ getAgentStats,
16789
+ getAgentTargetDirectory,
16790
+ getAgentsDirectory,
15926
16791
  getAllProviders,
15927
16792
  getAvailableCLIAgents,
15928
16793
  getBuiltinPacksDir,
@@ -15946,12 +16811,14 @@ export {
15946
16811
  initProject,
15947
16812
  initializeMemoryDirectory,
15948
16813
  isAgentCLIAvailable,
16814
+ isAgentCompatible,
15949
16815
  isGitUrl,
15950
16816
  isIndexStale,
15951
16817
  isLocalPath,
15952
16818
  isPathInside,
15953
16819
  listCICDTemplates,
15954
16820
  listWorkflows,
16821
+ loadAgentMetadata,
15955
16822
  loadConfig,
15956
16823
  loadContext,
15957
16824
  loadIndex,
@@ -15962,11 +16829,14 @@ export {
15962
16829
  loadWorkflow,
15963
16830
  loadWorkflowByName,
15964
16831
  memoryDirectoryExists,
16832
+ parseAgentDir,
16833
+ parseAgentFile,
15965
16834
  parseShorthand,
15966
16835
  parseSkill,
15967
16836
  parseSkillContent,
15968
16837
  parseSource,
15969
16838
  parseWorkflow,
16839
+ readAgentContent,
15970
16840
  readSkillContent,
15971
16841
  runTestSuite,
15972
16842
  saveConfig,
@@ -15980,9 +16850,15 @@ export {
15980
16850
  supportsSlashCommands,
15981
16851
  syncToAgent,
15982
16852
  syncToAllAgents,
16853
+ toCanonicalAgent,
16854
+ translateAgent,
16855
+ translateAgentContent,
16856
+ translateAgents,
16857
+ translateCanonicalAgent,
15983
16858
  translateSkill,
15984
16859
  translateSkillFile,
15985
16860
  translatorRegistry,
16861
+ validateAgent,
15986
16862
  validateBuiltinPacks,
15987
16863
  validatePackDirectory,
15988
16864
  validatePackManifest,