Skip to content

[codex] Sync upstream updates with NAS photo-processing fixes#53

Draft
rowankid wants to merge 18 commits into
LC044:masterfrom
rowankid:codex/sync-official-nas-fixes
Draft

[codex] Sync upstream updates with NAS photo-processing fixes#53
rowankid wants to merge 18 commits into
LC044:masterfrom
rowankid:codex/sync-official-nas-fixes

Conversation

@rowankid
Copy link
Copy Markdown

Summary

This PR merges the latest upstream master changes into the NAS/photo-processing branch and keeps the local fixes that were developed while running TrailSnap on a Synology NAS.

Key local fixes preserved in the merge:

  • add NAS Docker Compose setup and Synology Photos mount support
  • point NAS server to the Mac AI service when configured
  • improve photo time recovery from EXIF/path/filename before falling back to filesystem mtime
  • stabilize cleanup pagination ordering and add RAW companion deletion on permanent delete
  • skip Synology @eaDir and #recycle metadata directories during folder scans
  • harden visual description JSON parsing and keep Mimo-compatible request behavior

Upstream changes merged include the v0.4.0 updates, built-in AI/LLM work, toolbox organize/rename/time-from-filename features, frontend updates, and dependency bumps.

Notes

Merge conflicts were resolved in:

  • package/server/app/api/toolbox.py
  • package/server/app/service/task_worker.py
  • package/server/app/service/tasks/visual_description.py

The task worker keeps upstream priority-aware queue fetching while preserving the conservative NAS-friendly queue/concurrency behavior.

Validation

  • PYTHONPATH=. ./.venv/bin/python tests/test_scan_filters.py
  • PYTHONPATH=. ./.venv/bin/python tests/test_photo_time_extraction.py
  • python -m py_compile package/server/app/api/toolbox.py package/server/app/service/task_worker.py package/server/app/service/tasks/visual_description.py package/server/app/service/tasks/scan.py
  • pnpm -C package/website build

The frontend build completed successfully. It still reports existing Vite warnings about stale Browserslist data, unresolved /icon/backpack.svg at build time, mixed dynamic/static import of src/stores/user.ts, and large chunks.

@LC044
Copy link
Copy Markdown
Owner

LC044 commented May 29, 2026

你更新了哪些内容

@LC044
Copy link
Copy Markdown
Owner

LC044 commented May 29, 2026

你更新了哪些内容

建议先新建一个issues,然后关联issue发起对应的pr,每次不要修改太多东西

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR merges upstream master (v0.4.0-era changes) into the NAS/photo-processing branch while preserving NAS-specific operational fixes (Synology scan filters, safer task execution, improved timestamp recovery, cleanup stability, and more robust visual description handling).

Changes:

  • Stabilizes cleanup pagination (backend ordering + frontend dedupe) and adds route redirects for the People album.
  • Improves photo/video timestamp recovery (EXIF parsing hardening, folder/filename fallback, optional ffprobe creation_time) and adds tests for scan filters + time extraction.
  • Extends server operations for NAS deployments (task worker queue/concurrency behavior, RAW companion deletion, tag merge/rename/delete APIs, and NAS compose configs).

Reviewed changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
package/website/src/views/toolbox/CleanupPage.vue Client-side dedupe for pagination results; adjusts skip increment based on response size.
package/website/src/router/index.ts Adds /people and /people/:id redirects to /album/people.
package/website/src/components/home/FaceSection.vue Updates People album navigation path.
package/server/app/utils/filename.py Adds date-only filename parsing patterns (YYYY-MM-DD / YYYYMMDD).
package/server/app/utils/exif.py Adds multi-source photo_time recovery pipeline (+ photo_time_source) including optional ffprobe extraction.
package/server/app/service/tasks/visual_description.py Hardens JSON parsing from model responses and adds provider-specific client behavior.
package/server/app/service/task_worker.py Updates queue fetch thresholds and per-category concurrency behavior.
package/server/app/crud/tag.py Adds delete/rename/merge tag operations.
package/server/tests/test_scan_filters.py Test coverage for Synology @eaDir scan skipping.
package/server/tests/test_photo_time_extraction.py Test coverage for filename/path EXIF time extraction helpers.
docker-compose.nas.yml Adds NAS-focused Docker Compose configuration and mounts.
docker-compose.local.yml Adds local compose configuration.
.gitignore Updates ignored runtime/state directories (e.g., pg_data, backups).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 1 to 5
from app.service.task_strategy import BaseTaskStrategy, TaskStrategyFactory
from app.db.models.task import TaskType, DEFAULT_PRIORITIES
from typing import List, Dict
import logging
import os
Comment on lines 382 to +391
# Configure max concurrency per consumer category based on system settings
# or Fast Mode. Using Semaphores to allow multiple batches to run concurrently.
max_concurrency = 1
configured_workers = max(1, system_config.config.task.max_concurrent_tasks)
if category == 'CPU':
max_concurrency = os.cpu_count() or 4
max_concurrency = configured_workers
elif category == 'IO':
max_concurrency = 4
max_concurrency = configured_workers
elif category == 'AI':
max_concurrency = 1
max_concurrency = configured_workers
Comment on lines +412 to +417
# 5. Fallback to filesystem mtime
if metadata["photo_time"] is None:
photo_time = get_file_time_form_system(file_path)
metadata["photo_time"] = photo_time
metadata["photo_time_source"] = "file_mtime"

Comment on lines +239 to +248
source_relations = db.query(PhotoTagRelation).filter(
PhotoTagRelation.tag_id == source.id
).all()

for relation in source_relations:
target_relation = db.query(PhotoTagRelation).filter(
PhotoTagRelation.photo_id == relation.photo_id,
PhotoTagRelation.tag_id == target.id
).first()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants