codexapi 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.1
2
+ Name: codexapi
3
+ Version: 0.1.3
4
+ Summary: Minimal Python API for running the Codex CLI.
5
+ License: MIT
6
+ Keywords: codex,agent,cli,openai
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+
13
+ # CodexAPI
14
+
15
+ Use OpenAI's codex from python as easily as calling a function with your codex credits instead of the API.
16
+
17
+ *Note: this project is not affiliated with OpenAI in any way. Thanks for the awesome tools and models though!*
18
+
19
+ ## Requirements
20
+
21
+ - Codex CLI installed and authenticated (`codex` must be on your PATH).
22
+ - Python 3.8+.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install codexapi
28
+ ```
29
+
30
+ ## Quickstart
31
+
32
+ ```python
33
+ from codexapi import agent, Agent, Task
34
+
35
+ # Run one-shot tasks as a function call
36
+ print(agent("Say hello"))
37
+
38
+ # Run a multi-turn conversation as a session
39
+ session = Agent(cwd="/path/to/project")
40
+ print(session("Summarize this repo."))
41
+ print(session("Now list any risks."))
42
+
43
+ # Save and resume a session later
44
+ thread_id = session.thread_id
45
+ session2 = Agent(cwd="/path/to/project", thread_id=thread_id)
46
+ print(session2("Continue from where we left off."))
47
+
48
+ # Define a task with a checker
49
+ class RepoTask(Task):
50
+ def check(self):
51
+ # Return an error string if something is wrong, or None/"" if OK
52
+ return None
53
+
54
+ task = RepoTask("Summarize this repo.", cwd="/path/to/project")
55
+ result = task()
56
+ print(result.success, result.summary)
57
+ ```
58
+
59
+ ## API
60
+
61
+ ### `agent(prompt, cwd=None, yolo=False, flags=None, full_auto=False) -> str`
62
+
63
+ Runs a single Codex turn and returns only the agent's message. Any reasoning
64
+ items are filtered out.
65
+
66
+ - `prompt` (str): prompt to send to Codex.
67
+ - `cwd` (str | PathLike | None): working directory for the Codex session.
68
+ - `yolo` (bool): pass `--yolo` to Codex when true.
69
+ - `flags` (str | None): extra CLI flags to pass to Codex.
70
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
71
+
72
+ ### `Agent(cwd=None, yolo=False, thread_id=None, flags=None, full_auto=False)`
73
+
74
+ Creates a stateful session wrapper. Calling the instance sends the prompt into
75
+ the same conversation and returns only the agent's message.
76
+
77
+ - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
78
+ - `thread_id -> str | None`: expose the underlying session id once created.
79
+ - `yolo` (bool): pass `--yolo` to Codex when true.
80
+ - `flags` (str | None): extra CLI flags to pass to Codex.
81
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
82
+
83
+ ### `Task(prompt, max_attempts=10, cwd=None, yolo=False, thread_id=None, flags=None, full_auto=True)`
84
+
85
+ Runs a Codex task with checker-driven retries. Subclass it and implement
86
+ `check()` to return an error string when the task is incomplete, or return
87
+ `None`/`""` when the task passes.
88
+
89
+ - `__call__() -> TaskResult`: run the task.
90
+ - `set_up()`: optional setup hook.
91
+ - `tear_down()`: optional cleanup hook.
92
+ - `check() -> str | None`: return an error description or `None`/`""`.
93
+ - `on_success(result)`: optional success hook.
94
+ - `on_failure(result)`: optional failure hook.
95
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
96
+
97
+ ### `TaskResult(success, summary, attempts, errors, thread_id)`
98
+
99
+ Simple result object returned by `Task.__call__`.
100
+
101
+ - `success` (bool): whether the task completed successfully.
102
+ - `summary` (str): agent summary of what happened.
103
+ - `attempts` (int): how many attempts were used.
104
+ - `errors` (str | None): last checker error, if any.
105
+ - `thread_id` (str | None): Codex thread id for the session.
106
+
107
+ ## Behavior notes
108
+
109
+ - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
110
+ - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
111
+ - Passes `--yolo` when enabled (use with care).
112
+ - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
113
+
114
+ ## Configuration
115
+
116
+ Set `CODEX_BIN` to point at a non-default Codex binary:
117
+
118
+ ```bash
119
+ export CODEX_BIN=/path/to/codex
120
+ ```
@@ -0,0 +1,108 @@
1
+ # CodexAPI
2
+
3
+ Use OpenAI's codex from python as easily as calling a function with your codex credits instead of the API.
4
+
5
+ *Note: this project is not affiliated with OpenAI in any way. Thanks for the awesome tools and models though!*
6
+
7
+ ## Requirements
8
+
9
+ - Codex CLI installed and authenticated (`codex` must be on your PATH).
10
+ - Python 3.8+.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install codexapi
16
+ ```
17
+
18
+ ## Quickstart
19
+
20
+ ```python
21
+ from codexapi import agent, Agent, Task
22
+
23
+ # Run one-shot tasks as a function call
24
+ print(agent("Say hello"))
25
+
26
+ # Run a multi-turn conversation as a session
27
+ session = Agent(cwd="/path/to/project")
28
+ print(session("Summarize this repo."))
29
+ print(session("Now list any risks."))
30
+
31
+ # Save and resume a session later
32
+ thread_id = session.thread_id
33
+ session2 = Agent(cwd="/path/to/project", thread_id=thread_id)
34
+ print(session2("Continue from where we left off."))
35
+
36
+ # Define a task with a checker
37
+ class RepoTask(Task):
38
+ def check(self):
39
+ # Return an error string if something is wrong, or None/"" if OK
40
+ return None
41
+
42
+ task = RepoTask("Summarize this repo.", cwd="/path/to/project")
43
+ result = task()
44
+ print(result.success, result.summary)
45
+ ```
46
+
47
+ ## API
48
+
49
+ ### `agent(prompt, cwd=None, yolo=False, flags=None, full_auto=False) -> str`
50
+
51
+ Runs a single Codex turn and returns only the agent's message. Any reasoning
52
+ items are filtered out.
53
+
54
+ - `prompt` (str): prompt to send to Codex.
55
+ - `cwd` (str | PathLike | None): working directory for the Codex session.
56
+ - `yolo` (bool): pass `--yolo` to Codex when true.
57
+ - `flags` (str | None): extra CLI flags to pass to Codex.
58
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
59
+
60
+ ### `Agent(cwd=None, yolo=False, thread_id=None, flags=None, full_auto=False)`
61
+
62
+ Creates a stateful session wrapper. Calling the instance sends the prompt into
63
+ the same conversation and returns only the agent's message.
64
+
65
+ - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
66
+ - `thread_id -> str | None`: expose the underlying session id once created.
67
+ - `yolo` (bool): pass `--yolo` to Codex when true.
68
+ - `flags` (str | None): extra CLI flags to pass to Codex.
69
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
70
+
71
+ ### `Task(prompt, max_attempts=10, cwd=None, yolo=False, thread_id=None, flags=None, full_auto=True)`
72
+
73
+ Runs a Codex task with checker-driven retries. Subclass it and implement
74
+ `check()` to return an error string when the task is incomplete, or return
75
+ `None`/`""` when the task passes.
76
+
77
+ - `__call__() -> TaskResult`: run the task.
78
+ - `set_up()`: optional setup hook.
79
+ - `tear_down()`: optional cleanup hook.
80
+ - `check() -> str | None`: return an error description or `None`/`""`.
81
+ - `on_success(result)`: optional success hook.
82
+ - `on_failure(result)`: optional failure hook.
83
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
84
+
85
+ ### `TaskResult(success, summary, attempts, errors, thread_id)`
86
+
87
+ Simple result object returned by `Task.__call__`.
88
+
89
+ - `success` (bool): whether the task completed successfully.
90
+ - `summary` (str): agent summary of what happened.
91
+ - `attempts` (int): how many attempts were used.
92
+ - `errors` (str | None): last checker error, if any.
93
+ - `thread_id` (str | None): Codex thread id for the session.
94
+
95
+ ## Behavior notes
96
+
97
+ - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
98
+ - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
99
+ - Passes `--yolo` when enabled (use with care).
100
+ - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
101
+
102
+ ## Configuration
103
+
104
+ Set `CODEX_BIN` to point at a non-default Codex binary:
105
+
106
+ ```bash
107
+ export CODEX_BIN=/path/to/codex
108
+ ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codexapi"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  description = "Minimal Python API for running the Codex CLI."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -0,0 +1,7 @@
1
+ """Minimal Python API for running the Codex CLI."""
2
+
3
+ from .agent import Agent, agent
4
+ from .task import Task, TaskResult
5
+
6
+ __all__ = ["Agent", "Task", "TaskResult", "agent"]
7
+ __version__ = "0.1.2"
@@ -1,41 +1,32 @@
1
1
  """Codex CLI wrapper used by the codexapi public interface."""
2
2
 
3
- from __future__ import annotations
4
-
5
3
  import json
6
4
  import os
5
+ import shlex
7
6
  import subprocess
8
- from typing import Optional, Tuple, Union
9
-
10
- Pathish = Union[str, os.PathLike]
11
7
 
12
8
  _CODEX_BIN = os.environ.get("CODEX_BIN", "codex")
13
9
 
14
10
 
15
- def agent(
16
- prompt: str,
17
- cwd: Optional[Pathish] = None,
18
- *,
19
- yolo: bool = False,
20
- agent: str = "codex",
21
- ) -> str:
11
+ def agent(prompt, cwd=None, yolo=False, flags=None, full_auto=False):
22
12
  """Run a single Codex turn and return only the agent's message.
23
13
 
24
14
  Args:
25
15
  prompt: The user prompt to send to Codex.
26
16
  cwd: Optional working directory for the Codex session.
27
17
  yolo: Whether to pass --yolo to Codex.
28
- agent: Agent backend to use (only "codex" is supported).
18
+ flags: Additional raw CLI flags to pass to Codex.
29
19
 
30
20
  Returns:
31
21
  The agent's visible response text with reasoning traces removed.
32
22
  """
33
- _require_codex_agent(agent)
34
23
  message, _thread_id = _run_codex(
35
- prompt=prompt,
36
- cwd=cwd,
24
+ prompt,
25
+ cwd,
37
26
  thread_id=None,
38
27
  yolo=yolo,
28
+ flags=flags,
29
+ full_auto=full_auto,
39
30
  )
40
31
  return message
41
32
 
@@ -51,12 +42,12 @@ class Agent:
51
42
 
52
43
  def __init__(
53
44
  self,
54
- cwd: Optional[Pathish] = None,
55
- *,
56
- yolo: bool = False,
57
- agent: str = "codex",
58
- trace_id: Optional[str] = None,
59
- ) -> None:
45
+ cwd=None,
46
+ yolo=False,
47
+ thread_id=None,
48
+ flags=None,
49
+ full_auto=False,
50
+ ):
60
51
  """Create a new session wrapper.
61
52
 
62
53
  Args:
@@ -64,39 +55,32 @@ class Agent:
64
55
  yolo: Whether to pass --yolo to Codex.
65
56
  agent: Agent backend to use (only "codex" is supported).
66
57
  trace_id: Optional Codex thread id to resume from the first call.
58
+ flags: Additional raw CLI flags to pass to Codex.
67
59
  """
68
- _require_codex_agent(agent)
69
- self._cwd = cwd
60
+ self.cwd = cwd
70
61
  self._yolo = yolo
71
- self._thread_id: Optional[str] = trace_id
62
+ self._flags = flags
63
+ self._full_auto = full_auto
64
+ self.thread_id = thread_id
72
65
 
73
- def __call__(self, prompt: str) -> str:
66
+ def __call__(self, prompt):
74
67
  """Send a prompt to Codex and return only the agent's message."""
75
68
  message, thread_id = _run_codex(
76
- prompt=prompt,
77
- cwd=self._cwd,
78
- thread_id=self._thread_id,
79
- yolo=self._yolo,
69
+ prompt,
70
+ self.cwd,
71
+ self.thread_id,
72
+ self._yolo,
73
+ self._flags,
74
+ self._full_auto,
80
75
  )
81
76
  if thread_id:
82
- self._thread_id = thread_id
77
+ self.thread_id = thread_id
83
78
  return message
84
79
 
85
- @property
86
- def thread_id(self) -> Optional[str]:
87
- """Return the current Codex session id, if any."""
88
- return self._thread_id
89
80
 
90
-
91
- def _run_codex(
92
- *,
93
- prompt: str,
94
- cwd: Optional[Pathish],
95
- thread_id: Optional[str],
96
- yolo: bool,
97
- ) -> Tuple[str, Optional[str]]:
81
+ def _run_codex(prompt, cwd, thread_id, yolo, flags, full_auto):
98
82
  """Invoke the Codex CLI and return the message plus thread id (if any)."""
99
- cmd = [
83
+ command = [
100
84
  _CODEX_BIN,
101
85
  "exec",
102
86
  "--json",
@@ -105,20 +89,24 @@ def _run_codex(
105
89
  "--skip-git-repo-check",
106
90
  ]
107
91
  if yolo:
108
- cmd.append("--yolo")
109
- if cwd is not None:
110
- cmd.extend(["--cd", os.fspath(cwd)])
92
+ command.append("--yolo")
93
+ if full_auto:
94
+ command.append("--full-auto")
95
+ if flags:
96
+ command.extend(shlex.split(flags))
97
+ if cwd:
98
+ command.extend(["--cd", os.fspath(cwd)])
111
99
  if thread_id:
112
- cmd.extend(["resume", thread_id, "-"])
100
+ command.extend(["resume", thread_id, "-"])
113
101
  else:
114
- cmd.append("-")
102
+ command.append("-")
115
103
 
116
104
  result = subprocess.run(
117
- cmd,
105
+ command,
118
106
  input=prompt,
119
107
  text=True,
120
108
  capture_output=True,
121
- cwd=os.fspath(cwd) if cwd is not None else None,
109
+ cwd=os.fspath(cwd) if cwd else None,
122
110
  )
123
111
  if result.returncode != 0:
124
112
  stderr = result.stderr.strip()
@@ -130,16 +118,11 @@ def _run_codex(
130
118
  return _parse_jsonl(result.stdout)
131
119
 
132
120
 
133
- def _require_codex_agent(agent_name: str) -> None:
134
- if agent_name != "codex":
135
- raise ValueError('Only agent="codex" is supported right now.')
136
-
137
-
138
- def _parse_jsonl(output: str) -> Tuple[str, Optional[str]]:
121
+ def _parse_jsonl(output):
139
122
  """Extract agent messages and the latest thread id from Codex JSONL output."""
140
- thread_id: Optional[str] = None
141
- messages: list[str] = []
142
- raw_lines: list[str] = []
123
+ thread_id = None
124
+ messages = []
125
+ raw_lines = []
143
126
 
144
127
  for line in output.splitlines():
145
128
  line = line.strip()
@@ -0,0 +1,145 @@
1
+ """Task wrapper for running Codex Agent flows with checkers."""
2
+
3
+ import logging
4
+
5
+ from .agent import Agent
6
+
7
+ _logger = logging.getLogger(__name__)
8
+
9
+
10
+ class TaskResult:
11
+ """Outcome summary for a task run."""
12
+
13
+ def __init__(self, success, summary, attempts, errors, thread_id):
14
+ self.success = success
15
+ self.summary = summary
16
+ self.attempts = attempts
17
+ self.errors = errors
18
+ self.thread_id = thread_id
19
+
20
+ def __repr__(self):
21
+ return (
22
+ "TaskResult("
23
+ f"success={self.success}, "
24
+ f"attempts={self.attempts}, "
25
+ f"errors={self.errors!r}, "
26
+ f"thread_id={self.thread_id!r}, "
27
+ f"summary={self.summary!r}"
28
+ ")"
29
+ )
30
+
31
+
32
+ class Task:
33
+ """ Run a Codex Agent in a directory until it is verifiably done.
34
+ Subclass and override these functions:
35
+ set_up : prepare working directory, install things etc.
36
+ tear_down : undo the above and leave machine in a clean state
37
+ check : check if the task is done, return an error string if not
38
+ on_success : run if the task succeeds, e.g. commit and push
39
+ on_failure : run if the tsak fails, e.g. record why
40
+
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ prompt,
46
+ max_attempts=10,
47
+ cwd=None,
48
+ yolo=False,
49
+ thread_id=None,
50
+ flags=None,
51
+ full_auto=True,
52
+ ):
53
+ if max_attempts < 1:
54
+ raise ValueError("max_attempts must be >= 1")
55
+ self.prompt = prompt
56
+ self.max_attempts = max_attempts
57
+ self.cwd = cwd
58
+ self.agent = Agent(
59
+ cwd=cwd,
60
+ yolo=yolo,
61
+ thread_id=thread_id,
62
+ flags=flags,
63
+ full_auto=full_auto,
64
+ )
65
+
66
+ def set_up(self):
67
+ """Clone a repo, set up a directory etc."""
68
+
69
+ def tear_down(self):
70
+ """Delete the directory etc."""
71
+
72
+ def check(self):
73
+ """ Check if the task is done, return a string describing the problems if not.
74
+ This can be any combination of running tests, python code or running an agent
75
+ with a specific prompt in self.cwd.
76
+ """
77
+
78
+ def on_success(self, result):
79
+ """Hook called after a successful task, e.g. commit the changes."""
80
+
81
+ def on_failure(self, result):
82
+ """Hook called after a failed run, e.g. log the failure reason."""
83
+
84
+ def fix_prompt(self, error):
85
+ """Build a prompt that asks the agent to fix checker failures."""
86
+ return (
87
+ "The following checks failed:\n"
88
+ f"{error}\n\n"
89
+ "Can you please dive in and see if you agree with this assessment, then fix these issues while staying as close as you can to the spirit of the original task?"
90
+ )
91
+
92
+ def success_prompt(self):
93
+ """Ask the agent to summarize what it did."""
94
+ return "Awesome - great job! Can you please produce a short summary of what you've done?"
95
+
96
+ def failure_prompt(self, error):
97
+ """Ask the agent to summarize remaining issues after retries."""
98
+ return (
99
+ "We ran out of attempts. Can you please look back at everything you tried and summarize what it was that made this task too hard to complete, including anything you wish you'd known at the start that would have helped improve things?\n\n"
100
+ f"Outstanding issues:\n{error}"
101
+ )
102
+
103
+ def __call__(self, debug=False):
104
+ """Run the task with checker-driven retries.
105
+ If debug is True, log debug messages.
106
+ """
107
+ try:
108
+ # If this fails in the middle we will still try to tear down
109
+ self.set_up()
110
+
111
+ # Start with the initial prompt
112
+ output = self.agent(self.prompt)
113
+ if debug:
114
+ _logger.debug("Initial output: %s", output)
115
+
116
+ # Try correcting it up to max_attempts times
117
+ for attempt in range(self.max_attempts):
118
+ error = self.check()
119
+ if debug:
120
+ _logger.debug("Check error: %s", error)
121
+
122
+ if error:
123
+ # if there were errors, tell the agent to fix them
124
+ output = self.agent(self.fix_prompt(error))
125
+ if debug:
126
+ _logger.debug("Fix output: %s", output)
127
+ else:
128
+ # otherwise get a summary of what was done and run on_success
129
+ summary = self.agent(self.success_prompt())
130
+ if debug:
131
+ _logger.debug("Success summary: %s", summary)
132
+ result = TaskResult(True, summary, attempt + 1, error, self.agent.thread_id)
133
+ self.on_success(result)
134
+ return result
135
+
136
+ # Ran out of attempts - get a reason why and run on_failure
137
+ summary = self.agent(self.failure_prompt(error))
138
+ if debug:
139
+ _logger.debug("Failure summary: %s", summary)
140
+ result = TaskResult(False, summary, attempt + 1, error, self.agent.thread_id)
141
+ self.on_failure(result)
142
+ return result
143
+ finally:
144
+ # No matter what, once we have set_up we will always tear_down
145
+ self.tear_down()
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.1
2
+ Name: codexapi
3
+ Version: 0.1.3
4
+ Summary: Minimal Python API for running the Codex CLI.
5
+ License: MIT
6
+ Keywords: codex,agent,cli,openai
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.8
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+
13
+ # CodexAPI
14
+
15
+ Use OpenAI's codex from python as easily as calling a function with your codex credits instead of the API.
16
+
17
+ *Note: this project is not affiliated with OpenAI in any way. Thanks for the awesome tools and models though!*
18
+
19
+ ## Requirements
20
+
21
+ - Codex CLI installed and authenticated (`codex` must be on your PATH).
22
+ - Python 3.8+.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install codexapi
28
+ ```
29
+
30
+ ## Quickstart
31
+
32
+ ```python
33
+ from codexapi import agent, Agent, Task
34
+
35
+ # Run one-shot tasks as a function call
36
+ print(agent("Say hello"))
37
+
38
+ # Run a multi-turn conversation as a session
39
+ session = Agent(cwd="/path/to/project")
40
+ print(session("Summarize this repo."))
41
+ print(session("Now list any risks."))
42
+
43
+ # Save and resume a session later
44
+ thread_id = session.thread_id
45
+ session2 = Agent(cwd="/path/to/project", thread_id=thread_id)
46
+ print(session2("Continue from where we left off."))
47
+
48
+ # Define a task with a checker
49
+ class RepoTask(Task):
50
+ def check(self):
51
+ # Return an error string if something is wrong, or None/"" if OK
52
+ return None
53
+
54
+ task = RepoTask("Summarize this repo.", cwd="/path/to/project")
55
+ result = task()
56
+ print(result.success, result.summary)
57
+ ```
58
+
59
+ ## API
60
+
61
+ ### `agent(prompt, cwd=None, yolo=False, flags=None, full_auto=False) -> str`
62
+
63
+ Runs a single Codex turn and returns only the agent's message. Any reasoning
64
+ items are filtered out.
65
+
66
+ - `prompt` (str): prompt to send to Codex.
67
+ - `cwd` (str | PathLike | None): working directory for the Codex session.
68
+ - `yolo` (bool): pass `--yolo` to Codex when true.
69
+ - `flags` (str | None): extra CLI flags to pass to Codex.
70
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
71
+
72
+ ### `Agent(cwd=None, yolo=False, thread_id=None, flags=None, full_auto=False)`
73
+
74
+ Creates a stateful session wrapper. Calling the instance sends the prompt into
75
+ the same conversation and returns only the agent's message.
76
+
77
+ - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
78
+ - `thread_id -> str | None`: expose the underlying session id once created.
79
+ - `yolo` (bool): pass `--yolo` to Codex when true.
80
+ - `flags` (str | None): extra CLI flags to pass to Codex.
81
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
82
+
83
+ ### `Task(prompt, max_attempts=10, cwd=None, yolo=False, thread_id=None, flags=None, full_auto=True)`
84
+
85
+ Runs a Codex task with checker-driven retries. Subclass it and implement
86
+ `check()` to return an error string when the task is incomplete, or return
87
+ `None`/`""` when the task passes.
88
+
89
+ - `__call__() -> TaskResult`: run the task.
90
+ - `set_up()`: optional setup hook.
91
+ - `tear_down()`: optional cleanup hook.
92
+ - `check() -> str | None`: return an error description or `None`/`""`.
93
+ - `on_success(result)`: optional success hook.
94
+ - `on_failure(result)`: optional failure hook.
95
+ - `full_auto` (bool): enable `--full-auto` for workspace-write and on-request approvals.
96
+
97
+ ### `TaskResult(success, summary, attempts, errors, thread_id)`
98
+
99
+ Simple result object returned by `Task.__call__`.
100
+
101
+ - `success` (bool): whether the task completed successfully.
102
+ - `summary` (str): agent summary of what happened.
103
+ - `attempts` (int): how many attempts were used.
104
+ - `errors` (str | None): last checker error, if any.
105
+ - `thread_id` (str | None): Codex thread id for the session.
106
+
107
+ ## Behavior notes
108
+
109
+ - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
110
+ - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
111
+ - Passes `--yolo` when enabled (use with care).
112
+ - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
113
+
114
+ ## Configuration
115
+
116
+ Set `CODEX_BIN` to point at a non-default Codex binary:
117
+
118
+ ```bash
119
+ export CODEX_BIN=/path/to/codex
120
+ ```
@@ -2,7 +2,8 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  src/codexapi/__init__.py
5
- src/codexapi/client.py
5
+ src/codexapi/agent.py
6
+ src/codexapi/task.py
6
7
  src/codexapi.egg-info/PKG-INFO
