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 +1 -1
- package/dist/api.js +324 -33
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +329 -33
- package/dist/skills/frontmatter.d.ts +15 -0
- package/dist/skills/frontmatter.d.ts.map +1 -0
- package/dist/skills/frontmatter.js +51 -0
- package/dist/skills/index.d.ts +8 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +289 -0
- package/dist/skills/skills.d.ts +78 -0
- package/dist/skills/skills.d.ts.map +1 -0
- package/dist/skills/skills.js +287 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/system-prompt.d.ts +2 -0
- package/dist/utils/system-prompt.d.ts.map +1 -1
- package/dist/utils/system-prompt.js +279 -3
- package/package.json +2 -1
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;
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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
|
|
2921
|
-
import { join as
|
|
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 =
|
|
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((
|
|
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
|
|
3516
|
-
import { join as
|
|
3517
|
-
import { homedir as
|
|
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
|
|
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 =
|
|
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 =
|
|
3567
|
-
const filePath =
|
|
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:
|
|
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 =
|
|
3859
|
+
const filePath = join6(dir, `${sessionId}.jsonl`);
|
|
3584
3860
|
let lines;
|
|
3585
3861
|
try {
|
|
3586
|
-
lines =
|
|
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
|
|
3620
|
-
import { existsSync as
|
|
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 =
|
|
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 :
|
|
3635
|
-
const rel =
|
|
3636
|
-
if (rel.startsWith("..") ||
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
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 (
|
|
3991
|
+
if (existsSync5(absPath)) {
|
|
3716
3992
|
return `Error: File ${cmd.path} already exists`;
|
|
3717
3993
|
}
|
|
3718
|
-
const parentDir =
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
4075
|
+
if (!existsSync5(oldAbs)) {
|
|
3800
4076
|
return `Error: The path ${cmd.old_path} does not exist`;
|
|
3801
4077
|
}
|
|
3802
|
-
if (
|
|
4078
|
+
if (existsSync5(newAbs)) {
|
|
3803
4079
|
return `Error: The destination ${cmd.new_path} already exists`;
|
|
3804
4080
|
}
|
|
3805
|
-
const parentDir =
|
|
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 (!
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|