diff options
| author | Claude <claude@anthropic.com> | 2026-03-04 19:14:55 +0100 |
|---|---|---|
| committer | Claude <claude@anthropic.com> | 2026-03-04 19:14:55 +0100 |
| commit | 171c5b86ef05974426ba5c5d8547c8025977d1a2 (patch) | |
| tree | 2a1193e2bb81a6341e55d0b883a3fc33f77f8be1 /.agents | |
| parent | 9f14edf2b97286e02830d528038b32d5b31aaa0a (diff) | |
| parent | 0278c87f062a9ae7d617b92be22b175558a05086 (diff) | |
| download | gemini-py-main.tar.gz gemini-py-main.zip | |
Diffstat (limited to '.agents')
| -rw-r--r-- | .agents/commands/network-compat-test.md | 80 | ||||
| -rw-r--r-- | .agents/tests/test_basic.py | 45 |
2 files changed, 125 insertions, 0 deletions
diff --git a/.agents/commands/network-compat-test.md b/.agents/commands/network-compat-test.md new file mode 100644 index 0000000..ca3fd18 --- /dev/null +++ b/.agents/commands/network-compat-test.md @@ -0,0 +1,80 @@ +# Network Compatibility Test + +Verify that `gemini-py` produces wire-identical HTTP requests to `gemini-cli`. + +## Prerequisites + +- Docker + Compose +- OAuth credentials at `../config/.gemini/oauth_creds.json` + (or set `GEMINI_CONFIG_DIR` to point elsewhere) + +## Steps + +### 1. Start mitmproxy + +```bash +docker compose up proxy -d +``` + +Web UI available at `http://localhost:8081`. + +### 2. Clear previous captures + +```bash +rm -f test/captures/req_*.json test/captures/res_*.json +``` + +### 3. Run gemini-py + +```bash +docker compose run --rm gemini-py +``` + +### 4. Run gemini-cli + +```bash +docker compose run --rm gemini-cli +``` + +### 5. Identify the generateContent requests + +```bash +for f in test/captures/req_*.json; do + python3 -c " +import json +with open('$f') as fh: d=json.load(fh) +b=d.get('body',{}) +model=b.get('model','') if isinstance(b,dict) else '' +print(f'$(basename $f): [{d.get(\"source\",\"?\")}] {d[\"method\"]} {d[\"url\"].split(\"googleapis.com\")[1]} model={model}') +" +done +``` + +### 6. Compare + +```bash +python3 test/scripts/compare.py test/captures/ +``` + +## What Gets Compared + +| Layer | Fields checked | +|-------|----------------| +| **Headers** | All except `authorization`, `content-length`, `host`, `connection`, `accept-encoding` | +| **Body** | `model`, `project`, `request.generationConfig` | +| **Skipped** | `user_prompt_id`, `request.session_id`, `request.contents` (session-specific) | + +## Topology + +``` +┌───────────┐ ┌───────────┐ ┌──────────────────────────────┐ +│ gemini-py │──HTTP──│ mitmproxy │──HTTPS──│ cloudcode-pa.googleapis.com │ +└───────────┘ 9090 │ :9090 │ └──────────────────────────────┘ + │ web:8081 │ +┌────────────┐ │ capture │ +│ gemini-cli │──HTTP─│ addon │ +└────────────┘ └───────────┘ + │ + test/captures/ + req_NNNN.json +``` diff --git a/.agents/tests/test_basic.py b/.agents/tests/test_basic.py new file mode 100644 index 0000000..39fba1d --- /dev/null +++ b/.agents/tests/test_basic.py @@ -0,0 +1,45 @@ +import asyncio +import sys +sys.path.insert(0, "/home/claude/host/gemini-py/src") + +from gemini import GeminiClient, GeminiOptions, query + +CREDS = "/home/claude/host/config/.gemini/oauth_creds.json" + +async def test_non_streaming(): + print("=== Non-streaming test ===") + opts = GeminiOptions(model="gemini-2.5-flash-lite") + async with GeminiClient(options=opts, credentials_path=CREDS) as client: + response = await client.send_message("Say hello in exactly 3 words.") + print("Response:", response.text) + print("Thinking:", response.thinking[:100] if response.thinking else "(none)") + print("Usage:", response.usage_metadata) + print() + +async def test_streaming(): + print("=== Streaming test ===") + opts = GeminiOptions(model="gemini-2.5-flash-lite") + async with GeminiClient(options=opts, credentials_path=CREDS) as client: + print("Response: ", end="") + async for chunk in client.send_message_stream("Count from 1 to 5."): + print(chunk.text_delta, end="", flush=True) + print() + print() + +async def test_multi_turn(): + print("=== Multi-turn test ===") + opts = GeminiOptions(model="gemini-2.5-flash-lite") + async with GeminiClient(options=opts, credentials_path=CREDS) as client: + r1 = await client.send_message("My name is Alice.") + print("Turn 1:", r1.text) + r2 = await client.send_message("What is my name?") + print("Turn 2:", r2.text) + print() + +async def main(): + await test_non_streaming() + await test_streaming() + await test_multi_turn() + +if __name__ == "__main__": + asyncio.run(main()) |
