feat(code): gRPC server with JWT auth + tool routing

tonic 0.14 gRPC server for sunbeam code sessions:
- bidirectional streaming Session RPC
- JWT interceptor validates tokens against Hydra JWKS
- tool router classifies calls as client-side (file_read, bash,
  grep, etc.) or server-side (gitea, identity, search, etc.)
- service stub with session lifecycle (start, chat, tool results, end)
- coding_model config (default: devstral-small-2506)
- grpc config section (listen_addr, jwks_url)
- 182 tests (5 new: JWT claims, tool routing)

phase 2 TODOs: Matrix room bridge, Mistral agent loop, streaming
This commit is contained in:
2026-03-23 11:35:37 +00:00
parent 2a1d7a003d
commit 35b6246fa7
9 changed files with 472 additions and 0 deletions

View File

@@ -12,6 +12,8 @@ pub struct Config {
pub services: ServicesConfig,
#[serde(default)]
pub vault: VaultConfig,
#[serde(default)]
pub grpc: Option<GrpcConfig>,
}
#[derive(Debug, Clone, Deserialize)]
@@ -40,6 +42,9 @@ pub struct AgentsConfig {
/// Max recursion depth for research agents spawning sub-agents.
#[serde(default = "default_research_max_depth")]
pub research_max_depth: usize,
/// Model for coding agent sessions (sunbeam code).
#[serde(default = "default_coding_model")]
pub coding_model: String,
}
impl Default for AgentsConfig {
@@ -53,6 +58,7 @@ impl Default for AgentsConfig {
research_max_iterations: default_research_max_iterations(),
research_max_agents: default_research_max_agents(),
research_max_depth: default_research_max_depth(),
coding_model: default_coding_model(),
}
}
}
@@ -233,6 +239,19 @@ fn default_research_agent_model() -> String { "ministral-3b-latest".into() }
fn default_research_max_iterations() -> usize { 10 }
fn default_research_max_agents() -> usize { 25 }
fn default_research_max_depth() -> usize { 4 }
fn default_coding_model() -> String { "devstral-small-2506".into() }
#[derive(Debug, Clone, Deserialize)]
pub struct GrpcConfig {
/// Address to listen on (default: 0.0.0.0:50051).
#[serde(default = "default_grpc_addr")]
pub listen_addr: String,
/// JWKS URL for JWT validation (default: Hydra's .well-known endpoint).
#[serde(default)]
pub jwks_url: Option<String>,
}
fn default_grpc_addr() -> String { "0.0.0.0:50051".into() }
impl Config {
pub fn load(path: &str) -> anyhow::Result<Self> {