Files
local-deep-research/examples/api_usage/README.md
LearningCircuit 7d8fdee7dd fix: unify SettingsManagers, fix env var bugs (#2070)
* fix: unify SettingsManagers, fix env var bugs, delete duplicate

Two parallel SettingsManager implementations existed (settings/manager.py
and web/services/settings_manager.py) that diverged accidentally, each
with different bugs. This unifies them into a single implementation.

Bug fixes in settings/manager.py:
- get_setting() now checks env vars when setting is not in DB (was
  jumping straight to return default, ignoring env override)
- get_all_settings() now type-converts env overrides through
  get_typed_setting_value() (was storing raw strings like "true"
  instead of True)
- create_or_update_setting() now correctly checks db_setting.editable
  (was checking input dict's .editable which caused AttributeError)
- Added missing ui_element types: textarea, multiselect

Features added to settings/manager.py:
- get_bool_setting() method (required by rag_routes.py)
- default_settings now loads all 18 JSON files via rglob (was only
  loading 1 file with 370 settings, now loads 526)

All production and test imports updated from web.services.settings_manager
to settings.manager. Duplicate web/services/settings_manager.py deleted.

314 tests pass across 7 test files. 9 new tests cover bug fixes.

* test: add 29 tests for unified SettingsManager coverage gaps (#2071)

Cover create_or_update_setting (8 tests), default_settings property (4),
_ensure_settings_initialized (2), new UI element types textarea/multiselect/
range (4), _emit_settings_changed error resilience (3), plus edge cases
for get_setting check_env=False, get_all_settings with locked settings,
get_bool_setting with integers, parse_boolean edge cases, and env override
type conversion for text settings.

* fix: add missing abstract methods, env var defaults override, and type bug (#2074)

- Add get_bool_setting() and get_settings_snapshot() abstract methods to
  ISettingsManager base class so the interface contract is complete
- Fix create_or_update_setting: use setting_obj.type directly instead of
  SettingType[setting_obj.type.upper()] which fails when type is already
  a SettingType enum from the Pydantic model
- Add env var override in get_all_settings() defaults loop so settings
  not yet in DB can still be overridden via LDR_* environment variables
- Fix test_get_all_settings_db_error to expect defaults on DB failure
  (graceful degradation after unification)

* refactor: deduplicate provider availability checks and settings wrapper (#2054) (#2068)

- Delegate 5 provider availability functions in llm_config.py to their
  existing provider class is_available() methods (OpenAI, Anthropic,
  CustomOpenAIEndpoint, Ollama, LMStudio)
- Extract _get_or_create_status() helper in queue_service.py to
  eliminate duplicated QueueStatus lookup-or-create pattern
- Centralize get_llm_setting_from_snapshot() in thread_settings.py,
  replacing 6 identical copy-pasted wrappers across provider files
- Update test mock targets to reflect new delegation pattern

* fix: add missing abstract method implementations to InMemorySettingsManager

InMemorySettingsManager was missing get_bool_setting() and
get_settings_snapshot() implementations required by the ISettingsManager
ABC, causing TypeError on instantiation and cascading failures in
LLM unit tests, REST API tests, and Puppeteer auth tests.

* fix: convert web SettingType to database SettingType in create_or_update_setting

The PR changed `type=SettingType[setting_obj.type.upper()]` to
`type=setting_obj.type`, but setting_obj.type is a web model SettingType
(str, Enum) while Setting.type expects the database SettingType (enum.Enum).
This causes a 500 error when creating new settings via PUT endpoint.

Use `.name` for cleaner enum-to-enum conversion instead of `.upper()`.

* fix: add multiselect type conversion and warn on untyped env overrides (#2080)

Address review feedback from @djpetti on PR #2070:

1. Replace multiselect `lambda x: x` with `_parse_multiselect()` that
   properly handles env var strings — parses JSON arrays (e.g.
   '["markdown","latex"]') and comma-separated values (e.g.
   'markdown,latex') while passing through lists from SQLAlchemy
   unchanged.

2. Log a warning when get_setting() encounters an env var override for
   a setting not in defaults, returning the raw string without type
   conversion. This surfaces settings that should be added to a
   defaults JSON file to get proper type information.

Tests: 14 new tests (111 total in test_settings_manager.py, 0 failures)

* test: add tests for consolidated UI element-to-type mapping

Verifies single canonical _UI_ELEMENT_TO_SETTING_TYPE is reused by
both InMemorySettingsManager and SettingsManager.
2026-02-11 06:59:07 +01:00

6.1 KiB

Local Deep Research API Examples

This directory contains examples for using LDR through different interfaces.

Important: Authentication Required (v2.0+)

Since LDR v2.0, all API access requires authentication due to per-user encrypted databases. You must:

  1. Create a user account through the web interface
  2. Authenticate before making API calls
  3. Pass settings_snapshot for programmatic access

Directory Structure

  • programmatic/ - Direct Python API usage (import from local_deep_research.api)

    • programmatic_access.ipynb - Jupyter notebook with comprehensive examples
    • retriever_usage_example.py - Using LangChain retrievers with LDR
  • http/ - HTTP REST API usage (requires running server)

    • simple_working_example.py - BEST WORKING EXAMPLE - Clean, tested, and ready to use
    • simple_http_example.py - Quick start example (needs updating for auth)
    • http_api_examples.py - Comprehensive examples including batch processing

Quick Start

Programmatic API (Python Package)

from local_deep_research.api import quick_summary
from local_deep_research.settings import SettingsManager
from local_deep_research.database.session_context import get_user_db_session

# Authenticate and get settings
with get_user_db_session(username="your_username", password="your_password") as session:
    settings_manager = SettingsManager(session)
    settings_snapshot = settings_manager.get_all_settings()

    # Use the API
    result = quick_summary(
        "What is quantum computing?",
        settings_snapshot=settings_snapshot
    )
    print(result["summary"])

HTTP API (REST)

🎯 Quick Start - Works Completely Out of the Box!

Our tested working example requires zero manual setup:

# 1. Start the server
python -m local_deep_research.web.app

# 2. Run the working example (creates user automatically!)
python examples/api_usage/http/simple_working_example.py

# 3. Done! ✅ No other steps required

The example will:

  • Create a unique test user automatically
  • Test authentication with proper CSRF handling
  • Execute a research query using the correct API endpoint
  • Provide credentials for manual testing (if desired)
  • Show results with direct links to view them

📋 Manual API Usage:

If you want to integrate the API into your own code:

import requests
from bs4 import BeautifulSoup

# Create session for cookie persistence
session = requests.Session()

# Login - get CSRF token first
login_page = session.get("http://localhost:5000/auth/login")
soup = BeautifulSoup(login_page.text, 'html.parser')
csrf_input = soup.find('input', {'name': 'csrf_token'})
login_csrf = csrf_input.get('value')

# Login with form data
session.post(
    "http://localhost:5000/auth/login",
    data={
        "username": "your_username",
        "password": "your_password",
        "csrf_token": login_csrf
    }
)

# Get CSRF token
csrf_token = session.get("http://localhost:5000/auth/csrf-token").json()["csrf_token"]

# Make API request
response = session.post(
    "http://localhost:5000/api/start_research",
    json={"query": "What is quantum computing?"},
    headers={"X-CSRF-Token": csrf_token, "Content-Type": "application/json"}
)
print(response.json())

⚠️ Important Notes:

  • Use the correct endpoint: /api/start_research (not /research/api/start)
  • Login with form data (not JSON)
  • Handle CSRF tokens properly
  • User must be created through web interface first

Which API Should I Use?

  • Programmatic API: Use when integrating LDR into your Python application

    • Direct access, no HTTP overhead
    • Full access to all features and parameters
    • Can pass Python objects (like LangChain retrievers)
    • Requires LDR to be installed in your environment
    • Requires database session and settings snapshot
  • HTTP API: Use when accessing LDR from other languages or remote systems

    • Language agnostic - works with any HTTP client
    • Can run LDR on a separate server
    • Easy to scale and deploy
    • Limited to JSON-serializable parameters
    • Requires running the web server
    • Requires authentication and CSRF tokens

API Changes in v2.0

Breaking Changes

  1. Authentication Required: All endpoints now require login
  2. Settings Snapshot: Programmatic API needs settings_snapshot parameter
  3. New Endpoints: API routes moved (e.g., /api/v1/quick_summary/api/start_research)
  4. CSRF Protection: POST/PUT/DELETE requests need CSRF token

Migration Guide

Old (v1.x):

# Programmatic
from local_deep_research.api import quick_summary
result = quick_summary("query")

# HTTP
curl -X POST http://localhost:5000/api/v1/quick_summary \
  -d '{"query": "test"}'

New (v2.0+):

# Programmatic - with authentication and settings
with get_user_db_session(username, password) as session:
    settings_manager = SettingsManager(session)
    settings_snapshot = settings_manager.get_all_settings()
    result = quick_summary("query", settings_snapshot=settings_snapshot)

# HTTP - with authentication and CSRF
# See examples above

Running the Examples

Prerequisites

  1. Install LDR: pip install local-deep-research
  2. Create a user account:
  3. Configure your LLM provider in settings

Programmatic Examples

# Update credentials in the example files first!
python examples/api_usage/programmatic/retriever_usage_example.py

# Or use the Jupyter notebook
jupyter notebook examples/api_usage/programmatic/programmatic_access.ipynb

HTTP Examples

# First, start the LDR server
python -m local_deep_research.web.app

# In another terminal, run the examples
# Note: These need to be updated for v2.0 authentication!
python examples/api_usage/http/simple_http_example.py
python examples/api_usage/http/http_api_examples.py

Need Help?