Metadata-Version: 2.4
Name: mxview
Version: 1.2.0
Summary: A small, dependency-free personal media server for trusted networks
Author: Beast
License-Expression: MIT
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: pdf
Requires-Dist: PyMuPDF>=1.24; extra == "pdf"
Provides-Extra: speech
Requires-Dist: faster-whisper>=1.0; extra == "speech"
Provides-Extra: vision
Requires-Dist: Pillow>=10; extra == "vision"
Requires-Dist: transformers>=4.44; extra == "vision"
Requires-Dist: torch>=2.2; extra == "vision"
Provides-Extra: e2e
Requires-Dist: playwright>=1.50; extra == "e2e"
Provides-Extra: analysis
Requires-Dist: PyMuPDF>=1.24; extra == "analysis"
Requires-Dist: faster-whisper>=1.0; extra == "analysis"
Requires-Dist: Pillow>=10; extra == "analysis"
Requires-Dist: transformers>=4.44; extra == "analysis"
Requires-Dist: torch>=2.2; extra == "analysis"
Dynamic: license-file

# MxView

MxView is a personal AI media assistant for a trusted home LAN or private
Tailscale network. It combines a conversation-first assistant with durable
evidence and action workspaces, a local SQLite media index, evidence-backed
content search, optional answers through an OpenAI-compatible provider, and a
read-only OpenClaw skill. Browsing and file viewing remain supported, but the
conversation and evidence loop is the core workflow.

The base runtime uses only the Python standard library. Optional packages and
FFmpeg enable local content analysis and generated video/image thumbnails; they
are installed through explicit optional groups and never change the core
contract.

MxView is not an internet-grade service. It relies on network isolation and
optional Bearer authentication; it does not provide TLS termination. Read
`SECURITY.md` before enabling network access or writes.

## Run

```powershell
python mxview.py C:\Media
```

The default URL is `http://127.0.0.1:8080`. Multiple roots may be named:

```powershell
python mxview.py --root movies=D:\Movies --root books=D:\Books
```

To listen on LAN and Tailscale interfaces intentionally:

```powershell
python mxview.py --host 0.0.0.0 --root media=D:\Media
```

These are private-network HTTP URLs, not secure public deployment URLs. Ensure
your firewall and Tailscale ACLs permit only people you trust.

When binding to a non-loopback host, every request must present a Bearer token
of at least 32 characters:

```powershell
$env:MXVIEW_AUTH_TOKEN = "a-long-random-secret-token-at-least-32-characters"
python mxview.py --host 0.0.0.0 --root media=D:\Media
```

Or pass it directly with `--auth-token`. On loopback, a configured token is
still required for mutating requests, which keeps the local UI compatible.
Token comparisons use constant-time hashing and tokens are never written to the
index, the state database, or logs.

Requests must use a literal IP address, `localhost`, or the hostname explicitly
passed to `--host`. Other Host values are rejected to reduce DNS rebinding risk.

Startup is read-only by default. Conversations, evidence workspaces, and action
previews work in this mode, but confirmation cannot change files. Enable the
confirmed, journaled mutation service explicitly:

```powershell
python mxview.py --enable-mutations --root media=D:\Media
```

Anyone able to access that server can then confirm operations against configured
roots, so network isolation remains essential. Mutation mode is feature-frozen:
it is opt-in, receives security fixes only, and is not a vehicle for new file
operation capabilities. `--allow-write` retains the deprecated legacy
direct-write API for one compatibility release and is scheduled for removal in
2.0; it is mutually exclusive with `--enable-mutations` and lacks v2 plans,
journaling, and recovery. Root directories themselves cannot be mutated.

## Conversations, workspaces, and tasks

The home route creates or resumes durable conversations. A conversation may be
renamed, archived, unarchived, exported, or deleted. Archiving makes it
read-only, cancels its active read-only turn and unconfirmed plans, and hides it
from the default list. An already executing file operation continues as a
detached task. Deletion waits for detached execution to finish before removing
non-audit conversation data; it never deletes media.

Evidence Workspace B contains ordered, version-bound local evidence with safe
links to media timestamps and PDF pages. Action Workspace C contains an
immutable preview, capability and conflict information, storage estimates, and
L2/L3 confirmation controls. The Tasks route unifies Agent, indexing, analysis,
provider, and mutation progress without merging their internal workers.

