fix(prompt): correct live file backfill priority in enable flow (#225)
Fix backfill logic in prompt enable workflow: - Prioritize backfilling live file content to currently enabled prompt (prevent data loss) - Create backup only when no enabled prompt exists and content is new (avoid duplicate backups) - Implement staged persistence (save after backfill + save after enable) - Add explicit logging for backfill/backup operations Also simplify string formatting in prompt_files.rs with inline format strings.
This commit is contained in:
@@ -34,11 +34,8 @@ fn get_base_dir_with_fallback(
|
||||
.ok_or_else(|| {
|
||||
AppError::localized(
|
||||
"home_dir_not_found",
|
||||
format!("无法确定 {} 配置目录:用户主目录不存在", fallback_dir),
|
||||
format!(
|
||||
"Cannot determine {} config directory: user home not found",
|
||||
fallback_dir
|
||||
),
|
||||
format!("无法确定 {fallback_dir} 配置目录:用户主目录不存在"),
|
||||
format!("Cannot determine {fallback_dir} config directory: user home not found"),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -72,27 +72,38 @@ impl PromptService {
|
||||
}
|
||||
|
||||
pub fn enable_prompt(state: &AppState, app: AppType, id: &str) -> Result<(), AppError> {
|
||||
// 先保存当前文件内容(如果存在且没有对应的提示词)
|
||||
// 回填当前 live 文件内容到已启用的提示词,或创建备份
|
||||
let target_path = prompt_file_path(&app)?;
|
||||
if target_path.exists() {
|
||||
let mut cfg = state.config.write()?;
|
||||
let prompts = match app {
|
||||
AppType::Claude => &mut cfg.prompts.claude.prompts,
|
||||
AppType::Codex => &mut cfg.prompts.codex.prompts,
|
||||
AppType::Gemini => &mut cfg.prompts.gemini.prompts,
|
||||
};
|
||||
|
||||
// 检查是否有已启用的提示词
|
||||
let has_enabled = prompts.values().any(|p| p.enabled);
|
||||
|
||||
// 如果没有已启用的提示词,自动保存当前文件
|
||||
if !has_enabled {
|
||||
if let Ok(content) = std::fs::read_to_string(&target_path) {
|
||||
if !content.trim().is_empty() {
|
||||
// 检查是否已存在相同内容的提示词,避免重复备份
|
||||
let content_exists =
|
||||
prompts.values().any(|p| p.content.trim() == content.trim());
|
||||
if let Ok(live_content) = std::fs::read_to_string(&target_path) {
|
||||
if !live_content.trim().is_empty() {
|
||||
let mut cfg = state.config.write()?;
|
||||
let prompts = match app {
|
||||
AppType::Claude => &mut cfg.prompts.claude.prompts,
|
||||
AppType::Codex => &mut cfg.prompts.codex.prompts,
|
||||
AppType::Gemini => &mut cfg.prompts.gemini.prompts,
|
||||
};
|
||||
|
||||
// 尝试回填到当前已启用的提示词
|
||||
if let Some((enabled_id, enabled_prompt)) = prompts
|
||||
.iter_mut()
|
||||
.find(|(_, p)| p.enabled)
|
||||
.map(|(id, p)| (id.clone(), p))
|
||||
{
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs() as i64;
|
||||
enabled_prompt.content = live_content.clone();
|
||||
enabled_prompt.updated_at = Some(timestamp);
|
||||
log::info!("回填 live 提示词内容到已启用项: {enabled_id}");
|
||||
drop(cfg); // 释放锁后保存,避免死锁
|
||||
state.save()?; // 第一次保存:回填后立即持久化
|
||||
} else {
|
||||
// 没有已启用的提示词,则创建一次备份(避免重复备份)
|
||||
let content_exists = prompts
|
||||
.values()
|
||||
.any(|p| p.content.trim() == live_content.trim());
|
||||
if !content_exists {
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
@@ -105,21 +116,26 @@ impl PromptService {
|
||||
"原始提示词 {}",
|
||||
chrono::Local::now().format("%Y-%m-%d %H:%M")
|
||||
),
|
||||
content,
|
||||
content: live_content,
|
||||
description: Some("自动备份的原始提示词".to_string()),
|
||||
enabled: false,
|
||||
created_at: Some(timestamp),
|
||||
updated_at: Some(timestamp),
|
||||
};
|
||||
prompts.insert(backup_id, backup_prompt);
|
||||
prompts.insert(backup_id.clone(), backup_prompt);
|
||||
log::info!("回填 live 提示词内容,创建备份: {backup_id}");
|
||||
drop(cfg); // 释放锁后保存
|
||||
state.save()?; // 第一次保存:回填后立即持久化
|
||||
} else {
|
||||
// 即使内容已存在,也无需重复备份;但不需要保存任何更改
|
||||
drop(cfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(cfg);
|
||||
}
|
||||
|
||||
// 启用目标提示词
|
||||
// 启用目标提示词并写入文件
|
||||
let mut cfg = state.config.write()?;
|
||||
let prompts = match app {
|
||||
AppType::Claude => &mut cfg.prompts.claude.prompts,
|
||||
@@ -133,13 +149,13 @@ impl PromptService {
|
||||
|
||||
if let Some(prompt) = prompts.get_mut(id) {
|
||||
prompt.enabled = true;
|
||||
write_text_file(&target_path, &prompt.content)?;
|
||||
write_text_file(&target_path, &prompt.content)?; // 原子写入
|
||||
} else {
|
||||
return Err(AppError::InvalidInput(format!("提示词 {id} 不存在")));
|
||||
}
|
||||
|
||||
drop(cfg);
|
||||
state.save()?;
|
||||
state.save()?; // 第二次保存:启用目标提示词并写入文件后
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user