Skip to content

Commit fe9bbf6

Browse files
committed
test phase
1 parent a244d1a commit fe9bbf6

File tree

8 files changed

+110
-85
lines changed

8 files changed

+110
-85
lines changed

README.md

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ llm による自立型 Cli コーディングエージェントライブラリ l
44

55
ユーザーの指示通りコーディングし、自前の linter や formatter や test コードを評価フェーズに実行でき、通るまで修正します。
66
llm api のインターフェースは litellm ライブラリを使用。Claude や OpenAI など自由な LLM を利用できます。
7+
モデルや API キーの設定方法は litellm のプロバイダ設定に準拠します。
8+
詳細は https://docs.litellm.ai/docs/providers を参照してください。
79

810
## インストール方法
911

@@ -22,7 +24,6 @@ llm api のインターフェースは litellm ライブラリを使用。Claude
2224

2325
これにより、プロジェクトディレクトリ内で `llm-coder` コマンドが利用可能になります。
2426

25-
2627
## 使い方
2728

2829
インストール後、以下のコマンドで CLI ツールを実行できます:
@@ -31,57 +32,72 @@ llm api のインターフェースは litellm ライブラリを使用。Claude
3132
llm-coder <プロンプト> [オプション...]
3233
```
3334

34-
# Parameter
35+
## 利用可能なオプション
36+
37+
```
38+
positional arguments:
39+
prompt 実行するプロンプト (省略時は標準入力から。TOMLファイルでも指定可能)
40+
41+
options:
42+
-h, --help ヘルプメッセージを表示して終了
43+
--config CONFIG TOML設定ファイルのパス (デフォルト: llm_coder_config.toml)
44+
--model MODEL, -m MODEL
45+
使用するLLMモデル (デフォルト: gpt-4.1-nano)
46+
--temperature TEMPERATURE, -t TEMPERATURE
47+
LLMの温度パラメータ (デフォルト: 0.5)
48+
--max-iterations MAX_ITERATIONS, -i MAX_ITERATIONS
49+
最大実行イテレーション数 (デフォルト: 10)
50+
--allowed-dirs ALLOWED_DIRS [ALLOWED_DIRS ...]
51+
ファイルシステム操作を許可するディレクトリ(スペース区切りで複数指定可) (デフォルト: ['.', 'playground'])
52+
--repository-description-prompt REPOSITORY_DESCRIPTION_PROMPT
53+
LLMに渡すリポジトリの説明プロンプト (デフォルト: TOMLファイルまたは空)
54+
```
55+
56+
### 使用例
3557

3658
```sh
37-
llm_coder --model claude-3-opus-20240229 "Create a python script that outputs 'hello world'"
59+
# 基本的な使い方
60+
llm-coder "Create a python script that outputs 'hello world'"
61+
62+
# モデルを指定
63+
llm-coder --model claude-3-opus-20240229 "Create a python script that outputs 'hello world'"
64+
65+
# 温度と最大イテレーション数を指定
66+
llm-coder --temperature 0.7 --max-iterations 5 "Create a python script that outputs 'hello world'"
67+
68+
# 許可するディレクトリを指定
69+
llm-coder --allowed-dirs . ./output ./src "Create a python script that outputs 'hello world'"
3870
```
3971

40-
# Configuration
72+
## 設定
73+
74+
設定はコマンドライン引数または TOML ファイルを通じて行うことができます。
4175

42-
Configuration can be done via command line arguments or a TOML file.
76+
**設定の優先順位**: コマンドライン引数 > TOML 設定ファイル > ハードコードされたデフォルト値
4377

44-
## TOML Configuration Example
78+
### TOML 設定ファイルの例
4579

46-
Create a `config.toml` file with the following content:
80+
デフォルトでは `llm_coder_config.toml` という名前の設定ファイルが読み込まれます。カスタム設定ファイルは `--config` オプションで指定できます。
4781

4882
```toml
49-
# Global configuration
83+
# グローバル設定
5084
model = "claude-3-opus-20240229"
5185
prompt = "Create a python script that outputs 'hello world'"
52-
# log_level = "INFO"
53-
# max_iterations = 5
54-
# temperature = 0.7
55-
# execute_tests = true
56-
57-
# Global lint/format/test commands
58-
# lint_command = "pylint --disable=C0114,C0115,C0116,W0511"
59-
# format_command = "black"
60-
# test_command = "pytest"
61-
62-
# Directory-specific configurations
63-
[directories.python_project]
64-
path = "src/python_project"
65-
lint_command = "pylint --disable=C0114,C0115,C0116,W0511"
66-
format_command = "black"
67-
test_command = "pytest"
68-
69-
[directories.typescript_project]
70-
path = "src/typescript_project"
71-
lint_command = "eslint"
72-
format_command = "prettier --write"
73-
test_command = "jest"
86+
temperature = 0.5
87+
max_iterations = 10
88+
allowed_dirs = [".", "playground", "src"]
89+
repository_description_prompt = "このリポジトリはPythonのユーティリティツールです"
7490
```
7591

76-
Then run `llm_coder` with the `--config` option:
92+
設定ファイルを使用する場合:
7793

7894
```sh
79-
llm_coder --config config.toml
80-
```
81-
82-
The tool will apply the appropriate lint/format/test commands based on the directory path of the generated code. Directory-specific configurations override global settings.
83-
95+
# デフォルトの設定ファイル (llm_coder_config.toml) を使用
96+
llm-coder
8497

98+
# カスタム設定ファイルを指定
99+
llm-coder --config my_config.toml
100+
```
85101

