このファイルは、Gemini CLIのカスタムツールを作成する際のテンプレートです。
これまでの知見(`__main__`ブロックの禁止、`stdin`経由の引数受け渡し、依存関係の処理など)を全て反映しています。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A sample script for a Gemini CLI custom tool.
This script serves as a template and demonstrates the best practices we've
established. It is designed to be called by the 'call_tool' dispatcher,
receiving its arguments via a JSON object on stdin.
"""
import sys
import json
import logging
from typing import List # 必要に応じて型ヒントをインポート
# --- 1. 依存関係のハンドリング (Dependency Handling) ---
# 外部ライブラリをインポートする場合、必ず try...except ImportError ブロックで囲む。
# これにより、ライブラリがインストールされていない場合に、ユーザーに親切な
# エラーメッセージとインストール方法を提示できる。
try:
import requests # 例としてrequestsライブラリを使用
except ImportError:
# ログ(stderr)にエラーメッセージとインストール手順を出力して終了する
logging.error(
"ERROR: The 'requests' library is not installed. "
"Please install it by running: pip install requests"
)
sys.exit(1)
# --- 2. 基本設定 (Basic Configuration) ---
# 全てのログは、Gemini CLIがユーザーに表示する `returnDisplay` の元となる
# 標準エラー出力(stderr)に書き出すように設定する。
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - [%(levelname)s] - %(message)s',
stream=sys.stderr,
)
# --- 3. main関数: 唯一のインターフェース ---
# ツールのインターフェース(引数)は、このmain関数のシグネチャによってのみ定義される。
# これが、Gemini CLIがget_tools.pyを生成する際の唯一の「真実の源」となる。
#
# - 必須引数: デフォルト値なしで定義する (例: name: str)
# - 任意引数: 必ずデフォルト値を与える (例: repeat: int = 1)
def main(name: str, repeat: int = 1, loud: bool = False):
"""
A sample tool that generates a greeting string.
This docstring is important. Gemini CLI will use it as a reference
to generate the 'description' for this tool in get_tools.py.
Args:
name (str): The name to include in the greeting. This is a required argument.
repeat (int, optional): The number of times to repeat the greeting. Defaults to 1.
loud (bool, optional): If True, the greeting will be in uppercase. Defaults to False.
"""
# 処理開始と受け取った引数をログに出力する(デバッグに有用)
logging.info(f"Tool 'sample_tool' started with args: name='{name}', repeat={repeat}, loud={loud}")
try:
# --- 4. 主要ロジック (Core Logic) ---
# ここにツールの主となる処理を記述する。
# 例: あいさつ文を生成
greeting = f"Hello, {name}!"
if loud:
greeting = greeting.upper()
# 複数行の文字列を生成
final_output = "\n".join([greeting] * repeat)
# --- 5. 成功時の出力 (Success Output) ---
# 処理が成功した場合、LLMに渡したい結果の「文字列のみ」を標準出力(stdout)にprintする。
# これが `llmContent` となる。
print(final_output)
except Exception as e:
# --- 6. エラーハンドリング (Error Handling) ---
# 予期せぬエラーが発生した場合、詳細を標準エラー出力(stderr)にログとして書き出し、
# ゼロ以外のステータスコードで終了する。
logging.error(f"An unexpected error occurred: {e}")
sys.exit(1)
# --- 7. 禁止事項: if __name__ == "__main__" ---
#
# 以下のブロックは、仕様の二重管理(main関数のシグネチャ vs argparse)という
# 深刻な矛盾とバグの原因となるため、**絶対に記述してはならない。**
#
# if __name__ == '__main__':
# # このブロックは禁止!
# pass