From e025136047bfed99c7a66a0b2870b66ee79296d2 Mon Sep 17 00:00:00 2001 From: Jiho Son Date: Wed, 4 Feb 2026 02:56:31 +0900 Subject: [PATCH] Fix Docker runtime errors: migrate to google-genai SDK and fix SQLite permissions Migrate from deprecated google-generativeai to google-genai (>=1.0) using the new Client-based API, and fix SQLite "unable to open database file" in Docker by chowning the data directory to appuser before switching users. Co-Authored-By: Claude Opus 4.5 --- Dockerfile | 1 + pyproject.toml | 2 +- src/brain/gemini_client.py | 10 ++++++---- src/db.py | 3 +++ src/evolution/optimizer.py | 10 ++++++---- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index f2b0423..f47239e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,6 +35,7 @@ RUN mkdir -p data # Non-root user RUN useradd --create-home appuser +RUN chown appuser:appuser data USER appuser HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ diff --git a/pyproject.toml b/pyproject.toml index a1d141a..ab83e19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ dependencies = [ "aiohttp>=3.9,<4", "pydantic>=2.5,<3", "pydantic-settings>=2.1,<3", - "google-generativeai>=0.8,<1", + "google-genai>=1.0,<2", ] [project.optional-dependencies] diff --git a/src/brain/gemini_client.py b/src/brain/gemini_client.py index 9004545..0d48d28 100644 --- a/src/brain/gemini_client.py +++ b/src/brain/gemini_client.py @@ -12,7 +12,7 @@ import re from dataclasses import dataclass from typing import Any -import google.generativeai as genai +from google import genai from src.config import Settings @@ -36,8 +36,8 @@ class GeminiClient: def __init__(self, settings: Settings) -> None: self._settings = settings self._confidence_threshold = settings.CONFIDENCE_THRESHOLD - genai.configure(api_key=settings.GEMINI_API_KEY) - self._model = genai.GenerativeModel(settings.GEMINI_MODEL) + self._client = genai.Client(api_key=settings.GEMINI_API_KEY) + self._model_name = settings.GEMINI_MODEL # ------------------------------------------------------------------ # Prompt Construction @@ -133,7 +133,9 @@ class GeminiClient: logger.info("Requesting trade decision from Gemini") try: - response = await self._model.generate_content_async(prompt) + response = await self._client.aio.models.generate_content( + model=self._model_name, contents=prompt, + ) raw = response.text except Exception as exc: logger.error("Gemini API error: %s", exc) diff --git a/src/db.py b/src/db.py index 16f1e0e..c8d4957 100644 --- a/src/db.py +++ b/src/db.py @@ -4,11 +4,14 @@ from __future__ import annotations import sqlite3 from datetime import datetime, timezone +from pathlib import Path from typing import Any def init_db(db_path: str) -> sqlite3.Connection: """Initialize the trade logs database and return a connection.""" + if db_path != ":memory:": + Path(db_path).parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(db_path) conn.execute( """ diff --git a/src/evolution/optimizer.py b/src/evolution/optimizer.py index 4947b76..eb6d1dc 100644 --- a/src/evolution/optimizer.py +++ b/src/evolution/optimizer.py @@ -18,7 +18,7 @@ from datetime import datetime, timezone from pathlib import Path from typing import Any -import google.generativeai as genai +from google import genai from src.config import Settings @@ -51,8 +51,8 @@ class EvolutionOptimizer: def __init__(self, settings: Settings) -> None: self._settings = settings self._db_path = settings.DB_PATH - genai.configure(api_key=settings.GEMINI_API_KEY) - self._model = genai.GenerativeModel(settings.GEMINI_MODEL) + self._client = genai.Client(api_key=settings.GEMINI_API_KEY) + self._model_name = settings.GEMINI_MODEL # ------------------------------------------------------------------ # Analysis @@ -122,7 +122,9 @@ class EvolutionOptimizer: ) try: - response = await self._model.generate_content_async(prompt) + response = await self._client.aio.models.generate_content( + model=self._model_name, contents=prompt, + ) body = response.text.strip() except Exception as exc: logger.error("Failed to generate strategy: %s", exc)