mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-27 21:05:34 +00:00
fix: wire DigestConfig through SDK and system for end-to-end digest
- Inject DigestConfig (persona, sections, TTS backend, voice_id) into MorningDigestAgent from both JarvisSystem._run_agent and Jarvis SDK - Always inject digest_collect + text_to_speech tools for digest agent - Fix TTS tool: import speech backends before checking TTSRegistry - Fix Cartesia: default to British Butler voice when voice_id is empty - Fix DigestStore: allow cross-thread SQLite access for FastAPI - Propagate agent metadata (audio_path) through system return dict - Add music section to default source map in MorningDigestAgent Tested end-to-end: Qwen3.5 9B (Ollama) + Cartesia TTS + real data from Oura, Gmail, Calendar, Tasks, Spotify, Apple Music. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
fd354e229c
commit
bff925a679
@@ -69,7 +69,8 @@ class MorningDigestAgent(ToolUsingAgent):
|
||||
default_source_map = {
|
||||
"messages": ["gmail", "slack", "google_tasks"],
|
||||
"calendar": ["gcalendar"],
|
||||
"health": ["oura"],
|
||||
"health": ["oura", "apple_health"],
|
||||
"music": ["spotify", "apple_music"],
|
||||
"world": [], # Handled by web_search, not connectors
|
||||
}
|
||||
sources = set()
|
||||
|
||||
@@ -482,6 +482,30 @@ class Jarvis:
|
||||
if self._capability_policy is not None:
|
||||
agent_kwargs["capability_policy"] = self._capability_policy
|
||||
|
||||
# Inject DigestConfig for morning_digest agent
|
||||
if agent_name == "morning_digest" and hasattr(self._config, "digest"):
|
||||
dc = self._config.digest
|
||||
section_sources: Dict[str, Any] = {}
|
||||
for s in dc.sections:
|
||||
sc = getattr(dc, s, None)
|
||||
if sc and hasattr(sc, "sources"):
|
||||
section_sources[s] = sc.sources
|
||||
agent_kwargs.update({
|
||||
"persona": dc.persona,
|
||||
"sections": dc.sections,
|
||||
"section_sources": section_sources,
|
||||
"timezone": dc.timezone,
|
||||
"voice_id": dc.voice_id,
|
||||
"tts_backend": dc.tts_backend,
|
||||
})
|
||||
# Ensure digest agent always has its required tools
|
||||
from openjarvis.tools.digest_collect import DigestCollectTool
|
||||
from openjarvis.tools.text_to_speech import TextToSpeechTool
|
||||
|
||||
digest_tools = [DigestCollectTool(), TextToSpeechTool()]
|
||||
existing = agent_kwargs.get("tools", [])
|
||||
agent_kwargs["tools"] = digest_tools + list(existing)
|
||||
|
||||
agent_obj = agent_cls(self._engine, model_name, **agent_kwargs)
|
||||
ctx = AgentContext()
|
||||
|
||||
|
||||
@@ -70,6 +70,10 @@ class CartesiaTTSBackend(TTSBackend):
|
||||
if not self._api_key:
|
||||
raise RuntimeError("CARTESIA_API_KEY not set")
|
||||
|
||||
# Default to "British Butler" voice — warm, authoritative, Jarvis-like
|
||||
if not voice_id:
|
||||
voice_id = "a0e99841-438c-4a64-b679-ae501e7d6091"
|
||||
|
||||
audio = _cartesia_synthesize(
|
||||
self._api_key,
|
||||
text,
|
||||
|
||||
@@ -211,6 +211,30 @@ class JarvisSystem:
|
||||
agent_kwargs["session_store"] = self.session_store
|
||||
agent_kwargs["memory_backend"] = self.memory_backend
|
||||
|
||||
# Inject DigestConfig when instantiating the morning_digest agent
|
||||
if agent_name == "morning_digest" and hasattr(self.config, "digest"):
|
||||
dc = self.config.digest
|
||||
section_sources = {}
|
||||
for s in dc.sections:
|
||||
sc = getattr(dc, s, None)
|
||||
if sc and hasattr(sc, "sources"):
|
||||
section_sources[s] = sc.sources
|
||||
agent_kwargs.update({
|
||||
"persona": dc.persona,
|
||||
"sections": dc.sections,
|
||||
"section_sources": section_sources,
|
||||
"timezone": dc.timezone,
|
||||
"voice_id": dc.voice_id,
|
||||
"tts_backend": dc.tts_backend,
|
||||
})
|
||||
# Ensure digest agent always has its required tools
|
||||
from openjarvis.tools.digest_collect import DigestCollectTool
|
||||
from openjarvis.tools.text_to_speech import TextToSpeechTool
|
||||
|
||||
digest_tools = [DigestCollectTool(), TextToSpeechTool()]
|
||||
existing = agent_kwargs.get("tools", [])
|
||||
agent_kwargs["tools"] = digest_tools + list(existing)
|
||||
|
||||
try:
|
||||
ag = agent_cls(self.engine, self.model, **agent_kwargs)
|
||||
except TypeError:
|
||||
@@ -304,6 +328,7 @@ class JarvisSystem:
|
||||
for tr in getattr(result, "tool_results", [])
|
||||
],
|
||||
"turns": getattr(result, "turns", 1),
|
||||
"metadata": getattr(result, "metadata", {}),
|
||||
"model": self.model,
|
||||
"engine": self.engine_key,
|
||||
"_telemetry": _telemetry,
|
||||
|
||||
@@ -53,6 +53,9 @@ class TextToSpeechTool(BaseTool):
|
||||
)
|
||||
|
||||
def execute(self, **params: Any) -> ToolResult:
|
||||
# Ensure TTS backends are registered
|
||||
import openjarvis.speech # noqa: F401
|
||||
|
||||
text = params.get("text", "")
|
||||
voice_id = params.get("voice_id", "")
|
||||
backend_key = params.get("backend", "cartesia")
|
||||
|
||||
Reference in New Issue
Block a user