Files
Jay Brown 72de690894 Merged in feature/chatbot1 (pull request #223)
Chatbot functionality

* baseline working

* missing test file

* more tests
2026-05-07 20:56:18 +00:00

71 lines
2.8 KiB
Go

// Package bot owns the chatbot session/scope/turn service for the
// queryAPI. M2 implements session and scope CRUD; M3 adds the FastAPI
// client; M4 adds AddTurn orchestration. See plans/chatbot_plan_codex.v10.md
// for the canonical spec.
//
// Authorization boundary: this package never imports cognitoauth. The
// handler extracts the Cognito subject and passes it as the actor
// argument; every owner-scoped read/write filters on (client_id,
// created_by, is_deleted=false). Super-admin reads filter on
// (client_id, is_deleted=false).
package bot
import (
"fmt"
"net/http"
"queryorchestration/internal/serviceconfig"
"queryorchestration/internal/serviceconfig/chatbot"
)
// Service is the chatbot domain service. It holds the validated chatbot
// configuration plus the database access provided by the embedding
// QueryAPIConfig (via serviceconfig.ConfigProvider).
type Service struct {
cfg chatbot.ChatbotConfig
dbCfg serviceconfig.ConfigProvider
fastAPI *FastAPIClient
}
// New constructs a Service. It validates the supplied chatbot config
// up-front so a caller cannot accidentally instantiate a service whose
// preview turn-limit cap is out of range. The dbCfg argument is the
// existing serviceconfig.ConfigProvider (queryAPI's QueryAPIConfig) used
// for DB access; it may be nil in pure unit tests that exercise only
// the validation gate.
//
// Returns the constructed Service plus a non-nil error when the config
// fails Validate. Plan §8 mandates the validation here so any future
// caller (CLI, integration tests, alternate composition roots) inherits
// the same gate.
//
// The FastAPI client is constructed eagerly so M4's AddTurn path has a
// ready dependency and so the WithBaseURL / WithHTTPClient options get
// exercised from production code. WithBaseURL forces the client to
// honor the cfg.ServiceURL even if a future refactor changes the
// FastAPIClient default; WithHTTPClient passes a fresh http.Client so
// the M3 retry logic can drive its own timeouts without sharing a
// connection pool with unrelated callers.
func New(cfg chatbot.ChatbotConfig, dbCfg serviceconfig.ConfigProvider) (*Service, error) {
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("bot.New: %w", err)
}
fastAPI := NewFastAPIClient(cfg,
WithBaseURL(cfg.ServiceURL),
WithHTTPClient(&http.Client{}),
)
return &Service{cfg: cfg, dbCfg: dbCfg, fastAPI: fastAPI}, nil
}
// MinTurnLimit returns min(reqLimit, recentTurns). Plan §3 mandates
// turn_limit = min(request.limit, cfg.RecentTurns) for the session-list
// preview. Exported so the service, handlers, and tests share one
// implementation. Negative inputs are returned as-is so the caller can
// fail closed at the validation layer rather than silently clamping.
func MinTurnLimit(reqLimit, recentTurns int) int {
if reqLimit < recentTurns {
return reqLimit
}
return recentTurns
}