pixlstash 1.6.0.dev1__tar.gz → 1.6.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pixlstash-1.6.0.dev1/pixlstash.egg-info → pixlstash-1.6.0.dev2}/PKG-INFO +45 -6
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/README.md +43 -4
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/frontend/package-lock.json +2 -2
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/frontend/package.json +1 -1
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/auth.py +83 -6
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/face.py +6 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/picture.py +78 -409
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/user.py +3 -0
- pixlstash-1.6.0.dev2/pixlstash/frontend/dist/assets/Tiny5-Regular-WaYIHWdr.ttf +0 -0
- pixlstash-1.6.0.dev1/pixlstash/frontend/dist/assets/index-BIKsiyaO.css → pixlstash-1.6.0.dev2/pixlstash/frontend/dist/assets/index-DrzwWAiV.css +1 -1
- pixlstash-1.6.0.dev2/pixlstash/frontend/dist/assets/index-xPNJZNlg.js +19 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/index.html +2 -2
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/engine.py +10 -6
- pixlstash-1.6.0.dev2/pixlstash/migrations/versions/0052_drop_import_excluded_sentinel.py +268 -0
- pixlstash-1.6.0.dev2/pixlstash/migrations/versions/0053_add_face_model_pack.py +63 -0
- pixlstash-1.6.0.dev2/pixlstash/migrations/versions/0054_add_sidebar_docked.py +36 -0
- pixlstash-1.6.0.dev2/pixlstash/migrations/versions/0055_add_sidebar_width.py +34 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/picture_scoring.py +0 -2
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/config.py +2 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/import_folders.py +0 -1
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/picture_sets.py +8 -8
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_crud.py +636 -48
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_listing.py +20 -163
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_misc.py +30 -92
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_search.py +9 -5
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/server.py +253 -24
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/startup_checks.py +10 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/__init__.py +4 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/face_extraction_task.py +35 -4
- pixlstash-1.6.0.dev2/pixlstash/tasks/face_model_refresh_task.py +417 -0
- pixlstash-1.6.0.dev2/pixlstash/tasks/missing_face_model_refresh_finder.py +94 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/reference_folder_scan_task.py +22 -42
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/task_type.py +1 -0
- pixlstash-1.6.0.dev2/pixlstash/utils/insightface_model_utils.py +222 -0
- pixlstash-1.6.0.dev2/pixlstash/utils/query/__init__.py +3 -0
- pixlstash-1.6.0.dev2/pixlstash/utils/query/predicate_filter.py +379 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/picture_stats.py +22 -117
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/user_settings_utils.py +23 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/vault.py +4 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/work_planner.py +7 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2/pixlstash.egg-info}/PKG-INFO +45 -6
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash.egg-info/SOURCES.txt +16 -3
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pyproject.toml +2 -2
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_authentication.py +114 -0
- pixlstash-1.6.0.dev2/tests/test_default_device_override.py +62 -0
- pixlstash-1.6.0.dev2/tests/test_insightface_model_pack.py +578 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_likeness_and_face_search.py +64 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_migrations.py +6 -3
- pixlstash-1.6.0.dev2/tests/test_predicate_filter.py +444 -0
- pixlstash-1.6.0.dev2/tests/test_server_external_listener.py +148 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_server_simple.py +188 -2
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_user_settings_tagger_settings.py +1 -0
- pixlstash-1.6.0.dev1/pixlstash/frontend/dist/assets/PressStart2P-Regular-DogiNJoF.ttf +0 -0
- pixlstash-1.6.0.dev1/pixlstash/frontend/dist/assets/index-9eEGd5YI.js +0 -19
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/LICENSE +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/MANIFEST.in +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/frontend/LICENSE +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/LICENSE +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/alembic.ini +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/app.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/anchors/builtin_bad.npy +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/anchors/builtin_good.npy +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/comfyui-workflows/built-in/Flux2-Klein-Image-Edit.json +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/comfyui-workflows/built-in/Flux2-Klein-t2i.json +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/comfyui-workflows/built-in/Upscale-2x-RealESRGAN.json +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/scalar-assets/ScreenshotToken.jpg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/scalar-assets/ScreenshotTokens.jpg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/scalar-assets/ScreenshotsUserSettings.jpg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/scalar-assets/WhereIsUserSettings.jpg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/data/scalar-assets/logo.png +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/database.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/character.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/deleted_file_log.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/guest_score.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/guest_session.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/import_folder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/metadata.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/picture_likeness.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/picture_project.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/picture_set.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/picture_stack.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/project.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/quality.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/reference_folder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/snapshot.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/tag.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/tag_prediction.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/db_models/user_token.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/event_types.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/Empty.png +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/EmptyTrash.png +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/Logo.png +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/Watermark.png +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/favicon.ico +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/frontend/dist/vite.svg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_loading_dataset_prepper.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/base.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/blur_sharpen.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/brightness_contrast.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/colour_filter.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/pixelate.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/plugin_template.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/rotate.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/built-in/scaling.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/registry.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/image_plugins/service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/model_lifecycle.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/vram_budget.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/clip_embedding.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/description.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/face_embedding.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/tagging.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/inference/workflows/text_embedding.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/env.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/script.py.mako +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0001_baseline.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0002_add_text_score.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0003_add_original_file_name.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0004_add_comfyui_fields.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0005_add_projects.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0006_add_attachment_url.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0007_add_picture_project_id.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0008_add_compact_mode.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0009_add_picture_project_membership.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0010_project_name_uniqueness.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0011_pictureset_name_uniqueness.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0012_character_name_uniqueness.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0013_tag_prediction.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0014_tag_prediction_composite_index.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0015_tag_prediction_model_version_rename.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0016_tag_prediction_confirm_applied.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0017_anomaly_tag_uncertainty.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0018_anomaly_tag_uncertainty_disagreement.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0019_pending_character_id.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0020_source_picture_id.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0021_tagger_enabled_flags.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0022_add_check_for_updates.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0023_add_show_keyboard_hint.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0024_add_deleted_file_log.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0025_add_reference_folders.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0026_add_caption_file_and_sync_captions.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0027_add_caption_file_mtime.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0028_add_smart_score.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0029_add_import_excluded_to_picture.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0030_add_import_folders.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0031_migrate_watch_folders_to_import_folder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0032_add_reference_folder_host_path.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0033_add_import_folder_host_path.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0034_add_token_scope_fields.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0035_drop_face_quality.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0036_add_token_include_attachments.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0037_add_user_public_url.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0038_add_watermark_fields.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0039_drop_color_histogram.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0040_move_text_score_to_picture.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0041_guest_scores.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0042_guest_session_cookie_token.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0043_pictureset_icon_color.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0044_add_grid_sort_indexes.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0045_tagger_settings.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0046_tag_sentinel_rename.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0047_add_stack_leader_grid_indexes.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0048_normalize_stack_positions.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0049_snapshots.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0050_reset_metadata_hash_membership.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/migrations/versions/0051_deleted_file_log_path_sha.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/pixl_logging.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/_helpers.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/characters.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/comfyui.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/filesystem.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/guest_scores.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_export.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_face_search.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_helpers.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_import.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_likeness_search.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/pictures/_thumbnails.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/projects.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/reference_folders.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/share.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/snapshots.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/stacks.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/tag_predictions.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/taggers.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/routes/tags.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/config_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/plugin_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/restore_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/search_query_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/share_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/snapshot_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/stack_membership.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/services/tag_prediction_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/stacking.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/base.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/clip_service.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/florence2.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/joycaption.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/pixlstash_tagger.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/registry.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/sbert.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tagger_plugins/wd14.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/task_runner.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/base_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/base_task_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/comfyui_extraction_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/description_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/ensure_gfs_snapshot_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/ensure_gfs_snapshot_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/face_detection_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/image_embedding_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/likeness_parameters_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/likeness_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_comfyui_extraction_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_description_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_face_extraction_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_file_purge_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_file_purge_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_image_embedding_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_likeness_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_likeness_parameters_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_quality_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_smart_score_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_source_face_likeness_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_tag_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_text_embedding_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_text_score_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/missing_watch_folder_import_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/quality_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/reference_folder_scan_finder.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/smart_score_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/source_face_likeness_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/tag_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/text_embedding_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/text_score_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/tasks/watch_folder_import_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/atomic_write.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/caption_file_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/comfyui_utilities.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/face_tags.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/host_path_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/image_processing/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/image_processing/face_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/image_processing/image_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/image_processing/video_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/insightface_batched.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/likeness/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/likeness/likeness_parameter_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/likeness/likeness_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/model_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/path_mapper.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/quality/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/quality/quality_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/quality/smart_score_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/rate_limiter.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/reference_folder_validator.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/reference_folder_watcher.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/caption_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/export_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/filter_helpers.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/path_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/serialization_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/system_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/service/tag_prediction_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/snapshot_compression.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/stack/__init__.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/stack/stack_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/vram_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/utils/watermark.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash/worker_config.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash.egg-info/dependency_links.txt +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash.egg-info/entry_points.txt +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash.egg-info/requires.txt +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/pixlstash.egg-info/top_level.txt +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/setup.cfg +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/setup.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_api_coverage.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_architecture_guardrails.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_backend_order_stability.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_batch_apply_scores.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_characters_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_clip_text_embedding_similarity.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_comfyui_workflow_extraction.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_docker_windows_host_paths.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_export_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_face_detection_extreme_aspect_ratio.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_face_extraction_speed.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_facial_features_worker.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_find_orphaned_files.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_florence.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_full_pipeline.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_gfs_snapshot_schedule.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_guest_scoring.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_image_embedding_worker.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_image_plugins_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_likeness_worker.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_many_to_many_face_data.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_metadata_hash.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_openapi_response_schemas.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_picture_plugins.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_picture_sets.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_picture_stack_utils.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_pictures_stream.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_projects_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_quality_task_shutdown.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_rate_limiter.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_read_token_security.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_restore.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_server.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_smart_score_consistency.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_snapshot_compression.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_snapshots.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_snapshots_auth.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_ssl_generation.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_stack_position_invariant.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_stacks_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_stacks_membership.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_stats_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_tag_predictions_api.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_tag_task.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_tag_worker.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_tagger_plugin_registry.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_vram_batch_budget.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_watch_folder_worker.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_websocket_auth.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_work_planner.py +0 -0
- {pixlstash-1.6.0.dev1 → pixlstash-1.6.0.dev2}/tests/test_workers_api.py +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pixlstash
|
|
3
|
-
Version: 1.6.0.
|
|
3
|
+
Version: 1.6.0.dev2
|
|
4
4
|
Summary: Self-hosted picture library with AI tagging, semantic search, and a clean web UI
|
|
5
|
-
Author: Gaute Lindkvist
|
|
5
|
+
Author-email: Gaute Lindkvist <lindkvis@gmail.com>
|
|
6
6
|
License-Expression: GPL-3.0-only AND MIT
|
|
7
7
|
Project-URL: Homepage, https://pikselkroken.github.io/pixlstash
|
|
8
8
|
Project-URL: Repository, https://github.com/pikselkroken/pixlstash
|
|
@@ -110,6 +110,13 @@ PixlStash runs on your machine and serves the UI at a local (or Internet-facing)
|
|
|
110
110
|
</a>
|
|
111
111
|
</p>
|
|
112
112
|
|
|
113
|
+
PixlStash is available as a **native desktop app for Windows, macOS, and Linux**
|
|
114
|
+
(no Python or browser tab required), as a Windows installer, a Docker image, or a
|
|
115
|
+
pip package. The desktop app ships a ready-to-run CPU runtime (Metal on Apple
|
|
116
|
+
Silicon), so it works offline out of the box, and auto-detects your hardware to
|
|
117
|
+
offer optional GPU acceleration (NVIDIA CUDA / AMD ROCm), which it installs on
|
|
118
|
+
demand straight from PyPI / PyTorch.
|
|
119
|
+
|
|
113
120
|
Detailed installation instructions on <a href="http://pixlstash.dev/install.html">pixlstash.dev</a>.
|
|
114
121
|
|
|
115
122
|
|
|
@@ -121,6 +128,11 @@ On first run, PixlStash creates a user config directory and stores:
|
|
|
121
128
|
- Database
|
|
122
129
|
- Imported media files
|
|
123
130
|
|
|
131
|
+
The **desktop app** uses this same platform user data directory, so a desktop
|
|
132
|
+
install shares its library with a pip or Docker install on the same machine. If
|
|
133
|
+
you add GPU acceleration, the desktop app stores the downloaded GPU wheels under
|
|
134
|
+
the app's own user-data directory.
|
|
135
|
+
|
|
124
136
|
> **Model downloads:** On first startup, PixlStash automatically downloads the AI models required for tagging, captioning, and quality scoring. This includes several hundred MB of model weights. Downloads are stored in the platform user data directory:
|
|
125
137
|
>
|
|
126
138
|
> | OS | Path |
|
|
@@ -317,10 +329,36 @@ Import Folders UI/API, not in `server-config.json`.
|
|
|
317
329
|
|
|
318
330
|
### Processing
|
|
319
331
|
|
|
320
|
-
| Key | Default
|
|
321
|
-
| -------------------------------- |
|
|
322
|
-
| `default_device` | `"cpu"`
|
|
323
|
-
| `
|
|
332
|
+
| Key | Default | Description |
|
|
333
|
+
| -------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
334
|
+
| `default_device` | `"cpu"` | Device used for AI processing (`"cpu"` or `"cuda"`). |
|
|
335
|
+
| `insightface_model_pack` | `"buffalo_l"` | InsightFace model pack used by the face detection / recognition pipeline. One of `"buffalo_l"` or `"auraface"`. |
|
|
336
|
+
| `generate_thumbnails_on_startup` | `true` | Generate missing thumbnails when the server starts. |
|
|
337
|
+
|
|
338
|
+
#### Face model pack and licensing
|
|
339
|
+
|
|
340
|
+
`insightface_model_pack` selects which InsightFace model pack powers face
|
|
341
|
+
detection and face recognition. The licensing decision is yours;
|
|
342
|
+
PixlStash simply makes the choice available.
|
|
343
|
+
|
|
344
|
+
- **`buffalo_l`** (default): the standard InsightFace pack. Its recognition
|
|
345
|
+
weights are trained on the WebFace600K dataset, which is licensed for
|
|
346
|
+
**non-commercial research use only**. This is the right choice for personal
|
|
347
|
+
and research use, and it downloads automatically on first use.
|
|
348
|
+
- **`auraface`**: the [`fal/AuraFace-v1`](https://huggingface.co/fal/AuraFace-v1)
|
|
349
|
+
pack, whose weights are **Apache-2.0 licensed** and therefore suitable if you
|
|
350
|
+
need to use face features in a **commercial** setting. It uses the same
|
|
351
|
+
SCRFD-10G face detector as `buffalo_l`, so switching only changes the
|
|
352
|
+
recognition embedding. When selected, PixlStash downloads the pack from a
|
|
353
|
+
pinned HuggingFace revision into `~/.insightface/models/auraface/` on first
|
|
354
|
+
use. If the automatic download fails (for example, no network access), you can
|
|
355
|
+
place the pack's `.onnx` files in that directory manually and restart.
|
|
356
|
+
|
|
357
|
+
Changing this setting on an existing library does **not** delete your faces or
|
|
358
|
+
your manual character assignments. PixlStash detects faces whose embeddings came
|
|
359
|
+
from a different pack and refreshes those embeddings in place, in the background,
|
|
360
|
+
keeping each face's identity intact. New imports are always processed first, so a
|
|
361
|
+
refresh sweep never starves brand-new pictures.
|
|
324
362
|
|
|
325
363
|
To remove stale database records for missing source files at startup, run:
|
|
326
364
|
|
|
@@ -345,6 +383,7 @@ python -m pixlstash.app --cleanup-missing-pictures
|
|
|
345
383
|
"require_ssl": false,
|
|
346
384
|
"image_root": "/home/user/.config/pixlstash/images",
|
|
347
385
|
"default_device": "cpu",
|
|
386
|
+
"insightface_model_pack": "buffalo_l",
|
|
348
387
|
"generate_thumbnails_on_startup": true
|
|
349
388
|
}
|
|
350
389
|
```
|
|
@@ -36,6 +36,13 @@ PixlStash runs on your machine and serves the UI at a local (or Internet-facing)
|
|
|
36
36
|
</a>
|
|
37
37
|
</p>
|
|
38
38
|
|
|
39
|
+
PixlStash is available as a **native desktop app for Windows, macOS, and Linux**
|
|
40
|
+
(no Python or browser tab required), as a Windows installer, a Docker image, or a
|
|
41
|
+
pip package. The desktop app ships a ready-to-run CPU runtime (Metal on Apple
|
|
42
|
+
Silicon), so it works offline out of the box, and auto-detects your hardware to
|
|
43
|
+
offer optional GPU acceleration (NVIDIA CUDA / AMD ROCm), which it installs on
|
|
44
|
+
demand straight from PyPI / PyTorch.
|
|
45
|
+
|
|
39
46
|
Detailed installation instructions on <a href="http://pixlstash.dev/install.html">pixlstash.dev</a>.
|
|
40
47
|
|
|
41
48
|
|
|
@@ -47,6 +54,11 @@ On first run, PixlStash creates a user config directory and stores:
|
|
|
47
54
|
- Database
|
|
48
55
|
- Imported media files
|
|
49
56
|
|
|
57
|
+
The **desktop app** uses this same platform user data directory, so a desktop
|
|
58
|
+
install shares its library with a pip or Docker install on the same machine. If
|
|
59
|
+
you add GPU acceleration, the desktop app stores the downloaded GPU wheels under
|
|
60
|
+
the app's own user-data directory.
|
|
61
|
+
|
|
50
62
|
> **Model downloads:** On first startup, PixlStash automatically downloads the AI models required for tagging, captioning, and quality scoring. This includes several hundred MB of model weights. Downloads are stored in the platform user data directory:
|
|
51
63
|
>
|
|
52
64
|
> | OS | Path |
|
|
@@ -243,10 +255,36 @@ Import Folders UI/API, not in `server-config.json`.
|
|
|
243
255
|
|
|
244
256
|
### Processing
|
|
245
257
|
|
|
246
|
-
| Key | Default
|
|
247
|
-
| -------------------------------- |
|
|
248
|
-
| `default_device` | `"cpu"`
|
|
249
|
-
| `
|
|
258
|
+
| Key | Default | Description |
|
|
259
|
+
| -------------------------------- | -------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
260
|
+
| `default_device` | `"cpu"` | Device used for AI processing (`"cpu"` or `"cuda"`). |
|
|
261
|
+
| `insightface_model_pack` | `"buffalo_l"` | InsightFace model pack used by the face detection / recognition pipeline. One of `"buffalo_l"` or `"auraface"`. |
|
|
262
|
+
| `generate_thumbnails_on_startup` | `true` | Generate missing thumbnails when the server starts. |
|
|
263
|
+
|
|
264
|
+
#### Face model pack and licensing
|
|
265
|
+
|
|
266
|
+
`insightface_model_pack` selects which InsightFace model pack powers face
|
|
267
|
+
detection and face recognition. The licensing decision is yours;
|
|
268
|
+
PixlStash simply makes the choice available.
|
|
269
|
+
|
|
270
|
+
- **`buffalo_l`** (default): the standard InsightFace pack. Its recognition
|
|
271
|
+
weights are trained on the WebFace600K dataset, which is licensed for
|
|
272
|
+
**non-commercial research use only**. This is the right choice for personal
|
|
273
|
+
and research use, and it downloads automatically on first use.
|
|
274
|
+
- **`auraface`**: the [`fal/AuraFace-v1`](https://huggingface.co/fal/AuraFace-v1)
|
|
275
|
+
pack, whose weights are **Apache-2.0 licensed** and therefore suitable if you
|
|
276
|
+
need to use face features in a **commercial** setting. It uses the same
|
|
277
|
+
SCRFD-10G face detector as `buffalo_l`, so switching only changes the
|
|
278
|
+
recognition embedding. When selected, PixlStash downloads the pack from a
|
|
279
|
+
pinned HuggingFace revision into `~/.insightface/models/auraface/` on first
|
|
280
|
+
use. If the automatic download fails (for example, no network access), you can
|
|
281
|
+
place the pack's `.onnx` files in that directory manually and restart.
|
|
282
|
+
|
|
283
|
+
Changing this setting on an existing library does **not** delete your faces or
|
|
284
|
+
your manual character assignments. PixlStash detects faces whose embeddings came
|
|
285
|
+
from a different pack and refreshes those embeddings in place, in the background,
|
|
286
|
+
keeping each face's identity intact. New imports are always processed first, so a
|
|
287
|
+
refresh sweep never starves brand-new pictures.
|
|
250
288
|
|
|
251
289
|
To remove stale database records for missing source files at startup, run:
|
|
252
290
|
|
|
@@ -271,6 +309,7 @@ python -m pixlstash.app --cleanup-missing-pictures
|
|
|
271
309
|
"require_ssl": false,
|
|
272
310
|
"image_root": "/home/user/.config/pixlstash/images",
|
|
273
311
|
"default_device": "cpu",
|
|
312
|
+
"insightface_model_pack": "buffalo_l",
|
|
274
313
|
"generate_thumbnails_on_startup": true
|
|
275
314
|
}
|
|
276
315
|
```
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pixlstash-frontend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pixlstash-frontend",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.6.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@mdi/font": "^7.4.47",
|
|
12
12
|
"axios": "^1.16.0",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
import ipaddress
|
|
3
|
+
import os
|
|
3
4
|
import re
|
|
4
5
|
import secrets
|
|
5
6
|
import threading
|
|
@@ -195,6 +196,12 @@ class AuthService:
|
|
|
195
196
|
self._server_config_path = server_config_path
|
|
196
197
|
self._logger = logger
|
|
197
198
|
self.active_session_ids: dict[str, int] = {}
|
|
199
|
+
# The pre-authenticated Electron desktop owner session, if seeded (see
|
|
200
|
+
# seed_desktop_session). It grants full owner access and is therefore
|
|
201
|
+
# pinned to local connections only: the desktop window reaches the
|
|
202
|
+
# backend over loopback, so this session must never authenticate a
|
|
203
|
+
# request arriving on the optional external listener.
|
|
204
|
+
self._desktop_session_token: Optional[str] = None
|
|
198
205
|
self.user: Optional[User] = None
|
|
199
206
|
self.password_hash: Optional[str] = None
|
|
200
207
|
self.username: Optional[str] = None
|
|
@@ -269,12 +276,22 @@ class AuthService:
|
|
|
269
276
|
return sum(1 for ts in self._guest_sessions.values() if ts >= active_cutoff)
|
|
270
277
|
|
|
271
278
|
def ensure_secure_when_required(self, request: Request):
|
|
272
|
-
if self._server_config.get("require_ssl", False):
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
279
|
+
if not self._server_config.get("require_ssl", False):
|
|
280
|
+
return
|
|
281
|
+
if request.url.scheme == "https":
|
|
282
|
+
return
|
|
283
|
+
# require_ssl governs the *external* surface only. The Electron desktop
|
|
284
|
+
# window always reaches the backend over a plain-HTTP loopback connection
|
|
285
|
+
# by design (require_ssl drives the separate external listener, not this
|
|
286
|
+
# one), and a standalone HTTPS-only server never serves plaintext at all.
|
|
287
|
+
# So a local/loopback client must not be forced onto HTTPS — only a
|
|
288
|
+
# genuinely remote plaintext request is rejected.
|
|
289
|
+
if is_local_ip(self._get_real_client_ip(request)):
|
|
290
|
+
return
|
|
291
|
+
raise HTTPException(
|
|
292
|
+
status_code=403,
|
|
293
|
+
detail="HTTPS is required for this operation.",
|
|
294
|
+
)
|
|
278
295
|
|
|
279
296
|
def _get_real_client_ip(self, request: Request) -> str:
|
|
280
297
|
trusted = self._server_config.get("trusted_proxies", [])
|
|
@@ -340,6 +357,49 @@ class AuthService:
|
|
|
340
357
|
self.username = user.username if user else None
|
|
341
358
|
return user
|
|
342
359
|
|
|
360
|
+
# Env var the Electron desktop shell uses to hand the server a
|
|
361
|
+
# pre-authenticated owner session token (see seed_desktop_session).
|
|
362
|
+
DESKTOP_SESSION_ENV = "PIXLSTASH_DESKTOP_SESSION"
|
|
363
|
+
|
|
364
|
+
def seed_desktop_session(self) -> Optional[str]:
|
|
365
|
+
"""Register a pre-authenticated owner session for the local desktop app.
|
|
366
|
+
|
|
367
|
+
When PixlStash runs inside the Electron desktop shell, the shell
|
|
368
|
+
generates a high-entropy token once per launch, passes it to the server
|
|
369
|
+
via the ``PIXLSTASH_DESKTOP_SESSION`` env var, and injects the same value
|
|
370
|
+
as the ``session_id`` cookie in its own ``BrowserWindow``. Seeding the
|
|
371
|
+
token into :attr:`active_session_ids` here means the local window opens
|
|
372
|
+
straight into the library with no login/registration prompt.
|
|
373
|
+
|
|
374
|
+
This affects only the loopback owner: remote browsers and API clients
|
|
375
|
+
present a *different* cookie/token and continue to authenticate via the
|
|
376
|
+
normal password login (:meth:`login`) or share tokens. Returns the
|
|
377
|
+
seeded token, or ``None`` when no (valid) token was supplied.
|
|
378
|
+
"""
|
|
379
|
+
token = os.environ.get(self.DESKTOP_SESSION_ENV, "").strip()
|
|
380
|
+
if not token:
|
|
381
|
+
return None
|
|
382
|
+
# Guard against a weak/guessable token leaking owner access. The shell
|
|
383
|
+
# always supplies a 32+ char random token; reject anything shorter.
|
|
384
|
+
if len(token) < 16:
|
|
385
|
+
self._logger.warning(
|
|
386
|
+
"Ignoring %s: token too short (expected >=16 chars).",
|
|
387
|
+
self.DESKTOP_SESSION_ENV,
|
|
388
|
+
)
|
|
389
|
+
return None
|
|
390
|
+
user = self.ensure_user()
|
|
391
|
+
if not user or user.id is None:
|
|
392
|
+
self._logger.error(
|
|
393
|
+
"Could not seed desktop session: failed to ensure an owner user."
|
|
394
|
+
)
|
|
395
|
+
return None
|
|
396
|
+
self.active_session_ids[token] = user.id
|
|
397
|
+
self._desktop_session_token = token
|
|
398
|
+
self._logger.info(
|
|
399
|
+
"Seeded a pre-authenticated desktop session for the local owner."
|
|
400
|
+
)
|
|
401
|
+
return token
|
|
402
|
+
|
|
343
403
|
def set_password_hash(self, hashed_password: str):
|
|
344
404
|
def update_user(session: Session):
|
|
345
405
|
user = session.exec(select(User)).first()
|
|
@@ -1239,6 +1299,23 @@ class AuthService:
|
|
|
1239
1299
|
session_id = request.cookies.get("session_id")
|
|
1240
1300
|
user_id = self.active_session_ids.get(session_id) if session_id else None
|
|
1241
1301
|
|
|
1302
|
+
# The seeded Electron desktop owner session is loopback-only: the
|
|
1303
|
+
# window talks to the backend over 127.0.0.1, so this high-privilege
|
|
1304
|
+
# session must never grant access on the optional external listener
|
|
1305
|
+
# (even though the cookie is scoped to the loopback origin and so is
|
|
1306
|
+
# not normally sent there — this is the fail-closed backstop). Drop
|
|
1307
|
+
# it for non-local clients and let normal token auth take over.
|
|
1308
|
+
if (
|
|
1309
|
+
user_id is not None
|
|
1310
|
+
and session_id == self._desktop_session_token
|
|
1311
|
+
and not is_local_ip(self._get_real_client_ip(request))
|
|
1312
|
+
):
|
|
1313
|
+
self._logger.warning(
|
|
1314
|
+
"Rejected desktop owner session from non-local IP %s.",
|
|
1315
|
+
self._get_real_client_ip(request),
|
|
1316
|
+
)
|
|
1317
|
+
user_id = None
|
|
1318
|
+
|
|
1242
1319
|
if user_id is not None:
|
|
1243
1320
|
# Cookie session — full owner access, no scope restriction
|
|
1244
1321
|
request.state.auth_user_id = user_id
|
|
@@ -38,6 +38,12 @@ class Face(SQLModel, table=True):
|
|
|
38
38
|
)
|
|
39
39
|
bbox_: Optional[str] = Field(sa_column=Column("bbox", String, default=None))
|
|
40
40
|
features: Optional[bytes] = None
|
|
41
|
+
# Name of the InsightFace model pack that produced this face's embedding
|
|
42
|
+
# (e.g. "buffalo_l" or "auraface"). Nullable for rows created before the
|
|
43
|
+
# column existed; backfilled to "buffalo_l" by the Alembic migration.
|
|
44
|
+
model_pack: Optional[str] = Field(
|
|
45
|
+
sa_column=Column("model_pack", String, default=None)
|
|
46
|
+
)
|
|
41
47
|
|
|
42
48
|
# Relationships
|
|
43
49
|
picture: Optional["Picture"] = Relationship(
|