fourmis-agents-sdk 0.3.0 → 0.3.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/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAqB,MAAM,YAAY,CAAC;AAsBzE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB,GAAG,KAAK,CA4KR"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAqB,MAAM,YAAY,CAAC;AAwBzE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,KAAK,CAAC,MAAM,EAAE;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;CACxB,GAAG,KAAK,CA+LR"}
package/dist/api.js CHANGED
@@ -2916,9 +2916,277 @@ class SettingsManager {
2916
2916
  }
2917
2917
  }
2918
2918
 
2919
+ // src/skills/frontmatter.ts
2920
+ import { parse } from "yaml";
2921
+ function normalizeNewlines(value) {
2922
+ return value.replace(/\r\n/g, `
2923
+ `).replace(/\r/g, `
2924
+ `);
2925
+ }
2926
+ function extractFrontmatter(content) {
2927
+ const normalized = normalizeNewlines(content);
2928
+ if (!normalized.startsWith("---")) {
2929
+ return { yamlString: null, body: normalized };
2930
+ }
2931
+ const endIndex = normalized.indexOf(`
2932
+ ---`, 3);
2933
+ if (endIndex === -1) {
2934
+ return { yamlString: null, body: normalized };
2935
+ }
2936
+ return {
2937
+ yamlString: normalized.slice(4, endIndex),
2938
+ body: normalized.slice(endIndex + 4).trim()
2939
+ };
2940
+ }
2941
+ function parseFrontmatter(content) {
2942
+ const { yamlString, body } = extractFrontmatter(content);
2943
+ if (!yamlString) {
2944
+ return { frontmatter: {}, body };
2945
+ }
2946
+ const parsed = parse(yamlString);
2947
+ return { frontmatter: parsed ?? {}, body };
2948
+ }
2949
+ function stripFrontmatter(content) {
2950
+ return parseFrontmatter(content).body;
2951
+ }
2952
+
2953
+ // src/skills/skills.ts
2954
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync4, realpathSync, statSync } from "fs";
2955
+ import { homedir as homedir4 } from "os";
2956
+ import { basename, dirname as dirname3, isAbsolute, join as join4, resolve } from "path";
2957
+ var MAX_NAME_LENGTH = 64;
2958
+ var MAX_DESCRIPTION_LENGTH = 1024;
2959
+ var CONFIG_DIR_NAME = ".claude";
2960
+ function shouldIgnore(name) {
2961
+ return name.startsWith(".") || name === "node_modules";
2962
+ }
2963
+ function validateName(name, parentDirName) {
2964
+ const errors = [];
2965
+ if (name !== parentDirName) {
2966
+ errors.push(`name "${name}" does not match parent directory "${parentDirName}"`);
2967
+ }
2968
+ if (name.length > MAX_NAME_LENGTH) {
2969
+ errors.push(`name exceeds ${MAX_NAME_LENGTH} characters (${name.length})`);
2970
+ }
2971
+ if (!/^[a-z0-9-]+$/.test(name)) {
2972
+ errors.push(`name contains invalid characters (must be lowercase a-z, 0-9, hyphens only)`);
2973
+ }
2974
+ if (name.startsWith("-") || name.endsWith("-")) {
2975
+ errors.push(`name must not start or end with a hyphen`);
2976
+ }
2977
+ if (name.includes("--")) {
2978
+ errors.push(`name must not contain consecutive hyphens`);
2979
+ }
2980
+ return errors;
2981
+ }
2982
+ function validateDescription(description) {
2983
+ const errors = [];
2984
+ if (!description || description.trim() === "") {
2985
+ errors.push("description is required");
2986
+ } else if (description.length > MAX_DESCRIPTION_LENGTH) {
2987
+ errors.push(`description exceeds ${MAX_DESCRIPTION_LENGTH} characters (${description.length})`);
2988
+ }
2989
+ return errors;
2990
+ }
2991
+ function loadSkillsFromDir(options) {
2992
+ return loadSkillsFromDirInternal(options.dir, options.source, true);
2993
+ }
2994
+ function loadSkillsFromDirInternal(dir, source, includeRootFiles) {
2995
+ const skills = [];
2996
+ const diagnostics = [];
2997
+ if (!existsSync4(dir)) {
2998
+ return { skills, diagnostics };
2999
+ }
3000
+ try {
3001
+ const entries = readdirSync(dir, { withFileTypes: true });
3002
+ for (const entry of entries) {
3003
+ if (shouldIgnore(entry.name)) {
3004
+ continue;
3005
+ }
3006
+ const fullPath = join4(dir, entry.name);
3007
+ let isDirectory = entry.isDirectory();
3008
+ let isFile = entry.isFile();
3009
+ if (entry.isSymbolicLink()) {
3010
+ try {
3011
+ const stats = statSync(fullPath);
3012
+ isDirectory = stats.isDirectory();
3013
+ isFile = stats.isFile();
3014
+ } catch {
3015
+ continue;
3016
+ }
3017
+ }
3018
+ if (isDirectory) {
3019
+ const subResult = loadSkillsFromDirInternal(fullPath, source, false);
3020
+ skills.push(...subResult.skills);
3021
+ diagnostics.push(...subResult.diagnostics);
3022
+ continue;
3023
+ }
3024
+ if (!isFile)
3025
+ continue;
3026
+ const isRootMd = includeRootFiles && entry.name.endsWith(".md");
3027
+ const isSkillMd = !includeRootFiles && entry.name === "SKILL.md";
3028
+ if (!isRootMd && !isSkillMd)
3029
+ continue;
3030
+ const result = loadSkillFromFile(fullPath, source);
3031
+ if (result.skill) {
3032
+ skills.push(result.skill);
3033
+ }
3034
+ diagnostics.push(...result.diagnostics);
3035
+ }
3036
+ } catch {}
3037
+ return { skills, diagnostics };
3038
+ }
3039
+ function loadSkillFromFile(filePath, source) {
3040
+ const diagnostics = [];
3041
+ try {
3042
+ const rawContent = readFileSync4(filePath, "utf-8");
3043
+ const { frontmatter } = parseFrontmatter(rawContent);
3044
+ const skillDir = dirname3(filePath);
3045
+ const parentDirName = basename(skillDir);
3046
+ const descErrors = validateDescription(frontmatter.description);
3047
+ for (const error of descErrors) {
3048
+ diagnostics.push({ type: "warning", message: error, path: filePath });
3049
+ }
3050
+ const name = frontmatter.name || parentDirName;
3051
+ const nameErrors = validateName(name, parentDirName);
3052
+ for (const error of nameErrors) {
3053
+ diagnostics.push({ type: "warning", message: error, path: filePath });
3054
+ }
3055
+ if (!frontmatter.description || frontmatter.description.trim() === "") {
3056
+ return { skill: null, diagnostics };
3057
+ }
3058
+ return {
3059
+ skill: {
3060
+ name,
3061
+ description: frontmatter.description,
3062
+ filePath,
3063
+ baseDir: skillDir,
3064
+ source,
3065
+ disableModelInvocation: frontmatter["disable-model-invocation"] === true
3066
+ },
3067
+ diagnostics
3068
+ };
3069
+ } catch (error) {
3070
+ const message = error instanceof Error ? error.message : "failed to parse skill file";
3071
+ diagnostics.push({ type: "warning", message, path: filePath });
3072
+ return { skill: null, diagnostics };
3073
+ }
3074
+ }
3075
+ function normalizePath(input) {
3076
+ const trimmed = input.trim();
3077
+ if (trimmed === "~")
3078
+ return homedir4();
3079
+ if (trimmed.startsWith("~/"))
3080
+ return join4(homedir4(), trimmed.slice(2));
3081
+ if (trimmed.startsWith("~"))
3082
+ return join4(homedir4(), trimmed.slice(1));
3083
+ return trimmed;
3084
+ }
3085
+ function resolveSkillPath(p, cwd) {
3086
+ const normalized = normalizePath(p);
3087
+ return isAbsolute(normalized) ? normalized : resolve(cwd, normalized);
3088
+ }
3089
+ function loadSkills(options = {}) {
3090
+ const { cwd = process.cwd(), skillPaths = [], includeDefaults = true } = options;
3091
+ const skillMap = new Map;
3092
+ const realPathSet = new Set;
3093
+ const allDiagnostics = [];
3094
+ const collisionDiagnostics = [];
3095
+ function addSkills(result) {
3096
+ allDiagnostics.push(...result.diagnostics);
3097
+ for (const skill of result.skills) {
3098
+ let realPath;
3099
+ try {
3100
+ realPath = realpathSync(skill.filePath);
3101
+ } catch {
3102
+ realPath = skill.filePath;
3103
+ }
3104
+ if (realPathSet.has(realPath))
3105
+ continue;
3106
+ const existing = skillMap.get(skill.name);
3107
+ if (existing) {
3108
+ collisionDiagnostics.push({
3109
+ type: "collision",
3110
+ message: `name "${skill.name}" collision`,
3111
+ path: skill.filePath,
3112
+ collision: {
3113
+ resourceType: "skill",
3114
+ name: skill.name,
3115
+ winnerPath: existing.filePath,
3116
+ loserPath: skill.filePath
3117
+ }
3118
+ });
3119
+ } else {
3120
+ skillMap.set(skill.name, skill);
3121
+ realPathSet.add(realPath);
3122
+ }
3123
+ }
3124
+ }
3125
+ if (includeDefaults) {
3126
+ const userSkillsDir = join4(homedir4(), CONFIG_DIR_NAME, "skills");
3127
+ const projectSkillsDir = resolve(cwd, CONFIG_DIR_NAME, "skills");
3128
+ addSkills(loadSkillsFromDirInternal(userSkillsDir, "user", true));
3129
+ addSkills(loadSkillsFromDirInternal(projectSkillsDir, "project", true));
3130
+ }
3131
+ for (const rawPath of skillPaths) {
3132
+ const resolvedPath = resolveSkillPath(rawPath, cwd);
3133
+ if (!existsSync4(resolvedPath)) {
3134
+ allDiagnostics.push({ type: "warning", message: "skill path does not exist", path: resolvedPath });
3135
+ continue;
3136
+ }
3137
+ try {
3138
+ const stats = statSync(resolvedPath);
3139
+ if (stats.isDirectory()) {
3140
+ addSkills(loadSkillsFromDirInternal(resolvedPath, "path", true));
3141
+ } else if (stats.isFile() && resolvedPath.endsWith(".md")) {
3142
+ const result = loadSkillFromFile(resolvedPath, "path");
3143
+ if (result.skill) {
3144
+ addSkills({ skills: [result.skill], diagnostics: result.diagnostics });
3145
+ } else {
3146
+ allDiagnostics.push(...result.diagnostics);
3147
+ }
3148
+ } else {
3149
+ allDiagnostics.push({ type: "warning", message: "skill path is not a markdown file", path: resolvedPath });
3150
+ }
3151
+ } catch (error) {
3152
+ const message = error instanceof Error ? error.message : "failed to read skill path";
3153
+ allDiagnostics.push({ type: "warning", message, path: resolvedPath });
3154
+ }
3155
+ }
3156
+ return {
3157
+ skills: Array.from(skillMap.values()),
3158
+ diagnostics: [...allDiagnostics, ...collisionDiagnostics]
3159
+ };
3160
+ }
3161
+ function escapeXml(str) {
3162
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
3163
+ }
3164
+ function formatSkillsForPrompt(skills) {
3165
+ const visibleSkills = skills.filter((s) => !s.disableModelInvocation);
3166
+ if (visibleSkills.length === 0) {
3167
+ return "";
3168
+ }
3169
+ const lines = [
3170
+ "The following skills provide specialized instructions for specific tasks.",
3171
+ "Use the read tool to load a skill's file when the task matches its description.",
3172
+ "When a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.",
3173
+ "",
3174
+ "<available_skills>"
3175
+ ];
3176
+ for (const skill of visibleSkills) {
3177
+ lines.push(" <skill>");
3178
+ lines.push(` <name>${escapeXml(skill.name)}</name>`);
3179
+ lines.push(` <description>${escapeXml(skill.description)}</description>`);
3180
+ lines.push(` <location>${escapeXml(skill.filePath)}</location>`);
3181
+ lines.push(" </skill>");
3182
+ }
3183
+ lines.push("</available_skills>");
3184
+ return lines.join(`
3185
+ `);
3186
+ }
2919
3187
  // src/utils/system-prompt.ts
