diff --git a/.env.example b/.env.example index 29f14914a..0a489f10e 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,7 @@ ANTHROPIC_API_KEY=your-anthropic-api-key # Rev.ai token for imported audio transcription (optional) # Sign up: https://www.rev.ai/ then get token at https://www.rev.ai/access_token REVAI_ACCESS_TOKEN=your-revai-token + +# Plaud access token for importing Plaud recordings (optional) +# Log into the Plaud web portal and extract token from browser console +PLAUD_ACCESS_TOKEN=your-plaud-token diff --git a/apps/settings/routes.py b/apps/settings/routes.py index 0f4bcc2c4..ac148bbb4 100644 --- a/apps/settings/routes.py +++ b/apps/settings/routes.py @@ -30,6 +30,7 @@ API_KEY_ENV_VARS = [ "ANTHROPIC_API_KEY", "OPENAI_API_KEY", "REVAI_ACCESS_TOKEN", + "PLAUD_ACCESS_TOKEN", ] @@ -66,7 +67,7 @@ def update_config() -> Any: - identity: User profile (name, preferred, bio, pronouns, aliases, etc.) - transcribe: Transcription settings (device, model, compute_type) - convey: Web app settings (password) - - env: API keys (GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, REVAI_ACCESS_TOKEN) + - env: API keys (GOOGLE_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, REVAI_ACCESS_TOKEN, PLAUD_ACCESS_TOKEN) Note: Model/provider configuration is done via the 'providers' section in journal.json. See docs/JOURNAL.md for the providers config format. diff --git a/apps/settings/workspace.html b/apps/settings/workspace.html index 42e892457..c2e5109cf 100644 --- a/apps/settings/workspace.html +++ b/apps/settings/workspace.html @@ -1761,6 +1761,16 @@ input:checked + .slider:before { Audio transcription for imported files. Get token +
+ +
+ + +
+ Import audio from Plaud recorder. Log into the web portal and extract token from browser console. +
@@ -2342,6 +2352,7 @@ function populateFields(config) { updateEnvStatus('field-env-openai', env.OPENAI_API_KEY, sysEnv.OPENAI_API_KEY); updateEnvStatus('field-env-anthropic', env.ANTHROPIC_API_KEY, sysEnv.ANTHROPIC_API_KEY); updateEnvStatus('field-env-revai', env.REVAI_ACCESS_TOKEN, sysEnv.REVAI_ACCESS_TOKEN); + updateEnvStatus('field-env-plaud', env.PLAUD_ACCESS_TOKEN, sysEnv.PLAUD_ACCESS_TOKEN); } function updateEnvStatus(fieldId, isJournalConfigured, isSystemConfigured) { diff --git a/docs/JOURNAL.md b/docs/JOURNAL.md index 578ef5b5b..7741268d8 100644 --- a/docs/JOURNAL.md +++ b/docs/JOURNAL.md @@ -159,7 +159,8 @@ The `env` block provides fallback values for environment variables. These are lo "GOOGLE_API_KEY": "your-google-api-key", "ANTHROPIC_API_KEY": "your-anthropic-api-key", "OPENAI_API_KEY": "your-openai-api-key", - "REVAI_ACCESS_TOKEN": "your-revai-token" + "REVAI_ACCESS_TOKEN": "your-revai-token", + "PLAUD_ACCESS_TOKEN": "your-plaud-token" } } ``` diff --git a/tests/test_importer_sync.py b/tests/test_importer_sync.py index ec46bb64c..09566b8c7 100644 --- a/tests/test_importer_sync.py +++ b/tests/test_importer_sync.py @@ -75,14 +75,24 @@ def test_plaud_protocol_conformance(): assert isinstance(PlaudBackend(), SyncableBackend) -def test_plaud_sync_not_implemented(tmp_path): - """PlaudBackend.sync() raises NotImplementedError.""" +def test_plaud_sync_not_implemented(tmp_path, monkeypatch): + """With token configured, PlaudBackend.sync() raises NotImplementedError.""" from think.importers.plaud import PlaudBackend + monkeypatch.setenv("PLAUD_ACCESS_TOKEN", "test-token") with pytest.raises(NotImplementedError): PlaudBackend().sync(tmp_path) +def test_plaud_sync_requires_token(tmp_path, monkeypatch): + """Without token configured, PlaudBackend.sync() raises ValueError.""" + from think.importers.plaud import PlaudBackend + + monkeypatch.delenv("PLAUD_ACCESS_TOKEN", raising=False) + with pytest.raises(ValueError, match="PLAUD_ACCESS_TOKEN"): + PlaudBackend().sync(tmp_path) + + def test_backends_cli_flag(capsys, monkeypatch): """sol import --backends lists plaud.""" import sys diff --git a/think/importers/plaud.py b/think/importers/plaud.py index 268796b2e..97a100eab 100644 --- a/think/importers/plaud.py +++ b/think/importers/plaud.py @@ -282,6 +282,11 @@ class PlaudBackend: Not yet implemented — Phase 2 will wire up actual sync. """ + token = os.getenv("PLAUD_ACCESS_TOKEN") + if not token: + raise ValueError( + "PLAUD_ACCESS_TOKEN not configured — set in Settings > API Keys" + ) raise NotImplementedError("Plaud sync execution is not yet implemented")