codexapi 0.12.7__tar.gz → 0.12.9__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.12.7/src/codexapi.egg-info → codexapi-0.12.9}/PKG-INFO +17 -8
- {codexapi-0.12.7 → codexapi-0.12.9}/README.md +16 -7
- {codexapi-0.12.7 → codexapi-0.12.9}/pyproject.toml +1 -1
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/__init__.py +1 -1
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/agent.py +33 -4
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/agents.py +23 -9
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/async_agent.py +26 -6
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/cli.py +136 -55
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/foreach.py +4 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/gh_integration.py +4 -1
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/lead.py +6 -1
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/ralph.py +26 -18
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/science.py +23 -2
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/task.py +48 -13
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/taskfile.py +3 -0
- {codexapi-0.12.7 → codexapi-0.12.9/src/codexapi.egg-info}/PKG-INFO +17 -8
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_agent_backend.py +26 -1
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_agents.py +51 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_async_agent.py +61 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/LICENSE +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/setup.cfg +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/__main__.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/pushover.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/rate_limits.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi/welfare.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi.egg-info/SOURCES.txt +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi.egg-info/dependency_links.txt +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi.egg-info/entry_points.txt +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi.egg-info/requires.txt +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/src/codexapi.egg-info/top_level.txt +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_rate_limits.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_science.py +0 -0
- {codexapi-0.12.7 → codexapi-0.12.9}/tests/test_task_progress.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: codexapi
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.9
|
|
4
4
|
Summary: Minimal Python API for running the Codex CLI.
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: codex,agent,cli,openai
|
|
@@ -78,6 +78,8 @@ for update in agent.watch(poll_interval=2.0):
|
|
|
78
78
|
|
|
79
79
|
Use `backend="cursor"` (or set `CODEXAPI_BACKEND=cursor`) to switch to the
|
|
80
80
|
Cursor agent backend.
|
|
81
|
+
Use `fast=True` in Codex API calls, or `--fast` in the CLI, to opt into Codex
|
|
82
|
+
fast mode. Normal mode is the default.
|
|
81
83
|
|
|
82
84
|
## CLI
|
|
83
85
|
|
|
@@ -88,6 +90,7 @@ codexapi --version
|
|
|
88
90
|
codexapi run "Summarize this repo."
|
|
89
91
|
codexapi run --cwd /path/to/project "Fix the failing tests."
|
|
90
92
|
echo "Say hello." | codexapi run
|
|
93
|
+
codexapi run --fast "Summarize this repo quickly."
|
|
91
94
|
codexapi run --backend cursor "Summarize this repo."
|
|
92
95
|
```
|
|
93
96
|
|
|
@@ -333,7 +336,7 @@ codexapi foreach list.txt task.yaml --retry-all
|
|
|
333
336
|
|
|
334
337
|
## API
|
|
335
338
|
|
|
336
|
-
### `agent(prompt, cwd=None, yolo=True, flags=None, include_thinking=False, backend=None) -> str`
|
|
339
|
+
### `agent(prompt, cwd=None, yolo=True, flags=None, include_thinking=False, backend=None, fast=False) -> str`
|
|
337
340
|
|
|
338
341
|
Runs a single agent turn and returns only the agent's message. Any reasoning
|
|
339
342
|
items are filtered out.
|
|
@@ -344,8 +347,9 @@ items are filtered out.
|
|
|
344
347
|
- `flags` (str | None): extra CLI flags to pass to the agent backend.
|
|
345
348
|
- `include_thinking` (bool): when true, return all agent messages joined.
|
|
346
349
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
350
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
347
351
|
|
|
348
|
-
### `Agent(cwd=None, yolo=True, thread_id=None, flags=None, welfare=False, include_thinking=False, backend=None)`
|
|
352
|
+
### `Agent(cwd=None, yolo=True, thread_id=None, flags=None, welfare=False, include_thinking=False, backend=None, fast=False)`
|
|
349
353
|
|
|
350
354
|
Creates a stateful session wrapper. Calling the instance sends the prompt into
|
|
351
355
|
the same conversation and returns only the agent's message.
|
|
@@ -358,9 +362,10 @@ the same conversation and returns only the agent's message.
|
|
|
358
362
|
and raise `WelfareStop` if the agent outputs `MAKE IT STOP`.
|
|
359
363
|
- `include_thinking` (bool): when true, return all agent messages joined.
|
|
360
364
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
365
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
361
366
|
For Cursor, `thread_id` corresponds to the `session_id` returned by the agent.
|
|
362
367
|
|
|
363
|
-
### `lead(minutes, prompt, cwd=None, yolo=True, flags=None, leadbook=None, backend=None) -> dict`
|
|
368
|
+
### `lead(minutes, prompt, cwd=None, yolo=True, flags=None, leadbook=None, backend=None, fast=False) -> dict`
|
|
364
369
|
|
|
365
370
|
Runs a long-lived agent session and periodically checks in with the current
|
|
366
371
|
local time and a reminder of `prompt`. Each check-in expects JSON with keys:
|
|
@@ -373,7 +378,7 @@ Lead also injects the leadbook content into each prompt. By default it uses
|
|
|
373
378
|
path string to override the location.
|
|
374
379
|
Set `backend="cursor"` (or `CODEXAPI_BACKEND=cursor`) to use Cursor.
|
|
375
380
|
|
|
376
|
-
### `task(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None) -> str`
|
|
381
|
+
### `task(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None, fast=False) -> str`
|
|
377
382
|
|
|
378
383
|
Runs a task with checker-driven retries and returns the success summary.
|
|
379
384
|
Raises `TaskFailed` when the maximum iterations are reached.
|
|
@@ -383,14 +388,15 @@ Raises `TaskFailed` when the maximum iterations are reached.
|
|
|
383
388
|
- `progress` (bool): show a tqdm progress bar with a one-line status after each round.
|
|
384
389
|
- `set_up`/`tear_down`/`on_success`/`on_failure` (str | None): optional hook prompts.
|
|
385
390
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
391
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
386
392
|
|
|
387
|
-
### `task_result(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None) -> TaskResult`
|
|
393
|
+
### `task_result(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None, fast=False) -> TaskResult`
|
|
388
394
|
|
|
389
395
|
Runs a task with checker-driven retries and returns a `TaskResult` without
|
|
390
396
|
raising `TaskFailed`.
|
|
391
397
|
Arguments mirror `task()` (including hooks).
|
|
392
398
|
|
|
393
|
-
### `Task(prompt, max_iterations=10, cwd=None, yolo=True, thread_id=None, flags=None, backend=None)`
|
|
399
|
+
### `Task(prompt, max_iterations=10, cwd=None, yolo=True, thread_id=None, flags=None, backend=None, fast=False)`
|
|
394
400
|
|
|
395
401
|
Runs an agent task with checker-driven retries. Subclass it and implement
|
|
396
402
|
`check()` to return an error string when the task is incomplete, or return
|
|
@@ -423,7 +429,7 @@ Exception raised by `task()` when iterations are exhausted.
|
|
|
423
429
|
- `iterations` (int | None): iterations made when the task failed.
|
|
424
430
|
- `errors` (str | None): last checker error, if any.
|
|
425
431
|
|
|
426
|
-
### `foreach(list_file, task_file, n=None, cwd=None, yolo=True, flags=None, backend=None) -> ForeachResult`
|
|
432
|
+
### `foreach(list_file, task_file, n=None, cwd=None, yolo=True, flags=None, backend=None, fast=False) -> ForeachResult`
|
|
427
433
|
|
|
428
434
|
Runs a task file over a list of items, updating the list file in place.
|
|
429
435
|
|
|
@@ -434,6 +440,7 @@ Runs a task file over a list of items, updating the list file in place.
|
|
|
434
440
|
- `yolo` (bool): pass `--yolo` when true (defaults to true).
|
|
435
441
|
- `flags` (str | None): extra CLI flags to pass to the agent backend.
|
|
436
442
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
443
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
437
444
|
|
|
438
445
|
### `ForeachResult(succeeded, failed, skipped, results)`
|
|
439
446
|
|
|
@@ -448,6 +455,8 @@ Simple result object returned by `foreach()`.
|
|
|
448
455
|
|
|
449
456
|
- Codex backend uses `codex exec --json` and parses JSONL `agent_message` items.
|
|
450
457
|
- Codex backend passes `--skip-git-repo-check` so it can run outside a git repo.
|
|
458
|
+
- Codex backend defaults to normal mode and passes `features.fast_mode=false`;
|
|
459
|
+
`fast=True` / `--fast` also passes `service_tier=fast` and `features.fast_mode=true`.
|
|
451
460
|
- Cursor backend uses `cursor agent --print --output-format json --trust` and parses the JSON result.
|
|
452
461
|
- `include_thinking=True` only affects Codex; Cursor returns a single result string.
|
|
453
462
|
- Passes `--yolo` by default (Codex uses `--full-auto` when disabled).
|
|
@@ -63,6 +63,8 @@ for update in agent.watch(poll_interval=2.0):
|
|
|
63
63
|
|
|
64
64
|
Use `backend="cursor"` (or set `CODEXAPI_BACKEND=cursor`) to switch to the
|
|
65
65
|
Cursor agent backend.
|
|
66
|
+
Use `fast=True` in Codex API calls, or `--fast` in the CLI, to opt into Codex
|
|
67
|
+
fast mode. Normal mode is the default.
|
|
66
68
|
|
|
67
69
|
## CLI
|
|
68
70
|
|
|
@@ -73,6 +75,7 @@ codexapi --version
|
|
|
73
75
|
codexapi run "Summarize this repo."
|
|
74
76
|
codexapi run --cwd /path/to/project "Fix the failing tests."
|
|
75
77
|
echo "Say hello." | codexapi run
|
|
78
|
+
codexapi run --fast "Summarize this repo quickly."
|
|
76
79
|
codexapi run --backend cursor "Summarize this repo."
|
|
77
80
|
```
|
|
78
81
|
|
|
@@ -318,7 +321,7 @@ codexapi foreach list.txt task.yaml --retry-all
|
|
|
318
321
|
|
|
319
322
|
## API
|
|
320
323
|
|
|
321
|
-
### `agent(prompt, cwd=None, yolo=True, flags=None, include_thinking=False, backend=None) -> str`
|
|
324
|
+
### `agent(prompt, cwd=None, yolo=True, flags=None, include_thinking=False, backend=None, fast=False) -> str`
|
|
322
325
|
|
|
323
326
|
Runs a single agent turn and returns only the agent's message. Any reasoning
|
|
324
327
|
items are filtered out.
|
|
@@ -329,8 +332,9 @@ items are filtered out.
|
|
|
329
332
|
- `flags` (str | None): extra CLI flags to pass to the agent backend.
|
|
330
333
|
- `include_thinking` (bool): when true, return all agent messages joined.
|
|
331
334
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
335
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
332
336
|
|
|
333
|
-
### `Agent(cwd=None, yolo=True, thread_id=None, flags=None, welfare=False, include_thinking=False, backend=None)`
|
|
337
|
+
### `Agent(cwd=None, yolo=True, thread_id=None, flags=None, welfare=False, include_thinking=False, backend=None, fast=False)`
|
|
334
338
|
|
|
335
339
|
Creates a stateful session wrapper. Calling the instance sends the prompt into
|
|
336
340
|
the same conversation and returns only the agent's message.
|
|
@@ -343,9 +347,10 @@ the same conversation and returns only the agent's message.
|
|
|
343
347
|
and raise `WelfareStop` if the agent outputs `MAKE IT STOP`.
|
|
344
348
|
- `include_thinking` (bool): when true, return all agent messages joined.
|
|
345
349
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
350
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
346
351
|
For Cursor, `thread_id` corresponds to the `session_id` returned by the agent.
|
|
347
352
|
|
|
348
|
-
### `lead(minutes, prompt, cwd=None, yolo=True, flags=None, leadbook=None, backend=None) -> dict`
|
|
353
|
+
### `lead(minutes, prompt, cwd=None, yolo=True, flags=None, leadbook=None, backend=None, fast=False) -> dict`
|
|
349
354
|
|
|
350
355
|
Runs a long-lived agent session and periodically checks in with the current
|
|
351
356
|
local time and a reminder of `prompt`. Each check-in expects JSON with keys:
|
|
@@ -358,7 +363,7 @@ Lead also injects the leadbook content into each prompt. By default it uses
|
|
|
358
363
|
path string to override the location.
|
|
359
364
|
Set `backend="cursor"` (or `CODEXAPI_BACKEND=cursor`) to use Cursor.
|
|
360
365
|
|
|
361
|
-
### `task(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None) -> str`
|
|
366
|
+
### `task(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None, fast=False) -> str`
|
|
362
367
|
|
|
363
368
|
Runs a task with checker-driven retries and returns the success summary.
|
|
364
369
|
Raises `TaskFailed` when the maximum iterations are reached.
|
|
@@ -368,14 +373,15 @@ Raises `TaskFailed` when the maximum iterations are reached.
|
|
|
368
373
|
- `progress` (bool): show a tqdm progress bar with a one-line status after each round.
|
|
369
374
|
- `set_up`/`tear_down`/`on_success`/`on_failure` (str | None): optional hook prompts.
|
|
370
375
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
376
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
371
377
|
|
|
372
|
-
### `task_result(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None) -> TaskResult`
|
|
378
|
+
### `task_result(prompt, check=None, max_iterations=10, cwd=None, yolo=True, flags=None, progress=False, set_up=None, tear_down=None, on_success=None, on_failure=None, backend=None, fast=False) -> TaskResult`
|
|
373
379
|
|
|
374
380
|
Runs a task with checker-driven retries and returns a `TaskResult` without
|
|
375
381
|
raising `TaskFailed`.
|
|
376
382
|
Arguments mirror `task()` (including hooks).
|
|
377
383
|
|
|
378
|
-
### `Task(prompt, max_iterations=10, cwd=None, yolo=True, thread_id=None, flags=None, backend=None)`
|
|
384
|
+
### `Task(prompt, max_iterations=10, cwd=None, yolo=True, thread_id=None, flags=None, backend=None, fast=False)`
|
|
379
385
|
|
|
380
386
|
Runs an agent task with checker-driven retries. Subclass it and implement
|
|
381
387
|
`check()` to return an error string when the task is incomplete, or return
|
|
@@ -408,7 +414,7 @@ Exception raised by `task()` when iterations are exhausted.
|
|
|
408
414
|
- `iterations` (int | None): iterations made when the task failed.
|
|
409
415
|
- `errors` (str | None): last checker error, if any.
|
|
410
416
|
|
|
411
|
-
### `foreach(list_file, task_file, n=None, cwd=None, yolo=True, flags=None, backend=None) -> ForeachResult`
|
|
417
|
+
### `foreach(list_file, task_file, n=None, cwd=None, yolo=True, flags=None, backend=None, fast=False) -> ForeachResult`
|
|
412
418
|
|
|
413
419
|
Runs a task file over a list of items, updating the list file in place.
|
|
414
420
|
|
|
@@ -419,6 +425,7 @@ Runs a task file over a list of items, updating the list file in place.
|
|
|
419
425
|
- `yolo` (bool): pass `--yolo` when true (defaults to true).
|
|
420
426
|
- `flags` (str | None): extra CLI flags to pass to the agent backend.
|
|
421
427
|
- `backend` (str | None): `codex` or `cursor` (defaults to `CODEXAPI_BACKEND` or `codex`).
|
|
428
|
+
- `fast` (bool): enable Codex fast mode (defaults to normal mode).
|
|
422
429
|
|
|
423
430
|
### `ForeachResult(succeeded, failed, skipped, results)`
|
|
424
431
|
|
|
@@ -433,6 +440,8 @@ Simple result object returned by `foreach()`.
|
|
|
433
440
|
|
|
434
441
|
- Codex backend uses `codex exec --json` and parses JSONL `agent_message` items.
|
|
435
442
|
- Codex backend passes `--skip-git-repo-check` so it can run outside a git repo.
|
|
443
|
+
- Codex backend defaults to normal mode and passes `features.fast_mode=false`;
|
|
444
|
+
`fast=True` / `--fast` also passes `service_tier=fast` and `features.fast_mode=true`.
|
|
436
445
|
- Cursor backend uses `cursor agent --print --output-format json --trust` and parses the JSON result.
|
|
437
446
|
- `include_thinking=True` only affects Codex; Cursor returns a single result string.
|
|
438
447
|
- Passes `--yolo` by default (Codex uses `--full-auto` when disabled).
|
|
@@ -54,6 +54,7 @@ def agent(
|
|
|
54
54
|
include_thinking=False,
|
|
55
55
|
backend=None,
|
|
56
56
|
env=None,
|
|
57
|
+
fast=False,
|
|
57
58
|
):
|
|
58
59
|
"""Run a single agent turn and return only the agent's message.
|
|
59
60
|
|
|
@@ -65,12 +66,13 @@ def agent(
|
|
|
65
66
|
include_thinking: When true, return all agent messages joined together.
|
|
66
67
|
backend: Agent backend to use ("codex" or "cursor").
|
|
67
68
|
env: Optional environment variables for the backend subprocess.
|
|
69
|
+
fast: Enable Codex fast mode. Defaults to normal mode.
|
|
68
70
|
|
|
69
71
|
Returns:
|
|
70
72
|
The agent's visible response text with reasoning traces removed.
|
|
71
73
|
"""
|
|
72
74
|
message, _thread_id, _usage = _run_agent(
|
|
73
|
-
prompt, cwd, None, yolo, flags, include_thinking, backend, env
|
|
75
|
+
prompt, cwd, None, yolo, flags, include_thinking, backend, env, fast
|
|
74
76
|
)
|
|
75
77
|
return message
|
|
76
78
|
|
|
@@ -103,6 +105,7 @@ class Agent:
|
|
|
103
105
|
include_thinking=False,
|
|
104
106
|
backend=None,
|
|
105
107
|
env=None,
|
|
108
|
+
fast=False,
|
|
106
109
|
):
|
|
107
110
|
"""Create a new session wrapper.
|
|
108
111
|
|
|
@@ -116,6 +119,7 @@ class Agent:
|
|
|
116
119
|
include_thinking: When true, return all agent messages joined together.
|
|
117
120
|
backend: Agent backend to use ("codex" or "cursor").
|
|
118
121
|
env: Optional environment variables for the backend subprocess.
|
|
122
|
+
fast: Enable Codex fast mode. Defaults to normal mode.
|
|
119
123
|
"""
|
|
120
124
|
self.cwd = cwd
|
|
121
125
|
self._yolo = yolo
|
|
@@ -125,6 +129,7 @@ class Agent:
|
|
|
125
129
|
self.thread_id = thread_id
|
|
126
130
|
self._backend = backend
|
|
127
131
|
self._env = env
|
|
132
|
+
self._fast = fast
|
|
128
133
|
self.last_usage = {}
|
|
129
134
|
|
|
130
135
|
def __call__(self, prompt):
|
|
@@ -140,6 +145,7 @@ class Agent:
|
|
|
140
145
|
self._include_thinking,
|
|
141
146
|
self._backend,
|
|
142
147
|
self._env,
|
|
148
|
+
self._fast,
|
|
143
149
|
)
|
|
144
150
|
if thread_id:
|
|
145
151
|
self.thread_id = thread_id
|
|
@@ -149,15 +155,25 @@ class Agent:
|
|
|
149
155
|
return message
|
|
150
156
|
|
|
151
157
|
|
|
152
|
-
def _run_agent(
|
|
158
|
+
def _run_agent(
|
|
159
|
+
prompt,
|
|
160
|
+
cwd,
|
|
161
|
+
thread_id,
|
|
162
|
+
yolo,
|
|
163
|
+
flags,
|
|
164
|
+
include_thinking,
|
|
165
|
+
backend,
|
|
166
|
+
env,
|
|
167
|
+
fast=False,
|
|
168
|
+
):
|
|
153
169
|
backend = _resolve_backend(backend)
|
|
154
170
|
_ensure_backend_available(backend, env)
|
|
155
171
|
if backend == "codex":
|
|
156
|
-
return _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env)
|
|
172
|
+
return _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env, fast)
|
|
157
173
|
return _run_cursor(prompt, cwd, thread_id, yolo, flags, include_thinking, env)
|
|
158
174
|
|
|
159
175
|
|
|
160
|
-
def _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env):
|
|
176
|
+
def _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env, fast=False):
|
|
161
177
|
"""Invoke the Codex CLI and return the message plus thread id (if any)."""
|
|
162
178
|
command = [
|
|
163
179
|
_CODEX_BIN,
|
|
@@ -171,6 +187,7 @@ def _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env):
|
|
|
171
187
|
command.append("--yolo")
|
|
172
188
|
else:
|
|
173
189
|
command.append("--full-auto")
|
|
190
|
+
command.extend(_codex_fast_config(fast))
|
|
174
191
|
if flags:
|
|
175
192
|
command.extend(shlex.split(flags))
|
|
176
193
|
if cwd:
|
|
@@ -198,6 +215,18 @@ def _run_codex(prompt, cwd, thread_id, yolo, flags, include_thinking, env):
|
|
|
198
215
|
return _parse_jsonl(result.stdout, include_thinking)
|
|
199
216
|
|
|
200
217
|
|
|
218
|
+
def _codex_fast_config(fast):
|
|
219
|
+
"""Return Codex config flags for normal or fast mode."""
|
|
220
|
+
if fast:
|
|
221
|
+
return [
|
|
222
|
+
"-c",
|
|
223
|
+
"service_tier=fast",
|
|
224
|
+
"-c",
|
|
225
|
+
"features.fast_mode=true",
|
|
226
|
+
]
|
|
227
|
+
return ["-c", "features.fast_mode=false"]
|
|
228
|
+
|
|
229
|
+
|
|
201
230
|
def _run_cursor(prompt, cwd, thread_id, yolo, flags, include_thinking, env):
|
|
202
231
|
"""Invoke the Cursor agent CLI and return the message plus session id (if any)."""
|
|
203
232
|
command = [
|
|
@@ -210,6 +210,7 @@ def start_agent(
|
|
|
210
210
|
home=None,
|
|
211
211
|
hostname=None,
|
|
212
212
|
now=None,
|
|
213
|
+
fast=False,
|
|
213
214
|
):
|
|
214
215
|
"""Create a durable agent and return its current snapshot."""
|
|
215
216
|
if not isinstance(prompt, str) or not prompt.strip():
|
|
@@ -250,6 +251,7 @@ def start_agent(
|
|
|
250
251
|
"backend": backend_name,
|
|
251
252
|
"yolo": bool(yolo),
|
|
252
253
|
"flags": flags or "",
|
|
254
|
+
"fast": bool(fast),
|
|
253
255
|
"cwd": cwd,
|
|
254
256
|
"env": session_env,
|
|
255
257
|
"pending_messages": [],
|
|
@@ -1053,15 +1055,27 @@ def _run_agent_turn(meta, session, prompt, runner=None):
|
|
|
1053
1055
|
raise TypeError("runner must return a dict")
|
|
1054
1056
|
return outcome
|
|
1055
1057
|
started = utc_now()
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1058
|
+
if session.get("fast", False):
|
|
1059
|
+
worker = Agent(
|
|
1060
|
+
session.get("cwd") or meta.get("cwd"),
|
|
1061
|
+
session.get("yolo", True),
|
|
1062
|
+
session.get("thread_id") or None,
|
|
1063
|
+
session.get("flags") or None,
|
|
1064
|
+
include_thinking=False,
|
|
1065
|
+
backend=session.get("backend") or None,
|
|
1066
|
+
env=_agent_env(meta, session),
|
|
1067
|
+
fast=True,
|
|
1068
|
+
)
|
|
1069
|
+
else:
|
|
1070
|
+
worker = Agent(
|
|
1071
|
+
session.get("cwd") or meta.get("cwd"),
|
|
1072
|
+
session.get("yolo", True),
|
|
1073
|
+
session.get("thread_id") or None,
|
|
1074
|
+
session.get("flags") or None,
|
|
1075
|
+
include_thinking=False,
|
|
1076
|
+
backend=session.get("backend") or None,
|
|
1077
|
+
env=_agent_env(meta, session),
|
|
1078
|
+
)
|
|
1065
1079
|
message = worker(prompt)
|
|
1066
1080
|
usage = worker.last_usage or {}
|
|
1067
1081
|
rollout_path = ""
|
|
@@ -13,6 +13,7 @@ import uuid
|
|
|
13
13
|
from .agent import (
|
|
14
14
|
_CODEX_BIN,
|
|
15
15
|
_CURSOR_BIN,
|
|
16
|
+
_codex_fast_config,
|
|
16
17
|
_ensure_backend_available,
|
|
17
18
|
_event_usage,
|
|
18
19
|
_merged_env,
|
|
@@ -48,6 +49,7 @@ class AsyncAgent:
|
|
|
48
49
|
self._lock = threading.Lock()
|
|
49
50
|
self._stdout_lines: list[str] = []
|
|
50
51
|
self._stderr_lines: list[str] = []
|
|
52
|
+
self._errors: list[str] = []
|
|
51
53
|
self._messages: list[str] = []
|
|
52
54
|
self._thread_id = ""
|
|
53
55
|
self._rollout_path = ""
|
|
@@ -85,6 +87,7 @@ class AsyncAgent:
|
|
|
85
87
|
backend=None,
|
|
86
88
|
env=None,
|
|
87
89
|
name=None,
|
|
90
|
+
fast=False,
|
|
88
91
|
):
|
|
89
92
|
"""Start a backend subprocess and return an async handle immediately."""
|
|
90
93
|
if not isinstance(prompt, str) or not prompt.strip():
|
|
@@ -92,7 +95,7 @@ class AsyncAgent:
|
|
|
92
95
|
|
|
93
96
|
backend = _resolve_backend(backend)
|
|
94
97
|
_ensure_backend_available(backend, env)
|
|
95
|
-
command = _build_command(backend, cwd, yolo, flags)
|
|
98
|
+
command = _build_command(backend, cwd, yolo, flags, fast)
|
|
96
99
|
process = subprocess.Popen(
|
|
97
100
|
command,
|
|
98
101
|
stdin=subprocess.PIPE,
|
|
@@ -157,6 +160,7 @@ class AsyncAgent:
|
|
|
157
160
|
progress = list(self._progress)
|
|
158
161
|
tools = list(self._tools) if include_actions else []
|
|
159
162
|
stderr_lines = list(self._stderr_lines)
|
|
163
|
+
error_lines = list(self._errors)
|
|
160
164
|
thread_id = self._thread_id
|
|
161
165
|
rollout_path = self._rollout_path
|
|
162
166
|
last_event_at = self._last_event_at
|
|
@@ -168,7 +172,9 @@ class AsyncAgent:
|
|
|
168
172
|
progress=progress,
|
|
169
173
|
final_output=final_output,
|
|
170
174
|
stderr_lines=stderr_lines,
|
|
175
|
+
error_lines=error_lines,
|
|
171
176
|
)
|
|
177
|
+
last_error = error_lines[-1] if error_lines else stderr_lines[-1] if stderr_lines else ""
|
|
172
178
|
return {
|
|
173
179
|
"id": self.id,
|
|
174
180
|
"name": self.name,
|
|
@@ -184,8 +190,9 @@ class AsyncAgent:
|
|
|
184
190
|
"final_output": final_output,
|
|
185
191
|
"last_event_at": last_event_at,
|
|
186
192
|
"returncode": returncode,
|
|
187
|
-
"last_error":
|
|
193
|
+
"last_error": last_error,
|
|
188
194
|
"stderr": "\n".join(stderr_lines),
|
|
195
|
+
"errors": error_lines,
|
|
189
196
|
"messages": messages,
|
|
190
197
|
"usage": last_usage,
|
|
191
198
|
}
|
|
@@ -310,6 +317,16 @@ class AsyncAgent:
|
|
|
310
317
|
text = item.get("text")
|
|
311
318
|
if isinstance(text, str):
|
|
312
319
|
self._messages.append(text)
|
|
320
|
+
elif event.get("type") == "error":
|
|
321
|
+
message = event.get("message")
|
|
322
|
+
if isinstance(message, str) and message.strip():
|
|
323
|
+
self._errors.append(message.strip())
|
|
324
|
+
elif event.get("type") == "turn.failed":
|
|
325
|
+
error = event.get("error") or {}
|
|
326
|
+
if isinstance(error, dict):
|
|
327
|
+
message = error.get("message")
|
|
328
|
+
if isinstance(message, str) and message.strip():
|
|
329
|
+
self._errors.append(message.strip())
|
|
313
330
|
|
|
314
331
|
def _refresh_rollout(self) -> None:
|
|
315
332
|
if self.backend != "codex":
|
|
@@ -359,13 +376,13 @@ class AsyncAgent:
|
|
|
359
376
|
return self._rollout_final_output
|
|
360
377
|
|
|
361
378
|
|
|
362
|
-
def _build_command(backend, cwd, yolo, flags):
|
|
379
|
+
def _build_command(backend, cwd, yolo, flags, fast=False):
|
|
363
380
|
if backend == "codex":
|
|
364
|
-
return _build_codex_command(cwd, yolo, flags)
|
|
381
|
+
return _build_codex_command(cwd, yolo, flags, fast)
|
|
365
382
|
return _build_cursor_command(cwd, yolo, flags)
|
|
366
383
|
|
|
367
384
|
|
|
368
|
-
def _build_codex_command(cwd, yolo, flags):
|
|
385
|
+
def _build_codex_command(cwd, yolo, flags, fast=False):
|
|
369
386
|
command = [
|
|
370
387
|
_CODEX_BIN,
|
|
371
388
|
"exec",
|
|
@@ -378,6 +395,7 @@ def _build_codex_command(cwd, yolo, flags):
|
|
|
378
395
|
command.append("--yolo")
|
|
379
396
|
else:
|
|
380
397
|
command.append("--full-auto")
|
|
398
|
+
command.extend(_codex_fast_config(fast))
|
|
381
399
|
if flags:
|
|
382
400
|
command.extend(shlex.split(flags))
|
|
383
401
|
if cwd:
|
|
@@ -425,9 +443,11 @@ def _status_text(returncode, canceled):
|
|
|
425
443
|
return "error"
|
|
426
444
|
|
|
427
445
|
|
|
428
|
-
def _activity_text(status, progress, final_output, stderr_lines):
|
|
446
|
+
def _activity_text(status, progress, final_output, stderr_lines, error_lines=None):
|
|
429
447
|
if progress:
|
|
430
448
|
return progress[-1]
|
|
449
|
+
if status == "error" and error_lines:
|
|
450
|
+
return error_lines[-1]
|
|
431
451
|
if status == "error" and stderr_lines:
|
|
432
452
|
return stderr_lines[-1]
|
|
433
453
|
if final_output:
|