python写一个类似claude code和codex的命令行自主智能体代码
代码语言:python
所属分类:其他
代码描述:python写一个类似claude code和codex的命令行自主智能体代码 - 真流式输出(SSE),模型思考过程实时打字机效果显示 - 类 Claude Code 的终端 UI:工具调用/结果面板、步骤分隔线、圆角框、旋转动画 - REPL 斜杠命令:/mode /clear /compact /skills /tasks /help /exit - 其余能力保持不变:Plan/Build 模式、文件/命令/Python 执行、技能系统、 定时任务调度、自动+手动上下文压缩、系
代码标签: python 类似claude code codex 命令行 自主 智能体 代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
codex_agent.py
一个类似 Claude Code / Codex CLI 的命令行自主智能体(单文件实现)。
新特性:
- 真流式输出(SSE),模型思考过程实时打字机效果显示
- 类 Claude Code 的终端 UI:工具调用/结果面板、步骤分隔线、圆角框、旋转动画
- REPL 斜杠命令:/mode /clear /compact /skill /tasks /help /exit
- 技能系统升级:技能 = 自然语言描述 -> 模型自动生成的"指南文档"(可选内嵌可执行代码),
支持在 chat 中动态创建 / 修改 / 删除 / 调用技能,无需用户手写代码
- 其余能力保持不变:Plan/Build 模式、文件/命令/Python 执行、定时任务调度、
自动+手动上下文压缩、系统环境信息注入
依赖:仅 Python 标准库。
用法示例:
export OPENAI_API_KEY=sk-xxxx
export OPENAI_BASE_URL=https://your-endpoint/v1
export OPENAI_MODEL=gpt-4o-mini
python codex_agent.py run --goal "统计当前目录下代码行数" --mode build
python codex_agent.py chat --mode build
python codex_agent.py skill list
python codex_agent.py skill create --name deploy_guide --requirement "如何把一个静态网站部署到服务器"
python codex_agent.py skill update --name deploy_guide --instruction "补充 nginx 配置示例"
python codex_agent.py schedule add --name daily --when "daily:09:00" --goal "..."
python codex_agent.py daemon
python codex_agent.py config show
"""
import os
import sys
import re
import json
import time
import uuid
import base64
import shutil
import socket
import getpass
import platform
import argparse
import textwrap
import traceback
import threading
import unicodedata
import subprocess
import datetime
import urllib.request
import urllib.error
# ============================================================
# 全局路径
# ============================================================
HOME_DIR = os.path.join(os.path.expanduser("~"), ".codex_agent")
SKILLS_DIR = os.path.join(HOME_DIR, "skills")
LOGS_DIR = os.path.join(HOME_DIR, "logs")
TASKS_PATH = os.path.join(HOME_DIR, "tasks.json")
CONFIG_PATH = os.path.join(HOME_DIR, "config.json")
def ensure_dirs():
os.makedirs(HOME_DIR, exist_ok=True)
os.makedirs(SKILLS_DIR, exist_ok=True)
os.makedirs(LOGS_DIR, exist_ok=True)
# ============================================================
# UI / 终端美化模块
# ============================================================
class C:
RESET = BOLD = DIM = ITALIC = UNDERLINE = ""
BLACK = RED = GREEN = YELLOW = BLUE = MAGENTA = CYAN = WHITE = GRAY = ""
BRIGHT_RED = BRIGHT_GREEN = BRIGHT_YELLOW = BRIGHT_BLUE = ""
BRIGHT_MAGENTA = BRIGHT_CYAN = BRIGHT_WHITE = ""
def _enable_color():
C.RESET = "\033[0m"
C.BOLD = "\033[1m"
C.DIM = "\033[2m"
C.ITALIC = "\033[3m"
C.UNDERLINE = "\033[4m"
C.BLACK = "\033[30m"; C.RED = "\033[31m"; C.GREEN = "\033[32m"
C.YELLOW = "\033[33m"; C.BLUE = "\033[34m"; C.MAGENTA = "\033[35m"
C.CYAN = "\033[36m"; C.WHITE = "\033[37m"; C.GRAY = "\033[90m"
C.BRIGHT_RED = "\033[91m"; C.BRIGHT_GREEN = "\033[92m"
C.BRIGHT_YELLOW = "\033[93m"; C.BRIGHT_BLUE = "\033[94m"
C.BRIGHT_MAGENTA = "\033[95m"; C.BRIGHT_CYAN = "\033[96m"
C.BRIGHT_WHITE = "\033[97m"
def init_color(force=None):
color_on = force
if color_on is None:
color_on = sys.stdout.isatty() and os.environ.get("NO_COLOR") is None
if color_on:
_enable_color()
if platform.system() == "Windows":
os.system("") # 开启 Windows 终端 ANSI 转义支持
return color_on
ANSI_RE = re.compile(r"\x1b\[[0-9;]*m")
def strip_ansi(s):
return ANSI_RE.sub("", s or "")
def display_width(s):
s = strip_ansi(s)
w = 0
for ch in s:
w += 2 if unicodedata.east_asian_width(ch) in ("W", "F") else 1
return w
def draw_box(lines, color=None, padding=1, min_width=20):
color = color or ""
reset = C.RESET if color else ""
widths = [display_width(l) for l in lines] or [0]
inner = max(max(widths), min_width) + padding * 2
top = "╭" + "─" * inner + "╮"
bottom = "╰" + "─" * inner + "╯"
out = [f"{color}{top}{reset}"]
for l, w in zip(lines, widths):
right_pad = max(inner - w - padding, 0)
out.append(f"{color}│{reset}" + " " * padding + l + " " * right_pad + f"{color}│{reset}")
out.append(f"{color}{bottom}{reset}")
return "\n".join(out)
class Spinner:
FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
def __init__(self, message="Thinking"):
self.message = message
self._stop_evt = threading.Event()
self._thread = None
self._active = False
def start(self):
if self._active:
return
self._active = True
if not sys.stdout.isatty():
return
self._stop_evt.clear()
self._thread = threading.Thread(target=self._run, daemon=True)
self._thread.start()
def _run(self):
i = 0
while not self._stop_evt.is_set():
frame = self.FRAMES[i % len(self.FRAMES)]
sys.stdout.write(f"\r{C.CYAN}{frame}{C.RESET} {C.DIM}{self.message}…{C.RESET}")
sys.stdout.flush()
i += 1
time.sleep(0.08)
clear_len = display_width(self.message) + 6
sys.stdout.write("\r" + " " * clear_len + "\r")
sys.stdout.flush()
def stop(self):
if not self._active:
return
self._active = False
if self._thread:
self._stop_evt.set()
self._thread.join(timeout=1)
self._thread = None
def summarize_action_input(action, action_input):
action_input = action_input or {}
try:
if action == "read_file":
return action_input.get("path", "")
if action == "write_file":
c = action_input.get("content", "") or ""
tag = "追加" if action_input.get("append") else "写入"
return f'{action_input.get("path","")} ({tag} {len(c)} 字符)'
if action == "list_dir":
return action_input.get("path", ".")
if action == "run_command":
return action_input.get("cmd", "")
if action == "run_python":
code = action_input.get("code", "") or ""
n = code.count("\n") + 1
return f"<{n} 行代码>"
if action == "create_skill":
req = (action_input.get("requirement", "") or "")[:60]
return f'{action_input.get("name","")}: {req}'
if action == "update_skill":
ins = (action_input.get("instruction", "") or "")[:60]
return f'{action_input.get("name","")}: {ins}'
if action == "delete_skill":
return action_input.get("name", "")
if action == "use_skill":
return f'{action_input.get("name","")} {action_input.get("args", {})}'
if action in ("list_skills", "list_tasks", "compress_context"):
return ""
if action == "create_task":
return f'{action_input.get("name","")} [{action_input.get("schedule","")}]'
if action == "cancel_task":
return action_input.get("name", "")
if action == "ask_user":
return (action_input.get("question&quo.........完整代码请登录后点击上方下载按钮下载查看














网友评论0