cf-web 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. cf_web-0.1.0/PKG-INFO +175 -0
  2. cf_web-0.1.0/README.md +154 -0
  3. cf_web-0.1.0/pyproject.toml +47 -0
  4. cf_web-0.1.0/setup.cfg +4 -0
  5. cf_web-0.1.0/src/cf_web/__init__.py +5 -0
  6. cf_web-0.1.0/src/cf_web/api/__init__.py +1 -0
  7. cf_web-0.1.0/src/cf_web/api/routers/__init__.py +3 -0
  8. cf_web-0.1.0/src/cf_web/api/routers/health.py +13 -0
  9. cf_web-0.1.0/src/cf_web/api/routers/ontology.py +90 -0
  10. cf_web-0.1.0/src/cf_web/api/routers/packages.py +53 -0
  11. cf_web-0.1.0/src/cf_web/api/routers/pipelines.py +75 -0
  12. cf_web-0.1.0/src/cf_web/api/routers/resource_manager.py +110 -0
  13. cf_web-0.1.0/src/cf_web/cli.py +157 -0
  14. cf_web-0.1.0/src/cf_web/config.py +37 -0
  15. cf_web-0.1.0/src/cf_web/main.py +82 -0
  16. cf_web-0.1.0/src/cf_web/services/__init__.py +13 -0
  17. cf_web-0.1.0/src/cf_web/services/manager_provider.py +32 -0
  18. cf_web-0.1.0/src/cf_web/services/ontology_explorer_service.py +1376 -0
  19. cf_web-0.1.0/src/cf_web/services/package_template_service.py +908 -0
  20. cf_web-0.1.0/src/cf_web/services/pipeline_creator_service.py +114 -0
  21. cf_web-0.1.0/src/cf_web/services/pipeline_service.py +98 -0
  22. cf_web-0.1.0/src/cf_web/services/resource_manager_service.py +583 -0
  23. cf_web-0.1.0/src/cf_web/static/assets/index-2NRYpRG3.css +1 -0
  24. cf_web-0.1.0/src/cf_web/static/assets/index-DZmFkFw8.js +72 -0
  25. cf_web-0.1.0/src/cf_web/static/favicon.ico +0 -0
  26. cf_web-0.1.0/src/cf_web/static/index.html +33 -0
  27. cf_web-0.1.0/src/cf_web.egg-info/PKG-INFO +175 -0
  28. cf_web-0.1.0/src/cf_web.egg-info/SOURCES.txt +31 -0
  29. cf_web-0.1.0/src/cf_web.egg-info/dependency_links.txt +1 -0
  30. cf_web-0.1.0/src/cf_web.egg-info/entry_points.txt +5 -0
  31. cf_web-0.1.0/src/cf_web.egg-info/requires.txt +17 -0
  32. cf_web-0.1.0/src/cf_web.egg-info/top_level.txt +1 -0
  33. cf_web-0.1.0/tests/test_install_surface.py +78 -0