Every action plan expires after 30 minutes. The supported conflict policies are
`skip` (default), deterministic previewed `rename`, and L3 `replace`; a changed
identity, destination, capability, policy, or risk makes the plan stale.
Eligible completed operations expose an undo action for 30 days. Undo creates a
new plan and never silently reverses a task.

`GET /api/v2/capabilities` reports local search, analysis, provider, and mutation
availability. Unsupported roots remain usable for browsing and planning. On
Windows, the first mutation release supports regular local files on NTFS/ReFS
when the handle-relative startup probe succeeds. SMB/UNC roots, directories
across volumes, reparses/junctions, EFS, named streams, hard links, and volumes
without the required native primitives fail closed.

Durable application state defaults to
`%LOCALAPPDATA%\MxView\State\mxview-state.sqlite3` on Windows and
`$XDG_STATE_HOME/mxview/mxview-state.sqlite3` (or
`~/.local/state/mxview/mxview-state.sqlite3`) on POSIX. It is separate from the
rebuildable media index and cache. Mutation mode provisions identity-pinned,
owner-private managed trash on each supported volume: beside the state database
when it is on that volume, otherwise beside the configured media root. Trash
uses an opaque `.mxview-trash-*` directory, is never served, and is never
automatically purged.

The v2 API caps JSON requests at 64 KiB, messages at 8,000 Unicode code points,
evidence at 50 records per turn and 4 KiB per record, action plans at 500 items,
task milestones at 200, plan pages at 100 items, and responses at 1 MiB. SSE is
limited to 8 concurrent streams, sends 15-second heartbeats, rotates connections
after five minutes, and uses snapshot refetching as the source of truth.

## Content search

MxView scans configured roots in a background thread at startup and stores file
metadata in a local SQLite FTS5 index. Content analysis runs in one background
worker, never in an HTTP request thread. The default `balanced` mode processes
one heavy task at a time and pauses new heavy work while media is playing.

Install only the analyzers you need:

```powershell
python -m pip install ".[pdf]"       # native PDF text extraction
python -m pip install ".[speech]"    # local speech transcription
python -m pip install ".[vision]"    # local image and keyframe descriptions
python -m pip install ".[analysis]"  # all optional analyzers
```

Speech and video keyframe extraction also require `ffmpeg` and `ffprobe`.
Configure their executable paths with `--ffmpeg` and `--ffprobe`. Local model
selection is explicit:

```powershell
$env:MXVIEW_WHISPER_MODEL = "small"
$env:MXVIEW_VISION_MODEL = "C:\Models\local-vision-model"
python mxview.py --root media=D:\Media
```

Equivalent `--whisper-model` and `--vision-model` options override those
environment variables. Vision analysis is disabled when no vision model is
configured. `--no-content-analysis` disables the scheduler while preserving
filename search. Optional libraries are imported lazily; the base installation
has no runtime dependencies.

Search recognizes media-kind filters, configured root names, explicit years,
`this year`, `last year`, and unambiguous month/year combinations. Applied
filters are shown in the result view. Text that cannot be parsed reliably stays
part of the search terms.

The first content query fixes the visible result order. Completed analysis may
upgrade a card in place with a transcript, PDF page, image description, video
timestamp, or file-specific failure, but cards do not silently move. Newly
discovered results appear behind an explicit `N updates found` action. Use the
analysis status control to pause/resume scheduling and retry a failed file from
its result card.

## Answers and privacy

An optional OpenAI-compatible provider expands queries, reranks candidates, and
generates evidence-bound answers. Original media bytes are never sent to the
provider. Depending on the operation, it may receive the query, applied filters,
relative candidate paths and kinds, and a bounded set of locally extracted text
evidence. Do not configure a cloud provider if those details must remain local.
Configure a provider through environment variables before starting MxView:

```powershell
$env:MXVIEW_AI_BASE_URL = "https://api.deepseek.com"
$env:MXVIEW_AI_MODEL = "deepseek-chat"
$env:MXVIEW_AI_API_KEY = Read-Host "Provider API key"
python mxview.py C:\Media
```

OpenAI or another compatible provider uses its corresponding `/v1` base URL.
For local Ollama:

```powershell
$env:MXVIEW_AI_BASE_URL = "http://127.0.0.1:11434/v1"
$env:MXVIEW_AI_MODEL = "qwen3:8b"
$env:MXVIEW_AI_API_KEY = ""
python mxview.py C:\Media
```

`MXVIEW_AI_TIMEOUT` optionally changes the provider timeout in seconds. API keys
are read only by the server process and are not returned to browsers, written to
the index, or included in logs.

