@@ -2,6 +2,7 @@ package taskengine
22
33import (
44 "context"
5+ "fmt"
56 "net/http"
67 "strings"
78 "time"
@@ -108,31 +109,34 @@ func ComposeSummarySmart(vm *VM, currentStepName string) Summary {
108109 return s
109110}
110111
111- // NewContextMemorySummarizerFromAggregatorConfig creates a ContextMemorySummarizer from aggregator config
112- // Reads api_endpoint and api_key from notifications.summary section
113- func NewContextMemorySummarizerFromAggregatorConfig (c * config.Config ) Summarizer {
114- if c == nil {
115- return nil
116- }
117- if ! c .NotificationsSummary .Enabled || strings .ToLower (c .NotificationsSummary .Provider ) != "context-memory" {
118- return nil
119- }
120- baseURL := c .NotificationsSummary .APIEndpoint
121- if strings .TrimSpace (baseURL ) == "" {
122- return nil
112+ // NewContextMemorySummarizerFromAggregatorConfig builds the workflow summarizer from the
113+ // aggregator's notifications.summary config (api_endpoint + api_key).
114+ //
115+ // Returns (nil, nil) when summarization is disabled — a valid "off" mode in which callers
116+ // use the deterministic summarizer. Returns (nil, error) when summarization is ENABLED but
117+ // misconfigured (unsupported provider, or empty endpoint/key) so the daemon fails fast at
118+ // startup instead of silently degrading. There is no hardcoded endpoint default: the origin
119+ // must come from config (avs-infra: ${SUMMARIZER_API_URL} / ${SUMMARIZER_API_KEY}).
120+ func NewContextMemorySummarizerFromAggregatorConfig (c * config.Config ) (Summarizer , error ) {
121+ if c == nil || ! c .NotificationsSummary .Enabled {
122+ return nil , nil // Not enabled — deterministic fallback is used.
123123 }
124- authToken := c .NotificationsSummary .APIKey
125- if strings .TrimSpace (authToken ) == "" {
126- return nil
124+ if strings .ToLower (c .NotificationsSummary .Provider ) != "context-memory" {
125+ return nil , fmt .Errorf ("notifications.summary.enabled is true but provider %q is unsupported (expected \" context-memory\" )" , c .NotificationsSummary .Provider )
127126 }
127+ baseURL := strings .TrimSpace (c .NotificationsSummary .APIEndpoint )
128128 if baseURL == "" {
129- baseURL = ContextAPIURL
129+ return nil , fmt .Errorf ("notifications.summary.enabled is true but api_endpoint is empty (set SUMMARIZER_API_URL to the Studio origin, e.g. https://app.avaprotocol.org)" )
130+ }
131+ authToken := strings .TrimSpace (c .NotificationsSummary .APIKey )
132+ if authToken == "" {
133+ return nil , fmt .Errorf ("notifications.summary.enabled is true but api_key is empty (set SUMMARIZER_API_KEY)" )
130134 }
131135 return & ContextMemorySummarizer {
132136 baseURL : baseURL ,
133137 authToken : authToken ,
134138 httpClient : & http.Client {Timeout : 30 * time .Second },
135- }
139+ }, nil
136140}
137141
138142// FormatForMessageChannels converts a Summary into a concise chat message
0 commit comments