2920
- import { readFileSync as readFileSync4 } from "fs";
2921
- import { join as join4 } from "path";
3188
+ import { readFileSync as readFileSync5 } from "fs";
3189
+ import { join as join5 } from "path";
2922
3190
  var CORE_IDENTITY = `You are an AI coding agent. You help users with software engineering tasks by reading, writing, and modifying code. You have access to tools that let you interact with the filesystem and execute commands.
2923
3191
 
2924
3192
  You are highly capable and can help users complete complex tasks that would otherwise be too difficult or time-consuming.`;
@@ -2989,6 +3257,14 @@ Working directory: ${context.cwd}`);
2989
3257
  ${instructions}`);
2990
3258
  }
2991
3259
  }
3260
+ if (context.skills && context.skills.length > 0) {
3261
+ const skillsPrompt = formatSkillsForPrompt(context.skills);
3262
+ if (skillsPrompt) {
3263
+ sections.push(`# Skills
3264
+
3265
+ ${skillsPrompt}`);
3266
+ }
3267
+ }
2992
3268
  if (context.customPrompt) {
2993
3269
  sections.push(context.customPrompt);
2994
3270
  }
@@ -2999,7 +3275,7 @@ ${instructions}`);
2999
3275
  function readProjectInstructions(cwd) {
3000
3276
  for (const name of ["CLAUDE.md", "AGENTS.md"]) {
3001
3277
  try {
3002
- const content = readFileSync4(join4(cwd, name), "utf-8").trim();
3278
+ const content = readFileSync5(join5(cwd, name), "utf-8").trim();
3003
3279
  if (content)
3004
3280
  return content;
3005
3281
  } catch {}
@@ -3490,7 +3766,7 @@ class TaskManager {
3490
3766
  if (!block) {
3491
3767
  return `Task "${id}" is still running.`;
3492
3768
  }
3493
- const timeoutPromise = new Promise((resolve) => setTimeout(resolve, timeoutMs));
3769
+ const timeoutPromise = new Promise((resolve2) => setTimeout(resolve2, timeoutMs));
3494
3770
  await Promise.race([task.promise, timeoutPromise]);
3495
3771
  if (task.status === "running") {
3496
3772
  return `Task "${id}" is still running (timed out after ${timeoutMs}ms).`;
@@ -3512,21 +3788,21 @@ class TaskManager {
3512
3788
  }
3513
3789
 
3514
3790
  // src/utils/session-store.ts
3515
- import { readFileSync as readFileSync5, appendFileSync, mkdirSync as mkdirSync3, readdirSync, statSync } from "fs";
3516
- import { join as join5 } from "path";
3517
- import { homedir as homedir4 } from "os";
3791
+ import { readFileSync as readFileSync6, appendFileSync, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
3792
+ import { join as join6 } from "path";
3793
+ import { homedir as homedir5 } from "os";
3518
3794
  function sanitizeCwd(cwd) {
3519
3795
  return cwd.replace(/[/.]/g, "-");
3520
3796
  }
3521
3797
  function sessionsDir(cwd) {
3522
- return join5(homedir4(), ".claude", "projects", sanitizeCwd(cwd));
3798
+ return join6(homedir5(), ".claude", "projects", sanitizeCwd(cwd));
3523
3799
  }
3524
3800
  function ensureDir(dir) {
3525
3801
  mkdirSync3(dir, { recursive: true });
3526
3802
  }
3527
3803
  function logMessage(dir, sessionId, entry) {
3528
3804
  ensureDir(dir);
3529
- const filePath = join5(dir, `${sessionId}.jsonl`);
3805
+ const filePath = join6(dir, `${sessionId}.jsonl`);
3530
3806
  appendFileSync(filePath, JSON.stringify(entry) + `
