Skip to content

Commit 576762b

Browse files
refactor: 拆分大函数路径模块并收紧 nloc 棘轮 / split large-fn modules and tighten nloc ratchet
- chat_job_queue:worker 目录化(stream/json 任务体) - lib:run_agent_turn 迁至 run_agent_turn.rs 并再导出 - agent_turn:串行工具执行体迁至 serial/exec_serial.rs - 澄清问卷、markdown_links/check、quality_tools 等目录化(既有拆分) - 开发文档与 fn-nloc 基线同步 Co-authored-by: Yales Peter <noisystreet@users.noreply.github.com>
1 parent 9ed4a40 commit 576762b

20 files changed

Lines changed: 1608 additions & 1497 deletions

File tree

docs/开发文档.md

Lines changed: 5 additions & 4 deletions
Large diffs are not rendered by default.

scripts/fn_nloc_max_baseline.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
226
1+
217
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2039
1+
2006
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
//! 串行工具批执行主循环(从 [`super::`] 拆出以降低 `serial/mod.rs` 行数)。
2+
3+
use std::collections::HashMap;
4+
use std::time::Instant;
5+
6+
use log::info;
7+
8+
use crate::agent::workflow_tool_dispatch;
9+
use crate::tool_registry::{self, HandlerId, ToolRuntime};
10+
11+
use super::super::{
12+
ExecuteToolsBatchOutcome, ExecuteToolsCommonCtx, abort_tool_batch_if_sse_closed,
13+
};
14+
use super::after_dispatch::{
15+
serial_bookkeep_run_command_failure, serial_log_web_audit_write_tool_if_needed,
16+
serial_maybe_invalidate_codebase_semantic_index, serial_tool_iteration_sse_preface,
17+
};
18+
use super::emit::{
19+
emit_serial_tool_result, serial_bookkeep_readonly_tool_ttl_cache_after_tool,
20+
serial_emit_early_without_dispatch,
21+
};
22+
use super::{
23+
SerialEmitEarlyWithoutDispatchParams, SerialEmitToolResultParams,
24+
SerialToolIterationSsePreface, SerialTtlAfterDispatchParams,
25+
};
26+
27+
pub(super) async fn execute_tools_serial_impl(
28+
ctx: ExecuteToolsCommonCtx<'_>,
29+
workspace_changed: &mut bool,
30+
) -> ExecuteToolsBatchOutcome {
31+
let ExecuteToolsCommonCtx {
32+
tool_calls,
33+
per_coord,
34+
messages,
35+
cfg,
36+
effective_working_dir,
37+
workspace_is_set,
38+
read_file_turn_cache,
39+
workspace_changelist,
40+
out,
41+
tool_running_hook: _,
42+
clarification_questionnaire_hook,
43+
echo_terminal_transcript,
44+
terminal_tool_display_max_chars,
45+
tool_result_envelope_v1,
46+
web_tool_ctx,
47+
cli_tool_ctx,
48+
mcp_session,
49+
request_chrome_trace,
50+
step_executor_constraint,
51+
tools_defs_full,
52+
turn_allow,
53+
long_term_memory,
54+
long_term_memory_scope_id,
55+
tracing_chat_turn,
56+
request_audit,
57+
tool_outcome_recorder,
58+
handler_lookup,
59+
sync_default_sandbox_backend,
60+
readonly_tool_ttl_cache,
61+
sse_control_mirror,
62+
} = ctx;
63+
64+
let sse_mirror_for_emit = sse_control_mirror.clone();
65+
66+
let mut readonly_cache: HashMap<(String, String), String> = HashMap::new();
67+
for tc in tool_calls {
68+
if abort_tool_batch_if_sse_closed(
69+
out,
70+
"SSE sender closed during tool execution, aborting remaining tools",
71+
)
72+
.await
73+
{
74+
return ExecuteToolsBatchOutcome::AbortedSse;
75+
}
76+
77+
let name = tc.function.name.clone();
78+
let args = tc.function.arguments.clone();
79+
let id = tc.id.clone();
80+
serial_tool_iteration_sse_preface(SerialToolIterationSsePreface {
81+
out,
82+
sse_mirror: sse_mirror_for_emit.as_ref(),
83+
cfg,
84+
tracing_chat_turn: tracing_chat_turn.as_ref(),
85+
id: id.as_str(),
86+
name: &name,
87+
args: &args,
88+
messages,
89+
})
90+
.await;
91+
92+
if serial_emit_early_without_dispatch(SerialEmitEarlyWithoutDispatchParams {
93+
messages,
94+
per_coord,
95+
cfg,
96+
tool_outcome_recorder: &tool_outcome_recorder,
97+
out,
98+
sse_control_mirror: sse_mirror_for_emit.clone(),
99+
clarification_questionnaire_hook: clarification_questionnaire_hook.clone(),
100+
echo_terminal_transcript,
101+
terminal_tool_display_max_chars,
102+
tool_result_envelope_v1,
103+
effective_working_dir,
104+
name: name.as_str(),
105+
args: args.as_str(),
106+
id: id.as_str(),
107+
step_executor_constraint,
108+
tools_defs_full,
109+
turn_allow,
110+
readonly_cache: &mut readonly_cache,
111+
readonly_tool_ttl_cache: &readonly_tool_ttl_cache,
112+
})
113+
.await
114+
{
115+
continue;
116+
}
117+
118+
let is_readonly = tool_registry::is_readonly_tool(cfg.as_ref(), name.as_str());
119+
let cache_key = (name.clone(), args.clone());
120+
121+
let t_tool = Instant::now();
122+
let runtime = if let Some(cctx) = cli_tool_ctx {
123+
ToolRuntime::Cli {
124+
workspace_changed,
125+
ctx: cctx,
126+
}
127+
} else {
128+
ToolRuntime::Web {
129+
workspace_changed,
130+
ctx: web_tool_ctx,
131+
}
132+
};
133+
let (result, reflection_inject) =
134+
if handler_lookup.id_for(name.as_str()) == HandlerId::Workflow {
135+
workflow_tool_dispatch::dispatch_workflow_execute_tool(
136+
runtime,
137+
per_coord,
138+
cfg,
139+
effective_working_dir,
140+
workspace_is_set,
141+
args.as_str(),
142+
request_chrome_trace.clone(),
143+
)
144+
.await
145+
} else {
146+
tool_registry::dispatch_tool(tool_registry::DispatchToolParams {
147+
runtime,
148+
cfg,
149+
effective_working_dir,
150+
workspace_is_set,
151+
name: &name,
152+
args: &args,
153+
sse_out_tx: out,
154+
sse_control_mirror: sse_mirror_for_emit.as_ref(),
155+
tc,
156+
read_file_turn_cache: read_file_turn_cache.clone(),
157+
workspace_changelist: workspace_changelist.cloned(),
158+
mcp_session,
159+
turn_allow,
160+
long_term_memory: long_term_memory.clone(),
161+
long_term_memory_scope_id: long_term_memory_scope_id.clone(),
162+
handler_lookup: &handler_lookup,
163+
sync_default_sandbox_backend: &sync_default_sandbox_backend,
164+
})
165+
.await
166+
};
167+
168+
info!(
169+
target: super::super::LOG_TARGET,
170+
"工具调用完成 tool={} args_preview={} elapsed_ms={}",
171+
name,
172+
crate::redact::tool_arguments_preview_for_log(&args),
173+
t_tool.elapsed().as_millis()
174+
);
175+
176+
serial_log_web_audit_write_tool_if_needed(
177+
cfg.as_ref(),
178+
is_readonly,
179+
request_audit.as_ref(),
180+
tracing_chat_turn.as_ref(),
181+
long_term_memory_scope_id.as_deref(),
182+
name.as_str(),
183+
args.as_str(),
184+
);
185+
186+
serial_bookkeep_run_command_failure(
187+
per_coord,
188+
name.as_str(),
189+
args.as_str(),
190+
result.as_str(),
191+
);
192+
193+
serial_maybe_invalidate_codebase_semantic_index(
194+
cfg,
195+
effective_working_dir,
196+
workspace_changed,
197+
is_readonly,
198+
name.as_str(),
199+
args.as_str(),
200+
result.as_str(),
201+
);
202+
203+
serial_bookkeep_readonly_tool_ttl_cache_after_tool(SerialTtlAfterDispatchParams {
204+
cfg: cfg.as_ref(),
205+
effective_working_dir,
206+
readonly_tool_ttl_cache: &readonly_tool_ttl_cache,
207+
name: name.as_str(),
208+
args: args.as_str(),
209+
result: result.as_str(),
210+
workspace_changed: *workspace_changed,
211+
});
212+
213+
if (!is_readonly || *workspace_changed)
214+
&& let Some(c) = read_file_turn_cache.as_ref()
215+
{
216+
c.clear();
217+
}
218+
219+
if is_readonly {
220+
readonly_cache.insert(cache_key, result.clone());
221+
} else {
222+
readonly_cache.clear();
223+
}
224+
225+
emit_serial_tool_result(SerialEmitToolResultParams {
226+
messages,
227+
per_coord,
228+
cfg,
229+
tool_outcome_recorder: &tool_outcome_recorder,
230+
out,
231+
sse_control_mirror: sse_mirror_for_emit.clone(),
232+
clarification_questionnaire_hook: clarification_questionnaire_hook.clone(),
233+
echo_terminal_transcript,
234+
terminal_tool_display_max_chars,
235+
tool_result_envelope_v1,
236+
name: name.as_str(),
237+
args: args.as_str(),
238+
id: id.as_str(),
239+
result,
240+
reflection_inject,
241+
})
242+
.await;
243+
}
244+
245+
ExecuteToolsBatchOutcome::Finished
246+
}

0 commit comments

Comments
 (0)