maind 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.
- maind-0.1.0/.dockerignore +13 -0
- maind-0.1.0/.gitignore +27 -0
- maind-0.1.0/.python-version +1 -0
- maind-0.1.0/.woodpecker/backend-build.yml +63 -0
- maind-0.1.0/.woodpecker/backend-manifest.yml +40 -0
- maind-0.1.0/Dockerfile +72 -0
- maind-0.1.0/HANDOFF.md +110 -0
- maind-0.1.0/Makefile +113 -0
- maind-0.1.0/PKG-INFO +320 -0
- maind-0.1.0/README.md +303 -0
- maind-0.1.0/docs/superpowers/PLAN2-CONTRACTS.md +59 -0
- maind-0.1.0/docs/superpowers/plans/2026-07-03-mindreon-sdk-foundation.md +1158 -0
- maind-0.1.0/docs/superpowers/plans/2026-07-03-mindreon-sdk-project-create.md +1439 -0
- maind-0.1.0/docs/superpowers/specs/2026-07-03-mindreon-sdk-design.md +189 -0
- maind-0.1.0/pyproject.toml +67 -0
- maind-0.1.0/src/mai/__init__.py +38 -0
- maind-0.1.0/src/mai/__main__.py +6 -0
- maind-0.1.0/src/mai/_core/__init__.py +1 -0
- maind-0.1.0/src/mai/_core/api_response.py +10 -0
- maind-0.1.0/src/mai/_core/cli_output.py +101 -0
- maind-0.1.0/src/mai/_core/fvm_provider.py +47 -0
- maind-0.1.0/src/mai/_core/image_copy.py +59 -0
- maind-0.1.0/src/mai/_core/operations/__init__.py +1 -0
- maind-0.1.0/src/mai/_core/operations/auth.py +49 -0
- maind-0.1.0/src/mai/_core/operations/config_center.py +84 -0
- maind-0.1.0/src/mai/_core/operations/files.py +87 -0
- maind-0.1.0/src/mai/_core/operations/fvm.py +175 -0
- maind-0.1.0/src/mai/_core/operations/images.py +134 -0
- maind-0.1.0/src/mai/_core/operations/projects.py +74 -0
- maind-0.1.0/src/mai/_core/operations/resources.py +222 -0
- maind-0.1.0/src/mai/_core/operations/seed.py +314 -0
- maind-0.1.0/src/mai/_core/operations/sync.py +274 -0
- maind-0.1.0/src/mai/_core/resource_target.py +57 -0
- maind-0.1.0/src/mai/_core/routes.py +97 -0
- maind-0.1.0/src/mai/_core/settings.py +52 -0
- maind-0.1.0/src/mai/_core/tools.py +136 -0
- maind-0.1.0/src/mai/_core/transport.py +163 -0
- maind-0.1.0/src/mai/_core/vcs.py +927 -0
- maind-0.1.0/src/mai/_core/workspace.py +685 -0
- maind-0.1.0/src/mai/app.py +106 -0
- maind-0.1.0/src/mai/async_client.py +193 -0
- maind-0.1.0/src/mai/cli/__init__.py +1 -0
- maind-0.1.0/src/mai/cli/config_file.py +39 -0
- maind-0.1.0/src/mai/client.py +233 -0
- maind-0.1.0/src/mai/commands/__init__.py +1 -0
- maind-0.1.0/src/mai/commands/_workspace_common.py +26 -0
- maind-0.1.0/src/mai/commands/config_center.py +59 -0
- maind-0.1.0/src/mai/commands/connect.py +37 -0
- maind-0.1.0/src/mai/commands/create.py +80 -0
- maind-0.1.0/src/mai/commands/download.py +175 -0
- maind-0.1.0/src/mai/commands/file.py +26 -0
- maind-0.1.0/src/mai/commands/image.py +135 -0
- maind-0.1.0/src/mai/commands/install.py +28 -0
- maind-0.1.0/src/mai/commands/login.py +39 -0
- maind-0.1.0/src/mai/commands/project.py +67 -0
- maind-0.1.0/src/mai/commands/publish.py +48 -0
- maind-0.1.0/src/mai/commands/release.py +169 -0
- maind-0.1.0/src/mai/commands/repo.py +107 -0
- maind-0.1.0/src/mai/commands/seed.py +603 -0
- maind-0.1.0/src/mai/commands/status.py +38 -0
- maind-0.1.0/src/mai/commands/sync.py +67 -0
- maind-0.1.0/src/mai/errors.py +47 -0
- maind-0.1.0/src/mai/models.py +48 -0
- maind-0.1.0/tests/__init__.py +0 -0
- maind-0.1.0/tests/cli/__init__.py +0 -0
- maind-0.1.0/tests/cli/test_config_center_cli.py +42 -0
- maind-0.1.0/tests/cli/test_config_file.py +23 -0
- maind-0.1.0/tests/cli/test_connect_download_cli.py +156 -0
- maind-0.1.0/tests/cli/test_create_cli.py +79 -0
- maind-0.1.0/tests/cli/test_file_cli.py +53 -0
- maind-0.1.0/tests/cli/test_help_cli.py +60 -0
- maind-0.1.0/tests/cli/test_image_cli.py +184 -0
- maind-0.1.0/tests/cli/test_install_cli.py +66 -0
- maind-0.1.0/tests/cli/test_login_cli.py +46 -0
- maind-0.1.0/tests/cli/test_project_cli.py +60 -0
- maind-0.1.0/tests/cli/test_publish_cli.py +95 -0
- maind-0.1.0/tests/cli/test_release_cli.py +70 -0
- maind-0.1.0/tests/cli/test_repo_cli.py +129 -0
- maind-0.1.0/tests/cli/test_seed_cli.py +493 -0
- maind-0.1.0/tests/cli/test_status_cli.py +50 -0
- maind-0.1.0/tests/cli/test_sync_cli.py +147 -0
- maind-0.1.0/tests/conftest.py +17 -0
- maind-0.1.0/tests/core/__init__.py +0 -0
- maind-0.1.0/tests/core/test_auth_op.py +85 -0
- maind-0.1.0/tests/core/test_config_center_op.py +55 -0
- maind-0.1.0/tests/core/test_files_op.py +49 -0
- maind-0.1.0/tests/core/test_fvm_op.py +151 -0
- maind-0.1.0/tests/core/test_images_op.py +77 -0
- maind-0.1.0/tests/core/test_projects_op.py +68 -0
- maind-0.1.0/tests/core/test_publish.py +140 -0
- maind-0.1.0/tests/core/test_resource_target.py +33 -0
- maind-0.1.0/tests/core/test_resources_op.py +163 -0
- maind-0.1.0/tests/core/test_routes.py +48 -0
- maind-0.1.0/tests/core/test_seed_op.py +188 -0
- maind-0.1.0/tests/core/test_settings.py +50 -0
- maind-0.1.0/tests/core/test_sync_op.py +361 -0
- maind-0.1.0/tests/core/test_tools.py +62 -0
- maind-0.1.0/tests/core/test_transport.py +165 -0
- maind-0.1.0/tests/core/test_vcs.py +302 -0
- maind-0.1.0/tests/core/test_workspace.py +180 -0
- maind-0.1.0/tests/core/test_workspace_repo.py +407 -0
- maind-0.1.0/tests/test_async_client.py +165 -0
- maind-0.1.0/tests/test_client.py +179 -0
- maind-0.1.0/tests/test_errors.py +35 -0
- maind-0.1.0/tests/test_packaging.py +14 -0
- maind-0.1.0/uv.lock +2551 -0
maind-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
|
|
7
|
+
# Build
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
|
|
11
|
+
# Virtualenv / uv
|
|
12
|
+
.venv/
|
|
13
|
+
|
|
14
|
+
# Test / tooling caches
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.coverage
|
|
19
|
+
htmlcov/
|
|
20
|
+
|
|
21
|
+
# Editor / OS
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# SDD controller scratch (briefs, reports, diffs, ledger)
|
|
25
|
+
.superpowers/
|
|
26
|
+
.vscode
|
|
27
|
+
.idea
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# =========================================================================
|
|
2
|
+
# Mai CLI 镜像构建 Workflow (amd64 + arm64 并行)
|
|
3
|
+
# =========================================================================
|
|
4
|
+
clone:
|
|
5
|
+
git:
|
|
6
|
+
image: harbor.mindreon.com/ops/woodpeckerci/plugin-git:latest
|
|
7
|
+
environment:
|
|
8
|
+
CI_NETRC_MACHINE: gitlab.mindreon.com
|
|
9
|
+
CI_NETRC_USERNAME: { from_secret: gitlab_username }
|
|
10
|
+
CI_NETRC_PASSWORD: { from_secret: gitlab_password }
|
|
11
|
+
|
|
12
|
+
matrix:
|
|
13
|
+
include:
|
|
14
|
+
- PLATFORM: linux/amd64
|
|
15
|
+
ARCH: amd64
|
|
16
|
+
- PLATFORM: linux/arm64
|
|
17
|
+
ARCH: arm64
|
|
18
|
+
|
|
19
|
+
labels:
|
|
20
|
+
platform: ${PLATFORM}
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
build-cli-branch:
|
|
24
|
+
image: harbor.mindreon.com/ops/woodpeckerci/plugin-docker-buildx:6.0
|
|
25
|
+
privileged: true
|
|
26
|
+
volumes:
|
|
27
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
28
|
+
settings:
|
|
29
|
+
dockerfile: Dockerfile
|
|
30
|
+
repo: harbor.mindreon.com/baize/mai-cli
|
|
31
|
+
registry: harbor.mindreon.com
|
|
32
|
+
username: { from_secret: harbor_username }
|
|
33
|
+
password: { from_secret: harbor_password }
|
|
34
|
+
cache: true
|
|
35
|
+
daemon_off: true
|
|
36
|
+
platforms:
|
|
37
|
+
- ${PLATFORM}
|
|
38
|
+
provenance: false
|
|
39
|
+
auto_tag: false
|
|
40
|
+
tags:
|
|
41
|
+
- ${CI_COMMIT_BRANCH//\//-}-${ARCH}
|
|
42
|
+
when:
|
|
43
|
+
event: [push, manual]
|
|
44
|
+
|
|
45
|
+
build-cli-tag:
|
|
46
|
+
image: harbor.mindreon.com/ops/woodpeckerci/plugin-docker-buildx:6.0
|
|
47
|
+
privileged: true
|
|
48
|
+
volumes:
|
|
49
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
50
|
+
settings:
|
|
51
|
+
dockerfile: Dockerfile
|
|
52
|
+
repo: harbor.mindreon.com/baize/mai-cli
|
|
53
|
+
registry: harbor.mindreon.com
|
|
54
|
+
username: { from_secret: harbor_username }
|
|
55
|
+
password: { from_secret: harbor_password }
|
|
56
|
+
cache: true
|
|
57
|
+
daemon_off: true
|
|
58
|
+
platforms:
|
|
59
|
+
- ${PLATFORM}
|
|
60
|
+
provenance: false
|
|
61
|
+
tags: ${CI_COMMIT_TAG}-${ARCH}
|
|
62
|
+
when:
|
|
63
|
+
event: tag
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
depends_on:
|
|
2
|
+
- backend-build
|
|
3
|
+
|
|
4
|
+
skip_clone: true
|
|
5
|
+
|
|
6
|
+
labels:
|
|
7
|
+
platform: linux/amd64
|
|
8
|
+
|
|
9
|
+
steps:
|
|
10
|
+
manifest-cli-branch:
|
|
11
|
+
image: harbor.mindreon.com/ops/woodpeckerci/plugin-docker-buildx:6.0
|
|
12
|
+
volumes:
|
|
13
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
14
|
+
environment:
|
|
15
|
+
HARBOR_USER: { from_secret: harbor_username }
|
|
16
|
+
HARBOR_PWD: { from_secret: harbor_password }
|
|
17
|
+
REGISTRY: harbor.mindreon.com
|
|
18
|
+
REPO: harbor.mindreon.com/baize/mai-cli
|
|
19
|
+
commands:
|
|
20
|
+
- echo $HARBOR_PWD | docker login $REGISTRY -u $HARBOR_USER --password-stdin
|
|
21
|
+
- docker manifest create --amend $REPO:${CI_COMMIT_BRANCH//\//-} $REPO:${CI_COMMIT_BRANCH//\//-}-amd64 $REPO:${CI_COMMIT_BRANCH//\//-}-arm64
|
|
22
|
+
- docker manifest push $REPO:${CI_COMMIT_BRANCH//\//-}
|
|
23
|
+
when:
|
|
24
|
+
event: [push, manual]
|
|
25
|
+
|
|
26
|
+
manifest-cli-tag:
|
|
27
|
+
image: harbor.mindreon.com/ops/woodpeckerci/plugin-docker-buildx:6.0
|
|
28
|
+
volumes:
|
|
29
|
+
- /var/run/docker.sock:/var/run/docker.sock
|
|
30
|
+
environment:
|
|
31
|
+
HARBOR_USER: { from_secret: harbor_username }
|
|
32
|
+
HARBOR_PWD: { from_secret: harbor_password }
|
|
33
|
+
REGISTRY: harbor.mindreon.com
|
|
34
|
+
REPO: harbor.mindreon.com/baize/mai-cli
|
|
35
|
+
commands:
|
|
36
|
+
- echo $HARBOR_PWD | docker login $REGISTRY -u $HARBOR_USER --password-stdin
|
|
37
|
+
- docker manifest create --amend $REPO:$CI_COMMIT_TAG $REPO:$CI_COMMIT_TAG-amd64 $REPO:$CI_COMMIT_TAG-arm64
|
|
38
|
+
- docker manifest push $REPO:$CI_COMMIT_TAG
|
|
39
|
+
when:
|
|
40
|
+
event: tag
|
maind-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
FROM harbor.mindreon.com/ops/python:3.12-slim AS builder
|
|
2
|
+
|
|
3
|
+
COPY --from=harbor.mindreon.com/ops/astral/uv:latest /uv /uvx /bin/
|
|
4
|
+
|
|
5
|
+
ENV DEBIAN_FRONTEND=noninteractive \
|
|
6
|
+
PATH=/opt/venv/bin:$PATH \
|
|
7
|
+
PIP_NO_CACHE_DIR=1 \
|
|
8
|
+
PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple \
|
|
9
|
+
PIP_TRUSTED_HOST=pypi.tuna.tsinghua.edu.cn \
|
|
10
|
+
UV_PROJECT_ENVIRONMENT=/opt/venv
|
|
11
|
+
|
|
12
|
+
WORKDIR /opt/mai-cli
|
|
13
|
+
|
|
14
|
+
RUN sed -i \
|
|
15
|
+
-e 's#http://deb.debian.org/debian#https://mirrors.tuna.tsinghua.edu.cn/debian#g' \
|
|
16
|
+
-e 's#http://deb.debian.org/debian-security#https://mirrors.tuna.tsinghua.edu.cn/debian-security#g' \
|
|
17
|
+
/etc/apt/sources.list.d/debian.sources && \
|
|
18
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
19
|
+
bash \
|
|
20
|
+
ca-certificates \
|
|
21
|
+
git \
|
|
22
|
+
make \
|
|
23
|
+
openssh-client \
|
|
24
|
+
skopeo \
|
|
25
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
26
|
+
|
|
27
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
28
|
+
COPY src ./src
|
|
29
|
+
|
|
30
|
+
RUN uv sync --frozen --no-dev --no-editable --no-cache
|
|
31
|
+
|
|
32
|
+
RUN mai --help >/dev/null && \
|
|
33
|
+
python -m mai --help >/dev/null && \
|
|
34
|
+
python -c "import dvc.repo, huggingface_hub, modelscope_hub, botocore" && \
|
|
35
|
+
dvc version >/dev/null && \
|
|
36
|
+
hf --help >/dev/null && \
|
|
37
|
+
ms -V >/dev/null 2>&1 && \
|
|
38
|
+
modelscope -V >/dev/null 2>&1 && \
|
|
39
|
+
skopeo --version >/dev/null && \
|
|
40
|
+
git --version >/dev/null
|
|
41
|
+
|
|
42
|
+
FROM harbor.mindreon.com/ops/python:3.12-slim AS runtime
|
|
43
|
+
|
|
44
|
+
ENV DEBIAN_FRONTEND=noninteractive \
|
|
45
|
+
PATH=/opt/venv/bin:$PATH \
|
|
46
|
+
PYTHONUNBUFFERED=1 \
|
|
47
|
+
PYTHONDONTWRITEBYTECODE=1
|
|
48
|
+
|
|
49
|
+
RUN sed -i \
|
|
50
|
+
-e 's#http://deb.debian.org/debian#https://mirrors.tuna.tsinghua.edu.cn/debian#g' \
|
|
51
|
+
-e 's#http://deb.debian.org/debian-security#https://mirrors.tuna.tsinghua.edu.cn/debian-security#g' \
|
|
52
|
+
/etc/apt/sources.list.d/debian.sources && \
|
|
53
|
+
apt-get update && apt-get install -y --no-install-recommends \
|
|
54
|
+
bash \
|
|
55
|
+
ca-certificates \
|
|
56
|
+
git \
|
|
57
|
+
openssh-client \
|
|
58
|
+
skopeo \
|
|
59
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
60
|
+
|
|
61
|
+
COPY --from=builder /opt/venv /opt/venv
|
|
62
|
+
|
|
63
|
+
RUN ln -sf /opt/venv/bin/mai /usr/local/bin/mai && \
|
|
64
|
+
ln -sf /opt/venv/bin/dvc /usr/local/bin/dvc && \
|
|
65
|
+
ln -sf /opt/venv/bin/hf /usr/local/bin/hf && \
|
|
66
|
+
ln -sf /opt/venv/bin/ms /usr/local/bin/ms && \
|
|
67
|
+
ln -sf /opt/venv/bin/modelscope /usr/local/bin/modelscope && \
|
|
68
|
+
mkdir -p /workspace
|
|
69
|
+
|
|
70
|
+
WORKDIR /workspace
|
|
71
|
+
|
|
72
|
+
CMD ["mai", "--help"]
|
maind-0.1.0/HANDOFF.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# 交接文档 —— Mindreon Python SDK + CLI
|
|
2
|
+
|
|
3
|
+
> 更新时间: 2026-07-03
|
|
4
|
+
> 目的: 把当前上下文完整交接,任何人(或新会话)据此可无缝接手。
|
|
5
|
+
|
|
6
|
+
## 一句话概况
|
|
7
|
+
|
|
8
|
+
把现有的 `mindreon-cli`(Node.js) 重构为 **Python 的 SDK + CLI 二合一** 包,放进后端仓库既能 `import` 当 SDK、又能命令行当 CLI。**设计与实施计划已完成并提交;代码实现尚未开始(0/8 任务)。**
|
|
9
|
+
|
|
10
|
+
## 背景与动机
|
|
11
|
+
|
|
12
|
+
- 原始诉求: 维护者是 **Python 后端工程师(不会 Node)**,本想做一个放进后端仓库的 **Python SDK,同时具备 SDK 和 CLI 能力**。
|
|
13
|
+
- 现状问题: 现有 `../mindreon-cli` 是 Claude Code 迭代中"跑偏"用 **Node.js** 写出来的(已发布 npm、有 Docker 镜像、v0.1.26)。维护者驾驭不了 Node,且 Node 包无法被 Python 后端 import。
|
|
14
|
+
- 结论: 用 Python 重写。**不是语言偏好,而是**(1) 维护者不会 Node = Node 版是不可维护的黑盒;(2) 目标是"SDK 放后端仓库",Node 架构上做不到。
|
|
15
|
+
|
|
16
|
+
## 关键决策(已定)
|
|
17
|
+
|
|
18
|
+
| # | 决策点 | 结论 |
|
|
19
|
+
|---|--------|------|
|
|
20
|
+
| 1 | 定位 | Python,**SDK 为核心 + CLI 是薄壳**;业务逻辑只写一遍 |
|
|
21
|
+
| 2 | 后端环境 | FastAPI (async) |
|
|
22
|
+
| 3 | sync/async | **双客户端一次到位**:同步核心 + `MindreonClient` / `AsyncMindreonClient`;异步用 `anyio.to_thread` 包同步实现(不追求 git/dvc 的"真异步") |
|
|
23
|
+
| 4 | 认证/配置 | 显式参数 + 环境变量(OpenAI 式)+ `from_config_file()`;`~/.config/mindreon/config.json` 读写**归 CLI 层**,SDK 不碰家目录 |
|
|
24
|
+
| 5 | 外部工具 | git/git-lfs/dvc/modelscope/skopeo 全部 **subprocess + 运行时检测**;核心 SDK 只依赖 httpx/pyyaml(轻);dvc/modelscope 库调用留作未来可选 extras |
|
|
25
|
+
| 6 | 仓库形态 | **单包 `mindreon`**,SDK + CLI 同包 |
|
|
26
|
+
|
|
27
|
+
三个方法级默认(可推翻,已写进 spec 的"默认决策"节):
|
|
28
|
+
- `create_model` / `create_dataset` **分开**(不合并成 `create(kind,...)`)
|
|
29
|
+
- `ref` 用字符串 `"model:name"` 为主,也接受 `ResourceRef(kind,name)`
|
|
30
|
+
- 工作区用 **`Workspace` 对象**封装 `status/add/commit/push`
|
|
31
|
+
|
|
32
|
+
## 架构(三层)
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
返回结构化对象 ← SDK 门面(sync + async) ← CLI 薄壳(Typer)
|
|
36
|
+
↑ ↑ ↑
|
|
37
|
+
dataclass MindreonClient 解析参数→调门面→打印
|
|
38
|
+
AsyncMindreonClient
|
|
39
|
+
↑
|
|
40
|
+
_core 内部实现(同步纯逻辑:httpx / subprocess)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
目标目录结构(尚未落地,见 spec):`src/mindreon/{client,async_client,models,errors}.py` + `_core/{settings,transport,routes,resources,workspace,tools,operations/}` + `cli/{app,commands/,config_file}`。
|
|
44
|
+
|
|
45
|
+
## 已产出物(均在本仓库,已提交)
|
|
46
|
+
|
|
47
|
+
| 路径 | 内容 |
|
|
48
|
+
|------|------|
|
|
49
|
+
| `docs/superpowers/specs/2026-07-03-mindreon-sdk-design.md` | 完整设计规格(架构/双客户端/认证/错误/测试/迁移/6 项决策) |
|
|
50
|
+
| `docs/superpowers/plans/2026-07-03-mindreon-sdk-foundation.md` | **实施计划 1**:8 个 TDD 任务,打通架构基座 + login/status 端到端 |
|
|
51
|
+
| `src/mindreon_cli/` + `tests/` | 早期**骨架**(见下),包名仍是旧的 `mindreon_cli`,计划 Task 1 会改名为 `mindreon` |
|
|
52
|
+
|
|
53
|
+
### 现有骨架能干什么(已可运行)
|
|
54
|
+
|
|
55
|
+
- `uv sync` 装环境;`uv run mindreon --help` 列出全部 16 命令;`uv run mindreon status`/`login` 已真实现;其余命令注册为 stub(报 "not yet implemented")。
|
|
56
|
+
- 已通过: `pytest`(15 passed)、`ruff`、`mypy --strict`。
|
|
57
|
+
- ⚠️ 注意: 这套骨架是**按"CLI 移植"思路搭的**,不是 SDK-first。计划 1 会把它重构成三层架构。
|
|
58
|
+
|
|
59
|
+
## 当前状态(精确)
|
|
60
|
+
|
|
61
|
+
- **分支**: `master` (⚠️ 还没开 feature 分支;按 subagent-driven 流程,实现前必须开)
|
|
62
|
+
- **提交历史**:
|
|
63
|
+
- `192cda0` docs: add SDK foundation implementation plan
|
|
64
|
+
- `63e726c` docs: add Mindreon Python SDK + CLI design spec
|
|
65
|
+
- `bc3f989` chore: scaffold Python port skeleton
|
|
66
|
+
- **未提交改动**: `docs/.../2026-07-03-mindreon-sdk-foundation.md` 有一处**已做但未提交**的修正 —— 给 Task 1 补了"改名后同步替换 `tests/` 里对 `mindreon_cli` 的绝对导入"(原计划漏了,会导致 Task 1 测试失败)。
|
|
67
|
+
- **实现进度**: **0 / 8 任务**。尚未执行计划 1 的任何 Task,包名仍为 `mindreon_cli`。
|
|
68
|
+
- **进度 ledger**: 尚未创建(`.superpowers/sdd/progress.md`)。
|
|
69
|
+
|
|
70
|
+
## 下一步(接手就做)
|
|
71
|
+
|
|
72
|
+
1. **提交那处计划修正**,创建功能分支,初始化 ledger:
|
|
73
|
+
```bash
|
|
74
|
+
cd mindreon-cli-py
|
|
75
|
+
git add docs && git commit -m "docs: fix Task 1 to rewrite test imports on rename"
|
|
76
|
+
git checkout -b feature/sdk-foundation
|
|
77
|
+
mkdir -p .superpowers/sdd && printf '# SDD Progress\n\n' > .superpowers/sdd/progress.md
|
|
78
|
+
```
|
|
79
|
+
2. **按 `superpowers:subagent-driven-development` 流程执行计划 1** 的 Task 1→8:
|
|
80
|
+
每个 Task 派一个全新 implementer 子代理(计划里含完整代码,多为机械转录,用便宜模型即可),完成后派 reviewer 子代理审(spec 合规 + 代码质量),有 Critical/Important 问题派 fix 子代理,再复审,通过后记 ledger、下一个 Task。全程连续执行,不中途 check-in。
|
|
81
|
+
3. **计划 1 完成后**,做整分支 code review,然后用 `superpowers:finishing-a-development-branch` 收尾。
|
|
82
|
+
4. **后续计划(各自独立成文再执行)**:
|
|
83
|
+
- 计划 2: `project` + `create`
|
|
84
|
+
- 计划 3: `connect` + `download` + `repo`(首次引入 `Workspace` / subprocess / `tools.py`)
|
|
85
|
+
- 计划 4: `publish` + `file` + `image` + `seed`
|
|
86
|
+
|
|
87
|
+
## 快速上手(验证环境)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cd mindreon-cli-py
|
|
91
|
+
uv sync
|
|
92
|
+
uv run mindreon --help
|
|
93
|
+
MAI_CONFIG_DIR=/tmp/mr uv run mindreon status
|
|
94
|
+
uv run pytest -q # 现有骨架 15 passed
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
调试: VS Code 用 `.vscode/launch.json`(有 `mindreon: status` / `login` / `pytest` 配置)。
|
|
98
|
+
|
|
99
|
+
## 注意事项 / 坑
|
|
100
|
+
|
|
101
|
+
- **Python 版环境变量**: 统一使用 `MAI_*`,例如 `MAI_API_URL`、`MAI_AUTH_TOKEN`、`MAI_CONFIG_DIR`。不要再兼容 Node 版旧前缀。
|
|
102
|
+
- **计划 Task 1 的 `perl -pi -e` 命令**用于替换 tests 引用;macOS 上 `perl` 比 `sed -i` 稳。
|
|
103
|
+
- **不要在 `master` 上直接实现**(subagent-driven 硬规则)。
|
|
104
|
+
- **Node 版参考源**: `../mindreon-cli/src/`。计划里标注 `upload_file`/`seed_*`/`build_image` 的确切参数需在实现对应命令时读 Node 源码(`file.js`/`seed.js`/`image.js`)对齐 —— 但这些属于后续计划 2-4,计划 1 不涉及。
|
|
105
|
+
- **协调者工具怪癖**(本会话所用): `TaskCreate`/`TaskUpdate` 是单条操作(每次一个 `subject`/`taskId`),不接受数组批量。
|
|
106
|
+
|
|
107
|
+
## 参考
|
|
108
|
+
|
|
109
|
+
- 目标产物: 可 `pip install mindreon` → `from mindreon import MindreonClient` / `mindreon <cmd>`。
|
|
110
|
+
- 流程链路: `brainstorming`(设计)→ `writing-plans`(计划)→ `subagent-driven-development`(执行)→ `finishing-a-development-branch`(收尾)。
|
maind-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
IMAGE_NAME ?= mindreon/mai-cli
|
|
2
|
+
IMAGE_TAG ?= latest
|
|
3
|
+
IMAGE ?= $(IMAGE_NAME):$(IMAGE_TAG)
|
|
4
|
+
PLATFORMS ?= linux/amd64,linux/arm64
|
|
5
|
+
BUILDER ?= mai-cli-builder
|
|
6
|
+
TWINE ?= uv run --with twine twine
|
|
7
|
+
|
|
8
|
+
.PHONY: help install dev run test cov lint format typecheck build package-check release-check publish-pypi publish-testpypi publish-pip clean buildx-create image-build-local image-push image-build-push image-buildx image-buildx-push image-run-help
|
|
9
|
+
|
|
10
|
+
help: ## Show this help
|
|
11
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
|
|
12
|
+
awk 'BEGIN {FS = ":.*?## "}; {printf " %-12s %s\n", $$1, $$2}'
|
|
13
|
+
|
|
14
|
+
install: ## Create venv and install package + dev deps (editable)
|
|
15
|
+
uv sync
|
|
16
|
+
|
|
17
|
+
dev: install ## Alias for install
|
|
18
|
+
|
|
19
|
+
run: ## Run the CLI, e.g. make run ARGS="status"
|
|
20
|
+
uv run mai $(ARGS)
|
|
21
|
+
|
|
22
|
+
test: ## Run the test suite
|
|
23
|
+
uv run pytest
|
|
24
|
+
|
|
25
|
+
cov: ## Run tests with coverage report
|
|
26
|
+
uv run pytest --cov=mai --cov-report=term-missing
|
|
27
|
+
|
|
28
|
+
lint: ## Lint with ruff
|
|
29
|
+
uv run ruff check src tests
|
|
30
|
+
|
|
31
|
+
format: ## Auto-format with ruff
|
|
32
|
+
uv run ruff format src tests
|
|
33
|
+
|
|
34
|
+
typecheck: ## Static type check with mypy
|
|
35
|
+
uv run mypy
|
|
36
|
+
|
|
37
|
+
build: ## Build wheel + sdist into dist/
|
|
38
|
+
uv build
|
|
39
|
+
|
|
40
|
+
package-check: build ## Check dist/* package metadata
|
|
41
|
+
$(TWINE) check dist/*
|
|
42
|
+
|
|
43
|
+
release-check: lint typecheck test package-check ## Run all checks before publishing
|
|
44
|
+
|
|
45
|
+
publish-pypi: package-check ## Publish dist/* to PyPI using PYPI_USERNAME/PYPI_PASSWORD
|
|
46
|
+
@username="$${PYPI_USERNAME:-$${TWINE_USERNAME:-}}"; \
|
|
47
|
+
password="$${PYPI_PASSWORD:-$${TWINE_PASSWORD:-}}"; \
|
|
48
|
+
if [ -z "$$username" ] || [ -z "$$password" ]; then \
|
|
49
|
+
echo "Set PYPI_USERNAME and PYPI_PASSWORD before publishing."; \
|
|
50
|
+
exit 1; \
|
|
51
|
+
fi; \
|
|
52
|
+
TWINE_USERNAME="$$username" TWINE_PASSWORD="$$password" $(TWINE) upload --verbose dist/*
|
|
53
|
+
|
|
54
|
+
publish-testpypi: package-check ## Publish dist/* to TestPyPI
|
|
55
|
+
@username="$${PYPI_USERNAME:-$${TWINE_USERNAME:-}}"; \
|
|
56
|
+
password="$${PYPI_PASSWORD:-$${TWINE_PASSWORD:-}}"; \
|
|
57
|
+
if [ -z "$$username" ] || [ -z "$$password" ]; then \
|
|
58
|
+
echo "Set PYPI_USERNAME and PYPI_PASSWORD before publishing."; \
|
|
59
|
+
exit 1; \
|
|
60
|
+
fi; \
|
|
61
|
+
TWINE_USERNAME="$$username" TWINE_PASSWORD="$$password" \
|
|
62
|
+
TWINE_REPOSITORY_URL="https://test.pypi.org/legacy/" \
|
|
63
|
+
$(TWINE) upload --verbose dist/*
|
|
64
|
+
|
|
65
|
+
publish-pip: package-check ## Publish dist/* to custom PYPI_REPOSITORY_URL
|
|
66
|
+
@username="$${PYPI_USERNAME:-$${TWINE_USERNAME:-}}"; \
|
|
67
|
+
password="$${PYPI_PASSWORD:-$${TWINE_PASSWORD:-}}"; \
|
|
68
|
+
url="$${PYPI_REPOSITORY_URL:-$${TWINE_REPOSITORY_URL:-}}"; \
|
|
69
|
+
if [ -z "$$url" ]; then \
|
|
70
|
+
echo "Set PYPI_REPOSITORY_URL for custom pip repository publishing."; \
|
|
71
|
+
exit 1; \
|
|
72
|
+
fi; \
|
|
73
|
+
if [ -z "$$username" ] || [ -z "$$password" ]; then \
|
|
74
|
+
echo "Set PYPI_USERNAME and PYPI_PASSWORD before publishing."; \
|
|
75
|
+
exit 1; \
|
|
76
|
+
fi; \
|
|
77
|
+
TWINE_USERNAME="$$username" TWINE_PASSWORD="$$password" TWINE_REPOSITORY_URL="$$url" \
|
|
78
|
+
$(TWINE) upload --verbose dist/*
|
|
79
|
+
|
|
80
|
+
clean: ## Remove build/venv artifacts
|
|
81
|
+
rm -rf dist build .pytest_cache .ruff_cache .mypy_cache **/__pycache__
|
|
82
|
+
|
|
83
|
+
buildx-create: ## Create or select Docker buildx builder
|
|
84
|
+
@if ! docker buildx inspect $(BUILDER) >/dev/null 2>&1; then \
|
|
85
|
+
docker buildx create --name $(BUILDER) --use; \
|
|
86
|
+
else \
|
|
87
|
+
docker buildx use $(BUILDER); \
|
|
88
|
+
fi
|
|
89
|
+
docker buildx inspect --bootstrap >/dev/null
|
|
90
|
+
|
|
91
|
+
image-build-local: ## Build local Docker image
|
|
92
|
+
docker build -t $(IMAGE) .
|
|
93
|
+
|
|
94
|
+
image-push: ## Push Docker image
|
|
95
|
+
docker push $(IMAGE)
|
|
96
|
+
|
|
97
|
+
image-build-push: image-build-local image-push ## Build and push Docker image
|
|
98
|
+
|
|
99
|
+
image-buildx: buildx-create ## Build multi-platform image without pushing
|
|
100
|
+
docker buildx build \
|
|
101
|
+
--platform $(PLATFORMS) \
|
|
102
|
+
-t $(IMAGE) \
|
|
103
|
+
.
|
|
104
|
+
|
|
105
|
+
image-buildx-push: buildx-create ## Build and push multi-platform image
|
|
106
|
+
docker buildx build \
|
|
107
|
+
--platform $(PLATFORMS) \
|
|
108
|
+
-t $(IMAGE) \
|
|
109
|
+
--push \
|
|
110
|
+
.
|
|
111
|
+
|
|
112
|
+
image-run-help: ## Run mai --help in Docker image
|
|
113
|
+
docker run --rm $(IMAGE) mai --help
|