Commit graph

34 commits

Author SHA1 Message Date
LLLin000
508ef78d51 feat(#81, #82): Release N+1/2 cutover — remove setup_complete, auto_update, legacy migration, deprecated build-state JSON writer
#81 (N+1) remaining:
- settings.ts: _resolveRuntimeCommand fail-closed (no getCachedPython fallback)
- managed-runtime.ts: PYTHON_310_DEPRECATED warning removed, single 3.11+ gate
- Python backend: checker/setup_wizard/status → 3.11 minimum
- i18n: 3.10 → 3.11 user-facing strings

#82 (N+2) deletions:
- constants.ts: removed setup_complete, auto_update, auto_update_on_startup, selected_skill_platform
- main.ts: removed _autoUpdate, _firstLaunchSnapshotMigration, credential migration
- modals.ts: removed setup_complete write
- settings.ts: removed categorizeMaintenanceRow dead import
- build_state.py: removed deprecated get_vector_build_state_path

Build: 261.4KB | Tests: 384/384 passed | Typecheck: clean
2026-07-19 14:54:19 +08:00
LLLin000
2dab3d11ad fix: health probe uses detect_embedding_dim instead of hardcoded 1536 2026-07-11 00:28:49 +08:00
LLLin000
e7a030d057 refactor: remove ChromaDB dependency gating from status and preflight
Embed status no longer checks for chromadb import — vec0 runs in
paperforge.db and doesn't need the ChromaDB library. The preflight
check also no longer requires chromadb since vec0 backends do not
depend on it. The chroma_backend module remains for legacy test
compatibility but no longer gates any production build/status path.
2026-07-10 23:57:33 +08:00
LLLin000
40326d6759 fix: add vec0 k-NN health probe to embed status
embed status now runs a zero-vector k-NN query on each vec0 table
that has companion meta rows. If the probe fails (table dropped,
extension unavailable, index corrupted), healthy=false and
corrupted=true are reported even when meta row counts > 0.

Includes integration test that drops vec_fulltext and verifies
healthy=false.
2026-07-10 23:55:16 +08:00
LLLin000
65311fc1c5 fix(status): handle read-only DB during concurrent build
get_embed_status opens a read-only connection that cannot load the
vec extension when another process has the DB locked. ensure_vec_extension
failure is now non-fatal — the status query proceeds with vec0 meta
table reads, which work in read-only mode.
2026-07-10 02:48:51 +08:00
LLLin000
6348869941 feat: runtime embedding dimension detection
dim_detect.detect_embedding_dim() calls the embedding API once to
determine the model's output dimension. ensure_vec_tables() drops
and recreates vec0 tables when the dimension changes, so the schema
always matches the user's model (1536 for ada-002, 2560 for Qwen,
3072 for text-embedding-3-large, etc.).
2026-07-10 02:48:26 +08:00
LLLin000
4ff165ae49 feat(#38, #40): version history panel + @ Deep Search
#38: File Recovery-style version history panel with i18n (en/zh).
- _renderVersionMode() with paper list + timeline + restore/compare
- version-history.ts service for scan/restore/compare
- Paper mode [版本历史] button
- i18n strings for all panel text

#40: @ Deep Search with query rewrite + hybrid retrieval.
- query_rewrite.py: abbreviation expansion (28 terms) + synonyms (12)
- hybrid_search(): BM25 FTS5 + vec0 k-NN + score fusion (0.3/0.7)
- retrieve --deep flag routes to hybrid_search
- Graceful vec0 fallback (FTS5-only)
- 17 new tests

Co-authored-by: VersionPanel <agent>
Co-authored-by: DeepSearch <agent>
2026-07-10 01:01:48 +08:00
LLLin000
06fec04651 feat: Phase 0, 1, 3a — legacy OCR fix, ChromaDB migration, search bar UI
Phase 0 (#35): _needs_derived_rebuild returns (False, 'legacy_ocr') for
papers without structured blocks and derived_version. _can_rebuild adds
has_structured check. No misleading rebuild suggestions for legacy users.

Phase 1 (#36): migrate_chroma_to_vec0() copies existing ChromaDB vectors
to vec0 tables with zero API calls. Idempotent (skips by paper_id).
delete_paper_vectors() cleans both ChromaDB and vec0. CLI: embed migrate.
5 new tests.

Phase 3a (#39): Search bar in collection panel — two-mode input
(M metadata / @ deep) with card results display. JSON output parsed
from search/retrieve CLI. 289 lines TypeScript, 175 lines CSS.
Build passes clean.

Co-authored-by: Phase0LegacyOcr <agent>
Co-authored-by: ChromaMigration <agent>
Co-authored-by: SearchBarUI <agent>
2026-07-10 00:02:02 +08:00
LLLin000
d24c78c5dc feat(#27 #28 #29 #30 #32): migrate write/read/status/build_state from ChromaDB to sqlite-vec
#27: write_encoded_payload and delete_paper_vectors use sqlite-vec
  - builder.py: writes to vec0 tables + companion meta tables
  - _chroma.py: delete_paper_vectors deletes from vec0 + meta by paper_id
  - Stores body_units_hash, object_units_hash, retrieval_policy_version in meta tables

#28: merge_retrieve and retrieve_chunks use vec0 k-NN search
  - search.py: vec0 k-NN queries with companion meta JOINs
  - Same dedup/per-paper-cap logic, same result shapes

#29: build_state migrated from JSON file to SQLite build_state table

#30: E2E embed+retrieve test with sqlite-vec + FixedProvider
  - 3 tests: body roundtrip, source correctness, per-paper cap

#32: E2E OCR pipeline test with fixture PDFs

Additional changes:
- schema.py: bump to v6, add hash/policy columns to vec companion meta tables
- embed.py: _assert_collections_healthy uses sqlite-vec; resume hash checks read from meta tables
- status.py: chunk counts from SQL COUNT on companion tables
- Removed unused get_collection/embed_paper imports from embed.py
- All tests updated: 76 pass (was 72, +4 new E2E tests, +4 for migration)
- FixedFixedProvider to generate 1536-dim vectors (matching vec0 schema)
- Fixed health check tests for sqlite-vec path
2026-07-09 17:52:45 +08:00
LLLin000
49f84a1aad feat(#31): OpenAICompatibleProvider uses openai SDK with requests fallback
Rewrite embedding provider to use openai.OpenAI client instead of
raw requests.post. Old code preserved in requests_fallback.py,
selectable via VECTOR_DB_PROVIDER_TYPE env/setting.

Changes:
- paperforge/embedding/providers/openai_compatible.py: rewrite to SDK
- paperforge/embedding/providers/requests_fallback.py: NEW old impl
- paperforge/embedding/_config.py: add get_provider_type()
- tests/test_openai_compatible.py: 6 new tests (encode, timeout,
  provider_type switch, no-key error, custom base url)

feat(#33): E2E test fixtures — 3 synthetic PDFs + expected outputs

3 synthetic papers generated with PyMuPDF, each 3 pages:
- paper_a: The Effect of Machine Learning on Clinical Outcomes
- paper_b: A Randomized Trial of Remimazolam vs Propofol (with tables)
- paper_c: Deep Learning for Medical Image Segmentation (with figures)

Changes:
- tests/fixtures/papers/: 3 PDFs
- tests/fixtures/expected_outputs/: expected blocks + body units
- tests/conftest.py: e2e_fixture_dir + synthetic_paper_paths fixtures

feat(#26): sqlite-vec schema — vec0 virtual tables + build_state

Schema version bumped 4→5. Adds:
- 3 vec0 virtual tables: vec_fulltext, vec_body, vec_objects (1536-dim)
- 3 companion metadata tables: vec_*_meta (paper_id, chunk_index, text)
- build_state table (key/value/updated_at)
- ensure_vec_extension() in db.py for extension loading

Changes:
- paperforge/memory/schema.py: schema v5, new tables in ensure_schema()
- paperforge/memory/db.py: ensure_vec_extension() helper
- tests/test_vector_schema.py: 5 new tests (tables, virtual, idempotent, v5)
2026-07-09 17:15:19 +08:00
LLLin000
a588bd884a fix(#18): atomic build_state writes with .tmp fallback recovery
test(#17): integration tests for embed pipeline against EphemeralChromaDB

- build_state: write to .tmp first, leave as backup; read falls back to
  .tmp if main file corrupt. Extracted default/fallback state helpers.
- integration: 10 tests covering payload prep, encode→write→retrieve
  round-trip for all 3 collections, per-paper cap, delete, and
  encode_paper_job — all against real ChromaDB EphemeralClient with
  mocked provider
2026-07-09 02:03:20 +08:00
LLLin000
cc064bd74a fix: address 5 PR9 embedding pipeline issues from triage
- #13: Critical — swap delete/write order in _complete_one (write new
  vectors before deleting old ones) to prevent data loss on write failure
- #12: Add logger.warning() to 3 resume-skip except blocks so silent
  re-embed fallbacks are observable
- #14: Add lightweight HNSW query probe to _assert_collections_healthy
- #11: Log collection query failures in merge_retrieve instead of silent
  continue
- #16: Reuse provider across payloads in encode_paper_job — one creation
  per worker per paper instead of per payload
2026-07-09 01:46:22 +08:00
LLLin000
9c85b30d7f fix: write_vector_build_state fallback when file locked
Windows: tmp.replace(path) fails when Obsidian plugin is reading
vector-build-state.json. Fall back to direct write to avoid crashing
the embed build. Stale tmp files cleaned up lazily.
2026-07-07 02:12:27 +08:00
LLLin000
a71796536a fix: OpenAICompatibleProvider uses requests instead of openai client
The openai Python client (v2.44.0) has compatibility issues with
SiliconFlow API — calls hang indefinitely even with TCP keepalive.
Replace with plain requests, which is simpler and works reliably.

- Removed openai/httpx/socket dependencies
- Uses requests.post() directly, 60s timeout
- ~0.3s per batch vs 2.3s+ with openai client
2026-07-06 23:15:58 +08:00
LLLin000
6ff0f6d38b PR9B: Embed Parallel Encode
- Four new dataclasses: EmbeddingPayload, EncodedPayload, PaperEmbeddingJob, PaperEncodedBundle
- prepare_legacy/body/object_payload: extract prepare phase from legacy embed functions
- encode_payload / encode_paper_job: worker-thread-safe encode functions
- write_encoded_payload: ChromaDB serial write
- prepare_payloads_for_entry: routing to correct prepare function
- Existing embed_body_units/embed_paper/embed_object_units refactored as wrappers
- Embed main loop: three-phase pipeline (PREPARE -> ENCODE -> WRITE) with ThreadPoolExecutor
- Bounded batch processing (BATCH_SIZE=8, MAX_WORKERS=4)
- Encode-success-gated delete: old vectors only removed after encode succeeds
- 23 regression tests for new functions
2026-07-06 22:41:25 +08:00
LLLin000
6afcdc1830 fix: PR8.1 — status healthy init + object_units rebuild + version bump
- status.py: healthy=True init before if exists: (was UnboundLocalError
  when vector DB doesn't exist)
- manifest.py: RETRIEVAL_POLICY_VERSION l4.body.v1 → l4.body.v2 to
  trigger object_units rebuild with PR7 fix (unit_id fallback)
- Object_units corrected from 20→311 after rebuild (was INSERT OR
  REPLACE overwrite from old empty unit_id)
- Coverage parity: 20 papers have body_units = 20 have object_units 
  (body=811 chunks, object=311 chunks, expected difference due to
   section-split vs 1:1 caption structure)
- Unit tests: 97 pass (subset)
2026-07-06 20:08:51 +08:00
LLLin000
0dfbf2a68d feat: PR 8 — Object Vector Retrieval (paperforge_objects collection)
New paperforge_objects collection in ChromaDB for figure/table caption
vector search, completing the memory layer retrieval triad:

  paperforge_fulltext → legacy_chunk
  paperforge_body     → body_unit
  paperforge_objects  → object_unit (NEW)

Changes:
- manifest.py: compute_object_units_hash(), manifest records both hashes
- _chroma.py: _COLLECTION_NAMES includes paperforge_objects
- builder.py: get_object_units_for_embedding() + embed_object_units()
- status.py: object_chunk_count, total_chunks
- state_snapshot.py: write_vector_runtime() extended with new fields
- search.py: 3rd collection, dict-based source mapping, object_kind/label
- __init__.py: exports for new functions
- commands/embed.py: _has_object_units_in_db, body+object structured
  path routing with dual-hash resume, extended counters
- Test fix: test_build_paper_manifest data complete for hash functions

Verification: 20 object vectors embedded, all per-paper counts match,
status total consistent (58266 = 57435 + 811 + 20),
object caption queries return object_unit results via merge_retrieve.
Unit tests: 153 pass, 1 skip.
2026-07-06 19:58:46 +08:00
LLLin000
9f79ac3482 fix: hardening — FTS per-paper, object_units keys, unit_id collision, resume hash
P0-1: FTS per-paper insert — move SELECT INTO body_units_fts inside the
per-paper loop with WHERE paper_id = ? to avoid re-inserting other papers'
rows during full rebuild. Fix sqlite3.DatabaseError on empty FTS table.

P0-2: object_units real role_index keys — read from 'captions'/'tables'
(what build_role_indexes actually outputs) with fallback to old key names.

P1-1: unit_id collision for mixed body/backmatter — include unit_kind
suffix (:backmatter_body) in unit_id. Also fix duplicate tree node_ids
(block_id reused on different pages) by appending order{emitted_order}.

P1-2: Embed resume body_units_hash — add compute_body_units_hash() to
manifest.py, write hash + retrieval_policy_version to Chroma metadata,
resume compares both before skipping.
2026-07-06 16:56:33 +08:00
LLLin000
9f47245179 feat: PR 4 — Dual collection embedding with body_units
- get_collection(name=) supports paperforge_fulltext or paperforge_body
- delete_paper_vectors deletes from both collections
- embed_body_units + get_body_units_for_embedding (reads from memory DB)
- Status reports chunk_count, body_chunk_count, total_chunks
- Embed build routes to body_units path when DB has body_units
- merge_retrieve queries both collections with unit-level dedup
2026-07-06 16:42:54 +08:00
LLLin000
e23f35114c feat: add LanceDB evaluation backend scaffold 2026-07-05 14:19:37 +08:00
LLLin000
b9f4d6c4f0 refactor: add vector backend adapter with Chroma compatibility 2026-07-05 14:13:59 +08:00
Research Assistant
19c28a8b91 chore: commit session work before hotfix switch 2026-05-18 22:47:30 +08:00
Research Assistant
baa6c758f5 fix(vector): get_collection no longer silently deletes collection on error; memory builder skips full rebuild when index hash matches 2026-05-18 22:18:23 +08:00
Research Assistant
add220d93c feat(discussion): remove JSON output and markdown escaping 2026-05-18 21:09:54 +08:00
Research Assistant
402b0cadc7 feat(embedding): add API-only preflight check 2026-05-18 17:18:04 +08:00
Research Assistant
754365c60f feat(embedding): add get_embed_status() for API-only mode 2026-05-18 17:17:26 +08:00
Research Assistant
711be5e5bb feat(embedding): add API-only retrieve_chunks() semantic search 2026-05-18 17:16:51 +08:00
Research Assistant
22bf7fb1f5 feat(embedding): add API-only embed_paper() builder 2026-05-18 17:16:15 +08:00
Research Assistant
9b1221ee12 feat(embedding): add build state persistence 2026-05-18 17:15:40 +08:00
Research Assistant
2509fe595e feat(embedding): add ChromaDB collection manager (store only) 2026-05-18 17:14:50 +08:00
Research Assistant
1490ca1109 feat(embedding): add OpenAI-compatible embedding provider 2026-05-18 17:14:18 +08:00
Research Assistant
265419c14e feat(embedding): add EmbeddingProvider ABC 2026-05-18 17:13:40 +08:00
Research Assistant
1329a9ab79 feat(embedding): add config reader for API settings 2026-05-18 17:13:16 +08:00
Research Assistant
d965976832 feat(embedding): create embedding package skeleton 2026-05-18 17:12:14 +08:00