重构: 前端DRY收口+后端测试类型对齐
- 新增 useToast composable: 消除 AiChat/Settings/Projects 4处 toast 重复 统一默认3000ms(Projects原4000ms为操作类提示保留参数覆盖) - 新增 utils/json.ts parseJsonArray: 消除 parseStack/parseTags/ModuleNode 3处JSON字符串数组解析重复 - 新增 utils/html.ts escapeHtml: 消除 useMarkdown/FilePreview 2处重复 - ProjectDetail score-bar 内联三元改用 scoreTier(消除最后一处阈值硬编码) - ConversationSidebar 删除 formatTime 透传包装(直接用 formatRelative) - 清理死代码: parseTs/stringifyError/ErrorSink/_Unused 改私有或删除 wrapNakedDiff 改私有(无外部 import) - ModuleNode shortPath 改名 truncatedPath(与 useToolCard.shortPath 语义不同)
This commit is contained in:
@@ -282,8 +282,8 @@ fn compress_old_messages_marks_compressed_and_returns_refs() {
|
||||
assert_eq!(compressed[1].content, "旧回复1");
|
||||
|
||||
// status 已改 compressed
|
||||
assert_eq!(mgr.messages_mut()[0].message.status.as_deref(), Some("compressed"));
|
||||
assert_eq!(mgr.messages_mut()[1].message.status.as_deref(), Some("compressed"));
|
||||
assert_eq!(mgr.messages_mut()[0].message.status.as_ref(), Some(&MessageStatus::Compressed));
|
||||
assert_eq!(mgr.messages_mut()[1].message.status.as_ref(), Some(&MessageStatus::Compressed));
|
||||
// 保护区外(本例 index 2)仍 active
|
||||
assert!(mgr.messages_mut()[2].message.is_active(), "保护区外消息不应被动");
|
||||
|
||||
@@ -346,8 +346,8 @@ fn compress_old_messages_skips_already_inactive() {
|
||||
);
|
||||
// truncated 状态不被改成 compressed(保留原 truncated,语义不混淆)
|
||||
assert_eq!(
|
||||
mgr.messages_mut()[0].message.status.as_deref(),
|
||||
Some("truncated"),
|
||||
mgr.messages_mut()[0].message.status.as_ref(),
|
||||
Some(&MessageStatus::Truncated),
|
||||
"已 truncated 不应被改写为 compressed"
|
||||
);
|
||||
}
|
||||
@@ -660,7 +660,7 @@ fn topic_field_survives_compress_old_messages() {
|
||||
assert_eq!(mgr.messages_mut()[0].topic.as_deref(), Some("code"), "compressed 消息 topic 应保留");
|
||||
assert_eq!(mgr.messages_mut()[1].topic.as_deref(), Some("file"), "compressed 消息 topic 应保留");
|
||||
// status 改为 compressed
|
||||
assert_eq!(mgr.messages_mut()[0].message.status.as_deref(), Some("compressed"));
|
||||
assert_eq!(mgr.messages_mut()[0].message.status.as_ref(), Some(&MessageStatus::Compressed));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -218,7 +218,7 @@ mod tests {
|
||||
node_id: node_id.to_string(),
|
||||
inputs: HashMap::new(),
|
||||
config,
|
||||
execution_id: execution_id.to_string(),
|
||||
execution_id: execution_id.into(),
|
||||
event_bus: event_bus.clone(),
|
||||
node_status: StateMachine::new(),
|
||||
}
|
||||
@@ -235,7 +235,7 @@ mod tests {
|
||||
) {
|
||||
event_bus
|
||||
.send(WorkflowEvent::HumanApprovalResponse {
|
||||
execution_id: execution_id.to_string(),
|
||||
execution_id: execution_id.into(),
|
||||
node_id: node_id.to_string(),
|
||||
decision: decision.to_string(),
|
||||
decisions: vec![],
|
||||
@@ -254,7 +254,7 @@ mod tests {
|
||||
) {
|
||||
event_bus
|
||||
.send(WorkflowEvent::HumanApprovalResponse {
|
||||
execution_id: execution_id.to_string(),
|
||||
execution_id: execution_id.into(),
|
||||
node_id: node_id.to_string(),
|
||||
decision: String::new(),
|
||||
decisions: decisions.iter().map(|s| s.to_string()).collect(),
|
||||
@@ -477,8 +477,8 @@ mod tests {
|
||||
dag.add_node("b".to_string(), Box::new(HumanNode));
|
||||
dag.add_edge("a".to_string(), "b".to_string());
|
||||
|
||||
let mut executor = DagExecutor::new(bus.clone(), exec_id.to_string());
|
||||
let sm = executor.state_machine(); // 共享状态机(spawn 后仍可读)
|
||||
let mut executor = DagExecutor::new(bus.clone(), exec_id.into());
|
||||
let sm = executor.state_machine(); // 共享状态机(spawn 后仍可读)
|
||||
|
||||
let run_handle = tokio::spawn(async move {
|
||||
executor
|
||||
@@ -537,7 +537,7 @@ mod tests {
|
||||
let mut dag = Dag::new();
|
||||
dag.add_node("h".to_string(), Box::new(HumanNode));
|
||||
|
||||
let mut executor = DagExecutor::new(bus.clone(), exec_id.to_string());
|
||||
let mut executor = DagExecutor::new(bus.clone(), exec_id.into());
|
||||
let sm = executor.state_machine();
|
||||
|
||||
let run_handle = tokio::spawn(async move {
|
||||
|
||||
@@ -110,7 +110,7 @@ async fn node_config_overrides_global_in_node_context() {
|
||||
|
||||
let dag = registry.build_dag(&def).expect("build_dag");
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-nodecfg".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-nodecfg".into());
|
||||
// 全局 config 写 foo=GLOBAL(验证被 n1 节点级覆盖,n2 回退用全局)
|
||||
let outputs = executor
|
||||
.run(&dag, serde_json::json!({ "foo": "GLOBAL" }))
|
||||
@@ -138,7 +138,7 @@ async fn test_same_layer_runs_in_parallel() {
|
||||
dag.add_node("a".to_string(), Box::new(SleepNode { sleep_ms: 100 }));
|
||||
dag.add_node("b".to_string(), Box::new(SleepNode { sleep_ms: 100 }));
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-exec".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-exec".into());
|
||||
let start = std::time::Instant::now();
|
||||
let outputs = executor.run(&dag, serde_json::Value::Null).await.unwrap();
|
||||
let elapsed = start.elapsed();
|
||||
@@ -161,7 +161,7 @@ async fn test_layer_failure_aborts_following_layers() {
|
||||
dag.add_node("c".to_string(), Box::new(SleepNode { sleep_ms: 10 }));
|
||||
dag.add_edge("a".to_string(), "c".to_string());
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-exec".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-exec".into());
|
||||
let err = executor
|
||||
.run(&dag, serde_json::Value::Null)
|
||||
.await
|
||||
@@ -206,7 +206,7 @@ async fn test_cancelled_node_skips_set_failed() {
|
||||
let mut dag = Dag::new();
|
||||
dag.add_node("x".to_string(), Box::new(CancelSelfNode));
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cancel".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cancel".into());
|
||||
let result = executor.run(&dag, serde_json::Value::Null).await;
|
||||
|
||||
// run 返回 Err(取消致中止后续层),但不 panic/bail transition
|
||||
@@ -257,7 +257,7 @@ async fn test_cancelled_node_skips_set_completed() {
|
||||
let mut dag = Dag::new();
|
||||
dag.add_node("y".to_string(), Box::new(CancelSelfThenOkNode));
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cancel-ok".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cancel-ok".into());
|
||||
let result = executor.run(&dag, serde_json::Value::Null).await;
|
||||
|
||||
// run 返回 Ok —— Ok 节点不应因 TOCTOU 取消被误判为失败
|
||||
@@ -285,7 +285,7 @@ async fn test_cancelled_node_emits_node_cancelled_event() {
|
||||
|
||||
let bus = EventBus::new();
|
||||
let mut rx = bus.subscribe();
|
||||
let mut executor = DagExecutor::new(bus, "test-cancel-event".to_string());
|
||||
let mut executor = DagExecutor::new(bus, "test-cancel-event".into());
|
||||
let _ = executor.run(&dag, serde_json::Value::Null).await;
|
||||
|
||||
// 收集所有事件(run 已结束,事件总线无新事件)
|
||||
@@ -408,7 +408,7 @@ async fn conditions_eval_routes_by_edge_condition() {
|
||||
"$.ok == false".to_string(),
|
||||
);
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-route".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-route".into());
|
||||
let outputs = executor
|
||||
.run(&dag, serde_json::Value::Null)
|
||||
.await
|
||||
@@ -462,7 +462,7 @@ async fn conditions_eval_skip_keeps_pending() {
|
||||
"$.ok == false".to_string(),
|
||||
);
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-skip".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-skip".into());
|
||||
let outputs = executor
|
||||
.run(&dag, serde_json::Value::Null)
|
||||
.await
|
||||
@@ -504,7 +504,7 @@ async fn conditions_eval_unconditional_edge_always_passes() {
|
||||
"$.ok == false".to_string(),
|
||||
);
|
||||
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-mix".to_string());
|
||||
let mut executor = DagExecutor::new(EventBus::new(), "test-cond-mix".into());
|
||||
let outputs = executor
|
||||
.run(&dag, serde_json::Value::Null)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user