aboutsummaryrefslogtreecommitdiffstats
path: root/.agents
diff options
context:
space:
mode:
authorClaude <claude@anthropic.com>2026-03-04 19:14:55 +0100
committerClaude <claude@anthropic.com>2026-03-04 19:14:55 +0100
commit171c5b86ef05974426ba5c5d8547c8025977d1a2 (patch)
tree2a1193e2bb81a6341e55d0b883a3fc33f77f8be1 /.agents
parent9f14edf2b97286e02830d528038b32d5b31aaa0a (diff)
parent0278c87f062a9ae7d617b92be22b175558a05086 (diff)
downloadgemini-py-main.tar.gz
gemini-py-main.zip
Add initial versionHEADmain
Diffstat (limited to '.agents')
-rw-r--r--.agents/commands/network-compat-test.md80
-rw-r--r--.agents/tests/test_basic.py45
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())