mirror of
https://github.com/openai/codex.git
synced 2026-11-07 00:33:29 +00:00
extension: add initial typed extension API (#21736)
## Why `codex-core` still owns a growing amount of product-specific behavior. This PR starts the extraction path by introducing a small, typed first-party extension seam: features can install the contribution families they actually own, while the host keeps lifecycle and state ownership instead of pushing a broad service locator into the API. See the `examples/` for illustration ## Known limitations * Tool contract definition will be shared with core * Fragments must be extracted * Missing some contributors
This commit is contained in:
1 parent
2abdeb34d5
commit
d2c3ebac1f
14 files changed
+648
No files matched your search
@@ -0,0 +1,50 @@
|
||||
// All this file should be replaced by the existing fragment implementation ofc
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PromptSlot {
|
||||
DeveloperPolicy,
|
||||
DeveloperCapabilities,
|
||||
ContextualUser,
|
||||
SeparateDeveloper,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PromptFragment {
|
||||
slot: PromptSlot,
|
||||
text: String,
|
||||
}
|
||||
|
||||
impl PromptFragment {
|
||||
/// Creates a prompt fragment for the given slot.
|
||||
pub fn new(slot: PromptSlot, text: impl Into<String>) -> Self {
|
||||
Self {
|
||||
slot,
|
||||
text: text.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a developer-policy prompt fragment.
|
||||
pub fn developer_policy(text: impl Into<String>) -> Self {
|
||||
Self::new(PromptSlot::DeveloperPolicy, text)
|
||||
}
|
||||
|
||||
/// Creates a developer-capabilities prompt fragment.
|
||||
pub fn developer_capability(text: impl Into<String>) -> Self {
|
||||
Self::new(PromptSlot::DeveloperCapabilities, text)
|
||||
}
|
||||
|
||||
/// Creates a separate top-level developer prompt fragment.
|
||||
pub fn separate_developer(text: impl Into<String>) -> Self {
|
||||
Self::new(PromptSlot::SeparateDeveloper, text)
|
||||
}
|
||||
|
||||
/// Returns the target prompt slot.
|
||||
pub fn slot(&self) -> PromptSlot {
|
||||
self.slot
|
||||
}
|
||||
|
||||
/// Returns the model-visible text.
|
||||
pub fn text(&self) -> &str {
|
||||
&self.text
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use codex_tools::ResponsesApiTool;
|
||||
use serde_json::Value;
|
||||
use thiserror::Error;
|
||||
|
||||
// TMP while we don't have the fully extracted tools
|
||||
#[derive(Clone)]
|
||||
pub struct ToolContribution {
|
||||
spec: ResponsesApiTool,
|
||||
handler: Arc<dyn ToolHandler>,
|
||||
supports_parallel_tool_calls: bool,
|
||||
}
|
||||
|
||||
impl ToolContribution {
|
||||
pub fn new(spec: ResponsesApiTool, handler: Arc<dyn ToolHandler>) -> Self {
|
||||
Self {
|
||||
spec,
|
||||
handler,
|
||||
supports_parallel_tool_calls: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn allow_parallel_calls(mut self) -> Self {
|
||||
self.supports_parallel_tool_calls = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn spec(&self) -> &ResponsesApiTool {
|
||||
&self.spec
|
||||
}
|
||||
|
||||
pub fn supports_parallel_tool_calls(&self) -> bool {
|
||||
self.supports_parallel_tool_calls
|
||||
}
|
||||
|
||||
pub fn handler(&self) -> Arc<dyn ToolHandler> {
|
||||
Arc::clone(&self.handler)
|
||||
}
|
||||
}
|
||||
|
||||
//////// Just to make it compile ////////////////////////////////
|
||||
pub trait ToolHandler: Send + Sync {
|
||||
/// Handles one JSON-encoded invocation for this tool.
|
||||
fn handle<'a>(
|
||||
&'a self,
|
||||
arguments: Value,
|
||||
) -> Pin<Box<dyn Future<Output = Result<Value, ToolCallError>> + Send + 'a>>;
|
||||
}
|
||||
|
||||
/// Error returned by a contributed native tool handler.
|
||||
#[derive(Clone, Debug, Error, PartialEq, Eq)]
|
||||
#[error("{message}")]
|
||||
pub struct ToolCallError {
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl ToolCallError {
|
||||
/// Creates a contributed-tool error with the supplied model-visible text.
|
||||
pub fn new(message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user