Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ dist
deploy/k8s/kubeconfig-*.yaml
.pnpm-store
/nodeskclaw/
.venv/
__pycache__/
*.pyc
.pytest_cache
.mypy_cache
*.egg-info/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ npm install -g @nodeskai/genehub
|---|---|
| [`@nodeskai/genehub`](https://www.npmjs.com/package/@nodeskai/genehub) | CLI 命令行工具 |
| [`@nodeskai/genehub-sdk`](https://www.npmjs.com/package/@nodeskai/genehub-sdk) | TypeScript SDK(Adapters + Learning Engine) |
| `genehub-sdk` (PyPI / `packages/sdk/python`) | Python SDK(最小可用:Client + Adapter + GenericAdapter + LearningEngine) |
| [`@nodeskai/genehub-types`](https://www.npmjs.com/package/@nodeskai/genehub-types) | 共享类型定义与 Zod Schemas |

## 快速开始
Expand Down Expand Up @@ -210,6 +211,7 @@ genehub/
│ │ ├── AGENTS.md # Curator 系统提示词
│ │ └── listener.ts # 事件监听器(LISTEN/NOTIFY)
│ ├── sdk/typescript/ # @nodeskai/genehub-sdk - TypeScript SDK + Adapters
│ ├── sdk/python/ # genehub-sdk - Python SDK(Client + Adapter + GenericAdapter + LearningEngine)
│ ├── cli/ # @nodeskai/genehub - 命令行工具 (Commander.js)
│ └── web/ # 基因仓库 Web UI (React + Vite + Tailwind)
├── genes/ # 官方基因库
Expand Down
24 changes: 16 additions & 8 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ GitHub OAuth API Key
| 搜索引擎 | PostgreSQL ILIKE(当前)/ Meilisearch(Future) | 先简后繁 |
| CLI | TypeScript (tsx) | 跨平台,npm 全局安装 |
| Web 前端 | React 19 + Vite 7 + Tailwind CSS 4 + Radix UI | 基因浏览、搜索、API Key 管理(6 个页面) |
| SDK | TypeScript(已实现)+ Python(Future) | 覆盖主流 Agent 开发语言 |
| SDK | TypeScript(已实现)+ Python(已实现最小可用) | 覆盖主流 Agent 开发语言 |
| 分发 | npm + pip + GitHub Releases | 兼容主流包管理器 |
| Git Hooks | lefthook | pre-commit 执行 Biome lint |

Expand Down Expand Up @@ -725,11 +725,19 @@ genehub/
│ │ └── package.json
│ │
│ ├── sdk/
│ │ └── typescript/ # TypeScript SDK(@nodeskai/genehub-sdk)
│ │ └── src/
│ │ ├── client.ts # GeneHub API 客户端
│ │ ├── learning/ # 标准学习协议引擎(L1/L2)
│ │ └── adapters/ # 产品适配器(openclaw / nanobot / generic)
│ │ ├── typescript/ # TypeScript SDK(@nodeskai/genehub-sdk)
│ │ │ └── src/
│ │ │ ├── client.ts # GeneHub API 客户端
│ │ │ ├── learning/ # 标准学习协议引擎(L1/L2)
│ │ │ └── adapters/ # 产品适配器(openclaw / nanobot / generic)
│ │ └── python/ # Python SDK(genehub-sdk,最小可用)
│ │ ├── pyproject.toml
│ │ ├── src/genehub_sdk/
│ │ │ ├── client.py # GeneHubClient
│ │ │ ├── types.py # Gene / GeneManifest / 适配器类型
│ │ │ ├── adapters/ # GeneAdapter 基类 + GenericAdapter
│ │ │ └── learning/ # LearningEngine
│ │ └── tests/
│ │
│ ├── cli/ # 命令行工具(@nodeskai/genehub)
│ │ └── src/
Expand Down Expand Up @@ -774,7 +782,7 @@ genehub/
```

> **未实现的目录**(计划中):
> - `packages/sdk/python/` — Python SDK(M3 计划
> - ~~`packages/sdk/python/`~~ — Python SDK 已实现最小可用(Client + Adapter + GenericAdapter + LearningEngine
> - `adapters/` — 安装方式兼容层(clawhub / npm / pip,后续扩展)
> - `genes/rules/`、`genes/protocols/` — 规则类、协议类基因(当前仅有 skills 分类)

Expand Down Expand Up @@ -1359,7 +1367,7 @@ MINIMAX_API_KEY: sk-xxx
- [x] Web 版本历史展开查看文件内容和安装命令
- [x] GitHub OAuth + API Key 认证 + 管理员角色
- [x] GitHub Actions CI/CD(lint + build + test + npm publish + Docker deploy + K8s rolling update)
- [ ] Python SDK
- [x] Python SDK(最小可用:GeneHubClient、GeneAdapter、GenericAdapter、LearningEngine)
- [ ] npm / pip 分发支持
- [ ] 基因效能数据聚合与排行
- [ ] 全文搜索升级(Meilisearch)
Expand Down
96 changes: 96 additions & 0 deletions packages/sdk/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# GeneHub Python SDK

GeneHub 的 Python 客户端与产品适配层,与 TypeScript SDK 核心能力对齐,供 Python 侧 Agent 接入 GeneHub。

## 用途

- **GeneHubClient**:封装 Registry HTTP API,支持搜索基因、获取详情、获取 Manifest、发布基因。
- **GeneAdapter**:产品适配器抽象基类,定义 `detect` / `install` / `uninstall` / `is_installed` / `list`。
- **GenericAdapter**:基于文件系统的通用适配器,将基因写入 `.genehub/genes/`(可配置目录)。
- **LearningEngine**:标准学习协议引擎,创建学习任务、检查结果(最小可用)。

## 目录结构

```
packages/sdk/python/
├── pyproject.toml
├── README.md
├── src/
│ └── genehub_sdk/
│ ├── __init__.py
│ ├── client.py # GeneHubClient
│ ├── types.py # Gene / GeneManifest / 适配器相关类型
│ ├── adapters/
│ │ ├── __init__.py
│ │ ├── base.py # GeneAdapter 抽象基类
│ │ └── generic.py # GenericAdapter
│ └── learning/
│ ├── __init__.py
│ └── engine.py # LearningEngine
└── tests/
├── test_client.py
├── test_generic_adapter.py
└── test_learning_engine.py
```

## 使用方法

### 安装

在项目根目录使用 uv(推荐):

```bash
uv add ./packages/sdk/python
# 或从 PyPI(发布后):uv add genehub-sdk
```

### 客户端

```python
from genehub_sdk import GeneHubClient

client = GeneHubClient(base_url="https://registry.genehub.dev", token="ghb_xxx")
genes = client.search_genes(q="code")

Copilot AI Mar 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README 示例里调用了 client.search_genes(q="code"),但 GeneHubClient.search_genes 的参数名是 query(或直接用第一个位置参数)。按当前示例会触发 TypeError: unexpected keyword argument 'q';建议将示例改为 client.search_genes("code")client.search_genes(query="code")

Suggested change
genes = client.search_genes(q="code")
genes = client.search_genes(query="code")

Copilot uses AI. Check for mistakes.
gene = client.get_gene("clean-code")
manifest = client.get_manifest("clean-code", version="1.0.0")
published = client.publish(manifest)
```

### 适配器

```python
from genehub_sdk import GenericAdapter
from genehub_sdk.adapters import GeneAdapter

adapter: GeneAdapter = GenericAdapter(genes_dir="/path/to/genes")
if adapter.detect():
adapter.install(manifest, options={"force": True})
adapter.uninstall("clean-code")
print(adapter.list())
```

### 学习引擎

```python
from genehub_sdk import GeneHubClient
from genehub_sdk.adapters import GenericAdapter
from genehub_sdk.learning import LearningEngine

engine = LearningEngine(workspace_dir=".", adapter=GenericAdapter(), client=GeneHubClient(...))
task = engine.create_learning_task(manifest)
result = engine.check_result(manifest["slug"])
```

## 技术栈

- Python 3.12+
- httpx(HTTP 客户端)
- PyYAML(Manifest 序列化)
- 测试:pytest、pytest-httpx
- Lint:Ruff

## 参考

- TypeScript SDK:`packages/sdk/typescript/src/`
- API 文档:`docs/architecture.md` 第 6 节
- 学习协议:`docs/gene-learning-protocol.md`
39 changes: 39 additions & 0 deletions packages/sdk/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[project]
name = "genehub-sdk"
version = "0.1.0"
description = "GeneHub Python SDK - API 客户端与产品适配器(最小可用)"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"httpx>=0.27.0",
"pyyaml>=6.0",
]

[project.optional-dependencies]
dev = [
"pytest>=8.0.0",
"pytest-httpx>=0.30.0",
"ruff>=0.8.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/genehub_sdk"]

[tool.ruff]
target-version = "py312"
line-length = 100

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "C4", "SIM"]
ignore = ["E501"]

[tool.ruff.lint.isort]
known-first-party = ["genehub_sdk"]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
27 changes: 27 additions & 0 deletions packages/sdk/python/src/genehub_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""GeneHub Python SDK:API 客户端与产品适配器。"""

from genehub_sdk.adapters import GeneAdapter, GenericAdapter
from genehub_sdk.client import GeneHubClient, GeneHubError
from genehub_sdk.learning import LearningEngine
from genehub_sdk.types import (
Gene,
GeneManifest,
InstalledGene,
InstallOptions,
InstallResult,
UninstallResult,
)

__all__ = [
"GeneHubClient",
"GeneHubError",
"Gene",
"GeneManifest",
"GeneAdapter",
"GenericAdapter",
"InstallOptions",
"InstallResult",
"InstalledGene",
"UninstallResult",
"LearningEngine",
]
6 changes: 6 additions & 0 deletions packages/sdk/python/src/genehub_sdk/adapters/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""产品适配器:基类与 Generic 文件系统适配器。"""

from genehub_sdk.adapters.base import GeneAdapter
from genehub_sdk.adapters.generic import GenericAdapter

__all__ = ["GeneAdapter", "GenericAdapter"]
56 changes: 56 additions & 0 deletions packages/sdk/python/src/genehub_sdk/adapters/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""产品适配器抽象基类,与 types/adapter.ts GeneAdapter 对齐。"""

from abc import ABC, abstractmethod

from genehub_sdk.types import (
GeneManifest,
InstalledGene,
InstallOptions,
InstallResult,
UninstallOptions,
UninstallResult,
)


class GeneAdapter(ABC):
"""将 Gene Manifest 注入到目标产品的适配器接口。"""

@property
@abstractmethod
def product(self) -> str:
"""产品标识,如 generic / openclaw / nanobot。"""
...

@abstractmethod
def detect(self) -> bool:
"""检测当前环境是否支持该适配器。"""
...

@abstractmethod
def install(
self, manifest: GeneManifest, options: InstallOptions | None = None
) -> InstallResult:
"""安装基因。"""
...

@abstractmethod
def uninstall(self, slug: str, options: UninstallOptions | None = None) -> UninstallResult:
"""卸载基因。"""
...

@abstractmethod
def is_installed(self, slug: str) -> bool:
"""是否已安装该基因。"""
...

@abstractmethod
def list(self) -> list[InstalledGene]:
"""列出已安装的基因。"""
...

def get_installed_version(self, slug: str) -> str | None:
"""返回已安装版本号,未安装返回 None。默认通过 list 查找。"""
for g in self.list():
if g["slug"] == slug:
return g["version"]
return None
Loading