Phase 7: daily summary and read-only Hub API (AUD-73)
- internal/hub: project side of the frozen ask-contract. GET /capabilities, read-only POST /ask answerer (no LLM, <3s), and the outbound POST /notify client. - internal/apprise: daily-summary delivery through the house Apprise API. - internal/summary: deterministic plain-text daily summary builder. - internal/store: CountByCategory, MessagesByCategory, and summary CRUD. - internal/server: /capabilities and /ask (bearer-token protected), plus the Reports screen (/reports, build, send, delete). - main.go: -summary, -summary-send, and -notify CLI entry points for n8n. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -17,13 +17,16 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/apprise"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/classify"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/config"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/hub"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/mailfetch"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/mailops"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/reply"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/session"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/store"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/summary"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/internal/version"
|
||||
"gitea.lab.audasmedia.com.au/sam/email_agent/web"
|
||||
)
|
||||
@@ -46,6 +49,12 @@ type Server struct {
|
||||
actions MailActions
|
||||
replies ReplyGenerator
|
||||
sender MailSender
|
||||
// Phase 7 (FR-10/FR-12): the read-only Hub answerer, the outbound
|
||||
// notifier, the daily-summary builder, and the Apprise delivery client.
|
||||
answerer *hub.Answerer
|
||||
notifier *hub.Notifier
|
||||
summaries *summary.Builder
|
||||
apprise *apprise.Client
|
||||
}
|
||||
|
||||
// New builds a Server. It does not start listening.
|
||||
@@ -82,6 +91,10 @@ func New(cfg *config.Config, st *store.Store, logger *slog.Logger) (*Server, err
|
||||
reply.NewClient(cfg.OmniRouteBaseURL, cfg.OmniRouteAPIKey, cfg.OmniRouteModel, logger),
|
||||
logger,
|
||||
),
|
||||
answerer: hub.NewAnswerer(st),
|
||||
notifier: hub.NewNotifier(cfg.HubBaseURL, cfg.HubToken, cfg.HubNotifyTimeout, nil),
|
||||
summaries: summary.New(st),
|
||||
apprise: apprise.New(cfg.AppriseURL, cfg.AppriseKey, cfg.AppriseURLs, cfg.AppriseToken, 0),
|
||||
}
|
||||
s.http = &http.Server{
|
||||
Addr: cfg.Addr,
|
||||
@@ -161,6 +174,16 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("POST /unsubscribe/unignore", s.requireAuth(s.handleUnsubscribeUnignore))
|
||||
mux.HandleFunc("POST /unsubscribe/mark", s.requireAuth(s.handleUnsubscribeMark))
|
||||
|
||||
// Phase 7 (FR-12): the Hub contract. /ask is read-only and token-protected.
|
||||
mux.HandleFunc("GET /capabilities", s.requireHub(s.handleCapabilities))
|
||||
mux.HandleFunc("POST /ask", s.requireHub(s.handleAsk))
|
||||
|
||||
// Phase 7 (FR-10): daily summary and the Reports screen.
|
||||
mux.HandleFunc("GET /reports", s.requireAuth(s.handleReports))
|
||||
mux.HandleFunc("POST /reports/generate", s.requireAuth(s.handleSummaryGenerate))
|
||||
mux.HandleFunc("POST /reports/send", s.requireAuth(s.handleSummarySend))
|
||||
mux.HandleFunc("POST /reports/delete", s.requireAuth(s.handleSummaryDelete))
|
||||
|
||||
return s.recoverPanic(s.logRequests(mux))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user