优化: token消息级持久化 + 技能注入修复 + TopBar减法/UI调
token持久化(方案A,治压缩/切会话后历史token不显):ChatMessage/AiMessageRecord 加 prompt_tokens/completion_tokens(serde + DB V38 迁移 + message_repo 映射);agentic push_assistant_message 设本轮 token + provider/title 构造默认 None;前端 AiMessage 加字段 + switchConversation reload 映射 tokenUsage(双轨:消息级新+会话级旧累计保留) 技能注入修复:read_skill_content_stripped 改 skills_cached 扫盘(防御 SKILLS None 致不注入)+ 细化诊断(缓存/path/fs 各步) TopBar减法/UI:删铅笔新建(与侧栏+重复)/删垃圾桶clear-chat(危险,clear-context归档替代)/删系统就绪装饰占位;更多菜单popout CSS补全(修样式错乱);provider绿点有信息化(绿/红/灰基于AI请求成败)+垂直居中;goals面板补top:100%(修位置飘)+dot/check/remove CSS+goals/history item统一+history index边距;4面板互斥(点一个收其他) MessageList token v-if 去 !streaming(修发新消息历史token消失)
This commit is contained in:
@@ -1104,27 +1104,31 @@ pub(crate) async fn run_agentic_loop(
|
||||
let merge_result = coord.merge(&results);
|
||||
|
||||
// 将合并产出推回主对话(单条可展开 assistant 消息)
|
||||
// 消息级 token:Coordinator 路径无本轮 LLM(子任务已各自计入其会话/或未计入),
|
||||
// 此处为合成汇总非直接 LLM 输出,与下方 emit coord_usage(空 tokens 快照)对齐 → 0。
|
||||
{
|
||||
let mut session = session_arc.lock().await;
|
||||
session.conv(&conv_id).messages.push(
|
||||
ChatMessage::assistant(&format!(
|
||||
"## 多 Agent 执行完成\n\n共执行 {} 个子任务,成功 {} 个。\n\n{}",
|
||||
results.len(),
|
||||
results.iter().filter(|r| r.success).count(),
|
||||
merge_result.merged_output
|
||||
))
|
||||
);
|
||||
let mut merge_msg = ChatMessage::assistant(&format!(
|
||||
"## 多 Agent 执行完成\n\n共执行 {} 个子任务,成功 {} 个。\n\n{}",
|
||||
results.len(),
|
||||
results.iter().filter(|r| r.success).count(),
|
||||
merge_result.merged_output
|
||||
));
|
||||
merge_msg.prompt_tokens = Some(0);
|
||||
merge_msg.completion_tokens = Some(0);
|
||||
session.conv(&conv_id).messages.push(merge_msg);
|
||||
if !merge_result.conflicts.is_empty() {
|
||||
session.conv(&conv_id).messages.push(
|
||||
ChatMessage::assistant(&format!(
|
||||
"### 冲突检测\n\n检测到 {} 个文件冲突:\n{}",
|
||||
merge_result.conflicts.len(),
|
||||
merge_result.conflicts.iter()
|
||||
.map(|c| format!("- {}: {}", c.file, c.description))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
))
|
||||
);
|
||||
let mut conflict_msg = ChatMessage::assistant(&format!(
|
||||
"### 冲突检测\n\n检测到 {} 个文件冲突:\n{}",
|
||||
merge_result.conflicts.len(),
|
||||
merge_result.conflicts.iter()
|
||||
.map(|c| format!("- {}: {}", c.file, c.description))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
));
|
||||
conflict_msg.prompt_tokens = Some(0);
|
||||
conflict_msg.completion_tokens = Some(0);
|
||||
session.conv(&conv_id).messages.push(conflict_msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1565,6 +1569,10 @@ pub(crate) async fn run_agentic_loop(
|
||||
msg.model = Some(resolved_model.clone());
|
||||
// MidStream 保文也回填 reasoning_content
|
||||
msg.reasoning_content = round_reasoning_content.clone();
|
||||
// 消息级 token(对齐 push_assistant_message 双轨持久化):本轮 partial usage
|
||||
// (prompt=round 或 estimated 兜底,completion=round)。系统提示消息无 token,不设。
|
||||
msg.prompt_tokens = Some(usage.prompt_tokens);
|
||||
msg.completion_tokens = Some(usage.completion_tokens);
|
||||
conv.messages.push(msg);
|
||||
// 追加系统提示消息:响应因网络中断不完整(对齐决策 a1 系统提示机制)
|
||||
let mut notice = ChatMessage::system("⚠ 响应因网络中断不完整,以上为已接收的部分内容。可重新发送以获取完整回复。");
|
||||
@@ -1618,6 +1626,7 @@ pub(crate) async fn run_agentic_loop(
|
||||
push_assistant_message(
|
||||
&mut session, &conv_id, has_tool_calls, &tool_calls_acc,
|
||||
&full_text, &resolved_model, &last_reasoning_content,
|
||||
round_prompt, round_usage.completion_tokens,
|
||||
);
|
||||
if GOAL_PIN_ENABLED {
|
||||
update_pinned_goals(&mut session, &conv_id, &tool_calls_acc);
|
||||
@@ -2324,6 +2333,8 @@ async fn finish_round_exit(
|
||||
// has_tool_calls=true: assistant_with_tools(文本+工具调用占位), false 且文本非空: assistant(纯文本)。
|
||||
// 两分支都不为空且都不需 push 时(no tool + empty text),返回(no-op)。
|
||||
// 入参 session 需外层调用方持锁;本函数只做纯内存 mutate,无 await/emit,不会死锁。
|
||||
// prompt_tokens/completion_tokens: 本轮 LLM 调用 token 用量(消息级持久化,解 reload/压缩/切会话后
|
||||
// 历史 assistant 消息 token 不显)。两构造分支都设。
|
||||
fn push_assistant_message(
|
||||
session: &mut AiSession,
|
||||
conv_id: &str,
|
||||
@@ -2332,6 +2343,8 @@ fn push_assistant_message(
|
||||
full_text: &str,
|
||||
resolved_model: &str,
|
||||
last_reasoning_content: &Option<String>,
|
||||
prompt_tokens: u32,
|
||||
completion_tokens: u32,
|
||||
) {
|
||||
if has_tool_calls {
|
||||
let mut order: Vec<u32> = tool_calls_acc.keys().copied().collect();
|
||||
@@ -2353,11 +2366,15 @@ fn push_assistant_message(
|
||||
let mut msg = ChatMessage::assistant_with_tools(full_text, ai_tool_calls);
|
||||
msg.model = Some(resolved_model.to_string());
|
||||
msg.reasoning_content = last_reasoning_content.clone();
|
||||
msg.prompt_tokens = Some(prompt_tokens);
|
||||
msg.completion_tokens = Some(completion_tokens);
|
||||
session.conv(conv_id).messages.push(msg);
|
||||
} else if !full_text.is_empty() {
|
||||
let mut msg = ChatMessage::assistant(full_text);
|
||||
msg.model = Some(resolved_model.to_string());
|
||||
msg.reasoning_content = last_reasoning_content.clone();
|
||||
msg.prompt_tokens = Some(prompt_tokens);
|
||||
msg.completion_tokens = Some(completion_tokens);
|
||||
session.conv(conv_id).messages.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user