Stand up EasyStitch as an HTTP service for ThreadCraft #11
Labels
No labels
blocked:commit-ready-failed
blocked:gate-fetch
blocked:gate-lint
blocked:gate-plan
blocked:gate-research
blocked:needs-attention
blocked:needs-decision
blocked:needs-human
blocked:no-changes
blocked:verify-failed
bug
deferred
feature-request
in-progress
needs-decompose
needs-triage
quickfix
security/medium
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/Kimi_Agent_Brother_10_Digitizing_App#11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Stand up EasyStitch as an HTTP service for ThreadCraft
Context
ThreadCraft (this repo) is a TypeScript/React app. The auto-digitize pipeline (#6–#10)
and the PES export (#2) need an embroidery CAM engine to do the actual work.
A complete, mature Python implementation already exists: EasyStitch at
https://forgejo.tail018ac4.ts.net/Mark/easystitch (local clone at
~/Projects/easystitch/). It implements:src/raster/)src/svg_annotation/)src/embroidery_converter/classifier.py)src/embroidery_converter/satin_stitch_generator.py)src/embroidery_converter/fill_stitch_generator.py)src/embroidery_converter/underlay_generator.py)src/embroidery_converter/thread_manager.py)src/output_generators/)src/post_processing/,src/post_processor/)The algorithms are perf-tuned (recent KDTree + scipy commits, June 2026), have a
Dockerfile, and ship a 5-stage
EmbroideryPipelineorchestrator insrc/main_pipeline.py. What EasyStitch does not have is an HTTP layer — it'sCLI only today.
Goal
Expose EasyStitch's pipeline as an HTTP service the ThreadCraft frontend can call.
No algorithm ports — the Python code stays Python. Frontend issues HTTP requests,
receives JSON stitch objects, renders them on the Fabric.js canvas.
Architecture
API surface (v1)
Three endpoints, all
POST, JSON-in / mixed-out:POST /v1/digitizeInput raster → classified regions + stitch objects.
Request:
Response:
Backend: wraps
src/main_pipeline.pyEmbroideryPipelineafter the rasteringest stage.
POST /v1/exportStitch objects (already computed) → embroidery file bytes.
Request:
Response:
Content-Type: application/octet-streamwith the raw embroideryfile body. Headers include
X-Stitch-Count,X-Color-Count.Backend: wraps the relevant
src/output_generators/<fmt>_generator.pyplussrc/post_processing/pull-compensation.POST /v1/threads/resolveΔE-based thread palette lookup (used by the Workspace for live color previews
during manual editing).
Request:
Response:
Backend: wraps
src/embroidery_converter/thread_manager.pyΔE-2000 distanceagainst the embedded Brother PR-10 thread catalog.
Implementation
easystitch-service/at the repo root (or separaterepo — TBD based on monorepo vs sibling-service decision).
app.pyFastAPI app that importssrc.main_pipelineandthe relevant generator modules, exposes the 3 endpoints above. Validate inputs
with pydantic (already a dependency).
machine profile catalog path). 12-factor friendly.
Dockerfilein~/Projects/easystitch/toCMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]. Or athin
Dockerfilein the service dir thatFROM easystitch:latestand copiesthe FastAPI layer.
vars, expose via the existing
/proxy/:instanceIdreverse proxy. ThreadCraftfrontend talks to it at the tailnet-local URL — no public exposure needed.
http://localhost:3000) and prod originsonly. Tailnet is trusted; no auth required between them (matches node_hub's
NO AUTHpolicy).GET /healthzreturns{"status": "ok", "version": "..."}for node_hub's liveness probe.
CPU-bound; use
run_in_executoror a worker pool of N=CPU cores). Rejectrequests beyond a queue depth with
503.Files touched
easystitch-service/app.py,easystitch-service/Dockerfile,easystitch-service/requirements.txt,easystitch-service/README.md~/Projects/easystitch/Dockerfile(addCMD uvicorn) OR copythe base image and override.
package.json— addEASYSTITCH_API_URLenv varand a
src/lib/easystitch-client.tstyped wrapper.vite.config.ts— proxy/api/easystitchto theservice in dev.
Acceptance
POST /v1/digitizeon a 1024×1024 PNG returns stitch objects within 5 secondson the local dev box (CPU-only is fine; GPU not required for v1).
POST /v1/exportforformat=pesreturns a file that loads in a realBrother PR-10 (manual smoke test, no machine in CI).
tsc --noEmitclean./healthzreturns 200.PES → file opens in a viewer (e.g.
https://embroiderviewer.comor Ink/Stitch).Dependencies
This ticket blocks the following ThreadCraft issues, which currently frame
their work as "implement from scratch" and need to be re-scoped to "call the
service and render the result":
/v1/exportto theExportDialog and write the binary to a download"
/v1/digitizewith the uploaded raster; render returned
regions[]on the canvas"stitchObjects[].type=='satin'as parallel stitch pairs on the canvas"stitchObjects[].type=='fill'as alternating-direction rows on the canvas"paletteIndexfrom/v1/digitizeand surface in the Editor's color picker"This ticket does not block #7 (region classification), which operates on
canvas state and should port the rules from
~/Projects/easystitch/src/embroidery_converter/classifier.pyto TypeScript.Out of scope (v1)
service).
Risks
need a progress UI (covered in #10 integration notes).
oversized uploads with
413.auto-digitize button should fail gracefully (show error toast, fall back to
manual mode). Do not crash the React app.
types on the client. Keep them in lockstep; consider codegen from OpenAPI
schema in v2.
Dependents
The following ThreadCraft issues are blocked on this service:
Each has been re-scoped to a thin-client pattern: call the service, render
the result, do not port the algorithms. Once
/v1/digitizeand/v1/exportare live, the dependents become renderers and frontend plumbing.
Note: #7 (Phase 2: Region Classification) is not a service client —
it ports the classification rule set from
~/Projects/easystitch/src/embroidery_converter/classifier.pyto TypeScriptbecause classification runs over canvas state and must be synchronous for
live editor previews. #7 can proceed in parallel with #11.
Mark referenced this issue from Mark/easystitch2026-06-22 16:23:20 +00:00
⚠️ Re-scoped — decomposition in progress
This issue is being decomposed into sub-issues filed against the new
Mark/easystitch-servicerepo (created 2026-06-23).Repository: https://forgejo.tail018ac4.ts.net/Mark/easystitch-service
The HTTP service lives in its own repo (per integration-shape decision). The three endpoints specified here (
/v1/digitize,/v1/export,/v1/threads/resolve) and the deployment via node_hub remain the spec — see the new sub-issues for execution.This parent issue will stay open as the integration contract / API spec. Sub-issues track the actual build.