feat(agent): add full codex agent support (v4.2.0)
- Implement CodexAdapter in lib_py/agents/adapters/codex.py with safe flags and TUI readiness - Extend create_session, resume_session, stop_session, and reconcile for codex CLI - Support codex agent delegation and loop integration across all multi-agent skills - Add unit, component, and contract test suites for codex integration - Verify all 462 tests passing cleanly
This commit is contained in:
1 parent
de0a9c2e81
commit
76f10b2096
45 files changed
+2045
-276
No files matched your search
@@ -53,12 +53,12 @@ def resume_on_disk(s):
|
||||
name = s.get('name', '')
|
||||
cwd = (s.get('pane') or {}).get('cwd', '')
|
||||
agent = None
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode'):
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode', 'codex'):
|
||||
if any(name.endswith(f'-{r}-{a}') for r in ('creator', 'planner', 'reviewer')) or name.endswith(f'-{a}'):
|
||||
agent = a
|
||||
break
|
||||
if not agent:
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode'):
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode', 'codex'):
|
||||
if f"-{a}" in name or f"_{a}" in name:
|
||||
agent = a
|
||||
break
|
||||
@@ -125,6 +125,29 @@ def resume_on_disk(s):
|
||||
except Exception:
|
||||
return 'MISSING'
|
||||
return 'no'
|
||||
if agent == 'codex':
|
||||
u = s.get('codex_session_id_own')
|
||||
if u:
|
||||
codex_home = os.environ.get('CODEX_HOME', f"{home}/.codex")
|
||||
db_matches = glob.glob(f"{codex_home}/state_*.sqlite")
|
||||
if db_matches:
|
||||
db = max(db_matches, key=os.path.getmtime)
|
||||
try:
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(db)
|
||||
r = conn.execute("SELECT rollout_path FROM threads WHERE id=?", (u,)).fetchone()
|
||||
conn.close()
|
||||
if r and r[0] and os.path.exists(r[0]):
|
||||
return 'yes'
|
||||
if r:
|
||||
return 'yes'
|
||||
except Exception:
|
||||
pass
|
||||
m = glob.glob(f"{codex_home}/sessions/*/*/*/rollout-*-{u}.jsonl")
|
||||
if m and os.path.exists(m[0]):
|
||||
return 'yes'
|
||||
return 'MISSING'
|
||||
return 'no'
|
||||
return '?'
|
||||
|
||||
|
||||
@@ -231,12 +254,12 @@ def resume_on_disk(s):
|
||||
name = s.get('name', '')
|
||||
cwd = (s.get('pane') or {}).get('cwd', '')
|
||||
agent = None
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode'):
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode', 'codex'):
|
||||
if any(name.endswith(f'-{r}-{a}') for r in ('creator', 'planner', 'reviewer')) or name.endswith(f'-{a}'):
|
||||
agent = a
|
||||
break
|
||||
if not agent:
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode'):
|
||||
for a in ('claude', 'agy', 'hermes', 'grok', 'opencode', 'codex'):
|
||||
if f"-{a}" in name or f"_{a}" in name:
|
||||
agent = a
|
||||
break
|
||||
@@ -303,6 +326,29 @@ def resume_on_disk(s):
|
||||
except Exception:
|
||||
return 'MISSING'
|
||||
return 'no'
|
||||
if agent == 'codex':
|
||||
u = s.get('codex_session_id_own')
|
||||
if u:
|
||||
codex_home = os.environ.get('CODEX_HOME', f"{home}/.codex")
|
||||
db_matches = glob.glob(f"{codex_home}/state_*.sqlite")
|
||||
if db_matches:
|
||||
db = max(db_matches, key=os.path.getmtime)
|
||||
try:
|
||||
import sqlite3
|
||||
conn = sqlite3.connect(db)
|
||||
r = conn.execute("SELECT rollout_path FROM threads WHERE id=?", (u,)).fetchone()
|
||||
conn.close()
|
||||
if r and r[0] and os.path.exists(r[0]):
|
||||
return 'yes'
|
||||
if r:
|
||||
return 'yes'
|
||||
except Exception:
|
||||
pass
|
||||
m = glob.glob(f"{codex_home}/sessions/*/*/*/rollout-*-{u}.jsonl")
|
||||
if m and os.path.exists(m[0]):
|
||||
return 'yes'
|
||||
return 'MISSING'
|
||||
return 'no'
|
||||
return '?'
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user