mod config_builder_sections;
pub(crate) use config_builder_sections::ConfigBuilder;
use super::source::{AgentRoleRow, AgentSection, ScheduledAgentTaskRow, ToolRegistrySection};
pub(super) fn override_string(dst: &mut String, src: Option<String>) {
if let Some(s) = src {
let s = s.trim().to_string();
if !s.is_empty() {
*dst = s;
}
}
}
pub(super) fn override_opt_string_non_empty(dst: &mut Option<String>, src: Option<String>) {
if let Some(s) = src {
let s = s.trim().to_string();
if !s.is_empty() {
*dst = Some(s);
}
}
}
pub(super) fn override_opt_string_trimmed(dst: &mut Option<String>, src: Option<&String>) {
if let Some(s) = src {
*dst = Some(s.trim().to_string());
}
}
pub(super) fn override_opt_vec(dst: &mut Option<Vec<String>>, src: &Option<Vec<String>>) {
if let Some(ref v) = *src
&& !v.is_empty()
{
*dst = Some(v.clone());
}
}
pub(super) fn override_opt_vec_allow_empty(
dst: &mut Option<Vec<String>>,
src: &Option<Vec<String>>,
) {
if let Some(ref v) = *src {
*dst = Some(v.clone());
}
}
impl ConfigBuilder {
pub(super) fn apply_section(&mut self, agent: AgentSection) {
self.apply_section_identity_prompt_and_lists(&agent);
self.apply_section_merge_numeric_mid(&agent);
self.apply_section_merge_numeric_tail_queues(&agent);
self.apply_section_merge_numeric_tail_sandbox_web_conv(&agent);
self.apply_section_merge_numeric_tail_context_tool_explain(&agent);
self.apply_section_merge_numeric_tail_memory_mcp_semantic_intent(&agent);
}
fn apply_section_identity_prompt_and_lists(&mut self, agent: &AgentSection) {
let llm = &mut self.llm;
override_string(&mut llm.api_base, agent.api_base.clone());
override_string(&mut llm.model, agent.model.clone());
override_opt_string_non_empty(&mut llm.planner_model, agent.planner_model.clone());
override_opt_string_non_empty(&mut llm.executor_model, agent.executor_model.clone());
override_opt_string_non_empty(
&mut llm.llm_http_auth_mode_str,
agent.llm_http_auth_mode.clone(),
);
let rp = &mut self.roles_prompts;
let no_system_prompt_file_in_section = agent.system_prompt_file.is_none();
let inline_system_prompt_nonempty = agent
.system_prompt
.as_ref()
.is_some_and(|s| !s.trim().is_empty());
override_opt_string_non_empty(&mut rp.system_prompt_file, agent.system_prompt_file.clone());
override_string(&mut rp.system_prompt, agent.system_prompt.clone());
override_opt_string_non_empty(
&mut rp.default_agent_role_id,
agent.default_agent_role.clone(),
);
rp.coding_workbench_enabled = agent
.coding_workbench_enabled
.or(rp.coding_workbench_enabled);
override_opt_string_non_empty(
&mut rp.coding_workbench_increment_file,
agent.coding_workbench_increment_file.clone(),
);
override_opt_string_non_empty(
&mut rp.default_session_mode,
agent.default_session_mode.clone(),
);
if no_system_prompt_file_in_section && inline_system_prompt_nonempty {
rp.system_prompt_file = None;
}
override_opt_string_non_empty(
&mut self.command_exec.run_command_working_dir,
agent.run_command_working_dir.clone(),
);
override_opt_string_non_empty(
&mut self.web_search.web_search_provider_str,
agent.web_search_provider.clone(),
);
override_opt_string_non_empty(
&mut self.per_plan_policy.final_plan_requirement_str,
agent.final_plan_requirement.clone(),
);
override_opt_string_non_empty(
&mut self.per_plan_policy.planner_executor_mode_str,
agent.planner_executor_mode.clone(),
);
override_opt_string_non_empty(
&mut self.cursor_rules.cursor_rules_dir,
agent.cursor_rules_dir.clone(),
);
override_opt_string_non_empty(&mut self.skills.skills_dir, agent.skills_dir.clone());
override_opt_string_trimmed(
&mut self.skills.skills_user_dir,
agent.skills_user_dir.as_ref(),
);
override_opt_string_trimmed(
&mut self.skills.skills_system_dir,
agent.skills_system_dir.as_ref(),
);
override_opt_string_trimmed(
&mut self.web_api.web_api_bearer_token,
agent.web_api_bearer_token.as_ref(),
);
if let Some(ref k) = agent.web_search_api_key {
self.web_search.web_search_api_key = Some(k.clone());
}
override_opt_vec(
&mut self.command_exec.allowed_commands,
&agent.allowed_commands,
);
override_opt_vec_allow_empty(
&mut self.http_fetch.http_fetch_allowed_prefixes,
&agent.http_fetch_allowed_prefixes,
);
override_opt_vec(
&mut self.workspace_roots.workspace_allowed_roots,
&agent.workspace_allowed_roots,
);
override_opt_vec(
&mut self.web_api.web_cors_allowed_origins,
&agent.web_cors_allowed_origins,
);
if let Some(ref v) = agent.web_workspace_pool {
self.workspace_roots.web_workspace_pool = Some(v.clone());
}
}
fn apply_section_merge_numeric_mid(&mut self, agent: &AgentSection) {
let su = &mut self.session_ui;
su.max_message_history = agent.max_message_history.or(su.max_message_history);
let ce = &mut self.command_exec;
ce.command_timeout_secs = agent.command_timeout_secs.or(ce.command_timeout_secs);
ce.command_max_output_len = agent.command_max_output_len.or(ce.command_max_output_len);
ce.allow_external_path_with_approval = agent
.allow_external_path_with_approval
.or(ce.allow_external_path_with_approval);
let samp = &mut self.llm_sampling;
samp.max_tokens = agent.max_tokens.or(samp.max_tokens);
samp.llm_context_tokens = agent.llm_context_tokens.or(samp.llm_context_tokens);
samp.temperature = agent.temperature.or(samp.temperature);
samp.llm_seed = agent.llm_seed.or(samp.llm_seed);
let lv = &mut self.llm_vendor;
lv.llm_reasoning_split = agent.llm_reasoning_split.or(lv.llm_reasoning_split);
lv.llm_bigmodel_thinking = agent.llm_bigmodel_thinking.or(lv.llm_bigmodel_thinking);
lv.llm_kimi_thinking_disabled = agent
.llm_kimi_thinking_disabled
.or(lv.llm_kimi_thinking_disabled);
let retry = &mut self.llm_http_retry;
retry.api_timeout_secs = agent.api_timeout_secs.or(retry.api_timeout_secs);
retry.api_max_retries = agent.api_max_retries.or(retry.api_max_retries);
retry.api_retry_delay_secs = agent.api_retry_delay_secs.or(retry.api_retry_delay_secs);
self.weather_tool.weather_timeout_secs = agent
.weather_timeout_secs
.or(self.weather_tool.weather_timeout_secs);
let ws = &mut self.web_search;
ws.web_search_timeout_secs = agent.web_search_timeout_secs.or(ws.web_search_timeout_secs);
ws.web_search_max_results = agent.web_search_max_results.or(ws.web_search_max_results);
let hf = &mut self.http_fetch;
hf.http_fetch_timeout_secs = agent.http_fetch_timeout_secs.or(hf.http_fetch_timeout_secs);
hf.http_fetch_max_response_bytes = agent
.http_fetch_max_response_bytes
.or(hf.http_fetch_max_response_bytes);
override_opt_string_non_empty(&mut hf.http_fetch_user_agent, agent.http_fetch_user_agent.clone());
let pp = &mut self.per_plan_policy;
pp.reflection_default_max_rounds = agent
.reflection_default_max_rounds
.or(pp.reflection_default_max_rounds);
pp.plan_rewrite_max_attempts = agent
.plan_rewrite_max_attempts
.or(pp.plan_rewrite_max_attempts);
pp.final_plan_require_strict_workflow_node_coverage = agent
.final_plan_require_strict_workflow_node_coverage
.or(pp.final_plan_require_strict_workflow_node_coverage);
pp.final_plan_semantic_check_enabled = agent
.final_plan_semantic_check_enabled
.or(pp.final_plan_semantic_check_enabled);
pp.final_plan_semantic_check_accept_legacy_text = agent
.final_plan_semantic_check_accept_legacy_text
.or(pp.final_plan_semantic_check_accept_legacy_text);
pp.final_plan_semantic_check_max_non_readonly_tools = agent
.final_plan_semantic_check_max_non_readonly_tools
.or(pp.final_plan_semantic_check_max_non_readonly_tools);
pp.final_plan_semantic_check_max_tokens = agent
.final_plan_semantic_check_max_tokens
.or(pp.final_plan_semantic_check_max_tokens);
let cr = &mut self.cursor_rules;
cr.cursor_rules_enabled = agent.cursor_rules_enabled.or(cr.cursor_rules_enabled);
cr.cursor_rules_include_agents_md = agent
.cursor_rules_include_agents_md
.or(cr.cursor_rules_include_agents_md);
cr.cursor_rules_max_chars = agent.cursor_rules_max_chars.or(cr.cursor_rules_max_chars);
let sk = &mut self.skills;
sk.skills_enabled = agent.skills_enabled.or(sk.skills_enabled);
sk.skills_max_chars = agent.skills_max_chars.or(sk.skills_max_chars);
sk.skills_top_k = agent.skills_top_k.or(sk.skills_top_k);
let tt = &mut self.tool_transcript;
tt.tool_message_max_chars = agent.tool_message_max_chars.or(tt.tool_message_max_chars);
tt.tool_result_envelope_v1 = agent.tool_result_envelope_v1.or(tt.tool_result_envelope_v1);
tt.sse_tool_call_include_arguments = agent
.sse_tool_call_include_arguments
.or(tt.sse_tool_call_include_arguments);
let ats = &mut self.agent_tool_stats;
ats.agent_tool_stats_enabled = agent
.agent_tool_stats_enabled
.or(ats.agent_tool_stats_enabled);
ats.agent_tool_stats_window_events = agent
.agent_tool_stats_window_events
.or(ats.agent_tool_stats_window_events);
ats.agent_tool_stats_min_samples = agent
.agent_tool_stats_min_samples
.or(ats.agent_tool_stats_min_samples);
ats.agent_tool_stats_max_chars = agent
.agent_tool_stats_max_chars
.or(ats.agent_tool_stats_max_chars);
ats.agent_tool_stats_warn_below_success_ratio = agent
.agent_tool_stats_warn_below_success_ratio
.or(ats.agent_tool_stats_warn_below_success_ratio);
let te = &mut self.thinking_echo;
te.thinking_avoid_echo_system_prompt = agent
.thinking_avoid_echo_system_prompt
.or(te.thinking_avoid_echo_system_prompt);
let no_thinking_appendix_file_in_section =
agent.thinking_avoid_echo_appendix_file.is_none();
let inline_thinking_appendix_nonempty = agent
.thinking_avoid_echo_appendix
.as_ref()
.is_some_and(|s| !s.trim().is_empty());
override_opt_string_non_empty(
&mut te.thinking_avoid_echo_appendix_file,
agent.thinking_avoid_echo_appendix_file.clone(),
);
if let Some(ref s) = agent.thinking_avoid_echo_appendix
&& !s.trim().is_empty()
{
te.thinking_avoid_echo_appendix = Some(s.clone());
}
if no_thinking_appendix_file_in_section && inline_thinking_appendix_nonempty {
te.thinking_avoid_echo_appendix_file = None;
}
let cp = &mut self.context_pipeline;
cp.context_char_budget = agent.context_char_budget.or(cp.context_char_budget);
cp.context_min_messages_after_system = agent
.context_min_messages_after_system
.or(cp.context_min_messages_after_system);
cp.context_token_trigger_percent = agent
.context_token_trigger_percent
.or(cp.context_token_trigger_percent);
cp.context_token_target_percent = agent
.context_token_target_percent
.or(cp.context_token_target_percent);
cp.context_token_safety_margin_tokens = agent
.context_token_safety_margin_tokens
.or(cp.context_token_safety_margin_tokens);
cp.context_summary_trigger_chars = agent
.context_summary_trigger_chars
.or(cp.context_summary_trigger_chars);
cp.context_summary_tail_messages = agent
.context_summary_tail_messages
.or(cp.context_summary_tail_messages);
cp.context_summary_max_tokens = agent
.context_summary_max_tokens
.or(cp.context_summary_max_tokens);
cp.context_summary_transcript_max_chars = agent
.context_summary_transcript_max_chars
.or(cp.context_summary_transcript_max_chars);
if let Some(ref p) = agent.context_summary_system_file {
cp.context_summary_system_file = Some(p.clone());
}
if let Some(ref p) = agent.context_summary_user_file {
cp.context_summary_user_file = Some(p.clone());
}
let wa = &mut self.web_api;
wa.health_llm_models_probe = agent.health_llm_models_probe.or(wa.health_llm_models_probe);
wa.health_llm_models_probe_cache_secs = agent
.health_llm_models_probe_cache_secs
.or(wa.health_llm_models_probe_cache_secs);
}
fn apply_section_merge_numeric_tail_queues(&mut self, agent: &AgentSection) {
let cqc = &mut self.chat_queues_cache;
cqc.chat_queue_max_concurrent = agent
.chat_queue_max_concurrent
.or(cqc.chat_queue_max_concurrent);
cqc.chat_queue_max_pending = agent.chat_queue_max_pending.or(cqc.chat_queue_max_pending);
cqc.parallel_readonly_tools_max = agent
.parallel_readonly_tools_max
.or(cqc.parallel_readonly_tools_max);
cqc.read_file_turn_cache_max_entries = agent
.read_file_turn_cache_max_entries
.or(cqc.read_file_turn_cache_max_entries);
cqc.readonly_tool_ttl_cache_secs = agent
.readonly_tool_ttl_cache_secs
.or(cqc.readonly_tool_ttl_cache_secs);
cqc.readonly_tool_ttl_cache_max_entries = agent
.readonly_tool_ttl_cache_max_entries
.or(cqc.readonly_tool_ttl_cache_max_entries);
cqc.test_result_cache_enabled = agent
.test_result_cache_enabled
.or(cqc.test_result_cache_enabled);
cqc.test_result_cache_max_entries = agent
.test_result_cache_max_entries
.or(cqc.test_result_cache_max_entries);
let swc = &mut self.session_workspace_changelist;
swc.session_workspace_changelist_enabled = agent
.session_workspace_changelist_enabled
.or(swc.session_workspace_changelist_enabled);
swc.session_workspace_changelist_max_chars = agent
.session_workspace_changelist_max_chars
.or(swc.session_workspace_changelist_max_chars);
}
fn apply_section_merge_numeric_tail_sandbox_web_conv(&mut self, agent: &AgentSection) {
let sb = &mut self.sync_tool_sandbox;
override_opt_string_non_empty(
&mut sb.sync_default_tool_sandbox_mode_str,
agent.sync_default_tool_sandbox_mode.clone(),
);
override_opt_string_non_empty(
&mut sb.sync_default_tool_sandbox_docker_image,
agent.sync_default_tool_sandbox_docker_image.clone(),
);
override_opt_string_non_empty(
&mut sb.sync_default_tool_sandbox_docker_network,
agent.sync_default_tool_sandbox_docker_network.clone(),
);
sb.sync_default_tool_sandbox_docker_timeout_secs = agent
.sync_default_tool_sandbox_docker_timeout_secs
.or(sb.sync_default_tool_sandbox_docker_timeout_secs);
override_opt_string_non_empty(
&mut sb.sync_default_tool_sandbox_docker_user,
agent.sync_default_tool_sandbox_docker_user.clone(),
);
let wa = &mut self.web_api;
wa.web_api_require_bearer = agent.web_api_require_bearer.or(wa.web_api_require_bearer);
wa.web_audit_log_write_tools = agent
.web_audit_log_write_tools
.or(wa.web_audit_log_write_tools);
wa.web_audit_trust_x_forwarded_for = agent
.web_audit_trust_x_forwarded_for
.or(wa.web_audit_trust_x_forwarded_for);
wa.allow_insecure_no_auth_for_non_loopback = agent
.allow_insecure_no_auth_for_non_loopback
.or(wa.allow_insecure_no_auth_for_non_loopback);
override_opt_string_non_empty(
&mut self.conversation_persistence.conversation_store_sqlite_path,
agent.conversation_store_sqlite_path.clone(),
);
}
fn apply_section_merge_numeric_tail_context_tool_explain(&mut self, agent: &AgentSection) {
let cbi = &mut self.context_bootstrap_inject;
cbi.agent_memory_file_enabled = agent
.agent_memory_file_enabled
.or(cbi.agent_memory_file_enabled);
override_opt_string_non_empty(&mut cbi.agent_memory_file, agent.agent_memory_file.clone());
cbi.agent_memory_file_max_chars = agent
.agent_memory_file_max_chars
.or(cbi.agent_memory_file_max_chars);
cbi.living_docs_inject_enabled = agent
.living_docs_inject_enabled
.or(cbi.living_docs_inject_enabled);
override_opt_string_non_empty(
&mut cbi.living_docs_relative_dir,
agent.living_docs_relative_dir.clone(),
);
cbi.living_docs_inject_max_chars = agent
.living_docs_inject_max_chars
.or(cbi.living_docs_inject_max_chars);
cbi.living_docs_file_max_each_chars = agent
.living_docs_file_max_each_chars
.or(cbi.living_docs_file_max_each_chars);
cbi.project_profile_inject_enabled = agent
.project_profile_inject_enabled
.or(cbi.project_profile_inject_enabled);
cbi.project_profile_inject_max_chars = agent
.project_profile_inject_max_chars
.or(cbi.project_profile_inject_max_chars);
cbi.project_dependency_brief_inject_enabled = agent
.project_dependency_brief_inject_enabled
.or(cbi.project_dependency_brief_inject_enabled);
cbi.project_dependency_brief_inject_max_chars = agent
.project_dependency_brief_inject_max_chars
.or(cbi.project_dependency_brief_inject_max_chars);
let tce = &mut self.tool_call_explain;
tce.tool_call_explain_enabled = agent
.tool_call_explain_enabled
.or(tce.tool_call_explain_enabled);
tce.tool_call_explain_min_chars = agent
.tool_call_explain_min_chars
.or(tce.tool_call_explain_min_chars);
tce.tool_call_explain_max_chars = agent
.tool_call_explain_max_chars
.or(tce.tool_call_explain_max_chars);
}
fn apply_section_merge_numeric_tail_memory_mcp_semantic_intent(
&mut self,
agent: &AgentSection,
) {
let ltm = &mut self.long_term_memory;
ltm.long_term_memory_enabled = agent
.long_term_memory_enabled
.or(ltm.long_term_memory_enabled);
override_opt_string_non_empty(
&mut ltm.long_term_memory_scope_mode_str,
agent.long_term_memory_scope_mode.clone(),
);
override_opt_string_non_empty(
&mut ltm.long_term_memory_vector_backend_str,
agent.long_term_memory_vector_backend.clone(),
);
ltm.long_term_memory_max_entries = agent
.long_term_memory_max_entries
.or(ltm.long_term_memory_max_entries);
ltm.long_term_memory_inject_max_chars = agent
.long_term_memory_inject_max_chars
.or(ltm.long_term_memory_inject_max_chars);
override_opt_string_non_empty(
&mut ltm.long_term_memory_store_sqlite_path,
agent.long_term_memory_store_sqlite_path.clone(),
);
ltm.long_term_memory_top_k = agent.long_term_memory_top_k.or(ltm.long_term_memory_top_k);
ltm.long_term_memory_max_chars_per_chunk = agent
.long_term_memory_max_chars_per_chunk
.or(ltm.long_term_memory_max_chars_per_chunk);
ltm.long_term_memory_min_chars_to_index = agent
.long_term_memory_min_chars_to_index
.or(ltm.long_term_memory_min_chars_to_index);
ltm.long_term_memory_async_index = agent
.long_term_memory_async_index
.or(ltm.long_term_memory_async_index);
ltm.long_term_memory_auto_index_turns = agent
.long_term_memory_auto_index_turns
.or(ltm.long_term_memory_auto_index_turns);
ltm.long_term_memory_auto_summarize_experience = agent
.long_term_memory_auto_summarize_experience
.or(ltm.long_term_memory_auto_summarize_experience);
ltm.long_term_memory_prioritize_experience_recall = agent
.long_term_memory_prioritize_experience_recall
.or(ltm.long_term_memory_prioritize_experience_recall);
ltm.long_term_memory_default_ttl_secs = agent
.long_term_memory_default_ttl_secs
.or(ltm.long_term_memory_default_ttl_secs);
let mcp = &mut self.mcp_client;
mcp.mcp_enabled = agent.mcp_enabled.or(mcp.mcp_enabled);
override_opt_string_non_empty(&mut mcp.mcp_command, agent.mcp_command.clone());
mcp.mcp_tool_timeout_secs = agent.mcp_tool_timeout_secs.or(mcp.mcp_tool_timeout_secs);
let cs = &mut self.codebase_semantic;
cs.codebase_semantic_search_enabled = agent
.codebase_semantic_search_enabled
.or(cs.codebase_semantic_search_enabled);
cs.codebase_semantic_invalidate_on_workspace_change = agent
.codebase_semantic_invalidate_on_workspace_change
.or(cs.codebase_semantic_invalidate_on_workspace_change);
override_opt_string_non_empty(
&mut cs.codebase_semantic_index_sqlite_path,
agent.codebase_semantic_index_sqlite_path.clone(),
);
cs.codebase_semantic_max_file_bytes = agent
.codebase_semantic_max_file_bytes
.or(cs.codebase_semantic_max_file_bytes);
cs.codebase_semantic_chunk_max_chars = agent
.codebase_semantic_chunk_max_chars
.or(cs.codebase_semantic_chunk_max_chars);
cs.codebase_semantic_top_k = agent.codebase_semantic_top_k.or(cs.codebase_semantic_top_k);
cs.codebase_semantic_query_max_chunks = agent
.codebase_semantic_query_max_chunks
.or(cs.codebase_semantic_query_max_chunks);
cs.codebase_semantic_rebuild_max_files = agent
.codebase_semantic_rebuild_max_files
.or(cs.codebase_semantic_rebuild_max_files);
cs.codebase_semantic_rebuild_incremental = agent
.codebase_semantic_rebuild_incremental
.or(cs.codebase_semantic_rebuild_incremental);
cs.codebase_semantic_hybrid_alpha = agent
.codebase_semantic_hybrid_alpha
.or(cs.codebase_semantic_hybrid_alpha);
cs.codebase_semantic_fts_top_n = agent
.codebase_semantic_fts_top_n
.or(cs.codebase_semantic_fts_top_n);
cs.codebase_semantic_hybrid_semantic_pool = agent
.codebase_semantic_hybrid_semantic_pool
.or(cs.codebase_semantic_hybrid_semantic_pool);
}
pub(super) fn merge_agent_role_rows(&mut self, rows: &[AgentRoleRow]) {
for row in rows {
let id = row.id.trim().to_string();
if id.is_empty() {
continue;
}
super::agent_roles::merge_into_role_entry(
self.agent_role_entries.entry(id).or_default(),
row.system_prompt.clone(),
row.system_prompt_file.clone(),
row.allowed_tools.clone(),
row.prepend_coding_workbench,
row.default_session_mode.clone(),
);
}
}
pub(super) fn merge_scheduled_agent_task_rows(&mut self, rows: &[ScheduledAgentTaskRow]) {
for row in rows {
self.scheduled_agent_task_rows.push(row.clone());
}
}
pub(super) fn apply_tool_registry(&mut self, tr: ToolRegistrySection) {
apply_tool_registry_timeouts(&mut self.tool_registry_policy, &tr);
apply_tool_registry_tool_lists(&mut self.tool_registry_policy, tr);
}
}
fn apply_tool_registry_timeouts(
p: &mut config_builder_sections::ConfigBuilderToolRegistryPolicy,
tr: &ToolRegistrySection,
) {
if let Some(v) = tr.http_fetch_wall_timeout_secs {
p.tool_registry_http_fetch_wall_timeout_secs = Some(v);
}
if let Some(v) = tr.http_request_wall_timeout_secs {
p.tool_registry_http_request_wall_timeout_secs = Some(v);
}
for (k, v) in &tr.parallel_wall_timeout_secs {
p.tool_registry_parallel_wall_timeout_secs
.insert(k.clone(), *v);
}
}
fn apply_tool_registry_tool_lists(
p: &mut config_builder_sections::ConfigBuilderToolRegistryPolicy,
tr: ToolRegistrySection,
) {
if let Some(v) = tr.parallel_sync_denied_tools {
p.tool_registry_parallel_sync_denied_tools = Some(v);
}
if let Some(v) = tr.parallel_sync_denied_prefixes {
p.tool_registry_parallel_sync_denied_prefixes = Some(v);
}
if let Some(v) = tr.sync_default_inline_tools {
p.tool_registry_sync_default_inline_tools = Some(v);
}
if let Some(v) = tr.write_effect_tools {
p.tool_registry_write_effect_tools = Some(v);
}
if let Some(v) = tr.sub_agent_patch_write_extra_tools {
p.tool_registry_sub_agent_patch_write_extra_tools = Some(v);
}
if let Some(v) = tr.sub_agent_test_runner_extra_tools {
p.tool_registry_sub_agent_test_runner_extra_tools = Some(v);
}
if let Some(v) = tr.sub_agent_review_readonly_deny_tools {
p.tool_registry_sub_agent_review_readonly_deny_tools = Some(v);
}
p.tool_registry_background_jobs_enabled = tr
.background_jobs_enabled
.or(p.tool_registry_background_jobs_enabled);
p.tool_registry_background_job_max_concurrent = tr
.background_job_max_concurrent
.or(p.tool_registry_background_job_max_concurrent);
p.tool_registry_background_job_max_queued = tr
.background_job_max_queued
.or(p.tool_registry_background_job_max_queued);
p.tool_registry_background_job_ttl_secs = tr
.background_job_ttl_secs
.or(p.tool_registry_background_job_ttl_secs);
p.tool_registry_background_job_result_grace_secs = tr
.background_job_result_grace_secs
.or(p.tool_registry_background_job_result_grace_secs);
p.tool_registry_background_job_max_entries = tr
.background_job_max_entries
.or(p.tool_registry_background_job_max_entries);
}