3531
3807
  `);
3532
3808
  }
@@ -3563,10 +3839,10 @@ function createSessionLogger(cwd, sessionId, model) {
3563
3839
  function findLatestSession(cwd) {
3564
3840
  const dir = sessionsDir(cwd);
3565
3841
  try {
3566
- const files = readdirSync(dir).filter((f) => f.endsWith(".jsonl")).map((f) => {
3567
- const filePath = join5(dir, f);
3842
+ const files = readdirSync2(dir).filter((f) => f.endsWith(".jsonl")).map((f) => {
3843
+ const filePath = join6(dir, f);
3568
3844
  try {
3569
- return { name: f, mtime: statSync(filePath).mtimeMs };
3845
+ return { name: f, mtime: statSync2(filePath).mtimeMs };
3570
3846
  } catch {
3571
3847
  return null;
3572
3848
  }
@@ -3580,10 +3856,10 @@ function findLatestSession(cwd) {
3580
3856
  }
3581
3857
  function loadSessionMessages(cwd, sessionId) {
3582
3858
  const dir = sessionsDir(cwd);
3583
- const filePath = join5(dir, `${sessionId}.jsonl`);
3859
+ const filePath = join6(dir, `${sessionId}.jsonl`);
3584
3860
  let lines;
3585
3861
  try {
3586
- lines = readFileSync5(filePath, "utf-8").trim().split(`
3862
+ lines = readFileSync6(filePath, "utf-8").trim().split(`
3587
3863
  `).filter(Boolean);
