fix: dedup race, cwd-relative image paths, unencoded legacy URLs

- SQLite dedup race: add UNIQUE(collection_name, file_hash) and switch
  save_document to a plain INSERT. add_document now catches the
  IntegrityError from a concurrent add of the same content, cleans up its
  managed files, and returns the winning doc_id — instead of two doc_ids
  for one file (each having paid for its own LLM indexing).

- PDF image paths: store the absolute path to each extracted image
  instead of a path relative to the indexing process's cwd. The
  ![image](...) references broke as soon as a query ran from a different
  directory.

- LegacyCloudAPI: URL-encode doc_id / retrieval_id path segments (added
  _enc()), matching CloudBackend. An id containing '/', '?', '#' or a
  space previously hit the wrong endpoint or produced a malformed URL.

Adds regression tests: UNIQUE enforcement, the add-race resolving to the
winner, absolute image paths, and encoded legacy URLs.

Claude-Session: https://claude.ai/code/session_01Kx5DgKbhK1N8autqXH8SmS
This commit is contained in:
mountain 2026-07-07 12:06:58 +08:00
parent fe36e25773
commit b3616f76a2
8 changed files with 123 additions and 15 deletions

View file

@ -48,11 +48,10 @@ class PdfParser:
"""
images_path = Path(images_dir)
images_path.mkdir(parents=True, exist_ok=True)
# Use path relative to cwd so downstream consumers can access directly
try:
rel_images_path = images_path.relative_to(Path.cwd())
except ValueError:
rel_images_path = images_path
# Store an absolute path so the ![image](...) reference resolves
# regardless of the process's cwd at query time. (cwd-relative paths
# break as soon as the query runs from a different directory.)
abs_images_path = images_path.resolve()
parts: list[str] = []
images: list[dict] = []
@ -87,13 +86,13 @@ class PdfParser:
except Exception:
continue
rel_path = str(rel_images_path / filename)
img_path = str(abs_images_path / filename)
images.append({
"path": rel_path,
"path": img_path,
"width": width,
"height": height,
})
parts.append(f"![image]({rel_path})")
parts.append(f"![image]({img_path})")
img_idx += 1
content = "\n".join(parts)