diff --git a/src/openjarvis/agents/morning_digest.py b/src/openjarvis/agents/morning_digest.py index 876f63ef..5583ee97 100644 --- a/src/openjarvis/agents/morning_digest.py +++ b/src/openjarvis/agents/morning_digest.py @@ -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() diff --git a/src/openjarvis/sdk.py b/src/openjarvis/sdk.py index 835f9e29..10fd2c69 100644 --- a/src/openjarvis/sdk.py +++ b/src/openjarvis/sdk.py @@ -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() diff --git a/src/openjarvis/speech/cartesia_tts.py b/src/openjarvis/speech/cartesia_tts.py index 21a15a58..256a0c10 100644 --- a/src/openjarvis/speech/cartesia_tts.py +++ b/src/openjarvis/speech/cartesia_tts.py @@ -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, diff --git a/src/openjarvis/system.py b/src/openjarvis/system.py index e04cfbbb..09ae0303 100644 --- a/src/openjarvis/system.py +++ b/src/openjarvis/system.py @@ -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, diff --git a/src/openjarvis/tools/text_to_speech.py b/src/openjarvis/tools/text_to_speech.py index d17ebd82..a0378bf9 100644 --- a/src/openjarvis/tools/text_to_speech.py +++ b/src/openjarvis/tools/text_to_speech.py @@ -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")