|
@@ -3,6 +3,7 @@
|
|
|
## Notes
|
|
## Notes
|
|
|
- First-time setup: `fastapi`/`uvicorn`/`starlette` are listed in `requirements.txt` but are not installed by default in a fresh `.venv` — run `pip install -r requirements.txt` before running the API.
|
|
- First-time setup: `fastapi`/`uvicorn`/`starlette` are listed in `requirements.txt` but are not installed by default in a fresh `.venv` — run `pip install -r requirements.txt` before running the API.
|
|
|
- `ComponentCategory.other` maps to an empty subcategory list in `suppliers/lcsc/categories.py:89` (`_SUBCATEGORY_NAMES[other] = []`) — rows classified as `other` can never resolve to an LCSC subcategory. Needs a taxonomy decision (which LCSC categories represent the catch-all), not a code fix.
|
|
- `ComponentCategory.other` maps to an empty subcategory list in `suppliers/lcsc/categories.py:89` (`_SUBCATEGORY_NAMES[other] = []`) — rows classified as `other` can never resolve to an LCSC subcategory. Needs a taxonomy decision (which LCSC categories represent the catch-all), not a code fix.
|
|
|
|
|
+- `suppliers/lcsc/lcsc.py`'s original scraper (`lcsc.com/api/products/search` via CSRF session) was previously marked Done but was never actually verified live — it returns the Nuxt SSR shell, not JSON. Replaced with LCSC's real internal API (`wmsc.lcsc.com/ftps/wm/product/query/*`), found via live browser traffic capture and verified end-to-end.
|
|
|
|
|
|
|
|
## Done
|
|
## Done
|
|
|
|
|
|
|
@@ -26,6 +27,18 @@
|
|
|
- [x] `suppliers/lcsc/category_cache.json` — file-backed resolution cache (69 entries)
|
|
- [x] `suppliers/lcsc/category_cache.json` — file-backed resolution cache (69 entries)
|
|
|
- [x] `suppliers/lcsc/product_lookup.py`, `scout_ground_truth.py`, `eval_ground_truth.py` — ground-truth harness (60 rows from real LCSC part numbers) + accuracy eval
|
|
- [x] `suppliers/lcsc/product_lookup.py`, `scout_ground_truth.py`, `eval_ground_truth.py` — ground-truth harness (60 rows from real LCSC part numbers) + accuracy eval
|
|
|
- Current accuracy: **top-1 68% (41/60), top-3 88% (53/60)**
|
|
- Current accuracy: **top-1 68% (41/60), top-3 88% (53/60)**
|
|
|
|
|
+- [x] Verified live: `categories.json` subcategory ids are directly usable as `catalogIdList` values against LCSC's real search/facet API — no remapping layer needed
|
|
|
|
|
+
|
|
|
|
|
+### API + Frontend (backbone)
|
|
|
|
|
+- [x] `api/main.py` — FastAPI app entry point
|
|
|
|
|
+- [x] `POST /upload` — ingest file, return BomSession (HTMX-rendered row table)
|
|
|
|
|
+- [x] `GET /session/{id}/row/{row_id}/scout` — LLM category inference, HTMX-rendered candidate list
|
|
|
|
|
+- [x] `bom_assistant/scouting/` — framework-agnostic orchestrator (`build_session`, `scout_row`) backing the above
|
|
|
|
|
+- [x] HTMX-based test page (`api/templates/`, server-rendered by FastAPI, no separate frontend process) for interactively testing category inference
|
|
|
|
|
+
|
|
|
|
|
+### LCSC Search Adapter
|
|
|
|
|
+- [x] `suppliers/lcsc/lcsc.py` — `search()` against LCSC's real internal API (`wmsc.lcsc.com/ftps/wm/product/query/list`), reverse-engineered from live browser traffic; previous `lcsc.com/api/products/search` scraper endpoint was stale/never worked (returned the Nuxt SSR shell, not JSON) — no CSRF/session dance needed for the real endpoint
|
|
|
|
|
+- [x] `suppliers/lcsc/lcsc.py` — `query_facets()` against `wmsc.lcsc.com/ftps/wm/product/query/param/group`: returns Package/Manufacturer/Packaging + per-param value lists, scoped to category + already-applied filters — this is the source for building filter chips each scouting round, no scraping or manual aggregation needed
|
|
|
|
|
|
|
|
### Bug Fixes
|
|
### Bug Fixes
|
|
|
- [x] Double-space header normalization (`_normalize_key` collapses whitespace) — fixed `Ref Des (Multi-4)` mismatch
|
|
- [x] Double-space header normalization (`_normalize_key` collapses whitespace) — fixed `Ref Des (Multi-4)` mismatch
|
|
@@ -43,20 +56,16 @@
|
|
|
- [ ] Persian-header BOM support — AI column mapping for non-Latin headers (currently returns 0 rows)
|
|
- [ ] Persian-header BOM support — AI column mapping for non-Latin headers (currently returns 0 rows)
|
|
|
|
|
|
|
|
### LCSC Search Adapter
|
|
### LCSC Search Adapter
|
|
|
-- [x] `suppliers/lcsc/lcsc.py` — scraper mode: CSRF session + POST to `lcsc.com/api/products/search`
|
|
|
|
|
- [ ] `suppliers/lcsc/lcsc.py` — official API mode (`_search_official`) still a stub, raises `NotImplementedError`; needs HMAC signing + LCSC API key
|
|
- [ ] `suppliers/lcsc/lcsc.py` — official API mode (`_search_official`) still a stub, raises `NotImplementedError`; needs HMAC signing + LCSC API key
|
|
|
|
|
|
|
|
### Scouting Loop
|
|
### Scouting Loop
|
|
|
-- [ ] Scouting orchestrator — drive pending rows through scouting → filtering → confirmed
|
|
|
|
|
-- [ ] BomRow state machine transitions wired to category resolver + search adapter
|
|
|
|
|
|
|
+- [ ] BomRow state machine transitions for `filtering`/`confirmed` wired to `query_facets()` + `search()` (data layer for both is ready and live-verified, see Done)
|
|
|
- [ ] Retry / re-scout flow when user rejects results or picks a different category
|
|
- [ ] Retry / re-scout flow when user rejects results or picks a different category
|
|
|
|
|
|
|
|
### API
|
|
### API
|
|
|
-- [ ] FastAPI app entry point (`api/main.py`)
|
|
|
|
|
-- [ ] `POST /upload` — ingest file, return BomSession
|
|
|
|
|
- [ ] `GET /session/{id}` — return session state
|
|
- [ ] `GET /session/{id}` — return session state
|
|
|
-- [ ] `GET /session/{id}/row/{row_id}/scout` — LLM category inference, return `{subcategory, alternatives[]}`
|
|
|
|
|
-- [ ] `POST /session/{id}/row/{row_id}/confirm-category` — lock LCSC subcategory, advance state to filtering — **deferred** until category inference is validated interactively (only inference itself has been tested so far, not the full loop)
|
|
|
|
|
|
|
+- [ ] `GET /session/{id}/row/{row_id}/facets` — call `query_facets()`, return filter chip groups — **deferred** until category inference is validated interactively (only inference itself has been tested so far, not the full loop)
|
|
|
|
|
+- [ ] `POST /session/{id}/row/{row_id}/confirm-category` — lock LCSC subcategory, advance state to filtering — **deferred**, same reason
|
|
|
- [ ] `POST /session/{id}/row/{row_id}/search` — search within confirmed category + param filters — **deferred**, same reason
|
|
- [ ] `POST /session/{id}/row/{row_id}/search` — search within confirmed category + param filters — **deferred**, same reason
|
|
|
- [ ] `POST /session/{id}/row/{row_id}/confirm` — lock part pick, advance state to confirmed — **deferred**, same reason
|
|
- [ ] `POST /session/{id}/row/{row_id}/confirm` — lock part pick, advance state to confirmed — **deferred**, same reason
|
|
|
- [ ] `GET /session/{id}/export` — collate confirmed picks → downloadable BOM — **deferred**, same reason
|
|
- [ ] `GET /session/{id}/export` — collate confirmed picks → downloadable BOM — **deferred**, same reason
|
|
@@ -67,9 +76,7 @@
|
|
|
- [ ] Nexar adapter
|
|
- [ ] Nexar adapter
|
|
|
|
|
|
|
|
### Frontend
|
|
### Frontend
|
|
|
-- [ ] HTMX-based test page (server-rendered by FastAPI, no separate frontend process) for interactively testing category inference — backbone, in progress
|
|
|
|
|
-- [ ] React scaffold + build setup — deferred until the scouting loop is validated; HTMX test page covers interim needs
|
|
|
|
|
-- [ ] Upload page
|
|
|
|
|
|
|
+- [ ] React scaffold + build setup — deferred until the scouting loop is validated; HTMX test page (see Done) covers interim needs
|
|
|
- [ ] Row-by-row scouting UI (category dropdown, results grid, confirm/reject)
|
|
- [ ] Row-by-row scouting UI (category dropdown, results grid, confirm/reject)
|
|
|
- [ ] Session progress view (rows confirmed vs pending)
|
|
- [ ] Session progress view (rows confirmed vs pending)
|
|
|
- [ ] Export button
|
|
- [ ] Export button
|