修复: 上下文记忆与工作流注入生产侧空壳接通
WorkingContext 写入链落地(用户轮目标钉扎+压缩后 JSON 卡片回填重锚定,含 6 单测); 工作流 DAG 摘要注入生产侧接通(AI 路径启动写入+终态回写,审批调用点透传会话)。 附知识库与记忆走查诊断(「笨/丢历史」根因:消息压缩视图丢失+知识检索四重收口), todo 登记修复分档(含随批补登 09-28 交互走查索引条目)。
This commit is contained in:
@@ -272,10 +272,10 @@ pub(super) async fn maybe_auto_compress(
|
||||
}
|
||||
let conv = session.conv(&conv_id);
|
||||
let _compressed = conv.messages.compress_old_messages(protect_start);
|
||||
// T3: 插入 NL 摘要(向前兼容),JSON 卡片可供后续 WorkingContext(T5)使用
|
||||
// NL 摘要插首位 + JSON 卡片回填 WorkingContext,决策随压缩重锚定
|
||||
conv.messages.insert_at(0, ChatMessage::system(&summary.nl_summary));
|
||||
conv.messages.set_compressing(false);
|
||||
// TODO(T5): 如有 WorkingContext,调用 version.reset_all(summary.json_card, turn)
|
||||
conv.working_context.sync_after_compress(&summary.json_card);
|
||||
}
|
||||
tracing::info!(
|
||||
conv_id = %conv_id,
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
//! 工作流 DAG 上下文注入 — 当会话关联工作流时,将活跃路径注入 system prompt
|
||||
//!
|
||||
//! T4 实现。提供两个函数:
|
||||
//! - `build_dag_summary`: 从 DagDef 构建可读的 DAG 摘要文本
|
||||
//! - `extract_active_path`: 从完整 DAG 中提取当前活跃路径(简化)
|
||||
//! T4 实现,完整链路(生产侧已接通):
|
||||
//! - 生产:`run_workflow_inner`(workflow.rs)AI 路径(conv_id Some)启动时调
|
||||
//! `build_dag_summary` 产出摘要写入 `PerConvState.workflow_dag_summary`
|
||||
//! (`workflow_id` 存本次执行 ID,非模板 ID);执行闭包终态(completed/failed)
|
||||
//! 回写摘要并追加「状态: 已完成/已失败」行。
|
||||
//! - 消费:`agentic/mod.rs` 的 `build_runtime_prompt` 每轮读该字段注入 system prompt。
|
||||
//!
|
||||
//! 调用方(前端/workflow 引擎)在启动工作流时将摘要存入
|
||||
//! `PerConvState.workflow_dag_summary`,agentic loop 自动注入 system prompt。
|
||||
//!
|
||||
//! 预留说明(dead_code):本模块的 3 个函数当前无生产调用方——
|
||||
//! T4 消费侧已落地(`agentic/mod.rs` 在构建 system prompt 时读
|
||||
//! `PerConvState.workflow_dag_summary` 并注入),但生产侧尚无人写入该字段
|
||||
//! (`PerConvState::new` 初始化为 `None`,无代码调用 `build_dag_summary`)。
|
||||
//! 即完整链路为「工作流启动器 → 调本模块产出摘要 → 写 workflow_dag_summary
|
||||
//! → agentic loop 注入 system prompt」,中间「生产者」环节待接通。
|
||||
//! 属为后续工作流上下文注入准备的预留,非真死代码,故 allow 抑制告警。
|
||||
//! `build_dag_summary` 已有生产调用方;`extract_active_path` 仍无生产调用方
|
||||
//! (仅单测引用),模块级 allow 为其保留——节点级中间进度刷新属后续扩展。
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
||||
@@ -647,6 +647,8 @@ pub async fn ai_chat_send(
|
||||
} else {
|
||||
conv.messages.push(ChatMessage::user(&user_content));
|
||||
}
|
||||
// 新用户轮把本请求钉扎为 WorkingContext 常驻目标(截断 200 字符,与 agentic G1 目标钉扎 GOAL_MAX_CHARS 同量级)
|
||||
conv.working_context.begin_turn(&user_content, 200);
|
||||
// F-260619-04 P1:push 后取末条 user 消息 id(本轮 user,原供知识注入 referenced 溯源)。
|
||||
// DRY(B):知识注入已收敛至 inject_knowledge_into_prompt(helper 内部同消息取 text+id),
|
||||
// 此处 user_msg_id 不再透传到注入逻辑,保留下划线占用(锁内 push 已发生,语义不变)。
|
||||
@@ -891,7 +893,7 @@ pub async fn ai_approve(
|
||||
// 回填 / emit_data_changed / save / try_continue)。workflow 联动任务推进由 run_workflow 内部
|
||||
// 按 task_id+target_status 自动处理(workflow.rs:270-308),此处不重复推进。
|
||||
let exec_result: anyhow::Result<serde_json::Value> = if approval.tool_name == "run_workflow" {
|
||||
super::super::execute_run_workflow_for_tool(&app, &state, &args).await
|
||||
super::super::execute_run_workflow_for_tool(&app, &state, &args, conv_id.as_deref()).await
|
||||
} else {
|
||||
// F-260620 对齐 ai_authorize_dir(:658):ai_approve 执行同样包 60s 超时。
|
||||
// 防 list_directory 大目录/run_command 慢命令卡死 → 到不了 audit_finalize/emit/try_continue
|
||||
@@ -1273,7 +1275,7 @@ pub async fn ai_authorize_dir(
|
||||
// → 到不了 audit_finalize/emit/try_continue → IPC 永挂 → generating 永真。包 60s 超时(对齐
|
||||
// run_command),超时返 Err → 走 failed 分支 finalize+emit+try_continue,IPC 必返回不卡。
|
||||
let exec_result: anyhow::Result<serde_json::Value> = if approval.tool_name == "run_workflow" {
|
||||
super::super::execute_run_workflow_for_tool(&app, &state, &args).await
|
||||
super::super::execute_run_workflow_for_tool(&app, &state, &args, conv_id.as_deref()).await
|
||||
} else {
|
||||
match tokio::time::timeout(
|
||||
std::time::Duration::from_secs(60),
|
||||
@@ -1972,6 +1974,8 @@ pub async fn ai_chat_force_send(
|
||||
} else {
|
||||
conv.messages.push(ChatMessage::user(&user_content));
|
||||
}
|
||||
// 新用户轮把本请求钉扎为 WorkingContext 常驻目标(截断 200 字符,与 agentic G1 目标钉扎 GOAL_MAX_CHARS 同量级)
|
||||
conv.working_context.begin_turn(&user_content, 200);
|
||||
// F-260619-04 P1:push 后立即取末条 user 消息 id(供知识注入 referenced 溯源)。
|
||||
let user_msg_id = conv.messages.last_user_message_id();
|
||||
// G1 目标钉扎已迁移至 run_agentic_loop 工具调用推理(提取方式同 ai_chat_send)
|
||||
|
||||
@@ -1142,10 +1142,14 @@ pub(crate) struct ToolCallDraft {
|
||||
///
|
||||
/// 不在此推进任务状态 —— workflow.rs::run_workflow 内部已按 task_id+target_status 自动联动
|
||||
/// (成功推进到 target / 失败按 regression_target 退回),此处不重复。
|
||||
///
|
||||
/// `conv_id`(T4 会话关联)末参透传 run_workflow_inner:调用方带发起会话 ID 时,
|
||||
/// 启动写 workflow_id/workflow_dag_summary、终态回写摘要,供 agentic loop 注入 system prompt。
|
||||
pub(crate) async fn execute_run_workflow_for_tool(
|
||||
app: &tauri::AppHandle,
|
||||
state: &crate::state::AppState,
|
||||
args: &serde_json::Value,
|
||||
conv_id: Option<&str>,
|
||||
) -> anyhow::Result<serde_json::Value> {
|
||||
let task_id = args
|
||||
.get("task_id")
|
||||
@@ -1178,6 +1182,7 @@ pub(crate) async fn execute_run_workflow_for_tool(
|
||||
Some(task_id.clone()),
|
||||
Some(target_status.clone()),
|
||||
"ai",
|
||||
conv_id,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| anyhow::anyhow!("工作流执行失败: {}", e))?;
|
||||
|
||||
Reference in New Issue
Block a user