coderfleet 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.
Files changed (62) hide show
  1. coderfleet-0.1.0/.github/workflows/publish.yml +50 -0
  2. coderfleet-0.1.0/.gitignore +55 -0
  3. coderfleet-0.1.0/CLAUDE.md +73 -0
  4. coderfleet-0.1.0/Dockerfile +92 -0
  5. coderfleet-0.1.0/PKG-INFO +492 -0
  6. coderfleet-0.1.0/README.md +477 -0
  7. coderfleet-0.1.0/accounts.conf.example +26 -0
  8. coderfleet-0.1.0/changelog/migrate-from-aicm-to-coderfleet.md +138 -0
  9. coderfleet-0.1.0/coderfleet/__init__.py +1 -0
  10. coderfleet-0.1.0/coderfleet/__main__.py +4 -0
  11. coderfleet-0.1.0/coderfleet/cli.py +212 -0
  12. coderfleet-0.1.0/coderfleet/compose.py +176 -0
  13. coderfleet-0.1.0/coderfleet/config.py +69 -0
  14. coderfleet-0.1.0/coderfleet/config_cmds.py +243 -0
  15. coderfleet-0.1.0/coderfleet/data/Dockerfile +92 -0
  16. coderfleet-0.1.0/coderfleet/data/__init__.py +0 -0
  17. coderfleet-0.1.0/coderfleet/data/accounts.conf.example +26 -0
  18. coderfleet-0.1.0/coderfleet/data/config.conf.example +31 -0
  19. coderfleet-0.1.0/coderfleet/data/entrypoint.sh +56 -0
  20. coderfleet-0.1.0/coderfleet/data/projects.conf.example +17 -0
  21. coderfleet-0.1.0/coderfleet/data/scripts/coderfleet_usage_status.py +138 -0
  22. coderfleet-0.1.0/coderfleet/docker_ops.py +385 -0
  23. coderfleet-0.1.0/coderfleet/init_wizard.py +227 -0
  24. coderfleet-0.1.0/coderfleet/login_cmd.py +168 -0
  25. coderfleet-0.1.0/coderfleet/server/__init__.py +0 -0
  26. coderfleet-0.1.0/coderfleet/server/docker_mgr.py +45 -0
  27. coderfleet-0.1.0/coderfleet/server/main.py +546 -0
  28. coderfleet-0.1.0/coderfleet/server/models.py +285 -0
  29. coderfleet-0.1.0/coderfleet/server/scheduler.py +1219 -0
  30. coderfleet-0.1.0/coderfleet/server/static/css/main.css +2906 -0
  31. coderfleet-0.1.0/coderfleet/server/static/index.html +378 -0
  32. coderfleet-0.1.0/coderfleet/server/static/js/accounts.js +85 -0
  33. coderfleet-0.1.0/coderfleet/server/static/js/app.js +28 -0
  34. coderfleet-0.1.0/coderfleet/server/static/js/chat.js +743 -0
  35. coderfleet-0.1.0/coderfleet/server/static/js/log.js +145 -0
  36. coderfleet-0.1.0/coderfleet/server/static/js/nav.js +46 -0
  37. coderfleet-0.1.0/coderfleet/server/static/js/projects.js +298 -0
  38. coderfleet-0.1.0/coderfleet/server/static/js/renderer.js +586 -0
  39. coderfleet-0.1.0/coderfleet/server/static/js/state.js +76 -0
  40. coderfleet-0.1.0/coderfleet/server/static/js/submit.js +200 -0
  41. coderfleet-0.1.0/coderfleet/server/static/js/tasks.js +92 -0
  42. coderfleet-0.1.0/coderfleet/server/static/js/terminal.js +347 -0
  43. coderfleet-0.1.0/coderfleet/server/static/js/utils.js +147 -0
  44. coderfleet-0.1.0/coderfleet/server/static/vendor/marked.min.js +6 -0
  45. coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/addon-fit.js +2 -0
  46. coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/xterm.css +218 -0
  47. coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/xterm.js +2 -0
  48. coderfleet-0.1.0/coderfleet/server/terminal.py +129 -0
  49. coderfleet-0.1.0/coderfleet/task_cmds.py +311 -0
  50. coderfleet-0.1.0/config.conf.example +31 -0
  51. coderfleet-0.1.0/conversations/.gitkeep +0 -0
  52. coderfleet-0.1.0/entrypoint.sh +56 -0
  53. coderfleet-0.1.0/projects.conf.example +17 -0
  54. coderfleet-0.1.0/pyproject.toml +26 -0
  55. coderfleet-0.1.0/scripts/coderfleet_usage_status.py +138 -0
  56. coderfleet-0.1.0/tasks/.gitkeep +0 -0
  57. coderfleet-0.1.0/tests/conftest.py +13 -0
  58. coderfleet-0.1.0/tests/test_coderfleet_cli.py +173 -0
  59. coderfleet-0.1.0/tests/test_scheduler.py +469 -0
  60. coderfleet-0.1.0/tests/test_static_ui.py +196 -0
  61. coderfleet-0.1.0/tests/test_terminal.py +132 -0
  62. coderfleet-0.1.0/tests/test_usage_status_script.py +54 -0
