@click.command("digest", help="Display and play the morning digest.")
@click.option("--text-only", is_flag=True, help="Print text without audio playback.")
@click.option("--fresh", is_flag=True, help="Re-generate the digest (skip cache).")
@click.option("--history", is_flag=True, help="Show past digests.")
@click.option("--section", type=str, default="", help="Show only a specific section.")
@click.option("--db-path", type=str, default="", help="Path to digest database.")
@click.option(
"--schedule",
type=str,
default=None,
is_eager=True,
help=(
'Set cron schedule (e.g. "0 6 * * *"), '
'"off" to disable, or empty to show status.'
),
)
def digest(
text_only: bool,
fresh: bool,
history: bool,
section: str,
db_path: str,
schedule: Optional[str],
) -> None:
"""Display and optionally play the morning digest."""
console = Console()
# Handle --schedule flag
if schedule is not None:
_handle_schedule(console, schedule)
return
store = DigestStore(db_path=db_path) if db_path else DigestStore()
if history:
past = store.history(limit=10)
if not past:
console.print("[dim]No past digests found.[/dim]")
store.close()
return
for artifact in past:
console.print(
f"[bold]{artifact.generated_at.strftime('%Y-%m-%d %H:%M')}[/bold]"
f" — {artifact.model_used} / {artifact.voice_used}"
)
console.print(artifact.text[:200] + "...\n")
store.close()
return
if fresh:
# Trigger on-demand generation
console.print("[yellow]Generating fresh digest...[/yellow]")
try:
from openjarvis.sdk import Jarvis
with Jarvis() as j:
result = j.ask("Generate my morning digest", agent="morning_digest")
console.print(Markdown(result))
except Exception as exc:
console.print(f"[red]Failed to generate digest: {exc}[/red]")
store.close()
return
# Try to load today's cached digest
artifact = store.get_today()
if artifact is None:
console.print("[dim]No digest for today. Use --fresh to generate one.[/dim]")
store.close()
return
# Display text
text = artifact.text
if section:
# Try to extract just the requested section
lines = text.split("\n")
in_section = False
section_lines = []
for line in lines:
if line.strip().lower().startswith(
f"## {section.lower()}"
) or line.strip().lower().startswith(f"# {section.lower()}"):
in_section = True
section_lines.append(line)
elif in_section and line.strip().startswith("#"):
break
elif in_section:
section_lines.append(line)
text = "\n".join(section_lines) if section_lines else text
# Play audio in background while text renders
audio_path = str(artifact.audio_path)
if not text_only and audio_path and artifact.audio_path.exists():
audio_thread = threading.Thread(
target=_play_audio, args=(audio_path,), daemon=True
)
audio_thread.start()
console.print(Markdown(text))
store.close()