aiagent-runner 0.1.1__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.
- aiagent_runner-0.1.1/.gitignore +47 -0
- aiagent_runner-0.1.1/PKG-INFO +148 -0
- aiagent_runner-0.1.1/PyPI-Recovery-Codes-asato99-2026-01-09T01_18_40.124422.txt +8 -0
- aiagent_runner-0.1.1/README.md +124 -0
- aiagent_runner-0.1.1/config/coordinator_default.yaml +28 -0
- aiagent_runner-0.1.1/pyproject.toml +46 -0
- aiagent_runner-0.1.1/src/aiagent_runner/__init__.py +9 -0
- aiagent_runner-0.1.1/src/aiagent_runner/__main__.py +282 -0
- aiagent_runner-0.1.1/src/aiagent_runner/config.py +99 -0
- aiagent_runner-0.1.1/src/aiagent_runner/coordinator.py +462 -0
- aiagent_runner-0.1.1/src/aiagent_runner/coordinator_config.py +165 -0
- aiagent_runner-0.1.1/src/aiagent_runner/executor.py +99 -0
- aiagent_runner-0.1.1/src/aiagent_runner/mcp_client.py +478 -0
- aiagent_runner-0.1.1/src/aiagent_runner/prompt_builder.py +120 -0
- aiagent_runner-0.1.1/src/aiagent_runner/runner.py +236 -0
- aiagent_runner-0.1.1/tests/conftest.py +88 -0
- aiagent_runner-0.1.1/tests/integration/__init__.py +1 -0
- aiagent_runner-0.1.1/tests/integration/test_runner_integration.py +586 -0
- aiagent_runner-0.1.1/tests/test_config.py +171 -0
- aiagent_runner-0.1.1/tests/test_executor.py +191 -0
- aiagent_runner-0.1.1/tests/test_mcp_client.py +272 -0
- aiagent_runner-0.1.1/tests/test_prompt_builder.py +189 -0
- aiagent_runner-0.1.1/tests/test_runner.py +295 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# Virtual environments
|
|
28
|
+
.venv/
|
|
29
|
+
venv/
|
|
30
|
+
ENV/
|
|
31
|
+
|
|
32
|
+
# Testing
|
|
33
|
+
.coverage
|
|
34
|
+
.pytest_cache/
|
|
35
|
+
htmlcov/
|
|
36
|
+
.tox/
|
|
37
|
+
.nox/
|
|
38
|
+
|
|
39
|
+
# IDE
|
|
40
|
+
.idea/
|
|
41
|
+
.vscode/
|
|
42
|
+
*.swp
|
|
43
|
+
*.swo
|
|
44
|
+
|
|
45
|
+
# Logs
|
|
46
|
+
logs/
|
|
47
|
+
*.log
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aiagent-runner
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Runner for AI Agent PM - executes tasks via MCP and CLI
|
|
5
|
+
Author: AI Agent PM Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: agent,ai,automation,mcp,orchestration,task-management
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Requires-Dist: pyyaml>=6.0
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
22
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# AI Agent PM Coordinator
|
|
26
|
+
|
|
27
|
+
全エージェントのタスク実行を統合管理するオーケストレーションデーモン。
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## クイックスタート
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
cd runner
|
|
35
|
+
pip install -e .
|
|
36
|
+
|
|
37
|
+
# デフォルト設定で起動(config/coordinator_default.yaml を使用)
|
|
38
|
+
python -m aiagent_runner --coordinator
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Coordinatorモード(推奨)
|
|
44
|
+
|
|
45
|
+
単一のCoordinatorが全ての(agent_id, project_id)ペアを管理します。
|
|
46
|
+
|
|
47
|
+
### 基本起動
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# デフォルト設定で起動
|
|
51
|
+
python -m aiagent_runner --coordinator
|
|
52
|
+
|
|
53
|
+
# 詳細ログ出力
|
|
54
|
+
python -m aiagent_runner --coordinator -v
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### カスタム設定ファイル
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m aiagent_runner --coordinator -c /path/to/config.yaml
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 設定ファイル例
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
# config/coordinator_default.yaml がデフォルトで読み込まれます
|
|
67
|
+
# カスタム設定で上書き可能
|
|
68
|
+
|
|
69
|
+
polling_interval: 10
|
|
70
|
+
max_concurrent: 3
|
|
71
|
+
|
|
72
|
+
# MCP server configuration (Agent Instance用)
|
|
73
|
+
mcp_server_command: /path/to/mcp-server-pm
|
|
74
|
+
mcp_database_path: /path/to/database.db
|
|
75
|
+
|
|
76
|
+
# AI providers
|
|
77
|
+
ai_providers:
|
|
78
|
+
claude:
|
|
79
|
+
cli_command: claude
|
|
80
|
+
cli_args:
|
|
81
|
+
- "--dangerously-skip-permissions"
|
|
82
|
+
- "--max-turns"
|
|
83
|
+
- "50"
|
|
84
|
+
|
|
85
|
+
# Agents (passkeyのみ - ai_type等はMCPから取得)
|
|
86
|
+
agents:
|
|
87
|
+
agt_developer:
|
|
88
|
+
passkey: secret123
|
|
89
|
+
agt_reviewer:
|
|
90
|
+
passkey: ${REVIEWER_PASSKEY} # 環境変数展開対応
|
|
91
|
+
|
|
92
|
+
log_directory: /tmp/coordinator_logs
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### バックグラウンド実行
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
nohup python -m aiagent_runner --coordinator -v > coordinator.log 2>&1 &
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 設定の優先順位
|
|
104
|
+
|
|
105
|
+
1. **コマンドライン引数** (`--polling-interval` 等)
|
|
106
|
+
2. **指定した設定ファイル** (`-c /path/to/config.yaml`)
|
|
107
|
+
3. **デフォルト設定** (`runner/config/coordinator_default.yaml`)
|
|
108
|
+
4. **組み込みデフォルト値**
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 動作フロー
|
|
113
|
+
|
|
114
|
+
1. MCPサーバーに接続(Unixソケット)
|
|
115
|
+
2. `list_active_projects_with_agents()` で全プロジェクト・エージェントを取得
|
|
116
|
+
3. 各(agent_id, project_id)ペアに対して `should_start()` を呼び出し
|
|
117
|
+
4. 作業が必要な場合、Agent Instance(Claude CLI等)をスポーン
|
|
118
|
+
5. Agent Instanceが `authenticate` → `get_my_task` → 実行 → `report_completed`
|
|
119
|
+
6. 待機して2に戻る
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 前提条件
|
|
124
|
+
|
|
125
|
+
- MCPサーバーが起動していること
|
|
126
|
+
- エージェントがアプリで登録済みで、passkeyが設定されていること
|
|
127
|
+
- 該当エージェントがプロジェクトに割り当てられていること
|
|
128
|
+
- タスクが `in_progress` ステータスであること
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Legacy Runnerモード(非推奨)
|
|
133
|
+
|
|
134
|
+
1エージェント = 1デーモン の旧アーキテクチャ。
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# 非推奨: Coordinatorモードを使用してください
|
|
138
|
+
aiagent-runner --agent-id <AGENT_ID> --passkey <PASSKEY> --project-id <PROJECT_ID>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 開発
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
pip install -e ".[dev]"
|
|
147
|
+
pytest
|
|
148
|
+
```
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# AI Agent PM Coordinator
|
|
2
|
+
|
|
3
|
+
全エージェントのタスク実行を統合管理するオーケストレーションデーモン。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## クイックスタート
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd runner
|
|
11
|
+
pip install -e .
|
|
12
|
+
|
|
13
|
+
# デフォルト設定で起動(config/coordinator_default.yaml を使用)
|
|
14
|
+
python -m aiagent_runner --coordinator
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Coordinatorモード(推奨)
|
|
20
|
+
|
|
21
|
+
単一のCoordinatorが全ての(agent_id, project_id)ペアを管理します。
|
|
22
|
+
|
|
23
|
+
### 基本起動
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# デフォルト設定で起動
|
|
27
|
+
python -m aiagent_runner --coordinator
|
|
28
|
+
|
|
29
|
+
# 詳細ログ出力
|
|
30
|
+
python -m aiagent_runner --coordinator -v
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### カスタム設定ファイル
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m aiagent_runner --coordinator -c /path/to/config.yaml
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 設定ファイル例
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
# config/coordinator_default.yaml がデフォルトで読み込まれます
|
|
43
|
+
# カスタム設定で上書き可能
|
|
44
|
+
|
|
45
|
+
polling_interval: 10
|
|
46
|
+
max_concurrent: 3
|
|
47
|
+
|
|
48
|
+
# MCP server configuration (Agent Instance用)
|
|
49
|
+
mcp_server_command: /path/to/mcp-server-pm
|
|
50
|
+
mcp_database_path: /path/to/database.db
|
|
51
|
+
|
|
52
|
+
# AI providers
|
|
53
|
+
ai_providers:
|
|
54
|
+
claude:
|
|
55
|
+
cli_command: claude
|
|
56
|
+
cli_args:
|
|
57
|
+
- "--dangerously-skip-permissions"
|
|
58
|
+
- "--max-turns"
|
|
59
|
+
- "50"
|
|
60
|
+
|
|
61
|
+
# Agents (passkeyのみ - ai_type等はMCPから取得)
|
|
62
|
+
agents:
|
|
63
|
+
agt_developer:
|
|
64
|
+
passkey: secret123
|
|
65
|
+
agt_reviewer:
|
|
66
|
+
passkey: ${REVIEWER_PASSKEY} # 環境変数展開対応
|
|
67
|
+
|
|
68
|
+
log_directory: /tmp/coordinator_logs
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### バックグラウンド実行
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
nohup python -m aiagent_runner --coordinator -v > coordinator.log 2>&1 &
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 設定の優先順位
|
|
80
|
+
|
|
81
|
+
1. **コマンドライン引数** (`--polling-interval` 等)
|
|
82
|
+
2. **指定した設定ファイル** (`-c /path/to/config.yaml`)
|
|
83
|
+
3. **デフォルト設定** (`runner/config/coordinator_default.yaml`)
|
|
84
|
+
4. **組み込みデフォルト値**
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 動作フロー
|
|
89
|
+
|
|
90
|
+
1. MCPサーバーに接続(Unixソケット)
|
|
91
|
+
2. `list_active_projects_with_agents()` で全プロジェクト・エージェントを取得
|
|
92
|
+
3. 各(agent_id, project_id)ペアに対して `should_start()` を呼び出し
|
|
93
|
+
4. 作業が必要な場合、Agent Instance(Claude CLI等)をスポーン
|
|
94
|
+
5. Agent Instanceが `authenticate` → `get_my_task` → 実行 → `report_completed`
|
|
95
|
+
6. 待機して2に戻る
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 前提条件
|
|
100
|
+
|
|
101
|
+
- MCPサーバーが起動していること
|
|
102
|
+
- エージェントがアプリで登録済みで、passkeyが設定されていること
|
|
103
|
+
- 該当エージェントがプロジェクトに割り当てられていること
|
|
104
|
+
- タスクが `in_progress` ステータスであること
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Legacy Runnerモード(非推奨)
|
|
109
|
+
|
|
110
|
+
1エージェント = 1デーモン の旧アーキテクチャ。
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# 非推奨: Coordinatorモードを使用してください
|
|
114
|
+
aiagent-runner --agent-id <AGENT_ID> --passkey <PASSKEY> --project-id <PROJECT_ID>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 開発
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pip install -e ".[dev]"
|
|
123
|
+
pytest
|
|
124
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# AI Agent PM Coordinator - Default Configuration
|
|
2
|
+
# このファイルはデフォルト設定を定義します
|
|
3
|
+
# テスト時は -c オプションで上書き可能
|
|
4
|
+
|
|
5
|
+
# Polling settings
|
|
6
|
+
polling_interval: 10
|
|
7
|
+
max_concurrent: 3
|
|
8
|
+
|
|
9
|
+
# MCP connection (default socket path)
|
|
10
|
+
# mcp_socket_path: ~/Library/Application Support/AIAgentPM/mcp.sock
|
|
11
|
+
|
|
12
|
+
# AI providers - how to launch each AI type
|
|
13
|
+
ai_providers:
|
|
14
|
+
claude:
|
|
15
|
+
cli_command: claude
|
|
16
|
+
cli_args:
|
|
17
|
+
- "--dangerously-skip-permissions"
|
|
18
|
+
- "--max-turns"
|
|
19
|
+
- "50"
|
|
20
|
+
|
|
21
|
+
# Agents configuration
|
|
22
|
+
# 本番環境では環境変数または別ファイルでpasskeyを管理
|
|
23
|
+
# agents:
|
|
24
|
+
# agt_example:
|
|
25
|
+
# passkey: ${AGENT_PASSKEY}
|
|
26
|
+
|
|
27
|
+
# Logging (optional)
|
|
28
|
+
# log_directory: /tmp/coordinator_logs
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aiagent-runner"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Runner for AI Agent PM - executes tasks via MCP and CLI"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "AI Agent PM Team" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ai", "agent", "mcp", "automation", "task-management", "orchestration"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"pyyaml>=6.0",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=8.0",
|
|
34
|
+
"pytest-asyncio>=0.23",
|
|
35
|
+
"pytest-cov>=4.1",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
aiagent-runner = "aiagent_runner.__main__:main"
|
|
40
|
+
|
|
41
|
+
[tool.hatch.build.targets.wheel]
|
|
42
|
+
packages = ["src/aiagent_runner"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
asyncio_mode = "auto"
|
|
46
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# aiagent_runner - Runner for AI Agent PM
|
|
2
|
+
# Executes tasks via MCP protocol and CLI tools (claude, gemini, etc.)
|
|
3
|
+
|
|
4
|
+
__version__ = "0.1.0"
|
|
5
|
+
|
|
6
|
+
from aiagent_runner.config import RunnerConfig
|
|
7
|
+
from aiagent_runner.runner import Runner, run, run_async
|
|
8
|
+
|
|
9
|
+
__all__ = ["RunnerConfig", "Runner", "run", "run_async", "__version__"]
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# src/aiagent_runner/__main__.py
|
|
2
|
+
# Entry point for AI Agent PM Runner/Coordinator
|
|
3
|
+
# Reference: docs/plan/PHASE3_PULL_ARCHITECTURE.md - Phase 3-5 (legacy Runner)
|
|
4
|
+
# Reference: docs/plan/PHASE4_COORDINATOR_ARCHITECTURE.md (Coordinator)
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import logging
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from aiagent_runner.config import RunnerConfig
|
|
12
|
+
from aiagent_runner.coordinator import run_coordinator
|
|
13
|
+
from aiagent_runner.coordinator_config import CoordinatorConfig
|
|
14
|
+
from aiagent_runner.runner import run
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def setup_logging(verbose: bool = False) -> None:
|
|
18
|
+
"""Configure logging.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
verbose: If True, enable debug logging
|
|
22
|
+
"""
|
|
23
|
+
level = logging.DEBUG if verbose else logging.INFO
|
|
24
|
+
logging.basicConfig(
|
|
25
|
+
level=level,
|
|
26
|
+
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
|
|
27
|
+
datefmt="%Y-%m-%d %H:%M:%S"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def parse_args() -> argparse.Namespace:
|
|
32
|
+
"""Parse command line arguments.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
Parsed arguments
|
|
36
|
+
"""
|
|
37
|
+
parser = argparse.ArgumentParser(
|
|
38
|
+
prog="aiagent-runner",
|
|
39
|
+
description="Runner/Coordinator for AI Agent PM - executes tasks via MCP and CLI"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Mode selection
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--coordinator",
|
|
45
|
+
action="store_true",
|
|
46
|
+
help="Run in Coordinator mode (Phase 4: single orchestrator for all agents)"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Common arguments
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"-c", "--config",
|
|
52
|
+
type=Path,
|
|
53
|
+
help="Path to YAML configuration file"
|
|
54
|
+
)
|
|
55
|
+
parser.add_argument(
|
|
56
|
+
"-v", "--verbose",
|
|
57
|
+
action="store_true",
|
|
58
|
+
help="Enable verbose (debug) logging"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# Legacy Runner arguments (deprecated, use Coordinator mode instead)
|
|
62
|
+
parser.add_argument(
|
|
63
|
+
"--agent-id",
|
|
64
|
+
help="[Legacy Runner] Agent ID (overrides config/env)"
|
|
65
|
+
)
|
|
66
|
+
parser.add_argument(
|
|
67
|
+
"--passkey",
|
|
68
|
+
help="[Legacy Runner] Agent passkey (overrides config/env)"
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--project-id",
|
|
72
|
+
help="[Legacy Runner] Project ID (Phase 4 required)"
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--polling-interval",
|
|
76
|
+
type=int,
|
|
77
|
+
help="Polling interval in seconds (default: 5 for Runner, 10 for Coordinator)"
|
|
78
|
+
)
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
"--cli-command",
|
|
81
|
+
help="[Legacy Runner] CLI command to use (default: claude)"
|
|
82
|
+
)
|
|
83
|
+
parser.add_argument(
|
|
84
|
+
"--working-directory",
|
|
85
|
+
type=Path,
|
|
86
|
+
help="[Legacy Runner] Working directory for CLI execution"
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--log-directory",
|
|
90
|
+
type=Path,
|
|
91
|
+
help="Directory for execution logs"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return parser.parse_args()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def load_runner_config(args: argparse.Namespace) -> RunnerConfig:
|
|
98
|
+
"""Load configuration for legacy Runner mode.
|
|
99
|
+
|
|
100
|
+
Priority (highest to lowest):
|
|
101
|
+
1. CLI arguments
|
|
102
|
+
2. Config file
|
|
103
|
+
3. Environment variables
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
args: Parsed CLI arguments
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
RunnerConfig instance
|
|
110
|
+
"""
|
|
111
|
+
# Start with config file or environment
|
|
112
|
+
if args.config and args.config.exists():
|
|
113
|
+
config = RunnerConfig.from_yaml(args.config)
|
|
114
|
+
else:
|
|
115
|
+
try:
|
|
116
|
+
config = RunnerConfig.from_env()
|
|
117
|
+
except ValueError as e:
|
|
118
|
+
# If no config file and env vars missing, check CLI args
|
|
119
|
+
if args.agent_id and args.passkey and args.project_id:
|
|
120
|
+
config = RunnerConfig(
|
|
121
|
+
agent_id=args.agent_id,
|
|
122
|
+
passkey=args.passkey,
|
|
123
|
+
project_id=args.project_id
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
raise e
|
|
127
|
+
|
|
128
|
+
# Override with CLI arguments
|
|
129
|
+
if args.agent_id:
|
|
130
|
+
config.agent_id = args.agent_id
|
|
131
|
+
if args.passkey:
|
|
132
|
+
config.passkey = args.passkey
|
|
133
|
+
if args.project_id:
|
|
134
|
+
config.project_id = args.project_id
|
|
135
|
+
if args.polling_interval:
|
|
136
|
+
config.polling_interval = args.polling_interval
|
|
137
|
+
if args.cli_command:
|
|
138
|
+
config.cli_command = args.cli_command
|
|
139
|
+
if args.working_directory:
|
|
140
|
+
config.working_directory = str(args.working_directory)
|
|
141
|
+
if args.log_directory:
|
|
142
|
+
config.log_directory = str(args.log_directory)
|
|
143
|
+
|
|
144
|
+
return config
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def get_default_config_path() -> Path:
|
|
148
|
+
"""Get the default configuration file path.
|
|
149
|
+
|
|
150
|
+
The default config is located at:
|
|
151
|
+
runner/config/coordinator_default.yaml
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Path to default config file
|
|
155
|
+
"""
|
|
156
|
+
# Find the runner package root (where config/ directory is)
|
|
157
|
+
# __file__ is runner/src/aiagent_runner/__main__.py
|
|
158
|
+
# parent = runner/src/aiagent_runner/
|
|
159
|
+
# parent.parent = runner/src/
|
|
160
|
+
# parent.parent.parent = runner/
|
|
161
|
+
runner_root = Path(__file__).parent.parent.parent
|
|
162
|
+
return runner_root / "config" / "coordinator_default.yaml"
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def load_coordinator_config(args: argparse.Namespace) -> CoordinatorConfig:
|
|
166
|
+
"""Load configuration for Coordinator mode.
|
|
167
|
+
|
|
168
|
+
Configuration loading priority:
|
|
169
|
+
1. User-specified config file (-c/--config) - full override
|
|
170
|
+
2. Default config file (runner/config/coordinator_default.yaml)
|
|
171
|
+
|
|
172
|
+
Note: When using default config, agents must be configured via
|
|
173
|
+
environment variables or a separate config file.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
args: Parsed CLI arguments
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
CoordinatorConfig instance
|
|
180
|
+
"""
|
|
181
|
+
logger = logging.getLogger(__name__)
|
|
182
|
+
|
|
183
|
+
if args.config and args.config.exists():
|
|
184
|
+
# User specified a config file - use it directly
|
|
185
|
+
logger.info(f"Loading config from: {args.config}")
|
|
186
|
+
config = CoordinatorConfig.from_yaml(args.config)
|
|
187
|
+
else:
|
|
188
|
+
# Try to load default config
|
|
189
|
+
default_config_path = get_default_config_path()
|
|
190
|
+
if default_config_path.exists():
|
|
191
|
+
logger.info(f"Loading default config from: {default_config_path}")
|
|
192
|
+
config = CoordinatorConfig.from_yaml(default_config_path)
|
|
193
|
+
else:
|
|
194
|
+
# No config available - use built-in defaults
|
|
195
|
+
logger.warning(
|
|
196
|
+
"No config file found. Using built-in defaults.\n"
|
|
197
|
+
f"Expected default config at: {default_config_path}\n"
|
|
198
|
+
"Note: Agents must be configured to run tasks."
|
|
199
|
+
)
|
|
200
|
+
config = CoordinatorConfig()
|
|
201
|
+
|
|
202
|
+
# Override with CLI arguments
|
|
203
|
+
if args.polling_interval:
|
|
204
|
+
config.polling_interval = args.polling_interval
|
|
205
|
+
if args.log_directory:
|
|
206
|
+
config.log_directory = str(args.log_directory)
|
|
207
|
+
|
|
208
|
+
return config
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def main() -> int:
|
|
212
|
+
"""Main entry point.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Exit code (0 for success)
|
|
216
|
+
"""
|
|
217
|
+
args = parse_args()
|
|
218
|
+
setup_logging(args.verbose)
|
|
219
|
+
|
|
220
|
+
logger = logging.getLogger(__name__)
|
|
221
|
+
|
|
222
|
+
if args.coordinator:
|
|
223
|
+
# Phase 4: Coordinator mode
|
|
224
|
+
logger.info("Running in Coordinator mode (Phase 4)")
|
|
225
|
+
try:
|
|
226
|
+
config = load_coordinator_config(args)
|
|
227
|
+
except ValueError as e:
|
|
228
|
+
logger.error(f"Configuration error: {e}")
|
|
229
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
230
|
+
return 1
|
|
231
|
+
|
|
232
|
+
logger.info(f"Configured agents: {list(config.agents.keys())}")
|
|
233
|
+
logger.info(f"Polling interval: {config.polling_interval}s")
|
|
234
|
+
logger.info(f"Max concurrent: {config.max_concurrent}")
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
run_coordinator(config)
|
|
238
|
+
except KeyboardInterrupt:
|
|
239
|
+
logger.info("Coordinator stopped by user")
|
|
240
|
+
return 0
|
|
241
|
+
except Exception as e:
|
|
242
|
+
logger.exception(f"Coordinator failed: {e}")
|
|
243
|
+
return 1
|
|
244
|
+
else:
|
|
245
|
+
# Legacy Runner mode (deprecated)
|
|
246
|
+
logger.warning(
|
|
247
|
+
"Running in legacy Runner mode. "
|
|
248
|
+
"Consider using --coordinator mode for Phase 4 architecture."
|
|
249
|
+
)
|
|
250
|
+
try:
|
|
251
|
+
config = load_runner_config(args)
|
|
252
|
+
except ValueError as e:
|
|
253
|
+
logger.error(f"Configuration error: {e}")
|
|
254
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
255
|
+
print(
|
|
256
|
+
"\nProvide configuration via:\n"
|
|
257
|
+
" 1. YAML config file (-c/--config)\n"
|
|
258
|
+
" 2. Environment variables (AGENT_ID, AGENT_PASSKEY, PROJECT_ID)\n"
|
|
259
|
+
" 3. CLI arguments (--agent-id, --passkey, --project-id)",
|
|
260
|
+
file=sys.stderr
|
|
261
|
+
)
|
|
262
|
+
return 1
|
|
263
|
+
|
|
264
|
+
logger.info(f"Starting runner for agent: {config.agent_id}")
|
|
265
|
+
logger.info(f"Project: {config.project_id}")
|
|
266
|
+
logger.info(f"CLI command: {config.cli_command}")
|
|
267
|
+
logger.info(f"Polling interval: {config.polling_interval}s")
|
|
268
|
+
|
|
269
|
+
try:
|
|
270
|
+
run(config)
|
|
271
|
+
except KeyboardInterrupt:
|
|
272
|
+
logger.info("Runner stopped by user")
|
|
273
|
+
return 0
|
|
274
|
+
except Exception as e:
|
|
275
|
+
logger.exception(f"Runner failed: {e}")
|
|
276
|
+
return 1
|
|
277
|
+
|
|
278
|
+
return 0
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
if __name__ == "__main__":
|
|
282
|
+
sys.exit(main())
|