cf_web-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: cf-web
3
+ Version: 0.1.0
4
+ Summary: Web-based GUI for Cogniflow with FastAPI backend and React frontend
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: fastapi<1.0,>=0.100
8
+ Requires-Dist: uvicorn[standard]<1.0,>=0.24
9
+ Requires-Dist: pydantic<3.0,>=2.0
10
+ Requires-Dist: cf-ontology>=0.1
11
+ Provides-Extra: test
12
+ Requires-Dist: pytest<9.0,>=8.0; extra == "test"
13
+ Requires-Dist: pytest-asyncio<0.25,>=0.24; extra == "test"
14
+ Requires-Dist: httpx<1.0,>=0.25; extra == "test"
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
17
+ Requires-Dist: pytest-asyncio<0.25,>=0.24; extra == "dev"
18
+ Requires-Dist: httpx<1.0,>=0.25; extra == "dev"
19
+ Provides-Extra: pipeline
20
+ Requires-Dist: cf-pipeline-engine>=0.1; extra == "pipeline"
21
+
22
+ # CogniFlow Web
23
+
24
+ `cf_web` is the web application package for CogniFlow. It provides:
25
+
26
+ - a FastAPI backend (`src/cf_web`) exposing ontology/pipeline APIs
27
+ - a React + TypeScript frontend (`frontend`) for ontology exploration and pipeline editing
28
+ - a CLI entrypoint (`cogniflow-web`) to launch the app
29
+
30
+ Published distribution name:
31
+
32
+ ```bash
33
+ pip install cf-web
34
+ ```
35
+
36
+ Installed launcher surface:
37
+
38
+ ```powershell
39
+ cogniflow-web
40
+ ```
41
+
42
+ The backend reads semantics through `cf_ontology` and its DuckDB quads stores.
43
+
44
+ ## Architecture
45
+
46
+ - Backend framework: FastAPI + Uvicorn
47
+ - Frontend framework: React + Vite
48
+ - Semantics source: `cf_ontology.OntologyManager` (quads-backed)
49
+ - Service split:
50
+ - `ontology_explorer_service.py` for ontology explorer payloads
51
+ - `pipeline_creator_service.py` for step DTOs used by the editor
52
+ - `pipeline_service.py` for pipeline list/load/save/validate operations
53
+
54
+ ## Install
55
+
56
+ From repository root (recommended in a virtual environment):
57
+
58
+ ```powershell
59
+ python -m pip install -e "sandcastle/cf_web[test]"
60
+ ```
61
+
62
+ Install with pipeline runtime support:
63
+
64
+ ```powershell
65
+ python -m pip install -e "sandcastle/cf_web[test,pipeline]"
66
+ ```
67
+
68
+ If you want frontend production assets served by FastAPI, build the frontend first:
69
+
70
+ ```powershell
71
+ .\scripts\build_cf_web_frontend.ps1
72
+ ```
73
+
74
+ ## Run
75
+
76
+ ### Option 1: direct app launcher
77
+
78
+ ```powershell
79
+ cogniflow-web
80
+ ```
81
+
82
+ Disable browser auto-open:
83
+
84
+ ```powershell
85
+ cogniflow-web --no-browser
86
+ ```
87
+
88
+ ### Option 2: unified CLI
89
+
90
+ ```powershell
91
+ cf web start
92
+ ```
93
+
94
+ or
95
+
96
+ ```powershell
97
+ cf web start --no-browser
98
+ ```
99
+
100
+ ## Backend API
101
+
102
+ Key routes:
103
+
104
+ - `GET /api/health`
105
+ - `GET /api/ontology/graph`
106
+ - `GET /api/ontology/dataset`
107
+ - `GET /api/ontology/dashboard`
108
+ - `GET /api/ontology/steps`
109
+ - `GET /api/ontology/steps/{step_id}`
110
+ - `GET /api/pipelines/`
111
+ - `GET /api/pipelines/{pipeline_id}?rev={n}`
112
+ - `POST /api/pipelines/save`
113
+ - `POST /api/pipelines/validate`
114
+
115
+ ## Configuration
116
+
117
+ `cf_web` reads these environment variables:
118
+
119
+ - `CF_WEB_HOST` (default: `127.0.0.1`)
120
+ - `CF_WEB_PORT` (default: `8000`)
121
+ - `CF_WEB_RELOAD` (`1` enables reload, default: `0`)
122
+ - `CF_WEB_DEBUG` (`1` enables debug flag, default: `0`)
123
+ - `CF_WORKSPACE_DIR` (default: `~/.cogniflow/workspace`)
124
+ - `CF_SEMANTICS_DIR` (default: `<workspace>/semantics`)
125
+
126
+ By default the launcher sets:
127
+
128
+ - `CF_ENABLE_STEP_PACKAGES=1`
129
+
130
+ so installed step packages are ingested/discovered for UI usage.
131
+
132
+ ## Development Notes
133
+
134
+ - Frontend source of truth is under `frontend/src`.
135
+ - Built frontend files are emitted to `src/cf_web/static` by Vite.
136
+ - The publish workflow packages the checked-in `src/cf_web/static` bundle and does not run a frontend build step.
137
+ - Backend services use a shared `OntologyManager` provider (`manager_provider.py`) to avoid repeated manager instantiation.
138
+
139
+ ## Publishing
140
+
141
+ `cf_web` is published with the dedicated Windows workflow:
142
+
143
+ - Workflow: `.github/workflows/cf_web_windows_publish.yml`
144
+ - Package directory: `sandcastle/cf_web`
145
+ - Published distribution: `cf-web`
146
+ - PyPI tag: `cf-web-v<version>`
147
+ - TestPyPI tag: `cf-web-v<version>-test`
148
+
149
+ Local preflight:
150
+
151
+ ```powershell
152
+ powershell -ExecutionPolicy Bypass -File scripts/mimic_windows_python_publish_workflow.ps1 `
153
+ -WorkflowFile .github/workflows/cf_web_windows_publish.yml `
154
+ -PackageDir sandcastle/cf_web `
155
+ -PythonExe py `
156
+ -PythonVersion 3.13
157
+ ```
158
+
159
+ Queue a dry-run dispatch:
160
+
161
+ ```powershell
162
+ powershell -ExecutionPolicy Bypass -File scripts/queue_windows_python_publish_workflow.ps1 `
163
+ -WorkflowFile .github/workflows/cf_web_windows_publish.yml `
164
+ -PackageDir sandcastle/cf_web `
165
+ -PublishTarget testpypi `
166
+ -Ref main `
167
+ -RequireLocalPass `
168
+ -DryRun
169
+ ```
170
+
171
+ ## Troubleshooting
172
+
173
+ - `GET /favicon.ico 404`: ensure favicon exists in `src/cf_web/static/favicon.ico` and frontend was rebuilt.
174
+ - App opens but says frontend build missing: run `.\scripts\build_cf_web_frontend.ps1`.
175
+ - No steps visible in UI: ensure step packages are installed and `CF_ENABLE_STEP_PACKAGES=1` (default via launcher).
cf_web-0.1.0/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # CogniFlow Web
2
+
3
+ `cf_web` is the web application package for CogniFlow. It provides:
4
+
5
+ - a FastAPI backend (`src/cf_web`) exposing ontology/pipeline APIs
6
+ - a React + TypeScript frontend (`frontend`) for ontology exploration and pipeline editing
7
+ - a CLI entrypoint (`cogniflow-web`) to launch the app
8
+
9
+ Published distribution name:
10
+
11
+ ```bash
12
+ pip install cf-web
13
+ ```
14
+
15
+ Installed launcher surface:
16
+
17
+ ```powershell
18
+ cogniflow-web
19
+ ```
20
+
21
+ The backend reads semantics through `cf_ontology` and its DuckDB quads stores.
22
+
23
+ ## Architecture
24
+
25
+ - Backend framework: FastAPI + Uvicorn
26
+ - Frontend framework: React + Vite
27
+ - Semantics source: `cf_ontology.OntologyManager` (quads-backed)
28
+ - Service split:
29
+ - `ontology_explorer_service.py` for ontology explorer payloads
30
+ - `pipeline_creator_service.py` for step DTOs used by the editor
31
+ - `pipeline_service.py` for pipeline list/load/save/validate operations
32
+
33
+ ## Install
34
+
35
+ From repository root (recommended in a virtual environment):
36
+
37
+ ```powershell
38
+ python -m pip install -e "sandcastle/cf_web[test]"
39
+ ```
40
+
41
+ Install with pipeline runtime support:
42
+
43
+ ```powershell
44
+ python -m pip install -e "sandcastle/cf_web[test,pipeline]"
45
+ ```
46
+
47
+ If you want frontend production assets served by FastAPI, build the frontend first:
48
+
49
+ ```powershell
50
+ .\scripts\build_cf_web_frontend.ps1
51
+ ```
52
+
53
+ ## Run
54
+
55
+ ### Option 1: direct app launcher
56
+
57
+ ```powershell
58
+ cogniflow-web
59
+ ```
60
+
61
+ Disable browser auto-open:
62
+
63
+ ```powershell
64
+ cogniflow-web --no-browser
65
+ ```
66
+
67
+ ### Option 2: unified CLI
68
+
69
+ ```powershell
70
+ cf web start
71
+ ```
72
+
73
+ or
74
+
75
+ ```powershell
76
+ cf web start --no-browser
77
+ ```
78
+
79
+ ## Backend API
80
+
81
+ Key routes:
82
+
83
+ - `GET /api/health`
84
+ - `GET /api/ontology/graph`
85
+ - `GET /api/ontology/dataset`
86
+ - `GET /api/ontology/dashboard`
87
+ - `GET /api/ontology/steps`
88
+ - `GET /api/ontology/steps/{step_id}`
89
+ - `GET /api/pipelines/`
90
+ - `GET /api/pipelines/{pipeline_id}?rev={n}`
91
+ - `POST /api/pipelines/save`
92
+ - `POST /api/pipelines/validate`
93
+
94
+ ## Configuration
95
+
96
+ `cf_web` reads these environment variables:
97
+
98
+ - `CF_WEB_HOST` (default: `127.0.0.1`)
99
+ - `CF_WEB_PORT` (default: `8000`)
100
+ - `CF_WEB_RELOAD` (`1` enables reload, default: `0`)
101
+ - `CF_WEB_DEBUG` (`1` enables debug flag, default: `0`)
102
+ - `CF_WORKSPACE_DIR` (default: `~/.cogniflow/workspace`)
103
+ - `CF_SEMANTICS_DIR` (default: `<workspace>/semantics`)
104
+
105
+ By default the launcher sets:
106
+
107
+ - `CF_ENABLE_STEP_PACKAGES=1`
108
+
109
+ so installed step packages are ingested/discovered for UI usage.
110
+
111
+ ## Development Notes
112
+
113
+ - Frontend source of truth is under `frontend/src`.
114
+ - Built frontend files are emitted to `src/cf_web/static` by Vite.
115
+ - The publish workflow packages the checked-in `src/cf_web/static` bundle and does not run a frontend build step.
116
+ - Backend services use a shared `OntologyManager` provider (`manager_provider.py`) to avoid repeated manager instantiation.
117
+
118
+ ## Publishing
119
+
120
+ `cf_web` is published with the dedicated Windows workflow:
121
+
122
+ - Workflow: `.github/workflows/cf_web_windows_publish.yml`
123
+ - Package directory: `sandcastle/cf_web`
124
+ - Published distribution: `cf-web`
125
+ - PyPI tag: `cf-web-v<version>`
126
+ - TestPyPI tag: `cf-web-v<version>-test`
127
+
128
+ Local preflight:
129
+
130
+ ```powershell
131
+ powershell -ExecutionPolicy Bypass -File scripts/mimic_windows_python_publish_workflow.ps1 `
132
+ -WorkflowFile .github/workflows/cf_web_windows_publish.yml `
133
+ -PackageDir sandcastle/cf_web `
134
+ -PythonExe py `
135
+ -PythonVersion 3.13
136
+ ```
137
+
138
+ Queue a dry-run dispatch:
139
+
140
+ ```powershell
141
+ powershell -ExecutionPolicy Bypass -File scripts/queue_windows_python_publish_workflow.ps1 `
142
+ -WorkflowFile .github/workflows/cf_web_windows_publish.yml `
143
+ -PackageDir sandcastle/cf_web `
144
+ -PublishTarget testpypi `
145
+ -Ref main `
146
+ -RequireLocalPass `
147
+ -DryRun
148
+ ```
149
+
150
+ ## Troubleshooting
151
+
152
+ - `GET /favicon.ico 404`: ensure favicon exists in `src/cf_web/static/favicon.ico` and frontend was rebuilt.
153
+ - App opens but says frontend build missing: run `.\scripts\build_cf_web_frontend.ps1`.
154
+ - No steps visible in UI: ensure step packages are installed and `CF_ENABLE_STEP_PACKAGES=1` (default via launcher).
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["setuptools>=70"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cf-web"
7
+ version = "0.1.0"
8
+ description = "Web-based GUI for Cogniflow with FastAPI backend and React frontend"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = [
12
+ "fastapi>=0.100,<1.0",
13
+ "uvicorn[standard]>=0.24,<1.0",
14
+ "pydantic>=2.0,<3.0",
15
+ "cf-ontology>=0.1",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ test = [
20
+ "pytest>=8.0,<9.0",
21
+ "pytest-asyncio>=0.24,<0.25",
22
+ "httpx>=0.25,<1.0",
23
+ ]
24
+ dev = [
25
+ "pytest>=8.0,<9.0",
26
+ "pytest-asyncio>=0.24,<0.25",
27
+ "httpx>=0.25,<1.0",
28
+ ]
29
+ pipeline = [
30
+ "cf-pipeline-engine>=0.1",
31
+ ]
32
+
33
+ [project.scripts]
34
+ cogniflow-web = "cf_web.cli:main"
35
+
36
+ [project.entry-points."cogniflow.cli"]
37
+ web = "cf_web.cli:register_cli"
38
+
39
+ [tool.setuptools]
40
+ package-dir = {"" = "src"}
41
+ include-package-data = true
42
+
43
+ [tool.setuptools.packages.find]
44
+ where = ["src"]
45
+
46
+ [tool.setuptools.package-data]
47
+ cf_web = ["static/*", "static/**/*"]
cf_web-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ """Cogniflow web package."""
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """API package."""
@@ -0,0 +1,3 @@
1
+ """API routers."""
2
+
3
+ __all__ = ["health", "ontology", "packages", "pipelines", "resource_manager"]
@@ -0,0 +1,13 @@
1
+ """Health endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from fastapi import APIRouter
6
+
7
+ router = APIRouter()
8
+
9
+
10
+ @router.get("/health")
11
+ async def healthcheck() -> dict[str, str]:
12
+ """Return liveness status for API health probing."""
13
+ return {"status": "ok"}
@@ -0,0 +1,90 @@
1
+ """Ontology endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Optional
6
+
7
+ from fastapi import APIRouter, HTTPException
8
+
9
+ from cf_web.services.pipeline_creator_service import PipelineCreatorService
10
+ from cf_web.services.ontology_explorer_service import OntologyExplorerService
11
+
12
+ router = APIRouter()
13
+ pipeline_creator_service = PipelineCreatorService()
14
+ ontology_explorer_service = OntologyExplorerService()
15
+
16
+
17
+ @router.get("/graph")
18
+ async def get_graph() -> dict[str, object]:
19
+ """Return ontology explorer graph payload."""
20
+ return {"jsonld": ontology_explorer_service.get_graph()}
21
+
22
+
23
+ @router.get("/dataset")
24
+ async def get_dataset() -> dict[str, object]:
25
+ """Return ontology dataset payload."""
26
+ return {"jsonld": ontology_explorer_service.get_dataset()}
27
+
28
+
29
+ @router.get("/steps")
30
+ async def list_steps() -> dict[str, object]:
31
+ """List processing-step DTOs for pipeline creation."""
32
+ return {"steps": pipeline_creator_service.get_steps()}
33
+
34
+
35
+ @router.get("/steps/{step_id}")
36
+ async def get_step(step_id: str) -> dict[str, object]:
37
+ """Return one processing-step DTO by id or alias."""
38
+ step = pipeline_creator_service.get_step(step_id)
39
+ if not step:
40
+ raise HTTPException(status_code=404, detail="Step not found")
41
+ return {"step": step}
42
+
43
+
44
+ @router.get("/step-builder-options")
45
+ async def get_step_builder_options() -> dict[str, object]:
46
+ """Return ontology-derived dropdown options for the package creator step builder."""
47
+ return pipeline_creator_service.get_step_builder_options()
48
+
49
+
50
+ @router.get("/dashboard")
51
+ async def get_dashboard() -> dict[str, object]:
52
+ """Return ontology dashboard graph data."""
53
+ return {"graphs": ontology_explorer_service.get_dashboard_graphs()}
54
+
55
+
56
+ @router.get("/datatypes")
57
+ async def get_datatypes_graph() -> dict[str, object]:
58
+ """Return the virtual datatypes graph payload."""
59
+ return {"graph": ontology_explorer_service.get_datatypes_graph()}
60
+
61
+
62
+ @router.get("/node-quads")
63
+ async def get_node_quads(
64
+ node_id: str,
65
+ graph_id: Optional[str] = None,
66
+ aliases: Optional[str] = None,
67
+ limit: int = 200,
68
+ ) -> dict[str, object]:
69
+ """Return raw quads for one selected node id/alias."""
70
+ alias_items = [item for item in (aliases or "").split(",") if item]
71
+ return {
72
+ "quads": ontology_explorer_service.get_node_quads(
73
+ node_id=node_id,
74
+ graph_id=graph_id,
75
+ aliases=alias_items,
76
+ limit=limit,
77
+ )
78
+ }
79
+
80
+
81
+ @router.get("/diagnostics")
82
+ async def get_diagnostics() -> dict[str, object]:
83
+ """Return read-only diagnostics for ontology graph/quads quality checks."""
84
+ return ontology_explorer_service.get_diagnostics_report()
85
+
86
+
87
+ @router.post("/diagnostics/run")
88
+ async def run_diagnostics() -> dict[str, object]:
89
+ """Run comprehensive diagnostics across semantics DuckDB quad stores."""
90
+ return ontology_explorer_service.run_comprehensive_diagnostics()
@@ -0,0 +1,53 @@
1
+ """Package template endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+
7
+ from fastapi import APIRouter, HTTPException
8
+ from fastapi.responses import StreamingResponse
9
+
10
+ from cf_web.services.package_template_service import (
11
+ PackageTemplateRequest,
12
+ PackageTemplateService,
13
+ )
14
+
15
+ router = APIRouter()
16
+ service = PackageTemplateService()
17
+
18
+
19
+ @router.post("/template")
20
+ async def create_package_template(payload: PackageTemplateRequest) -> StreamingResponse:
21
+ """Generate a package template archive and return as a download."""
22
+ try:
23
+ result = service.create_template(payload)
24
+ except RuntimeError as exc:
25
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
26
+ except ValueError as exc:
27
+ raise HTTPException(status_code=422, detail=str(exc)) from exc
28
+
29
+ headers = {"Content-Disposition": f'attachment; filename="{result.filename}"'}
30
+ return StreamingResponse(
31
+ iter([result.content]),
32
+ media_type="application/zip",
33
+ headers=headers,
34
+ )
35
+
36
+
37
+ @router.post("/template/build")
38
+ async def build_package_template(payload: PackageTemplateRequest) -> dict[str, object]:
39
+ """Generate a package template and return zip payload plus validation report."""
40
+ try:
41
+ result = service.create_template(payload)
42
+ except RuntimeError as exc:
43
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
44
+ except ValueError as exc:
45
+ raise HTTPException(status_code=422, detail=str(exc)) from exc
46
+
47
+ return {
48
+ "filename": result.filename,
49
+ "zip_base64": base64.b64encode(result.content).decode("ascii"),
50
+ "validation_report": result.validation_report,
51
+ "generated_files": result.generated_files,
52
+ "generated_at_utc": result.generated_at_utc,
53
+ }
@@ -0,0 +1,75 @@
1
+ """Pipeline endpoints."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Optional
6
+
7
+ from fastapi import APIRouter, HTTPException
8
+ from pydantic import BaseModel, Field
9
+
10
+ from cf_web.services.pipeline_service import PipelineService
11
+
12
+ router = APIRouter()
13
+ service = PipelineService()
14
+
15
+
16
+ class SavePipelineRequest(BaseModel):
17
+ """Payload for saving a pipeline revision."""
18
+
19
+ pipeline_id: str = Field(min_length=1)
20
+ jsonld: dict[str, Any]
21
+ user: Optional[str] = None
22
+ message: Optional[str] = None
23
+
24
+
25
+ class ValidatePipelineRequest(BaseModel):
26
+ """Payload for validating pipeline JSON-LD."""
27
+
28
+ jsonld: dict[str, Any]
29
+
30
+
31
+ @router.get("/")
32
+ async def list_pipelines() -> dict[str, list[dict[str, Any]]]:
33
+ """List stored pipelines with current revision metadata."""
34
+ return {"pipelines": service.list_pipelines()}
35
+
36
+
37
+ @router.get("/{pipeline_id}")
38
+ async def load_pipeline(pipeline_id: str, rev: Optional[int] = None) -> dict[str, object]:
39
+ """Load a pipeline by id, optionally for a specific revision."""
40
+ try:
41
+ jsonld = service.get_pipeline(pipeline_id, rev=rev)
42
+ except KeyError as exc:
43
+ raise HTTPException(status_code=404, detail=str(exc)) from exc
44
+ except RuntimeError as exc:
45
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
46
+ return {"pipeline_id": pipeline_id, "rev": rev, "jsonld": jsonld}
47
+
48
+
49
+ @router.post("/save")
50
+ async def save_pipeline(payload: SavePipelineRequest) -> dict[str, object]:
51
+ """Commit a pipeline revision to the pipeline store."""
52
+ try:
53
+ result = service.save_pipeline(
54
+ pipeline_id=payload.pipeline_id,
55
+ jsonld=payload.jsonld,
56
+ user=payload.user,
57
+ message=payload.message,
58
+ )
59
+ except RuntimeError as exc:
60
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
61
+ except ValueError as exc:
62
+ raise HTTPException(status_code=422, detail=str(exc)) from exc
63
+ return result
64
+
65
+
66
+ @router.post("/validate")
67
+ async def validate_pipeline(payload: ValidatePipelineRequest) -> dict[str, object]:
68
+ """Validate pipeline JSON-LD and return validation diagnostics."""
69
+ try:
70
+ result = service.validate_pipeline(payload.jsonld)
71
+ except RuntimeError as exc:
72
+ raise HTTPException(status_code=503, detail=str(exc)) from exc
73
+ except ValueError as exc:
74
+ raise HTTPException(status_code=422, detail=str(exc)) from exc
75
+ return result