codexapi 0.1.2__tar.gz → 0.1.7__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.
- codexapi-0.1.7/PKG-INFO +164 -0
- codexapi-0.1.7/README.md +152 -0
- {codexapi-0.1.2 → codexapi-0.1.7}/pyproject.toml +4 -1
- codexapi-0.1.7/src/codexapi/__init__.py +15 -0
- codexapi-0.1.7/src/codexapi/__main__.py +5 -0
- codexapi-0.1.2/src/codexapi/client.py → codexapi-0.1.7/src/codexapi/agent.py +32 -70
- codexapi-0.1.7/src/codexapi/cli.py +918 -0
- codexapi-0.1.7/src/codexapi/task.py +293 -0
- codexapi-0.1.7/src/codexapi.egg-info/PKG-INFO +164 -0
- {codexapi-0.1.2 → codexapi-0.1.7}/src/codexapi.egg-info/SOURCES.txt +5 -1
- codexapi-0.1.7/src/codexapi.egg-info/entry_points.txt +2 -0
- codexapi-0.1.2/PKG-INFO +0 -85
- codexapi-0.1.2/README.md +0 -73
- codexapi-0.1.2/src/codexapi/__init__.py +0 -6
- codexapi-0.1.2/src/codexapi.egg-info/PKG-INFO +0 -85
- {codexapi-0.1.2 → codexapi-0.1.7}/LICENSE +0 -0
- {codexapi-0.1.2 → codexapi-0.1.7}/setup.cfg +0 -0
- {codexapi-0.1.2 → codexapi-0.1.7}/src/codexapi.egg-info/dependency_links.txt +0 -0
- {codexapi-0.1.2 → codexapi-0.1.7}/src/codexapi.egg-info/top_level.txt +0 -0
codexapi-0.1.7/PKG-INFO
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: codexapi
|
|
3
|
+
Version: 0.1.7
|
|
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
|
+
## CLI
|
|
60
|
+
|
|
61
|
+
After installing, use the `codexapi` command:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
codexapi "Summarize this repo."
|
|
65
|
+
codexapi --cwd /path/to/project "Fix the failing tests."
|
|
66
|
+
echo "Say hello." | codexapi
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Task mode exits with code 0 on success and 1 on failure, printing the summary.
|
|
70
|
+
|
|
71
|
+
Show running sessions and their latest activity:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
codexapi top
|
|
75
|
+
```
|
|
76
|
+
Press `h` for keys.
|
|
77
|
+
|
|
78
|
+
Resume a session and print the thread id to stderr:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
codexapi --thread-id THREAD_ID --print-thread-id "Continue where we left off."
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## API
|
|
85
|
+
|
|
86
|
+
### `agent(prompt, cwd=None, yolo=False, flags=None) -> str`
|
|
87
|
+
|
|
88
|
+
Runs a single Codex turn and returns only the agent's message. Any reasoning
|
|
89
|
+
items are filtered out.
|
|
90
|
+
|
|
91
|
+
- `prompt` (str): prompt to send to Codex.
|
|
92
|
+
- `cwd` (str | PathLike | None): working directory for the Codex session.
|
|
93
|
+
- `yolo` (bool): pass `--yolo` to Codex when true.
|
|
94
|
+
- `flags` (str | None): extra CLI flags to pass to Codex.
|
|
95
|
+
|
|
96
|
+
### `Agent(cwd=None, yolo=False, thread_id=None, flags=None)`
|
|
97
|
+
|
|
98
|
+
Creates a stateful session wrapper. Calling the instance sends the prompt into
|
|
99
|
+
the same conversation and returns only the agent's message.
|
|
100
|
+
|
|
101
|
+
- `__call__(prompt) -> str`: send a prompt to Codex and return the message.
|
|
102
|
+
- `thread_id -> str | None`: expose the underlying session id once created.
|
|
103
|
+
- `yolo` (bool): pass `--yolo` to Codex when true.
|
|
104
|
+
- `flags` (str | None): extra CLI flags to pass to Codex.
|
|
105
|
+
|
|
106
|
+
### `task(prompt, check=None, n=10, cwd=None, yolo=False, flags=None) -> str`
|
|
107
|
+
|
|
108
|
+
Runs a task with checker-driven retries and returns the success summary.
|
|
109
|
+
Raises `TaskFailed` when the maximum attempts are reached.
|
|
110
|
+
|
|
111
|
+
- `check` (str | None | False): custom check prompt, default checker, or `False` to skip.
|
|
112
|
+
- `n` (int): maximum number of retries after a failed check.
|
|
113
|
+
|
|
114
|
+
### `task_result(prompt, check=None, n=10, cwd=None, yolo=False, flags=None) -> TaskResult`
|
|
115
|
+
|
|
116
|
+
Runs a task with checker-driven retries and returns a `TaskResult` without
|
|
117
|
+
raising `TaskFailed`.
|
|
118
|
+
|
|
119
|
+
### `Task(prompt, max_attempts=10, cwd=None, yolo=False, thread_id=None, flags=None)`
|
|
120
|
+
|
|
121
|
+
Runs a Codex task with checker-driven retries. Subclass it and implement
|
|
122
|
+
`check()` to return an error string when the task is incomplete, or return
|
|
123
|
+
`None`/`""` when the task passes.
|
|
124
|
+
|
|
125
|
+
- `__call__() -> TaskResult`: run the task.
|
|
126
|
+
- `set_up()`: optional setup hook.
|
|
127
|
+
- `tear_down()`: optional cleanup hook.
|
|
128
|
+
- `check() -> str | None`: return an error description or `None`/`""`.
|
|
129
|
+
- `on_success(result)`: optional success hook.
|
|
130
|
+
- `on_failure(result)`: optional failure hook.
|
|
131
|
+
|
|
132
|
+
### `TaskResult(success, summary, attempts, errors, thread_id)`
|
|
133
|
+
|
|
134
|
+
Simple result object returned by `Task.__call__`.
|
|
135
|
+
|
|
136
|
+
- `success` (bool): whether the task completed successfully.
|
|
137
|
+
- `summary` (str): agent summary of what happened.
|
|
138
|
+
- `attempts` (int): how many attempts were used.
|
|
139
|
+
- `errors` (str | None): last checker error, if any.
|
|
140
|
+
- `thread_id` (str | None): Codex thread id for the session.
|
|
141
|
+
|
|
142
|
+
### `TaskFailed`
|
|
143
|
+
|
|
144
|
+
Exception raised by `task()` when retries are exhausted.
|
|
145
|
+
|
|
146
|
+
- `summary` (str): failure summary text.
|
|
147
|
+
- `attempts` (int | None): attempts made when the task failed.
|
|
148
|
+
- `errors` (str | None): last checker error, if any.
|
|
149
|
+
|
|
150
|
+
## Behavior notes
|
|
151
|
+
|
|
152
|
+
- Uses `codex exec --json` and parses JSONL events for `agent_message` items.
|
|
153
|
+
- Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
|
|
154
|
+
- Passes `--full-auto` unless `--yolo` is enabled.
|
|
155
|
+
- Passes `--yolo` when enabled (use with care).
|
|
156
|
+
- Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
|
|
157
|
+
|
|
158
|
+
## Configuration
|
|
159
|
+
|
|
160
|
+
Set `CODEX_BIN` to point at a non-default Codex binary:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
export CODEX_BIN=/path/to/codex
|
|
164
|
+
```
|
codexapi-0.1.7/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
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
|
+
## CLI
|
|
48
|
+
|
|
49
|
+
After installing, use the `codexapi` command:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
codexapi "Summarize this repo."
|
|
53
|
+
codexapi --cwd /path/to/project "Fix the failing tests."
|
|
54
|
+
echo "Say hello." | codexapi
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Task mode exits with code 0 on success and 1 on failure, printing the summary.
|
|
58
|
+
|
|
59
|
+
Show running sessions and their latest activity:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
codexapi top
|
|
63
|
+
```
|
|
64
|
+
Press `h` for keys.
|
|
65
|
+
|
|
66
|
+
Resume a session and print the thread id to stderr:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
codexapi --thread-id THREAD_ID --print-thread-id "Continue where we left off."
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## API
|
|
73
|
+
|
|
74
|
+
### `agent(prompt, cwd=None, yolo=False, flags=None) -> str`
|
|
75
|
+
|
|
76
|
+
Runs a single Codex turn and returns only the agent's message. Any reasoning
|
|
77
|
+
items are filtered out.
|
|
78
|
+
|
|
79
|
+
- `prompt` (str): prompt to send to Codex.
|
|
80
|
+
- `cwd` (str | PathLike | None): working directory for the Codex session.
|
|
81
|
+
- `yolo` (bool): pass `--yolo` to Codex when true.
|
|
82
|
+
- `flags` (str | None): extra CLI flags to pass to Codex.
|
|
83
|
+
|
|
84
|
+
### `Agent(cwd=None, yolo=False, thread_id=None, flags=None)`
|
|
85
|
+
|
|
86
|
+
Creates a stateful session wrapper. Calling the instance sends the prompt into
|
|
87
|
+
the same conversation and returns only the agent's message.
|
|
88
|
+
|
|
89
|
+
- `__call__(prompt) -> str`: send a prompt to Codex and return the message.
|
|
90
|
+
- `thread_id -> str | None`: expose the underlying session id once created.
|
|
91
|
+
- `yolo` (bool): pass `--yolo` to Codex when true.
|
|
92
|
+
- `flags` (str | None): extra CLI flags to pass to Codex.
|
|
93
|
+
|
|
94
|
+
### `task(prompt, check=None, n=10, cwd=None, yolo=False, flags=None) -> str`
|
|
95
|
+
|
|
96
|
+
Runs a task with checker-driven retries and returns the success summary.
|
|
97
|
+
Raises `TaskFailed` when the maximum attempts are reached.
|
|
98
|
+
|
|
99
|
+
- `check` (str | None | False): custom check prompt, default checker, or `False` to skip.
|
|
100
|
+
- `n` (int): maximum number of retries after a failed check.
|
|
101
|
+
|
|
102
|
+
### `task_result(prompt, check=None, n=10, cwd=None, yolo=False, flags=None) -> TaskResult`
|
|
103
|
+
|
|
104
|
+
Runs a task with checker-driven retries and returns a `TaskResult` without
|
|
105
|
+
raising `TaskFailed`.
|
|
106
|
+
|
|
107
|
+
### `Task(prompt, max_attempts=10, cwd=None, yolo=False, thread_id=None, flags=None)`
|
|
108
|
+
|
|
109
|
+
Runs a Codex task with checker-driven retries. Subclass it and implement
|
|
110
|
+
`check()` to return an error string when the task is incomplete, or return
|
|
111
|
+
`None`/`""` when the task passes.
|
|
112
|
+
|
|
113
|
+
- `__call__() -> TaskResult`: run the task.
|
|
114
|
+
- `set_up()`: optional setup hook.
|
|
115
|
+
- `tear_down()`: optional cleanup hook.
|
|
116
|
+
- `check() -> str | None`: return an error description or `None`/`""`.
|
|
117
|
+
- `on_success(result)`: optional success hook.
|
|
118
|
+
- `on_failure(result)`: optional failure hook.
|
|
119
|
+
|
|
120
|
+
### `TaskResult(success, summary, attempts, errors, thread_id)`
|
|
121
|
+
|
|
122
|
+
Simple result object returned by `Task.__call__`.
|
|
123
|
+
|
|
124
|
+
- `success` (bool): whether the task completed successfully.
|
|
125
|
+
- `summary` (str): agent summary of what happened.
|
|
126
|
+
- `attempts` (int): how many attempts were used.
|
|
127
|
+
- `errors` (str | None): last checker error, if any.
|
|
128
|
+
- `thread_id` (str | None): Codex thread id for the session.
|
|
129
|
+
|
|
130
|
+
### `TaskFailed`
|
|
131
|
+
|
|
132
|
+
Exception raised by `task()` when retries are exhausted.
|
|
133
|
+
|
|
134
|
+
- `summary` (str): failure summary text.
|
|
135
|
+
- `attempts` (int | None): attempts made when the task failed.
|
|
136
|
+
- `errors` (str | None): last checker error, if any.
|
|
137
|
+
|
|
138
|
+
## Behavior notes
|
|
139
|
+
|
|
140
|
+
- Uses `codex exec --json` and parses JSONL events for `agent_message` items.
|
|
141
|
+
- Automatically passes `--skip-git-repo-check` so it can run outside a git repo.
|
|
142
|
+
- Passes `--full-auto` unless `--yolo` is enabled.
|
|
143
|
+
- Passes `--yolo` when enabled (use with care).
|
|
144
|
+
- Raises `RuntimeError` if Codex exits non-zero or returns no agent message.
|
|
145
|
+
|
|
146
|
+
## Configuration
|
|
147
|
+
|
|
148
|
+
Set `CODEX_BIN` to point at a non-default Codex binary:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
export CODEX_BIN=/path/to/codex
|
|
152
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codexapi"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.7"
|
|
8
8
|
description = "Minimal Python API for running the Codex CLI."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -17,6 +17,9 @@ classifiers = [
|
|
|
17
17
|
|
|
18
18
|
dependencies = []
|
|
19
19
|
|
|
20
|
+
[project.scripts]
|
|
21
|
+
codexapi = "codexapi.cli:main"
|
|
22
|
+
|
|
20
23
|
[tool.setuptools]
|
|
21
24
|
package-dir = {"" = "src"}
|
|
22
25
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Minimal Python API for running the Codex CLI."""
|
|
2
|
+
|
|
3
|
+
from .agent import Agent, agent
|
|
4
|
+
from .task import Task, TaskFailed, TaskResult, task, task_result
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"Agent",
|
|
8
|
+
"Task",
|
|
9
|
+
"TaskFailed",
|
|
10
|
+
"TaskResult",
|
|
11
|
+
"agent",
|
|
12
|
+
"task",
|
|
13
|
+
"task_result",
|
|
14
|
+
]
|
|
15
|
+
__version__ = "0.1.7"
|
|
@@ -1,46 +1,26 @@
|
|
|
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
|
|
7
5
|
import shlex
|
|
8
6
|
import subprocess
|
|
9
|
-
from typing import Optional, Tuple, Union
|
|
10
|
-
|
|
11
|
-
Pathish = Union[str, os.PathLike]
|
|
12
7
|
|
|
13
8
|
_CODEX_BIN = os.environ.get("CODEX_BIN", "codex")
|
|
14
9
|
|
|
15
10
|
|
|
16
|
-
def agent(
|
|
17
|
-
prompt: str,
|
|
18
|
-
cwd: Optional[Pathish] = None,
|
|
19
|
-
*,
|
|
20
|
-
yolo: bool = False,
|
|
21
|
-
agent: str = "codex",
|
|
22
|
-
flags: Optional[str] = None,
|
|
23
|
-
) -> str:
|
|
11
|
+
def agent(prompt, cwd=None, yolo=False, flags=None):
|
|
24
12
|
"""Run a single Codex turn and return only the agent's message.
|
|
25
13
|
|
|
26
14
|
Args:
|
|
27
15
|
prompt: The user prompt to send to Codex.
|
|
28
16
|
cwd: Optional working directory for the Codex session.
|
|
29
17
|
yolo: Whether to pass --yolo to Codex.
|
|
30
|
-
agent: Agent backend to use (only "codex" is supported).
|
|
31
18
|
flags: Additional raw CLI flags to pass to Codex.
|
|
32
19
|
|
|
33
20
|
Returns:
|
|
34
21
|
The agent's visible response text with reasoning traces removed.
|
|
35
22
|
"""
|
|
36
|
-
|
|
37
|
-
message, _thread_id = _run_codex(
|
|
38
|
-
prompt=prompt,
|
|
39
|
-
cwd=cwd,
|
|
40
|
-
thread_id=None,
|
|
41
|
-
yolo=yolo,
|
|
42
|
-
flags=flags,
|
|
43
|
-
)
|
|
23
|
+
message, _thread_id = _run_codex(prompt, cwd, None, yolo, flags)
|
|
44
24
|
return message
|
|
45
25
|
|
|
46
26
|
|
|
@@ -55,13 +35,11 @@ class Agent:
|
|
|
55
35
|
|
|
56
36
|
def __init__(
|
|
57
37
|
self,
|
|
58
|
-
cwd
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
flags: Optional[str] = None,
|
|
64
|
-
) -> None:
|
|
38
|
+
cwd=None,
|
|
39
|
+
yolo=False,
|
|
40
|
+
thread_id=None,
|
|
41
|
+
flags=None,
|
|
42
|
+
):
|
|
65
43
|
"""Create a new session wrapper.
|
|
66
44
|
|
|
67
45
|
Args:
|
|
@@ -71,41 +49,28 @@ class Agent:
|
|
|
71
49
|
trace_id: Optional Codex thread id to resume from the first call.
|
|
72
50
|
flags: Additional raw CLI flags to pass to Codex.
|
|
73
51
|
"""
|
|
74
|
-
|
|
75
|
-
self._cwd = cwd
|
|
52
|
+
self.cwd = cwd
|
|
76
53
|
self._yolo = yolo
|
|
77
54
|
self._flags = flags
|
|
78
|
-
self.
|
|
55
|
+
self.thread_id = thread_id
|
|
79
56
|
|
|
80
|
-
def __call__(self, prompt
|
|
57
|
+
def __call__(self, prompt):
|
|
81
58
|
"""Send a prompt to Codex and return only the agent's message."""
|
|
82
59
|
message, thread_id = _run_codex(
|
|
83
|
-
prompt
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
60
|
+
prompt,
|
|
61
|
+
self.cwd,
|
|
62
|
+
self.thread_id,
|
|
63
|
+
self._yolo,
|
|
64
|
+
self._flags,
|
|
88
65
|
)
|
|
89
66
|
if thread_id:
|
|
90
|
-
self.
|
|
67
|
+
self.thread_id = thread_id
|
|
91
68
|
return message
|
|
92
69
|
|
|
93
|
-
@property
|
|
94
|
-
def thread_id(self) -> Optional[str]:
|
|
95
|
-
"""Return the current Codex session id, if any."""
|
|
96
|
-
return self._thread_id
|
|
97
70
|
|
|
98
|
-
|
|
99
|
-
def _run_codex(
|
|
100
|
-
*,
|
|
101
|
-
prompt: str,
|
|
102
|
-
cwd: Optional[Pathish],
|
|
103
|
-
thread_id: Optional[str],
|
|
104
|
-
yolo: bool,
|
|
105
|
-
flags: Optional[str],
|
|
106
|
-
) -> Tuple[str, Optional[str]]:
|
|
71
|
+
def _run_codex(prompt, cwd, thread_id, yolo, flags):
|
|
107
72
|
"""Invoke the Codex CLI and return the message plus thread id (if any)."""
|
|
108
|
-
|
|
73
|
+
command = [
|
|
109
74
|
_CODEX_BIN,
|
|
110
75
|
"exec",
|
|
111
76
|
"--json",
|
|
@@ -114,22 +79,24 @@ def _run_codex(
|
|
|
114
79
|
"--skip-git-repo-check",
|
|
115
80
|
]
|
|
116
81
|
if yolo:
|
|
117
|
-
|
|
82
|
+
command.append("--yolo")
|
|
83
|
+
else:
|
|
84
|
+
command.append("--full-auto")
|
|
118
85
|
if flags:
|
|
119
|
-
|
|
120
|
-
if cwd
|
|
121
|
-
|
|
86
|
+
command.extend(shlex.split(flags))
|
|
87
|
+
if cwd:
|
|
88
|
+
command.extend(["--cd", os.fspath(cwd)])
|
|
122
89
|
if thread_id:
|
|
123
|
-
|
|
90
|
+
command.extend(["resume", thread_id, "-"])
|
|
124
91
|
else:
|
|
125
|
-
|
|
92
|
+
command.append("-")
|
|
126
93
|
|
|
127
94
|
result = subprocess.run(
|
|
128
|
-
|
|
95
|
+
command,
|
|
129
96
|
input=prompt,
|
|
130
97
|
text=True,
|
|
131
98
|
capture_output=True,
|
|
132
|
-
cwd=os.fspath(cwd) if cwd
|
|
99
|
+
cwd=os.fspath(cwd) if cwd else None,
|
|
133
100
|
)
|
|
134
101
|
if result.returncode != 0:
|
|
135
102
|
stderr = result.stderr.strip()
|
|
@@ -141,16 +108,11 @@ def _run_codex(
|
|
|
141
108
|
return _parse_jsonl(result.stdout)
|
|
142
109
|
|
|
143
110
|
|
|
144
|
-
def
|
|
145
|
-
if agent_name != "codex":
|
|
146
|
-
raise ValueError('Only agent="codex" is supported right now.')
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def _parse_jsonl(output: str) -> Tuple[str, Optional[str]]:
|
|
111
|
+
def _parse_jsonl(output):
|
|
150
112
|
"""Extract agent messages and the latest thread id from Codex JSONL output."""
|
|
151
|
-
thread_id
|
|
152
|
-
messages
|
|
153
|
-
raw_lines
|
|
113
|
+
thread_id = None
|
|
114
|
+
messages = []
|
|
115
|
+
raw_lines = []
|
|
154
116
|
|
|
155
117
|
for line in output.splitlines():
|
|
156
118
|
line = line.strip()
|