use std::path::PathBuf; use anyhow::Result; use forge_app::dto::ToolsOverview; use forge_app::{User, UserUsage}; use forge_domain::{AgentId, Effort, ModelId, ProviderModels}; use forge_stream::MpscStream; use futures::stream::BoxStream; use url::Url; use crate::*; #[async_trait::async_trait] pub trait API: Sync + Send { /// Provides a list of files in the current working directory for auto /// completion async fn discover(&self) -> Result>; /// Provides information about the tools available in the current /// environment async fn get_tools(&self) -> anyhow::Result; /// Provides a list of models available in the current environment async fn get_models(&self) -> Result>; /// Provides models from all configured providers. Providers that /// successfully return models are included in the result. If every /// configured provider fails (e.g. due to an invalid API key), the /// first error is returned so the caller sees the real underlying cause /// rather than an empty list. async fn get_all_provider_models(&self) -> Result>; /// Provides a list of agents available in the current environment async fn get_agents(&self) -> Result>; /// Provides lightweight metadata for all agents without requiring a /// configured provider or model async fn get_agent_infos(&self) -> Result>; /// Provides a list of providers available in the current environment async fn get_providers(&self) -> Result>; /// Gets a provider by ID async fn get_provider(&self, id: &ProviderId) -> Result; /// Executes a chat request and returns a stream of responses async fn chat(&self, chat: ChatRequest) -> Result>>; /// Commits changes with an AI-generated commit message async fn commit( &self, preview: bool, max_diff_size: Option, diff: Option, additional_context: Option, ) -> Result; /// Returns the current environment fn environment(&self) -> Environment; /// Adds a new conversation to the conversation store async fn upsert_conversation(&self, conversation: Conversation) -> Result<()>; /// Returns the conversation with the given ID async fn conversation(&self, conversation_id: &ConversationId) -> Result>; /// Lists all conversations for the active workspace async fn get_conversations(&self, limit: Option) -> Result>; /// Finds the last active conversation for the current workspace async fn last_conversation(&self) -> Result>; /// Permanently deletes a conversation /// /// # Arguments /// * `conversation_id` - The ID of the conversation to delete /// /// # Errors /// Returns an error if the operation fails async fn delete_conversation(&self, conversation_id: &ConversationId) -> Result<()>; /// Renames a conversation by setting its title /// /// # Arguments /// * `conversation_id` - The ID of the conversation to rename /// * `title` - The new title for the conversation /// /// # Errors /// Returns an error if the conversation is not found or the operation fails async fn rename_conversation( &self, conversation_id: &ConversationId, title: String, ) -> Result<()>; /// Compacts the context of the main agent for the given conversation and /// persists it. Returns metrics about the compaction (original vs. /// compacted tokens and messages). async fn compact_conversation( &self, conversation_id: &ConversationId, ) -> Result; /// Executes a shell command using the shell tool infrastructure async fn execute_shell_command( &self, command: &str, working_dir: PathBuf, ) -> Result; /// Executes the shell command on present stdio. async fn execute_shell_command_raw(&self, command: &str) -> Result; /// Reads and merges MCP configurations from all available configuration /// files This combines both user-level and local configurations with /// local taking precedence. If scope is provided, only loads from that /// specific scope. async fn read_mcp_config(&self, scope: Option<&Scope>) -> Result; /// Writes the provided MCP configuration to disk at the specified scope /// The scope determines whether the configuration is written to user-level /// or local configuration User-level configuration is stored in the /// user's home directory Local configuration is stored in the current /// project directory async fn write_mcp_config(&self, scope: &Scope, config: &McpConfig) -> Result<()>; /// Retrieves the provider configuration for the specified agent async fn get_agent_provider(&self, agent_id: AgentId) -> anyhow::Result>; /// Gets the current session configuration (provider and model pair). /// /// Returns `None` when no session has been configured yet, allowing callers /// to distinguish between "not configured" and an actual error. async fn get_session_config(&self) -> Option; /// Retrieves the provider configuration for the default agent. /// /// Delegates to [`Self::get_session_config`] and resolves the provider. async fn get_default_provider(&self) -> anyhow::Result>; /// Applies one or more configuration mutations atomically. /// /// Each operation in `ops` is applied in order and persisted as a single /// atomic write. Use [`forge_domain::ConfigOperation`] variants to describe /// each mutation. Provider and model changes also invalidate the agent /// cache so the next request picks up the updated configuration. async fn update_config(&self, ops: Vec) -> anyhow::Result<()>; /// Retrieves information about the currently authenticated user async fn user_info(&self) -> anyhow::Result>; /// Retrieves usage statistics for the currently authenticated user async fn user_usage(&self) -> anyhow::Result>; /// Gets the currently operating agent async fn get_active_agent(&self) -> Option; /// Sets the active agent async fn set_active_agent(&self, agent_id: AgentId) -> anyhow::Result<()>; /// Gets the model for the specified agent async fn get_agent_model(&self, agent_id: AgentId) -> Option; /// Gets the commit configuration (provider and model for commit message /// generation). async fn get_commit_config(&self) -> anyhow::Result>; /// Gets the suggest configuration (provider and model for command /// suggestion generation). async fn get_suggest_config(&self) -> anyhow::Result>; /// Gets the current reasoning effort setting. async fn get_reasoning_effort(&self) -> anyhow::Result>; /// Refresh MCP caches by fetching fresh data async fn reload_mcp(&self) -> Result<()>; /// Applies the interactive trust gate for any project-local MCP config. /// Servers are NOT connected here — connections remain lazy and happen on /// first tool use. Must be called once at startup. async fn init_mcp(&self) -> Result<()>; /// List of commands defined in .md file(s) async fn get_commands(&self) -> Result>; /// List of available skills async fn get_skills(&self) -> Result>; /// Generate a shell command from natural language prompt async fn generate_command(&self, prompt: UserPrompt) -> Result; /// Initiate provider auth flow async fn init_provider_auth( &self, provider_id: ProviderId, method: AuthMethod, ) -> Result; /// Complete provider authentication and save credentials async fn complete_provider_auth( &self, provider_id: ProviderId, context: AuthContextResponse, timeout: std::time::Duration, ) -> Result<()>; /// Remove provider credentials (logout) async fn remove_provider(&self, provider_id: &ProviderId) -> Result<()>; /// Sync a workspace directory for semantic search async fn sync_workspace( &self, path: PathBuf, ) -> Result>>; /// Query the indexed workspace async fn query_workspace( &self, path: PathBuf, params: forge_domain::SearchParams<'_>, ) -> Result>; /// List all workspaces async fn list_workspaces(&self) -> Result>; /// Get workspace information for a specific path async fn get_workspace_info( &self, path: PathBuf, ) -> Result>; /// Delete one or more workspaces in parallel async fn delete_workspaces(&self, workspace_ids: Vec) -> Result<()>; /// Get sync status for all files in workspace async fn get_workspace_status(&self, path: PathBuf) -> Result>; /// Hydrates the gRPC channel fn hydrate_channel(&self) -> Result<()>; /// Check if authentication credentials exist async fn is_authenticated(&self) -> Result; /// Create new authentication credentials async fn create_auth_credentials(&self) -> Result; /// Initialize a new empty workspace async fn init_workspace(&self, path: PathBuf) -> Result; /// Migrate environment variable-based credentials to file-based /// credentials. This is a one-time migration that runs only if the /// credentials file doesn't exist. async fn migrate_env_credentials(&self) -> Result>; async fn generate_data( &self, data_parameters: DataGenerationParameters, ) -> Result>>; /// Authenticate with an MCP server via OAuth flow async fn mcp_auth(&self, server_url: &str) -> Result<()>; /// Remove stored OAuth credentials for an MCP server (or all servers) async fn mcp_logout(&self, server_url: Option<&str>) -> Result<()>; /// Check the OAuth authentication status of an MCP server async fn mcp_auth_status(&self, server_url: &str) -> Result; }