@mariozechner/pi-coding-agent 0.20.0 → 0.20.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/CHANGELOG.md +6 -0
- package/dist/core/skills.d.ts +18 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +36 -7
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +3 -21
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.20.1] - 2025-12-13
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Exported skills API**: `loadSkillsFromDir`, `formatSkillsForPrompt`, and related types are now exported for use by other packages (e.g., mom).
|
|
8
|
+
|
|
3
9
|
## [0.20.0] - 2025-12-13
|
|
4
10
|
|
|
5
11
|
### Breaking Changes
|
package/dist/core/skills.d.ts
CHANGED
|
@@ -2,13 +2,29 @@ export interface SkillFrontmatter {
|
|
|
2
2
|
name?: string;
|
|
3
3
|
description: string;
|
|
4
4
|
}
|
|
5
|
-
export type SkillSource = "user" | "project" | "claude-user" | "claude-project" | "codex-user";
|
|
6
5
|
export interface Skill {
|
|
7
6
|
name: string;
|
|
8
7
|
description: string;
|
|
9
8
|
filePath: string;
|
|
10
9
|
baseDir: string;
|
|
11
|
-
source:
|
|
10
|
+
source: string;
|
|
12
11
|
}
|
|
12
|
+
export interface LoadSkillsFromDirOptions {
|
|
13
|
+
/** Directory to scan for skills */
|
|
14
|
+
dir: string;
|
|
15
|
+
/** Source identifier for these skills */
|
|
16
|
+
source: string;
|
|
17
|
+
/** Use colon-separated path names (e.g., db:migrate) instead of simple directory name */
|
|
18
|
+
useColonPath?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load skills from a directory recursively.
|
|
22
|
+
* Skills are directories containing a SKILL.md file with frontmatter including a description.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadSkillsFromDir(options: LoadSkillsFromDirOptions, subdir?: string): Skill[];
|
|
25
|
+
/**
|
|
26
|
+
* Format skills for inclusion in a system prompt.
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatSkillsForPrompt(skills: Skill[]): string;
|
|
13
29
|
export declare function loadSkills(): Skill[];
|
|
14
30
|
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CACf;AA4CD,MAAM,WAAW,wBAAwB;IACxC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,EAAE,MAAM,GAAE,MAAW,GAAG,KAAK,EAAE,CAGjG;AA+FD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAqB7D;AAED,wBAAgB,UAAU,IAAI,KAAK,EAAE,CAgCpC","sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { CONFIG_DIR_NAME } from \"../config.js\";\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription: string;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsource: string;\n}\n\ntype SkillFormat = \"recursive\" | \"claude\";\n\nfunction stripQuotes(value: string): string {\n\tif ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n\t\treturn value.slice(1, -1);\n\t}\n\treturn value;\n}\n\nfunction parseFrontmatter(content: string): { frontmatter: SkillFrontmatter; body: string } {\n\tconst frontmatter: SkillFrontmatter = { description: \"\" };\n\n\tconst normalizedContent = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\tif (!normalizedContent.startsWith(\"---\")) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst endIndex = normalizedContent.indexOf(\"\\n---\", 3);\n\tif (endIndex === -1) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst frontmatterBlock = normalizedContent.slice(4, endIndex);\n\tconst body = normalizedContent.slice(endIndex + 4).trim();\n\n\tfor (const line of frontmatterBlock.split(\"\\n\")) {\n\t\tconst match = line.match(/^(\\w+):\\s*(.*)$/);\n\t\tif (match) {\n\t\t\tconst key = match[1];\n\t\t\tconst value = stripQuotes(match[2].trim());\n\t\t\tif (key === \"name\") {\n\t\t\t\tfrontmatter.name = value;\n\t\t\t} else if (key === \"description\") {\n\t\t\t\tfrontmatter.description = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { frontmatter, body };\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n\t/** Use colon-separated path names (e.g., db:migrate) instead of simple directory name */\n\tuseColonPath?: boolean;\n}\n\n/**\n * Load skills from a directory recursively.\n * Skills are directories containing a SKILL.md file with frontmatter including a description.\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions, subdir: string = \"\"): Skill[] {\n\tconst { dir, source, useColonPath = false } = options;\n\treturn loadSkillsFromDirInternal(dir, source, \"recursive\", useColonPath, subdir);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tformat: SkillFormat,\n\tuseColonPath: boolean = false,\n\tsubdir: string = \"\",\n): Skill[] {\n\tconst skills: Skill[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn skills;\n\t}\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tif (format === \"recursive\") {\n\t\t\t\t// Recursive format: scan directories, look for SKILL.md files\n\t\t\t\tif (entry.isDirectory()) {\n\t\t\t\t\tconst newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;\n\t\t\t\t\tskills.push(...loadSkillsFromDirInternal(fullPath, source, format, useColonPath, newSubdir));\n\t\t\t\t} else if (entry.isFile() && entry.name === \"SKILL.md\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst rawContent = readFileSync(fullPath, \"utf-8\");\n\t\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst skillDir = dirname(fullPath);\n\t\t\t\t\t\t// useColonPath: db:migrate (pi), otherwise just: migrate (codex)\n\t\t\t\t\t\tconst nameFromPath = useColonPath ? subdir || basename(skillDir) : basename(skillDir);\n\t\t\t\t\t\tconst name = frontmatter.name || nameFromPath;\n\n\t\t\t\t\t\tskills.push({\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\t\tfilePath: fullPath,\n\t\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t} else if (format === \"claude\") {\n\t\t\t\t// Claude format: only one level deep, each directory must contain SKILL.md\n\t\t\t\tif (!entry.isDirectory()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst skillDir = fullPath;\n\t\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\t\tif (!existsSync(skillFile)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst rawContent = readFileSync(skillFile, \"utf-8\");\n\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst name = frontmatter.name || entry.name;\n\n\t\t\t\t\tskills.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\tfilePath: skillFile,\n\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t} catch {}\n\n\treturn skills;\n}\n\n/**\n * Format skills for inclusion in a system prompt.\n */\nexport function formatSkillsForPrompt(skills: Skill[]): string {\n\tif (skills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\n\t\t\"\\n\\n<available_skills>\",\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Use the read tool to load a skill's file when the task matches its description.\",\n\t\t\"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\\n\",\n\t];\n\n\tfor (const skill of skills) {\n\t\tlines.push(`- ${skill.name}: ${skill.description}`);\n\t\tlines.push(` File: ${skill.filePath}`);\n\t\tlines.push(` Base directory: ${skill.baseDir}`);\n\t}\n\n\tlines.push(\"</available_skills>\");\n\n\treturn lines.join(\"\\n\");\n}\n\nexport function loadSkills(): Skill[] {\n\tconst skillMap = new Map<string, Skill>();\n\n\t// Codex: recursive, simple directory name\n\tconst codexUserDir = join(homedir(), \".codex\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(codexUserDir, \"codex-user\", \"recursive\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Claude: single level only\n\tconst claudeUserDir = join(homedir(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(claudeUserDir, \"claude-user\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst claudeProjectDir = resolve(process.cwd(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(claudeProjectDir, \"claude-project\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Pi: recursive, colon-separated path names\n\tconst globalSkillsDir = join(homedir(), CONFIG_DIR_NAME, \"agent\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(globalSkillsDir, \"user\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst projectSkillsDir = resolve(process.cwd(), CONFIG_DIR_NAME, \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(projectSkillsDir, \"project\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\treturn Array.from(skillMap.values());\n}\n"]}
|
package/dist/core/skills.js
CHANGED
|
@@ -35,7 +35,15 @@ function parseFrontmatter(content) {
|
|
|
35
35
|
}
|
|
36
36
|
return { frontmatter, body };
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Load skills from a directory recursively.
|
|
40
|
+
* Skills are directories containing a SKILL.md file with frontmatter including a description.
|
|
41
|
+
*/
|
|
42
|
+
export function loadSkillsFromDir(options, subdir = "") {
|
|
43
|
+
const { dir, source, useColonPath = false } = options;
|
|
44
|
+
return loadSkillsFromDirInternal(dir, source, "recursive", useColonPath, subdir);
|
|
45
|
+
}
|
|
46
|
+
function loadSkillsFromDirInternal(dir, source, format, useColonPath = false, subdir = "") {
|
|
39
47
|
const skills = [];
|
|
40
48
|
if (!existsSync(dir)) {
|
|
41
49
|
return skills;
|
|
@@ -54,7 +62,7 @@ function loadSkillsFromDir(dir, source, format, useColonPath = false, subdir = "
|
|
|
54
62
|
// Recursive format: scan directories, look for SKILL.md files
|
|
55
63
|
if (entry.isDirectory()) {
|
|
56
64
|
const newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;
|
|
57
|
-
skills.push(...
|
|
65
|
+
skills.push(...loadSkillsFromDirInternal(fullPath, source, format, useColonPath, newSubdir));
|
|
58
66
|
}
|
|
59
67
|
else if (entry.isFile() && entry.name === "SKILL.md") {
|
|
60
68
|
try {
|
|
@@ -110,29 +118,50 @@ function loadSkillsFromDir(dir, source, format, useColonPath = false, subdir = "
|
|
|
110
118
|
catch { }
|
|
111
119
|
return skills;
|
|
112
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Format skills for inclusion in a system prompt.
|
|
123
|
+
*/
|
|
124
|
+
export function formatSkillsForPrompt(skills) {
|
|
125
|
+
if (skills.length === 0) {
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
const lines = [
|
|
129
|
+
"\n\n<available_skills>",
|
|
130
|
+
"The following skills provide specialized instructions for specific tasks.",
|
|
131
|
+
"Use the read tool to load a skill's file when the task matches its description.",
|
|
132
|
+
"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\n",
|
|
133
|
+
];
|
|
134
|
+
for (const skill of skills) {
|
|
135
|
+
lines.push(`- ${skill.name}: ${skill.description}`);
|
|
136
|
+
lines.push(` File: ${skill.filePath}`);
|
|
137
|
+
lines.push(` Base directory: ${skill.baseDir}`);
|
|
138
|
+
}
|
|
139
|
+
lines.push("</available_skills>");
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
113
142
|
export function loadSkills() {
|
|
114
143
|
const skillMap = new Map();
|
|
115
144
|
// Codex: recursive, simple directory name
|
|
116
145
|
const codexUserDir = join(homedir(), ".codex", "skills");
|
|
117
|
-
for (const skill of
|
|
146
|
+
for (const skill of loadSkillsFromDirInternal(codexUserDir, "codex-user", "recursive", false)) {
|
|
118
147
|
skillMap.set(skill.name, skill);
|
|
119
148
|
}
|
|
120
149
|
// Claude: single level only
|
|
121
150
|
const claudeUserDir = join(homedir(), ".claude", "skills");
|
|
122
|
-
for (const skill of
|
|
151
|
+
for (const skill of loadSkillsFromDirInternal(claudeUserDir, "claude-user", "claude", false)) {
|
|
123
152
|
skillMap.set(skill.name, skill);
|
|
124
153
|
}
|
|
125
154
|
const claudeProjectDir = resolve(process.cwd(), ".claude", "skills");
|
|
126
|
-
for (const skill of
|
|
155
|
+
for (const skill of loadSkillsFromDirInternal(claudeProjectDir, "claude-project", "claude", false)) {
|
|
127
156
|
skillMap.set(skill.name, skill);
|
|
128
157
|
}
|
|
129
158
|
// Pi: recursive, colon-separated path names
|
|
130
159
|
const globalSkillsDir = join(homedir(), CONFIG_DIR_NAME, "agent", "skills");
|
|
131
|
-
for (const skill of
|
|
160
|
+
for (const skill of loadSkillsFromDirInternal(globalSkillsDir, "user", "recursive", true)) {
|
|
132
161
|
skillMap.set(skill.name, skill);
|
|
133
162
|
}
|
|
134
163
|
const projectSkillsDir = resolve(process.cwd(), CONFIG_DIR_NAME, "skills");
|
|
135
|
-
for (const skill of
|
|
164
|
+
for (const skill of loadSkillsFromDirInternal(projectSkillsDir, "project", "recursive", true)) {
|
|
136
165
|
skillMap.set(skill.name, skill);
|
|
137
166
|
}
|
|
138
167
|
return Array.from(skillMap.values());
|
package/dist/core/skills.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { CONFIG_DIR_NAME } from \"../config.js\";\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription: string;\n}\n\nexport type SkillSource = \"user\" | \"project\" | \"claude-user\" | \"claude-project\" | \"codex-user\";\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsource: SkillSource;\n}\n\ntype SkillFormat = \"recursive\" | \"claude\";\n\nfunction stripQuotes(value: string): string {\n\tif ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n\t\treturn value.slice(1, -1);\n\t}\n\treturn value;\n}\n\nfunction parseFrontmatter(content: string): { frontmatter: SkillFrontmatter; body: string } {\n\tconst frontmatter: SkillFrontmatter = { description: \"\" };\n\n\tconst normalizedContent = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\tif (!normalizedContent.startsWith(\"---\")) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst endIndex = normalizedContent.indexOf(\"\\n---\", 3);\n\tif (endIndex === -1) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst frontmatterBlock = normalizedContent.slice(4, endIndex);\n\tconst body = normalizedContent.slice(endIndex + 4).trim();\n\n\tfor (const line of frontmatterBlock.split(\"\\n\")) {\n\t\tconst match = line.match(/^(\\w+):\\s*(.*)$/);\n\t\tif (match) {\n\t\t\tconst key = match[1];\n\t\t\tconst value = stripQuotes(match[2].trim());\n\t\t\tif (key === \"name\") {\n\t\t\t\tfrontmatter.name = value;\n\t\t\t} else if (key === \"description\") {\n\t\t\t\tfrontmatter.description = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { frontmatter, body };\n}\n\nfunction loadSkillsFromDir(\n\tdir: string,\n\tsource: SkillSource,\n\tformat: SkillFormat,\n\tuseColonPath: boolean = false,\n\tsubdir: string = \"\",\n): Skill[] {\n\tconst skills: Skill[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn skills;\n\t}\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tif (format === \"recursive\") {\n\t\t\t\t// Recursive format: scan directories, look for SKILL.md files\n\t\t\t\tif (entry.isDirectory()) {\n\t\t\t\t\tconst newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;\n\t\t\t\t\tskills.push(...loadSkillsFromDir(fullPath, source, format, useColonPath, newSubdir));\n\t\t\t\t} else if (entry.isFile() && entry.name === \"SKILL.md\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst rawContent = readFileSync(fullPath, \"utf-8\");\n\t\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst skillDir = dirname(fullPath);\n\t\t\t\t\t\t// useColonPath: db:migrate (pi), otherwise just: migrate (codex)\n\t\t\t\t\t\tconst nameFromPath = useColonPath ? subdir || basename(skillDir) : basename(skillDir);\n\t\t\t\t\t\tconst name = frontmatter.name || nameFromPath;\n\n\t\t\t\t\t\tskills.push({\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\t\tfilePath: fullPath,\n\t\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t} else if (format === \"claude\") {\n\t\t\t\t// Claude format: only one level deep, each directory must contain SKILL.md\n\t\t\t\tif (!entry.isDirectory()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst skillDir = fullPath;\n\t\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\t\tif (!existsSync(skillFile)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst rawContent = readFileSync(skillFile, \"utf-8\");\n\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst name = frontmatter.name || entry.name;\n\n\t\t\t\t\tskills.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\tfilePath: skillFile,\n\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t} catch {}\n\n\treturn skills;\n}\n\nexport function loadSkills(): Skill[] {\n\tconst skillMap = new Map<string, Skill>();\n\n\t// Codex: recursive, simple directory name\n\tconst codexUserDir = join(homedir(), \".codex\", \"skills\");\n\tfor (const skill of loadSkillsFromDir(codexUserDir, \"codex-user\", \"recursive\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Claude: single level only\n\tconst claudeUserDir = join(homedir(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDir(claudeUserDir, \"claude-user\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst claudeProjectDir = resolve(process.cwd(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDir(claudeProjectDir, \"claude-project\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Pi: recursive, colon-separated path names\n\tconst globalSkillsDir = join(homedir(), CONFIG_DIR_NAME, \"agent\", \"skills\");\n\tfor (const skill of loadSkillsFromDir(globalSkillsDir, \"user\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst projectSkillsDir = resolve(process.cwd(), CONFIG_DIR_NAME, \"skills\");\n\tfor (const skill of loadSkillsFromDir(projectSkillsDir, \"project\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\treturn Array.from(skillMap.values());\n}\n"]}
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readdirSync, readFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { CONFIG_DIR_NAME } from \"../config.js\";\n\nexport interface SkillFrontmatter {\n\tname?: string;\n\tdescription: string;\n}\n\nexport interface Skill {\n\tname: string;\n\tdescription: string;\n\tfilePath: string;\n\tbaseDir: string;\n\tsource: string;\n}\n\ntype SkillFormat = \"recursive\" | \"claude\";\n\nfunction stripQuotes(value: string): string {\n\tif ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n\t\treturn value.slice(1, -1);\n\t}\n\treturn value;\n}\n\nfunction parseFrontmatter(content: string): { frontmatter: SkillFrontmatter; body: string } {\n\tconst frontmatter: SkillFrontmatter = { description: \"\" };\n\n\tconst normalizedContent = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\n\tif (!normalizedContent.startsWith(\"---\")) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst endIndex = normalizedContent.indexOf(\"\\n---\", 3);\n\tif (endIndex === -1) {\n\t\treturn { frontmatter, body: normalizedContent };\n\t}\n\n\tconst frontmatterBlock = normalizedContent.slice(4, endIndex);\n\tconst body = normalizedContent.slice(endIndex + 4).trim();\n\n\tfor (const line of frontmatterBlock.split(\"\\n\")) {\n\t\tconst match = line.match(/^(\\w+):\\s*(.*)$/);\n\t\tif (match) {\n\t\t\tconst key = match[1];\n\t\t\tconst value = stripQuotes(match[2].trim());\n\t\t\tif (key === \"name\") {\n\t\t\t\tfrontmatter.name = value;\n\t\t\t} else if (key === \"description\") {\n\t\t\t\tfrontmatter.description = value;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { frontmatter, body };\n}\n\nexport interface LoadSkillsFromDirOptions {\n\t/** Directory to scan for skills */\n\tdir: string;\n\t/** Source identifier for these skills */\n\tsource: string;\n\t/** Use colon-separated path names (e.g., db:migrate) instead of simple directory name */\n\tuseColonPath?: boolean;\n}\n\n/**\n * Load skills from a directory recursively.\n * Skills are directories containing a SKILL.md file with frontmatter including a description.\n */\nexport function loadSkillsFromDir(options: LoadSkillsFromDirOptions, subdir: string = \"\"): Skill[] {\n\tconst { dir, source, useColonPath = false } = options;\n\treturn loadSkillsFromDirInternal(dir, source, \"recursive\", useColonPath, subdir);\n}\n\nfunction loadSkillsFromDirInternal(\n\tdir: string,\n\tsource: string,\n\tformat: SkillFormat,\n\tuseColonPath: boolean = false,\n\tsubdir: string = \"\",\n): Skill[] {\n\tconst skills: Skill[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn skills;\n\t}\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tif (entry.name.startsWith(\".\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tif (format === \"recursive\") {\n\t\t\t\t// Recursive format: scan directories, look for SKILL.md files\n\t\t\t\tif (entry.isDirectory()) {\n\t\t\t\t\tconst newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;\n\t\t\t\t\tskills.push(...loadSkillsFromDirInternal(fullPath, source, format, useColonPath, newSubdir));\n\t\t\t\t} else if (entry.isFile() && entry.name === \"SKILL.md\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst rawContent = readFileSync(fullPath, \"utf-8\");\n\t\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst skillDir = dirname(fullPath);\n\t\t\t\t\t\t// useColonPath: db:migrate (pi), otherwise just: migrate (codex)\n\t\t\t\t\t\tconst nameFromPath = useColonPath ? subdir || basename(skillDir) : basename(skillDir);\n\t\t\t\t\t\tconst name = frontmatter.name || nameFromPath;\n\n\t\t\t\t\t\tskills.push({\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\t\tfilePath: fullPath,\n\t\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch {}\n\t\t\t\t}\n\t\t\t} else if (format === \"claude\") {\n\t\t\t\t// Claude format: only one level deep, each directory must contain SKILL.md\n\t\t\t\tif (!entry.isDirectory()) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst skillDir = fullPath;\n\t\t\t\tconst skillFile = join(skillDir, \"SKILL.md\");\n\n\t\t\t\tif (!existsSync(skillFile)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst rawContent = readFileSync(skillFile, \"utf-8\");\n\t\t\t\t\tconst { frontmatter } = parseFrontmatter(rawContent);\n\n\t\t\t\t\tif (!frontmatter.description) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst name = frontmatter.name || entry.name;\n\n\t\t\t\t\tskills.push({\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tdescription: frontmatter.description,\n\t\t\t\t\t\tfilePath: skillFile,\n\t\t\t\t\t\tbaseDir: skillDir,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t} catch {}\n\n\treturn skills;\n}\n\n/**\n * Format skills for inclusion in a system prompt.\n */\nexport function formatSkillsForPrompt(skills: Skill[]): string {\n\tif (skills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\n\t\t\"\\n\\n<available_skills>\",\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Use the read tool to load a skill's file when the task matches its description.\",\n\t\t\"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\\n\",\n\t];\n\n\tfor (const skill of skills) {\n\t\tlines.push(`- ${skill.name}: ${skill.description}`);\n\t\tlines.push(` File: ${skill.filePath}`);\n\t\tlines.push(` Base directory: ${skill.baseDir}`);\n\t}\n\n\tlines.push(\"</available_skills>\");\n\n\treturn lines.join(\"\\n\");\n}\n\nexport function loadSkills(): Skill[] {\n\tconst skillMap = new Map<string, Skill>();\n\n\t// Codex: recursive, simple directory name\n\tconst codexUserDir = join(homedir(), \".codex\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(codexUserDir, \"codex-user\", \"recursive\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Claude: single level only\n\tconst claudeUserDir = join(homedir(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(claudeUserDir, \"claude-user\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst claudeProjectDir = resolve(process.cwd(), \".claude\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(claudeProjectDir, \"claude-project\", \"claude\", false)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\t// Pi: recursive, colon-separated path names\n\tconst globalSkillsDir = join(homedir(), CONFIG_DIR_NAME, \"agent\", \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(globalSkillsDir, \"user\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\tconst projectSkillsDir = resolve(process.cwd(), CONFIG_DIR_NAME, \"skills\");\n\tfor (const skill of loadSkillsFromDirInternal(projectSkillsDir, \"project\", \"recursive\", true)) {\n\t\tskillMap.set(skill.name, skill);\n\t}\n\n\treturn Array.from(skillMap.values());\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAkDjD;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAqClF;AAyBD,MAAM,WAAW,wBAAwB;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,MAAM,CA0JhF","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join, resolve } from \"path\";\nimport { getAgentDir, getDocsPath, getReadmePath } from \"../config.js\";\nimport { loadSkills, type Skill } from \"./skills.js\";\nimport type { ToolName } from \"./tools/index.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<ToolName, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n};\n\n/** Resolve input as file path or literal string */\nfunction resolvePromptInput(input: string | undefined, description: string): string | undefined {\n\tif (!input) {\n\t\treturn undefined;\n\t}\n\n\tif (existsSync(input)) {\n\t\ttry {\n\t\t\treturn readFileSync(input, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${description} file ${input}: ${error}`));\n\t\t\treturn input;\n\t\t}\n\t}\n\n\treturn input;\n}\n\n/** Look for AGENTS.md or CLAUDE.md in a directory (prefers AGENTS.md) */\nfunction loadContextFileFromDir(dir: string): { path: string; content: string } | null {\n\tconst candidates = [\"AGENTS.md\", \"CLAUDE.md\"];\n\tfor (const filename of candidates) {\n\t\tconst filePath = join(dir, filename);\n\t\tif (existsSync(filePath)) {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tcontent: readFileSync(filePath, \"utf-8\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Load all project context files in order:\n * 1. Global: ~/{CONFIG_DIR_NAME}/agent/AGENTS.md or CLAUDE.md\n * 2. Parent directories (top-most first) down to cwd\n * Each returns {path, content} for separate messages\n */\nexport function loadProjectContextFiles(): Array<{ path: string; content: string }> {\n\tconst contextFiles: Array<{ path: string; content: string }> = [];\n\n\t// 1. Load global context from ~/{CONFIG_DIR_NAME}/agent/\n\tconst globalContextDir = getAgentDir();\n\tconst globalContext = loadContextFileFromDir(globalContextDir);\n\tif (globalContext) {\n\t\tcontextFiles.push(globalContext);\n\t}\n\n\t// 2. Walk up from cwd to root, collecting all context files\n\tconst cwd = process.cwd();\n\tconst ancestorContextFiles: Array<{ path: string; content: string }> = [];\n\n\tlet currentDir = cwd;\n\tconst root = resolve(\"/\");\n\n\twhile (true) {\n\t\tconst contextFile = loadContextFileFromDir(currentDir);\n\t\tif (contextFile) {\n\t\t\t// Add to beginning so we get top-most parent first\n\t\t\tancestorContextFiles.unshift(contextFile);\n\t\t}\n\n\t\t// Stop if we've reached root\n\t\tif (currentDir === root) break;\n\n\t\t// Move up one directory\n\t\tconst parentDir = resolve(currentDir, \"..\");\n\t\tif (parentDir === currentDir) break; // Safety check\n\t\tcurrentDir = parentDir;\n\t}\n\n\t// Add ancestor files in order (top-most → cwd)\n\tcontextFiles.push(...ancestorContextFiles);\n\n\treturn contextFiles;\n}\n\nfunction buildSkillsSection(skills: Skill[]): string {\n\tif (skills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\n\t\t\"\\n\\n<available_skills>\",\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Use the read tool to load a skill's file when the task matches its description.\",\n\t\t\"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\\n\",\n\t];\n\n\tfor (const skill of skills) {\n\t\tlines.push(`- ${skill.name}: ${skill.description}`);\n\t\tlines.push(` File: ${skill.filePath}`);\n\t\tlines.push(` Base directory: ${skill.baseDir}`);\n\t}\n\n\tlines.push(\"</available_skills>\");\n\n\treturn lines.join(\"\\n\");\n}\n\nexport interface BuildSystemPromptOptions {\n\tcustomPrompt?: string;\n\tselectedTools?: ToolName[];\n\tappendSystemPrompt?: string;\n\tskillsEnabled?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst { customPrompt, selectedTools, appendSystemPrompt, skillsEnabled = true } = options;\n\tconst resolvedCustomPrompt = resolvePromptInput(customPrompt, \"system prompt\");\n\tconst resolvedAppendPrompt = resolvePromptInput(appendSystemPrompt, \"append system prompt\");\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = resolvedAppendPrompt ? `\\n\\n${resolvedAppendPrompt}` : \"\";\n\n\tif (resolvedCustomPrompt) {\n\t\tlet prompt = resolvedCustomPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (skillsEnabled && customPromptHasRead) {\n\t\t\tconst skills = loadSkills();\n\t\t\tprompt += buildSkillsSection(skills);\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\n\t// Build tools list based on selected tools\n\tconst tools = selectedTools || ([\"read\", \"bash\", \"edit\", \"write\"] as ToolName[]);\n\tconst toolsList = tools.map((t) => `- ${t}: ${toolDescriptions[t]}`).join(\"\\n\");\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// Read-only mode notice (no bash, edit, or write)\n\tif (!hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\"You are in READ-ONLY mode - you cannot modify files or execute arbitrary commands\");\n\t}\n\n\t// Bash without edit/write = read-only bash mode\n\tif (hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"Use bash ONLY for read-only operations (git log, gh issue view, curl, etc.) - do NOT modify any files\",\n\t\t);\n\t}\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tguidelinesList.push(\"Use bash for file operations like ls, grep, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tguidelinesList.push(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\tguidelinesList.push(\"Use read to examine files before editing\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\tguidelinesList.push(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\tguidelinesList.push(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// Output guideline (only when actually writing/executing)\n\tif (hasEdit || hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\t// Always include these\n\tguidelinesList.push(\"Be concise in your responses\");\n\tguidelinesList.push(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nGuidelines:\n${guidelines}\n\nDocumentation:\n- Your own documentation (including custom model setup and theme creation) is at: ${readmePath}\n- Additional documentation (hooks, themes, RPC, etc.) is in: ${docsPath}\n- Read it when users ask about features, configuration, or setup, and especially if the user asks you to add a custom model or provider, create a custom theme, or write a hook.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tconst contextFiles = loadProjectContextFiles();\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (skillsEnabled && hasRead) {\n\t\tconst skills = loadSkills();\n\t\tprompt += buildSkillsSection(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAkDjD;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAqClF;AAED,MAAM,WAAW,wBAAwB;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,MAAM,CA0JhF","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join, resolve } from \"path\";\nimport { getAgentDir, getDocsPath, getReadmePath } from \"../config.js\";\nimport { formatSkillsForPrompt, loadSkills } from \"./skills.js\";\nimport type { ToolName } from \"./tools/index.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<ToolName, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n};\n\n/** Resolve input as file path or literal string */\nfunction resolvePromptInput(input: string | undefined, description: string): string | undefined {\n\tif (!input) {\n\t\treturn undefined;\n\t}\n\n\tif (existsSync(input)) {\n\t\ttry {\n\t\t\treturn readFileSync(input, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${description} file ${input}: ${error}`));\n\t\t\treturn input;\n\t\t}\n\t}\n\n\treturn input;\n}\n\n/** Look for AGENTS.md or CLAUDE.md in a directory (prefers AGENTS.md) */\nfunction loadContextFileFromDir(dir: string): { path: string; content: string } | null {\n\tconst candidates = [\"AGENTS.md\", \"CLAUDE.md\"];\n\tfor (const filename of candidates) {\n\t\tconst filePath = join(dir, filename);\n\t\tif (existsSync(filePath)) {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tcontent: readFileSync(filePath, \"utf-8\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Load all project context files in order:\n * 1. Global: ~/{CONFIG_DIR_NAME}/agent/AGENTS.md or CLAUDE.md\n * 2. Parent directories (top-most first) down to cwd\n * Each returns {path, content} for separate messages\n */\nexport function loadProjectContextFiles(): Array<{ path: string; content: string }> {\n\tconst contextFiles: Array<{ path: string; content: string }> = [];\n\n\t// 1. Load global context from ~/{CONFIG_DIR_NAME}/agent/\n\tconst globalContextDir = getAgentDir();\n\tconst globalContext = loadContextFileFromDir(globalContextDir);\n\tif (globalContext) {\n\t\tcontextFiles.push(globalContext);\n\t}\n\n\t// 2. Walk up from cwd to root, collecting all context files\n\tconst cwd = process.cwd();\n\tconst ancestorContextFiles: Array<{ path: string; content: string }> = [];\n\n\tlet currentDir = cwd;\n\tconst root = resolve(\"/\");\n\n\twhile (true) {\n\t\tconst contextFile = loadContextFileFromDir(currentDir);\n\t\tif (contextFile) {\n\t\t\t// Add to beginning so we get top-most parent first\n\t\t\tancestorContextFiles.unshift(contextFile);\n\t\t}\n\n\t\t// Stop if we've reached root\n\t\tif (currentDir === root) break;\n\n\t\t// Move up one directory\n\t\tconst parentDir = resolve(currentDir, \"..\");\n\t\tif (parentDir === currentDir) break; // Safety check\n\t\tcurrentDir = parentDir;\n\t}\n\n\t// Add ancestor files in order (top-most → cwd)\n\tcontextFiles.push(...ancestorContextFiles);\n\n\treturn contextFiles;\n}\n\nexport interface BuildSystemPromptOptions {\n\tcustomPrompt?: string;\n\tselectedTools?: ToolName[];\n\tappendSystemPrompt?: string;\n\tskillsEnabled?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst { customPrompt, selectedTools, appendSystemPrompt, skillsEnabled = true } = options;\n\tconst resolvedCustomPrompt = resolvePromptInput(customPrompt, \"system prompt\");\n\tconst resolvedAppendPrompt = resolvePromptInput(appendSystemPrompt, \"append system prompt\");\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = resolvedAppendPrompt ? `\\n\\n${resolvedAppendPrompt}` : \"\";\n\n\tif (resolvedCustomPrompt) {\n\t\tlet prompt = resolvedCustomPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (skillsEnabled && customPromptHasRead) {\n\t\t\tconst skills = loadSkills();\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\n\t// Build tools list based on selected tools\n\tconst tools = selectedTools || ([\"read\", \"bash\", \"edit\", \"write\"] as ToolName[]);\n\tconst toolsList = tools.map((t) => `- ${t}: ${toolDescriptions[t]}`).join(\"\\n\");\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// Read-only mode notice (no bash, edit, or write)\n\tif (!hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\"You are in READ-ONLY mode - you cannot modify files or execute arbitrary commands\");\n\t}\n\n\t// Bash without edit/write = read-only bash mode\n\tif (hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"Use bash ONLY for read-only operations (git log, gh issue view, curl, etc.) - do NOT modify any files\",\n\t\t);\n\t}\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tguidelinesList.push(\"Use bash for file operations like ls, grep, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tguidelinesList.push(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\tguidelinesList.push(\"Use read to examine files before editing\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\tguidelinesList.push(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\tguidelinesList.push(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// Output guideline (only when actually writing/executing)\n\tif (hasEdit || hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\t// Always include these\n\tguidelinesList.push(\"Be concise in your responses\");\n\tguidelinesList.push(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nGuidelines:\n${guidelines}\n\nDocumentation:\n- Your own documentation (including custom model setup and theme creation) is at: ${readmePath}\n- Additional documentation (hooks, themes, RPC, etc.) is in: ${docsPath}\n- Read it when users ask about features, configuration, or setup, and especially if the user asks you to add a custom model or provider, create a custom theme, or write a hook.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tconst contextFiles = loadProjectContextFiles();\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (skillsEnabled && hasRead) {\n\t\tconst skills = loadSkills();\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -5,7 +5,7 @@ import chalk from "chalk";
|
|
|
5
5
|
import { existsSync, readFileSync } from "fs";
|
|
6
6
|
import { join, resolve } from "path";
|
|
7
7
|
import { getAgentDir, getDocsPath, getReadmePath } from "../config.js";
|
|
8
|
-
import { loadSkills } from "./skills.js";
|
|
8
|
+
import { formatSkillsForPrompt, loadSkills } from "./skills.js";
|
|
9
9
|
/** Tool descriptions for system prompt */
|
|
10
10
|
const toolDescriptions = {
|
|
11
11
|
read: "Read file contents",
|
|
@@ -89,24 +89,6 @@ export function loadProjectContextFiles() {
|
|
|
89
89
|
contextFiles.push(...ancestorContextFiles);
|
|
90
90
|
return contextFiles;
|
|
91
91
|
}
|
|
92
|
-
function buildSkillsSection(skills) {
|
|
93
|
-
if (skills.length === 0) {
|
|
94
|
-
return "";
|
|
95
|
-
}
|
|
96
|
-
const lines = [
|
|
97
|
-
"\n\n<available_skills>",
|
|
98
|
-
"The following skills provide specialized instructions for specific tasks.",
|
|
99
|
-
"Use the read tool to load a skill's file when the task matches its description.",
|
|
100
|
-
"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\n",
|
|
101
|
-
];
|
|
102
|
-
for (const skill of skills) {
|
|
103
|
-
lines.push(`- ${skill.name}: ${skill.description}`);
|
|
104
|
-
lines.push(` File: ${skill.filePath}`);
|
|
105
|
-
lines.push(` Base directory: ${skill.baseDir}`);
|
|
106
|
-
}
|
|
107
|
-
lines.push("</available_skills>");
|
|
108
|
-
return lines.join("\n");
|
|
109
|
-
}
|
|
110
92
|
/** Build the system prompt with tools, guidelines, and context */
|
|
111
93
|
export function buildSystemPrompt(options = {}) {
|
|
112
94
|
const { customPrompt, selectedTools, appendSystemPrompt, skillsEnabled = true } = options;
|
|
@@ -142,7 +124,7 @@ export function buildSystemPrompt(options = {}) {
|
|
|
142
124
|
const customPromptHasRead = !selectedTools || selectedTools.includes("read");
|
|
143
125
|
if (skillsEnabled && customPromptHasRead) {
|
|
144
126
|
const skills = loadSkills();
|
|
145
|
-
prompt +=
|
|
127
|
+
prompt += formatSkillsForPrompt(skills);
|
|
146
128
|
}
|
|
147
129
|
// Add date/time and working directory last
|
|
148
130
|
prompt += `\nCurrent date and time: ${dateTime}`;
|
|
@@ -226,7 +208,7 @@ Documentation:
|
|
|
226
208
|
// Append skills section (only if read tool is available)
|
|
227
209
|
if (skillsEnabled && hasRead) {
|
|
228
210
|
const skills = loadSkills();
|
|
229
|
-
prompt +=
|
|
211
|
+
prompt += formatSkillsForPrompt(skills);
|
|
230
212
|
}
|
|
231
213
|
// Add date/time and working directory last
|
|
232
214
|
prompt += `\nCurrent date and time: ${dateTime}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join, resolve } from \"path\";\nimport { getAgentDir, getDocsPath, getReadmePath } from \"../config.js\";\nimport { loadSkills, type Skill } from \"./skills.js\";\nimport type { ToolName } from \"./tools/index.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<ToolName, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n};\n\n/** Resolve input as file path or literal string */\nfunction resolvePromptInput(input: string | undefined, description: string): string | undefined {\n\tif (!input) {\n\t\treturn undefined;\n\t}\n\n\tif (existsSync(input)) {\n\t\ttry {\n\t\t\treturn readFileSync(input, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${description} file ${input}: ${error}`));\n\t\t\treturn input;\n\t\t}\n\t}\n\n\treturn input;\n}\n\n/** Look for AGENTS.md or CLAUDE.md in a directory (prefers AGENTS.md) */\nfunction loadContextFileFromDir(dir: string): { path: string; content: string } | null {\n\tconst candidates = [\"AGENTS.md\", \"CLAUDE.md\"];\n\tfor (const filename of candidates) {\n\t\tconst filePath = join(dir, filename);\n\t\tif (existsSync(filePath)) {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tcontent: readFileSync(filePath, \"utf-8\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Load all project context files in order:\n * 1. Global: ~/{CONFIG_DIR_NAME}/agent/AGENTS.md or CLAUDE.md\n * 2. Parent directories (top-most first) down to cwd\n * Each returns {path, content} for separate messages\n */\nexport function loadProjectContextFiles(): Array<{ path: string; content: string }> {\n\tconst contextFiles: Array<{ path: string; content: string }> = [];\n\n\t// 1. Load global context from ~/{CONFIG_DIR_NAME}/agent/\n\tconst globalContextDir = getAgentDir();\n\tconst globalContext = loadContextFileFromDir(globalContextDir);\n\tif (globalContext) {\n\t\tcontextFiles.push(globalContext);\n\t}\n\n\t// 2. Walk up from cwd to root, collecting all context files\n\tconst cwd = process.cwd();\n\tconst ancestorContextFiles: Array<{ path: string; content: string }> = [];\n\n\tlet currentDir = cwd;\n\tconst root = resolve(\"/\");\n\n\twhile (true) {\n\t\tconst contextFile = loadContextFileFromDir(currentDir);\n\t\tif (contextFile) {\n\t\t\t// Add to beginning so we get top-most parent first\n\t\t\tancestorContextFiles.unshift(contextFile);\n\t\t}\n\n\t\t// Stop if we've reached root\n\t\tif (currentDir === root) break;\n\n\t\t// Move up one directory\n\t\tconst parentDir = resolve(currentDir, \"..\");\n\t\tif (parentDir === currentDir) break; // Safety check\n\t\tcurrentDir = parentDir;\n\t}\n\n\t// Add ancestor files in order (top-most → cwd)\n\tcontextFiles.push(...ancestorContextFiles);\n\n\treturn contextFiles;\n}\n\nfunction buildSkillsSection(skills: Skill[]): string {\n\tif (skills.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\n\t\t\"\\n\\n<available_skills>\",\n\t\t\"The following skills provide specialized instructions for specific tasks.\",\n\t\t\"Use the read tool to load a skill's file when the task matches its description.\",\n\t\t\"Skills may contain {baseDir} placeholders - replace them with the skill's base directory path.\\n\",\n\t];\n\n\tfor (const skill of skills) {\n\t\tlines.push(`- ${skill.name}: ${skill.description}`);\n\t\tlines.push(` File: ${skill.filePath}`);\n\t\tlines.push(` Base directory: ${skill.baseDir}`);\n\t}\n\n\tlines.push(\"</available_skills>\");\n\n\treturn lines.join(\"\\n\");\n}\n\nexport interface BuildSystemPromptOptions {\n\tcustomPrompt?: string;\n\tselectedTools?: ToolName[];\n\tappendSystemPrompt?: string;\n\tskillsEnabled?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst { customPrompt, selectedTools, appendSystemPrompt, skillsEnabled = true } = options;\n\tconst resolvedCustomPrompt = resolvePromptInput(customPrompt, \"system prompt\");\n\tconst resolvedAppendPrompt = resolvePromptInput(appendSystemPrompt, \"append system prompt\");\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = resolvedAppendPrompt ? `\\n\\n${resolvedAppendPrompt}` : \"\";\n\n\tif (resolvedCustomPrompt) {\n\t\tlet prompt = resolvedCustomPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (skillsEnabled && customPromptHasRead) {\n\t\t\tconst skills = loadSkills();\n\t\t\tprompt += buildSkillsSection(skills);\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\n\t// Build tools list based on selected tools\n\tconst tools = selectedTools || ([\"read\", \"bash\", \"edit\", \"write\"] as ToolName[]);\n\tconst toolsList = tools.map((t) => `- ${t}: ${toolDescriptions[t]}`).join(\"\\n\");\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// Read-only mode notice (no bash, edit, or write)\n\tif (!hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\"You are in READ-ONLY mode - you cannot modify files or execute arbitrary commands\");\n\t}\n\n\t// Bash without edit/write = read-only bash mode\n\tif (hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"Use bash ONLY for read-only operations (git log, gh issue view, curl, etc.) - do NOT modify any files\",\n\t\t);\n\t}\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tguidelinesList.push(\"Use bash for file operations like ls, grep, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tguidelinesList.push(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\tguidelinesList.push(\"Use read to examine files before editing\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\tguidelinesList.push(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\tguidelinesList.push(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// Output guideline (only when actually writing/executing)\n\tif (hasEdit || hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\t// Always include these\n\tguidelinesList.push(\"Be concise in your responses\");\n\tguidelinesList.push(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nGuidelines:\n${guidelines}\n\nDocumentation:\n- Your own documentation (including custom model setup and theme creation) is at: ${readmePath}\n- Additional documentation (hooks, themes, RPC, etc.) is in: ${docsPath}\n- Read it when users ask about features, configuration, or setup, and especially if the user asks you to add a custom model or provider, create a custom theme, or write a hook.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tconst contextFiles = loadProjectContextFiles();\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (skillsEnabled && hasRead) {\n\t\tconst skills = loadSkills();\n\t\tprompt += buildSkillsSection(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGhE,0CAA0C;AAC1C,MAAM,gBAAgB,GAA6B;IAClD,IAAI,EAAE,oBAAoB;IAC1B,IAAI,EAAE,8CAA8C;IACpD,IAAI,EAAE,4DAA4D;IAClE,KAAK,EAAE,2BAA2B;IAClC,IAAI,EAAE,yDAAyD;IAC/D,IAAI,EAAE,kDAAkD;IACxD,EAAE,EAAE,yBAAyB;CAC7B,CAAC;AAEF,mDAAmD;AACnD,SAAS,kBAAkB,CAAC,KAAyB,EAAE,WAAmB,EAAsB;IAC/F,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC;YACJ,OAAO,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,WAAW,SAAS,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC;YAC9F,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AAAA,CACb;AAED,yEAAyE;AACzE,SAAS,sBAAsB,CAAC,GAAW,EAA4C;IACtF,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC9C,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACrC,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACJ,OAAO;oBACN,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;iBACxC,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,QAAQ,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC;YAC9E,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,GAA6C;IACnF,MAAM,YAAY,GAA6C,EAAE,CAAC;IAElE,yDAAyD;IACzD,MAAM,gBAAgB,GAAG,WAAW,EAAE,CAAC;IACvC,MAAM,aAAa,GAAG,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IAC/D,IAAI,aAAa,EAAE,CAAC;QACnB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IAED,4DAA4D;IAC5D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,oBAAoB,GAA6C,EAAE,CAAC;IAE1E,IAAI,UAAU,GAAG,GAAG,CAAC;IACrB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAE1B,OAAO,IAAI,EAAE,CAAC;QACb,MAAM,WAAW,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,WAAW,EAAE,CAAC;YACjB,mDAAmD;YACnD,oBAAoB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC3C,CAAC;QAED,6BAA6B;QAC7B,IAAI,UAAU,KAAK,IAAI;YAAE,MAAM;QAE/B,wBAAwB;QACxB,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC5C,IAAI,SAAS,KAAK,UAAU;YAAE,MAAM,CAAC,eAAe;QACpD,UAAU,GAAG,SAAS,CAAC;IACxB,CAAC;IAED,iDAA+C;IAC/C,YAAY,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,CAAC;IAE3C,OAAO,YAAY,CAAC;AAAA,CACpB;AASD,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,OAAO,GAA6B,EAAE,EAAU;IACjF,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAC1F,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IAC/E,MAAM,oBAAoB,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,sBAAsB,CAAC,CAAC;IAE5F,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE;QAC5C,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,OAAO;KACrB,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,oBAAoB,CAAC,CAAC,CAAC,OAAO,oBAAoB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEhF,IAAI,oBAAoB,EAAE,CAAC;QAC1B,IAAI,MAAM,GAAG,oBAAoB,CAAC;QAElC,IAAI,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,aAAa,CAAC;QACzB,CAAC;QAED,+BAA+B;QAC/B,MAAM,YAAY,GAAG,uBAAuB,EAAE,CAAC;QAC/C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,2BAA2B,CAAC;YACtC,MAAM,IAAI,2DAA2D,CAAC;YACtE,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;gBACxD,MAAM,IAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC;YAC9C,CAAC;QACF,CAAC;QAED,yDAAyD;QACzD,MAAM,mBAAmB,GAAG,CAAC,aAAa,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7E,IAAI,aAAa,IAAI,mBAAmB,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;YAC5B,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,2CAA2C;QAC3C,MAAM,IAAI,4BAA4B,QAAQ,EAAE,CAAC;QACjD,MAAM,IAAI,gCAAgC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;QAE1D,OAAO,MAAM,CAAC;IACf,CAAC;IAED,sCAAsC;IACtC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAE/B,2CAA2C;IAC3C,MAAM,KAAK,GAAG,aAAa,IAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAgB,CAAC;IACjF,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhF,+DAA+D;IAC/D,MAAM,cAAc,GAAa,EAAE,CAAC;IAEpC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEvC,kDAAkD;IAClD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvC,cAAc,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;IAC1G,CAAC;IAED,gDAAgD;IAChD,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtC,cAAc,CAAC,IAAI,CAClB,uGAAuG,CACvG,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/C,cAAc,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IACzE,CAAC;SAAM,IAAI,OAAO,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;IAC/G,CAAC;IAED,6BAA6B;IAC7B,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;QACxB,cAAc,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACjE,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAO,EAAE,CAAC;QACb,cAAc,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IACnF,CAAC;IAED,kBAAkB;IAClB,IAAI,QAAQ,EAAE,CAAC;QACd,cAAc,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IAC1E,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;QACzB,cAAc,CAAC,IAAI,CAClB,4GAA4G,CAC5G,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,cAAc,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IACpD,cAAc,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAElE,IAAI,MAAM,GAAG;;;EAGZ,SAAS;;;EAGT,UAAU;;;oFAGwE,UAAU;+DAC/B,QAAQ;iLAC0G,CAAC;IAEjL,IAAI,aAAa,EAAE,CAAC;QACnB,MAAM,IAAI,aAAa,CAAC;IACzB,CAAC;IAED,+BAA+B;IAC/B,MAAM,YAAY,GAAG,uBAAuB,EAAE,CAAC;IAC/C,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,2BAA2B,CAAC;QACtC,MAAM,IAAI,2DAA2D,CAAC;QACtE,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,YAAY,EAAE,CAAC;YACxD,MAAM,IAAI,MAAM,QAAQ,OAAO,OAAO,MAAM,CAAC;QAC9C,CAAC;IACF,CAAC;IAED,yDAAyD;IACzD,IAAI,aAAa,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;QAC5B,MAAM,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAED,2CAA2C;IAC3C,MAAM,IAAI,4BAA4B,QAAQ,EAAE,CAAC;IACjD,MAAM,IAAI,gCAAgC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC;IAE1D,OAAO,MAAM,CAAC;AAAA,CACd","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport chalk from \"chalk\";\nimport { existsSync, readFileSync } from \"fs\";\nimport { join, resolve } from \"path\";\nimport { getAgentDir, getDocsPath, getReadmePath } from \"../config.js\";\nimport { formatSkillsForPrompt, loadSkills } from \"./skills.js\";\nimport type { ToolName } from \"./tools/index.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<ToolName, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n};\n\n/** Resolve input as file path or literal string */\nfunction resolvePromptInput(input: string | undefined, description: string): string | undefined {\n\tif (!input) {\n\t\treturn undefined;\n\t}\n\n\tif (existsSync(input)) {\n\t\ttry {\n\t\t\treturn readFileSync(input, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${description} file ${input}: ${error}`));\n\t\t\treturn input;\n\t\t}\n\t}\n\n\treturn input;\n}\n\n/** Look for AGENTS.md or CLAUDE.md in a directory (prefers AGENTS.md) */\nfunction loadContextFileFromDir(dir: string): { path: string; content: string } | null {\n\tconst candidates = [\"AGENTS.md\", \"CLAUDE.md\"];\n\tfor (const filename of candidates) {\n\t\tconst filePath = join(dir, filename);\n\t\tif (existsSync(filePath)) {\n\t\t\ttry {\n\t\t\t\treturn {\n\t\t\t\t\tpath: filePath,\n\t\t\t\t\tcontent: readFileSync(filePath, \"utf-8\"),\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(chalk.yellow(`Warning: Could not read ${filePath}: ${error}`));\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * Load all project context files in order:\n * 1. Global: ~/{CONFIG_DIR_NAME}/agent/AGENTS.md or CLAUDE.md\n * 2. Parent directories (top-most first) down to cwd\n * Each returns {path, content} for separate messages\n */\nexport function loadProjectContextFiles(): Array<{ path: string; content: string }> {\n\tconst contextFiles: Array<{ path: string; content: string }> = [];\n\n\t// 1. Load global context from ~/{CONFIG_DIR_NAME}/agent/\n\tconst globalContextDir = getAgentDir();\n\tconst globalContext = loadContextFileFromDir(globalContextDir);\n\tif (globalContext) {\n\t\tcontextFiles.push(globalContext);\n\t}\n\n\t// 2. Walk up from cwd to root, collecting all context files\n\tconst cwd = process.cwd();\n\tconst ancestorContextFiles: Array<{ path: string; content: string }> = [];\n\n\tlet currentDir = cwd;\n\tconst root = resolve(\"/\");\n\n\twhile (true) {\n\t\tconst contextFile = loadContextFileFromDir(currentDir);\n\t\tif (contextFile) {\n\t\t\t// Add to beginning so we get top-most parent first\n\t\t\tancestorContextFiles.unshift(contextFile);\n\t\t}\n\n\t\t// Stop if we've reached root\n\t\tif (currentDir === root) break;\n\n\t\t// Move up one directory\n\t\tconst parentDir = resolve(currentDir, \"..\");\n\t\tif (parentDir === currentDir) break; // Safety check\n\t\tcurrentDir = parentDir;\n\t}\n\n\t// Add ancestor files in order (top-most → cwd)\n\tcontextFiles.push(...ancestorContextFiles);\n\n\treturn contextFiles;\n}\n\nexport interface BuildSystemPromptOptions {\n\tcustomPrompt?: string;\n\tselectedTools?: ToolName[];\n\tappendSystemPrompt?: string;\n\tskillsEnabled?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst { customPrompt, selectedTools, appendSystemPrompt, skillsEnabled = true } = options;\n\tconst resolvedCustomPrompt = resolvePromptInput(customPrompt, \"system prompt\");\n\tconst resolvedAppendPrompt = resolvePromptInput(appendSystemPrompt, \"append system prompt\");\n\n\tconst now = new Date();\n\tconst dateTime = now.toLocaleString(\"en-US\", {\n\t\tweekday: \"long\",\n\t\tyear: \"numeric\",\n\t\tmonth: \"long\",\n\t\tday: \"numeric\",\n\t\thour: \"2-digit\",\n\t\tminute: \"2-digit\",\n\t\tsecond: \"2-digit\",\n\t\ttimeZoneName: \"short\",\n\t});\n\n\tconst appendSection = resolvedAppendPrompt ? `\\n\\n${resolvedAppendPrompt}` : \"\";\n\n\tif (resolvedCustomPrompt) {\n\t\tlet prompt = resolvedCustomPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tconst contextFiles = loadProjectContextFiles();\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (skillsEnabled && customPromptHasRead) {\n\t\t\tconst skills = loadSkills();\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date/time and working directory last\n\t\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\t\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\n\t// Build tools list based on selected tools\n\tconst tools = selectedTools || ([\"read\", \"bash\", \"edit\", \"write\"] as ToolName[]);\n\tconst toolsList = tools.map((t) => `- ${t}: ${toolDescriptions[t]}`).join(\"\\n\");\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\n\t// Read-only mode notice (no bash, edit, or write)\n\tif (!hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\"You are in READ-ONLY mode - you cannot modify files or execute arbitrary commands\");\n\t}\n\n\t// Bash without edit/write = read-only bash mode\n\tif (hasBash && !hasEdit && !hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"Use bash ONLY for read-only operations (git log, gh issue view, curl, etc.) - do NOT modify any files\",\n\t\t);\n\t}\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\tguidelinesList.push(\"Use bash for file operations like ls, grep, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\tguidelinesList.push(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\tguidelinesList.push(\"Use read to examine files before editing\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\tguidelinesList.push(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\tguidelinesList.push(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// Output guideline (only when actually writing/executing)\n\tif (hasEdit || hasWrite) {\n\t\tguidelinesList.push(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\t// Always include these\n\tguidelinesList.push(\"Be concise in your responses\");\n\tguidelinesList.push(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant. You help users with coding tasks by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nGuidelines:\n${guidelines}\n\nDocumentation:\n- Your own documentation (including custom model setup and theme creation) is at: ${readmePath}\n- Additional documentation (hooks, themes, RPC, etc.) is in: ${docsPath}\n- Read it when users ask about features, configuration, or setup, and especially if the user asks you to add a custom model or provider, create a custom theme, or write a hook.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tconst contextFiles = loadProjectContextFiles();\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"The following project context files have been loaded:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (only if read tool is available)\n\tif (skillsEnabled && hasRead) {\n\t\tconst skills = loadSkills();\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time and working directory last\n\tprompt += `\\nCurrent date and time: ${dateTime}`;\n\tprompt += `\\nCurrent working directory: ${process.cwd()}`;\n\n\treturn prompt;\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type { AgentEndEvent, AgentStartEvent, BranchEvent, BranchEventResult, Ho
|
|
|
4
4
|
export { messageTransformer } from "./core/messages.js";
|
|
5
5
|
export { type CompactionEntry, createSummaryMessage, getLatestCompactionEntry, type LoadedSession, loadSessionFromEntries, type ModelChangeEntry, parseSessionEntries, type SessionEntry, type SessionHeader, SessionManager, type SessionMessageEntry, SUMMARY_PREFIX, SUMMARY_SUFFIX, type ThinkingLevelChangeEntry, } from "./core/session-manager.js";
|
|
6
6
|
export { type CompactionSettings, type RetrySettings, type Settings, SettingsManager, } from "./core/settings-manager.js";
|
|
7
|
+
export { formatSkillsForPrompt, type LoadSkillsFromDirOptions, loadSkills, loadSkillsFromDir, type Skill, type SkillFrontmatter, } from "./core/skills.js";
|
|
7
8
|
export { bashTool, codingTools, editTool, readTool, writeTool } from "./core/tools/index.js";
|
|
8
9
|
export { main } from "./main.js";
|
|
9
10
|
//# 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":"AACA,OAAO,EACN,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,KAAK,cAAc,EACnB,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,aAAa,GACb,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,cAAc,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACN,KAAK,eAAe,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,KAAK,aAAa,EAClB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,mBAAmB,EACxB,cAAc,EACd,cAAc,EACd,KAAK,wBAAwB,GAC7B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,eAAe,GACf,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,GACjB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,KAAK,cAAc,EACnB,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,aAAa,GACb,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACX,aAAa,EACb,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,YAAY,EACZ,cAAc,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACN,KAAK,eAAe,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,KAAK,aAAa,EAClB,sBAAsB,EACtB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,cAAc,EACd,KAAK,mBAAmB,EACxB,cAAc,EACd,cAAc,EACd,KAAK,wBAAwB,GAC7B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,eAAe,GACf,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACN,qBAAqB,EACrB,KAAK,wBAAwB,EAC7B,UAAU,EACV,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,gBAAgB,GACrB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAG7F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// Core session management\nexport {\n\tAgentSession,\n\ttype AgentSessionConfig,\n\ttype AgentSessionEvent,\n\ttype AgentSessionEventListener,\n\ttype CompactionResult,\n\ttype ModelCycleResult,\n\ttype PromptOptions,\n\ttype SessionStats,\n} from \"./core/agent-session.js\";\n// Compaction\nexport {\n\ttype CutPointResult,\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tshouldCompact,\n} from \"./core/compaction.js\";\n// Hook system types\nexport type {\n\tAgentEndEvent,\n\tAgentStartEvent,\n\tBranchEvent,\n\tBranchEventResult,\n\tHookAPI,\n\tHookEvent,\n\tHookEventContext,\n\tHookFactory,\n\tHookUIContext,\n\tSessionStartEvent,\n\tSessionSwitchEvent,\n\tToolCallEvent,\n\tToolCallEventResult,\n\tToolResultEvent,\n\tToolResultEventResult,\n\tTurnEndEvent,\n\tTurnStartEvent,\n} from \"./core/hooks/index.js\";\nexport { messageTransformer } from \"./core/messages.js\";\nexport {\n\ttype CompactionEntry,\n\tcreateSummaryMessage,\n\tgetLatestCompactionEntry,\n\ttype LoadedSession,\n\tloadSessionFromEntries,\n\ttype ModelChangeEntry,\n\tparseSessionEntries,\n\ttype SessionEntry,\n\ttype SessionHeader,\n\tSessionManager,\n\ttype SessionMessageEntry,\n\tSUMMARY_PREFIX,\n\tSUMMARY_SUFFIX,\n\ttype ThinkingLevelChangeEntry,\n} from \"./core/session-manager.js\";\nexport {\n\ttype CompactionSettings,\n\ttype RetrySettings,\n\ttype Settings,\n\tSettingsManager,\n} from \"./core/settings-manager.js\";\n// Skills\nexport {\n\tformatSkillsForPrompt,\n\ttype LoadSkillsFromDirOptions,\n\tloadSkills,\n\tloadSkillsFromDir,\n\ttype Skill,\n\ttype SkillFrontmatter,\n} from \"./core/skills.js\";\n\n// Tools\nexport { bashTool, codingTools, editTool, readTool, writeTool } from \"./core/tools/index.js\";\n\n// Main entry point\nexport { main } from \"./main.js\";\n"]}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,8 @@ export { calculateContextTokens, compact, DEFAULT_COMPACTION_SETTINGS, estimateT
|
|
|
5
5
|
export { messageTransformer } from "./core/messages.js";
|
|
6
6
|
export { createSummaryMessage, getLatestCompactionEntry, loadSessionFromEntries, parseSessionEntries, SessionManager, SUMMARY_PREFIX, SUMMARY_SUFFIX, } from "./core/session-manager.js";
|
|
7
7
|
export { SettingsManager, } from "./core/settings-manager.js";
|
|
8
|
+
// Skills
|
|
9
|
+
export { formatSkillsForPrompt, loadSkills, loadSkillsFromDir, } from "./core/skills.js";
|
|
8
10
|
// Tools
|
|
9
11
|
export { bashTool, codingTools, editTool, readTool, writeTool } from "./core/tools/index.js";
|
|
10
12
|
// Main entry point
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EACN,YAAY,GAQZ,MAAM,yBAAyB,CAAC;AACjC,aAAa;AACb,OAAO,EAEN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,aAAa,GACb,MAAM,sBAAsB,CAAC;AAqB9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAEN,oBAAoB,EACpB,wBAAwB,EAExB,sBAAsB,EAEtB,mBAAmB,EAGnB,cAAc,EAEd,cAAc,EACd,cAAc,GAEd,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAIN,eAAe,GACf,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EACN,YAAY,GAQZ,MAAM,yBAAyB,CAAC;AACjC,aAAa;AACb,OAAO,EAEN,sBAAsB,EACtB,OAAO,EACP,2BAA2B,EAC3B,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,aAAa,GACb,MAAM,sBAAsB,CAAC;AAqB9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAEN,oBAAoB,EACpB,wBAAwB,EAExB,sBAAsB,EAEtB,mBAAmB,EAGnB,cAAc,EAEd,cAAc,EACd,cAAc,GAEd,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAIN,eAAe,GACf,MAAM,4BAA4B,CAAC;AACpC,SAAS;AACT,OAAO,EACN,qBAAqB,EAErB,UAAU,EACV,iBAAiB,GAGjB,MAAM,kBAAkB,CAAC;AAE1B,QAAQ;AACR,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE7F,mBAAmB;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC","sourcesContent":["// Core session management\nexport {\n\tAgentSession,\n\ttype AgentSessionConfig,\n\ttype AgentSessionEvent,\n\ttype AgentSessionEventListener,\n\ttype CompactionResult,\n\ttype ModelCycleResult,\n\ttype PromptOptions,\n\ttype SessionStats,\n} from \"./core/agent-session.js\";\n// Compaction\nexport {\n\ttype CutPointResult,\n\tcalculateContextTokens,\n\tcompact,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgetLastAssistantUsage,\n\tshouldCompact,\n} from \"./core/compaction.js\";\n// Hook system types\nexport type {\n\tAgentEndEvent,\n\tAgentStartEvent,\n\tBranchEvent,\n\tBranchEventResult,\n\tHookAPI,\n\tHookEvent,\n\tHookEventContext,\n\tHookFactory,\n\tHookUIContext,\n\tSessionStartEvent,\n\tSessionSwitchEvent,\n\tToolCallEvent,\n\tToolCallEventResult,\n\tToolResultEvent,\n\tToolResultEventResult,\n\tTurnEndEvent,\n\tTurnStartEvent,\n} from \"./core/hooks/index.js\";\nexport { messageTransformer } from \"./core/messages.js\";\nexport {\n\ttype CompactionEntry,\n\tcreateSummaryMessage,\n\tgetLatestCompactionEntry,\n\ttype LoadedSession,\n\tloadSessionFromEntries,\n\ttype ModelChangeEntry,\n\tparseSessionEntries,\n\ttype SessionEntry,\n\ttype SessionHeader,\n\tSessionManager,\n\ttype SessionMessageEntry,\n\tSUMMARY_PREFIX,\n\tSUMMARY_SUFFIX,\n\ttype ThinkingLevelChangeEntry,\n} from \"./core/session-manager.js\";\nexport {\n\ttype CompactionSettings,\n\ttype RetrySettings,\n\ttype Settings,\n\tSettingsManager,\n} from \"./core/settings-manager.js\";\n// Skills\nexport {\n\tformatSkillsForPrompt,\n\ttype LoadSkillsFromDirOptions,\n\tloadSkills,\n\tloadSkillsFromDir,\n\ttype Skill,\n\ttype SkillFrontmatter,\n} from \"./core/skills.js\";\n\n// Tools\nexport { bashTool, codingTools, editTool, readTool, writeTool } from \"./core/tools/index.js\";\n\n// Main entry point\nexport { main } from \"./main.js\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mariozechner/pi-coding-agent",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"prepublishOnly": "npm run clean && npm run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@mariozechner/pi-agent-core": "^0.20.
|
|
43
|
-
"@mariozechner/pi-ai": "^0.20.
|
|
44
|
-
"@mariozechner/pi-tui": "^0.20.
|
|
42
|
+
"@mariozechner/pi-agent-core": "^0.20.1",
|
|
43
|
+
"@mariozechner/pi-ai": "^0.20.1",
|
|
44
|
+
"@mariozechner/pi-tui": "^0.20.1",
|
|
45
45
|
"chalk": "^5.5.0",
|
|
46
46
|
"diff": "^8.0.2",
|
|
47
47
|
"glob": "^11.0.3",
|