82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
import subprocess
|
|
import json
|
|
import sys
|
|
import time
|
|
import os
|
|
|
|
class GeminiCliAdapter:
|
|
def __init__(self, binary_path="gemini"):
|
|
self.binary_path = binary_path
|
|
self.last_usage = None
|
|
self.session_id = None
|
|
self.last_latency = 0.0
|
|
|
|
def send(self, message):
|
|
"""
|
|
Sends a message to the Gemini CLI and processes the streaming JSON output.
|
|
"""
|
|
start_time = time.time()
|
|
# On Windows, using shell=True allows executing .cmd/.bat files and
|
|
# handles command strings with arguments more gracefully.
|
|
# We pass the message via stdin to avoid command-line length limits.
|
|
command = f'{self.binary_path} run --output-format stream-json'
|
|
if self.session_id:
|
|
command += f' --resume {self.session_id}'
|
|
|
|
accumulated_text = ""
|
|
|
|
env = os.environ.copy()
|
|
env["GEMINI_CLI_HOOK_CONTEXT"] = "manual_slop"
|
|
|
|
process = subprocess.Popen(
|
|
command,
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
shell=True,
|
|
env=env
|
|
)
|
|
|
|
try:
|
|
# Send message to stdin and close it
|
|
process.stdin.write(message)
|
|
process.stdin.close()
|
|
|
|
# Read stdout line by line
|
|
for line in process.stdout:
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
|
|
try:
|
|
data = json.loads(line)
|
|
msg_type = data.get("type")
|
|
|
|
if msg_type == "message":
|
|
# Append message text to results
|
|
accumulated_text += data.get("text", "")
|
|
|
|
elif msg_type == "result":
|
|
# Capture final usage and session persistence
|
|
self.last_usage = data.get("usage")
|
|
self.session_id = data.get("session_id")
|
|
|
|
elif msg_type in ("status", "tool_use"):
|
|
# Log status/tool_use to stderr for debugging
|
|
sys.stderr.write(f"GeminiCliAdapter [{msg_type}]: {line}\n")
|
|
sys.stderr.flush()
|
|
|
|
except json.JSONDecodeError:
|
|
# Skip lines that are not valid JSON
|
|
continue
|
|
|
|
process.wait()
|
|
except Exception as e:
|
|
process.kill()
|
|
raise e
|
|
finally:
|
|
self.last_latency = time.time() - start_time
|
|
|
|
return accumulated_text
|