imbue-mngr-codex 0.1.0__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.
- imbue_mngr_codex-0.1.0/.gitignore +359 -0
- imbue_mngr_codex-0.1.0/CHANGELOG.md +16 -0
- imbue_mngr_codex-0.1.0/PKG-INFO +177 -0
- imbue_mngr_codex-0.1.0/README.md +169 -0
- imbue_mngr_codex-0.1.0/UNABRIDGED_CHANGELOG.md +45 -0
- imbue_mngr_codex-0.1.0/changelog/.gitkeep +0 -0
- imbue_mngr_codex-0.1.0/conftest.py +21 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/__init__.py +0 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/codex_config.py +531 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/codex_config_test.py +331 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/conftest.py +35 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/plugin.py +791 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/plugin_test.py +596 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/__init__.py +0 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/clear_active_marker.sh +70 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/clear_active_marker_test.py +259 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/codex_background_tasks.sh +104 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/codex_marker_state.sh +103 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/common_transcript.sh +295 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/common_transcript_test.py +324 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/set_active_marker.sh +96 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/set_active_marker_test.py +177 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/stream_transcript.sh +190 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/stream_transcript_test.py +204 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/subagent_started.sh +43 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/subagent_started_test.py +94 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/subagent_stopped.sh +40 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/subagent_stopped_test.py +117 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/resources/testing.py +59 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/test_codex_agent_e2e.py +132 -0
- imbue_mngr_codex-0.1.0/imbue/mngr_codex/test_ratchets.py +278 -0
- imbue_mngr_codex-0.1.0/pyproject.toml +69 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
**/__pycache__/
|
|
3
|
+
**/*.py[codz]
|
|
4
|
+
**/*$py.class
|
|
5
|
+
|
|
6
|
+
# macOS Finder metadata
|
|
7
|
+
**/.DS_Store
|
|
8
|
+
|
|
9
|
+
# C extensions
|
|
10
|
+
**/*.so
|
|
11
|
+
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
**/.Python
|
|
14
|
+
**/build/
|
|
15
|
+
**/develop-eggs/
|
|
16
|
+
**/dist/
|
|
17
|
+
**/downloads/
|
|
18
|
+
**/eggs/
|
|
19
|
+
**/.eggs/
|
|
20
|
+
**/lib/
|
|
21
|
+
**/lib64/
|
|
22
|
+
**/parts/
|
|
23
|
+
**/sdist/
|
|
24
|
+
**/var/
|
|
25
|
+
**/wheels/
|
|
26
|
+
**/share/python-wheels/
|
|
27
|
+
**/*.egg-info/
|
|
28
|
+
**/.installed.cfg
|
|
29
|
+
**/*.egg
|
|
30
|
+
**/MANIFEST
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
**/*.manifest
|
|
36
|
+
**/*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
**/pip-log.txt
|
|
40
|
+
**/pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
**/htmlcov/
|
|
44
|
+
**/.tox/
|
|
45
|
+
**/.nox/
|
|
46
|
+
**/.coverage
|
|
47
|
+
**/.coverage.*
|
|
48
|
+
**/.cache
|
|
49
|
+
**/nosetests.xml
|
|
50
|
+
**/coverage.xml
|
|
51
|
+
**/*.cover
|
|
52
|
+
**/*.py.cover
|
|
53
|
+
**/.hypothesis/
|
|
54
|
+
**/.pytest_cache/
|
|
55
|
+
**/cover/
|
|
56
|
+
|
|
57
|
+
# Translations
|
|
58
|
+
**/*.mo
|
|
59
|
+
**/*.pot
|
|
60
|
+
|
|
61
|
+
# Django stuff:
|
|
62
|
+
**/*.log
|
|
63
|
+
**/local_settings.py
|
|
64
|
+
**/db.sqlite3
|
|
65
|
+
**/db.sqlite3-journal
|
|
66
|
+
|
|
67
|
+
# Flask stuff:
|
|
68
|
+
**/instance/
|
|
69
|
+
**/.webassets-cache
|
|
70
|
+
|
|
71
|
+
# Scrapy stuff:
|
|
72
|
+
**/.scrapy
|
|
73
|
+
|
|
74
|
+
# Sphinx documentation
|
|
75
|
+
**/docs/_build/
|
|
76
|
+
|
|
77
|
+
# PyBuilder
|
|
78
|
+
**/.pybuilder/
|
|
79
|
+
**/target/
|
|
80
|
+
|
|
81
|
+
# Jupyter Notebook
|
|
82
|
+
**/.ipynb_checkpoints
|
|
83
|
+
|
|
84
|
+
# IPython
|
|
85
|
+
**/profile_default/
|
|
86
|
+
**/ipython_config.py
|
|
87
|
+
|
|
88
|
+
# pyenv
|
|
89
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
90
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
91
|
+
# .python-version
|
|
92
|
+
|
|
93
|
+
# pipenv
|
|
94
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
95
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
96
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
97
|
+
# install all needed dependencies.
|
|
98
|
+
#Pipfile.lock
|
|
99
|
+
|
|
100
|
+
# UV
|
|
101
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
102
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
103
|
+
# commonly ignored for libraries.
|
|
104
|
+
#uv.lock
|
|
105
|
+
|
|
106
|
+
# poetry
|
|
107
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
108
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
109
|
+
# commonly ignored for libraries.
|
|
110
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
111
|
+
#poetry.lock
|
|
112
|
+
#poetry.toml
|
|
113
|
+
|
|
114
|
+
# pdm
|
|
115
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
116
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
117
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
118
|
+
#pdm.lock
|
|
119
|
+
#pdm.toml
|
|
120
|
+
**/.pdm-python
|
|
121
|
+
**/.pdm-build/
|
|
122
|
+
|
|
123
|
+
# pixi
|
|
124
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
125
|
+
#pixi.lock
|
|
126
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
127
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
128
|
+
**/.pixi
|
|
129
|
+
|
|
130
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
131
|
+
**/__pypackages__/
|
|
132
|
+
|
|
133
|
+
# Celery stuff
|
|
134
|
+
**/celerybeat-schedule
|
|
135
|
+
**/celerybeat.pid
|
|
136
|
+
|
|
137
|
+
# SageMath parsed files
|
|
138
|
+
**/*.sage.py
|
|
139
|
+
|
|
140
|
+
# Environments
|
|
141
|
+
**/.env
|
|
142
|
+
**/.envrc
|
|
143
|
+
**/.venv
|
|
144
|
+
**/.venv-*
|
|
145
|
+
**/env/
|
|
146
|
+
**/venv/
|
|
147
|
+
**/ENV/
|
|
148
|
+
**/env.bak/
|
|
149
|
+
**/venv.bak/
|
|
150
|
+
|
|
151
|
+
# Spyder project settings
|
|
152
|
+
**/.spyderproject
|
|
153
|
+
**/.spyproject
|
|
154
|
+
|
|
155
|
+
# Rope project settings
|
|
156
|
+
**/.ropeproject
|
|
157
|
+
|
|
158
|
+
# mkdocs documentation
|
|
159
|
+
**/site
|
|
160
|
+
|
|
161
|
+
# mypy
|
|
162
|
+
**/.mypy_cache/
|
|
163
|
+
**/.dmypy.json
|
|
164
|
+
**/dmypy.json
|
|
165
|
+
|
|
166
|
+
# Pyre type checker
|
|
167
|
+
**/.pyre/
|
|
168
|
+
|
|
169
|
+
# pytype static type analyzer
|
|
170
|
+
**/.pytype/
|
|
171
|
+
|
|
172
|
+
# Cython debug symbols
|
|
173
|
+
**/cython_debug/
|
|
174
|
+
|
|
175
|
+
# PyCharm
|
|
176
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
177
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
178
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
179
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
180
|
+
**/.idea/
|
|
181
|
+
|
|
182
|
+
# Abstra
|
|
183
|
+
# Abstra is an AI-powered process automation framework.
|
|
184
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
185
|
+
# Learn more at https://abstra.io/docs
|
|
186
|
+
**/.abstra/
|
|
187
|
+
|
|
188
|
+
# Visual Studio Code
|
|
189
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
190
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
191
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
192
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
193
|
+
# .vscode/
|
|
194
|
+
|
|
195
|
+
# Ruff stuff:
|
|
196
|
+
**/.ruff_cache/
|
|
197
|
+
|
|
198
|
+
# PyPI configuration file
|
|
199
|
+
**/.pypirc
|
|
200
|
+
|
|
201
|
+
# Cursor
|
|
202
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
203
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
204
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
205
|
+
**/.cursorignore
|
|
206
|
+
**/.cursorindexingignore
|
|
207
|
+
|
|
208
|
+
# Marimo
|
|
209
|
+
**/marimo/_static/
|
|
210
|
+
**/marimo/_lsp/
|
|
211
|
+
**/__marimo__/
|
|
212
|
+
|
|
213
|
+
# task folders for local custom claude workflow (at any depth, incl. the
|
|
214
|
+
# root-level `dev` project's `dev/_tasks/`, which `*/*/_tasks/` missed)
|
|
215
|
+
**/_tasks/
|
|
216
|
+
**/.sesskey
|
|
217
|
+
|
|
218
|
+
# Node.js
|
|
219
|
+
**/node_modules/
|
|
220
|
+
|
|
221
|
+
# Frontend build artifacts
|
|
222
|
+
**/frontend-dist/
|
|
223
|
+
|
|
224
|
+
# Claude Code local settings (session-specific permissions)
|
|
225
|
+
**/.claude/settings.local.json
|
|
226
|
+
|
|
227
|
+
# Local Claude settings backup files
|
|
228
|
+
**/.claude/*.bak
|
|
229
|
+
|
|
230
|
+
# Claude worktress
|
|
231
|
+
**/.claude/worktrees
|
|
232
|
+
|
|
233
|
+
# Agent definitions deployed by mngr_subagent_proxy at session start
|
|
234
|
+
**/.claude/agents/
|
|
235
|
+
|
|
236
|
+
# Local mngr settings (not committed)
|
|
237
|
+
**/.mngr/settings.local.toml
|
|
238
|
+
|
|
239
|
+
# Local working / scratch markdown (not committed)
|
|
240
|
+
**/*.local.md
|
|
241
|
+
|
|
242
|
+
# Local working / scratch shell scripts (not committed)
|
|
243
|
+
# (covers user notification scripts like scripts/notify_user.local.sh, too)
|
|
244
|
+
**/*.local.sh
|
|
245
|
+
|
|
246
|
+
# Local-only throwaway scripts (e.g. one-off test harnesses).
|
|
247
|
+
**/scripts/*.local.sh
|
|
248
|
+
|
|
249
|
+
# Test output files (slow tests, coverage summaries)
|
|
250
|
+
**/.test_output/
|
|
251
|
+
|
|
252
|
+
# TMR output directories (reports + test outputs)
|
|
253
|
+
**/tmr_*/
|
|
254
|
+
**/tmr-report/
|
|
255
|
+
|
|
256
|
+
# Active session marker file (used to detect interrupted sessions)
|
|
257
|
+
**/.claude/active
|
|
258
|
+
|
|
259
|
+
# we stick the image build artifacts here
|
|
260
|
+
**/.mngr/dev/build/
|
|
261
|
+
**/.mngr/dev/secrets/
|
|
262
|
+
|
|
263
|
+
# Offload caches and local files
|
|
264
|
+
**/.offload/**
|
|
265
|
+
**/test-results
|
|
266
|
+
|
|
267
|
+
# Minds deploy-time build artifacts.
|
|
268
|
+
# Ignore contents so we can un-ignore the committed `template/` subtree: git
|
|
269
|
+
# won't descend into a fully-ignored directory, so negations must live below
|
|
270
|
+
# the contents pattern rather than below the directory pattern.
|
|
271
|
+
**/.minds/*
|
|
272
|
+
# The template directory is committed: it defines the expected keys for each
|
|
273
|
+
# <service>.sh file, with empty values. `scripts/push_modal_secrets.py` uses
|
|
274
|
+
# it to check that per-env .sh files declare every template key.
|
|
275
|
+
!/.minds/template/
|
|
276
|
+
!/.minds/template/**
|
|
277
|
+
# Vault ACL policies for the minds tiers. The HCL is non-sensitive and is
|
|
278
|
+
# the source of truth for the policies pushed to Vault via
|
|
279
|
+
# `vault policy write <name> .minds/policies/<name>.hcl`.
|
|
280
|
+
!/.minds/policies/
|
|
281
|
+
!/.minds/policies/**
|
|
282
|
+
|
|
283
|
+
# Autofix session artifacts
|
|
284
|
+
**/.autofix/
|
|
285
|
+
**/.reviewer/logs/
|
|
286
|
+
**/.reviewer/outputs/
|
|
287
|
+
**/.reviewer/settings.local.json
|
|
288
|
+
**/.reviewer/.stop_hook_consecutive_blocks
|
|
289
|
+
**/.reviewer/conversation-issues.jsonl
|
|
290
|
+
**/.reviews/
|
|
291
|
+
|
|
292
|
+
# Stuck agent tracking (stop hook escape valve)
|
|
293
|
+
**/.claude/blocked_stop_commits
|
|
294
|
+
|
|
295
|
+
# Scheduled tasks lock file
|
|
296
|
+
**/.claude/scheduled_tasks.lock
|
|
297
|
+
|
|
298
|
+
# Demo recordings (asciinema .cast, .txt, and scripts)
|
|
299
|
+
**/.demos/
|
|
300
|
+
|
|
301
|
+
# for git worktrees from other repos
|
|
302
|
+
**/.external_worktrees/
|
|
303
|
+
|
|
304
|
+
# ignore coverage files generated within subprojects
|
|
305
|
+
**/cov.xml
|
|
306
|
+
|
|
307
|
+
# ignore demos
|
|
308
|
+
**/recordings
|
|
309
|
+
apps/minds_workspace_server/package-lock.json
|
|
310
|
+
**/*.local.md
|
|
311
|
+
|
|
312
|
+
# Generated by the _generate-dockerignore justfile recipe before each
|
|
313
|
+
# test-offload* run. The recipe strips this self-reference so offload's
|
|
314
|
+
# copy_untracked_files ships the generated file into the build context.
|
|
315
|
+
/.dockerignore
|
|
316
|
+
|
|
317
|
+
# Transient offload image-cache marker written by test-offload runs; not
|
|
318
|
+
# checked in (unlike the committed .offload-*-cache-key files which pin CI
|
|
319
|
+
# image versions).
|
|
320
|
+
/.offload-image-cache
|
|
321
|
+
|
|
322
|
+
# Generated by _generate-release-dockerfile from Dockerfile + .release.extras.
|
|
323
|
+
/libs/mngr/imbue/mngr/resources/Dockerfile.release
|
|
324
|
+
**/.reviewer/autofix/issues/
|
|
325
|
+
.reviewer/logs/
|
|
326
|
+
|
|
327
|
+
# Tailwind Play CDN JS for the minds desktop client. Fetched once via
|
|
328
|
+
# `just minds-tailwind` (plain curl, no build) and shipped with the
|
|
329
|
+
# distributable. Not checked in because it's a ~300KB blob we can always
|
|
330
|
+
# re-fetch.
|
|
331
|
+
/apps/minds/imbue/minds/desktop_client/static/tailwind.js
|
|
332
|
+
|
|
333
|
+
# macOS Finder metadata
|
|
334
|
+
**/.DS_Store
|
|
335
|
+
**/.env.swp
|
|
336
|
+
# Vim swap files for any file (`.foo.swp`, `.foo.swo`, etc.) -- generated
|
|
337
|
+
# while a file is open in vim. Never checked in.
|
|
338
|
+
**/.*.sw[a-p]
|
|
339
|
+
|
|
340
|
+
# `minds env deploy` writes a recover-target file at the monorepo root
|
|
341
|
+
# on failed deploys; `minds env recover` deletes it after rolling back.
|
|
342
|
+
# Never checked in. Per-env naming
|
|
343
|
+
# (``.minds-deploy-recover-target-<env-name>.json``) means each in-flight
|
|
344
|
+
# deploy has its own file, so concurrent deploys against different envs
|
|
345
|
+
# don't trip over each other.
|
|
346
|
+
**/.minds-deploy-*.json
|
|
347
|
+
# Per-env deploy lock files (kernel-level ``flock`` targets). Created
|
|
348
|
+
# by ``hold_deploy_lock`` in ``apps/minds/imbue/minds/envs/recover.py``
|
|
349
|
+
# and held for the entire duration of ``minds env deploy`` /
|
|
350
|
+
# ``minds env recover`` so two concurrent invocations against the same
|
|
351
|
+
# env serialize. The file itself is empty and cheap to leave around.
|
|
352
|
+
**/.minds-deploy-lock-*.lock
|
|
353
|
+
**/.antigravitycli/
|
|
354
|
+
|
|
355
|
+
# Playwright MCP scratch artifacts (mock screenshots, page snapshots)
|
|
356
|
+
**/.playwright-mcp/
|
|
357
|
+
|
|
358
|
+
# tmr (task-runner) orchestration scratch report
|
|
359
|
+
**/tmr-report/
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog - mngr_codex
|
|
2
|
+
|
|
3
|
+
A concise, human-friendly summary of changes for the `mngr_codex` library. Entries are categorized using the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) categories: Added, Changed, Deprecated, Removed, Fixed, Security.
|
|
4
|
+
|
|
5
|
+
For the full, unedited changelog entries, see [UNABRIDGED_CHANGELOG.md](UNABRIDGED_CHANGELOG.md).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [v0.1.0] - 2026-06-13
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added: real `codex` agent-type support as its own plugin (`imbue-mngr-codex`), wiring OpenAI's Codex CLI into mngr and replacing the previous in-core `BaseAgent` stub. Each agent runs under its own per-agent `CODEX_HOME` for isolated config, sessions, and transcripts, while sharing authentication through a write-through `auth.json` symlink so logging in once authenticates every agent. Codex agents report RUNNING while working and WAITING when idle via four hooks (`UserPromptSubmit`/`Stop`/`SubagentStart`/`SubagentStop`); because codex subagents run asynchronously, the `active` marker is recomputed under a lock from a root-turn flag plus one file per in-flight subagent so it stays RUNNING until the root turn AND every subagent are done. Includes conversation resume across stop/start (root `session_id` captured to a tracking file; `mngr start` shell-evaluates `codex resume <id>`), common transcripts readable by `mngr transcript`, and seeded trust/onboarding for a silent first launch.
|
|
14
|
+
- Added: `send_message` blocks until submission registers — the `UserPromptSubmit` hook signals a `mngr-submit-<session>` tmux wait-for channel after it sets the active marker, so `mngr message` returns only once the agent reads RUNNING (closes a race where a follow-up lifecycle check could see the pre-turn idle state).
|
|
15
|
+
- Added: Update handling — codex's blocking startup "Update available!" prompt is disabled, and mngr surfaces updates itself at provision by comparing `codex --version` to `~/.codex/version.json`. A single `update_policy` setting governs action (default `ASK`): `AUTO` runs `codex update` silently, `ASK` prompts on an attended local run (interactive tty + local host) and otherwise logs a non-blocking notice, and `NEVER` only logs the notice.
|
|
16
|
+
- Added: Conformance test asserting codex's emitted common-transcript records validate against the canonical envelope schema (`imbue.mngr.agents.common_transcript_records`); release test now runs on the shared agent release-lifecycle harness (`imbue.mngr.agents.agent_release_testing`) against the real codex binary, including stop/start resume.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: imbue-mngr-codex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Codex agent type plugin for mngr
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: imbue-mngr==0.2.13
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# imbue-mngr-codex
|
|
10
|
+
|
|
11
|
+
The `codex` agent-type plugin for [`mngr`](https://pypi.org/project/imbue-mngr/): real
|
|
12
|
+
support for the OpenAI Codex CLI (the Rust `codex` binary) as a first-class mngr agent,
|
|
13
|
+
on par with the `claude` and `antigravity` agent types.
|
|
14
|
+
|
|
15
|
+
`mngr create my-task codex` launches an interactive Codex TUI agent that mngr can monitor
|
|
16
|
+
(RUNNING/WAITING), message, transcript, stop, resume, and isolate per agent.
|
|
17
|
+
|
|
18
|
+
## How it works
|
|
19
|
+
|
|
20
|
+
See `specs/agent-plugin-parity/codex-investigation.md` in the monorepo for the full,
|
|
21
|
+
source-verified investigation behind each decision.
|
|
22
|
+
|
|
23
|
+
- **Per-agent isolation via `CODEX_HOME`.** Codex resolves its whole
|
|
24
|
+
config/auth/session/hook tree from `CODEX_HOME` (default `~/.codex`). Each agent gets its
|
|
25
|
+
own `CODEX_HOME` under the agent state dir, injected only on the codex process
|
|
26
|
+
(`env CODEX_HOME=...`), leaving the user's real `$HOME` untouched. codex accepts the
|
|
27
|
+
dotted `~/.mngr/...` cwd, so there is no workspace symlink either.
|
|
28
|
+
- **Shared auth.** The per-agent `auth.json` is a symlink to the user's shared
|
|
29
|
+
`~/.codex/auth.json`. Codex writes that file in place and reloads-before-refreshing, so
|
|
30
|
+
one login authenticates every agent and token refreshes propagate. `config.toml` pins
|
|
31
|
+
`cli_auth_credentials_store = "file"` so codex never falls back to a keyring entry keyed
|
|
32
|
+
by the per-agent `CODEX_HOME` path (which would defeat sharing).
|
|
33
|
+
- **Lifecycle marker (RUNNING/WAITING), subagent-aware.** Codex subagents (the multi-agent
|
|
34
|
+
`spawn_agent` feature) run *asynchronously* -- the root agent's `Stop` hook fires while
|
|
35
|
+
subagents are still running, with no `fullyIdle` signal. So mngr does not just clear the
|
|
36
|
+
marker on `Stop`; it recomputes an `active` marker that is present while either the root
|
|
37
|
+
turn is running (`codex_root_active`, set on `UserPromptSubmit`, cleared on the root
|
|
38
|
+
`Stop`) or any subagent is in flight (one file per `agent_id` under `codex_subagents/`,
|
|
39
|
+
maintained by the `SubagentStart`/`SubagentStop` hooks). The recompute runs under a portable
|
|
40
|
+
`mkdir` lock so a concurrent root `Stop` and final `SubagentStop` can't strand it. A
|
|
41
|
+
recorded root `session_id` guards against a nested `codex` process sharing the same
|
|
42
|
+
`CODEX_HOME`. (Backgrounded OS processes the agent launches are not tracked -- codex emits
|
|
43
|
+
no hook for them.)
|
|
44
|
+
- **Conversation resume.** `mngr stop` then `mngr start` resumes the prior conversation: the
|
|
45
|
+
hook records the root `session_id`, and the launch command shell-evaluates
|
|
46
|
+
`codex resume <id>` (codex's session JSONL survives the hard kill `mngr stop` performs).
|
|
47
|
+
- **Transcripts.** The native rollout JSONL is streamed verbatim to the raw transcript and
|
|
48
|
+
converted into mngr's agent-agnostic common transcript that `mngr transcript` reads.
|
|
49
|
+
- **Trust & hook bypass (consent-gated).** mngr seeds the work dir as a trusted project to
|
|
50
|
+
skip codex's folder-trust dialog, and passes `--dangerously-bypass-hook-trust` so its own
|
|
51
|
+
lifecycle hooks run. Because trusting the workspace also lets codex load repo-local
|
|
52
|
+
`.codex/hooks.json`, that bypass is consent-gated together with workspace trust: mngr
|
|
53
|
+
prompts before trusting (or use `mngr create --yes` / `auto_dismiss_dialogs = true`).
|
|
54
|
+
|
|
55
|
+
## Configuration
|
|
56
|
+
|
|
57
|
+
Set fields under an `[agent_types.codex]` table in your mngr config, or pass overrides.
|
|
58
|
+
|
|
59
|
+
- `model` — model slug to pin (e.g. `"gpt-5.5"`). Default: unset (codex's own default).
|
|
60
|
+
- `model_reasoning_effort` — `none|minimal|low|medium|high|xhigh`. Default: unset.
|
|
61
|
+
- `sandbox_mode` — `read-only|workspace-write|danger-full-access`. Default: `workspace-write`.
|
|
62
|
+
- `auto_allow_permissions` — when `true`, sets `approval_policy = "never"` so codex never
|
|
63
|
+
prompts for tool approval (the sandbox still applies). Default: `false`.
|
|
64
|
+
- `config_overrides` — free-form key/values merged last into the per-agent `config.toml`.
|
|
65
|
+
- `auto_dismiss_dialogs` — when `true`, trust the repo and allow the hook bypass without
|
|
66
|
+
prompting. Default: `false`.
|
|
67
|
+
- `update_policy` — how mngr handles an outdated codex CLI at provision (see "Updates" below):
|
|
68
|
+
`AUTO` (run `codex update`, no prompt), `ASK` (prompt on an attended local run, else just
|
|
69
|
+
notify), or `NEVER` (only notify). Default: `ASK`.
|
|
70
|
+
- `emit_common_transcript` — emit the common-schema transcript. Default: `true`.
|
|
71
|
+
|
|
72
|
+
### Updates
|
|
73
|
+
|
|
74
|
+
mngr pins `check_for_update_on_startup = false` in the per-agent `config.toml`, because codex's
|
|
75
|
+
own "Update available!" prompt is **blocking** and would intercept the first message mngr sends
|
|
76
|
+
(an Enter could even select "Update now"). mngr surfaces updates itself instead: at provision it
|
|
77
|
+
compares `codex --version` against the `latest_version` codex last recorded in its own
|
|
78
|
+
`~/.codex/version.json` (no network call — codex refreshes that file on its own throttled
|
|
79
|
+
schedule during your normal codex use). The check always runs and is best-effort: any probe or
|
|
80
|
+
parse failure is swallowed (debug-logged) and never blocks agent creation. When codex is outdated,
|
|
81
|
+
the action is governed by `update_policy`: `AUTO` runs `codex update`; `ASK` (the default) prompts
|
|
82
|
+
to update now only on an *attended* run — a local host driven from an interactive terminal, and
|
|
83
|
+
not `--yes` — otherwise it logs a non-blocking notice (so an unattended remote/deploy agent
|
|
84
|
+
defaults to neither prompting nor upgrading the remote's global install); `NEVER` only logs the
|
|
85
|
+
notice. `codex update` self-detects the install method (it runs `brew upgrade --cask codex` for a
|
|
86
|
+
brew install, `npm i -g` for npm, the curl installer for standalone), so mngr needs no per-method
|
|
87
|
+
logic. Updating is optional — an outdated codex still runs — so a declined prompt, a `NEVER`
|
|
88
|
+
policy, or a non-interactive run never blocks agent creation, and `--yes` does **not** trigger a
|
|
89
|
+
global upgrade (only the explicit `AUTO` policy does).
|
|
90
|
+
|
|
91
|
+
### Model note
|
|
92
|
+
|
|
93
|
+
Codex picks the account's default model, and a **ChatGPT-account login rejects some
|
|
94
|
+
`*-codex` model slugs** (e.g. `gpt-5.2-codex`) with a 400 "model is not supported when using
|
|
95
|
+
Codex with a ChatGPT account". Two distinct things cause this:
|
|
96
|
+
|
|
97
|
+
- **Deprecation:** `gpt-5.2` / `gpt-5.2-codex` / `gpt-5.3-codex` have been sunset for ChatGPT
|
|
98
|
+
subscriptions (OpenAI's announcement points those users to the API). These fail on a ChatGPT
|
|
99
|
+
plan in *every* mode, including the TUI.
|
|
100
|
+
- **Run-mode entitlement:** the backend gates some `*-codex` models by the `originator` HTTP
|
|
101
|
+
header (i.e. the client identity). The interactive TUI presents as `codex-tui` and is
|
|
102
|
+
allowed; `codex exec` presents as `codex_exec` and is denied. (See the app-server note below
|
|
103
|
+
for why this matters and why we do *not* spoof the TUI identity.)
|
|
104
|
+
|
|
105
|
+
If your agent errors on the first message with the "not supported" 400, set `model` to a model
|
|
106
|
+
your account supports (e.g. `"gpt-5.5"`), or authenticate with an API key (which carries the
|
|
107
|
+
full model entitlement).
|
|
108
|
+
|
|
109
|
+
## Not yet implemented
|
|
110
|
+
|
|
111
|
+
Relative to `mngr_claude`, these are not yet ported (tracked for follow-up): session
|
|
112
|
+
preservation on destroy, deploy/scheduling contributions, field generators (`waiting_reason`),
|
|
113
|
+
the streaming snapshot, and installation/version management.
|
|
114
|
+
|
|
115
|
+
## Future direction: an app-server-backed agent variant
|
|
116
|
+
|
|
117
|
+
This agent drives the codex **TUI** by `tmux send-keys` (paste + Enter), with banner-poll
|
|
118
|
+
readiness. That works, but it's fragile (screen-scraping) and codex's `SessionStart` fires
|
|
119
|
+
lazily, so there's no clean pre-input readiness signal. Codex offers a much cleaner surface to
|
|
120
|
+
drive programmatically -- the **app-server** -- and a second agent type built on it is a planned
|
|
121
|
+
follow-up (mirroring `mngr_claude`'s `claude` + `headless_claude` split).
|
|
122
|
+
|
|
123
|
+
We built the TUI agent **first**, though, for a concrete reason: like `claude -p`, the app-server
|
|
124
|
+
does not have full feature parity with the interactive TUI on a ChatGPT-subscription login. The
|
|
125
|
+
backend gates some `*-codex` models on the **client identity** (the `originator`, derived from the
|
|
126
|
+
app-server's `initialize` `clientInfo.name`) -- the first-party TUI presents as `codex-tui` and is
|
|
127
|
+
entitled to them; a programmatic app-server client identifying honestly as mngr is not. The only
|
|
128
|
+
way to close that gap is to spoof the TUI identity, which OpenAI's terms disallow (see "client
|
|
129
|
+
identity" below). So the TUI agent is how you get full `*-codex` model access on a ChatGPT login
|
|
130
|
+
today, and the app-server variant is a *complement* for the cases where the identity gap is
|
|
131
|
+
acceptable (API-key auth, which carries the full entitlement; or only models the honest identity
|
|
132
|
+
already gets) -- not a replacement.
|
|
133
|
+
|
|
134
|
+
### What it would give us
|
|
135
|
+
- **Programmatic messaging instead of tmux paste.** `codex app-server` speaks a JSON-RPC
|
|
136
|
+
protocol over a socket; you send a turn with `initialize` -> `thread/start` -> `turn/start`.
|
|
137
|
+
No `send-keys`, no paste-visibility polling.
|
|
138
|
+
- **You can still view it in the TUI.** Launch the TUI as a *viewer* with
|
|
139
|
+
`codex --remote unix://<sock>` (accepts `ws://`, `wss://`, `unix://` too) connected to the
|
|
140
|
+
app-server -- so it runs in tmux and you watch it live, but mngr drives it over the socket.
|
|
141
|
+
- **Clean synchronous readiness.** The `initialize` response / `thread.started` event is an
|
|
142
|
+
unambiguous "ready for input" signal -- it eliminates the lazy-`SessionStart` banner-poll
|
|
143
|
+
workaround entirely.
|
|
144
|
+
- **Cleaner lifecycle/transcript.** `turn.started` / `turn.completed` / `item.*` events could
|
|
145
|
+
drive the RUNNING/WAITING marker and the transcript directly, instead of (or alongside) the
|
|
146
|
+
hook scripts. The hooks, subagents, sandbox, and approval policy are all **engine-level**
|
|
147
|
+
(`codex-core`), so they fire identically whether codex is driven via the TUI or the
|
|
148
|
+
app-server -- the existing marker hooks would keep working.
|
|
149
|
+
|
|
150
|
+
### How (verified against codex 0.138.0)
|
|
151
|
+
- `codex app-server --listen unix://<sock>` runs the server and **works with the brew/npm
|
|
152
|
+
install**. (The convenience wrapper `codex remote-control start` / `codex app-server daemon`
|
|
153
|
+
requires codex's *standalone* installer at a fixed path -- avoid it; use raw `app-server
|
|
154
|
+
--listen`.) `codex app-server proxy --sock <sock>` proxies stdio to a running server's
|
|
155
|
+
control socket.
|
|
156
|
+
- mngr would override `send_message` to speak JSON-RPC to the socket, and `assemble_command`
|
|
157
|
+
would launch `app-server` + a `--remote` TUI viewer instead of the bare TUI.
|
|
158
|
+
|
|
159
|
+
### Important: client identity and OpenAI's ToS (do NOT spoof the TUI)
|
|
160
|
+
The app-server sets its `originator` from the `initialize` request's `clientInfo.name`. It is
|
|
161
|
+
**tempting but against the spirit (and likely the letter) of OpenAI's terms** to set
|
|
162
|
+
`clientInfo.name = "codex-tui"` so the backend grants the `*-codex` model entitlement it
|
|
163
|
+
otherwise denies non-TUI clients. That presents a programmatic client as the first-party TUI
|
|
164
|
+
specifically to bypass an *intentional* server-side model gate -- which falls under OpenAI's
|
|
165
|
+
"circumvent any restrictions / bypass any protective measures" clause (codex's own code treats
|
|
166
|
+
these names as a trust boundary; the override env var is literally `CODEX_INTERNAL_ORIGINATOR_OVERRIDE`).
|
|
167
|
+
|
|
168
|
+
So the app-server variant must **identify honestly** (mngr's own client name) and use whatever
|
|
169
|
+
models that identity is legitimately entitled to. For the gated `*-codex` models in app-server
|
|
170
|
+
mode, authenticate with an **API key** (OpenAI's documented path for programmatic workflows) --
|
|
171
|
+
do not spoof the TUI. The genuine `codex` TUI agent in this plugin remains the legitimate way
|
|
172
|
+
to use `*-codex` models on a ChatGPT-subscription login (it really *is* the TUI).
|
|
173
|
+
|
|
174
|
+
(Driving codex programmatically via the app-server on a single user's own ChatGPT login is
|
|
175
|
+
itself fine -- it's a first-party feature and OpenAI staff have called such use "permissive";
|
|
176
|
+
the line we don't cross is identity-spoofing to defeat the model gate, plus the usual no
|
|
177
|
+
credential-sharing / no multi-tenant-proxying / no rate-limit-bypass.)
|