1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
| private _rebuildSystemPrompt(toolNames: string[]): string { const validToolNames = toolNames.filter((name) => this._toolRegistry.has(name)); const toolSnippets: Record<string, string> = {}; const promptGuidelines: string[] = []; for (const name of validToolNames) { const snippet = this._toolPromptSnippets.get(name); if (snippet) { toolSnippets[name] = snippet; }
const toolGuidelines = this._toolPromptGuidelines.get(name); if (toolGuidelines) { promptGuidelines.push(...toolGuidelines); } }
const loaderSystemPrompt = this._resourceLoader.getSystemPrompt(); const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt(); const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : undefined; const loadedSkills = this._resourceLoader.getSkills().skills; const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
this._baseSystemPromptOptions = { cwd: this._cwd, skills: loadedSkills, contextFiles: loadedContextFiles, customPrompt: loaderSystemPrompt, appendSystemPrompt, selectedTools: validToolNames, toolSnippets, promptGuidelines, }; return buildSystemPrompt(this._baseSystemPromptOptions); }
export function buildSystemPrompt(options: BuildSystemPromptOptions): string { const { customPrompt, selectedTools, toolSnippets, promptGuidelines, appendSystemPrompt, cwd, contextFiles: providedContextFiles, skills: providedSkills, } = options; const promptCwd = cwd.replace(/\\/g, "/");
const appendSection = appendSystemPrompt ? `\n\n${appendSystemPrompt}` : "";
const contextFiles = providedContextFiles ?? []; const skills = providedSkills ?? [];
if (customPrompt) { let prompt = customPrompt;
if (appendSection) { prompt += appendSection; }
if (contextFiles.length > 0) { prompt += "\n\n<project_context>\n\n"; prompt += "Project-specific instructions and guidelines:\n\n"; for (const { path: filePath, content } of contextFiles) { prompt += `<project_instructions path="${filePath}">\n${content}\n</project_instructions>\n\n`; } prompt += "</project_context>\n"; }
const customPromptHasRead = !selectedTools || selectedTools.includes("read"); if (customPromptHasRead && skills.length > 0) { prompt += formatSkillsForPrompt(skills); }
prompt += `\nCurrent working directory: ${promptCwd}`;
return prompt; }
const readmePath = getReadmePath(); const docsPath = getDocsPath(); const examplesPath = getExamplesPath();
const tools = selectedTools || ["read", "bash", "edit", "write"]; const visibleTools = tools.filter((name) => !!toolSnippets?.[name]); const toolsList = visibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join("\n") : "(none)";
const guidelinesList: string[] = []; const guidelinesSet = new Set<string>(); const addGuideline = (guideline: string): void => { if (guidelinesSet.has(guideline)) { return; } guidelinesSet.add(guideline); guidelinesList.push(guideline); };
const hasBash = tools.includes("bash"); const hasGrep = tools.includes("grep"); const hasFind = tools.includes("find"); const hasLs = tools.includes("ls"); const hasRead = tools.includes("read");
if (hasBash && !hasGrep && !hasFind && !hasLs) { addGuideline("Use bash for file operations like ls, rg, find"); }
for (const guideline of promptGuidelines ?? []) { const normalized = guideline.trim(); if (normalized.length > 0) { addGuideline(normalized); } }
addGuideline("Be concise in your responses"); addGuideline("Show file paths clearly when working with files");
const guidelines = guidelinesList.map((g) => `- ${g}`).join("\n");
let prompt = `You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
Available tools: ${toolsList}
In addition to the tools above, you may have access to other custom tools depending on the project.
Guidelines: ${guidelines}
Pi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI): - Main documentation: ${readmePath} - Additional docs: ${docsPath} - Examples: ${examplesPath} (extensions, custom tools, SDK) - When reading pi docs or examples, resolve docs/... under Additional docs and examples/... under Examples, not the current working directory - When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md), environment variables (docs/environment-variables.md) - When working on pi topics, read the docs and examples, and follow .md cross-references before implementing - Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;
if (appendSection) { prompt += appendSection; }
if (contextFiles.length > 0) { prompt += "\n\n<project_context>\n\n"; prompt += "Project-specific instructions and guidelines:\n\n"; for (const { path: filePath, content } of contextFiles) { prompt += `<project_instructions path="${filePath}">\n${content}\n</project_instructions>\n\n`; } prompt += "</project_context>\n"; }
if (hasRead && skills.length > 0) { prompt += formatSkillsForPrompt(skills); }
prompt += `\nCurrent working directory: ${promptCwd}`;
return prompt; }
|