@@ -0,0 +1,50 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ publish:
12
+ name: Build and publish
13
+ runs-on: ubuntu-latest
14
+ environment:
15
+ name: pypi
16
+ url: https://pypi.org/p/coderfleet
17
+ permissions:
18
+ contents: read
19
+ id-token: write
20
+
21
+ steps:
22
+ - name: Check out repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Set up Python
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+
30
+ - name: Verify release tag matches package version
31
+ run: |
32
+ python - <<'PY'
33
+ import os
34
+ import tomllib
35
+ from pathlib import Path
36
+
37
+ tag = os.environ["GITHUB_REF_NAME"]
38
+ version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
39
+ expected = f"v{version}"
40
+ if tag not in {version, expected}:
41
+ raise SystemExit(f"Release tag {tag!r} does not match package version {version!r} or {expected!r}")
42
+ PY
43
+
44
+ - name: Build distributions
45
+ run: |
46
+ python -m pip install --upgrade build
47
+ python -m build
48
+
49
+ - name: Publish distributions to PyPI
50
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,55 @@
1
+ # ── 自动生成的编排文件(由 coderfleet apply 生成)──────────
2
+ docker-compose.yml
3
+
4
+ # ── 账号认证数据(敏感凭据,绝对不能入库)────────────────
5
+ accounts/
6
+
7
+ # ── 任务执行记录与日志 ────────────────────────────────────
8
+ tasks/*.json
9
+ tasks/*.log
10
+ !tasks/.gitkeep
11
+
12
+ # ── 容器任务临时文件(I/O 解耦写入项目目录)──────────────
13
+ .coderfleet-tasks/
14
+ .*-tasks/
15
+
16
+ # ── 任务链会话记录 ────────────────────────────────────────
17
+ conversations/*.json
18
+ !conversations/.gitkeep
19
+
20
+ # ── Python ────────────────────────────────────────────────
21
+ __pycache__/
22
+ *.pyc
23
+ *.pyo
24
+ *.egg-info/
25
+ .venv/
26
+ venv/
27
+
28
+ # ── macOS ─────────────────────────────────────────────────
29
+ .DS_Store
30
+
31
+ # ── IDE / 编辑器 ──────────────────────────────────────────
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+ *~
37
+
38
+ accounts.conf
39
+ config.conf
40
+ projects.conf
41
+
42
+ .claude/settings.local.json
43
+
44
+ .agent
45
+ # ── 视频等大体积媒体文件 ───────────────────────────────
46
+ *.mp4
47
+
48
+ .claude/worktrees
49
+
50
+ core
51
+
52
+ .coderfleet-uploads
53
+ .*-uploads
54
+
55
+ server.log
@@ -0,0 +1,73 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this project is
6
+
7
+ CoderFleet runs multiple Claude Code / Codex CLI accounts in isolated Docker containers on a single host, pooling quota across accounts. Each account gets its own container with independent auth, proxied through a gost relay so all outbound traffic flows through the host proxy.
8
+
9
+ ## Key commands
10
+
11
+ ```bash
12
+ # Container lifecycle
13
+ coderfleet build # Build the shared Docker image (first time ~5–10 min)
14
+ coderfleet apply # Regenerate docker-compose.yml and restart all containers
15
+ coderfleet up / down / restart
16
+
17
+ # Account & project management (edits accounts.conf / projects.conf then requires apply)
18
+ coderfleet account add <name> TYPE=claude|codex [--auth login|env] [--proxy relay|off]
19
+ coderfleet project add <name> <account> <host-path>
20
+ coderfleet login <account> # Interactive OAuth; starts a temp container if needed
21
+
22
+ # Scheduler server (required for task commands and Web UI)
23
+ coderfleet server # Starts FastAPI on :8765; Web UI at http://localhost:8765
24
+
25
+ # Task submission (requires server running)
26
+ coderfleet task run "<prompt>" --project <name> [--auto] [--conversation <id>] [--new-chain <name>]
27
+ coderfleet task list
28
+ coderfleet task logs <id> [-f]
29
+ ```
30
+
31
+ Run the Python test suite with `uv run --with pytest pytest -q`.
32
+
33
+ ## Architecture
34
+
35
+ ### Two modes of operation
36
+
37
+ 1. **Interactive** — `coderfleet enter <project>` drops into a container shell; user runs `claude` or `codex` directly.
38
+ 2. **Scheduled** — `coderfleet server` runs the FastAPI scheduler; tasks are submitted via CLI or Web UI and executed non-interactively inside containers.
39
+
40
+ ### Component map
41
+
42
+ | Component | Role |
43
+ |-----------|------|
44
+ | `coderfleet/cli.py` | Click entry point for all host-side operations. |
45
+ | `coderfleet/server/main.py` | FastAPI app. Defines all REST endpoints and WebSocket terminal handler. |
46
+ | `coderfleet/server/scheduler.py` | Core task queue. Resolves account/project, spawns async tasks inside containers via `docker exec`, tracks state. |
47
+ | `coderfleet/server/models.py` | Pydantic models: `Task`, `Conversation`, `Account`, `Project` and their HTTP request/response shapes. |
48
+ | `coderfleet/server/docker_mgr.py` | Docker API wrapper (container status, exec). |
49
+ | `coderfleet/server/terminal.py` | WebSocket ↔ `docker exec -it` bridge for the in-browser terminal. |
50
+ | `coderfleet/server/static/` | Single-page Web UI (vanilla JS, no build step). JS is split into `chat.js`, `projects.js`, `tasks.js`, `accounts.js`, `nav.js`, `state.js`, `utils.js`. |
51
+
52
+ ### Data storage (all under workspace root)
53
+
54
+ - `config.conf`, `accounts.conf`, `projects.conf` — authoritative config files; `docker-compose.yml` is **generated** from these, never edit it manually.
55
+ - `accounts/<name>/` — per-account CLI auth data mounted into containers.
56
+ - `tasks/*.json` — task state records.
57
+ - `tasks/*.log` — task execution logs.
58
+ - `conversations/*.json` — conversation (task chain) records.
59
+
60
+ ### Task / Conversation model
61
+
62
+ A **Task** is a single `claude`/`codex` invocation inside a container. A **Conversation** is a named chain of tasks that share context via `--resume {native_session_id}`. Tasks store `project` (path) and `project_name` (config name) — both are needed because multiple projects can share the same path, and sidebar grouping uses `project_name` for disambiguation.
63
+
64
+ ### Network isolation
65
+
66
+ Containers join an `internal: true` Docker network; they cannot reach the public internet directly. All traffic is forced through a `coderfleet-proxy-relay` container running gost, which forwards to the host proxy (Clash/v2ray). `PROXY=off` accounts skip the relay and connect to the default bridge.
67
+
68
+ ### Frontend conventions
69
+
70
+ - Global mutable state lives in `state.js` (e.g. `activeConversationId`, `chatNewSessionProject`, `projectsCache`).
71
+ - `conversationBelongsToProject` and `taskBelongsToProject` (in `projects.js`) are used everywhere for sidebar grouping — if `project_name` is present, it takes precedence over path matching.
72
+ - SSE (`EventSource`) is used for real-time log streaming; WebSocket for the terminal.
73
+ - New chat sessions are always started from a per-project "+" button, so `chatNewSessionProject` is pre-set before the empty chat state renders.
@@ -0,0 +1,92 @@
1
+ # ============================================================
2
+ # CoderFleet — 统一工作容器镜像
3
+ # 包含:Python 3.12 / Node.js 20 / Codex CLI / Claude Code
4
+ # 平台:linux/amd64(Apple Silicon 通过 Docker 模拟运行)
5
+ # ============================================================
6
+
7
+ FROM --platform=linux/amd64 ubuntu:24.04
8
+
9
+ # 避免交互式安装询问
10
+ ENV DEBIAN_FRONTEND=noninteractive
11
+ ENV TZ=Asia/Shanghai
12
+
13
+ # ── 基础系统工具 ──────────────────────────────────────────
14
+ RUN apt-get update && apt-get install -y --no-install-recommends \
15
+ # 网络工具
16
+ curl wget ca-certificates netcat-openbsd \
17
+ # 开发基础
18
+ git build-essential pkg-config \
19
+ # Python 依赖
20
+ libssl-dev libffi-dev zlib1g-dev libbz2-dev \
21
+ libreadline-dev libsqlite3-dev liblzma-dev \
22
+ # 系统工具
23
+ bash-completion less vim nano \
24
+ && apt-get clean && rm -rf /var/lib/apt/lists/*
25
+
26
+ # ── Node.js 20 (via NodeSource) ───────────────────────────
27
+ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
28
+ && apt-get install -y nodejs \
29
+ && apt-get clean && rm -rf /var/lib/apt/lists/*
30
+
31
+ # 验证 Node 版本并安装常用全局包
32
+ RUN node --version && npm --version \
33
+ && npm install -g npm@latest
34
+
35
+ # ── Python 3.12 (via deadsnakes PPA) ─────────────────────
36
+ RUN apt-get update && apt-get install -y --no-install-recommends \
37
+ software-properties-common \
38
+ && add-apt-repository ppa:deadsnakes/ppa \
39
+ && apt-get update && apt-get install -y --no-install-recommends \
40
+ python3.12 python3.12-dev python3.12-venv python3-pip \
41
+ && apt-get clean && rm -rf /var/lib/apt/lists/*
42
+
43
+ # 设置 python3.12 为默认 python3
44
+ RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1 \
45
+ && update-alternatives --install /usr/bin/python python /usr/bin/python3.12 1
46
+
47
+ # 安装常用 Python 工具
48
+ # Ubuntu 24.04 实行 PEP 668,系统 Python 需加 --break-system-packages
49
+ RUN pip3 install --no-cache-dir --break-system-packages \
50
+ uv ruff black mypy pexpect
51
+
52
+ # ── Codex CLI ─────────────────────────────────────────────
53
+ RUN npm install -g @openai/codex
54
+
55
+ # ── Claude Code CLI ───────────────────────────────────────
56
+ RUN npm install -g @anthropic-ai/claude-code
57
+
58
+ # ── Rust 1.93.0 ───────────────────────────────────────────
59
+ ENV RUSTUP_HOME=/usr/local/rustup \
60
+ CARGO_HOME=/usr/local/cargo \
61
+ PATH=/usr/local/cargo/bin:$PATH \
62
+ RUSTUP_DIST_SERVER=https://rsproxy.cn \
63
+ RUSTUP_UPDATE_ROOT=https://rsproxy.cn/rustup
64
+ RUN curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh -s -- -y --no-modify-path --default-toolchain 1.93.0 \
65
+ && chmod -R a+w $RUSTUP_HOME $CARGO_HOME \
66
+ && rustc --version
67
+
68
+ # ── 创建非特权用户 byclaw ─────────────────────────────────
69
+ RUN groupadd -r byclaw && useradd -r -g byclaw -m -s /bin/bash byclaw
70
+
71
+ # ── 工作目录和环境变量 ────────────────────────────────────
72
+ RUN mkdir -p /workspace && chown byclaw:byclaw /workspace
73
+ WORKDIR /workspace
74
+
75
+ # 这两个目录由 CoderFleet 按账号挂载,容器内路径固定
76
+ # Codex 认证:/home/byclaw/.codex 由 CODEX_HOME 控制
77
+ # Claude 认证:/home/byclaw/.claude 由 CLAUDE_CONFIG_DIR 控制
78
+ ENV CODEX_HOME=/home/byclaw/.codex
79
+ ENV CLAUDE_CONFIG_DIR=/home/byclaw/.claude
80
+
81
+ # ── 启动脚本 ──────────────────────────────────────────────
82
+ COPY entrypoint.sh /entrypoint.sh
83
+ RUN chmod +x /entrypoint.sh
84
+
85
+ COPY scripts/coderfleet_usage_status.py /usr/local/bin/coderfleet-usage-status
86
+ RUN chmod +x /usr/local/bin/coderfleet-usage-status
87
+
88
+ # ── 切换为非特权用户 ──────────────────────────────────────
89
+ USER byclaw
90
+
91
+ ENTRYPOINT ["/entrypoint.sh"]
92
+ CMD ["sleep", "infinity"]