matrixcode_core/prompt/
mod.rs1pub mod section;
19pub mod cache;
20pub mod context;
21pub mod orchestrator;
22pub mod preprocess;
23pub mod dump;
24pub mod constants;
25
26pub use section::{PromptSection, SectionContent, SectionBuilder};
28pub use cache::{SectionCache, CacheKey, CachedEntry, CacheStats, global_cache, clear_global_cache, estimate_tokens};
29pub use context::{ContextInjector, UserContext, SystemContext, ProjectType};
30pub use orchestrator::{PromptOrchestrator, PromptProfile, PromptBuilder, AssembledPrompt, CACHE_BOUNDARY};
31pub use preprocess::{PreProcessHook, ProcessResult, SkillPattern, WorkflowTrigger, preprocess};
32pub use dump::{PromptDumper, DumpEntry, PromptAnalysis, DumpFileAnalysis, read_dump_file, analyze_dump_file};
33
34pub use constants::*;
36
37pub use orchestrator::PromptProfile as LegacyPromptProfile;
43
44#[derive(Debug, Clone)]
47pub struct OverviewContext {
48 pub project_name: String,
49 pub project_type: String,
50 pub directory_structure: String,
51 pub config_files: Vec<(String, String)>, pub readme: Option<String>,
53 pub source_files: Vec<(String, String)>, }
55
56impl Default for OverviewContext {
57 fn default() -> Self {
58 Self {
59 project_name: String::new(),
60 project_type: String::new(),
61 directory_structure: String::new(),
62 config_files: Vec::new(),
63 readme: None,
64 source_files: Vec::new(),
65 }
66 }
67}
68
69pub fn build_overview_prompt(context: &OverviewContext) -> String {
72 let mut prompt = String::new();
73
74 prompt.push_str("你是一个项目分析专家,请根据提供的项目信息生成项目概览文档(MATRIX.md)。\n\n");
76 prompt.push_str("要求:\n");
77 prompt.push_str("- 使用 Markdown 格式\n");
78 prompt.push_str("- 简洁明了,突出重点\n");
79 prompt.push_str("- 包含项目定位、技术栈、架构要点\n");
80 prompt.push_str("- 便于 AI 助手快速理解项目\n");
81 prompt.push_str("\n---\n\n");
82
83 prompt.push_str(&format!("项目名称: {}\n", context.project_name));
85 prompt.push_str(&format!("项目类型: {}\n\n", context.project_type));
86
87 prompt.push_str("## 目录结构\n\n");
89 prompt.push_str("```\n");
90 prompt.push_str(&context.directory_structure);
91 prompt.push_str("```\n\n");
92
93 if !context.config_files.is_empty() {
95 prompt.push_str("## 配置文件\n\n");
96 for (filename, content) in &context.config_files {
97 prompt.push_str(&format!("### {}\n\n", filename));
98 prompt.push_str("```\n");
99 prompt.push_str(content);
100 prompt.push_str("\n```\n\n");
101 }
102 }
103
104 if let Some(readme) = &context.readme {
106 prompt.push_str("## README.md (开头部分)\n\n");
107 prompt.push_str(readme);
108 prompt.push_str("\n\n");
109 }
110
111 if !context.source_files.is_empty() {
113 prompt.push_str("## 关键源文件\n\n");
114 for (filename, content) in &context.source_files {
115 prompt.push_str(&format!("### {}\n\n", filename));
116 prompt.push_str("```\n");
117 prompt.push_str(content);
118 prompt.push_str("\n```\n\n");
119 }
120 }
121
122 prompt.push_str("---\n\n");
123 prompt.push_str("请根据以上信息生成 MATRIX.md 文档内容:\n");
124
125 prompt
126}
127
128use crate::skills::Skill;
129use std::path::PathBuf;
130
131fn join_lines(items: &[String]) -> String {
133 items.join("\n")
134}
135
136pub fn build_system_prompt(
138 profile: &PromptProfile,
139 skills: &[Skill],
140 project_overview: Option<&str>,
141 memory_summary: Option<&str>,
142) -> String {
143 build_system_prompt_with_workflows(profile, skills, project_overview, memory_summary, None, None)
144}
145
146pub fn build_system_prompt_with_workflows(
151 profile: &PromptProfile,
152 skills: &[Skill],
153 project_overview: Option<&str>,
154 memory_summary: Option<&str>,
155 project_path: Option<&PathBuf>,
156 lsp_servers: Option<&[crate::lsp::LspServerInfo]>,
157) -> String {
158 let has_codegraph = project_path
160 .map(|p| crate::tools::codegraph::should_inject_codegraph_tools(p))
161 .unwrap_or(false);
162
163 let mut builder = PromptBuilder::new(
165 project_path.cloned().unwrap_or_else(|| std::env::current_dir().unwrap())
166 )
167 .profile(*profile)
168 .no_context();
169
170 for (name, content) in constants::get_static_sections(has_codegraph) {
172 builder = builder.add_static(name, content);
173 }
174
175 for (name, content) in constants::get_memory_sections() {
177 builder = builder.add_static(name, content);
178 }
179
180 let mut orchestrator = builder.build();
182
183 let assembled = orchestrator.assemble();
185 let mut parts = vec![assembled.prompt];
186
187 let tools_prompt = crate::tools::generate_tools_prompt_with_path(project_path);
189 parts.push(tools_prompt);
190
191 if !skills.is_empty() {
193 let skills_lines: Vec<String> = skills.iter()
194 .map(|s| {
195 if let Some(trigger) = &s.trigger {
196 format!(" - {}: {}\n 触发场景: {}", s.name, s.description, trigger)
197 } else {
198 format!(" - {}: {}", s.name, s.description)
199 }
200 })
201 .collect();
202 let skills_section = format!(
203 "[AVAILABLE SKILLS]\n可用技能(使用 skill 工具调用):\n\n{}",
204 join_lines(&skills_lines)
205 );
206 parts.push(skills_section);
207 }
208
209 if let Some(path) = project_path {
211 let registry = crate::workflow::WorkflowRegistry::new(Some(path));
212 if !registry.is_empty() {
213 let workflows_lines: Vec<String> = registry.list().iter()
214 .map(|w| {
215 let desc = w.description.as_deref().unwrap_or(&w.name);
216 if w.required_inputs.is_empty() {
217 format!(" - {}: {}", w.id, desc)
218 } else {
219 format!(" - {}: {} (需要输入: {})", w.id, desc, w.required_inputs.join(", "))
220 }
221 })
222 .collect();
223 let workflows_section = format!(
224 "[AVAILABLE WORKFLOWS]\n可执行的自动化流程(使用 workflow_run 工具调用):\n\n{}",
225 join_lines(&workflows_lines)
226 );
227 parts.push(workflows_section);
228 }
229 }
230
231 if let Some(overview) = project_overview {
233 parts.push(format!("[PROJECT CONTEXT]\n{}", overview));
234 }
235
236 if let Some(memory) = memory_summary {
238 parts.push(format!(
239 "{}\n{}\n\n{}",
240 MEMORY_SUMMARY_HEADER,
241 MEMORY_USAGE_INSTRUCTIONS,
242 memory
243 ));
244 }
245
246 if let Some(servers) = lsp_servers {
248 if let Some(lsp_section) = crate::prompt::constants::get_lsp_section(servers) {
249 parts.push(lsp_section);
250 }
251 }
252
253 parts.join("\n\n")
254}