Answers are generated only when requested. Each answer is immutable and tied to
the evidence version used to create it; new evidence leaves the old answer in
place until `Update answer` is selected. Provider citations are accepted only
when the server can resolve them to evidence from the current query. Valid
citations open the source file, PDF page, or media timestamp. An answer with no
valid citation is marked as insufficient evidence.

The SQLite index stores file metadata, extracted evidence, analysis jobs, query
sessions, and answer versions in the user cache directory. Temporary normalized
images, PCM chunks, and keyframes use random private directories under
`<cache>/analysis-jobs` and are cleaned after use, at startup, and periodically.
Analysis pauses temporary extraction with `disk_space_low` when free space falls
below `--min-free-bytes`; filename search remains available.

The separate application-state database stores visible messages, validated
evidence references, workspace snapshots, plans, tasks, and minimum recovery
metadata. It does not store API keys, raw media, temporary analyzer files, or
hidden model reasoning. Conversation exports warn that messages and relative
media names may still be sensitive.

## OpenClaw

The read-only skill is in `openclaw/mxview-media/`. Install it into an OpenClaw
workspace by linking or copying that directory to
`~/.openclaw/workspace/skills/mxview-media`, then run:

```powershell
openclaw skills check
```

The skill supports legacy filename search, stable content queries and polling,
explicit answer generation, file-level analysis retry, explicit
`request-analysis` (queue analysis for a query's candidate media, with optional
`--wait`), metadata inspection,
index status/refresh, and safe browser URL generation. It intentionally has no
rename, move, or delete command and does not require SSE. Set `MXVIEW_URL` for
OpenClaw if MxView is not available at `http://127.0.0.1:8080`.

## Legacy browser UI

The original HTML interface under `/view`, `/library`, and their supporting
`/api/media` and `/api/fs` endpoints is **legacy**. It receives security fixes
only; a browser migration is scheduled for after 2.0. New conversation,
evidence, and task workflows live on the v2 API and the chat shell. Legacy
write controls are hidden by default and the legacy direct-write API is
deprecated.

## Options

```text
PATH                  one or more media roots; labels are generated automatically
--root KEY=PATH       named media root; repeatable
--host HOST           bind address (default: 127.0.0.1)
--port PORT           TCP port (default: 8080)
--auth-token TOKEN    Bearer token for non-loopback access and mutations
--allow-write         deprecated legacy direct-write mode (removed in 2.0)
--enable-mutations    enable confirmed journaled v2 mutation execution
--cache-dir PATH      thumbnail cache directory
--ffmpeg PATH         ffmpeg executable (default: ffmpeg)
--ffprobe PATH        ffprobe executable (default: ffprobe)
--no-index            disable the local search index
--index-db PATH       SQLite media index path
--state-db PATH       durable conversation/plan/task/journal database
--no-auto-index       do not scan roots automatically at startup
--no-content-analysis disable local content analysis
--analysis-mode MODE  analysis profile (balanced)
--whisper-model ID    local speech model identifier (default: small)
--vision-model ID     local vision model identifier (disabled by default)
--min-free-bytes N    free-space floor for temporary extraction (default: 512 MiB)
--promotion-limit N   maximum query-driven promotions (default: 10)
--version             show version
```

Positional roots and `--root` may not be mixed. Root keys must contain letters,
digits, dots, underscores, or hyphens. Paths are canonicalized and validated at
startup.

The default thumbnail cache and media index are stored in the current user's
platform cache directory, not in a shared temporary directory.

## Development

```powershell
python -m unittest discover -s tests -v
python -m py_compile mxview.py mxview_ai.py mxview_content.py mxview_context.py mxview_agent.py mxview_api_v2.py mxview_fileops.py mxview_win32.py
```

`mxview.py` owns HTTP routing and service lifecycle; `mxview_ai.py` and
`mxview_content.py` own search, providers, analyzers, and scheduling;
`mxview_context.py`, `mxview_agent.py`, and `mxview_api_v2.py` own durable
conversation orchestration; `mxview_fileops.py` and `mxview_win32.py` own
planning and fail-closed native execution. Vendored PDF.js assets are served
only from `vendor/pdfjs/`.

The bundled PDF.js version and file hashes are recorded in
`THIRD_PARTY_LICENSES.md`. MxView disables PDF.js evaluation as the documented
workaround for CVE-2024-4367.

## License

MxView is MIT licensed. Vendored PDF.js files retain the Apache License 2.0;
see `THIRD_PARTY_LICENSES.md`.