86102
### 開発中の直接実行
87103

@@ -101,5 +117,3 @@ uv run python -m llm_coder.cli <引数...>
101117
# プロジェクトのルートディレクトリにいることを想定
102118
uv run python -m llm_coder.cli "Create a python script that outputs 'hello world'"
103119
```
104-
105-
`playground` ディレクトリは、生成されたコードやテストファイルなどを配置する作業スペースとして利用できます。

llm_coder/agent.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717

1818

1919
# デフォルトプロンプト定数
20-
COMPLETION_CHECK_PROMPT = "タスクは完了しましたか?まだ必要な操作がある場合は、ツールを呼び出して続行してください。"
20+
COMPLETION_CHECK_PROMPT = (
21+
"タスクは完了しましたか?\n"
22+
"もし完了していれば、返答に必ず「TASK_COMPLETE」という文字列を含めてください。\n"
23+
"まだ必要な操作がある場合は、ツールを呼び出して続行してください。"
24+
)
2125
FINAL_SUMMARY_PROMPT = (
2226
"タスクが完了しました。実行した内容の要約と結果を教えてください。"
2327
)
@@ -77,12 +81,15 @@ def __init__(
7781
Dict[str, Any]
7882
] = None, # ツールリストをコンストラクタで受け取る
7983
final_summary_prompt: str = FINAL_SUMMARY_PROMPT, # 最終要約用プロンプト
84+
repository_description_prompt: str = None, # リポジトリ説明プロンプト
8085
):
8186
self.model = model
8287
self.temperature = temperature
8388
self.max_iterations = max_iterations
8489
self.conversation_history: List[Message] = []
8590
self.final_summary_prompt = final_summary_prompt
91+
# repository_description_prompt が None または空文字列の場合はそのまま None または空文字列を保持
92+
self.repository_description_prompt = repository_description_prompt
8693

8794
# 利用可能なツールを設定
8895
self.available_tools = available_tools or []
@@ -99,6 +106,9 @@ def __init__(
99106
temperature=self.temperature,
100107
max_iterations=self.max_iterations,
101108
tool_count=len(self.available_tools),
109+
repository_description_length=len(self.repository_description_prompt)
110+
if self.repository_description_prompt
111+
else 0,
102112
)
103113

104114
async def _execute_tool(self, tool_name: str, arguments: Dict[str, Any]) -> str:
@@ -147,7 +157,16 @@ async def _planning_phase(self, prompt: str) -> None:
147157
self.conversation_history = []
148158
logger.debug("Conversation history initialized")
149159

160+
# リポジトリ説明をシステムプロンプトに含める (存在する場合のみ)
161+
repo_context_message = ""
162+
if (
163+
self.repository_description_prompt
164+
and self.repository_description_prompt.strip()
165+
):
166+
repo_context_message = f"作業対象のリポジトリに関する背景情報:\n---\n{self.repository_description_prompt.strip()}\n---\n\n"
167+
150168
system_message_content = (
169+
f"{repo_context_message}" # repo_context_message が空なら何も追加されない
151170
"あなたは自律型のコーディングエージェントです。提示されたタスクを解決するために"
152171
"ファイルシステム上のコードを読み込み、編集し、必要なら新規作成します。\n"
153172
"タスクを次のステップで実行してください:\n"
@@ -267,7 +286,7 @@ async def _execution_phase(self) -> bool:
267286
history_length=len(self.conversation_history),
268287
)
269288

270-
if not check_message_data.get("tool_calls") and "完了" in (
289+
if not check_message_data.get("tool_calls") and "TASK_COMPLETE" in (
271290
check_message_data.get("content") or ""
272291
):
273292
logger.info("Task confirmed complete by LLM")
@@ -359,10 +378,7 @@ async def _execution_phase(self) -> bool:
359378
if (
360379
not new_message_data.get("tool_calls")
361380
and new_message_data.get("content")
362-
and (
363-
"完了" in new_message_data.get("content")
364-
or "成功" in new_message_data.get("content")
365-
)
381+
and ("TASK_COMPLETE" in new_message_data.get("content"))
366382
):
367383
logger.info("Task completed successfully based on LLM response")
368384
return True

llm_coder/cli.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
) # get_shell_command_tools をインポート
1414
import structlog # structlog をインポート (agent.py と同様の設定を想定)
1515

16-
# structlog の基本的な設定 (agent.py と同様に設定するか、共通の設定モジュールを作るのが望ましい)
17-
# ここでは簡易的に設定
1816
logger = structlog.get_logger("llm_coder.cli")
1917

2018

@@ -111,6 +109,16 @@ def parse_args():
111109
f" (デフォルト: {allowed_dirs_default if allowed_dirs_default != [os.getcwd()] else '現在の作業ディレクトリ'})",
112110
)
113111

112+
repository_description_prompt_default = config_values.get(
113+
"repository_description_prompt", ""
114+
)
115+
parser.add_argument(
116+
"--repository-description-prompt",
117+
type=str,
118+
default=repository_description_prompt_default,
119+
help="LLMに渡すリポジトリの説明プロンプト (デフォルト: TOMLファイルまたは空)",
120+
)
121+
114122
# remaining_argv を使って、--config 以外の引数を解析
115123
return parser.parse_args(remaining_argv)
116124

@@ -167,6 +175,7 @@ async def run_agent_from_cli(args):
167175
temperature=args.temperature,
168176
max_iterations=args.max_iterations,
169177
available_tools=all_available_tools, # 更新されたツールリストを使用
178+
repository_description_prompt=args.repository_description_prompt, # リポジトリ説明プロンプトを渡す
170179
)
171180

172181
logger.info("Starting agent run from CLI", prompt_length=len(prompt))

llm_coder/logging_config.py

Lines changed: 0 additions & 27 deletions
This file was deleted.

llm_coder_config.example.toml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,26 @@ allowed_dirs = [
2222
# "/tmp/llm_coder_output" # 必要に応じて他のディレクトリを追加
2323
]
2424

25-
# 今後追加される可能性のある設定:
26-
# log_level = "INFO" # "DEBUG", "INFO", "WARNING", "ERROR"
27-
# execute_tests = true # 生成されたコードのテストを自動実行するかどうか
28-
29-
# ディレクトリ固有の設定 (README.md の例を参照)
30-
# [directories.python_project]
31-
# path = "src/python_project"
32-
# lint_command = "pylint --disable=C0114,C0115,C0116,W0511"
33-
# format_command = "black"
34-
# test_command = "pytest"
25+
# リポジトリの説明プロンプト (エージェントにリポジトリのコンテキストを理解させるために使用)
26+
repository_description_prompt = """
27+
## server ディレクトリ (Python FastAPIプロジェクト)
28+
29+
### コマンド
30+
- **Lint:** `uv run ruff check .`
31+
- **Format:** `uv run ruff format .`
32+
- **Test:** `uv run pytest`
33+
34+
## front ディレクトリ (TypeScript React Viteプロジェクト)
35+
36+
### セットアップ
37+
プロジェクトのルートディレクトリ (front) で以下のコマンドを実行して、依存関係をインストールします。
38+
```bash
39+
yarn install
40+
```
41+
42+
### コマンド (package.json の scripts を参照)
43+
- **Lint:** `yarn lint` (内部的に `eslint .` を実行)
44+
- **Format:** `yarn lint -- --fix` (eslint を使って修正) または別途 Prettier などを導入している場合はそのコマンド (`npx prettier --write .` など)
45+
- **Test:** `yarn test` (内部的に `vitest` を実行)
46+
47+
"""

main.py

Whitespace-only changes.

playground/server/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Item(BaseModel):
1414

1515
@app.get("/")
1616
def read_root():
17-
return "Hello Japan"
17+
return "Hello USA"
1818

1919

2020
@app.get("/items/{item_id}")

playground/server/test_main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ def test_read_root():
1010
"""
1111
response = client.get("/")
1212
assert response.status_code == 200
13-
assert response.json() == "Hello Japan"
13+
assert response.json() == "Hello USA"
1414

1515

1616
def test_read_item():

0 commit comments

Comments
 (0)