From b5183c7711acd6f19a3cca185d81c93f9758e48f Mon Sep 17 00:00:00 2001 From: cexll Date: Sat, 22 Nov 2025 14:56:31 +0800 Subject: [PATCH] update gemini skills --- skills/gemini/SKILL.md | 55 ++++++----------- skills/gemini/scripts/gemini.py | 104 +++++++++++++------------------- 2 files changed, 61 insertions(+), 98 deletions(-) diff --git a/skills/gemini/SKILL.md b/skills/gemini/SKILL.md index 128b809..87afb45 100644 --- a/skills/gemini/SKILL.md +++ b/skills/gemini/SKILL.md @@ -17,38 +17,32 @@ Execute Gemini CLI commands with support for multiple models and flexible prompt - Alternative perspective on code problems ## Usage - -**推荐方式**(使用 uv run,自动管理 Python 环境): +**Mandatory**: Run via uv with fixed timeout 7200000ms (foreground): ```bash -uv run ~/.claude/skills/gemini/scripts/gemini.py -m -p "" [working_dir] +uv run ~/.claude/skills/gemini/scripts/gemini.py "" [working_dir] ``` -**备选方式**(直接执行或使用 Python): +**Optional** (direct execution or using Python): ```bash -~/.claude/skills/gemini/scripts/gemini.py -m -p "" [working_dir] -# 或 -python3 ~/.claude/skills/gemini/scripts/gemini.py -m -p "" [working_dir] +~/.claude/skills/gemini/scripts/gemini.py "" [working_dir] +# or +python3 ~/.claude/skills/gemini/scripts/gemini.py "" [working_dir] ``` ## Environment Variables -- **GEMINI_MODEL**: Override default model (default: `gemini-3-pro-preview`) +- **GEMINI_MODEL**: Configure model (default: `gemini-3-pro-preview`) - Example: `export GEMINI_MODEL=gemini-3` -- **GEMINI_TIMEOUT**: Override timeout in milliseconds (default: 7200000 = 2 hours) - - Example: `export GEMINI_TIMEOUT=3600000` for 1 hour ## Timeout Control -- **Built-in**: Script enforces 2-hour timeout by default -- **Override**: Set `GEMINI_TIMEOUT` environment variable (in milliseconds) -- **Bash tool**: Always set `timeout: 7200000` parameter for double protection +- **Fixed**: 7200000 milliseconds (2 hours), immutable +- **Bash tool**: Always set `timeout: 7200000` for double protection ### Parameters -- `-m, --model` (optional): Model to use (default: gemini-3-pro-preview) - - `gemini-3-pro-preview`: Latest flagship model -- `-p, --prompt` (required): Task prompt or question -- `working_dir` (optional): Working directory (default: current) +- `prompt` (required): Task prompt or question +- `working_dir` (optional): Working directory (default: current directory) ### Return Format @@ -70,7 +64,7 @@ When calling via Bash tool, always include the timeout parameter: ```yaml Bash tool parameters: -- command: uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "" +- command: uv run ~/.claude/skills/gemini/scripts/gemini.py "" - timeout: 7200000 - description: ``` @@ -79,10 +73,10 @@ Alternatives: ```yaml # Direct execution (simplest) -- command: ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "" +- command: ~/.claude/skills/gemini/scripts/gemini.py "" # Using python3 -- command: python3 ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "" +- command: python3 ~/.claude/skills/gemini/scripts/gemini.py "" ``` ### Examples @@ -90,39 +84,28 @@ Alternatives: **Basic query:** ```bash -# Recommended: via uv run -uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "explain quantum computing" +uv run ~/.claude/skills/gemini/scripts/gemini.py "explain quantum computing" # timeout: 7200000 - -# Alternative: direct execution -~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "explain quantum computing" ``` **Code analysis:** ```bash -uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "review this code for security issues: $(cat app.py)" +uv run ~/.claude/skills/gemini/scripts/gemini.py "review this code for security issues: $(cat app.py)" # timeout: 7200000 ``` **With specific working directory:** ```bash -uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "analyze project structure" "/path/to/project" -# timeout: 7200000 -``` - -**Using fast model:** - -```bash -uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "quick code suggestion" +uv run ~/.claude/skills/gemini/scripts/gemini.py "analyze project structure" "/path/to/project" # timeout: 7200000 ``` **Using python3 directly (alternative):** ```bash -python3 ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "your prompt here" +python3 ~/.claude/skills/gemini/scripts/gemini.py "your prompt here" ``` ## Notes @@ -133,5 +116,5 @@ python3 ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "yo - Cross-platform compatible (Windows/macOS/Linux) - PEP 723 compliant (inline script metadata) - Requires Gemini CLI installed and authenticated -- Supports all Gemini model variants +- Supports all Gemini model variants (configure via `GEMINI_MODEL` environment variable) - Output is streamed directly from Gemini CLI diff --git a/skills/gemini/scripts/gemini.py b/skills/gemini/scripts/gemini.py index 24991ec..fd0f63d 100755 --- a/skills/gemini/scripts/gemini.py +++ b/skills/gemini/scripts/gemini.py @@ -7,18 +7,18 @@ Gemini CLI wrapper with cross-platform support. Usage: - uv run gemini.py -m -p "" [workdir] - python3 gemini.py -m -p "" - ./gemini.py -m gemini-3-pro-preview -p "your prompt" + uv run gemini.py "" [workdir] + python3 gemini.py "" + ./gemini.py "your prompt" """ import subprocess import sys import os -import argparse DEFAULT_MODEL = os.environ.get('GEMINI_MODEL', 'gemini-3-pro-preview') DEFAULT_WORKDIR = '.' -DEFAULT_TIMEOUT = 7200 # 2 hours in seconds +TIMEOUT_MS = 7_200_000 # 固定 2 小时,毫秒 +DEFAULT_TIMEOUT = TIMEOUT_MS // 1000 FORCE_KILL_DELAY = 5 @@ -32,76 +32,56 @@ def log_warn(message: str): sys.stderr.write(f"WARN: {message}\n") -def resolve_timeout() -> int: - """解析超时配置(秒)""" - raw = os.environ.get('GEMINI_TIMEOUT', '') - if not raw: - return DEFAULT_TIMEOUT - - try: - parsed = int(raw) - if parsed <= 0: - log_warn(f"Invalid GEMINI_TIMEOUT '{raw}', falling back to {DEFAULT_TIMEOUT}s") - return DEFAULT_TIMEOUT - # 环境变量是毫秒,转换为秒 - return parsed // 1000 if parsed > 10000 else parsed - except ValueError: - log_warn(f"Invalid GEMINI_TIMEOUT '{raw}', falling back to {DEFAULT_TIMEOUT}s") - return DEFAULT_TIMEOUT +def log_info(message: str): + """输出信息到 stderr""" + sys.stderr.write(f"INFO: {message}\n") def parse_args(): - """解析命令行参数""" - parser = argparse.ArgumentParser( - description='Gemini CLI wrapper for Claude Code integration', - formatter_class=argparse.RawDescriptionHelpFormatter - ) - parser.add_argument( - '-m', '--model', - default=DEFAULT_MODEL, - help=f'Gemini model to use (default: {DEFAULT_MODEL})' - ) - parser.add_argument( - '-p', '--prompt', - required=True, - help='Prompt to send to Gemini' - ) - parser.add_argument( - 'workdir', - nargs='?', - default=DEFAULT_WORKDIR, - help='Working directory (default: current directory)' - ) + """解析位置参数""" + if len(sys.argv) < 2: + log_error('Prompt required') + sys.exit(1) - return parser.parse_args() + return { + 'prompt': sys.argv[1], + 'workdir': sys.argv[2] if len(sys.argv) > 2 else DEFAULT_WORKDIR + } def build_gemini_args(args) -> list: """构建 gemini CLI 参数""" return [ 'gemini', - '-m', args.model, - '-p', args.prompt + '-m', DEFAULT_MODEL, + '-p', args['prompt'] ] def main(): + log_info('Script started') args = parse_args() + log_info(f"Prompt length: {len(args['prompt'])}") + log_info(f"Working dir: {args['workdir']}") gemini_args = build_gemini_args(args) - timeout_sec = resolve_timeout() + timeout_sec = DEFAULT_TIMEOUT + log_info(f"Timeout: {timeout_sec}s") # 如果指定了工作目录,切换到该目录 - if args.workdir != DEFAULT_WORKDIR: + if args['workdir'] != DEFAULT_WORKDIR: try: - os.chdir(args.workdir) + os.chdir(args['workdir']) except FileNotFoundError: - log_error(f"Working directory not found: {args.workdir}") + log_error(f"Working directory not found: {args['workdir']}") sys.exit(1) except PermissionError: - log_error(f"Permission denied: {args.workdir}") + log_error(f"Permission denied: {args['workdir']}") sys.exit(1) + log_info('Changed working directory') try: + log_info(f"Starting gemini with model {DEFAULT_MODEL}") + process = None # 启动 gemini 子进程,直接透传 stdout 和 stderr process = subprocess.Popen( gemini_args, @@ -112,11 +92,9 @@ def main(): ) # 实时输出 stdout - stdout_lines = [] for line in process.stdout: sys.stdout.write(line) sys.stdout.flush() - stdout_lines.append(line) # 等待进程结束 returncode = process.wait(timeout=timeout_sec) @@ -135,11 +113,12 @@ def main(): except subprocess.TimeoutExpired: log_error(f'Gemini execution timeout ({timeout_sec}s)') - process.kill() - try: - process.wait(timeout=FORCE_KILL_DELAY) - except subprocess.TimeoutExpired: - pass + if process is not None: + process.kill() + try: + process.wait(timeout=FORCE_KILL_DELAY) + except subprocess.TimeoutExpired: + pass sys.exit(124) except FileNotFoundError: @@ -148,11 +127,12 @@ def main(): sys.exit(127) except KeyboardInterrupt: - process.terminate() - try: - process.wait(timeout=FORCE_KILL_DELAY) - except subprocess.TimeoutExpired: - process.kill() + if process is not None: + process.terminate() + try: + process.wait(timeout=FORCE_KILL_DELAY) + except subprocess.TimeoutExpired: + process.kill() sys.exit(130)