update gemini skills

This commit is contained in:
cexll
2025-11-22 14:56:31 +08:00
parent 3fab18a6bb
commit d3552d33a8
2 changed files with 61 additions and 98 deletions

View File

@@ -17,38 +17,32 @@ Execute Gemini CLI commands with support for multiple models and flexible prompt
- Alternative perspective on code problems - Alternative perspective on code problems
## Usage ## Usage
**Mandatory**: Run via uv with fixed timeout 7200000ms (foreground):
**推荐方式**(使用 uv run自动管理 Python 环境):
```bash ```bash
uv run ~/.claude/skills/gemini/scripts/gemini.py -m <model> -p "<prompt>" [working_dir] uv run ~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
``` ```
**备选方式**(直接执行或使用 Python **Optional** (direct execution or using Python):
```bash ```bash
~/.claude/skills/gemini/scripts/gemini.py -m <model> -p "<prompt>" [working_dir] ~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
# # or
python3 ~/.claude/skills/gemini/scripts/gemini.py -m <model> -p "<prompt>" [working_dir] python3 ~/.claude/skills/gemini/scripts/gemini.py "<prompt>" [working_dir]
``` ```
## Environment Variables ## 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` - 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 ## Timeout Control
- **Built-in**: Script enforces 2-hour timeout by default - **Fixed**: 7200000 milliseconds (2 hours), immutable
- **Override**: Set `GEMINI_TIMEOUT` environment variable (in milliseconds) - **Bash tool**: Always set `timeout: 7200000` for double protection
- **Bash tool**: Always set `timeout: 7200000` parameter for double protection
### Parameters ### Parameters
- `-m, --model` (optional): Model to use (default: gemini-3-pro-preview) - `prompt` (required): Task prompt or question
- `gemini-3-pro-preview`: Latest flagship model - `working_dir` (optional): Working directory (default: current directory)
- `-p, --prompt` (required): Task prompt or question
- `working_dir` (optional): Working directory (default: current)
### Return Format ### Return Format
@@ -70,7 +64,7 @@ When calling via Bash tool, always include the timeout parameter:
```yaml ```yaml
Bash tool parameters: Bash tool parameters:
- command: uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "<prompt>" - command: uv run ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
- timeout: 7200000 - timeout: 7200000
- description: <brief description of the task> - description: <brief description of the task>
``` ```
@@ -79,10 +73,10 @@ Alternatives:
```yaml ```yaml
# Direct execution (simplest) # Direct execution (simplest)
- command: ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "<prompt>" - command: ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
# Using python3 # Using python3
- command: python3 ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "<prompt>" - command: python3 ~/.claude/skills/gemini/scripts/gemini.py "<prompt>"
``` ```
### Examples ### Examples
@@ -90,39 +84,28 @@ Alternatives:
**Basic query:** **Basic query:**
```bash ```bash
# Recommended: via uv run uv run ~/.claude/skills/gemini/scripts/gemini.py "explain quantum computing"
uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "explain quantum computing"
# timeout: 7200000 # timeout: 7200000
# Alternative: direct execution
~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "explain quantum computing"
``` ```
**Code analysis:** **Code analysis:**
```bash ```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 # timeout: 7200000
``` ```
**With specific working directory:** **With specific working directory:**
```bash ```bash
uv run ~/.claude/skills/gemini/scripts/gemini.py -m gemini-3-pro-preview -p "analyze project structure" "/path/to/project" uv run ~/.claude/skills/gemini/scripts/gemini.py "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"
# timeout: 7200000 # timeout: 7200000
``` ```
**Using python3 directly (alternative):** **Using python3 directly (alternative):**
```bash ```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 ## 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) - Cross-platform compatible (Windows/macOS/Linux)
- PEP 723 compliant (inline script metadata) - PEP 723 compliant (inline script metadata)
- Requires Gemini CLI installed and authenticated - 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 - Output is streamed directly from Gemini CLI

View File

@@ -7,18 +7,18 @@
Gemini CLI wrapper with cross-platform support. Gemini CLI wrapper with cross-platform support.
Usage: Usage:
uv run gemini.py -m <model> -p "<prompt>" [workdir] uv run gemini.py "<prompt>" [workdir]
python3 gemini.py -m <model> -p "<prompt>" python3 gemini.py "<prompt>"
./gemini.py -m gemini-3-pro-preview -p "your prompt" ./gemini.py "your prompt"
""" """
import subprocess import subprocess
import sys import sys
import os import os
import argparse
DEFAULT_MODEL = os.environ.get('GEMINI_MODEL', 'gemini-3-pro-preview') DEFAULT_MODEL = os.environ.get('GEMINI_MODEL', 'gemini-3-pro-preview')
DEFAULT_WORKDIR = '.' DEFAULT_WORKDIR = '.'
DEFAULT_TIMEOUT = 7200 # 2 hours in seconds TIMEOUT_MS = 7_200_000 # 固定 2 小时,毫秒
DEFAULT_TIMEOUT = TIMEOUT_MS // 1000
FORCE_KILL_DELAY = 5 FORCE_KILL_DELAY = 5
@@ -32,76 +32,56 @@ def log_warn(message: str):
sys.stderr.write(f"WARN: {message}\n") sys.stderr.write(f"WARN: {message}\n")
def resolve_timeout() -> int: def log_info(message: str):
"""解析超时配置(秒)""" """输出信息到 stderr"""
raw = os.environ.get('GEMINI_TIMEOUT', '') sys.stderr.write(f"INFO: {message}\n")
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 parse_args(): def parse_args():
"""解析命令行参数""" """解析位置参数"""
parser = argparse.ArgumentParser( if len(sys.argv) < 2:
description='Gemini CLI wrapper for Claude Code integration', log_error('Prompt required')
formatter_class=argparse.RawDescriptionHelpFormatter sys.exit(1)
)
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)'
)
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: def build_gemini_args(args) -> list:
"""构建 gemini CLI 参数""" """构建 gemini CLI 参数"""
return [ return [
'gemini', 'gemini',
'-m', args.model, '-m', DEFAULT_MODEL,
'-p', args.prompt '-p', args['prompt']
] ]
def main(): def main():
log_info('Script started')
args = parse_args() args = parse_args()
log_info(f"Prompt length: {len(args['prompt'])}")
log_info(f"Working dir: {args['workdir']}")
gemini_args = build_gemini_args(args) 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: try:
os.chdir(args.workdir) os.chdir(args['workdir'])
except FileNotFoundError: except FileNotFoundError:
log_error(f"Working directory not found: {args.workdir}") log_error(f"Working directory not found: {args['workdir']}")
sys.exit(1) sys.exit(1)
except PermissionError: except PermissionError:
log_error(f"Permission denied: {args.workdir}") log_error(f"Permission denied: {args['workdir']}")
sys.exit(1) sys.exit(1)
log_info('Changed working directory')
try: try:
log_info(f"Starting gemini with model {DEFAULT_MODEL}")
process = None
# 启动 gemini 子进程,直接透传 stdout 和 stderr # 启动 gemini 子进程,直接透传 stdout 和 stderr
process = subprocess.Popen( process = subprocess.Popen(
gemini_args, gemini_args,
@@ -112,11 +92,9 @@ def main():
) )
# 实时输出 stdout # 实时输出 stdout
stdout_lines = []
for line in process.stdout: for line in process.stdout:
sys.stdout.write(line) sys.stdout.write(line)
sys.stdout.flush() sys.stdout.flush()
stdout_lines.append(line)
# 等待进程结束 # 等待进程结束
returncode = process.wait(timeout=timeout_sec) returncode = process.wait(timeout=timeout_sec)
@@ -135,11 +113,12 @@ def main():
except subprocess.TimeoutExpired: except subprocess.TimeoutExpired:
log_error(f'Gemini execution timeout ({timeout_sec}s)') log_error(f'Gemini execution timeout ({timeout_sec}s)')
process.kill() if process is not None:
try: process.kill()
process.wait(timeout=FORCE_KILL_DELAY) try:
except subprocess.TimeoutExpired: process.wait(timeout=FORCE_KILL_DELAY)
pass except subprocess.TimeoutExpired:
pass
sys.exit(124) sys.exit(124)
except FileNotFoundError: except FileNotFoundError:
@@ -148,11 +127,12 @@ def main():
sys.exit(127) sys.exit(127)
except KeyboardInterrupt: except KeyboardInterrupt:
process.terminate() if process is not None:
try: process.terminate()
process.wait(timeout=FORCE_KILL_DELAY) try:
except subprocess.TimeoutExpired: process.wait(timeout=FORCE_KILL_DELAY)
process.kill() except subprocess.TimeoutExpired:
process.kill()
sys.exit(130) sys.exit(130)