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.
- coderfleet-0.1.0/.github/workflows/publish.yml +50 -0
- coderfleet-0.1.0/.gitignore +55 -0
- coderfleet-0.1.0/CLAUDE.md +73 -0
- coderfleet-0.1.0/Dockerfile +92 -0
- coderfleet-0.1.0/PKG-INFO +492 -0
- coderfleet-0.1.0/README.md +477 -0
- coderfleet-0.1.0/accounts.conf.example +26 -0
- coderfleet-0.1.0/changelog/migrate-from-aicm-to-coderfleet.md +138 -0
- coderfleet-0.1.0/coderfleet/__init__.py +1 -0
- coderfleet-0.1.0/coderfleet/__main__.py +4 -0
- coderfleet-0.1.0/coderfleet/cli.py +212 -0
- coderfleet-0.1.0/coderfleet/compose.py +176 -0
- coderfleet-0.1.0/coderfleet/config.py +69 -0
- coderfleet-0.1.0/coderfleet/config_cmds.py +243 -0
- coderfleet-0.1.0/coderfleet/data/Dockerfile +92 -0
- coderfleet-0.1.0/coderfleet/data/__init__.py +0 -0
- coderfleet-0.1.0/coderfleet/data/accounts.conf.example +26 -0
- coderfleet-0.1.0/coderfleet/data/config.conf.example +31 -0
- coderfleet-0.1.0/coderfleet/data/entrypoint.sh +56 -0
- coderfleet-0.1.0/coderfleet/data/projects.conf.example +17 -0
- coderfleet-0.1.0/coderfleet/data/scripts/coderfleet_usage_status.py +138 -0
- coderfleet-0.1.0/coderfleet/docker_ops.py +385 -0
- coderfleet-0.1.0/coderfleet/init_wizard.py +227 -0
- coderfleet-0.1.0/coderfleet/login_cmd.py +168 -0
- coderfleet-0.1.0/coderfleet/server/__init__.py +0 -0
- coderfleet-0.1.0/coderfleet/server/docker_mgr.py +45 -0
- coderfleet-0.1.0/coderfleet/server/main.py +546 -0
- coderfleet-0.1.0/coderfleet/server/models.py +285 -0
- coderfleet-0.1.0/coderfleet/server/scheduler.py +1219 -0
- coderfleet-0.1.0/coderfleet/server/static/css/main.css +2906 -0
- coderfleet-0.1.0/coderfleet/server/static/index.html +378 -0
- coderfleet-0.1.0/coderfleet/server/static/js/accounts.js +85 -0
- coderfleet-0.1.0/coderfleet/server/static/js/app.js +28 -0
- coderfleet-0.1.0/coderfleet/server/static/js/chat.js +743 -0
- coderfleet-0.1.0/coderfleet/server/static/js/log.js +145 -0
- coderfleet-0.1.0/coderfleet/server/static/js/nav.js +46 -0
- coderfleet-0.1.0/coderfleet/server/static/js/projects.js +298 -0
- coderfleet-0.1.0/coderfleet/server/static/js/renderer.js +586 -0
- coderfleet-0.1.0/coderfleet/server/static/js/state.js +76 -0
- coderfleet-0.1.0/coderfleet/server/static/js/submit.js +200 -0
- coderfleet-0.1.0/coderfleet/server/static/js/tasks.js +92 -0
- coderfleet-0.1.0/coderfleet/server/static/js/terminal.js +347 -0
- coderfleet-0.1.0/coderfleet/server/static/js/utils.js +147 -0
- coderfleet-0.1.0/coderfleet/server/static/vendor/marked.min.js +6 -0
- coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/addon-fit.js +2 -0
- coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/xterm.css +218 -0
- coderfleet-0.1.0/coderfleet/server/static/vendor/xterm/xterm.js +2 -0
- coderfleet-0.1.0/coderfleet/server/terminal.py +129 -0
- coderfleet-0.1.0/coderfleet/task_cmds.py +311 -0
- coderfleet-0.1.0/config.conf.example +31 -0
- coderfleet-0.1.0/conversations/.gitkeep +0 -0
- coderfleet-0.1.0/entrypoint.sh +56 -0
- coderfleet-0.1.0/projects.conf.example +17 -0
- coderfleet-0.1.0/pyproject.toml +26 -0
- coderfleet-0.1.0/scripts/coderfleet_usage_status.py +138 -0
- coderfleet-0.1.0/tasks/.gitkeep +0 -0
- coderfleet-0.1.0/tests/conftest.py +13 -0
- coderfleet-0.1.0/tests/test_coderfleet_cli.py +173 -0
- coderfleet-0.1.0/tests/test_scheduler.py +469 -0
- coderfleet-0.1.0/tests/test_static_ui.py +196 -0
- coderfleet-0.1.0/tests/test_terminal.py +132 -0
- 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"]
|