package grpc import ( "context" "gitea.nik4nao.com/nik/home-services/ai-gateway/internal/app" "gitea.nik4nao.com/nik/home-services/ai-gateway/internal/logger" aiv1 "gitea.nik4nao.com/nik/home-services/gen/ai/v1" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // Server adapts the AI query app to the gRPC transport. type Server struct { aiv1.UnimplementedAIServiceServer app *app.QueryApp } // NewServer constructs the AIService gRPC adapter. func NewServer(app *app.QueryApp) *Server { return &Server{app: app} } // Query handles one AI query request. func (s *Server) Query(ctx context.Context, req *aiv1.QueryRequest) (*aiv1.QueryResponse, error) { if req.GetText() == "" { return nil, status.Error(codes.InvalidArgument, "text is required") } log := logger.FromContext(ctx) if req.GetSource() != "" { log = log.With("source", req.GetSource()) ctx = logger.WithLogger(ctx, log) } result, err := s.app.Query(ctx, req.GetText(), req.GetModel()) if err != nil { return nil, status.Errorf(codes.Unavailable, "query failed: %v", err) } return &aiv1.QueryResponse{ Reply: result.Reply, Intent: result.Intent, ActionTaken: result.ActionTaken, ModelUsed: result.ModelUsed, }, nil } // ListModels returns the installed model names from Ollama. func (s *Server) ListModels(ctx context.Context, _ *aiv1.ListModelsRequest) (*aiv1.ListModelsResponse, error) { names, err := s.app.ListModels(ctx) if err != nil { return nil, status.Errorf(codes.Unavailable, "list models: %v", err) } return &aiv1.ListModelsResponse{Names: names}, nil }