use std::fs; use std::path::{Path, PathBuf}; use commands::{CommandManifestEntry, CommandRegistry, CommandSource}; use runtime::{BootstrapPhase, BootstrapPlan}; use tools::{ToolManifestEntry, ToolRegistry, ToolSource}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct UpstreamPaths { repo_root: PathBuf, } impl UpstreamPaths { #[must_use] pub fn from_repo_root(repo_root: impl Into) -> Self { Self { repo_root: repo_root.into(), } } #[must_use] pub fn from_workspace_dir(workspace_dir: impl AsRef) -> Self { let workspace_dir = workspace_dir .as_ref() .canonicalize() .unwrap_or_else(|_| workspace_dir.as_ref().to_path_buf()); let repo_root = workspace_dir .parent() .map_or_else(|| PathBuf::from(".."), Path::to_path_buf); Self { repo_root } } #[must_use] pub fn commands_path(&self) -> PathBuf { self.repo_root.join("src/commands.ts") } #[must_use] pub fn tools_path(&self) -> PathBuf { self.repo_root.join("src/tools.ts") } #[must_use] pub fn cli_path(&self) -> PathBuf { self.repo_root.join("src/entrypoints/cli.tsx") } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExtractedManifest { pub commands: CommandRegistry, pub tools: ToolRegistry, pub bootstrap: BootstrapPlan, } pub fn extract_manifest(paths: &UpstreamPaths) -> std::io::Result { let commands_source = fs::read_to_string(paths.commands_path())?; let tools_source = fs::read_to_string(paths.tools_path())?; let cli_source = fs::read_to_string(paths.cli_path())?; Ok(ExtractedManifest { commands: extract_commands(&commands_source), tools: extract_tools(&tools_source), bootstrap: extract_bootstrap_plan(&cli_source), }) } #[must_use] pub fn extract_commands(source: &str) -> CommandRegistry { let mut entries = Vec::new(); let mut in_internal_block = false; for raw_line in source.lines() { let line = raw_line.trim(); if line.starts_with("export const INTERNAL_ONLY_COMMANDS = [") { in_internal_block = true; continue; } if in_internal_block { if line.starts_with(']') { in_internal_block = false; continue; } if let Some(name) = first_identifier(line) { entries.push(CommandManifestEntry { name, source: CommandSource::InternalOnly, }); } continue; } if line.starts_with("import ") { for imported in imported_symbols(line) { entries.push(CommandManifestEntry { name: imported, source: CommandSource::Builtin, }); } } if line.contains("feature('") && line.contains("./commands/") { if let Some(name) = first_assignment_identifier(line) { entries.push(CommandManifestEntry { name, source: CommandSource::FeatureGated, }); } } } dedupe_commands(entries) } #[must_use] pub fn extract_tools(source: &str) -> ToolRegistry { let mut entries = Vec::new(); for raw_line in source.lines() { let line = raw_line.trim(); if line.starts_with("import ") && line.contains("./tools/") { for imported in imported_symbols(line) { if imported.ends_with("Tool") { entries.push(ToolManifestEntry { name: imported, source: ToolSource::Base, }); } } } if line.contains("feature('") && line.contains("Tool") { if let Some(name) = first_assignment_identifier(line) { if name.ends_with("Tool") || name.ends_with("Tools") { entries.push(ToolManifestEntry { name, source: ToolSource::Conditional, }); } } } } dedupe_tools(entries) } #[must_use] pub fn extract_bootstrap_plan(source: &str) -> BootstrapPlan { let mut phases = vec![BootstrapPhase::CliEntry]; if source.contains("--version") { phases.push(BootstrapPhase::FastPathVersion); } if source.contains("startupProfiler") { phases.push(BootstrapPhase::StartupProfiler); } if source.contains("--dump-system-prompt") { phases.push(BootstrapPhase::SystemPromptFastPath); } if source.contains("--claude-in-chrome-mcp") { phases.push(BootstrapPhase::ChromeMcpFastPath); } if source.contains("--daemon-worker") { phases.push(BootstrapPhase::DaemonWorkerFastPath); } if source.contains("remote-control") { phases.push(BootstrapPhase::BridgeFastPath); } if source.contains("args[0] === 'daemon'") { phases.push(BootstrapPhase::DaemonFastPath); } if source.contains("args[0] === 'ps'") || source.contains("args.includes('--bg')") { phases.push(BootstrapPhase::BackgroundSessionFastPath); } if source.contains("args[0] === 'new' || args[0] === 'list' || args[0] === 'reply'") { phases.push(BootstrapPhase::TemplateFastPath); } if source.contains("environment-runner") { phases.push(BootstrapPhase::EnvironmentRunnerFastPath); } phases.push(BootstrapPhase::MainRuntime); BootstrapPlan::from_phases(phases) } fn imported_symbols(line: &str) -> Vec { let Some(after_import) = line.strip_prefix("import ") else { return Vec::new(); }; let before_from = after_import .split(" from ") .next() .unwrap_or_default() .trim(); if before_from.starts_with('{') { return before_from .trim_matches(|c| c == '{' || c == '}') .split(',') .filter_map(|part| { let trimmed = part.trim(); if trimmed.is_empty() { return None; } Some(trimmed.split_whitespace().next()?.to_string()) }) .collect(); } let first = before_from.split(',').next().unwrap_or_default().trim(); if first.is_empty() { Vec::new() } else { vec![first.to_string()] } } fn first_assignment_identifier(line: &str) -> Option { let trimmed = line.trim_start(); let candidate = trimmed.split('=').next()?.trim(); first_identifier(candidate) } fn first_identifier(line: &str) -> Option { let mut out = String::new(); for ch in line.chars() { if ch.is_ascii_alphanumeric() || ch == '_' || ch == '-' { out.push(ch); } else if !out.is_empty() { break; } } (!out.is_empty()).then_some(out) } fn dedupe_commands(entries: Vec) -> CommandRegistry { let mut deduped = Vec::new(); for entry in entries { let exists = deduped.iter().any(|seen: &CommandManifestEntry| { seen.name == entry.name && seen.source == entry.source }); if !exists { deduped.push(entry); } } CommandRegistry::new(deduped) } fn dedupe_tools(entries: Vec) -> ToolRegistry { let mut deduped = Vec::new(); for entry in entries { let exists = deduped .iter() .any(|seen: &ToolManifestEntry| seen.name == entry.name && seen.source == entry.source); if !exists { deduped.push(entry); } } ToolRegistry::new(deduped) } #[cfg(test)] mod tests { use super::*; fn fixture_paths() -> UpstreamPaths { let workspace_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); UpstreamPaths::from_workspace_dir(workspace_dir) } #[test] fn extracts_non_empty_manifests_from_upstream_repo() { let manifest = extract_manifest(&fixture_paths()).expect("manifest should load"); assert!(!manifest.commands.entries().is_empty()); assert!(!manifest.tools.entries().is_empty()); assert!(!manifest.bootstrap.phases().is_empty()); } #[test] fn detects_known_upstream_command_symbols() { let commands = extract_commands( &fs::read_to_string(fixture_paths().commands_path()).expect("commands.ts"), ); let names: Vec<_> = commands .entries() .iter() .map(|entry| entry.name.as_str()) .collect(); assert!(names.contains(&"addDir")); assert!(names.contains(&"review")); assert!(!names.contains(&"INTERNAL_ONLY_COMMANDS")); } #[test] fn detects_known_upstream_tool_symbols() { let tools = extract_tools(&fs::read_to_string(fixture_paths().tools_path()).expect("tools.ts")); let names: Vec<_> = tools .entries() .iter() .map(|entry| entry.name.as_str()) .collect(); assert!(names.contains(&"AgentTool")); assert!(names.contains(&"BashTool")); } }