让项目聊天读取原始 item 历史
DirectProject 聊天命令写入 Responses message item 聊天读取从原始 item 投影 user/assistant 内容 保留 Agent session 旧会话读写路径
This commit is contained in:
@@ -72,10 +72,41 @@ pub(crate) fn append_direct_project_history_item_at(
|
||||
let path = history_path(root);
|
||||
let lock = project_append_lock_for(&path)?;
|
||||
let _append_guard = lock.lock("DirectProject 历史追加写")?;
|
||||
if let Some(item_id) = item.get("id").and_then(Value::as_str) {
|
||||
if read_direct_project_history_items_at(root)?.iter().any(|existing| {
|
||||
existing.get("id").and_then(Value::as_str) == Some(item_id)
|
||||
}) {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
let line = record(item)?;
|
||||
append_jsonl_line_unlocked(&path, &line, "DirectProject 历史")
|
||||
}
|
||||
|
||||
pub(crate) fn direct_project_local_message_item(
|
||||
role: &str,
|
||||
content: &str,
|
||||
message_id: Option<&str>,
|
||||
) -> Result<Value, String> {
|
||||
let role = role.trim();
|
||||
let content = content.trim();
|
||||
if content.is_empty() || !matches!(role, "user" | "assistant") {
|
||||
return Err("DirectProject 只接受非空 user/assistant 历史消息".to_string());
|
||||
}
|
||||
let mut item = serde_json::json!({
|
||||
"type": "message",
|
||||
"role": role,
|
||||
"content": [{
|
||||
"type": if role == "user" { "input_text" } else { "output_text" },
|
||||
"text": content,
|
||||
}],
|
||||
});
|
||||
if let Some(message_id) = message_id.map(str::trim).filter(|value| !value.is_empty()) {
|
||||
item["id"] = Value::String(message_id.to_string());
|
||||
}
|
||||
Ok(item)
|
||||
}
|
||||
|
||||
pub(crate) fn direct_project_user_message_item(prompt: &str) -> Value {
|
||||
serde_json::json!({
|
||||
"type": "message",
|
||||
@@ -133,3 +164,47 @@ pub(crate) fn read_direct_project_history_items_at(
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
|
||||
pub(crate) fn read_direct_project_chat_history_at(
|
||||
root: &Path,
|
||||
) -> Result<LocalConversationResult, String> {
|
||||
let path = history_path(root);
|
||||
let items = read_direct_project_history_items_at(root)?;
|
||||
let messages = items
|
||||
.into_iter()
|
||||
.filter_map(|item| {
|
||||
let role = item.get("role").and_then(Value::as_str)?;
|
||||
if !matches!(role, "user" | "assistant") {
|
||||
return None;
|
||||
}
|
||||
let content = item
|
||||
.get("content")
|
||||
.and_then(Value::as_array)
|
||||
.map(|parts| {
|
||||
parts
|
||||
.iter()
|
||||
.filter_map(|part| part.get("text").and_then(Value::as_str))
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
(!content.is_empty()).then(|| LocalConversationMessageRecord {
|
||||
schema_version: "agc-direct-project-context.v1".to_string(),
|
||||
role: role.to_string(),
|
||||
content,
|
||||
agent_id: None,
|
||||
message_id: item
|
||||
.get("id")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::to_string),
|
||||
updated_at: 0,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Ok(LocalConversationResult {
|
||||
path: path.to_string_lossy().into_owned(),
|
||||
agent_id: None,
|
||||
session_id: None,
|
||||
messages,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use crate::agent::read_direct_project_chat_history_at;
|
||||
use crate::ui_editor::resource::font::FontAsset;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
@@ -4707,6 +4708,9 @@ pub(crate) fn read_local_conversation(
|
||||
) -> Result<LocalConversationResult, String> {
|
||||
let root = Path::new(project_path.trim());
|
||||
enforce_project_permission_policy(root, "conversation.read")?;
|
||||
if agent_id.is_none() && session_id.is_none() {
|
||||
return read_direct_project_chat_history_at(root);
|
||||
}
|
||||
read_local_conversation_for_session_at(root, agent_id.as_deref(), session_id.as_deref())
|
||||
}
|
||||
|
||||
@@ -4720,6 +4724,15 @@ pub(crate) fn append_local_conversation_message(
|
||||
) -> Result<LocalConversationResult, String> {
|
||||
let root = Path::new(project_path.trim());
|
||||
enforce_project_permission_policy(root, "conversation.write")?;
|
||||
if agent_id.is_none() && session_id.is_none() {
|
||||
let item = direct_project_local_message_item(
|
||||
&message.role,
|
||||
&message.content,
|
||||
message_id.as_deref(),
|
||||
)?;
|
||||
append_direct_project_history_item_at(root, &item)?;
|
||||
return read_direct_project_chat_history_at(root);
|
||||
}
|
||||
let _lock = acquire_project_write_lock(root, "conversation.write")?;
|
||||
match message_id.as_deref() {
|
||||
Some(message_id) => append_local_conversation_message_for_session_idempotent_at(
|
||||
|
||||
Reference in New Issue
Block a user