Spaces:
Running
Running
Commit History
-
merge: v3.0 frontend β main Running
3838059 -
feat(frontend): v3.0 β project-first 3-step wizardβ
- Rewrite landing to health-badge + 4 entry tiles - /projects list (GET /projects), /projects/new form (POST /projects) - /projects/{id} 3-step wizard: - Step A BlueprintsPanel β multi-upload to project (POST /uploads/blueprint) - Step B DocumentationPanel β GET /dokumentatsiya + POST /extract-all with Cached badge when aggregate_sha256 matches last_summary, Run button otherwise - Step C SheetVisionPanel β POST /extract-sheets w/ (upload_id, page_no) pairs - /documents β template picker + .docx render & download (POST /documents/render) - /history β GET /inference/history with project_id chip filter - lib/api.ts: add v2.0 types & 6 new functions (listProjectUploads, projectDokumentatsiya, extractProjectAll, extractProjectSheetsV2, uploadBlueprintV2) + UploadRow/DokumentatsiyaResponse - Drop legacy /blueprint single-upload flow4308ec9
-
feat: v2.0 β project-aware blueprint aggregationβ
Adds four endpoints scoped to /projects/{id}/: GET /projects/{id}/uploads β lists every blueprint upload belonging to the project; each entry includes upload_id, file_name, sha256, page_count, has_native_text, status. Used by the UI to surface the "uploaded files" panel before triggering an extract. GET /projects/{id}/dokumentatsiya β pure-data aggregation of all uploads (no LLM call). Returns the full ProjectBlueprintSnapshot: per-upload metadata, per-page stamps/titles/empty-filters, aggregate_sha256, overall_project_section. Mirrors what a /extract-all call would compute, but served instantly from Supabase rows. POST /projects/{id}/extract-all β text-only LLM pass over all pages of all uploads. Cache key = aggregate_sha256 (SHA of sorted upload shas). On cache hit (sha matches persisted value + last_summary exists) returns the cached ProjectSummary wβ¦2718788
-
chore(uploads): v1.0.4 β Qwen primary again, reasoning-mode as #1 fallbackβ
Live data from v1.0.3 (Nemotron-3-Nano-Omni-Reasoning primary) showed: - elapsed=114s for 3 pages (vs Qwen ~24s in v1.0.1) β on the edge of HF Space 60-s page budget. - sheets_index=1/3 (vs Qwen's 3/3 on the same tests/test.pdf). - object_name="Π¦Π΅Ρ ΡΠ΅Π»ΠΎΠΌΠ΅Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ" β partial misread of "ΡΠ΅Π»ΡΠ½ΠΎΠΌΠΎΠ»ΠΎΡΠ½ΠΎΠΉ ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠΈ" (Qwen reads the spec page correctly). - reasoning-mode is still useful: high quality description-only and severe content=null without chat_template_kwargs=0 (handled now). So this commit flips the chain back to: 1. qwen/qwen3.5-397b-a17b (primary β fast + accurate) 2. nvidia/nemotron-3-nano-omni-30b-a3b-reasoning (first fallback, NVIDIA-native) 3. nvidia/nemotron-nano-12b-v2-vl 4. meta/llama-3.2-90b-vision-instruct 5. meta/llama-3.2-11b-vision-instruct 6. microsoft/phi-4-multimodal-instruct (still DEGRADED @ NVIDIA) Two side-tweaks: - extract-sheets budget_s 45.0 β 75.0 (~3 retries Γ single_aβ¦60bae90 -
feat(llm): reasoning-aware chain β Nemotron-3-Omni-30B as primary VLMβ
Two-part change so the NVIDIA reasoning nodes work as vision-capable chat-completions models on the chain: (1) Reasoning-aware request building in app/services/llm.py._call_model_once - Detect reasoning nodes by name fragment (nvidia/nemotron-3-nano-omni*-reasoning, nvidia/cosmos-reason*, deepseek-r1*, openai/o1-*, openai/o3-*, qwen/qwq-*, microsoft/phi-4-reasoning). - When matched, attach payload["chat_template_kwargs"] = {"reasoning_effort": 0} so the model writes its final summary into `content` instead of leaving it in `reasoning_content` and emitting content=null. - Bump max_tokens 2000 -> 4000 for reasoning nodes (they burn tokens on the internal CoT before emitting user-visible text). - Robust response parsing: if content=null and reasoning_content holds a JSON-looking tail, recover it; if reasoning_content holds no JSON, fall back to its full text; if both null, raise _StructuredResponseError as β¦9c0909f -
chore(vlm): add nvidia/nemotron-nano-12b-v2-vl as VLM fallback #2β
After auditing the NVIDIA Build catalog we know: - text-only models on NVIDIA Build: gemma-3/4-*it, codegemma, deepseek-v4-flash - reasoning-only: nvidia/cosmos-reason2-8b (no /chat/completions vision support) - vision-capable: qwen/qwen3.5-397b-a17b, meta/llama-3.2-90b/11b-vision, microsoft/phi-4-multimodal, nvidia/nemotron-nano-12b-v2-vl, nvidia/llama-3.1-nemotron-nano-vl-8b-v1 Verified the new entry with a direct chat/completions probe: - model = nvidia/nemotron-nano-12b-v2-vl - inline data:image/png accepted, returns HTTP 200 Slot in v1.0.1 was the Qwen β Llama-3.2-90B β Llama-3.2-11B β Phi-4 chain. Now: Qwen β Nemotron-Nano-12B-VL (NVIDIA-native) β Llama-3.2-90B β ... This gives two independent NVIDIA-provided models in the chain so a Qwen 429 doesn't immediately drag us back to stub-vision β the next call hits Nemotron which lives on the same integration endpoint with no geo routing. Note: the chain description now explicitly warns against adding gemma-3/4/codegemma (textβ¦bdb8f0b -
feat(uploads): v1.0.1 β ground-truth section + empty-page filter + stamp validatorβ
Adds three reliability fixes to the D-light blueprint pipeline. No OCR was added β the fix is purely about not lying to the model. * project_section ground-truth - heuristic_section() scans the first ~80 lines for explicit phrasing ("ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΊΠΎΠΌΠΏΠ»Π΅ΠΊΡ ΡΠ΅ΡΡΠ΅ΠΆΠ΅ΠΉ: ΠΠΠ", "Π Π°Π·Π΄Π΅Π» ΠΏΡΠΎΠ΅ΠΊΡΠ° ΠΠ ") and falls back to scanning for known tokens (ΠΠ /ΠΠ/ΠΠ/ΠΠΠ/ΠΠ/ΠΠ/...). - extract_pages_text() aggregates to artifact.project_section. - /uploads/blueprint/{id}/extract-sheets injects this ground-truth into the VLM prompt as a hint, and falls back to it when the model returned nothing or something we couldn't validate β solves the "model returned ΠΠ but the doc is ΠΠΠ" report. * empty-page filter - ExtractedPage.is_empty + EMPTY_PAGE_TEXT_THRESHOLD (60 chars). - extract-sheets skips empty pages from the VLM chain but surfaces them in sheets_index with title_guess="(ΠΏΡΡΡΠΎ)" and notes the count in spec_summary so the UI doesn't think the page vanished. * stamp validβ¦84808f2 -
chore(vlm): swap primary VLM to qwen/qwen3.5-397b-a17bβ
VLM chain now leads with qwen3.5-397b-a17b, fallbacks retained: llama-3.2-90b-vision-instruct llama-3.2-11b-vision-instruct phi-4-multimodal-instruct Updated llm_vlm_chain default + Field description in app/core/config.py. Local: 12/12 tests pass.d2bc581
-
fix(uploads): extract-sheets falls back to preview cacheβ
Unblocks Phase-2 VLM endpoint when Supabase creds are absent (the HF Space demo env, for instance). Mirrors the same on-disk fallback the GET status and extract-text endpoints already use.3ed4461 -
feat(frontend): two-step blueprint flowβ
Moves the Next.js sources (lib/, configs, package manifest) from the project root down into frontend/ so the FastAPI app/ tree doesn't collide with the App Router. vercel.json now points at frontend/package.json. UI: / short explainer + entry /blueprint two-step flow step 1 β upload PDF / image β server extracts native text on all pages β page list with stamp + title excerpts. "Π‘Π²ΠΎΠ΄ΠΊΠ° ΠΏΠΎ ΡΠ΅ΠΊΡΡΡ" button calls /uploads/blueprint/{id}/extract-text which LLM-summarises the whole document. step 2 β multi-select pages β "VLM ΠΏΠΎ Π²ΡΠ±ΡΠ°Π½Π½ΡΠΌ (N)" button calls /uploads/blueprint/{id}/extract-sheets which runs the real VLM chain per selected page with sibling text context. lib/api.ts adds typed wrappers for all 5 new endpoints (uploadBlueprint, getBlueprintStatus, getPagePreview, extractProjectText, extractProjectSheets) plus matching request and response types. Page preview rendered inline as a datβ¦6d57e0d -
feat(uploads): wire extract-sheets to the real VLM chainβ
Replaces the placeholder stub in POST /uploads/blueprint/{id}/extract-sheets with a per-page vision_completion call against the configured vlm_chain. Sibling text (collect_text_window, span=2) is sent as user prompt context alongside the PNG data URL of the selected page. Per-page fallback keeps the response usable if one VLM call fails β aggregator rolls the successful instances into a single ProjectSummary and dedups missing_info_prompts. 5/5 smoke tests still pass.7d34787 -
feat(uploads): D-light blueprint pipeline (Phase-2, no OCR)β
Two-phase strategy for project documentation: Phase 1 β native-PDF text extraction over ALL pages via pypdfium2, persisted to new blueprint_uploads / blueprint_pages tables (Supabase). Stamp (ΠΠ -/ΠΠ-/...) and title heuristics applied per page. Phase 2 β VLM only on user-selected pages (POST /extract-sheets). The text-only LLM pass over all pages (POST /extract-text) produces object_name, address, section, sheets_index, spec_summary, missing_info_prompts. Endpoints: POST /uploads/blueprint accept PDF/JPG/HEIC GET /uploads/blueprint/{upload_id} status + page list GET /uploads/blueprint/{upload_id}/pages/{n}/preview PNG base64 POST /uploads/blueprint/{upload_id}/extract-text text-LLM summary POST /uploads/blueprint/{upload_id}/extract-sheets VLM on chosen pages Caps: 50 MB body, 64 pages, 200 KB text total budget. Preview cache unβ¦e10629e
-
fix(space): restore HF Spaces README front-matterβ
The pre-release commit removed the YAML front-matter at the top of README.md β HF reported `Missing configuration in README` (CONFIG_ERROR). Re-adding so HF picks up the sdk=docker + app_port=7860 directives. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>f627b3a -
chore: pre-release β full project lifecycle (CRUD, history, docs, tests)β
Backend: - GET /projects (list), DELETE /projects/{id} - GET /inference/history - project_id threaded through POST /work/infer + /work/blueprint (form-field) - DailyWorkInput length caps (raw_text <= 4000, axes <= 200) - Blueprint upload size cap (50 MB β 413) - Supabase service: list_projects + delete_project + list_inference_history - X-Request-ID middleware (echo / auto-generate + access log line) - CORS constrained to the live Vercel deploy (no longer "*") - inference_history payload now includes "persisted" hint to client Frontend: - /project list page β cards with cross-links to work/blueprint/documents/history - /project/new rewired to POST /projects, surfaces returned project_id - /work + /blueprint accept ?project_id= and thread it into the request - /documents: full pick-project / pick-template / boilerplate / auto-download - /history: read-only inference feed, filterable by project_id - lib/api.ts: complete client for projects/crud/history/docuβ¦1d5d841 -
fix(llm): compose chain from VLM list directly for vision callsβ
structured_completion was building [override, primary, fbs...] then filter-restricting to VLM models. With llm_model_fallbacks="" the only VLM matching the override was the primary VLM β so a single failing model produced no fallback. New logic: build candidate list, then append all VLM-chain entries (de-duped) to ensure vision calls always have β₯2 attempts with the remaining VLM models serving as chain-wide fallbacks. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>0a027e6 -
fix(llm): bound per-attempt VLM timeouts so the chain can flowβ
Prior logic used asyncio.wait_for(timeout=remaining), where 'remaining' shrinks to whatever's left of the budget. If the first model hangs for ~45 s the chain ran out before getting to the second/third VLMs. Now per-attempt ceiling clamps to ~35 s (45 s for vision) so even with 3 models Γ 2 attempts each, the 60 s budget is preserved for the full chain. Raises the inner DEFAULT_TIMEOUT to 45 s for VLM slow nodes. The blueprint budget was also raised to 80 s because VLM models on NVIDIA integrate occasionally take 30+ s on cold paths. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>4638031 -
fix(llm): always send response_format=json_object; degrade-on-400 retryβ
Root cause: NVIDIA VLM model was returning the image_url content array ([{"type":"text",...},{"type":"image_url",...}]) verbatim because the prompt's "ONLY JSON" instruction alone wasn't enough without the response_format=json_object anchor. Re-enable response_format by default (Llama-3.2-Vision / Phi-4-multimodal both accept it on NVIDIA integrate). On 400 from the VLM (e.g. "multimodal processing is not enabled") the per-model loop now retries once with response_format disabled. Also splits ValidationError into its own branch so the retry can append a stricter "single valid JSON object" prompt β without this, models that wrap their output in arrays kept producing the same shape. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>503d208 -
fix(blueprint): surface chain-failure diagnostics in stub promptβ
When the VLM chain fully exhausts, the UI gets a generic stub and the real error disappears. Embed the LLMError summary in missing_info_prompts and log full chain tries/failures so diagnosis is possible over a single API call. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>ebda1de -
fix(blueprint): cap rendered PDF page to VLM-friendly dimensionsβ
Previous render at scale=2.0 produced 4768Γ3368 PNGs for A1 sheets which exceeds NVIDIA integrate image_url payload limits (silent 4xx from their handler β instant stub fallback). Compute a render scale dynamically so the longest edge β€ 1536 px β pages render at ~3β5 MP which the VLM nodes accept. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>0aefce5 -
fix(blueprint): render PDF first page before VLM callβ
NVIDIA VLM nodes (Llama-3.2-Vision, Phi-4-multimodal) silently 400 on application/pdf in image_url: their image-handler treats it as PIL input ("cannot identify image file"). PDFs must be rasterised client-side before being handed to the model. Adds pypdfium2 (pure-Python + bundled PDFium binary, no apt) + Pillow for bitmap-to-PNG conversion. Renders the first page at 2Γ scale (~144 DPI) which captures cover/title sheets carrying the project index. If the user uploads a multi-page PDF only the first page goes to the VLM; the multi-page caveat is surfaced via missing_info_prompts. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>ffef1b7 -
feat(frontend): blueprint upload pageβ
Adds /blueprint route with multipart upload + structured result cards (sheets, axes, dimensions, room labels, scales, RU notes, missing info). Backend wires through /work/blueprint β NVIDIA VLM chain (Llama-3.2-Vision). Home page gets a "ΠΠ°Π³ΡΡΠ·ΠΈΡΡ ΡΠ΅ΡΡΡΠΆ" link; /work gets a sibling back-link. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>696d80b -
fix(blueprint): prompt examples leak into tiny-PNG outputsβ
The Llama-3.2-Vision model was parroting back the example values "ΠΠ -1 / 1:100 / Π, Π, Π" verbatim because the prompt template presented them as literal answers. Replaced examples with placeholders + hard "do not invent" rule. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>5675e1c
-
fix(llm): omit response_format=json_object on vision callsβ
Some NVIDIA VLM nodes 400 on response_format. The system prompt already demands JSON-only, so we drop the field when sending image_url and rely on Pydantic validation as the safety net. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>3740efc -
fix(llm): swap VLM chain to Llama-3.2-Vision / Phi-4-multimodalβ
deepseek-v4-flash returns 400 "multimodal processing is not enabled" on NVIDIA integrate β text-only. VLM chain now uses Llama-3.2-Vision (11B + 90B) plus Phi-4-multimodal as fallback. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>88a61bd -
feat(work): blueprint upload + VLM extraction endpointβ
POST /work/blueprint accepts multipart image/PDF (PNG/JPEG/WebP/HEIC/PDF) and returns structured extraction via NVIDIA VLM (deepseek-v4-flash). Pipelines: - BlueprintExtraction schema (sheets / axes / dimensions / RU notes) - LLMClient vision path w/ VLM-only chain filtering - Stub fallback when VLM chain exhausts (UI never dead-ends) - Best-effort persistence to inference_history Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>d477ef1 -
deploy: backend 2026-06-22T18:15:19Z
cb75105 -
deploy: backend 2026-06-22T12:56:51Z
dff2eb8 -
deploy: backend 2026-06-22T12:22:55Z
6a0cb28 -
deploy: backend 2026-06-22T11:21:06Z
47fbc33 -
deploy: backend 2026-06-22T10:10:14Z
0ebedd1 -
deploy: backend 2026-06-22T08:22:30Z
46c3b99 -
deploy: backend 2026-06-22T05:07:40Z
0c46399 -
fix(deploy): sanitize deploy.sh + correct git author emailβ
Two failures addressed simultaneously: 1) pre-commit/author identity: prior deploy-bot commits used 'bot@local' as committer email, which GitHub rejected via its block on commits without a verified primary email and Vercel's webhook triggered the same error. Updated everywhere to: name : Pi Agent email : dirboll@gmail.com Run git filter-branch across all 6 local commits; force-pushed the rewritten history to both HF Space and GitHub main. 2) deploy.sh pre-receive hook failure at HF: hardcoded HF and GitHub tokens in the script (carried over from the original prompt) tripped HF's secret-scanning pre-receive hook on the most recent force-push. Removed all literal tokens; deploy.sh now requires the operator to export HF_TOKEN and GITHUB_TOKEN (or load from .env.deploy.example). Suggestion text in the startup banner points to the right URLs. Both remediations together ensure future deploys honor GitHub's commit attribution rules AND pass HF'sβ¦6b7d6c2
-
feat(deploy): frontend push to GitHub + Vercel wiringβ
- frontend/.gitignore: Vercel-friendly excludes (node_modules, .next, IDE files) - frontend/vercel.json: env values now plain strings (NEXT_PUBLIC_API_URL= https://dirbol-virtforemanbackend.hf.space, APP_NAME=Virtual Foreman) so first deploy works without manual env-var injection on Vercel side - deploy.sh deploy_frontend: same pattern as backend * separate src + clone mktemp dirs * rsync_or_cp + find-wipe + git add -A * additionally bring in project-root .gitignore and .dockerignore Pushed to dirboll-commits/VirtForeman (main): 2c36e8a β 6799da6 β a35e505 β c9f1892 Clean tree, 18 files. Ready for Vercel connect. Note: Vercel auto-deploy hook requires the GitHub integration to be activated once on Vercel (manual "Connect Git Repo" step). Once active, every push to main triggers a build automatically. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>004ea40 -
fix(deploy): portable deploy.sh + clean HF Space stateβ
Issue: First deploy of deploy.sh pushed the working tree of the HF clone into the Space's repo as an embedded submodule (`mode 160000 space_repo`), because: (a) the directory `space_repo` left from the clone was never cleaned up, (b) Termux lacks `rsync` so the original cp -r expanded onto the symlinked path and tripped. Fix: - `deploy.sh`: rewrite `deploy_backend` for portability on Termux * `rsync_or_cp` helper β uses rsync if available, else python3 shutil * Two separate tmpdirs (src + clone), cleaned via trap on RETURN * Clone into a unique mktemp path (`_hf_space/sp`), avoiding `space_repo` collisions and removing any chance of nested-folder accidents * `find β¦ ! -name '.git' ! -name 'README.md'` clears the clone's working tree, then `git add -A` re-stages fresh * Cleanup commit removes the orphaned submodule pointer from the Space's history (cda6242 β daef69a) Verified live (https://dirbol-virtforemanbackend.hf.space): - GET /health β β¦ad913cc -
test(integration): OpenRouter live call + schema split + multi-fallback chainβ
Live verification of the inference path. Run with: cd backend && cp .env.example .env # fill OPENROUTER_API_KEY python3 -m tests.test_openrouter_live Schema split (fix for model refusing to fill envelope fields): - New TechStackPayload: what the LLM fills (inferred_summary, steps, docs, prompts) - TechStack extends it + adds service-side envelope (source_input, model_used, generated_at). LLM is no longer asked for fields only the server knows. Multi-fallback chain (was 2 models, now 5): - Primary: meta-llama/llama-3.3-70b-instruct:free - Fallbacks (in order, all live on OpenRouter as of 2026-06-21): qwen/qwen3-next-80b-a3b-instruct:free nvidia/nemotron-3-super-120b-a12b:free openai/gpt-oss-20b:free google/gemma-4-31b-it:free - Settings exposes `openrouter_fallback_chain` property + `OPENROUTER_FREE_MODEL_FALLBACKS` env var (comma-separated). - Structured-completion retries 2x per model, then moves on; final exhaustion lists every model tried in the erroβ¦db9eb12 -
fix(backend): pin working dependency versions; ignore generated docx templatesβ
- requirements.txt: * docxtpl 0.18.1 β 0.18.0 (0.18.1 doesn't exist on PyPI) * supabase 2.10.0 β 2.31.0 (older release required httpx<0.28) * pydantic 2.10.3 β 2.11.7 (realtime needs >=2.11.7) * Jinja2 3.1.4 β 3.1.6 (litellm transitive requires >=3.1.6) - .gitignore: exclude backend/templates/*.docx (regenerable via scripts/generate_templates.py) Verified locally (Termux, Python 3.13): - pip install -r requirements.txt succeeds after ANDROID_API_LEVEL=33 - uvicorn boots on :7860 - GET /health / / /documents/templates β 200 - POST /documents/render β valid 37KB .docx (PK\\003\\004 ZIP magic) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>fc604a2 -
Phases 2-5: full FastAPI backend, Pydantic OpenRouter client, docxtpl engine, Next.js UI, deploy.shβ
Backend: - app/models: Pydantic schemas for Project, DailyWorkInput, TechStack (BY-context) - app/services/openrouter: async client w/ primary+fallback free models, required headers (Authorization, HTTP-Referer, X-Title), JSON response_format, Pydantic-validated structured outputs, tenacity retries - app/services/tech_stack_service: orchestrates OpenRouter call β TechStack model - app/services/document_engine: docxtpl wrapper, BY act templates (AOSR, OO, etc.) - app/services/supabase_service: optional persistence (graceful no-op if absent) - app/ai/prompts: GPT-style system prompt as chief engineer / head of PTO with strict JSON mandate and Belarusian SN/TKP knowledge - app/routers: /projects, /work/infer, /documents/render, /documents/templates - app/main: lifespan-managed OpenRouter HTTP client, CORSMiddleware - scripts/generate_templates: generates 4 .docx templates w/ Jinja2 tags - supabase/schema.sql: projects + acts_history tables w/ RLS Frontend (Next.js 14, App Router, Tβ¦51122e7 -
Phase 1: scaffold backend (FastAPI + Dockerfile) and frontend (Next.js + Vercel)β
- backend/: FastAPI app skeleton with /health endpoint, pydantic-settings config - backend/Dockerfile: Python 3.11 slim, port 7860 for HF Spaces SDK - backend/requirements.txt: pinned deps (fastapi, pydantic, httpx, supabase, docxtpl) - backend/.env.example: env template (no secrets committed) - frontend/: Next.js 14 + Tailwind + TS, vercel.json with build env wiring - .gitignore: covers Python, Node, .env, HF, Vercel artifacts Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>93628d9