chore(config): wire the agent, sandbox, attachment and MCP settings
Declare the new config sections, expose the MCP runtime URL, and document the search, agent, sandbox_rpc and attachment defaults in config/default.toml. The dev script and ignore file pick up the extra local tooling.
ZhenYi committed
Modified config/default.toml config/default.toml +34 −0 View config/default.toml
@@ -27,6 +27,12 @@
2727batch_size = 100
2828poll_interval_secs = 2
2929task_timeout_secs = 120
30incremental = true
31incremental_max_changed_files = 2000
32git_timeout_secs = 120
33cat_file_batch = true
34parse_threads = 4
35meili_inflight = 4
3036
3137[import]
3238enabled = false
@@ -183,9 +189,15 @@
183189max_pagination = 100
184190default_pagination = 20
185191max_board_name_len = 100
192max_board_prefix_len = 10
186193max_title_len = 255
187194max_body_len = 65535
188195max_comment_len = 65535
196
197[issues.attachment]
198max_size = 26214400
199presign_ttl_secs = 3600
200max_pending_per_user = 50
189201max_label_name_len = 50
190202max_label_color_len = 7
191203max_milestone_title_len = 100
@@ -193,6 +205,24 @@
193205max_reaction_emoji_len = 32
194206max_mentions_per_message = 20
195207
208[agents]
209max_pagination = 100
210default_pagination = 20
211max_collection_name_len = 100
212max_agent_name_len = 100
213max_instructions_len = 32768
214# Lifetime of the per-run space token handed to the sandbox runtime when the
215# agent chat "MCP" option is enabled (seconds).
216mcp_token_ttl_secs = 86400
217
218[sandbox_rpc]
219enabled = false
220endpoint = "http://127.0.0.1:8091"
221fanout_endpoint = "http://127.0.0.1:8090"
222trusted_key = ""
223request_timeout_secs = 30
224stream_token_ttl_secs = 600
225
196226[git]
197227repo_root = "/opt/gitdata/repos"
198228objects_root = "/opt/gitdata/objects"
@@ -384,6 +414,10 @@
384414enabled = true
385415bind_addr = "0.0.0.0"
386416port = 3007
417# URL the sandbox-agent runtime uses to reach this MCP endpoint. Empty keeps
418# the agent chat "MCP" option unavailable. Dev sets it in config/local.toml;
419# production must point it at the runtime-reachable address.
420runtime_url = ""
387421# MCP endpoint Host header allowlist. Empty keeps the rmcp default (loopback only).
388422# Production must set e.g. ["mcp.gitdata.ai"].
389423allowed_hosts = []
Modified lib/config/src/issues.rs lib/config/src/issues.rs +25 −0 View lib/config/src/issues.rs
@@ -1,11 +1,33 @@
11use serde::Deserialize;
22
3/// Issue attachment uploads: presigned direct-to-storage PUTs plus the caps the
4/// web dialog mirrors (see `web/src/entities/issue/model/meta.ts`).
35#[derive(Clone, Debug, Deserialize)]
46#[serde(default)]
7pub struct IssueAttachmentConfig {
8 pub max_size: i64,
9 pub presign_ttl_secs: u64,
10 /// Unreferenced (or not-yet-submitted) uploads one user may keep around.
11 pub max_pending_per_user: u64,
12}
13
14impl Default for IssueAttachmentConfig {
15 fn default() -> Self {
16 Self {
17 max_size: 26_214_400,
18 presign_ttl_secs: 3600,
19 max_pending_per_user: 50,
20 }
21 }
22}
23
24#[derive(Clone, Debug, Deserialize)]
25#[serde(default)]
526pub struct IssueConfig {
627 pub max_pagination: u64,
728 pub default_pagination: u64,
829 pub max_board_name_len: usize,
30 pub max_board_prefix_len: usize,
931 pub max_title_len: usize,
1032 pub max_body_len: usize,
1133 pub max_comment_len: usize,
@@ -15,6 +37,7 @@
1537 pub max_milestone_description_len: usize,
1638 pub max_reaction_emoji_len: usize,
1739 pub max_mentions_per_message: usize,
40 pub attachment: IssueAttachmentConfig,
1841}
1942
2043impl Default for IssueConfig {
@@ -23,6 +46,7 @@
2346 max_pagination: 100,
2447 default_pagination: 20,
2548 max_board_name_len: 100,
49 max_board_prefix_len: 10,
2650 max_title_len: 255,
2751 max_body_len: 65_535,
2852 max_comment_len: 65_535,
@@ -32,6 +56,7 @@
3256 max_milestone_description_len: 1024,
3357 max_reaction_emoji_len: 32,
3458 max_mentions_per_message: 20,
59 attachment: IssueAttachmentConfig::default(),
3560 }
3661 }
3762}
Modified lib/config/src/lib.rs lib/config/src/lib.rs +10 −0 View lib/config/src/lib.rs
@@ -1,4 +1,5 @@
11pub mod admin;
2pub mod agents;
23pub mod ai;
34pub mod aihost;
45pub mod apihost;
@@ -22,6 +23,7 @@
2223pub mod redis;
2324pub mod runner;
2425pub mod s3;
26pub mod sandbox_rpc;
2527pub mod scoped;
2628pub mod search;
2729pub mod session;
@@ -36,6 +38,7 @@
3638pub use error::ConfigError;
3739
3840use crate::admin::AdminConfig;
41use crate::agents::AgentsConfig;
3942use crate::ai::AiConfig;
4043use crate::aihost::AiHostServerConfig;
4144use crate::apihost::ApihostConfig;
@@ -58,6 +61,7 @@
5861use crate::redis::RedisConfig;
5962use crate::runner::RunnerConfig;
6063use crate::s3::S3Config;
64use crate::sandbox_rpc::SandboxRpcConfig;
6165use crate::search::SearchConfig;
6266use crate::session::SessionConfig;
6367use crate::space::SpaceConfig;
@@ -83,6 +87,8 @@
8387 pub quota: quota::QuotaConfig,
8488 pub space: SpaceConfig,
8589 pub issues: IssueConfig,
90 pub agents: AgentsConfig,
91 pub sandbox_rpc: SandboxRpcConfig,
8692 pub livekit: LiveKitConfig,
8793 pub mcp: McpConfig,
8894 pub git: GitConfig,
@@ -130,6 +136,10 @@
130136 self.aihost.is_valid().map_err(ConfigError::Validation)?;
131137 self.livekit.is_valid().map_err(ConfigError::Validation)?;
132138 self.mcp.is_valid().map_err(ConfigError::Validation)?;
139 self.agents.validate().map_err(ConfigError::Validation)?;
140 self.sandbox_rpc
141 .is_valid()
142 .map_err(ConfigError::Validation)?;
133143 self.push.is_valid().map_err(ConfigError::Validation)?;
134144 Ok(())
135145 }
Modified lib/config/src/mcp.rs lib/config/src/mcp.rs +17 −0 View lib/config/src/mcp.rs
@@ -14,6 +14,9 @@
1414 pub internal_cidrs: Vec<String>,
1515 pub trusted_proxies: Vec<String>,
1616 pub internal_keys: Vec<InternalKeyConfig>,
17 /// URL the sandbox-agent runtime uses to reach this MCP endpoint (e.g.
18 /// `http://127.0.0.1:3007/v1`). Empty disables the agent-chat MCP option.
19 pub runtime_url: Option<String>,
1720}
1821
1922impl Default for McpConfig {
@@ -26,6 +29,7 @@
2629 internal_cidrs: vec!["127.0.0.1/32".to_string(), "::1/128".to_string()],
2730 trusted_proxies: Vec::new(),
2831 internal_keys: Vec::new(),
32 runtime_url: None,
2933 }
3034 }
3135}
@@ -58,6 +62,12 @@
5862 self.port.unwrap_or(3007)
5963 }
6064
65 /// Runtime-facing URL of this MCP endpoint; empty when the agent chat MCP
66 /// option must stay unavailable.
67 pub fn runtime_url(&self) -> &str {
68 self.runtime_url.as_deref().unwrap_or("").trim()
69 }
70
6171 pub fn is_valid(&self) -> Result<(), String> {
6272 if !self.enabled() {
6373 return Ok(());
@@ -69,6 +79,13 @@
6979 if self.port == Some(0) {
7080 return Err("mcp.port must be greater than 0".to_string());
7181 }
82 if !self.runtime_url().is_empty() {
83 let url = url::Url::parse(self.runtime_url())
84 .map_err(|e| format!("mcp.runtime_url is not a valid URL: {e}"))?;
85 if url.scheme() != "http" && url.scheme() != "https" {
86 return Err("mcp.runtime_url must use http or https".to_string());
87 }
88 }
7289 for host in &self.allowed_hosts {
7390 if host.trim().is_empty() {
7491 return Err("mcp.allowed_hosts must not contain empty entries".to_string());
Modified lib/config/Cargo.toml lib/config/Cargo.toml +1 −0 View lib/config/Cargo.toml
@@ -12,3 +12,4 @@
1212ipnet = { workspace = true }
1313thiserror = { workspace = true }
1414tracing = { workspace = true }
15url = { workspace = true }
Modified scripts/dev.ps1 scripts/dev.ps1 +3 −2 View scripts/dev.ps1
@@ -18,6 +18,7 @@
1818 githost = @{ Exe = 'githost'; Port = 9418; Health = $true; Extra = @(4022) }
1919 im = @{ Exe = 'im'; Port = 4082; Health = $true }
2020 synchost = @{ Exe = 'synchost'; Port = 4083; Health = $true }
21 searchhost = @{ Exe = 'searchhost'; Port = 0; Health = $false }
2122 mails = @{ Exe = 'mails'; Port = 4084; Health = $true }
2223 adminhost = @{ Exe = 'adminhost'; Port = 3004; Health = $true }
2324 webhook = @{ Exe = 'webhook'; Port = 3005; Health = $true }
@@ -25,8 +26,8 @@
2526 mcp = @{ Exe = 'mcp'; Port = 3007; Health = $true }
2627 web = @{ Bun = 'web'; Port = 5173; Health = $false }
2728}
28$Order = @('migrate', 'apihost', 'githost', 'im', 'synchost', 'mails', 'adminhost', 'webhook', 'aihost', 'mcp', 'web')
29$Backends = @('migrate', 'apihost', 'githost', 'im', 'synchost', 'mails', 'adminhost', 'webhook', 'aihost', 'mcp')
29$Order = @('migrate', 'apihost', 'githost', 'im', 'synchost', 'searchhost', 'mails', 'adminhost', 'webhook', 'aihost', 'mcp', 'web')
30$Backends = @('migrate', 'apihost', 'githost', 'im', 'synchost', 'searchhost', 'mails', 'adminhost', 'webhook', 'aihost', 'mcp')
3031$Aliases = @{
3132 api = 'apihost'
3233 git = 'githost'
Modified .gitignore .gitignore +1 −0 View .gitignore
@@ -11,3 +11,4 @@
1111admin/node_modules
1212.codegraph
1313sagent-plan.md
14.playwright-mcp
No newline at end of file