3588
3864
  } catch {
3589
3865
  return [];
@@ -3616,10 +3892,10 @@ function loadSessionMessages(cwd, sessionId) {
3616
3892
 
3617
3893
  // src/memory/memory-handler.ts
3618
3894
  import { readdir, stat, readFile, writeFile, rm, rename, mkdir as mkdir2 } from "fs/promises";
3619
- import { join as join6, resolve, relative } from "path";
3620
- import { existsSync as existsSync4 } from "fs";
3895
+ import { join as join7, resolve as resolve2, relative as relative2 } from "path";
3896
+ import { existsSync as existsSync5 } from "fs";
3621
3897
  function createMemoryHandler(memoryDir) {
3622
- const absMemoryDir = resolve(memoryDir);
3898
+ const absMemoryDir = resolve2(memoryDir);
3623
3899
  function resolvePath2(logicalPath) {
3624
3900
  let cleaned = logicalPath;
3625
3901
  if (cleaned.startsWith("/memories")) {
@@ -3631,15 +3907,15 @@ function createMemoryHandler(memoryDir) {
3631
3907
  if (cleaned.includes("..") || cleaned.includes("%2e") || cleaned.includes("%2E")) {
3632
3908
  throw new Error(`Path traversal detected: ${logicalPath}`);
3633
3909
  }
3634
- const absPath = cleaned === "" ? absMemoryDir : resolve(absMemoryDir, cleaned);
3635
- const rel = relative(absMemoryDir, absPath);
3636
- if (rel.startsWith("..") || resolve(absPath) !== absPath && !absPath.startsWith(absMemoryDir)) {
3910
+ const absPath = cleaned === "" ? absMemoryDir : resolve2(absMemoryDir, cleaned);
3911
+ const rel = relative2(absMemoryDir, absPath);
3912
+ if (rel.startsWith("..") || resolve2(absPath) !== absPath && !absPath.startsWith(absMemoryDir)) {
3637
3913
  throw new Error(`Path traversal detected: ${logicalPath}`);
3638
3914
  }
3639
3915
  return absPath;
3640
3916
  }
3641
3917
  function toLogicalPath(absPath) {
3642
- const rel = relative(absMemoryDir, absPath);
3918
+ const rel = relative2(absMemoryDir, absPath);
3643
3919
  return rel === "" ? "/memories" : `/memories/${rel}`;
3644
3920
  }
3645
3921
  function formatSize(bytes) {
@@ -3662,7 +3938,7 @@ function createMemoryHandler(memoryDir) {
3662
3938
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
3663
3939
  if (entry.name.startsWith(".") || entry.name === "node_modules")
3664
3940
  continue;
3665
- const entryPath = join6(dirPath, entry.name);
3941
+ const entryPath = join7(dirPath, entry.name);
3666
3942
  const entryStat = await stat(entryPath);
3667
3943
  lines.push(`${formatSize(entryStat.size)} ${toLogicalPath(entryPath)}`);
3668
3944
  if (entry.isDirectory()) {
@@ -3695,7 +3971,7 @@ function createMemoryHandler(memoryDir) {
3695
3971
  }
3696
3972
  async function handleView(cmd) {
3697
3973
  const absPath = resolvePath2(cmd.path);
3698
- if (!existsSync4(absPath)) {
3974
+ if (!existsSync5(absPath)) {
3699
3975
  return `The path ${cmd.path} does not exist. Please provide a valid path.`;
3700
3976
  }
3701
3977
  const s = await stat(absPath);
@@ -3712,17 +3988,17 @@ ${formatted}`;
3712
3988
  }
3713
3989
  async function handleCreate(cmd) {
3714
3990
  const absPath = resolvePath2(cmd.path);
3715
- if (existsSync4(absPath)) {
3991
+ if (existsSync5(absPath)) {
3716
3992
  return `Error: File ${cmd.path} already exists`;
3717
3993
  }
3718
- const parentDir = resolve(absPath, "..");
3994
+ const parentDir = resolve2(absPath, "..");
3719
3995
  await mkdir2(parentDir, { recursive: true });
3720
3996
  await writeFile(absPath, cmd.file_text, "utf-8");
3721
3997
  return `File created successfully at: ${cmd.path}`;
3722
3998
  }
3723
3999
  async function handleStrReplace(cmd) {
3724
4000
  const absPath = resolvePath2(cmd.path);
3725
- if (!existsSync4(absPath)) {
4001
+ if (!existsSync5(absPath)) {
3726
4002
  return `Error: The path ${cmd.path} does not exist. Please provide a valid path.`;
3727
4003
  }
3728
4004
  const s = await stat(absPath);
@@ -3765,7 +4041,7 @@ ${snippet}`;
3765
4041
  }
3766
4042
  async function handleInsert(cmd) {
3767
4043
  const absPath = resolvePath2(cmd.path);
3768
- if (!existsSync4(absPath)) {
4044
+ if (!existsSync5(absPath)) {
3769
4045
  return `Error: The path ${cmd.path} does not exist`;
3770
4046
  }
3771
4047
  const s = await stat(absPath);
@@ -3787,7 +4063,7 @@ ${snippet}`;
3787
4063
  }
3788
4064
  async function handleDelete(cmd) {
3789
4065
  const absPath = resolvePath2(cmd.path);
3790
- if (!existsSync4(absPath)) {
4066
+ if (!existsSync5(absPath)) {
3791
4067
  return `Error: The path ${cmd.path} does not exist`;
3792
4068
  }
3793
4069
  await rm(absPath, { recursive: true, force: true });
@@ -3796,19 +4072,19 @@ ${snippet}`;
3796
4072
  async function handleRename(cmd) {
3797
4073
  const oldAbs = resolvePath2(cmd.old_path);
3798
4074
  const newAbs = resolvePath2(cmd.new_path);
3799
- if (!existsSync4(oldAbs)) {
4075
+ if (!existsSync5(oldAbs)) {
3800
4076
  return `Error: The path ${cmd.old_path} does not exist`;
3801
4077
  }
3802
- if (existsSync4(newAbs)) {
4078
+ if (existsSync5(newAbs)) {
3803
4079
  return `Error: The destination ${cmd.new_path} already exists`;
3804
4080
  }
3805
- const parentDir = resolve(newAbs, "..");
4081
+ const parentDir = resolve2(newAbs, "..");
3806
4082
  await mkdir2(parentDir, { recursive: true });
3807
4083
  await rename(oldAbs, newAbs);
3808
4084
  return `Successfully renamed ${cmd.old_path} to ${cmd.new_path}`;
3809
4085
  }
3810
4086
  async function execute(cmd) {
3811
- if (!existsSync4(absMemoryDir)) {
4087
+ if (!existsSync5(absMemoryDir)) {
3812
4088
  await mkdir2(absMemoryDir, { recursive: true });
3813
4089
  }
3814
4090
  switch (cmd.command) {
@@ -3929,10 +4205,25 @@ function query(params) {
3929
4205
  const model = options.model ?? DEFAULT_MODEL;
3930
4206
  const toolNames = resolveToolNames(options.tools);
3931
4207
  const registry = buildToolRegistry(toolNames, undefined, options.disallowedTools);
4208
+ let skills = [];
4209
+ {
4210
+ const skillsResult = loadSkills({
4211
+ cwd: options.cwd,
4212
+ skillPaths: options.skillPaths,
4213
+ includeDefaults: options.includeDefaultSkills !== false
4214
+ });
4215
+ skills = skillsResult.skills;
4216
+ if (options.debug && skillsResult.diagnostics.length > 0) {
4217
+ for (const d of skillsResult.diagnostics) {
4218
+ console.warn(`[skills] ${d.type}: ${d.message} (${d.path})`);
4219
+ }
4220
+ }
4221
+ }
3932
4222
  const systemPrompt = options.systemPrompt ?? buildSystemPrompt({
3933
4223
  tools: registry.list(),
3934
4224
  cwd: options.cwd,
3935
- customPrompt: options.appendSystemPrompt
4225
+ customPrompt: options.appendSystemPrompt,
4226
+ skills
3936
4227
  });
3937
4228
  let settingsManager;
3938
4229
  let mergedPermissions = options.permissions;
package/dist/index.d.ts CHANGED
@@ -24,6 +24,8 @@ export { createMcpServer, tool as mcpTool } from "./mcp/server.js";
24
24
  export type { McpServerConfig, McpStdioConfig, McpSseConfig, McpHttpConfig, McpSdkConfig, McpServerStatus, } from "./mcp/types.js";
25
25
  export { TaskManager } from "./agents/task-manager.js";
26
26
  export type { AgentDefinition, BackgroundTask } from "./agents/types.js";
27
+ export { loadSkills, loadSkillsFromDir, formatSkillsForPrompt, parseFrontmatter, stripFrontmatter } from "./skills/index.js";
28
+ export type { Skill, SkillFrontmatter, SkillDiagnostic, LoadSkillsResult, LoadSkillsFromDirOptions, LoadSkillsOptions, ParsedFrontmatter } from "./skills/index.js";
27
29
  export { createMemoryHandler, createNativeMemoryTool, createMemoryTool } from "./memory/index.js";
28
30
  export type { MemoryConfig, NativeMemoryTool, MemoryCommand } from "./memory/index.js";
29
31
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,KAAK,EACL,UAAU,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,iBAAiB,EACjB,UAAU,EACV,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,YAAY,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,SAAS,GACV,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EACV,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClG,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,YAAY,EACV,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,KAAK,EACL,UAAU,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,2BAA2B,EAC3B,iBAAiB,EACjB,UAAU,EACV,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGhD,YAAY,EACV,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,SAAS,GACV,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGxE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EACV,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,SAAS,EACT,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGzE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC7H,YAAY,EAAE,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGpK,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAClG,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}