use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use codex_context_fragments::ContextualUserFragment;
use codex_protocol::items::TurnItem;
use codex_protocol::protocol::ReviewDecision;
use codex_protocol::protocol::TokenUsageInfo;
use codex_tools::ToolCall;
use codex_tools::ToolExecutor;
use crate::ExtensionData;
mod context;
mod mcp;
mod prompt;
mod skill_invocation;
mod thread_lifecycle;
mod tool_lifecycle;
mod turn_input;
mod turn_lifecycle;
mod world_state;
pub use context::TurnContextContributionInput;
pub use mcp::McpServerContribution;
pub use mcp::McpServerContributionContext;
pub use prompt::PromptFragment;
pub use prompt::PromptSlot;
pub use skill_invocation::SkillInvocationInput;
pub use skill_invocation::SkillInvocationKind;
pub use thread_lifecycle::ThreadIdleInput;
pub use thread_lifecycle::ThreadOriginator;
pub use thread_lifecycle::ThreadResumeInput;
pub use thread_lifecycle::ThreadStartInput;
pub use thread_lifecycle::ThreadStopInput;
pub use tool_lifecycle::ToolCallOutcome;
pub use tool_lifecycle::ToolCallSource;
pub use tool_lifecycle::ToolFinishInput;
pub use tool_lifecycle::ToolLifecycleFuture;
pub use tool_lifecycle::ToolStartInput;
pub use turn_input::TurnInputContext;
pub use turn_input::TurnInputEnvironment;
pub use turn_lifecycle::TurnAbortInput;
pub use turn_lifecycle::TurnErrorInput;
pub use turn_lifecycle::TurnStartInput;
pub use turn_lifecycle::TurnStopInput;
pub use world_state::PreviousWorldStateSection;
pub use world_state::RenderedWorldStateFragment;
pub use world_state::WorldStateContributionInput;
pub use world_state::WorldStateSectionContribution;
pub type ExtensionFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub trait McpServerContributor<C: Sync>: Send + Sync {
fn id(&self) -> &'static str;
fn contribute<'a>(
&'a self,
context: McpServerContributionContext<'a, C>,
) -> ExtensionFuture<'a, Vec<McpServerContribution>>;
}
pub trait ContextContributor: Send + Sync {
fn contribute_thread_context<'a>(
&'a self,
session_store: &'a ExtensionData,
thread_store: &'a ExtensionData,
step_store: &'a ExtensionData,
) -> ExtensionFuture<'a, Vec<PromptFragment>> {
Box::pin(async move {
let _self = self;
let _session_store = session_store;
let _thread_store = thread_store;
let _step_store = step_store;
Vec::new()
})
}
fn contribute_turn_context<'a>(
&'a self,
input: TurnContextContributionInput<'a>,
) -> ExtensionFuture<'a, Vec<PromptFragment>> {
Box::pin(async move {
let _self = self;
let _input = input;
Vec::new()
})
}
fn contribute_world_state<'a>(
&'a self,
input: WorldStateContributionInput<'a>,
) -> ExtensionFuture<'a, Vec<WorldStateSectionContribution>> {
Box::pin(async move {
let _self = self;
let _input = input;
Vec::new()
})
}
}
pub trait ThreadLifecycleContributor<C: Sync>: Send + Sync {
fn on_thread_start<'a>(&'a self, input: ThreadStartInput<'a, C>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_thread_resume<'a>(&'a self, input: ThreadResumeInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_thread_idle<'a>(&'a self, input: ThreadIdleInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_thread_stop<'a>(&'a self, input: ThreadStopInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
}
pub trait TurnLifecycleContributor: Send + Sync {
fn on_turn_start<'a>(&'a self, input: TurnStartInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_turn_stop<'a>(&'a self, input: TurnStopInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_turn_abort<'a>(&'a self, input: TurnAbortInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
fn on_turn_error<'a>(&'a self, input: TurnErrorInput<'a>) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = input;
})
}
}
pub trait TurnInputContributor: Send + Sync {
fn contribute<'a>(
&'a self,
input: TurnInputContext,
session_store: &'a ExtensionData,
thread_store: &'a ExtensionData,
turn_store: &'a ExtensionData,
step_store: &'a ExtensionData,
) -> ExtensionFuture<'a, Vec<Box<dyn ContextualUserFragment + Send>>>;
}
pub trait ConfigContributor<C>: Send + Sync {
fn on_config_changed(
&self,
_session_store: &ExtensionData,
_thread_store: &ExtensionData,
_previous_config: &C,
_new_config: &C,
) {
}
}
pub trait TokenUsageContributor: Send + Sync {
fn on_token_usage<'a>(
&'a self,
_session_store: &'a ExtensionData,
_thread_store: &'a ExtensionData,
_turn_store: &'a ExtensionData,
_token_usage: &'a TokenUsageInfo,
) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _inputs = (_session_store, _thread_store, _turn_store, _token_usage);
})
}
}
pub trait SkillInvocationContributor: Send + Sync {
fn on_skill_invocation<'a>(
&'a self,
_input: SkillInvocationInput<'a>,
) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let _self = self;
let _input = _input;
})
}
}
pub trait ToolContributor: Send + Sync {
fn tools(
&self,
session_store: &ExtensionData,
thread_store: &ExtensionData,
step_store: &ExtensionData,
) -> Vec<Arc<dyn ToolExecutor<ToolCall>>>;
}
pub trait ToolLifecycleContributor: Send + Sync {
fn on_tool_start<'a>(&'a self, _input: ToolStartInput<'a>) -> ToolLifecycleFuture<'a> {
Box::pin(std::future::ready(()))
}
fn on_tool_finish<'a>(&'a self, _input: ToolFinishInput<'a>) -> ToolLifecycleFuture<'a> {
Box::pin(std::future::ready(()))
}
}
pub trait ApprovalReviewContributor: Send + Sync {
fn contribute<'a>(
&'a self,
session_store: &'a ExtensionData,
thread_store: &'a ExtensionData,
prompt: &'a str,
) -> ExtensionFuture<'a, Option<ReviewDecision>>;
}
pub trait TurnItemContributor: Send + Sync {
fn contribute<'a>(
&'a self,
thread_store: &'a ExtensionData,
turn_store: &'a ExtensionData,
item: &'a mut TurnItem,
) -> ExtensionFuture<'a, Result<(), String>>;
}