update readme

This commit is contained in:
2025-11-27 04:40:00 -05:00
parent f07973f86c
commit a9778d0f93
5 changed files with 30 additions and 78 deletions

View File

@@ -2,7 +2,7 @@
"metadata": { "metadata": {
"dependency_versions": { "dependency_versions": {
"python": "3.13", "python": "3.13",
"dspy": "3.0.4b1", "dspy": "3.0.4",
"cloudpickle": "3.1" "cloudpickle": "3.1"
} }
} }

View File

@@ -1,4 +1,4 @@
{ {
"AutoConfig": "src.index.CodexAgentConfig", "AutoConfig": "src.codex_dspy.agent.CodexAgentConfig",
"AutoAgent": "src.index.CodexAgent" "AutoAgent": "src.codex_dspy.agent.CodexModule"
} }

View File

@@ -1,6 +1,6 @@
from src.index import CodexAgent, CodexAgentConfig from src.codex_dspy.agent import CodexModule, CodexAgentConfig
codex_agent = CodexAgent(CodexAgentConfig()) codex_agent = CodexModule(CodexAgentConfig())
def main(): def main():

View File

@@ -12,7 +12,7 @@ from pydantic import BaseModel
import dspy import dspy
from dspy.primitives.prediction import Prediction from dspy.primitives.prediction import Prediction
from dspy.signatures.signature import Signature, ensure_signature from dspy.signatures.signature import Signature, ensure_signature
from modaic import PrecompiledAgent, PrecompiledConfig
from ..codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions from ..codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
@@ -38,7 +38,18 @@ def _is_str_type(annotation: Any) -> bool:
return False return False
class CodexModule(dspy.Module): class CodexAgentConfig(PrecompiledConfig):
signature: str | type[Signature] = "message:str -> answer:str"
working_directory: str = "."
model: Optional[str] = "gpt-4o"
sandbox_mode: Optional[SandboxMode] = None
skip_git_repo_check: bool = False
api_key: Optional[str] = None
base_url: Optional[str] = None
codex_path_override: Optional[str] = "/opt/homebrew/bin/codex"
class CodexModule(PrecompiledAgent):
"""DSPy module for Codex SDK integration. """DSPy module for Codex SDK integration.
Creates a stateful agent where each instance maintains one conversation thread. Creates a stateful agent where each instance maintains one conversation thread.
@@ -72,21 +83,13 @@ class CodexModule(dspy.Module):
>>> print(result.report.severity) # typed access >>> print(result.report.severity) # typed access
""" """
def __init__( config: CodexAgentConfig
self,
signature: str | type[Signature], def __init__(self, config: CodexAgentConfig, **kwargs):
working_directory: str, super().__init__(config, **kwargs)
model: Optional[str] = None,
sandbox_mode: Optional[SandboxMode] = None,
skip_git_repo_check: bool = False,
api_key: Optional[str] = None,
base_url: Optional[str] = None,
codex_path_override: Optional[str] = None,
):
super().__init__()
# Ensure signature is valid # Ensure signature is valid
self.signature = ensure_signature(signature) self.signature = ensure_signature(config.signature)
# Validate: exactly 1 input field, 1 output field # Validate: exactly 1 input field, 1 output field
if len(self.signature.input_fields) != 1: if len(self.signature.input_fields) != 1:
@@ -112,19 +115,19 @@ class CodexModule(dspy.Module):
# Create Codex client # Create Codex client
self.client = Codex( self.client = Codex(
options=CodexOptions( options=CodexOptions(
api_key=api_key, api_key=config.api_key,
base_url=base_url, base_url=config.base_url,
codex_path_override=codex_path_override, codex_path_override=config.codex_path_override,
) )
) )
# Start thread (1 agent instance = 1 stateful thread) # Start thread (1 agent instance = 1 stateful thread)
self.thread = self.client.start_thread( self.thread = self.client.start_thread(
options=ThreadOptions( options=ThreadOptions(
working_directory=working_directory, working_directory=config.working_directory,
model=model, model=config.model,
sandbox_mode=sandbox_mode, sandbox_mode=config.sandbox_mode,
skip_git_repo_check=skip_git_repo_check, skip_git_repo_check=config.skip_git_repo_check,
) )
) )

View File

@@ -1,51 +0,0 @@
import dspy
from modaic import PrecompiledAgent, PrecompiledConfig
from .codex_dspy import CodexModule
from .codex import Codex, CodexOptions, SandboxMode, ThreadOptions, TurnOptions
from dspy.signatures.signature import Signature
from dspy.primitives.prediction import Prediction
from typing import Optional
class CodexAgentConfig(PrecompiledConfig):
signature: str | type[Signature] = "message:str -> answer:str"
working_directory: str = "."
model: Optional[str] = "gpt-4o"
sandbox_mode: Optional[SandboxMode] = None
skip_git_repo_check: bool = False
api_key: Optional[str] = None
base_url: Optional[str] = None
codex_path_override: Optional[str] = "/opt/homebrew/bin/codex"
class CodexAgent(PrecompiledAgent):
config: CodexAgentConfig
def __init__(self, config: CodexAgentConfig, **kwargs):
super().__init__(config, **kwargs)
self.codex_module = CodexModule(
signature=config.signature,
working_directory=config.working_directory,
model=config.model,
sandbox_mode=config.sandbox_mode,
skip_git_repo_check=config.skip_git_repo_check,
api_key=config.api_key,
base_url=config.base_url,
codex_path_override=config.codex_path_override,
)
def forward(self, **kwargs) -> Prediction:
return self.codex_module(**kwargs)
@property
def thread_id(self) -> Optional[str]:
"""Get thread ID for this agent instance.
The thread ID is assigned after the first forward() call.
Useful for debugging and visibility into the conversation state.
Returns:
Thread ID string, or None if no forward() calls have been made yet
"""
return self.codex_module.thread.id