AITuberFlowへの貢献に興味を持っていただきありがとうございます!このドキュメントでは、貢献のガイドラインと手順を説明します。
このプロジェクトは行動規範に従います。参加することで、この規範を遵守することが期待されます。
以下の種類の貢献を歓迎します:
- バグ修正 - 既存コードの問題を修正
- 新しいプラグイン - 機能を拡張する新しいノードの追加
- ドキュメント - ドキュメントの改善や翻訳
- 機能強化 - 既存コードへの新機能追加
- テスト - テストカバレッジの追加や改善
- 新しいIssueを作成する前に既存のIssueを確認してください
- 利用可能な場合はIssueテンプレートを使用してください
- バグの場合は明確な再現手順を提供してください
- 関連する環境情報を含めてください
- Node.js 22以上
- Python 3.11以上
- Git
ワンクリックで開発環境を構築できます。
- リポジトリをフォークしてクローン
git clone https://github.com/YOUR_USERNAME/AITuberFlow.git
cd AITuberFlow- バックエンドのセットアップ
cd apps/server
# uvを使用(推奨)
uv sync
uv pip install -e ../../packages/sdk
# またはpipを使用
python -m venv .venv
source .venv/bin/activate # Windowsの場合: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e ../../packages/sdk
# 環境設定をコピー
cp .env.example .env- フロントエンドのセットアップ
cd apps/web
npm install
cp .env.example .env.local- 開発サーバーを起動
# ターミナル1: バックエンド
cd apps/server
uv run python main.py # またはvenvを有効化してpython main.py
# ターミナル2: フロントエンド
cd apps/web
npm run devわかりやすいブランチ名を使用してください:
feature/twitter連携追加- 新機能fix/音声再生問題- バグ修正docs/readme更新- ドキュメント変更plugin/画像生成- 新しいプラグイン
明確で簡潔なコミットメッセージを日本語で書いてください:
type: 簡潔な説明
必要に応じて詳細な説明。
「何を」だけでなく「なぜ」を説明。
タイプ:
feat: 新機能fix: バグ修正docs: ドキュメント変更plugin: 新規または更新されたプラグインrefactor: コードリファクタリングtest: テストの追加や更新chore: メンテナンスタスク
例:
feat: Discord チャット連携ノードを追加
fix: Safari での音声再生タイミング問題を解決
docs: プラグイン開発ガイドを更新
-
変更の準備が整っていることを確認
- コードがプロジェクトのコーディング規約に従っている
- ローカルでテストが通過する
- 必要に応じてドキュメントが更新されている
-
プルリクエストを作成
- 明確でわかりやすいタイトルを使用
- 関連するIssueを参照(
Fixes #123) - 変更の概要を提供
- UI変更の場合はスクリーンショットを含める
-
PRレビュー
- メンテナーがPRをレビューします
- 要求された変更に対応してください
- 忍耐強く、レスポンシブに
-
マージ
- 承認後にPRがマージされます
- クリーンな履歴のためにスカッシュマージが推奨されます
plugins/に新しいディレクトリを作成:
plugins/my-plugin/
├── manifest.json
└── node.py
- マニフェストを定義(
manifest.json):
{
"id": "my-plugin",
"name": "マイプラグイン",
"version": "1.0.0",
"description": "プラグインの説明",
"category": "utility",
"inputs": [
{
"id": "text",
"name": "テキスト入力",
"type": "string"
}
],
"outputs": [
{
"id": "result",
"name": "結果",
"type": "string"
}
],
"config": [
{
"id": "setting",
"name": "設定",
"type": "string",
"default": "デフォルト値"
}
]
}- ノードを実装(
node.py):
from aituber_flow_sdk import BaseNode, NodeContext
class MyPluginNode(BaseNode):
async def setup(self, config: dict, context: NodeContext) -> None:
self.setting = config.get("setting", "default")
async def execute(self, inputs: dict, context: NodeContext) -> dict:
text = inputs.get("text", "")
result = f"処理結果: {text}"
return {"result": result}
async def teardown(self) -> None:
pass- フロントエンドに登録(
Sidebar.tsxとCanvas.tsxを更新)
- 1つのプラグインに1つの責任
- エラーを適切に処理
- 意味のあるログメッセージを出力
teardown()でリソースをクリーンアップ- 設定オプションをドキュメント化
- PEP 8スタイルガイドラインに従う
- 可能な限り型ヒントを使用
- I/O操作にはasync/awaitを使用
- パブリック関数にはdocstringでドキュメント化
async def process_message(text: str, config: dict) -> dict:
"""
受信メッセージを処理する。
Args:
text: 処理する入力テキスト
config: 設定辞書
Returns:
処理結果を含む辞書
"""
pass- TypeScript strictモードを使用
- データ構造にインターフェースを定義
- 意味のある変数名を使用
- Reactのベストプラクティスに従う
interface NodeConfig {
id: string;
type: string;
position: { x: number; y: number };
}
const processNode = (config: NodeConfig): void => {
// 実装
};# バックエンドテスト
cd apps/server
uv run pytest -v
# フロントエンドテスト(利用可能な場合)
cd apps/web
npm test- エッジケースとエラー条件をテスト
- わかりやすいテスト名を使用
- 外部サービスをモック
@pytest.mark.asyncio
async def test_node_handles_empty_input():
node = MyPluginNode()
result = await node.execute({"text": ""}, mock_context)
assert result["result"] == "処理結果: "- 新機能の追加時
- 既存の動作の変更時
- 新しいプラグインの追加時
- APIエンドポイントの変更時
| ファイル | 日本語 | 英語 |
|---|---|---|
| README | README.md |
README.en.md |
| はじめに | docs/getting-started.ja.md |
docs/getting-started.md |
| アーキテクチャ | docs/architecture.ja.md |
docs/architecture.md |
| APIリファレンス | docs/api-reference.ja.md |
docs/api-reference.md |
| SDK | packages/sdk/README.md |
- |
貢献について質問がある場合:
- 既存のドキュメントを確認
- クローズされたIssueを検索
- 「question」ラベルを付けて新しいIssueを開く
AITuberFlowへの貢献ありがとうございます!