feat: add default AGENTS.md and USER.md templates and ensure their presence in the user's config directory

This commit is contained in:
xiaoxixi 2026-05-10 18:07:50 +08:00
parent c81b1e42c7
commit af07eaf820
4 changed files with 118 additions and 9 deletions

View File

@ -0,0 +1,19 @@
# Agent Instructions
You are PicoBot, a personal AI assistant.
## Personality
- Helpful and friendly
- Concise and to the point
- Proactive when useful, respects user boundaries
## Values
- Accuracy over speed
- User privacy and safety
- Transparency in actions
## Communication Style
- Be clear and direct
- Use Chinese or English based on the user's language
- Explain reasoning when helpful
- Ask clarifying questions when needed

View File

@ -0,0 +1,31 @@
# 用户配置
PicoBot 会根据此文件了解你的偏好。
## 基本信息
- **称呼**: 用户
- **时区**: Asia/Shanghai (UTC+8)
- **语言**: 中文
## 偏好设置
### 回复风格
- [ ] 简洁扼要
- [ ] 详细解释
- [ ] 根据问题自适应
### 沟通风格
- [ ] 随意
- [ ] 专业
- [ ] 技术导向
## 工作环境
- **主要角色**: 开发者
- **当前项目**:
- **常用工具**:
---
*编辑此文件来定制 PicoBot 的行为偏好。*

View File

@ -3,8 +3,11 @@
//! This module provides a modular framework for building system prompts //! This module provides a modular framework for building system prompts
//! using the SystemPromptBuilder pattern. //! using the SystemPromptBuilder pattern.
//! //!
//! Configuration: //! Prompt section ordering: Identity → Environment → Tasks → Rules → Capabilities → Dynamic
//! - USER.md is loaded from ~/.picobot/USER.md (user's personal configuration) //!
//! Configuration files loaded from ~/.picobot/:
//! - AGENTS.md — agent identity and behavior
//! - USER.md — user preferences and profile
use crate::tools::ToolRegistry; use crate::tools::ToolRegistry;
use std::fmt::Write; use std::fmt::Write;
@ -42,16 +45,17 @@ impl SystemPromptBuilder {
pub fn with_defaults() -> Self { pub fn with_defaults() -> Self {
Self { Self {
sections: vec![ sections: vec![
Box::new(ToolHonestySection), Box::new(AgentProfileSection),
Box::new(YourTaskSection),
Box::new(SafetySection),
Box::new(WorkspaceSection),
Box::new(UserProfileSection), Box::new(UserProfileSection),
Box::new(RuntimeSection),
Box::new(DateTimeSection),
Box::new(WorkspaceSection),
Box::new(YourTaskSection),
Box::new(ToolHonestySection),
Box::new(SafetySection),
Box::new(CrossChannelSection),
Box::new(MemorySection), Box::new(MemorySection),
Box::new(HistorySection), Box::new(HistorySection),
Box::new(DateTimeSection),
Box::new(RuntimeSection),
Box::new(CrossChannelSection),
], ],
} }
} }
@ -202,6 +206,29 @@ impl PromptSection for UserProfileSection {
} }
} }
/// Agent profile from ~/.picobot/AGENTS.md.
pub struct AgentProfileSection;
impl PromptSection for AgentProfileSection {
fn name(&self) -> &str {
"agent_profile"
}
fn build(&self, _ctx: &PromptContext<'_>) -> String {
let mut output = String::from("## Agent 配置\n\n");
if let Some(user_config_dir) = get_user_config_dir()
&& let Some(content) =
load_file_from_dir(&user_config_dir, "AGENTS.md", BOOTSTRAP_MAX_CHARS)
{
output.push_str(&content);
return output;
}
String::new()
}
}
/// Current date and time. /// Current date and time.
pub struct DateTimeSection; pub struct DateTimeSection;

View File

@ -36,6 +36,9 @@ impl GatewayState {
tracing::info!("Using workspace directory: {}", workspace_path.display()); tracing::info!("Using workspace directory: {}", workspace_path.display());
// Release default AGENTS.md and USER.md to ~/.picobot/ if not exist
ensure_default_config_files();
// Get provider config for SessionManager // Get provider config for SessionManager
let mut provider_config = config.get_provider_config("default")?; let mut provider_config = config.get_provider_config("default")?;
// Override workspace_dir with the ensured path // Override workspace_dir with the ensured path
@ -347,3 +350,32 @@ pub async fn run(host: Option<String>, port: Option<u16>) -> Result<(), Box<dyn
Ok(()) Ok(())
} }
/// Release default AGENTS.md and USER.md templates to ~/.picobot/ if not already present.
fn ensure_default_config_files() {
let picobot_dir = dirs::home_dir().unwrap_or_default().join(".picobot");
if let Err(e) = std::fs::create_dir_all(&picobot_dir) {
tracing::warn!(dir = %picobot_dir.display(), error = %e, "Failed to create ~/.picobot directory");
return;
}
let agents_path = picobot_dir.join("AGENTS.md");
if !agents_path.exists() {
let content = include_str!("../../resources/templates/AGENTS.md");
if let Err(e) = std::fs::write(&agents_path, content) {
tracing::warn!(path = %agents_path.display(), error = %e, "Failed to write AGENTS.md template");
} else {
tracing::info!(path = %agents_path.display(), "Released default AGENTS.md template");
}
}
let user_path = picobot_dir.join("USER.md");
if !user_path.exists() {
let content = include_str!("../../resources/templates/USER.md");
if let Err(e) = std::fs::write(&user_path, content) {
tracing::warn!(path = %user_path.display(), error = %e, "Failed to write USER.md template");
} else {
tracing::info!(path = %user_path.display(), "Released default USER.md template");
}
}
}