chore: archive observability-service-registry, track pi-map artifacts
- Archive the completed observability-service-registry SDD change into openspec/changes/archive/ (delivered across 5 slices; only jellyfin-service-registry remains active). - Stop ignoring .pi-map.md / .pi-map.index.md so the navigation maps are versioned alongside the code, and add the regenerated map pairs repo-wide.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# archive (index)
|
||||
dir: archive
|
||||
|
||||
## role
|
||||
Archive of an earlier project structure for a Streamlit-based Jellyfin media library browser with SSH remote file inspection capabilities.
|
||||
## parent
|
||||
index: ./.pi-map.index.md
|
||||
map: ./.pi-map.md
|
||||
## children
|
||||
- archive/src
|
||||
index: archive/src/.pi-map.index.md
|
||||
map: archive/src/.pi-map.md
|
||||
- archive/tests
|
||||
index: archive/tests/.pi-map.index.md
|
||||
map: archive/tests/.pi-map.md
|
||||
## files
|
||||
- app.py
|
||||
- pyproject.toml
|
||||
- requirements.txt
|
||||
## links
|
||||
index: archive/.pi-map.index.md
|
||||
map: archive/.pi-map.md
|
||||
## workflows
|
||||
- change archive behavior
|
||||
read: app.py, pyproject.toml, requirements.txt
|
||||
- change archive config
|
||||
read: pyproject.toml
|
||||
- explore archive subdirectories
|
||||
index: archive/src/.pi-map.index.md, archive/tests/.pi-map.index.md
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,26 @@
|
||||
# archive
|
||||
dir: archive
|
||||
|
||||
index: archive/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Archive of an earlier project structure for a Streamlit-based Jellyfin media library browser with SSH remote file inspection capabilities.
|
||||
## files
|
||||
- app.py | Provides a minimal Streamlit entrypoint that adds the src directory to Python's path and delegates to the actual application in media_library_viewer.app. | dep: sys, pathlib, media_library_viewer.app
|
||||
- pyproject.toml | Defines Python package metadata, dependencies, and tool configurations for a Streamlit-based Jellyfin media library browser with SSH remote file inspection. | dep: hatchling, streamlit, streamlit-aggrid, requests, paramiko, python-dotenv, pandas, ruff, pytest
|
||||
- requirements.txt | Installs the current package in editable/development mode using pip | dep: pip, setuptools
|
||||
## arch
|
||||
Thin entrypoint pattern using a bootstrap app.py that manipulates sys.path to delegate execution to a nested media_library_viewer package, managed via standard Python packaging (pyproject.toml).
|
||||
## tags
|
||||
streamlit, app, python, media, library, package, pyproject, pip
|
||||
## symbols
|
||||
-
|
||||
## workflows
|
||||
- change archive behavior
|
||||
read: app.py, pyproject.toml, requirements.txt
|
||||
- change archive config
|
||||
read: pyproject.toml
|
||||
- explore archive subdirectories
|
||||
index: archive/src/.pi-map.index.md, archive/tests/.pi-map.index.md
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,20 @@
|
||||
# archive/src (index)
|
||||
dir: archive/src
|
||||
|
||||
## role
|
||||
No files provided — directory appears to be empty or contents were not included, so the package's role cannot be determined.
|
||||
## parent
|
||||
index: archive/.pi-map.index.md
|
||||
map: archive/.pi-map.md
|
||||
## children
|
||||
- archive/src/media_library_viewer
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## files
|
||||
## links
|
||||
index: archive/src/.pi-map.index.md
|
||||
map: archive/src/.pi-map.md
|
||||
## workflows
|
||||
-
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,18 @@
|
||||
# archive/src
|
||||
dir: archive/src
|
||||
|
||||
index: archive/src/.pi-map.index.md
|
||||
|
||||
## role
|
||||
No files provided — directory appears to be empty or contents were not included, so the package's role cannot be determined.
|
||||
## files
|
||||
## arch
|
||||
Cannot be assessed due to missing file contents; please provide the file listing for analysis.
|
||||
## tags
|
||||
-
|
||||
## symbols
|
||||
-
|
||||
## workflows
|
||||
-
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,39 @@
|
||||
# archive/src/media_library_viewer (index)
|
||||
dir: archive/src/media_library_viewer
|
||||
|
||||
## role
|
||||
Streamlit-based media library viewer that provides a unified dashboard for browsing and monitoring Jellyfin media alongside remote SSH file systems.
|
||||
## parent
|
||||
index: archive/src/.pi-map.index.md
|
||||
map: archive/src/.pi-map.md
|
||||
## children
|
||||
- archive/src/media_library_viewer/clients
|
||||
index: archive/src/media_library_viewer/clients/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/clients/.pi-map.md
|
||||
- archive/src/media_library_viewer/domain
|
||||
index: archive/src/media_library_viewer/domain/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/domain/.pi-map.md
|
||||
- archive/src/media_library_viewer/services
|
||||
index: archive/src/media_library_viewer/services/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/services/.pi-map.md
|
||||
- archive/src/media_library_viewer/ui
|
||||
index: archive/src/media_library_viewer/ui/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/ui/.pi-map.md
|
||||
## files
|
||||
- __init__.py
|
||||
- app.py
|
||||
- config.py
|
||||
- jobs.py
|
||||
- utils.py
|
||||
## links
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## workflows
|
||||
- change media_library_viewer behavior
|
||||
read: __init__.py, app.py, config.py
|
||||
- change media_library_viewer config
|
||||
read: config.py
|
||||
- explore media_library_viewer subdirectories
|
||||
index: archive/src/media_library_viewer/clients/.pi-map.index.md, archive/src/media_library_viewer/domain/.pi-map.index.md, archive/src/media_library_viewer/services/.pi-map.index.md
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,35 @@
|
||||
# archive/src/media_library_viewer
|
||||
dir: archive/src/media_library_viewer
|
||||
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Streamlit-based media library viewer that provides a unified dashboard for browsing and monitoring Jellyfin media alongside remote SSH file systems.
|
||||
## files
|
||||
- __init__.py | Package initialization file that defines the Media Library Viewer package metadata and exports the version string.
|
||||
- app.py | Streamlit UI entrypoint for a Media Library Viewer that connects to Jellyfin and SSH backends, providing dashboard, monitoring, media browsing, and file browser tabs with cached data and path resolution between systems. | exp: func:get_jellyfin_client(base_url: str, api_key: str) → JellyfinClient, call:JellyfinClient, func:cached_users(base_url: str, api_key: str), call:get_jellyfin_client(base_url, api_key).users, func:get_ssh_client(host: str, username: str, port: int, key_filename: str, password: str) → RemoteSSHClient, call:RemoteSSHClient, call:client.connect, func:cached_libraries(base_url: str, api_key: str, user_id: str), call:get_jellyfin_client(base_url, api_key).libraries, func:cached_media_counts(base_url: str, api_key: str, user_id: str), call:get_jellyfin_client(base_url, api_key).media_counts, func:cached_library_counts(base_url: str, api_key: str, user_id: str), call:get_jellyfin_client, call:client.libraries, call:client.library_item_counts, func:cached_active_sessions(base_url: str, api_key: str), call:get_jellyfin_client(base_url, api_key).active_sessions, func:cached_dir_listing(host: str, username: str, port: int, key_filename: str, password: str, path: str), call:get_ssh_client, call:ssh.list_dir, call:json.loads, raise:RuntimeError, func:cached_ffprobe_preview(host: str, username: str, port: int, key_filename: str, password: str, path: str), call:get_ssh_client, call:ssh.ffprobe_json, func:apply_remote_path_prefix(path: str, prefix: str) → str, call:(prefix or "").strip, call:normalized_prefix.rstrip, call:path.startswith, call:posixpath.normpath, call:posixpath.join, func:map_path_to_media_root(path: str, media_root: str) → str, call:(media_root or "").strip, call:posixpath.normpath, call:str(path).split, call:"/".join, call:path_absolute.startswith, call:posixpath.basename, call:raw_parts.index, call:posixpath.join, func:resolve_remote_media_path(path: str, media_root: str, fallback_prefix: str) → str, call:map_path_to_media_root, call:apply_remote_path_prefix, func:credentials_panel(), call:load_config, call:st.header, call:st.expander, call:st.text_input, call:st.number_input, call:int, func:main(), call:st.set_page_config, call:st.title, call:st.caption, call:credentials_panel, call:st.info, call:get_jellyfin_client, call:cached_users, call:st.error, call:user.get, call:st.selectbox, call:list, call:user_options.keys, call:st.tabs, call:render_now_playing, call:st.divider, call:render_resource_dashboard, call:render_media_overview, call:cached_libraries, call:set_file_browser_path, call:resolve_remote_media_path, call:render_media_tab, call:render_file_browser, call:get_ssh_client, call:render_ssh_tools, func:set_prefixed_file_browser_path(path: str, selected_path, reset_filters) → None, call:set_file_browser_path, call:resolve_remote_media_path | dep: json, posixpath, typing, media_library_viewer.clients.jellyfin, media_library_viewer.clients.ssh, media_library_viewer.config, media_library_viewer.ui.dashboard, media_library_viewer.ui.file_browser, media_library_viewer.ui.media, media_library_viewer.ui.preview, streamlit
|
||||
- config.py | Loads application configuration from environment variables and .env files using immutable dataclasses for Jellyfin and SSH settings. | exp: class:JellyfinConfig, class:SSHConfig, class:AppConfig, func:load_config() → AppConfig, call:AppConfig | dep: os, dataclasses, pathlib, dotenv
|
||||
- jobs.py | Defines safe, template-based remote SSH jobs with shell-quoted parameter rendering. | exp: class:JobTemplate, method:render(self, values: Mapping[str, str]) → str, call:shlex.quote, call:values.items, call:self.command_template.format, func:run_job(ssh: RemoteSSHClient, job_key: str, path: str, timeout) → CommandResult, call:template.render, call:ssh.run | dep: shlex, dataclasses, typing, media_library_viewer.clients.ssh, typing.Mapping
|
||||
- utils.py | Provides UI-independent formatting helpers and ffprobe output summarizers for video/audio/subtitle stream metadata. | exp: func:ticks_to_minutes(ticks: int | None) → int | None, call:round, func:human_size(num: int | float | None) → str, call:float, call:int, func:timestamp_to_local(ts: float | None) → str, call:datetime.fromtimestamp(ts).strftime, func:is_known_video_file(path: str | None) → bool, call:PurePosixPath(path).suffix.lower, func:format_duration(seconds: str | int | float | None) → str, call:float, call:str, call:int, func:format_bitrate(bit_rate: str | int | float | None) → str, call:float, call:str, func:_tags(stream: dict[str, Any]) → dict[str, Any], call:stream.get, func:_disposition(stream: dict[str, Any], key: str) → str, call:(stream.get("disposition") or {}).get, call:stream.get, func:_side_data_types(stream: dict[str, Any]) → str, call:stream.get, call:item.get, call:values.append, call:", ".join, func:ffprobe_format_summary(ffprobe: dict[str, Any]) → dict[str, str], call:ffprobe.get, call:fmt.get, call:format_duration, call:human_size, call:float, call:format_bitrate, call:str, func:summarize_video_streams(ffprobe: dict[str, Any]) → list[dict[str, Any]], call:ffprobe.get, call:stream.get, call:_tags, call:rows.append, call:format_bitrate, call:_side_data_types, call:tags.get, call:_disposition, func:summarize_audio_streams(ffprobe: dict[str, Any]) → list[dict[str, Any]], call:ffprobe.get, call:stream.get, call:_tags, call:rows.append, call:format_bitrate, call:tags.get, call:_disposition, func:summarize_subtitle_streams(ffprobe: dict[str, Any]) → list[dict[str, Any]], call:ffprobe.get, call:stream.get, call:_tags, call:rows.append, call:tags.get, call:_disposition, func:summarize_streams(ffprobe: dict[str, Any]) → list[dict[str, Any]], call:ffprobe.get, call:rows.append, call:format_bitrate, call:stream.get("tags", {}).get | dep: datetime, pathlib, typing
|
||||
## arch
|
||||
Layered Streamlit application using immutable dataclass configuration, template-based remote job execution, cached data access, and separated utility functions following a tab-based modular UI pattern.
|
||||
## tags
|
||||
client, path, media, call:, jellyfin, call:get, ssh, cached
|
||||
## symbols
|
||||
- JellyfinConfig
|
||||
- SSHConfig
|
||||
- AppConfig
|
||||
- JobTemplate
|
||||
- get_jellyfin_client
|
||||
- cached_users
|
||||
- get_ssh_client
|
||||
- cached_libraries
|
||||
## workflows
|
||||
- change media_library_viewer behavior
|
||||
read: __init__.py, app.py, config.py
|
||||
- change media_library_viewer config
|
||||
read: config.py
|
||||
- explore media_library_viewer subdirectories
|
||||
index: archive/src/media_library_viewer/clients/.pi-map.index.md, archive/src/media_library_viewer/domain/.pi-map.index.md, archive/src/media_library_viewer/services/.pi-map.index.md
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,23 @@
|
||||
# archive/src/media_library_viewer/clients (index)
|
||||
dir: archive/src/media_library_viewer/clients
|
||||
|
||||
## role
|
||||
External service and system integration layer providing HTTP API clients for Jellyfin/Emby media servers and SSH-based remote system metrics collection.
|
||||
## parent
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## children
|
||||
-
|
||||
## files
|
||||
- __init__.py
|
||||
- jellyfin.py
|
||||
- resources.py
|
||||
- ssh.py
|
||||
## links
|
||||
index: archive/src/media_library_viewer/clients/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/clients/.pi-map.md
|
||||
## workflows
|
||||
- change clients behavior
|
||||
read: __init__.py, jellyfin.py, resources.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,30 @@
|
||||
# archive/src/media_library_viewer/clients
|
||||
dir: archive/src/media_library_viewer/clients
|
||||
|
||||
index: archive/src/media_library_viewer/clients/.pi-map.index.md
|
||||
|
||||
## role
|
||||
External service and system integration layer providing HTTP API clients for Jellyfin/Emby media servers and SSH-based remote system metrics collection.
|
||||
## files
|
||||
- __init__.py | Package initialization file that defines external service clients module boundaries and constraints
|
||||
- jellyfin.py | HTTP API client for Jellyfin/Emby media servers providing user, library, item, and session management with plain Python return types for frontend agnosticism. | exp: class:JellyfinClient, method:__init__(self, base_url: str, api_key: str, timeout), call:base_url.rstrip, call:self.base_url.endswith, call:requests.Session, call:self.session.headers.update, raise:ValueError, method:get(self, path: str, **params: Any) → dict[str, Any], call:params.items, call:self.session.get, call:response.raise_for_status, call:response.json, raise:requests.HTTPError, method:users(self) → list[dict[str, Any]], call:self.get, method:libraries(self, user_id: str) → list[dict[str, Any]], call:self.get(f"/Users/{user_id}/Views").get, method:items(self, user_id: str, parent_id, start_index, limit, search, include_item_types, recursive, sort_by, sort_order) → dict[str, Any], call:self.get, call:str(recursive).lower, method:item_count(self, user_id: str, include_item_types: str, parent_id) → int, call:self.get, call:int, call:response.get, method:media_counts(self, user_id: str) → dict[str, int], call:self.item_count, method:library_item_counts(self, user_id: str, libraries: list[dict[str, Any]]) → list[dict[str, Any]], call:lib.get, call:self.item_count, call:results.append, method:active_sessions(self, active_within_seconds) → list[dict[str, Any]], call:self.get, call:isinstance, call:session.get, method:image_url(self, item_id: str, image_type) → str | dep: typing, requests
|
||||
- resources.py | Manages a lightweight POSIX shell-based remote system metrics collector that samples CPU, memory, network, and disk statistics via SSH and reads the resulting JSONL data. | exp: class:ResourceMonitorPaths, func:start_resource_collector(ssh: RemoteSSHClient, interval_seconds, retention_seconds, max_lines, paths) → str, call:shlex.quote, call:int, call:ssh.run, call:result.stdout.strip, raise:RuntimeError, func:stop_resource_collector(ssh: RemoteSSHClient, paths) → str, call:shlex.quote, call:ssh.run, call:result.stdout.strip, raise:RuntimeError, func:restart_resource_collector(ssh: RemoteSSHClient, interval_seconds, retention_seconds, max_lines, paths) → str, call:stop_resource_collector, call:start_resource_collector, func:resource_collector_status(ssh: RemoteSSHClient, paths) → str, call:shlex.quote, call:ssh.run, call:result.stdout.strip, raise:RuntimeError, func:resource_collector_debug_info(ssh: RemoteSSHClient, paths) → str, call:shlex.quote, call:ssh.run, func:read_resource_metrics(ssh: RemoteSSHClient, max_lines, paths) → list[dict[str, Any]], call:shlex.quote, call:int, call:ssh.run, call:result.stdout.splitlines, call:line.strip, call:rows.append, call:json.loads, raise:RuntimeError, func:disk_space(ssh: RemoteSSHClient, path) → dict[str, Any], call:shlex.quote, call:ssh.run, call:result.stdout.strip, call:json.loads, raise:RuntimeError | dep: json, shlex, dataclasses, typing, media_library_viewer.clients.ssh
|
||||
- ssh.py | Provides an SSH client wrapper around Paramiko for remote filesystem inspection and media analysis, ensuring POSIX shell compatibility regardless of the user's login shell. | exp: class:CommandResult, class:RemoteSSHClient, method:__init__(self, host: str, username: str, port, key_filename, password, timeout), raise:ValueError, method:connect(self) → paramiko.SSHClient, call:paramiko.SSHClient, call:client.load_system_host_keys, call:client.set_missing_host_key_policy, call:paramiko.RejectPolicy, call:client.connect, method:close(self) → None, call:self._client.close, method:run(self, command: str, timeout) → CommandResult, call:self.connect, call:shlex.quote, call:client.exec_command, call:stdout.channel.recv_exit_status, call:CommandResult, call:stdout.read().decode, call:stderr.read().decode, method:list_dir(self, path: str) → CommandResult, call:shlex.quote, call:self.run, method:stat_path(self, path: str) → CommandResult, call:shlex.quote, call:self.run, method:ffprobe_json(self, path: str) → dict[str, Any], call:shlex.quote, call:self.run, call:json.loads, raise:RuntimeError | dep: json, posixpath, shlex, dataclasses, typing, paramiko
|
||||
## arch
|
||||
Client-wrapper pattern with each module encapsulating a specific integration concern (Jellyfin HTTP API, SSH filesystem access, remote resource monitoring), returning plain Python types for frontend agnosticism.
|
||||
## tags
|
||||
call:shlex.quote, resource, error, collector, call:ssh.run, raise:runtime, call:self.get, call:result.stdout.strip
|
||||
## symbols
|
||||
- JellyfinClient
|
||||
- ResourceMonitorPaths
|
||||
- CommandResult
|
||||
- RemoteSSHClient
|
||||
- __init__
|
||||
- get
|
||||
- users
|
||||
- libraries
|
||||
## workflows
|
||||
- change clients behavior
|
||||
read: __init__.py, jellyfin.py, resources.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,21 @@
|
||||
# archive/src/media_library_viewer/domain (index)
|
||||
dir: archive/src/media_library_viewer/domain
|
||||
|
||||
## role
|
||||
Provides domain-level normalization logic that transforms inconsistent Jellyfin API responses into stable, flattened data structures for storage and display.
|
||||
## parent
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## children
|
||||
-
|
||||
## files
|
||||
- __init__.py
|
||||
- media.py
|
||||
## links
|
||||
index: archive/src/media_library_viewer/domain/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/domain/.pi-map.md
|
||||
## workflows
|
||||
- change domain behavior
|
||||
read: __init__.py, media.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,28 @@
|
||||
# archive/src/media_library_viewer/domain
|
||||
dir: archive/src/media_library_viewer/domain
|
||||
|
||||
index: archive/src/media_library_viewer/domain/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Provides domain-level normalization logic that transforms inconsistent Jellyfin API responses into stable, flattened data structures for storage and display.
|
||||
## files
|
||||
- __init__.py | Serves as the package docstring for a domain-level helpers/normalization module that converts external data into stable app concepts.
|
||||
- media.py | Flattens inconsistent Jellyfin API item JSON into stable, normalized dictionaries for SQLite storage and frontend display. | exp: func:first_media_source(item: dict[str, Any]) → dict[str, Any], call:item.get, func:media_streams(item: dict[str, Any], stream_type) → list[dict[str, Any]], call:item.get, call:streams.extend, call:source.get, call:str(stream.get("Type") or stream.get("codec_type") or "").lower, call:stream.get, call:stream_type.lower, func:stream_value(stream: dict[str, Any], *keys: str) → Any, func:is_hdr_item(item: dict[str, Any]) → bool, call:media_streams, call:stream_value, call:" ".join, call:str(value).lower, call:any, func:format_date_added(value: str | None) → str, call:pd.to_datetime(value).strftime, call:str, func:timestamp_date_added(value: str | None) → int | None, call:int, call:pd.to_datetime(value).timestamp, func:format_rate_bits_decimal(bits_per_second: float | int | str | None) → str, call:float, call:str, func:normalize_media_item(item: dict[str, Any], library_id, library_name) → dict[str, Any], call:first_media_source, call:media_streams, call:source.get, call:item.get, call:stream_value, call:is_hdr_item, call:int, call:ticks_to_minutes, call:human_size, call:format_rate_bits_decimal, call:video.get, call:format_date_added, call:timestamp_date_added, func:display_media_row(row: dict[str, Any]) → dict[str, Any], call:row.get, call:human_size, call:format_rate_bits_decimal | dep: typing, media_library_viewer.utils, pandas, media_library_viewer.utils (human_size, ticks_to_minutes)
|
||||
## arch
|
||||
Functional transformation layer pattern mapping raw external API JSON directly into normalized flat dictionaries without intermediate ORM or complex object hierarchies.
|
||||
## tags
|
||||
media, call:str, date, added, item, call:item.get, streams, call:stream
|
||||
## symbols
|
||||
- first_media_source
|
||||
- media_streams
|
||||
- stream_value
|
||||
- is_hdr_item
|
||||
- format_date_added
|
||||
- timestamp_date_added
|
||||
- format_rate_bits_decimal
|
||||
- normalize_media_item
|
||||
## workflows
|
||||
- change domain behavior
|
||||
read: __init__.py, media.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,21 @@
|
||||
# archive/src/media_library_viewer/services (index)
|
||||
dir: archive/src/media_library_viewer/services
|
||||
|
||||
## role
|
||||
Application service layer that coordinates domain logic and external clients into reusable, UI-agnostic media library operations.
|
||||
## parent
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## children
|
||||
-
|
||||
## files
|
||||
- __init__.py
|
||||
- media_index.py
|
||||
## links
|
||||
index: archive/src/media_library_viewer/services/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/services/.pi-map.md
|
||||
## workflows
|
||||
- change services behavior
|
||||
read: __init__.py, media_index.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,28 @@
|
||||
# archive/src/media_library_viewer/services
|
||||
dir: archive/src/media_library_viewer/services
|
||||
|
||||
index: archive/src/media_library_viewer/services/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Application service layer that coordinates domain logic and external clients into reusable, UI-agnostic media library operations.
|
||||
## files
|
||||
- __init__.py | Marks the directory as a Python package and documents it as the application services layer for coordinating clients/domain logic into reusable operations.
|
||||
- media_index.py | Provides a UI-agnostic SQLite-backed media inventory service that indexes, queries, and manages Jellyfin media metadata with filtering, sorting, and pagination capabilities. | exp: class:MediaIndexStatus, class:MediaIndex, method:__init__(self, db_path), call:Path, call:self.db_path.parent.mkdir, method:connect(self) → sqlite3.Connection, call:sqlite3.connect, method:init_schema(self) → None, call:self.connect, call:conn.executescript, method:set_metadata(self, key: str, value: str | int | float) → None, call:self.init_schema, call:self.connect, call:conn.execute, call:str, method:replace_items(self, rows: Iterable[dict[str, Any]]) → int, call:self.init_schema, call:list, call:",".join, call:len, call:self.connect, call:conn.execute, call:conn.executemany, call:','.join, call:row.get, call:str, call:int, call:time.time, method:status(self) → MediaIndexStatus, call:self.db_path.exists, call:MediaIndexStatus, call:self.connect, call:int, call:conn.execute("SELECT COUNT(*) FROM media_items").fetchone, call:conn.execute("SELECT value FROM index_metadata WHERE key='updated_at'").fetchone, call:conn.execute("SELECT value FROM index_metadata WHERE key='build_duration_seconds'").fetchone, call:str(updated_row[0]).isdigit, call:time.strftime, call:time.localtime, call:float, method:query(self, library_id, library_ids, media_types, search, hdr_filter, sort_key, sort_order, limit, offset) → tuple[list[dict[str, Any]], int], call:self.init_schema, call:where.append, call:",".join, call:len, call:params.extend, call:params.append, call:search.lower, call:" AND ".join, call:SORT_COLUMNS.get, call:self.connect, call:int, call:conn.execute("SELECT COUNT(*) FROM media_items" + where_sql, params).fetchone, call:conn.execute( "SELECT * FROM media_items" + where_sql + order_sql + " LIMIT ? OFFSET ?", [*params, int(limit), int(offset)], ).fetchall, call:display_media_row, call:dict, func:build_media_index(client: JellyfinClient, user_id: str, libraries: list[dict[str, Any]], index, page_size) → int, call:MediaIndex, call:time.perf_counter, call:library.get, call:client.items, call:response.get, call:normalized_rows.extend, call:normalize_media_item, call:len, call:int, call:index.replace_items, call:index.set_metadata | dep: sqlite3, time, dataclasses, pathlib, typing, media_library_viewer.clients.jellyfin, media_library_viewer.domain.media, media_library_viewer.clients.jellyfin.JellyfinClient, media_library_viewer.domain.media.display_media_row, media_library_viewer.domain.media.normalize_media_item
|
||||
## arch
|
||||
Service-oriented pattern with SQLite-backed indexing, query filtering, and pagination encapsulated behind a single cohesive media index service module.
|
||||
## tags
|
||||
media, call:conn.execute, index, call:self.connect, schema, call:int, init, status
|
||||
## symbols
|
||||
- MediaIndexStatus
|
||||
- MediaIndex
|
||||
- __init__
|
||||
- connect
|
||||
- init_schema
|
||||
- set_metadata
|
||||
- replace_items
|
||||
- status
|
||||
## workflows
|
||||
- change services behavior
|
||||
read: __init__.py, media_index.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,24 @@
|
||||
# archive/src/media_library_viewer/ui (index)
|
||||
dir: archive/src/media_library_viewer/ui
|
||||
|
||||
## role
|
||||
Streamlit UI rendering layer for the media library viewer application, providing dashboard monitoring, file browsing, media indexing, and preview capabilities.
|
||||
## parent
|
||||
index: archive/src/media_library_viewer/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/.pi-map.md
|
||||
## children
|
||||
-
|
||||
## files
|
||||
- __init__.py
|
||||
- dashboard.py
|
||||
- file_browser.py
|
||||
- media.py
|
||||
- preview.py
|
||||
## links
|
||||
index: archive/src/media_library_viewer/ui/.pi-map.index.md
|
||||
map: archive/src/media_library_viewer/ui/.pi-map.md
|
||||
## workflows
|
||||
- change ui behavior
|
||||
read: __init__.py, dashboard.py, file_browser.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,31 @@
|
||||
# archive/src/media_library_viewer/ui
|
||||
dir: archive/src/media_library_viewer/ui
|
||||
|
||||
index: archive/src/media_library_viewer/ui/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Streamlit UI rendering layer for the media library viewer application, providing dashboard monitoring, file browsing, media indexing, and preview capabilities.
|
||||
## files
|
||||
- __init__.py | Package initialization file for Streamlit UI modules that documents the architectural pattern of splitting the application into separate render modules.
|
||||
- dashboard.py | Implements a Streamlit dashboard for monitoring a Jellyfin media server, displaying media library statistics, active playback sessions, and server resource metrics via SSH. | exp: func:format_rate_bytes(bytes_per_second: float | int | None) → str, call:human_size, func:rate_scale(max_value: float | int | None) → tuple[float, str], call:abs, call:float, func:scaled_rate_chart_df(chart_df: pd.DataFrame, columns: list[str], labels: list[str]) → tuple[pd.DataFrame, str], call:chart_df[columns].max(numeric_only=True).max, call:rate_scale, call:chart_df[columns].copy, func:format_elapsed(seconds: float | int | None) → str, call:float, call:int, func:render_media_overview(cached_media_counts, cached_library_counts, base_url: str, api_key: str, user_id: str) → None, call:st.subheader, call:cached_media_counts, call:st.warning, call:counts.get, call:st.columns, call:top_cols[0].metric, call:top_cols[1].metric, call:top_cols[2].metric, call:top_cols[3].metric, call:cached_library_counts, call:st.caption, call:st.markdown, call:e.get, call:st.container, call:m_cols[0].metric, call:m_cols[1].metric, func:render_now_playing(cached_active_sessions, base_url: str, api_key: str) → None, call:st.subheader, call:cached_active_sessions, call:st.warning, call:st.caption, call:session.get, call:bool, call:play_state.get, call:item.get, call:transcoding.get, call:transcode_type.append, call:rows.append, call:", ".join, call:st.dataframe, call:pd.DataFrame, func:render_resource_dashboard(get_ssh_client, ssh_args: tuple, media_root: str, detailed) → None, call:st.subheader, call:get_ssh_client, call:resource_collector_status, call:st.error, call:st.columns, call:control_col.caption, call:start_col.button, call:st.success, call:start_resource_collector, call:restart_col.button, call:restart_resource_collector, call:stop_col.button, call:st.info, call:stop_resource_collector, call:refresh_col.button, call:st.rerun, call:st.caption, call:read_resource_metrics, call:disk_space, call:float, call:str(space.get("used_pct", "0")).rstrip, call:space.get, call:disk_cols[0].metric, call:human_size, call:disk_cols[1].metric, call:disk_cols[2].metric, call:disk_cols[3].metric, call:st.progress, call:min, call:max, call:st.warning, call:st.expander, call:st.code, call:resource_collector_debug_info, call:pd.DataFrame, call:pd.to_numeric, call:df.dropna, call:pd.to_datetime(df["ts"], unit="s", utc=True).dt.tz_convert, call:time.time, call:len, call:st.write, call:raw_df['ts'].astype(float).max, call:st.dataframe, call:raw_df.tail, call:df.sort_values, call:df["cpu_pct"].mean, call:df["cpu_pct"].max, call:df["iowait_pct"].mean, call:df["iowait_pct"].max, call:df["mem_pct"].mean, call:df["mem_pct"].max, call:df["net_rx_bytes_per_sec"].mean, call:df["net_rx_bytes_per_sec"].max, call:df["net_tx_bytes_per_sec"].mean, call:df["net_tx_bytes_per_sec"].max, call:df["disk_read_bps"].mean, call:df["disk_read_bps"].max, call:df["disk_write_bps"].mean, call:df["disk_write_bps"].max, call:metric_cols[0].metric, call:metric_cols[0].caption, call:metric_cols[1].metric, call:latest.get, call:metric_cols[1].caption, call:metric_cols[2].metric, call:metric_cols[2].caption, call:metric_cols[3].metric, call:format_rate_bytes, call:metric_cols[3].caption, call:metric_cols[4].metric, call:metric_cols[4].caption, call:metric_cols[5].metric, call:metric_cols[5].caption, call:metric_cols[6].metric, call:metric_cols[6].caption, call:df.set_index, call:st.markdown, call:st.line_chart, call:scaled_rate_chart_df | dep: time, typing, media_library_viewer.clients.resources, media_library_viewer.utils, pandas, streamlit
|
||||
- file_browser.py | Renders an interactive SSH remote file browser UI in Streamlit with filtering, sorting, pagination, and directory navigation using ag-grid. | exp: func:reset_file_browser_filters() → None, call:st.session_state.pop, func:set_file_browser_path(path: str, selected_path, reset_filters) → None, func:aggrid_selected_rows(response: dict) → list[dict], call:response.get, call:isinstance, call:selected_rows.to_dict, call:list, func:render_file_browser(cached_dir_listing: Callable[..., list[dict]], ssh_args: tuple, initial_path: str) → str, call:st.subheader, call:st.session_state.pop, call:reset_file_browser_filters, call:st.session_state.get, call:st.columns, call:status_col.caption, call:selected_col.caption, call:path_col.text_input, call:set_file_browser_path, call:st.rerun, call:refresh_col.button, call:cached_dir_listing.clear, call:st.error, call:PurePosixPath(name).suffix.lower, call:str, call:display_rows.append, call:int, call:human_size, call:float, call:timestamp_to_local, call:len, call:sum, call:st.caption, call:st.container, call:filter_col.selectbox, call:search_col.text_input, call:sorted, call:ext_col.selectbox, call:sort_col.selectbox, call:order_col.toggle, call:page_size_col.selectbox, call:search_term.lower, call:r["name"].lower, call:filtered_rows.sort, call:max, call:page_col.number_input, call:summary_col.caption, call:min, call:visible_rows.append, call:visible_rows.extend, call:st.info, call:st.expander, call:st.write, call:pd.DataFrame, call:GridOptionsBuilder.from_dataframe, call:grid_builder.configure_default_column, call:grid_builder.configure_column, call:grid_builder.configure_selection, call:grid_builder.build, call:JsCode, call:AgGrid, call:aggrid_selected_rows, call:picked_row.get | dep: json, pathlib, typing, st_aggrid, media_library_viewer.utils, streamlit, pandas
|
||||
- media.py | Renders a Streamlit UI tab for browsing and filtering a local SQLite-backed media index with ag-grid table display and automatic file browser synchronization. | exp: func:aggrid_selected_rows(response: dict[str, Any]) → list[dict[str, Any]], call:response.get, call:isinstance, call:selected_rows.to_dict, call:list, func:format_elapsed(seconds: float | int | None) → str, call:float, call:int, func:render_media_tab(client, user_id: str, libraries: list[dict[str, Any]], set_file_browser_path: Callable[[str, str | None, bool], None]) → None, call:st.subheader, call:st.caption, call:MediaIndex, call:index.status, call:st.columns, call:status_parts.append, call:format_elapsed, call:status_col.caption, call:" | ".join, call:status_col.warning, call:build_col.button, call:st.spinner, call:build_media_index, call:st.success, call:st.rerun, call:refresh_col.button, call:st.info, call:filter_col.multiselect, call:list, call:library_options.keys, call:type_col.multiselect, call:search_col.text_input, call:page_size_col.selectbox, call:page_col.number_input, call:sort_col.selectbox, call:sort_options.keys, call:order_col.selectbox, call:hdr_col.selectbox, call:index.query, call:int, call:len, call:pd.DataFrame(rows)[columns].fillna, call:st.session_state.get, call:GridOptionsBuilder.from_dataframe, call:grid_builder.configure_default_column, call:grid_builder.configure_column, call:grid_builder.configure_selection, call:grid_builder.build, call:JsCode, call:AgGrid, call:min, call:aggrid_selected_rows, call:selected_rows[0].get, call:set_file_browser_path, call:str, call:PurePosixPath, call:st.expander, call:st.write | dep: pathlib, typing, st_aggrid, media_library_viewer.services.media_index, pandas, streamlit
|
||||
- preview.py | Renders a Streamlit UI for previewing selected media file metadata via ffprobe and executing remote SSH diagnostic tools/jobs. | exp: func:render_ffprobe_sections(ffprobe_data: dict[str, Any]) → None, call:ffprobe_format_summary, call:summarize_video_streams, call:summarize_audio_streams, call:summarize_subtitle_streams, call:st.markdown, call:st.dataframe, call:pd.DataFrame, call:st.caption, func:render_selected_file_preview(ssh_args: tuple, selected_path: str | None, cached_ffprobe_preview: Callable[..., dict[str, Any]]) → None, call:st.container, call:st.markdown, call:st.caption, call:is_known_video_file, call:st.columns, call:refresh_col.button, call:cached_ffprobe_preview.clear, call:st.rerun, call:st.spinner, call:status_col.error, call:status_col.success, call:render_ffprobe_sections, call:st.expander, call:st.json, func:render_ssh_tools(ssh, ssh_args: tuple, selected_path: str | None, cached_ffprobe_preview: Callable[..., dict[str, Any]]) → None, call:render_selected_file_preview, call:st.subheader, call:st.tabs, call:st.button, call:ssh.ffprobe_json, call:render_ffprobe_sections, call:st.expander, call:st.dataframe, call:pd.DataFrame, call:summarize_streams, call:st.json, call:st.error, call:str, call:ssh.stat_path, call:st.code, call:st.warning, call:st.selectbox, call:list, call:JOB_TEMPLATES.keys, call:st.caption, call:JOB_TEMPLATES[job_key].render, call:run_job, call:st.write | dep: typing, media_library_viewer.jobs, media_library_viewer.utils, pandas, streamlit
|
||||
## arch
|
||||
Module-based render pattern where each UI tab/view is isolated in its own module, sharing session state for cross-component synchronization (e.g., file browser auto-sync) and leveraging ag-grid for interactive data tables.
|
||||
## tags
|
||||
call:metric, call:grid, render, call:st.caption, col.button, browser, col.selectbox, media
|
||||
## symbols
|
||||
- format_rate_bytes
|
||||
- rate_scale
|
||||
- scaled_rate_chart_df
|
||||
- format_elapsed
|
||||
- render_media_overview
|
||||
- render_now_playing
|
||||
- render_resource_dashboard
|
||||
- reset_file_browser_filters
|
||||
## workflows
|
||||
- change ui behavior
|
||||
read: __init__.py, dashboard.py, file_browser.py
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,19 @@
|
||||
# archive/tests (index)
|
||||
dir: archive/tests
|
||||
|
||||
## role
|
||||
Legacy or archived test directory currently containing only a placeholder file with no active test code.
|
||||
## parent
|
||||
index: archive/.pi-map.index.md
|
||||
map: archive/.pi-map.md
|
||||
## children
|
||||
-
|
||||
## files
|
||||
- .gitkeep
|
||||
## links
|
||||
index: archive/tests/.pi-map.index.md
|
||||
map: archive/tests/.pi-map.md
|
||||
## workflows
|
||||
-
|
||||
## dirty
|
||||
-
|
||||
@@ -0,0 +1,19 @@
|
||||
# archive/tests
|
||||
dir: archive/tests
|
||||
|
||||
index: archive/tests/.pi-map.index.md
|
||||
|
||||
## role
|
||||
Legacy or archived test directory currently containing only a placeholder file with no active test code.
|
||||
## files
|
||||
- .gitkeep | Swaps the position of two tmux panes within a window or between windows | dep: tmux, sh
|
||||
## arch
|
||||
Empty placeholder structure using a `.gitkeep` file to preserve the directory in version control for potential future use.
|
||||
## tags
|
||||
tmux, swaps, position, two, panes, within, window, windows
|
||||
## symbols
|
||||
-
|
||||
## workflows
|
||||
-
|
||||
## dirty
|
||||
-
|
||||
Reference in New Issue
Block a user