Compare commits

..

5 Commits
v4.2 ... v4.2.2

Author SHA1 Message Date
cexll
e6b229645a update codex skills 2025-11-15 23:14:35 +08:00
cexll
9dc3e8f43d Merge pull request #21 from Tshoiasc/master
Enhance codex.py to auto-detect long inputs and switch to stdin mode,…
2025-11-14 09:45:24 +08:00
cexll
e9faa0bc2d Merge branch 'master' into master 2025-11-14 09:45:04 +08:00
swe-agent[bot]
70caa8d7fc Change default model to gpt-5.1-codex
- Update SKILL.md documentation
- Update codex.py DEFAULT_MODEL constant

Generated by swe-agent
2025-11-14 01:40:23 +00:00
Tshoiasc
4f74d5afa1 Enhance codex.py to auto-detect long inputs and switch to stdin mode, improving handling of shell argument issues. Updated build_codex_args to support stdin and added relevant logging for task length warnings. 2025-11-14 09:33:34 +08:00
2 changed files with 73 additions and 37 deletions

View File

@@ -14,7 +14,7 @@ Execute Codex CLI commands and parse structured JSON responses. Supports file re
- Complex code analysis requiring deep understanding - Complex code analysis requiring deep understanding
- Large-scale refactoring across multiple files - Large-scale refactoring across multiple files
- Automated code generation with safety controls - Automated code generation with safety controls
- Tasks requiring specialized reasoning models (o3, gpt-5) - Tasks requiring specialized reasoning models (gpt-5.1, gpt-5.1-codex)
## Usage ## Usage
@@ -46,9 +46,9 @@ uv run ~/.claude/skills/codex/scripts/codex.py resume <session_id> "<task>" [mod
### Parameters ### Parameters
- `task` (required): Task description, supports `@file` references - `task` (required): Task description, supports `@file` references
- `model` (optional): Model to use (default: gpt-5-codex) - `model` (optional): Model to use (default: gpt-5.1-codex)
- `gpt-5-codex`: Default, optimized for code - `gpt-5.1-codex`: Default, optimized for code
- `gpt-5`: Fast general purpose - `gpt-5.1`: Fast general purpose
- `working_dir` (optional): Working directory (default: current) - `working_dir` (optional): Working directory (default: current)
### Return Format ### Return Format
@@ -99,20 +99,20 @@ uv run ~/.claude/skills/codex/scripts/codex.py "explain @src/main.ts"
**Refactoring with specific model:** **Refactoring with specific model:**
```bash ```bash
uv run ~/.claude/skills/codex/scripts/codex.py "refactor @src/utils for performance" "gpt-5" uv run ~/.claude/skills/codex/scripts/codex.py "refactor @src/utils for performance" "gpt-5.1-codex"
# timeout: 7200000 # timeout: 7200000
``` ```
**Multi-file analysis:** **Multi-file analysis:**
```bash ```bash
uv run ~/.claude/skills/codex/scripts/codex.py "analyze @. and find security issues" "gpt-5-codex" "/path/to/project" uv run ~/.claude/skills/codex/scripts/codex.py "analyze @. and find security issues" "gpt-5.1-codex" "/path/to/project"
# timeout: 7200000 # timeout: 7200000
``` ```
**Resume previous session:** **Resume previous session:**
```bash ```bash
# First session # First session
uv run ~/.claude/skills/codex/scripts/codex.py "add comments to @utils.js" "gpt-5-codex" uv run ~/.claude/skills/codex/scripts/codex.py "add comments to @utils.js" "gpt-5.1-codex"
# Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14 # Output includes: SESSION_ID: 019a7247-ac9d-71f3-89e2-a823dbd8fd14
# Continue the conversation # Continue the conversation

View File

@@ -5,6 +5,7 @@
# /// # ///
""" """
Codex CLI wrapper with cross-platform support and session management. Codex CLI wrapper with cross-platform support and session management.
**FIXED**: Auto-detect long inputs and use stdin mode to avoid shell argument issues.
Usage: Usage:
New session: uv run codex.py "task" [model] [workdir] New session: uv run codex.py "task" [model] [workdir]
@@ -18,10 +19,11 @@ import sys
import os import os
from typing import Optional from typing import Optional
DEFAULT_MODEL = 'gpt-5-codex' DEFAULT_MODEL = 'gpt-5.1-codex'
DEFAULT_WORKDIR = '.' DEFAULT_WORKDIR = '.'
DEFAULT_TIMEOUT = 7200 # 2 hours in seconds DEFAULT_TIMEOUT = 7200 # 2 hours in seconds
FORCE_KILL_DELAY = 5 FORCE_KILL_DELAY = 5
STDIN_THRESHOLD = 800 # Auto-switch to stdin for prompts longer than 800 chars
def log_error(message: str): def log_error(message: str):
@@ -88,34 +90,64 @@ def parse_args():
} }
def build_codex_args(params: dict) -> list: def build_codex_args(params: dict, use_stdin: bool) -> list:
"""构建 codex CLI 参数""" """
构建 codex CLI 参数
Args:
params: 参数字典
use_stdin: 是否使用 stdin 模式(不在命令行参数中传递 task
"""
if params['mode'] == 'resume': if params['mode'] == 'resume':
return [ if use_stdin:
'codex', 'e', return [
'--skip-git-repo-check', 'codex', 'e',
'--json', '--skip-git-repo-check',
'resume', '--json',
params['session_id'], 'resume',
params['task'] params['session_id'],
] '-' # 从 stdin 读取
]
else:
return [
'codex', 'e',
'--skip-git-repo-check',
'--json',
'resume',
params['session_id'],
params['task']
]
else: else:
return [ base_args = [
'codex', 'e', 'codex', 'e',
'-m', params['model'], '-m', params['model'],
'--dangerously-bypass-approvals-and-sandbox', '--dangerously-bypass-approvals-and-sandbox',
'--skip-git-repo-check', '--skip-git-repo-check',
'-C', params['workdir'], '-C', params['workdir'],
'--json', '--json'
params['task']
] ]
if use_stdin:
base_args.append('-') # 从 stdin 读取
else:
base_args.append(params['task'])
return base_args
def main(): def main():
params = parse_args() params = parse_args()
codex_args = build_codex_args(params)
timeout_sec = resolve_timeout() timeout_sec = resolve_timeout()
# **FIX: Auto-detect long inputs and enable stdin mode**
task_length = len(params['task'])
use_stdin = task_length > STDIN_THRESHOLD
if use_stdin:
log_warn(f"Task length ({task_length} chars) exceeds threshold, using stdin mode to avoid shell escaping issues")
codex_args = build_codex_args(params, use_stdin)
thread_id: Optional[str] = None thread_id: Optional[str] = None
last_agent_message: Optional[str] = None last_agent_message: Optional[str] = None
@@ -123,12 +155,18 @@ def main():
# 启动 codex 子进程 # 启动 codex 子进程
process = subprocess.Popen( process = subprocess.Popen(
codex_args, codex_args,
stdin=subprocess.PIPE if use_stdin else None, # **FIX: Enable stdin**
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=sys.stderr, # 错误直接透传到 stderr stderr=sys.stderr, # 错误直接透传到 stderr
text=True, text=True,
bufsize=1 # 行缓冲 bufsize=1 # 行缓冲
) )
# **FIX: 如果使用 stdin 模式,写入任务到 stdin**
if use_stdin:
process.stdin.write(params['task'])
process.stdin.close()
# 逐行解析 JSON 输出 # 逐行解析 JSON 输出
for line in process.stdout: for line in process.stdout:
line = line.strip() line = line.strip()
@@ -155,24 +193,22 @@ def main():
# 等待进程结束 # 等待进程结束
returncode = process.wait(timeout=timeout_sec) returncode = process.wait(timeout=timeout_sec)
# 优先检查是否有有效输出,而非退出码 if returncode == 0:
if last_agent_message: if last_agent_message:
# 输出 agent_message # 输出 agent_message
sys.stdout.write(f"{last_agent_message}\n") sys.stdout.write(f"{last_agent_message}\n")
# 输出 session_id如果存在 # 输出 session_id如果存在
if thread_id: if thread_id:
sys.stdout.write(f"\n---\nSESSION_ID: {thread_id}\n") sys.stdout.write(f"\n---\nSESSION_ID: {thread_id}\n")
# 有输出但退出码非零,输出警告而非失败 sys.exit(0)
if returncode != 0: else:
log_warn(f'Codex completed with non-zero status {returncode} but produced valid output') log_error('Codex completed without agent_message output')
sys.exit(1)
sys.exit(0)
else: else:
# 没有输出才算真正失败 log_error(f'Codex exited with status {returncode}')
log_error(f'Codex exited with status {returncode} without agent_message output') sys.exit(returncode)
sys.exit(returncode if returncode != 0 else 1)
except subprocess.TimeoutExpired: except subprocess.TimeoutExpired:
log_error('Codex execution timeout') log_error('Codex execution timeout')