julee 0.1.0__py3-none-any.whl

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 (161) hide show
  1. julee/__init__.py +3 -0
  2. julee/api/__init__.py +20 -0
  3. julee/api/app.py +180 -0
  4. julee/api/dependencies.py +257 -0
  5. julee/api/requests.py +175 -0
  6. julee/api/responses.py +43 -0
  7. julee/api/routers/__init__.py +43 -0
  8. julee/api/routers/assembly_specifications.py +212 -0
  9. julee/api/routers/documents.py +182 -0
  10. julee/api/routers/knowledge_service_configs.py +79 -0
  11. julee/api/routers/knowledge_service_queries.py +293 -0
  12. julee/api/routers/system.py +137 -0
  13. julee/api/routers/workflows.py +234 -0
  14. julee/api/services/__init__.py +20 -0
  15. julee/api/services/system_initialization.py +214 -0
  16. julee/api/tests/__init__.py +14 -0
  17. julee/api/tests/routers/__init__.py +17 -0
  18. julee/api/tests/routers/test_assembly_specifications.py +749 -0
  19. julee/api/tests/routers/test_documents.py +301 -0
  20. julee/api/tests/routers/test_knowledge_service_configs.py +234 -0
  21. julee/api/tests/routers/test_knowledge_service_queries.py +738 -0
  22. julee/api/tests/routers/test_system.py +179 -0
  23. julee/api/tests/routers/test_workflows.py +393 -0
  24. julee/api/tests/test_app.py +285 -0
  25. julee/api/tests/test_dependencies.py +245 -0
  26. julee/api/tests/test_requests.py +250 -0
  27. julee/domain/__init__.py +22 -0
  28. julee/domain/models/__init__.py +49 -0
  29. julee/domain/models/assembly/__init__.py +17 -0
  30. julee/domain/models/assembly/assembly.py +103 -0
  31. julee/domain/models/assembly/tests/__init__.py +0 -0
  32. julee/domain/models/assembly/tests/factories.py +37 -0
  33. julee/domain/models/assembly/tests/test_assembly.py +430 -0
  34. julee/domain/models/assembly_specification/__init__.py +24 -0
  35. julee/domain/models/assembly_specification/assembly_specification.py +172 -0
  36. julee/domain/models/assembly_specification/knowledge_service_query.py +123 -0
  37. julee/domain/models/assembly_specification/tests/__init__.py +0 -0
  38. julee/domain/models/assembly_specification/tests/factories.py +78 -0
  39. julee/domain/models/assembly_specification/tests/test_assembly_specification.py +490 -0
  40. julee/domain/models/assembly_specification/tests/test_knowledge_service_query.py +310 -0
  41. julee/domain/models/custom_fields/__init__.py +0 -0
  42. julee/domain/models/custom_fields/content_stream.py +68 -0
  43. julee/domain/models/custom_fields/tests/__init__.py +0 -0
  44. julee/domain/models/custom_fields/tests/test_custom_fields.py +53 -0
  45. julee/domain/models/document/__init__.py +17 -0
  46. julee/domain/models/document/document.py +150 -0
  47. julee/domain/models/document/tests/__init__.py +0 -0
  48. julee/domain/models/document/tests/factories.py +76 -0
  49. julee/domain/models/document/tests/test_document.py +297 -0
  50. julee/domain/models/knowledge_service_config/__init__.py +17 -0
  51. julee/domain/models/knowledge_service_config/knowledge_service_config.py +86 -0
  52. julee/domain/models/policy/__init__.py +15 -0
  53. julee/domain/models/policy/document_policy_validation.py +220 -0
  54. julee/domain/models/policy/policy.py +203 -0
  55. julee/domain/models/policy/tests/__init__.py +0 -0
  56. julee/domain/models/policy/tests/factories.py +47 -0
  57. julee/domain/models/policy/tests/test_document_policy_validation.py +420 -0
  58. julee/domain/models/policy/tests/test_policy.py +546 -0
  59. julee/domain/repositories/__init__.py +27 -0
  60. julee/domain/repositories/assembly.py +45 -0
  61. julee/domain/repositories/assembly_specification.py +52 -0
  62. julee/domain/repositories/base.py +146 -0
  63. julee/domain/repositories/document.py +49 -0
  64. julee/domain/repositories/document_policy_validation.py +52 -0
  65. julee/domain/repositories/knowledge_service_config.py +54 -0
  66. julee/domain/repositories/knowledge_service_query.py +44 -0
  67. julee/domain/repositories/policy.py +49 -0
  68. julee/domain/use_cases/__init__.py +17 -0
  69. julee/domain/use_cases/decorators.py +107 -0
  70. julee/domain/use_cases/extract_assemble_data.py +649 -0
  71. julee/domain/use_cases/initialize_system_data.py +842 -0
  72. julee/domain/use_cases/tests/__init__.py +7 -0
  73. julee/domain/use_cases/tests/test_extract_assemble_data.py +548 -0
  74. julee/domain/use_cases/tests/test_initialize_system_data.py +455 -0
  75. julee/domain/use_cases/tests/test_validate_document.py +1228 -0
  76. julee/domain/use_cases/validate_document.py +736 -0
  77. julee/fixtures/assembly_specifications.yaml +70 -0
  78. julee/fixtures/documents.yaml +178 -0
  79. julee/fixtures/knowledge_service_configs.yaml +37 -0
  80. julee/fixtures/knowledge_service_queries.yaml +27 -0
  81. julee/repositories/__init__.py +17 -0
  82. julee/repositories/memory/__init__.py +31 -0
  83. julee/repositories/memory/assembly.py +84 -0
  84. julee/repositories/memory/assembly_specification.py +125 -0
  85. julee/repositories/memory/base.py +227 -0
  86. julee/repositories/memory/document.py +149 -0
  87. julee/repositories/memory/document_policy_validation.py +104 -0
  88. julee/repositories/memory/knowledge_service_config.py +123 -0
  89. julee/repositories/memory/knowledge_service_query.py +120 -0
  90. julee/repositories/memory/policy.py +87 -0
  91. julee/repositories/memory/tests/__init__.py +0 -0
  92. julee/repositories/memory/tests/test_document.py +212 -0
  93. julee/repositories/memory/tests/test_document_policy_validation.py +161 -0
  94. julee/repositories/memory/tests/test_policy.py +443 -0
  95. julee/repositories/minio/__init__.py +31 -0
  96. julee/repositories/minio/assembly.py +103 -0
  97. julee/repositories/minio/assembly_specification.py +170 -0
  98. julee/repositories/minio/client.py +570 -0
  99. julee/repositories/minio/document.py +530 -0
  100. julee/repositories/minio/document_policy_validation.py +120 -0
  101. julee/repositories/minio/knowledge_service_config.py +187 -0
  102. julee/repositories/minio/knowledge_service_query.py +211 -0
  103. julee/repositories/minio/policy.py +106 -0
  104. julee/repositories/minio/tests/__init__.py +0 -0
  105. julee/repositories/minio/tests/fake_client.py +213 -0
  106. julee/repositories/minio/tests/test_assembly.py +374 -0
  107. julee/repositories/minio/tests/test_assembly_specification.py +391 -0
  108. julee/repositories/minio/tests/test_client_protocol.py +57 -0
  109. julee/repositories/minio/tests/test_document.py +591 -0
  110. julee/repositories/minio/tests/test_document_policy_validation.py +192 -0
  111. julee/repositories/minio/tests/test_knowledge_service_config.py +374 -0
  112. julee/repositories/minio/tests/test_knowledge_service_query.py +438 -0
  113. julee/repositories/minio/tests/test_policy.py +559 -0
  114. julee/repositories/temporal/__init__.py +38 -0
  115. julee/repositories/temporal/activities.py +114 -0
  116. julee/repositories/temporal/activity_names.py +34 -0
  117. julee/repositories/temporal/proxies.py +159 -0
  118. julee/services/__init__.py +18 -0
  119. julee/services/knowledge_service/__init__.py +48 -0
  120. julee/services/knowledge_service/anthropic/__init__.py +12 -0
  121. julee/services/knowledge_service/anthropic/knowledge_service.py +331 -0
  122. julee/services/knowledge_service/anthropic/tests/test_knowledge_service.py +318 -0
  123. julee/services/knowledge_service/factory.py +138 -0
  124. julee/services/knowledge_service/knowledge_service.py +160 -0
  125. julee/services/knowledge_service/memory/__init__.py +13 -0
  126. julee/services/knowledge_service/memory/knowledge_service.py +278 -0
  127. julee/services/knowledge_service/memory/test_knowledge_service.py +345 -0
  128. julee/services/knowledge_service/test_factory.py +112 -0
  129. julee/services/temporal/__init__.py +38 -0
  130. julee/services/temporal/activities.py +86 -0
  131. julee/services/temporal/activity_names.py +22 -0
  132. julee/services/temporal/proxies.py +41 -0
  133. julee/util/__init__.py +0 -0
  134. julee/util/domain.py +119 -0
  135. julee/util/repos/__init__.py +0 -0
  136. julee/util/repos/minio/__init__.py +0 -0
  137. julee/util/repos/minio/file_storage.py +213 -0
  138. julee/util/repos/temporal/__init__.py +11 -0
  139. julee/util/repos/temporal/client_proxies/file_storage.py +68 -0
  140. julee/util/repos/temporal/data_converter.py +123 -0
  141. julee/util/repos/temporal/minio_file_storage.py +12 -0
  142. julee/util/repos/temporal/proxies/__init__.py +0 -0
  143. julee/util/repos/temporal/proxies/file_storage.py +58 -0
  144. julee/util/repositories.py +55 -0
  145. julee/util/temporal/__init__.py +22 -0
  146. julee/util/temporal/activities.py +123 -0
  147. julee/util/temporal/decorators.py +473 -0
  148. julee/util/tests/__init__.py +1 -0
  149. julee/util/tests/test_decorators.py +770 -0
  150. julee/util/validation/__init__.py +29 -0
  151. julee/util/validation/repository.py +100 -0
  152. julee/util/validation/type_guards.py +369 -0
  153. julee/worker.py +211 -0
  154. julee/workflows/__init__.py +26 -0
  155. julee/workflows/extract_assemble.py +215 -0
  156. julee/workflows/validate_document.py +228 -0
  157. julee-0.1.0.dist-info/METADATA +195 -0
  158. julee-0.1.0.dist-info/RECORD +161 -0
  159. julee-0.1.0.dist-info/WHEEL +5 -0
  160. julee-0.1.0.dist-info/licenses/LICENSE +674 -0
  161. julee-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,43 @@
