#!/usr/bin/env python3 """Transform one complete Jukebox transcript through an authenticated CLI.""" from __future__ import annotations import json import sys import time from pathlib import Path PLUGIN_DIR = Path(__file__).resolve().parent.parent sys.path.insert(0, str(PLUGIN_DIR)) from jukeboxlib.core import ( # noqa: E402 MEETING_STATE, RUNTIME_DIR, PROVIDER_MODELS, all_provider_statuses, cleanup_history, load_prompt_template, load_settings, reset_prompt_template, save_settings, save_prompt_template, stream_transform, ) MODES = PROVIDER_MODELS["codex"] def configure_settings(mode: str, provider: str, model: str) -> int: settings = load_settings() settings.update({"mode": mode, "provider": provider, "model": model}) try: save_settings(settings) except (TypeError, ValueError): return 2 return 0 def selected_settings() -> tuple[str, str, str]: """Return only the settings explicitly selected through Jukebox controls. Transcript text is an untrusted transformation payload. It must never select or persist a provider, model, or transformation mode. """ settings = load_settings() return str(settings["mode"]), str(settings["provider"]), str(settings["model"]) def compile_prompt(transcript: str, mode: str) -> str: template = load_prompt_template(mode) return template.replace("{{TRANSCRIPT}}", transcript) def meeting_active() -> bool: try: return MEETING_STATE.read_text(encoding="utf-8").splitlines()[0].strip() in {"recording", "paused"} except (OSError, IndexError): return False def main() -> int: if len(sys.argv) >= 2 and sys.argv[1] == "--providers": print(json.dumps(all_provider_statuses(), separators=(",", ":"))) return 0 if len(sys.argv) >= 2 and sys.argv[1] == "--settings": print(json.dumps(load_settings(), separators=(",", ":"))) return 0 if len(sys.argv) >= 3 and sys.argv[1] == "--set": settings = load_settings() key = sys.argv[2] if key not in {"delivery", "language", "historyDays", "openrouterModel"} or len(sys.argv) != 4: return 2 settings[key] = int(sys.argv[3]) if key == "historyDays" else sys.argv[3] try: save_settings(settings) except (TypeError, ValueError): return 2 return 0 if len(sys.argv) >= 4 and sys.argv[1] == "--prompt": action, mode = sys.argv[2], sys.argv[3] try: if action == "get": sys.stdout.write(load_prompt_template(mode)) elif action == "set": save_prompt_template(mode, sys.stdin.read()) elif action == "reset": reset_prompt_template(mode) else: return 2 except (OSError, ValueError): return 2 return 0 if len(sys.argv) == 3 and sys.argv[1] == "--prompt-import": staged = RUNTIME_DIR / "jukebox-prompt-editor.txt" try: save_prompt_template(sys.argv[2], staged.read_text(encoding="utf-8")) staged.unlink(missing_ok=True) except (OSError, ValueError): return 2 return 0 if len(sys.argv) >= 2 and sys.argv[1] == "--cleanup-history": print(cleanup_history()) return 0 if len(sys.argv) >= 2 and sys.argv[1] == "--configure": if len(sys.argv) == 4: return configure_settings(sys.argv[2].lower(), "codex", sys.argv[3].lower()) if len(sys.argv) == 5: return configure_settings(sys.argv[2].lower(), sys.argv[3].lower(), sys.argv[4].lower()) return 2 streaming = len(sys.argv) == 2 and sys.argv[1] == "--stream" if len(sys.argv) != 1 and not streaming: return 2 transcript = sys.stdin.read().strip() if not transcript: return 0 if meeting_active(): sys.stdout.write(transcript) return 0 cleanup_history() mode, provider, model = selected_settings() prompt = compile_prompt(transcript, mode) for attempt in range(3): try: def publish(event): if streaming: sys.stdout.write(json.dumps(event, separators=(",", ":")) + "\n") sys.stdout.flush() result = stream_transform(provider, model, prompt, publish) if not streaming: sys.stdout.write(result) return 0 except Exception: if attempt < 2: time.sleep(1) return 2 if __name__ == "__main__": raise SystemExit(main())