本ドキュメントは、コーディングエージェントのメインエントリーポイント(main.py)とタスク処理の中核を担うTaskHandler(handlers/task_handler.py)の詳細設計を記述します。
- GitHub/GitLabからタスク(Issue/PR/MR)を取得
- LLMを使用してタスクを自動処理
- Producer/Consumerパターンによる柔軟な実行モード
- 継続動作モードでのバックグラウンド処理
- タスクソース: GitHub、GitLab
- タスクタイプ: Issue、Pull Request、Merge Request
- 処理モード:
- Producer(タスク取得)
- Consumer(タスク処理)
- 統合モード(Producer + Consumer)
- 継続動作モード(Docker Compose用)
処理内容: ログ設定を初期化する関数です。
詳細処理:
- 環境変数
LOGSからログファイルパスを取得(デフォルト:logs/agent.log) - 環境変数
DEBUGに基づいてログレベルを決定DEBUG=true: DEBUGレベル- それ以外: INFOレベル
logging.confファイルから設定を読み込み、ロガーを初期化
パラメータ: なし
戻り値: なし
処理内容: 設定ファイルを読み込み、環境変数で上書きする関数です。
詳細処理:
- YAMLファイルから基本設定を読み込み
- 以下の関数を順次呼び出して環境変数で設定を上書き:
_override_task_source_config(): タスクソース設定_override_database_config(): データベース設定_override_user_config_api(): ユーザー設定API設定_override_github_config(): GitHub設定_override_gitlab_config(): GitLab設定_override_mcp_config(): MCPサーバー設定_override_rabbitmq_config(): RabbitMQ設定_override_bot_config(): ボット名設定_override_llm_config(): LLM設定_override_feature_flags(): 機能フラグ設定_override_executor_config(): 実行環境設定
- 上書き済みの設定辞書を返す
パラメータ:
config_file: 設定ファイルのパス(デフォルト: "config.yaml")
戻り値:
dict[str, Any]: 上書き済みの設定辞書
例外:
FileNotFoundError: 設定ファイルが見つからない場合yaml.YAMLError: YAML解析に失敗した場合
処理内容: タスクのユーザーに基づいて設定を取得する関数です。
詳細処理:
user_config_api.enabledフラグを確認- フラグが
falseの場合、base_configをそのまま返す - フラグが
trueの場合:- タスクからユーザー名を取得(
task.get_user()) - ユーザー名が取得できない場合、警告ログを出力して
base_configを返す _fetch_config_from_api()を呼び出してAPI経由で設定を取得- エラー発生時は警告ログを出力して
base_configを返す
- タスクからユーザー名を取得(
パラメータ:
task: タスクオブジェクトbase_config: ベースとなる設定辞書
戻り値:
dict[str, Any]: ユーザー設定でマージされた設定辞書
処理内容: タスクを取得してキューに追加する関数です。
詳細処理:
TaskGetter.factory()でタスクゲッターインスタンスを生成PauseResumeManagerを使用して一時停止中のタスクを検出- 一時停止タスクごとに:
- タスクがまだ存在するか確認
- 存在する場合、再開用のタスク辞書を準備してキューに投入
- エラー時は例外ログを出力して次のタスクへ
task_getter.get_task_list()で新規タスクリストを取得- 各タスクに対して:
task.prepare()で準備処理(ラベル付与など)を実行- タスクキーを辞書形式に変換
- UUID v4を生成して追加
- ユーザー情報を取得して追加
- ユーザー情報が取得できない場合はエラーログを出力してスキップ
- タスク辞書をキューに追加
- 追加したタスク数をログ出力
パラメータ:
config: アプリケーション設定辞書mcp_clients: MCPクライアントの辞書task_source: タスクソース("github" または "gitlab")task_queue: タスクキューオブジェクトlogger: ログ出力用のロガー
戻り値: なし
処理内容: キューからタスクを取得して処理する関数です。
詳細処理:
- 設定からMCPクライアント、config、task_sourceを取得
TaskGetter.factory()でタスクゲッターインスタンスを生成- 無限ループで以下を実行:
task_queue.get()でタスクキーを取得- タイムアウトした場合(
Noneが返る)はループを終了 task_getter.from_task_key()でTaskインスタンスを生成- タスクが無効な場合はエラーログを出力して次のタスクへ
- タスクにUUIDとユーザー情報を設定
- 再開タスクフラグを設定
fetch_user_config()でユーザー固有の設定を取得- ハンドラーの設定を更新
- 再開タスクでない場合、
task.check()で状態確認 handler.handle(task)でタスク処理を実行- エラー発生時は例外ログを出力し、タスクにエラーコメントを追加してfinish()
パラメータ:
task_queue: タスクキューオブジェクトhandler: タスク処理ハンドラーlogger: ログ出力用のロガーtask_config: タスク設定情報(mcp_clients、config、task_sourceを含む)
戻り値: なし
処理内容: Producer継続動作モードで定期的にタスクを取得する関数です。
詳細処理:
- 設定から継続動作モードの設定を取得
- ヘルスチェックディレクトリを作成
- 初回実行遅延設定を確認し、必要に応じて待機
- 無限ループで以下を実行:
- 一時停止シグナルの確認(
contexts/pause_signalの存在確認) - シグナルがある場合はループを終了
- ヘルスチェックファイルを更新
produce_tasks()を実行- エラー発生時は例外ログを出力して次のサイクルへ
- 設定された間隔(分)だけ待機(一時停止シグナルを定期的にチェック)
- 一時停止シグナルの確認(
パラメータ:
config: アプリケーション設定辞書mcp_clients: MCPクライアントの辞書task_source: タスクソースtask_queue: タスクキューオブジェクトlogger: ログ出力用のロガー
戻り値: なし
処理内容: Consumer継続動作モードで継続的にタスクを処理する関数です。
詳細処理:
- 設定から継続動作モードの設定を取得
- ヘルスチェックディレクトリを作成
- 最終ヘルスチェック更新時刻を初期化
- 無限ループで以下を実行:
- 一時停止シグナルの確認
- シグナルがある場合はループを終了
- 定期的にヘルスチェックファイルを更新
task_queue.get()でタスクキーを取得- タスクが取得できた場合:
task_getter.from_task_key()でTaskインスタンスを生成- タスクにUUIDとユーザー情報を設定
- ユーザー固有の設定を取得
handler.handle(task)でタスク処理を実行- エラー発生時は例外ログを出力してタスクにエラーコメント
- 最小待機時間が設定されている場合は待機
- タスクが取得できない場合:
- 短時間待機して次のサイクルへ
パラメータ:
task_queue: タスクキューオブジェクトhandler: タスク処理ハンドラーlogger: ログ出力用のロガーtask_config: タスク設定情報
戻り値: なし
処理内容: メインエントリーポイント関数です。
詳細処理:
- コマンドライン引数を解析:
--mode: producer/consumer モード指定--continuous: 継続動作モード有効化
- 標準出力・標準エラー出力のラインバッファリング設定
setup_logger()でログ設定を初期化- 環境変数
CONFIG_FILEから設定ファイルパスを取得(デフォルト: "config.yaml") load_config()で設定を読み込み- タスクソース設定を取得
- 継続動作モードの判定(コマンドラインオプション優先)
- MCPクライアントを初期化:
- ファンクションコーリング設定を確認
- 各MCPサーバー設定を処理
- タスクソースに応じて不要なMCPサーバーを除外
- MCPクライアントを生成してfunctionsとtoolsを収集
get_llm_client()でLLMクライアントを初期化- タスクキューを初期化(RabbitMQまたはインメモリ)
TaskHandlerを初期化- 実行モードに応じて分岐:
- Producer mode:
- 継続動作:
run_producer_continuous() - 単発:
produce_tasks()をFileL ockで排他制御して実行
- 継続動作:
- Consumer mode:
- 継続動作:
run_consumer_continuous() - 単発:
consume_tasks()
- 継続動作:
- デフォルトmode (producer + consumer):
produce_tasks()を実行consume_tasks()を実行
- Producer mode:
パラメータ: なし
戻り値: なし
環境変数TASK_SOURCEでタスクソース設定を上書きします。
環境変数DATABASE_URLまたは個別のデータベース設定で上書きします。
DATABASE_HOSTDATABASE_PORTDATABASE_NAMEDATABASE_USERDATABASE_PASSWORD
ユーザー設定API関連の環境変数で上書きします。
USE_USER_CONFIG_APIUSER_CONFIG_API_URLUSER_CONFIG_API_KEY
GitHub関連の環境変数で上書きします。
GITHUB_PERSONAL_ACCESS_TOKENGITHUB_API_URL
GitLab関連の環境変数で上書きします。
GITLAB_PERSONAL_ACCESS_TOKENGITLAB_API_URL
LLM関連の環境変数で上書きします。内部で以下を呼び出し:
_override_lmstudio_config(): LM Studio設定_override_ollama_config(): Ollama設定_override_openai_config(): OpenAI設定
MCP関連の環境変数で上書きします。
GITHUB_MCP_COMMAND- 各MCPサーバーの環境変数を動的に上書き
RabbitMQ関連の環境変数で上書きします。
RABBITMQ_HOSTRABBITMQ_PORTRABBITMQ_USERRABBITMQ_PASSWORDRABBITMQ_QUEUE
機能フラグを環境変数で上書きします。
COMMAND_EXECUTOR_ENABLEDTEXT_EDITOR_MCP_ENABLEDISSUE_TO_MR_ENABLEDPROJECT_AGENT_RULES_ENABLED
実行環境関連の環境変数で上書きします。
EXECUTOR_DEFAULT_ENVIRONMENTEXECUTOR_BASE_IMAGEEXECUTOR_CPU_LIMITEXECUTOR_MEMORY_LIMITEXECUTOR_TIMEOUT
ボット名を環境変数で上書きします。
GITHUB_BOT_NAMEGITLAB_BOT_NAME
flowchart TD
A[main開始] --> B[コマンドライン引数解析]
B --> C[setup_logger]
C --> D[load_config]
D --> E[MCPクライアント初期化]
E --> F[LLMクライアント初期化]
F --> G[TaskQueue初期化]
G --> H[TaskHandler初期化]
H --> I{実行モード?}
I -->|Producer| J{継続モード?}
I -->|Consumer| K{継続モード?}
I -->|デフォルト| L[produce_tasks]
J -->|Yes| M[run_producer_continuous]
J -->|No| N[produce_tasks<br/>with FileLock]
K -->|Yes| O[run_consumer_continuous]
K -->|No| P[consume_tasks]
L --> Q[consume_tasks]
M --> END[終了]
N --> END
O --> END
P --> END
Q --> END
style A fill:#e1f5ff
style END fill:#ffe1e1
flowchart TD
A[produce_tasks開始] --> B[TaskGetter生成]
B --> C[PauseResumeManager生成]
C --> D[一時停止タスク取得]
D --> E{一時停止タスクあり?}
E -->|Yes| F[タスク存在確認]
F -->|存在| G[再開用辞書準備]
F -->|不存在| H[警告ログ]
G --> I[キューに投入]
I --> J[次のタスクへ]
H --> J
J --> E
E -->|No| K[get_task_list]
K --> L{タスクあり?}
L -->|Yes| M[task.prepare]
M --> N[UUID生成]
N --> O[ユーザー情報取得]
O --> P{ユーザー取得成功?}
P -->|Yes| Q[キューに投入]
P -->|No| R[エラーログ]
Q --> S[次のタスクへ]
R --> S
S --> L
L -->|No| T[ログ出力]
T --> END[終了]
style A fill:#e1f5ff
style END fill:#ffe1e1
flowchart TD
A[consume_tasks開始] --> B[TaskGetter生成]
B --> C{キューから取得}
C -->|タスクあり| D[Taskインスタンス生成]
C -->|タイムアウト| END[終了]
D --> E{生成成功?}
E -->|失敗| F[エラーログ]
F --> C
E -->|成功| G[UUID/ユーザー設定]
G --> H[fetch_user_config]
H --> I[ハンドラー設定更新]
I --> J{再開タスク?}
J -->|No| K[task.check]
K --> L{チェックOK?}
L -->|No| M[スキップログ]
M --> C
J -->|Yes| N[handler.handle]
L -->|Yes| N
N --> O{処理成功?}
O -->|成功| C
O -->|失敗| P[例外ログ]
P --> Q[エラーコメント追加]
Q --> R[task.finish]
R --> C
style A fill:#e1f5ff
style END fill:#ffe1e1
TaskHandlerは、LLMクライアントとMCPツールクライアントを統合し、タスクに対する自動化された処理を実行するクラスです。
処理内容: TaskHandlerを初期化します。
詳細処理:
- LLMクライアントを保存
- MCPクライアント辞書を保存
- アプリケーション設定を保存
- ロガーを初期化
パラメータ:
llm_client: LLMクライアントのインスタンスmcp_clients: MCPツールクライアントの辞書config: アプリケーション設定辞書
処理内容: 引数をサニタイズして辞書形式に変換します。
詳細処理:
- 引数が既にdict型の場合、そのまま返す
- 引数がstr型の場合:
- JSONとしてパース
- パース結果がdict型であることを確認
- dict型でない場合はValueError
- その他の型の場合、TypeErrorを発生
パラメータ:
arguments: サニタイズ対象の引数(str、dict、またはlist)
戻り値:
dict[str, Any]: 辞書形式に変換された引数
例外:
ValueError: JSON文字列の解析に失敗した場合TypeError: サポートされていない型の場合
処理内容: タスクを処理するメインメソッドです。
詳細処理:
- Issue→MR/PR変換のチェック:
_should_convert_issue_to_mr()で変換条件を確認- 条件を満たす場合、
_convert_issue_to_mr()を実行 - 変換成功時はタスクステータスを"completed"に更新して終了
- 変換失敗時は通常処理に進む
- 計画機能の有効性を判定
_init_execution_environment()で実行環境を初期化- 処理モードを判定:
- Planning有効かつUUID存在:
_handle_with_planning() - Context Storage有効かつUUID存在:
_handle_with_context_storage() - それ以外:
_handle_legacy()(Legacy モード)
- Planning有効かつUUID存在:
- 最終的に実行環境をクリーンアップ
パラメータ:
task: 処理対象のTaskオブジェクト
戻り値: なし
処理内容: Planning モードでタスクを処理します。
詳細処理:
PlanningCoordinatorをインポートTaskContextManagerを生成- トークン統計記録フックを設定
PlanningCoordinatorを初期化coordinator.execute_task()で計画実行を開始- 処理完了後、タスクステータスを"completed"に更新
- エラー発生時:
- 例外ログを出力
- タスクステータスを"failed"に更新
- エラーメッセージを記録
- タスクにエラーコメントを追加
パラメータ:
task: Taskオブジェクトtask_config: タスク設定辞書execution_manager: 実行環境マネージャー
戻り値: なし
処理内容: Context Storage モードでタスクを処理します。
詳細処理:
TaskContextManagerを生成- トークン統計記録フックを設定
- LLMクライアントのツール定義を更新
_setup_task_handling_with_client()でタスク処理セットアップ- メッセージとツールストアを取得
- 最大LLM処理回数のループで以下を実行:
_process_llm_interaction_with_client()でLLM対話処理- 処理継続フラグがFalseの場合はループを終了
- ループ終了後、タスクステータスを更新
- エラー発生時:
- 例外ログを出力
- タスクステータスを"failed"に更新
- エラーメッセージを記録
- タスクにエラーコメントを追加
パラメータ:
task: Taskオブジェクトtask_config: タスク設定辞書
戻り値: なし
処理内容: Legacy モード(従来のインメモリ処理)でタスクを処理します。
詳細処理:
_setup_task_handling()でタスク処理セットアップ- エラーカウンター辞書を初期化
- 最大LLM処理回数のループで以下を実行:
_process_llm_interaction()でLLM対話処理- 処理継続フラグがFalseの場合はループを終了
- ループ終了後、
task.finish()を呼び出し
パラメータ:
task: Taskオブジェクトtask_config: タスク設定辞書
戻り値: なし
処理内容: 実行環境を初期化します。
詳細処理:
- Command Executor機能の有効性を確認
- 無効の場合はNoneを返す
- 有効の場合:
ExecutionEnvironmentManagerをインポート- マネージャーを生成
- タスクに基づいて実行環境を取得
prepare=Trueの場合、環境を準備- 実行環境のMCPラッパーをmcp_clientsに登録
- マネージャーを返す
パラメータ:
task: Taskオブジェクトconfig: 設定辞書prepare: 環境準備フラグ(デフォルト: False)
戻り値:
ExecutionEnvironmentManagerまたはNone
処理内容: LLMクライアントのツール定義を更新します。
詳細処理:
- ファンクションコーリングが有効か確認
- 無効の場合は何もしない
- 有効の場合:
- 全MCPクライアントからfunctionsとtoolsを収集
llm_client.update_tools()で更新
パラメータ: なし
戻り値: なし
処理内容: 実行環境をクリーンアップします。
詳細処理:
- execution_managerがNoneの場合は何もしない
- それ以外の場合:
execution_manager.cleanup()を呼び出し- エラー発生時は警告ログを出力
- mcp_clientsから実行環境ラッパーを削除
パラメータ:
execution_manager: 実行環境マネージャーtask: Taskオブジェクト
戻り値: なし
処理内容: LLMとの対話処理を実行します(Legacy モード用)。
詳細処理:
llm_client.get_response()でLLM応答を取得<think>タグを処理- JSON部分を抽出
- 応答データを処理:
planフィールド:_process_plan_field()commandフィールド:_process_command_field()doneフィールド:_process_done_field()
- エラー発生時:
- JSONパースエラー: エラーカウント、閾値超過で処理終了
- その他のエラー: 例外ログを出力、処理終了フラグを返す
パラメータ:
task: Taskオブジェクトcount: 現在のループカウントerror_state: エラー状態辞書
戻り値:
bool: 処理継続フラグ(True=継続、False=終了)
処理内容: 関数リストを実行します。
詳細処理:
- 各関数に対して
_execute_single_function()を呼び出し - いずれかの関数で処理終了フラグが返された場合、Falseを返す
- 全関数の実行が完了した場合、Trueを返す
パラメータ:
task: Taskオブジェクトfunctions: 関数リストerror_state: エラー状態辞書
戻り値:
bool: 処理継続フラグ
処理内容: 単一の関数を実行します。
詳細処理:
- 関数から名前と引数を取得
- 引数をサニタイズ
_call_mcp_tool()でMCPツールを呼び出し- MCPエラー発生時:
_handle_mcp_error()でエラー処理- エラーメッセージをLLMに送信
- エラーカウント、閾値超過で処理終了フラグを返す
- その他のエラー発生時:
_handle_general_error()でエラー処理- エラーメッセージをLLMに送信
- 処理終了フラグを返す
パラメータ:
task: Taskオブジェクトfunction: 関数辞書error_state: エラー状態辞書
戻り値:
bool: 処理継続フラグ
処理内容: MCPツールを呼び出します。
詳細処理:
- ツール名を
/で分割してサーバー名とツール名を取得 - MCPクライアントを検索
- クライアントが見つからない場合、KeyErrorを発生
mcp_client.call_tool()でツールを呼び出し- 結果を取得
- 結果が辞書で
outputキーを持つ場合、output値を返す - それ以外の場合、結果をJSON文字列に変換して返す
パラメータ:
task: Taskオブジェクトname: ツール名("サーバー名/ツール名"形式)arguments: ツール引数辞書
戻り値:
str: ツール実行結果
例外:
KeyError: MCPクライアントが見つからない場合McpError: MCPツール呼び出しエラー
処理内容: システムプロンプトを取得します。
詳細処理:
_make_system_prompt()を呼び出してプロンプト文字列を生成- 生成されたプロンプトを返す
パラメータ: なし
戻り値:
str: システムプロンプト文字列
処理内容: システムプロンプトを生成します。
詳細処理:
- ベースとなるシステムプロンプトファイルを読み込み
- MCPクライアントからツール情報を収集してプロンプトに統合
- Command Executor機能が有効な場合、プロンプトを読み込んで追加
- Text Editor MCP機能が有効な場合、プロンプトを読み込んで追加
- プロジェクトエージェントルールを読み込んで追加
- プロジェクトファイル一覧を読み込んで追加
- 完成したプロンプト文字列を返す
パラメータ: なし
戻り値:
str: システムプロンプト文字列
処理内容: テキストからJSON部分を抽出してパースします。
詳細処理:
- テキストから最初の
{と最後の}の位置を検索 - 見つかった場合、その範囲を抽出してJSONとしてパース
- 見つからない場合、ValueError を発生
- JSONパースエラーの場合、エラー情報を含む例外を発生
パラメータ:
text: JSON部分を含むテキスト
戻り値:
dict[str, Any]: パースされたJSON辞書
例外:
ValueError: JSONが見つからない場合またはパースエラー
処理内容: IssueをMR/PRに変換すべきかどうかを判定します。
詳細処理:
- Issue→MR変換機能が有効か確認
- タスクがIssueタイプか確認(
_is_issue_task()) - 両方の条件を満たす場合、Trueを返す
パラメータ:
task: Taskオブジェクトtask_config: タスク設定辞書
戻り値:
bool: 変換すべきかどうか
処理内容: IssueをMR/PRに変換します。
詳細処理:
IssueToMRConverterをインポート- プラットフォームを取得(GitHubまたはGitLab)
- MCPクライアントを取得
- コンバーターを初期化
converter.convert()でIssueをMR/PRに変換- 変換結果を返す
- エラー発生時は例外ログを出力してNoneを返す
パラメータ:
task: Taskオブジェクトtask_config: タスク設定辞書
戻り値:
ConversionResultまたはNone: 変換結果
処理内容: 全モード共通のトークン統計記録フックを設定します。
詳細処理:
- context_managerまたはllm_clientがNoneの場合は何もしない
- 統計記録フック関数を定義:
context_manager.update_statistics()を呼び出し- エラー発生時は警告ログを出力(処理は継続)
llm_client.set_statistics_hook()でフックを設定- フック設定失敗時は警告ログを出力
処理内容: Legacy モード用のトークン統計記録フックを設定します。
詳細処理:
- タスクにUUIDがない場合は何もしない
TaskContextManagerを生成_setup_statistics_hook()でフックを設定- インスタンスを
_statistics_context_managerに保存
処理内容: トークン統計記録フックをクリアします。
詳細処理:
_statistics_context_managerが存在する場合、Noneに設定llm_client.set_statistics_hook(None)でフックをクリア
classDiagram
class TaskHandler {
-LLMClient llm_client
-dict~str,MCPToolClient~ mcp_clients
-dict~str,Any~ config
-Logger logger
-TaskContextManager _statistics_context_manager
+__init__(llm_client, mcp_clients, config)
+sanitize_arguments(arguments) dict
+handle(task) void
+get_system_prompt() str
-_handle_with_planning(task, task_config, execution_manager) void
-_handle_with_context_storage(task, task_config) void
-_handle_legacy(task, task_config) void
-_init_execution_environment(task, config, prepare) ExecutionEnvironmentManager
-_update_llm_client_tools() void
-_cleanup_execution_environment(execution_manager, task) void
-_setup_statistics_hook(context_manager, llm_client) void
-_setup_statistics_hook_for_legacy(task) void
-_clear_statistics_hook() void
-_setup_task_handling(task, task_config) void
-_setup_task_handling_with_client(task, context_manager, execution_manager) tuple
-_process_llm_interaction(task, count, error_state) bool
-_process_llm_interaction_with_client(task, count, msg_store, tool_store, context_manager, execution_manager, error_state) bool
-_process_think_tags(task, resp) str
-_process_response_data(task, data, error_state) bool
-_process_response_data_with_context(task, data, tool_store, context_manager, error_state) bool
-_execute_functions(task, functions, error_state) bool
-_execute_single_function(task, function, error_state) bool
-_call_mcp_tool(task, name, arguments) str
-_handle_mcp_error(task, e, name, error_state) str
-_handle_general_error(task, e, name, error_state) str
-_update_error_count(name, error_state) void
-_process_plan_field(task, data) void
-_process_command_field(task, data, error_state) bool
-_process_done_field(task, data) void
-_make_system_prompt() str
-_load_command_executor_prompt() str
-_load_text_editor_prompt() str
-_load_project_agent_rules() str
-_load_file_list_context() str
-_extract_json(text) dict
-_load_comment_detection_state(task) dict
-_save_comment_detection_state(task, state) void
-_is_issue_task(task) bool
-_should_convert_issue_to_mr(task, task_config) bool
-_convert_issue_to_mr(task, task_config) ConversionResult
-_get_platform_for_task(task) str
-_get_mcp_client_for_task(task) MCPToolClient
-_get_issue_number(task) int
}
class LLMClient {
<<interface>>
+send_system_prompt(prompt)
+send_user_message(message)
+get_response() str
+set_statistics_hook(hook)
+update_tools(functions, tools)
}
class MCPToolClient {
+get_function_calling_functions() list
+get_function_calling_tools() list
+call_tool(name, arguments) Any
}
class Task {
<<interface>>
+uuid str
+user str
+is_resumed bool
+prepare()
+get_prompt() str
+comment(message)
+update_comment(comment_id, message)
+finish()
+check() bool
+get_task_key() TaskKey
+get_user() str
}
class TaskContextManager {
+update_statistics(llm_calls, tokens)
+get_metadata() dict
+update_status(status)
+complete()
+fail(error_message)
}
class ExecutionEnvironmentManager {
+get_environment(task) Any
+cleanup()
}
class PlanningCoordinator {
+execute_task(task)
}
TaskHandler --> LLMClient : uses
TaskHandler --> MCPToolClient : uses
TaskHandler --> Task : processes
TaskHandler --> TaskContextManager : manages
TaskHandler --> ExecutionEnvironmentManager : manages
TaskHandler --> PlanningCoordinator : uses
flowchart TD
A[handle開始] --> B{Issue→MR変換?}
B -->|Yes| C[_convert_issue_to_mr]
C --> D{変換成功?}
D -->|Yes| E[ステータス更新<br/>completed]
E --> END[終了]
D -->|No| F[通常処理継続]
B -->|No| F
F --> G[計画機能判定]
G --> H[_init_execution_environment]
H --> I{処理モード?}
I -->|Planning| J[_handle_with_planning]
I -->|Context Storage| K[_handle_with_context_storage]
I -->|Legacy| L[_handle_legacy]
J --> M[_cleanup_execution_environment]
K --> M
L --> M
M --> END
style A fill:#e1f5ff
style END fill:#ffe1e1
flowchart TD
A[_handle_with_planning開始] --> B[TaskContextManager生成]
B --> C[統計フック設定]
C --> D[PlanningCoordinator初期化]
D --> E[coordinator.execute_task]
E --> F{処理成功?}
F -->|成功| G[ステータス更新<br/>completed]
F -->|失敗| H[例外ログ]
H --> I[ステータス更新<br/>failed]
I --> J[エラーメッセージ記録]
J --> K[エラーコメント追加]
G --> END[終了]
K --> END
style A fill:#e1f5ff
style END fill:#ffe1e1
flowchart TD
A[_process_llm_interaction開始] --> B[llm_client.get_response]
B --> C[thinkタグ処理]
C --> D[JSON抽出]
D --> E{JSON抽出成功?}
E -->|失敗| F[エラーカウント]
F --> G{閾値超過?}
G -->|Yes| H[処理終了フラグ]
G -->|No| I[処理継続フラグ]
E -->|成功| J[_process_response_data]
J --> K{処理継続?}
K -->|Yes| I
K -->|No| H
H --> END[False返却]
I --> END2[True返却]
style A fill:#e1f5ff
style END fill:#ffe1e1
style END2 fill:#ffe1e1
flowchart TD
A[_execute_single_function開始] --> B[関数情報取得]
B --> C[引数サニタイズ]
C --> D[_call_mcp_tool]
D --> E{エラー?}
E -->|McpError| F[_handle_mcp_error]
E -->|その他| G[_handle_general_error]
E -->|成功| H[結果をLLMに送信]
F --> I[エラーカウント]
I --> J{閾値超過?}
J -->|Yes| K[処理終了フラグ]
J -->|No| L[処理継続フラグ]
G --> M[エラーをLLMに送信]
M --> K
H --> L
K --> END[False返却]
L --> END2[True返却]
style A fill:#e1f5ff
style END fill:#ffe1e1
style END2 fill:#ffe1e1
sequenceDiagram
participant Main as main()
participant Config as load_config()
participant MCP as MCPToolClient
participant LLM as LLMClient
participant Queue as TaskQueue
participant Handler as TaskHandler
participant Producer as produce_tasks()
participant Consumer as consume_tasks()
participant Task as Task
Main->>Config: 設定読み込み
Config-->>Main: config
Main->>MCP: MCPクライアント初期化
MCP-->>Main: mcp_clients
Main->>LLM: LLMクライアント初期化
LLM-->>Main: llm_client
Main->>Queue: キュー初期化
Queue-->>Main: task_queue
Main->>Handler: ハンドラー初期化
Handler-->>Main: handler
alt Producer mode
Main->>Producer: タスク取得
Producer->>Task: タスクリスト取得
Task-->>Producer: tasks
Producer->>Queue: タスク投入
end
alt Consumer mode
Main->>Consumer: タスク処理
loop キューが空になるまで
Consumer->>Queue: タスク取得
Queue-->>Consumer: task_key_dict
Consumer->>Task: Taskインスタンス生成
Task-->>Consumer: task
Consumer->>Handler: handle(task)
Handler->>Task: 処理実行
end
end
sequenceDiagram
participant Handler as TaskHandler
participant CTX as TaskContextManager
participant PC as PlanningCoordinator
participant LLM as LLMClient
participant MCP as MCPToolClient
participant Task as Task
Handler->>CTX: TaskContextManager生成
CTX-->>Handler: context_manager
Handler->>LLM: 統計フックを設定
Handler->>PC: PlanningCoordinator初期化
PC-->>Handler: coordinator
Handler->>PC: execute_task(task)
loop Planning process
PC->>LLM: get_response()
LLM-->>PC: response
PC->>PC: プロンプト解析
alt ツール呼び出し
PC->>MCP: call_tool()
MCP-->>PC: result
PC->>LLM: send_user_message(result)
end
PC->>Task: comment(進捗)
PC->>CTX: update_statistics()
end
PC->>Task: finish()
PC->>CTX: complete()
PC-->>Handler: 完了
- 発生条件: LLM応答からJSON抽出に失敗
- 対応: エラーカウント、最大5回までリトライ
- 処理: 閾値超過で処理終了
- 発生条件: MCPツール呼び出しに失敗(McpError)
- 対応: エラーカウント、最大3回までリトライ
- 処理: エラーメッセージをLLMに送信、閾値超過で処理終了
- 発生条件: その他の予期しないエラー
- 対応: エラーメッセージをLLMに送信
- 処理: 処理終了
- 発生条件: handle()内で例外発生
- 対応: 例外ログ出力、タスクにエラーコメント追加
- 処理: task.finish()で完了
エラーカウントはerror_state辞書で管理:
error_state = {
"json_parse_errors": 0, # JSONパースエラー回数
"consecutive_tool_errors": {} # ツール別連続エラー回数
}task_source: "github" または "gitlab"- 環境変数:
TASK_SOURCE
llm.provider: "openai", "ollama", "lmstudio"llm.function_calling: true/false- 環境変数:
LLM_PROVIDER,OPENAI_API_KEY, etc.
planning.enabled: true/falseplanning.max_subtasks: 最大サブタスク数planning.progress_comment.enabled: 進捗コメント機能
context_storage.enabled: true/falsecontext_storage.base_dir: コンテキスト保存ディレクトリ
command_executor.enabled: true/falsecommand_executor.environments: 利用可能な実行環境
issue_to_mr_conversion.enabled: true/falseissue_to_mr_conversion.auto_draft: ドラフト状態で作成
user_config_api.enabled: true/falseuser_config_api.url: APIのURLuser_config_api.api_key: APIキー
以下の環境変数は必須または重要:
TASK_SOURCE: タスクソース(github/gitlab)GITHUB_PERSONAL_ACCESS_TOKEN: GitHub APIトークン(GitHub使用時)GITLAB_PERSONAL_ACCESS_TOKEN: GitLab APIトークン(GitLab使用時)OPENAI_API_KEY: OpenAI APIキー(OpenAI使用時)LOGS: ログファイルパスDEBUG: デバッグモードフラグ
動作:
- 設定された間隔(分)で定期的にタスクを取得
- 一時停止シグナル(
contexts/pause_signal)でループ終了 - ヘルスチェックファイルを定期更新
設定:
continuous:
enabled: true
producer:
interval_minutes: 1
delay_first_run: false動作:
- キューを監視してタスクを継続的に処理
- 一時停止シグナルでループ終了
- ヘルスチェックファイルを定期更新
- 最小待機時間の設定可能
設定:
continuous:
enabled: true
consumer:
queue_timeout_seconds: 30
min_interval_seconds: 0方法:
touch contexts/pause_signal処理:
- Producer/Consumerが次のチェックポイントでシグナルを検出
- 現在の状態を保存
- タスクに一時停止ラベルを付与
- プロセスを終了
方法:
rm contexts/pause_signal
docker-compose up -d処理:
produce_tasks()で一時停止タスクを検出- 再開用のタスク辞書を準備
- キューに再投入
- Consumerが処理を再開
- アプリケーションの初期化
- 設定の読み込みと環境変数による上書き
- MCPクライアントとLLMクライアントの初期化
- Producer/Consumerモードの制御
- 継続動作モードの管理
- タスク処理の実行
- LLMとMCPツールの統合
- Processing モードの選択と実行
- エラーハンドリング
- 統計記録とコンテキスト管理
- Issue→MR/PR変換
- 実行環境の管理
- Planning モード: プランニング機能を使用した高度な処理
- Context Storage モード: ファイルベースのコンテキスト管理
- Legacy モード: 従来のインメモリ処理
文書バージョン: 1.0
最終更新日: 2024-12-07
ステータス: 設計書