1
+ """
2
+ API routers for the julee CEAP system.
3
+
4
+ This package contains APIRouter modules that organize endpoints by domain.
5
+ Each router module defines routes at the root level and is mounted with a
6
+ prefix in the main app.
7
+
8
+ Organization:
9
+ - knowledge_service_queries: CRUD operations for knowledge service queries
10
+ - assembly_specifications: CRUD operations for assembly specifications
11
+ - documents: CRUD operations for documents
12
+ - workflows: Workflow management and execution endpoints
13
+ - system: Health checks and system status endpoints
14
+
15
+ Router modules follow the pattern:
16
+ 1. Define routes at root level ("/" and "/{id}")
17
+ 2. Include proper dependency injection
18
+ 3. Use domain models for request/response
19
+ 4. Follow consistent error handling patterns
20
+ """
21
+
22
+ # Import routers for convenient access
23
+ from julee.api.routers.knowledge_service_queries import (
24
+ router as knowledge_service_queries_router,
25
+ )
26
+ from julee.api.routers.knowledge_service_configs import (
27
+ router as knowledge_service_configs_router,
28
+ )
29
+ from julee.api.routers.assembly_specifications import (
30
+ router as assembly_specifications_router,
31
+ )
32
+ from julee.api.routers.system import router as system_router
33
+ from julee.api.routers.documents import router as documents_router
34
+ from julee.api.routers.workflows import router as workflows_router
35
+
36
+ __all__ = [
37
+ "knowledge_service_queries_router",
38
+ "knowledge_service_configs_router",
39
+ "assembly_specifications_router",
40
+ "documents_router",
41
+ "workflows_router",
42
+ "system_router",
43
+ ]
@@ -0,0 +1,212 @@
1
+ """
2
+ Assembly Specifications API router for the julee CEAP system.
3
+
4
+ This module provides the API endpoints for assembly specifications,
5
+ which define how to assemble documents of specific types including
6
+ JSON schemas and knowledge service query configurations.
7
+
8
+ Routes defined at root level:
9
+ - GET / - List assembly specifications (paginated)
10
+ - GET /{id} - Get a specific assembly specification by ID
11
+
12
+ These routes are mounted at /assembly_specifications in the main app.
13
+ """
14
+
15
+ import logging
16
+ from typing import cast
17
+ from fastapi import APIRouter, Depends, HTTPException, Path
18
+ from fastapi_pagination import Page, paginate
19
+
20
+ from julee.domain.models import AssemblySpecification
21
+ from julee.domain.repositories.assembly_specification import (
22
+ AssemblySpecificationRepository,
23
+ )
24
+ from julee.api.dependencies import (
25
+ get_assembly_specification_repository,
26
+ )
27
+ from julee.api.requests import CreateAssemblySpecificationRequest
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ # Create the router for assembly specifications
32
+ router = APIRouter()
33
+
34
+
35
+ @router.get("/", response_model=Page[AssemblySpecification])
36
+ async def get_assembly_specifications(
37
+ repository: AssemblySpecificationRepository = Depends( # type: ignore[misc]
38
+ get_assembly_specification_repository
39
+ ),
40
+ ) -> Page[AssemblySpecification]:
41
+ """
42
+ Get a paginated list of assembly specifications.
43
+
44
+ This endpoint returns all assembly specifications in the system
45
+ with pagination support. Each specification contains the configuration
46
+ needed to define how to assemble documents of specific types.
47
+
48
+ Returns:
49
+ Page[AssemblySpecification]: Paginated list of specifications
50
+ """
51
+ logger.info("Assembly specifications requested")
52
+
53
+ try:
54
+ # Get all assembly specifications from the repository
55
+ specifications = await repository.list_all()
56
+
57
+ logger.info(
58
+ "Assembly specifications retrieved successfully",
59
+ extra={"count": len(specifications)},
60
+ )
61
+
62
+ # Use fastapi-pagination to paginate the results
63
+ return cast(Page[AssemblySpecification], paginate(specifications))
64
+
65
+ except Exception as e:
66
+ logger.error(
67
+ "Failed to retrieve assembly specifications",
68
+ exc_info=True,
69
+ extra={"error_type": type(e).__name__, "error_message": str(e)},
70
+ )
71
+ raise HTTPException(
72
+ status_code=500,
73
+ detail="Failed to retrieve specifications due to an internal " "error.",
74
+ )
75
+
76
+
77
+ @router.get("/{assembly_specification_id}", response_model=AssemblySpecification)
78
+ async def get_assembly_specification(
79
+ assembly_specification_id: str = Path(
80
+ description="The ID of the assembly specification to retrieve"
81
+ ),
82
+ repository: AssemblySpecificationRepository = Depends( # type: ignore[misc]
83
+ get_assembly_specification_repository
84
+ ),
85
+ ) -> AssemblySpecification:
86
+ """
87
+ Get a specific assembly specification by ID.
88
+
89
+ This endpoint retrieves a single assembly specification by its unique
90
+ identifier. The specification contains the JSON schema and knowledge
91
+ service query configurations needed for document assembly.
92
+
93
+ Args:
94
+ assembly_specification_id: The unique ID of the specification
95
+
96
+ Returns:
97
+ AssemblySpecification: The requested specification
98
+
99
+ Raises:
100
+ HTTPException: 404 if specification not found, 500 for other errors
101
+ """
102
+ logger.info(
103
+ "Assembly specification requested",
104
+ extra={"assembly_specification_id": assembly_specification_id},
105
+ )
106
+
107
+ try:
108
+ # Get the specific assembly specification from the repository
109
+ specification = await repository.get(assembly_specification_id)
110
+
111
+ if specification is None:
112
+ logger.warning(
113
+ "Assembly specification not found",
114
+ extra={"assembly_specification_id": assembly_specification_id},
115
+ )
116
+ raise HTTPException(
117
+ status_code=404,
118
+ detail=f"Assembly specification with ID "
119
+ f"'{assembly_specification_id}' not found.",
120
+ )
121
+
122
+ logger.info(
123
+ "Assembly specification retrieved successfully",
124
+ extra={
125
+ "assembly_specification_id": assembly_specification_id,
126
+ "specification_name": specification.name,
127
+ },
128
+ )
129
+
130
+ return specification
131
+
132
+ except HTTPException:
133
+ # Re-raise HTTP exceptions (like 404)
134
+ raise
135
+ except Exception as e:
136
+ logger.error(
137
+ "Failed to retrieve assembly specification",
138
+ exc_info=True,
139
+ extra={
140
+ "error_type": type(e).__name__,
141
+ "error_message": str(e),
142
+ "assembly_specification_id": assembly_specification_id,
143
+ },
144
+ )
145
+ raise HTTPException(
146
+ status_code=500,
147
+ detail="Failed to retrieve specification due to an internal " "error.",
148
+ )
149
+
150
+
151
+ @router.post("/", response_model=AssemblySpecification)
152
+ async def create_assembly_specification(
153
+ request: CreateAssemblySpecificationRequest,
154
+ repository: AssemblySpecificationRepository = Depends( # type: ignore[misc]
155
+ get_assembly_specification_repository
156
+ ),
157
+ ) -> AssemblySpecification:
158
+ """
159
+ Create a new assembly specification.
160
+
161
+ This endpoint creates a new assembly specification that defines how to
162
+ assemble documents of specific types, including JSON schemas and
163
+ knowledge service query configurations.
164
+
165
+ Args:
166
+ request: The assembly specification creation request
167
+ repository: Injected repository for persistence
168
+
169
+ Returns:
170
+ AssemblySpecification: The created specification with generated ID and
171
+ timestamps
172
+ """
173
+ logger.info(
174
+ "Assembly specification creation requested",
175
+ extra={"specification_name": request.name},
176
+ )
177
+
178
+ try:
179
+ # Generate unique ID for the new specification
180
+ specification_id = await repository.generate_id()
181
+
182
+ # Convert request to domain model with generated ID
183
+ specification = request.to_domain_model(specification_id)
184
+
185
+ # Save the specification via repository
186
+ await repository.save(specification)
187
+
188
+ logger.info(
189
+ "Assembly specification created successfully",
190
+ extra={
191
+ "assembly_specification_id": (specification.assembly_specification_id),
192
+ "specification_name": specification.name,
193
+ "version": specification.version,
194
+ },
195
+ )
196
+
197
+ return specification
198
+
199
+ except Exception as e:
200
+ logger.error(
201
+ "Failed to create assembly specification",
202
+ exc_info=True,
203
+ extra={
204
+ "error_type": type(e).__name__,
205
+ "error_message": str(e),
206
+ "specification_name": request.name,
207
+ },
208
+ )
209
+ raise HTTPException(
210
+ status_code=500,
211
+ detail="Failed to create specification due to an internal error.",
212
+ )
@@ -0,0 +1,182 @@
1
+ """
2
+ Documents API router for the julee CEAP system.
3
+
4
+ This module provides document management API endpoints for retrieving
5
+ and managing documents in the system.
6
+
7
+ Routes defined at root level:
8
+ - GET / - List all documents with pagination
9
+ - GET /{document_id} - Get document metadata by ID
10
+ - GET /{document_id}/content - Get document content by ID
11
+
12
+ These routes are mounted with '/documents' prefix in the main app.
13
+ """
14
+
15
+ import logging
16
+ from typing import cast
17
+
18
+ from fastapi import APIRouter, Depends, HTTPException, Path
19
+ from fastapi.responses import Response
20
+ from fastapi_pagination import Page, paginate
21
+
22
+ from julee.domain.models.document import Document
23
+ from julee.domain.repositories.document import DocumentRepository
24
+ from julee.api.dependencies import get_document_repository
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ router = APIRouter()
29
+
30
+
31
+ @router.get("/", response_model=Page[Document])
32
+ async def list_documents(
33
+ repository: DocumentRepository = Depends(get_document_repository),
34
+ ) -> Page[Document]:
35
+ """
36
+ List all documents with pagination.
37
+
38
+ Args:
39
+ repository: Document repository dependency
40
+
41
+ Returns:
42
+ Paginated list of documents
43
+
44
+ Raises:
45
+ HTTPException: If repository operation fails
46
+ """
47
+ try:
48
+ logger.info("Listing documents")
49
+
50
+ # Get all documents from repository
51
+ documents = await repository.list_all()
52
+
53
+ logger.info("Retrieved %d documents", len(documents))
54
+
55
+ # Return paginated result using fastapi-pagination
56
+ return cast(Page[Document], paginate(documents))
57
+
58
+ except Exception as e:
59
+ logger.error("Failed to list documents: %s", e)
60
+ raise HTTPException(
61
+ status_code=500, detail="Failed to retrieve documents"
62
+ ) from e
63
+
64
+
65
+ @router.get("/{document_id}", response_model=Document)
66
+ async def get_document(
67
+ document_id: str = Path(..., description="Document ID"),
68
+ repository: DocumentRepository = Depends(get_document_repository),
69
+ ) -> Document:
70
+ """
71
+ Get a single document by ID with metadata only.
72
+
73
+ Args:
74
+ document_id: Unique document identifier
75
+ repository: Document repository dependency
76
+
77
+ Returns:
78
+ Document with metadata only (no content)
79
+
80
+ Raises:
81
+ HTTPException: If document not found or repository operation fails
82
+ """
83
+ try:
84
+ logger.info("Retrieving document metadata: %s", document_id)
85
+
86
+ # Get document from repository
87
+ document = await repository.get(document_id)
88
+
89
+ if not document:
90
+ raise HTTPException(
91
+ status_code=404,
92
+ detail=f"Document with ID '{document_id}' not found",
93
+ )
94
+
95
+ logger.info("Retrieved document metadata: %s", document_id)
96
+ return document
97
+
98
+ except HTTPException:
99
+ # Re-raise HTTP exceptions (like 404) without wrapping
100
+ raise
101
+ except Exception as e:
102
+ logger.error("Failed to get document %s: %s", document_id, e)
103
+ raise HTTPException(
104
+ status_code=500, detail="Failed to retrieve document"
105
+ ) from e
106
+
107
+
108
+ @router.get("/{document_id}/content")
109
+ async def get_document_content(
110
+ document_id: str = Path(..., description="Document ID"),
111
+ repository: DocumentRepository = Depends(get_document_repository),
112
+ ) -> Response:
113
+ """
114
+ Get the content of a document by ID.
115
+
116
+ Args:
117
+ document_id: Unique document identifier
118
+ repository: Document repository dependency
119
+
120
+ Returns:
121
+ Raw document content with appropriate Content-Type header
122
+
123
+ Raises:
124
+ HTTPException: If document not found or has no content
125
+ """
126
+ try:
127
+ logger.info("Retrieving document content: %s", document_id)
128
+
129
+ # Get document from repository
130
+ document = await repository.get(document_id)
131
+
132
+ if not document:
133
+ raise HTTPException(
134
+ status_code=404,
135
+ detail=f"Document with ID '{document_id}' not found",
136
+ )
137
+
138
+ if not document.content:
139
+ raise HTTPException(
140
+ status_code=422,
141
+ detail=f"Document '{document_id}' has no content",
142
+ )
143
+
144
+ try:
145
+ # Read content
146
+ content_bytes = document.content.read()
147
+
148
+ logger.info(
149
+ "Retrieved document content: %s (%d bytes)",
150
+ document_id,
151
+ len(content_bytes),
152
+ )
153
+
154
+ # Return content with appropriate Content-Type
155
+ return Response(
156
+ content=content_bytes,
157
+ media_type=document.content_type,
158
+ headers={
159
+ "Content-Disposition": (
160
+ f'inline; filename="{document.original_filename}"'
161
+ )
162
+ },
163
+ )
164
+
165
+ except Exception as content_error:
166
+ logger.error(
167
+ "Failed to read content for document %s: %s",
168
+ document_id,
169
+ content_error,
170
+ )
171
+ raise HTTPException(
172
+ status_code=500, detail="Failed to read document content"
173
+ ) from content_error
174
+
175
+ except HTTPException:
176
+ # Re-raise HTTP exceptions (like 404) without wrapping
177
+ raise
178
+ except Exception as e:
179
+ logger.error("Failed to get document content %s: %s", document_id, e)
180
+ raise HTTPException(
181
+ status_code=500, detail="Failed to retrieve document content"
182
+ ) from e
@@ -0,0 +1,79 @@
1
+ """
2
+ Knowledge Service Configs API router for the julee CEAP system.
3
+
4
+ This module provides the API endpoints for knowledge service configurations,
5
+ which define the available knowledge services that can be used for extracting
6
+ data during the assembly process.
7
+
8
+ Routes defined at root level:
9
+ - GET / - List all knowledge service configurations (paginated)
10
+
11
+ These routes are mounted at /knowledge_service_configs in the main app.
12
+ """
13
+
14
+ import logging
15
+ from typing import cast
16
+ from fastapi import APIRouter, Depends, HTTPException
17
+ from fastapi_pagination import Page, paginate
18
+
19
+ from julee.domain.models.knowledge_service_config import (
20
+ KnowledgeServiceConfig,
21
+ )
22
+ from julee.domain.repositories.knowledge_service_config import (
23
+ KnowledgeServiceConfigRepository,
24
+ )
25
+ from julee.api.dependencies import (
26
+ get_knowledge_service_config_repository,
27
+ )
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+ # Create the router for knowledge service configurations
32
+ router = APIRouter()
33
+
34
+
35
+ @router.get("/", response_model=Page[KnowledgeServiceConfig])
36
+ async def get_knowledge_service_configs(
37
+ repository: KnowledgeServiceConfigRepository = Depends( # type: ignore[misc]
38
+ get_knowledge_service_config_repository
39
+ ),
40
+ ) -> Page[KnowledgeServiceConfig]:
41
+ """
42
+ Get all knowledge service configurations with pagination.
43
+
44
+ This endpoint returns all available knowledge service configurations
45
+ that can be used when creating knowledge service queries. Each
46
+ configuration contains the metadata needed to interact with a specific
47
+ external knowledge service.
48
+
49
+ Returns:
50
+ Page[KnowledgeServiceConfig]: Paginated list of all knowledge
51
+ service configurations
52
+ """
53
+ logger.info("All knowledge service configurations requested")
54
+
55
+ try:
56
+ # Get all knowledge service configurations from the repository
57
+ configs = await repository.list_all()
58
+
59
+ logger.info(
60
+ "Knowledge service configurations retrieved successfully",
61
+ extra={"count": len(configs)},
62
+ )
63
+
64
+ # Use fastapi-pagination to paginate the results
65
+ return cast(Page[KnowledgeServiceConfig], paginate(configs))
66
+
67
+ except Exception as e:
68
+ logger.error(
69
+ "Failed to retrieve knowledge service configurations",
70
+ exc_info=True,
71
+ extra={
72
+ "error_type": type(e).__name__,
73
+ "error_message": str(e),
74
+ },
75
+ )
76
+ raise HTTPException(
77
+ status_code=500,
78
+ detail="Failed to retrieve configurations due to an " "internal error.",
79
+ )