Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 66 additions & 14 deletions anton/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import typer
from rich.console import Console
from rich.live import Live
from rich.panel import Panel
from rich.prompt import Confirm
from rich.spinner import Spinner
from rich.table import Table
Expand Down Expand Up @@ -175,9 +176,26 @@ def _ensure_dependencies(console: Console) -> None:
raise typer.Exit(1)


def _ensure_terms_consent(console: Console, settings) -> None:
"""Show terms acceptance screen on first run and persist the choice."""
# Clear screen
_TERMS_SUMMARY = (
"[bold]What you should know[/]\n\n"
" • Anton runs on your machine. Your code, files, and queries\n"
" stay local unless you explicitly ask Anton to send them.\n\n"
" • Anton sends anonymous usage events (e.g. session started)\n"
" to MindsDB to help us improve. No code or query content is\n"
" included. Disable with [anton.cyan]ANTON_ANALYTICS_ENABLED=false[/].\n\n"
" • When Anton uses an LLM provider you configure (OpenAI,\n"
" Anthropic, Minds, etc.), the prompts you send go to that\n"
" provider and are governed by their own terms.\n\n"
" • You're responsible for what Anton does on your behalf —\n"
" review proposed actions before authorizing them.\n\n"
"[bold]Full text[/]\n\n"
" Terms: [link=https://mindsdb.com/terms]https://mindsdb.com/terms[/]\n"
" Privacy: [link=https://mindsdb.com/privacy-policy]https://mindsdb.com/privacy-policy[/]\n"
)


def _render_terms_screen(console: Console) -> None:
"""Render the welcome banner + policy summary panel."""
os.system("cls" if sys.platform == "win32" else "clear")

logo = "A N T O N"
Expand All @@ -192,21 +210,55 @@ def _ensure_terms_consent(console: Console, settings) -> None:
" and accept our Anton policies."
)
console.print()
console.print(
Panel(
_TERMS_SUMMARY,
title="Anton — Terms & Privacy",
title_align="left",
border_style="anton.cyan",
padding=(1, 2),
)
)
console.print()

if Confirm.ask(
" Would you like to read the policies?", default=True, console=console
):
webbrowser.open("https://mindsdb.com/terms")
webbrowser.open("https://mindsdb.com/privacy-policy")

def _show_full_policies(console: Console) -> None:
"""Render the full Terms + Privacy Policy through the system pager."""
from rich.markdown import Markdown
from rich.rule import Rule

from anton.policies import PRIVACY_POLICY_MD, TERMS_OF_USE_MD

with console.pager(styles=True):
console.print(Markdown(TERMS_OF_USE_MD))
console.print()
console.print(" [anton.muted]Policies opened in your browser.[/]")
console.print(Rule(style="anton.cyan"))
console.print()
console.print(Markdown(PRIVACY_POLICY_MD))

accepted = Confirm.ask(
" Do you accept the Terms and Privacy Policy?",
default=True,
console=console,
)

def _ensure_terms_consent(console: Console, settings) -> None:
"""Show terms acceptance screen on first run and persist the choice."""
from rich.prompt import Prompt

accepted: bool | None = None
while accepted is None:
_render_terms_screen(console)
choice = Prompt.ask(
" Accept Terms and Privacy Policy? "
"[bold]y[/]es / [bold]n[/]o / [bold]s[/]how full text",
choices=["y", "n", "s"],
default="y",
show_choices=False,
console=console,
).lower()

if choice == "y":
accepted = True
elif choice == "n":
accepted = False
elif choice == "s":
_show_full_policies(console)

if not accepted:
console.print()
Expand Down
Loading
Loading