Fix Docker runtime errors: migrate to google-genai SDK and fix SQLite permissions
Some checks failed
CI / test (push) Has been cancelled

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 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 02:56:31 +09:00
parent 03c6b2b942
commit e025136047
5 changed files with 17 additions and 9 deletions

View File

@@ -35,6 +35,7 @@ RUN mkdir -p data
# Non-root user # Non-root user
RUN useradd --create-home appuser RUN useradd --create-home appuser
RUN chown appuser:appuser data
USER appuser USER appuser
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=5s --retries=3 \

View File

@@ -7,7 +7,7 @@ dependencies = [
"aiohttp>=3.9,<4", "aiohttp>=3.9,<4",
"pydantic>=2.5,<3", "pydantic>=2.5,<3",
"pydantic-settings>=2.1,<3", "pydantic-settings>=2.1,<3",
"google-generativeai>=0.8,<1", "google-genai>=1.0,<2",
] ]
[project.optional-dependencies] [project.optional-dependencies]

View File

@@ -12,7 +12,7 @@ import re
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
import google.generativeai as genai from google import genai
from src.config import Settings from src.config import Settings
@@ -36,8 +36,8 @@ class GeminiClient:
def __init__(self, settings: Settings) -> None: def __init__(self, settings: Settings) -> None:
self._settings = settings self._settings = settings
self._confidence_threshold = settings.CONFIDENCE_THRESHOLD self._confidence_threshold = settings.CONFIDENCE_THRESHOLD
genai.configure(api_key=settings.GEMINI_API_KEY) self._client = genai.Client(api_key=settings.GEMINI_API_KEY)
self._model = genai.GenerativeModel(settings.GEMINI_MODEL) self._model_name = settings.GEMINI_MODEL
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Prompt Construction # Prompt Construction
@@ -133,7 +133,9 @@ class GeminiClient:
logger.info("Requesting trade decision from Gemini") logger.info("Requesting trade decision from Gemini")
try: 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 raw = response.text
except Exception as exc: except Exception as exc:
logger.error("Gemini API error: %s", exc) logger.error("Gemini API error: %s", exc)

View File

@@ -4,11 +4,14 @@ from __future__ import annotations
import sqlite3 import sqlite3
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path
from typing import Any from typing import Any
def init_db(db_path: str) -> sqlite3.Connection: def init_db(db_path: str) -> sqlite3.Connection:
"""Initialize the trade logs database and return a 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 = sqlite3.connect(db_path)
conn.execute( conn.execute(
""" """

View File

@@ -18,7 +18,7 @@ from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
import google.generativeai as genai from google import genai
from src.config import Settings from src.config import Settings
@@ -51,8 +51,8 @@ class EvolutionOptimizer:
def __init__(self, settings: Settings) -> None: def __init__(self, settings: Settings) -> None:
self._settings = settings self._settings = settings
self._db_path = settings.DB_PATH self._db_path = settings.DB_PATH
genai.configure(api_key=settings.GEMINI_API_KEY) self._client = genai.Client(api_key=settings.GEMINI_API_KEY)
self._model = genai.GenerativeModel(settings.GEMINI_MODEL) self._model_name = settings.GEMINI_MODEL
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Analysis # Analysis
@@ -122,7 +122,9 @@ class EvolutionOptimizer:
) )
try: 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() body = response.text.strip()
except Exception as exc: except Exception as exc:
logger.error("Failed to generate strategy: %s", exc) logger.error("Failed to generate strategy: %s", exc)