7
8
  src/codexapi.egg-info/SOURCES.txt
8
9
  src/codexapi.egg-info/dependency_links.txt
codexapi-0.1.1/PKG-INFO DELETED
@@ -1,78 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: codexapi
3
- Version: 0.1.1
4
- Summary: Minimal Python API for running the Codex CLI.
5
- License: MIT
6
- Keywords: codex,agent,cli,openai
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: Operating System :: OS Independent
9
- Requires-Python: >=3.8
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
-
13
- # CodexAPI
14
-
15
- Use codex from python as easily as calling a function with your codex credits instead of the API.
16
-
17
- ## Requirements
18
-
19
- - Codex CLI installed and authenticated (`codex` must be on your PATH).
20
- - Python 3.8+.
21
-
22
- ## Install
23
-
24
- ```bash
25
- pip install codexapi
26
- ```
27
-
28
- ## Quickstart
29
-
30
- ```python
31
- from codexapi import agent, Agent
32
-
33
- # Run one-shot tasks as a function call
34
- print(agent("Say hello"))
35
-
36
- # Run a multi-turn conversation as a session
37
- session = Agent(cwd="/path/to/project")
38
- print(session("Summarize this repo."))
39
- print(session("Now list any risks."))
40
- ```
41
-
42
- ## API
43
-
44
- ### `agent(prompt, cwd=None, *, yolo=False, agent="codex") -> str`
45
-
46
- Runs a single Codex turn and returns only the agent's message. Any reasoning
47
- items are filtered out.
48
-
49
- - `prompt` (str): prompt to send to Codex.
50
- - `cwd` (str | PathLike | None): working directory for the Codex session.
51
- - `yolo` (bool): pass `--yolo` to Codex when true.
52
- - `agent` (str): agent backend to use (only `"codex"` is supported).
53
-
54
- ### `Agent(cwd=None, *, yolo=False, agent="codex", trace_id=None)`
55
-
56
- Creates a stateful session wrapper. Calling the instance sends the prompt into
57
- the same conversation and returns only the agent's message.
58
-
59
- - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
60
- - `thread_id -> str | None`: expose the underlying session id once created.
61
- - `trace_id` (str | None): Codex thread id to resume from the first call.
62
- - `yolo` (bool): pass `--yolo` to Codex when true.
63
- - `agent` (str): agent backend to use (only `"codex"` is supported).
64
-
65
- ## Behavior notes
66
-
67
- - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
68
- - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
69
- - Passes `--yolo` when enabled (use with care).
70
- - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
71
-
72
- ## Configuration
73
-
74
- Set `CODEX_BIN` to point at a non-default Codex binary:
75
-
76
- ```bash
77
- export CODEX_BIN=/path/to/codex
78
- ```
codexapi-0.1.1/README.md DELETED
@@ -1,66 +0,0 @@
1
- # CodexAPI
2
-
3
- Use codex from python as easily as calling a function with your codex credits instead of the API.
4
-
5
- ## Requirements
6
-
7
- - Codex CLI installed and authenticated (`codex` must be on your PATH).
8
- - Python 3.8+.
9
-
10
- ## Install
11
-
12
- ```bash
13
- pip install codexapi
14
- ```
15
-
16
- ## Quickstart
17
-
18
- ```python
19
- from codexapi import agent, Agent
20
-
21
- # Run one-shot tasks as a function call
22
- print(agent("Say hello"))
23
-
24
- # Run a multi-turn conversation as a session
25
- session = Agent(cwd="/path/to/project")
26
- print(session("Summarize this repo."))
27
- print(session("Now list any risks."))
28
- ```
29
-
30
- ## API
31
-
32
- ### `agent(prompt, cwd=None, *, yolo=False, agent="codex") -> str`
33
-
34
- Runs a single Codex turn and returns only the agent's message. Any reasoning
35
- items are filtered out.
36
-
37
- - `prompt` (str): prompt to send to Codex.
38
- - `cwd` (str | PathLike | None): working directory for the Codex session.
39
- - `yolo` (bool): pass `--yolo` to Codex when true.
40
- - `agent` (str): agent backend to use (only `"codex"` is supported).
41
-
42
- ### `Agent(cwd=None, *, yolo=False, agent="codex", trace_id=None)`
43
-
44
- Creates a stateful session wrapper. Calling the instance sends the prompt into
45
- the same conversation and returns only the agent's message.
46
-
47
- - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
48
- - `thread_id -> str | None`: expose the underlying session id once created.
49
- - `trace_id` (str | None): Codex thread id to resume from the first call.
50
- - `yolo` (bool): pass `--yolo` to Codex when true.
51
- - `agent` (str): agent backend to use (only `"codex"` is supported).
52
-
53
- ## Behavior notes
54
-
55
- - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
56
- - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
57
- - Passes `--yolo` when enabled (use with care).
58
- - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
59
-
60
- ## Configuration
61
-
62
- Set `CODEX_BIN` to point at a non-default Codex binary:
63
-
64
- ```bash
65
- export CODEX_BIN=/path/to/codex
66
- ```
@@ -1,6 +0,0 @@
1
- """Minimal Python API for running the Codex CLI."""
2
-
3
- from .client import Agent, agent
4
-
5
- __all__ = ["Agent", "agent"]
6
- __version__ = "0.1.1"
@@ -1,78 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: codexapi
3
- Version: 0.1.1
4
- Summary: Minimal Python API for running the Codex CLI.
5
- License: MIT
6
- Keywords: codex,agent,cli,openai
7
- Classifier: Programming Language :: Python :: 3
8
- Classifier: Operating System :: OS Independent
9
- Requires-Python: >=3.8
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
-
13
- # CodexAPI
14
-
15
- Use codex from python as easily as calling a function with your codex credits instead of the API.
16
-
17
- ## Requirements
18
-
19
- - Codex CLI installed and authenticated (`codex` must be on your PATH).
20
- - Python 3.8+.
21
-
22
- ## Install
23
-
24
- ```bash
25
- pip install codexapi
26
- ```
27
-
28
- ## Quickstart
29
-
30
- ```python
31
- from codexapi import agent, Agent
32
-
33
- # Run one-shot tasks as a function call
34
- print(agent("Say hello"))
35
-
36
- # Run a multi-turn conversation as a session
37
- session = Agent(cwd="/path/to/project")
38
- print(session("Summarize this repo."))
39
- print(session("Now list any risks."))
40
- ```
41
-
42
- ## API
43
-
44
- ### `agent(prompt, cwd=None, *, yolo=False, agent="codex") -> str`
45
-
46
- Runs a single Codex turn and returns only the agent's message. Any reasoning
47
- items are filtered out.
48
-
49
- - `prompt` (str): prompt to send to Codex.
50
- - `cwd` (str | PathLike | None): working directory for the Codex session.
51
- - `yolo` (bool): pass `--yolo` to Codex when true.
52
- - `agent` (str): agent backend to use (only `"codex"` is supported).
53
-
54
- ### `Agent(cwd=None, *, yolo=False, agent="codex", trace_id=None)`
55
-
56
- Creates a stateful session wrapper. Calling the instance sends the prompt into
57
- the same conversation and returns only the agent's message.
58
-
59
- - `__call__(prompt) -> str`: send a prompt to Codex and return the message.
60
- - `thread_id -> str | None`: expose the underlying session id once created.
61
- - `trace_id` (str | None): Codex thread id to resume from the first call.
62
- - `yolo` (bool): pass `--yolo` to Codex when true.
63
- - `agent` (str): agent backend to use (only `"codex"` is supported).
64
-
65
- ## Behavior notes
66
-
67
- - Uses `codex exec --json` and parses JSONL events for `agent_message` items.
68
- - Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
69
- - Passes `--yolo` when enabled (use with care).
70
- - Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
71
-
72
- ## Configuration
73
-
74
- Set `CODEX_BIN` to point at a non-default Codex binary:
75
-
76
- ```bash
77
- export CODEX_BIN=/path/to/codex
78
- ```
File without changes
File without changes