优化OpenClaw会话解析
This commit is contained in:
@@ -156,6 +156,15 @@ async fn build_agent(
|
|||||||
parts.push("--session".into());
|
parts.push("--session".into());
|
||||||
parts.push(key.clone());
|
parts.push(key.clone());
|
||||||
}
|
}
|
||||||
|
// When creating a new conversation (no session_id to resume),
|
||||||
|
// pass --reset-session so OpenClaw mints a fresh transcript
|
||||||
|
// instead of appending to the previous one.
|
||||||
|
if runtime_env
|
||||||
|
.get("OPENCLAW_RESET_SESSION")
|
||||||
|
.map_or(false, |v| v == "1")
|
||||||
|
{
|
||||||
|
parts.push("--reset-session".into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let refs: Vec<&str> = parts.iter().map(|s| s.as_str()).collect();
|
let refs: Vec<&str> = parts.iter().map(|s| s.as_str()).collect();
|
||||||
AcpAgent::from_args(&refs).map_err(|e| AcpError::SpawnFailed(e.to_string()))
|
AcpAgent::from_args(&refs).map_err(|e| AcpError::SpawnFailed(e.to_string()))
|
||||||
|
|||||||
@@ -1306,9 +1306,15 @@ pub async fn acp_connect(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let local_config_json = load_agent_local_config_json(agent_type);
|
let local_config_json = load_agent_local_config_json(agent_type);
|
||||||
let runtime_env =
|
let mut runtime_env =
|
||||||
build_runtime_env_from_setting(agent_type, setting.as_ref(), local_config_json.as_deref());
|
build_runtime_env_from_setting(agent_type, setting.as_ref(), local_config_json.as_deref());
|
||||||
|
|
||||||
|
// For OpenClaw: when creating a new conversation (no session_id to resume),
|
||||||
|
// signal that we want a fresh transcript via --reset-session.
|
||||||
|
if agent_type == AgentType::OpenClaw && session_id.is_none() {
|
||||||
|
runtime_env.insert("OPENCLAW_RESET_SESSION".into(), "1".into());
|
||||||
|
}
|
||||||
|
|
||||||
if let registry::AgentDistribution::Npx { package, .. } = meta.distribution {
|
if let registry::AgentDistribution::Npx { package, .. } = meta.distribution {
|
||||||
if detect_npx_cached_version(package).await.is_none() {
|
if detect_npx_cached_version(package).await.is_none() {
|
||||||
prepare_npx_package(package).await?;
|
prepare_npx_package(package).await?;
|
||||||
|
|||||||
@@ -261,9 +261,18 @@ pub async fn get_folder_conversation(
|
|||||||
.await
|
.await
|
||||||
.map_err(AppCommandError::from)?;
|
.map_err(AppCommandError::from)?;
|
||||||
|
|
||||||
let (turns, session_stats) = if let Some(ref ext_id) = summary.external_id {
|
let (turns, session_stats, resolved_ext_id) = if let Some(ref ext_id) = summary.external_id
|
||||||
|
{
|
||||||
let at = summary.agent_type;
|
let at = summary.agent_type;
|
||||||
let eid = ext_id.clone();
|
let eid = ext_id.clone();
|
||||||
|
let db_created_at = summary.created_at;
|
||||||
|
let folder_path_for_fallback = {
|
||||||
|
let folder = folder_service::get_folder_by_id(&db.conn, summary.folder_id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
|
folder.map(|f| f.path)
|
||||||
|
};
|
||||||
tokio::task::spawn_blocking(move || -> Result<_, AppCommandError> {
|
tokio::task::spawn_blocking(move || -> Result<_, AppCommandError> {
|
||||||
let parser: Box<dyn AgentParser> = match at {
|
let parser: Box<dyn AgentParser> = match at {
|
||||||
AgentType::ClaudeCode => Box::new(ClaudeParser::new()),
|
AgentType::ClaudeCode => Box::new(ClaudeParser::new()),
|
||||||
@@ -271,13 +280,47 @@ pub async fn get_folder_conversation(
|
|||||||
AgentType::OpenCode => Box::new(OpenCodeParser::new()),
|
AgentType::OpenCode => Box::new(OpenCodeParser::new()),
|
||||||
AgentType::Gemini => Box::new(GeminiParser::new()),
|
AgentType::Gemini => Box::new(GeminiParser::new()),
|
||||||
AgentType::OpenClaw => Box::new(OpenClawParser::new()),
|
AgentType::OpenClaw => Box::new(OpenClawParser::new()),
|
||||||
_ => return Ok((vec![], None)),
|
_ => return Ok((vec![], None, None)),
|
||||||
};
|
};
|
||||||
// If the external session file doesn't exist yet (e.g., new ACP session
|
|
||||||
// not yet synced to disk), return empty turns instead of failing.
|
|
||||||
match parser.get_conversation(&eid) {
|
match parser.get_conversation(&eid) {
|
||||||
Ok(d) => Ok((d.turns, d.session_stats)),
|
Ok(d) => Ok((d.turns, d.session_stats, None)),
|
||||||
Err(crate::parsers::ParseError::ConversationNotFound(_)) => Ok((vec![], None)),
|
Err(crate::parsers::ParseError::ConversationNotFound(_)) => {
|
||||||
|
// For OpenClaw, the external_id may be an ACP session UUID that
|
||||||
|
// doesn't correspond to any JSONL file. Fall back to matching
|
||||||
|
// by title and folder_path from the parsed conversation list.
|
||||||
|
if at == AgentType::OpenClaw {
|
||||||
|
if let Ok(all) = parser.list_conversations() {
|
||||||
|
// Filter by folder_path first, then find the closest
|
||||||
|
// started_at match within 300 seconds of db_created_at.
|
||||||
|
let matched = all
|
||||||
|
.into_iter()
|
||||||
|
.filter(|c| {
|
||||||
|
c.folder_path
|
||||||
|
.as_ref()
|
||||||
|
.zip(folder_path_for_fallback.as_ref())
|
||||||
|
.is_some_and(|(a, b)| path_eq_for_matching(a, b))
|
||||||
|
})
|
||||||
|
.min_by_key(|c| {
|
||||||
|
(c.started_at - db_created_at).num_seconds().unsigned_abs()
|
||||||
|
})
|
||||||
|
.filter(|c| {
|
||||||
|
let diff = (c.started_at - db_created_at).num_seconds().unsigned_abs();
|
||||||
|
diff < 300
|
||||||
|
});
|
||||||
|
if let Some(conv) = matched {
|
||||||
|
let new_ext_id = conv.id.clone();
|
||||||
|
if let Ok(d) = parser.get_conversation(&new_ext_id) {
|
||||||
|
return Ok((
|
||||||
|
d.turns,
|
||||||
|
d.session_stats,
|
||||||
|
Some(new_ext_id),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((vec![], None, None))
|
||||||
|
}
|
||||||
Err(e) => Err(parse_error_to_app_error(e)),
|
Err(e) => Err(parse_error_to_app_error(e)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -289,9 +332,16 @@ pub async fn get_folder_conversation(
|
|||||||
.with_detail(e.to_string())
|
.with_detail(e.to_string())
|
||||||
})??
|
})??
|
||||||
} else {
|
} else {
|
||||||
(vec![], None)
|
(vec![], None, None)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If we resolved a different external_id (e.g. ACP UUID → parser branch ID),
|
||||||
|
// update the database so future lookups are direct.
|
||||||
|
if let Some(new_ext_id) = resolved_ext_id {
|
||||||
|
let _ =
|
||||||
|
conversation_service::update_external_id(&db.conn, conversation_id, new_ext_id).await;
|
||||||
|
}
|
||||||
|
|
||||||
let mut summary = summary;
|
let mut summary = summary;
|
||||||
summary.message_count = turns.len() as u32;
|
summary.message_count = turns.len() as u32;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user