julee 0.1.2__py3-none-any.whl → 0.1.4__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 (158) hide show
  1. julee/api/app.py +9 -8
  2. julee/api/dependencies.py +15 -15
  3. julee/api/requests.py +10 -9
  4. julee/api/responses.py +2 -1
  5. julee/api/routers/__init__.py +5 -5
  6. julee/api/routers/assembly_specifications.py +5 -4
  7. julee/api/routers/documents.py +1 -1
  8. julee/api/routers/knowledge_service_configs.py +4 -3
  9. julee/api/routers/knowledge_service_queries.py +7 -6
  10. julee/api/routers/system.py +4 -3
  11. julee/api/routers/workflows.py +4 -5
  12. julee/api/services/system_initialization.py +6 -6
  13. julee/api/tests/routers/test_assembly_specifications.py +4 -3
  14. julee/api/tests/routers/test_documents.py +11 -10
  15. julee/api/tests/routers/test_knowledge_service_configs.py +7 -6
  16. julee/api/tests/routers/test_knowledge_service_queries.py +4 -3
  17. julee/api/tests/routers/test_system.py +5 -4
  18. julee/api/tests/routers/test_workflows.py +5 -4
  19. julee/api/tests/test_app.py +5 -4
  20. julee/api/tests/test_dependencies.py +3 -2
  21. julee/api/tests/test_requests.py +2 -1
  22. julee/contrib/__init__.py +15 -0
  23. julee/contrib/polling/__init__.py +47 -0
  24. julee/contrib/polling/domain/__init__.py +17 -0
  25. julee/contrib/polling/domain/models/__init__.py +13 -0
  26. julee/contrib/polling/domain/models/polling_config.py +39 -0
  27. julee/contrib/polling/domain/services/__init__.py +11 -0
  28. julee/contrib/polling/domain/services/poller.py +39 -0
  29. julee/contrib/polling/infrastructure/__init__.py +15 -0
  30. julee/contrib/polling/infrastructure/services/__init__.py +12 -0
  31. julee/contrib/polling/infrastructure/services/polling/__init__.py +12 -0
  32. julee/contrib/polling/infrastructure/services/polling/http/__init__.py +12 -0
  33. julee/contrib/polling/infrastructure/services/polling/http/http_poller_service.py +80 -0
  34. julee/contrib/polling/infrastructure/temporal/__init__.py +20 -0
  35. julee/contrib/polling/infrastructure/temporal/activities.py +42 -0
  36. julee/contrib/polling/infrastructure/temporal/activity_names.py +20 -0
  37. julee/contrib/polling/infrastructure/temporal/proxies.py +45 -0
  38. julee/contrib/polling/tests/__init__.py +6 -0
  39. julee/contrib/polling/tests/unit/__init__.py +6 -0
  40. julee/contrib/polling/tests/unit/infrastructure/__init__.py +7 -0
  41. julee/contrib/polling/tests/unit/infrastructure/services/__init__.py +6 -0
  42. julee/contrib/polling/tests/unit/infrastructure/services/polling/__init__.py +6 -0
  43. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/__init__.py +7 -0
  44. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/test_http_poller_service.py +163 -0
  45. julee/docs/__init__.py +5 -0
  46. julee/docs/sphinx_hcd/__init__.py +76 -0
  47. julee/docs/sphinx_hcd/accelerators.py +1175 -0
  48. julee/docs/sphinx_hcd/apps.py +518 -0
  49. julee/docs/sphinx_hcd/config.py +148 -0
  50. julee/docs/sphinx_hcd/epics.py +453 -0
  51. julee/docs/sphinx_hcd/integrations.py +310 -0
  52. julee/docs/sphinx_hcd/journeys.py +797 -0
  53. julee/docs/sphinx_hcd/personas.py +457 -0
  54. julee/docs/sphinx_hcd/stories.py +960 -0
  55. julee/docs/sphinx_hcd/utils.py +185 -0
  56. julee/domain/models/__init__.py +5 -6
  57. julee/domain/models/assembly/assembly.py +7 -7
  58. julee/domain/models/assembly/tests/factories.py +2 -1
  59. julee/domain/models/assembly/tests/test_assembly.py +16 -13
  60. julee/domain/models/assembly_specification/assembly_specification.py +11 -10
  61. julee/domain/models/assembly_specification/knowledge_service_query.py +7 -6
  62. julee/domain/models/assembly_specification/tests/factories.py +2 -1
  63. julee/domain/models/assembly_specification/tests/test_assembly_specification.py +9 -6
  64. julee/domain/models/assembly_specification/tests/test_knowledge_service_query.py +3 -1
  65. julee/domain/models/custom_fields/content_stream.py +3 -2
  66. julee/domain/models/custom_fields/tests/test_custom_fields.py +2 -1
  67. julee/domain/models/document/document.py +23 -30
  68. julee/domain/models/document/tests/factories.py +3 -2
  69. julee/domain/models/document/tests/test_document.py +20 -37
  70. julee/domain/models/knowledge_service_config/knowledge_service_config.py +4 -4
  71. julee/domain/models/policy/__init__.py +4 -4
  72. julee/domain/models/policy/document_policy_validation.py +17 -17
  73. julee/domain/models/policy/policy.py +10 -10
  74. julee/domain/models/policy/tests/factories.py +2 -1
  75. julee/domain/models/policy/tests/test_document_policy_validation.py +3 -1
  76. julee/domain/models/policy/tests/test_policy.py +2 -1
  77. julee/domain/repositories/__init__.py +3 -3
  78. julee/domain/repositories/assembly.py +3 -1
  79. julee/domain/repositories/assembly_specification.py +2 -0
  80. julee/domain/repositories/base.py +5 -4
  81. julee/domain/repositories/document.py +3 -1
  82. julee/domain/repositories/document_policy_validation.py +3 -1
  83. julee/domain/repositories/knowledge_service_config.py +2 -0
  84. julee/domain/repositories/knowledge_service_query.py +1 -0
  85. julee/domain/repositories/policy.py +3 -1
  86. julee/domain/use_cases/decorators.py +3 -2
  87. julee/domain/use_cases/extract_assemble_data.py +14 -13
  88. julee/domain/use_cases/initialize_system_data.py +88 -34
  89. julee/domain/use_cases/tests/test_extract_assemble_data.py +10 -10
  90. julee/domain/use_cases/tests/test_initialize_system_data.py +2 -2
  91. julee/domain/use_cases/tests/test_validate_document.py +11 -11
  92. julee/domain/use_cases/validate_document.py +14 -14
  93. julee/fixtures/documents.yaml +4 -43
  94. julee/fixtures/knowledge_service_queries.yaml +9 -0
  95. julee/maintenance/__init__.py +1 -0
  96. julee/maintenance/release.py +243 -0
  97. julee/repositories/memory/assembly.py +6 -5
  98. julee/repositories/memory/assembly_specification.py +8 -9
  99. julee/repositories/memory/base.py +12 -11
  100. julee/repositories/memory/document.py +27 -20
  101. julee/repositories/memory/document_policy_validation.py +7 -6
  102. julee/repositories/memory/knowledge_service_config.py +8 -7
  103. julee/repositories/memory/knowledge_service_query.py +8 -7
  104. julee/repositories/memory/policy.py +6 -5
  105. julee/repositories/memory/tests/test_document.py +24 -22
  106. julee/repositories/memory/tests/test_document_policy_validation.py +2 -1
  107. julee/repositories/memory/tests/test_policy.py +2 -1
  108. julee/repositories/minio/assembly.py +4 -4
  109. julee/repositories/minio/assembly_specification.py +6 -8
  110. julee/repositories/minio/client.py +22 -25
  111. julee/repositories/minio/document.py +36 -33
  112. julee/repositories/minio/document_policy_validation.py +5 -5
  113. julee/repositories/minio/knowledge_service_config.py +6 -6
  114. julee/repositories/minio/knowledge_service_query.py +6 -9
  115. julee/repositories/minio/policy.py +4 -4
  116. julee/repositories/minio/tests/fake_client.py +11 -9
  117. julee/repositories/minio/tests/test_assembly.py +3 -1
  118. julee/repositories/minio/tests/test_assembly_specification.py +2 -1
  119. julee/repositories/minio/tests/test_client_protocol.py +5 -5
  120. julee/repositories/minio/tests/test_document.py +23 -22
  121. julee/repositories/minio/tests/test_document_policy_validation.py +3 -1
  122. julee/repositories/minio/tests/test_knowledge_service_config.py +4 -2
  123. julee/repositories/minio/tests/test_knowledge_service_query.py +3 -2
  124. julee/repositories/minio/tests/test_policy.py +3 -1
  125. julee/repositories/temporal/activities.py +5 -5
  126. julee/repositories/temporal/proxies.py +5 -5
  127. julee/services/knowledge_service/__init__.py +1 -2
  128. julee/services/knowledge_service/anthropic/knowledge_service.py +8 -7
  129. julee/services/knowledge_service/anthropic/tests/test_knowledge_service.py +11 -10
  130. julee/services/knowledge_service/factory.py +8 -8
  131. julee/services/knowledge_service/knowledge_service.py +12 -14
  132. julee/services/knowledge_service/memory/knowledge_service.py +13 -12
  133. julee/services/knowledge_service/memory/test_knowledge_service.py +10 -7
  134. julee/services/knowledge_service/test_factory.py +11 -10
  135. julee/services/temporal/activities.py +10 -10
  136. julee/services/temporal/proxies.py +2 -2
  137. julee/util/domain.py +6 -6
  138. julee/util/repos/minio/file_storage.py +8 -9
  139. julee/util/repos/temporal/client_proxies/file_storage.py +3 -4
  140. julee/util/repos/temporal/data_converter.py +6 -6
  141. julee/util/repos/temporal/minio_file_storage.py +1 -1
  142. julee/util/repos/temporal/proxies/file_storage.py +2 -3
  143. julee/util/repositories.py +4 -3
  144. julee/util/temporal/decorators.py +20 -18
  145. julee/util/tests/test_decorators.py +13 -15
  146. julee/util/validation/repository.py +3 -3
  147. julee/util/validation/type_guards.py +12 -11
  148. julee/worker.py +9 -8
  149. julee/workflows/__init__.py +2 -2
  150. julee/workflows/extract_assemble.py +2 -1
  151. julee/workflows/validate_document.py +3 -2
  152. {julee-0.1.2.dist-info → julee-0.1.4.dist-info}/METADATA +3 -3
  153. julee-0.1.4.dist-info/RECORD +196 -0
  154. julee/fixtures/assembly_specifications.yaml +0 -70
  155. julee-0.1.2.dist-info/RECORD +0 -161
  156. {julee-0.1.2.dist-info → julee-0.1.4.dist-info}/WHEEL +0 -0
  157. {julee-0.1.2.dist-info → julee-0.1.4.dist-info}/licenses/LICENSE +0 -0
  158. {julee-0.1.2.dist-info → julee-0.1.4.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,6 @@ key.
14
14
  """
15
15
 
16
16
  import logging
17
- from typing import Optional, List, Dict
18
17
 
19
18
  from julee.domain.models.knowledge_service_config import (
20
19
  KnowledgeServiceConfig,
@@ -22,6 +21,7 @@ from julee.domain.models.knowledge_service_config import (
22
21
  from julee.domain.repositories.knowledge_service_config import (
23
22
  KnowledgeServiceConfigRepository,
24
23
  )
24
+
25
25
  from .client import MinioClient, MinioRepositoryMixin
26
26
 
27
27
 
@@ -53,7 +53,7 @@ class MinioKnowledgeServiceConfigRepository(
53
53
  self.bucket_name = "knowledge-service-configs"
54
54
  self.ensure_buckets_exist(self.bucket_name)
55
55
 
56
- async def get(self, knowledge_service_id: str) -> Optional[KnowledgeServiceConfig]:
56
+ async def get(self, knowledge_service_id: str) -> KnowledgeServiceConfig | None:
57
57
  """Retrieve a knowledge service configuration by ID.
58
58
 
59
59
  Args:
@@ -98,8 +98,8 @@ class MinioKnowledgeServiceConfigRepository(
98
98
  )
99
99
 
100
100
  async def get_many(
101
- self, knowledge_service_ids: List[str]
102
- ) -> Dict[str, Optional[KnowledgeServiceConfig]]:
101
+ self, knowledge_service_ids: list[str]
102
+ ) -> dict[str, KnowledgeServiceConfig | None]:
103
103
  """Retrieve multiple knowledge service configs by ID.
104
104
 
105
105
  Args:
@@ -124,7 +124,7 @@ class MinioKnowledgeServiceConfigRepository(
124
124
  )
125
125
 
126
126
  # Convert object names back to knowledge service IDs for the result
127
- result: Dict[str, Optional[KnowledgeServiceConfig]] = {}
127
+ result: dict[str, KnowledgeServiceConfig | None] = {}
128
128
  for i, service_id in enumerate(knowledge_service_ids):
129
129
  object_name = object_names[i]
130
130
  result[service_id] = object_results[object_name]
@@ -139,7 +139,7 @@ class MinioKnowledgeServiceConfigRepository(
139
139
  """
140
140
  return self.generate_id_with_prefix("ks")
141
141
 
142
- async def list_all(self) -> List[KnowledgeServiceConfig]:
142
+ async def list_all(self) -> list[KnowledgeServiceConfig]:
143
143
  """List all knowledge service configurations.
144
144
 
145
145
  Returns:
@@ -16,17 +16,14 @@ Each query is stored as a separate object with the query ID as the key.
16
16
  import logging
17
17
  import uuid
18
18
 
19
- from typing import Optional, List, Dict
20
-
21
-
22
19
  from julee.domain.models.assembly_specification import (
23
20
  KnowledgeServiceQuery,
24
21
  )
25
- from .client import MinioClient, MinioRepositoryMixin
26
22
  from julee.domain.repositories.knowledge_service_query import (
27
23
  KnowledgeServiceQueryRepository,
28
24
  )
29
25
 
26
+ from .client import MinioClient, MinioRepositoryMixin
30
27
 
31
28
  logger = logging.getLogger(__name__)
32
29
 
@@ -54,7 +51,7 @@ class MinioKnowledgeServiceQueryRepository(
54
51
  self.bucket_name = "knowledge-service-queries"
55
52
  self.ensure_buckets_exist(self.bucket_name)
56
53
 
57
- async def get(self, query_id: str) -> Optional[KnowledgeServiceQuery]:
54
+ async def get(self, query_id: str) -> KnowledgeServiceQuery | None:
58
55
  """Retrieve a knowledge service query by ID.
59
56
 
60
57
  Args:
@@ -124,8 +121,8 @@ class MinioKnowledgeServiceQueryRepository(
124
121
  return query_id
125
122
 
126
123
  async def get_many(
127
- self, query_ids: List[str]
128
- ) -> Dict[str, Optional[KnowledgeServiceQuery]]:
124
+ self, query_ids: list[str]
125
+ ) -> dict[str, KnowledgeServiceQuery | None]:
129
126
  """Retrieve multiple knowledge service queries by ID.
130
127
 
131
128
  Args:
@@ -159,14 +156,14 @@ class MinioKnowledgeServiceQueryRepository(
159
156
  )
160
157
 
161
158
  # Convert object names back to query IDs for the result
162
- result: Dict[str, Optional[KnowledgeServiceQuery]] = {}
159
+ result: dict[str, KnowledgeServiceQuery | None] = {}
163
160
  for i, query_id in enumerate(query_ids):
164
161
  object_name = object_names[i]
165
162
  result[query_id] = object_results[object_name]
166
163
 
167
164
  return result
168
165
 
169
- async def list_all(self) -> List[KnowledgeServiceQuery]:
166
+ async def list_all(self) -> list[KnowledgeServiceQuery]:
170
167
  """List all knowledge service queries.
171
168
 
172
169
  Returns:
@@ -13,10 +13,10 @@ and transformation queries.
13
13
  """
14
14
 
15
15
  import logging
16
- from typing import Optional, List, Dict
17
16
 
18
17
  from julee.domain.models.policy import Policy
19
18
  from julee.domain.repositories.policy import PolicyRepository
19
+
20
20
  from .client import MinioClient, MinioRepositoryMixin
21
21
 
22
22
 
@@ -40,7 +40,7 @@ class MinioPolicyRepository(PolicyRepository, MinioRepositoryMixin):
40
40
  self.policies_bucket = "policies"
41
41
  self.ensure_buckets_exist(self.policies_bucket)
42
42
 
43
- async def get(self, policy_id: str) -> Optional[Policy]:
43
+ async def get(self, policy_id: str) -> Policy | None:
44
44
  """Retrieve a policy by ID."""
45
45
  return self.get_json_object(
46
46
  bucket_name=self.policies_bucket,
@@ -72,7 +72,7 @@ class MinioPolicyRepository(PolicyRepository, MinioRepositoryMixin):
72
72
  },
73
73
  )
74
74
 
75
- async def get_many(self, policy_ids: List[str]) -> Dict[str, Optional[Policy]]:
75
+ async def get_many(self, policy_ids: list[str]) -> dict[str, Policy | None]:
76
76
  """Retrieve multiple policies by ID.
77
77
 
78
78
  Args:
@@ -95,7 +95,7 @@ class MinioPolicyRepository(PolicyRepository, MinioRepositoryMixin):
95
95
  )
96
96
 
97
97
  # Convert object names back to policy IDs for the result
98
- result: Dict[str, Optional[Policy]] = {}
98
+ result: dict[str, Policy | None] = {}
99
99
  for policy_id in policy_ids:
100
100
  result[policy_id] = object_results[policy_id]
101
101
 
@@ -7,15 +7,17 @@ state-based testing where you can verify actual storage state rather than
7
7
  just mocking method calls.
8
8
  """
9
9
 
10
- from typing import Dict, Any, Optional, Callable, BinaryIO, Union, List
10
+ from collections.abc import Callable
11
+ from datetime import datetime, timezone
11
12
  from functools import wraps
13
+ from typing import Any, BinaryIO
12
14
  from unittest.mock import Mock
13
- from datetime import datetime, timezone
14
- from minio.error import S3Error
15
- from minio.datatypes import Object
15
+
16
16
  from minio.api import ObjectWriteResult
17
- from urllib3.response import BaseHTTPResponse
17
+ from minio.datatypes import Object
18
+ from minio.error import S3Error
18
19
  from urllib3 import HTTPHeaderDict
20
+ from urllib3.response import BaseHTTPResponse
19
21
 
20
22
  from ..client import MinioClient
21
23
 
@@ -83,8 +85,8 @@ class FakeMinioClient(MinioClient):
83
85
  """
84
86
 
85
87
  def __init__(self) -> None:
86
- self._buckets: Dict[str, Dict[str, Any]] = {}
87
- self._objects: Dict[str, Dict[str, Dict[str, Any]]] = {}
88
+ self._buckets: dict[str, dict[str, Any]] = {}
89
+ self._objects: dict[str, dict[str, dict[str, Any]]] = {}
88
90
 
89
91
  def bucket_exists(self, bucket_name: str) -> bool:
90
92
  """Check if a bucket exists."""
@@ -112,7 +114,7 @@ class FakeMinioClient(MinioClient):
112
114
  data: BinaryIO,
113
115
  length: int,
114
116
  content_type: str = "application/octet-stream",
115
- metadata: Optional[Dict[str, Union[str, List[str], tuple[str]]]] = None,
117
+ metadata: dict[str, str | list[str] | tuple[str]] | None = None,
116
118
  ) -> ObjectWriteResult:
117
119
  """Store an object in the bucket."""
118
120
 
@@ -195,7 +197,7 @@ class FakeMinioClient(MinioClient):
195
197
  del self._objects[bucket_name][object_name]
196
198
 
197
199
  # Inspection methods for testing
198
- def get_stored_objects(self, bucket_name: str) -> Dict[str, Dict[str, Any]]:
200
+ def get_stored_objects(self, bucket_name: str) -> dict[str, dict[str, Any]]:
199
201
  """Get all stored objects in a bucket (for testing purposes)."""
200
202
  return self._objects.get(bucket_name, {}).copy()
201
203
 
@@ -6,11 +6,13 @@ repository implementation, using the fake client to avoid external
6
6
  dependencies during testing.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
 
11
+ import pytest
12
+
12
13
  from julee.domain.models.assembly import Assembly, AssemblyStatus
13
14
  from julee.repositories.minio.assembly import MinioAssemblyRepository
15
+
14
16
  from .fake_client import FakeMinioClient
15
17
 
16
18
 
@@ -6,9 +6,9 @@ specification repository implementation, using the fake client to avoid
6
6
  external dependencies during testing.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
 
11
+ import pytest
12
12
 
13
13
  from julee.domain.models.assembly_specification import (
14
14
  AssemblySpecification,
@@ -17,6 +17,7 @@ from julee.domain.models.assembly_specification import (
17
17
  from julee.repositories.minio.assembly_specification import (
18
18
  MinioAssemblySpecificationRepository,
19
19
  )
20
+
20
21
  from .fake_client import FakeMinioClient
21
22
 
22
23
 
@@ -34,11 +34,11 @@ class TestMinioClientProtocol:
34
34
  assert hasattr(real_client, "stat_object")
35
35
 
36
36
  # Test that methods are callable
37
- assert callable(getattr(real_client, "bucket_exists"))
38
- assert callable(getattr(real_client, "make_bucket"))
39
- assert callable(getattr(real_client, "put_object"))
40
- assert callable(getattr(real_client, "get_object"))
41
- assert callable(getattr(real_client, "stat_object"))
37
+ assert callable(real_client.bucket_exists)
38
+ assert callable(real_client.make_bucket)
39
+ assert callable(real_client.put_object)
40
+ assert callable(real_client.get_object)
41
+ assert callable(real_client.stat_object)
42
42
 
43
43
  def test_protocol_accepts_real_minio_client(self) -> None:
44
44
  """Test that our protocol accepts a real Minio client instance."""
@@ -6,20 +6,21 @@ without requiring a real MinIO instance. They follow the Clean Architecture
6
6
  testing patterns and verify idempotency, error handling, and content.
7
7
  """
8
8
 
9
- import io
10
- import pytest
11
9
  import hashlib
12
- import multihash
10
+ import io
13
11
  from typing import Any
14
12
  from unittest.mock import Mock
15
- from minio.error import S3Error
16
13
 
14
+ import multihash
15
+ import pytest
16
+ from minio.error import S3Error
17
17
 
18
- from julee.repositories.minio.document import MinioDocumentRepository
19
- from julee.domain.models.document import Document, DocumentStatus
20
18
  from julee.domain.models.custom_fields.content_stream import (
21
19
  ContentStream,
22
20
  )
21
+ from julee.domain.models.document import Document, DocumentStatus
22
+ from julee.repositories.minio.document import MinioDocumentRepository
23
+
23
24
  from .fake_client import FakeMinioClient
24
25
 
25
26
 
@@ -428,16 +429,16 @@ class TestMinioDocumentRepositoryMultihash:
428
429
  assert len(multihash_result) > 0
429
430
 
430
431
 
431
- class TestMinioDocumentRepositoryContentString:
432
- """Test content_string functionality."""
432
+ class TestMinioDocumentRepositoryContentBytes:
433
+ """Test content_bytes functionality."""
433
434
 
434
- async def test_save_document_with_content_string(
435
+ async def test_save_document_with_content_bytes(
435
436
  self, repository: MinioDocumentRepository
436
437
  ) -> None:
437
- """Test saving document with content_string (small content)."""
438
+ """Test saving document with content_bytes (small content)."""
438
439
  content = '{"assembled": "document", "data": "test"}'
439
440
 
440
- # Create document with content_string
441
+ # Create document with content_bytes
441
442
  document = Document(
442
443
  document_id="test-doc-content-string",
443
444
  original_filename="assembled.json",
@@ -445,27 +446,27 @@ class TestMinioDocumentRepositoryContentString:
445
446
  size_bytes=100, # Will be updated automatically
446
447
  content_multihash="placeholder", # Will be updated automatically
447
448
  status=DocumentStatus.CAPTURED,
448
- content_string=content,
449
+ content_bytes=content,
449
450
  )
450
451
 
451
- # Act - save should convert content_string to ContentStream
452
+ # Act - save should convert content_bytes to ContentStream
452
453
  await repository.save(document)
453
454
 
454
455
  # Assert document was saved successfully
455
456
  retrieved = await repository.get(document.document_id)
456
457
  assert retrieved is not None
457
458
  assert retrieved.content_multihash != "placeholder" # Hash was calculated
458
- assert retrieved.size_bytes == len(content.encode("utf-8"))
459
+ assert retrieved.size_bytes == len(content)
459
460
 
460
461
  # Verify content can be read
461
462
  assert retrieved.content is not None
462
463
  retrieved_content = retrieved.content.read().decode("utf-8")
463
464
  assert retrieved_content == content
464
465
 
465
- async def test_save_document_with_content_string_unicode(
466
+ async def test_save_document_with_content_bytes_unicode(
466
467
  self, repository: MinioDocumentRepository
467
468
  ) -> None:
468
- """Test saving document with unicode content_string."""
469
+ """Test saving document with unicode content_bytes."""
469
470
  content = '{"title": "测试文档", "emoji": "🚀", "content": "éñ"}'
470
471
 
471
472
  document = Document(
@@ -475,7 +476,7 @@ class TestMinioDocumentRepositoryContentString:
475
476
  size_bytes=100,
476
477
  content_multihash="placeholder",
477
478
  status=DocumentStatus.CAPTURED,
478
- content_string=content,
479
+ content_bytes=content,
479
480
  )
480
481
 
481
482
  await repository.save(document)
@@ -489,12 +490,12 @@ class TestMinioDocumentRepositoryContentString:
489
490
  # Note: Empty content test removed because domain model requires
490
491
  # size_bytes > 0
491
492
 
492
- async def test_save_excludes_content_string_from_metadata(
493
+ async def test_save_excludes_content_bytes_from_metadata(
493
494
  self,
494
495
  repository: MinioDocumentRepository,
495
496
  fake_minio_client: FakeMinioClient,
496
497
  ) -> None:
497
- """Test that content_string is not stored in metadata."""
498
+ """Test that content_bytes is not stored in metadata."""
498
499
  content = '{"test": "data that should not be in metadata"}'
499
500
 
500
501
  document = Document(
@@ -504,7 +505,7 @@ class TestMinioDocumentRepositoryContentString:
504
505
  size_bytes=100,
505
506
  content_multihash="placeholder",
506
507
  status=DocumentStatus.CAPTURED,
507
- content_string=content,
508
+ content_bytes=content,
508
509
  )
509
510
 
510
511
  await repository.save(document)
@@ -520,8 +521,8 @@ class TestMinioDocumentRepositoryContentString:
520
521
 
521
522
  metadata_dict = json.loads(metadata_json)
522
523
 
523
- # Verify content_string is not in stored metadata
524
- assert "content_string" not in metadata_dict
524
+ # Verify content_bytes is not in stored metadata
525
+ assert "content_bytes" not in metadata_dict
525
526
  assert "content" not in metadata_dict
526
527
 
527
528
  # Verify essential fields are still present
@@ -7,9 +7,10 @@ repository that differs from the inherited mixins. Uses the fake client to
7
7
  avoid external dependencies during testing.
8
8
  """
9
9
 
10
- import pytest
11
10
  from datetime import datetime, timezone
12
11
 
12
+ import pytest
13
+
13
14
  from julee.domain.models.policy import (
14
15
  DocumentPolicyValidation,
15
16
  DocumentPolicyValidationStatus,
@@ -17,6 +18,7 @@ from julee.domain.models.policy import (
17
18
  from julee.repositories.minio.document_policy_validation import (
18
19
  MinioDocumentPolicyValidationRepository,
19
20
  )
21
+
20
22
  from .fake_client import FakeMinioClient
21
23
 
22
24
 
@@ -6,16 +6,18 @@ configuration repository implementation, using the fake client to avoid
6
6
  external dependencies during testing.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
 
11
+ import pytest
12
+
12
13
  from julee.domain.models.knowledge_service_config import (
13
14
  KnowledgeServiceConfig,
15
+ ServiceApi,
14
16
  )
15
- from julee.domain.models.knowledge_service_config import ServiceApi
16
17
  from julee.repositories.minio.knowledge_service_config import (
17
18
  MinioKnowledgeServiceConfigRepository,
18
19
  )
20
+
19
21
  from .fake_client import FakeMinioClient
20
22
 
21
23
 
@@ -6,16 +6,17 @@ query repository implementation, using the fake client to avoid external
6
6
  dependencies during testing.
7
7
  """
8
8
 
9
- import pytest
10
-
11
9
  from datetime import datetime, timezone
12
10
 
11
+ import pytest
12
+
13
13
  from julee.domain.models.assembly_specification import (
14
14
  KnowledgeServiceQuery,
15
15
  )
16
16
  from julee.repositories.minio.knowledge_service_query import (
17
17
  MinioKnowledgeServiceQueryRepository,
18
18
  )
19
+
19
20
  from .fake_client import FakeMinioClient
20
21
 
21
22
 
@@ -6,11 +6,13 @@ implementation, using the fake client to avoid external dependencies during
6
6
  testing.
7
7
  """
8
8
 
9
- import pytest
10
9
  from datetime import datetime, timezone
11
10
 
11
+ import pytest
12
+
12
13
  from julee.domain.models.policy import Policy, PolicyStatus
13
14
  from julee.repositories.minio.policy import MinioPolicyRepository
15
+
14
16
  from .fake_client import FakeMinioClient
15
17
 
16
18
 
@@ -10,12 +10,14 @@ The classes follow the naming pattern documented in systemPatterns.org:
10
10
  - Each repository type gets its own activity prefix
11
11
  """
12
12
 
13
- from julee.util.temporal.decorators import temporal_activity_registration
14
13
  from julee.repositories.minio.assembly import MinioAssemblyRepository
15
14
  from julee.repositories.minio.assembly_specification import (
16
15
  MinioAssemblySpecificationRepository,
17
16
  )
18
17
  from julee.repositories.minio.document import MinioDocumentRepository
18
+ from julee.repositories.minio.document_policy_validation import (
19
+ MinioDocumentPolicyValidationRepository,
20
+ )
19
21
  from julee.repositories.minio.knowledge_service_config import (
20
22
  MinioKnowledgeServiceConfigRepository,
21
23
  )
@@ -25,20 +27,18 @@ from julee.repositories.minio.knowledge_service_query import (
25
27
  from julee.repositories.minio.policy import (
26
28
  MinioPolicyRepository,
27
29
  )
28
- from julee.repositories.minio.document_policy_validation import (
29
- MinioDocumentPolicyValidationRepository,
30
- )
31
30
 
32
31
  # Import activity name bases from shared module
33
32
  from julee.repositories.temporal.activity_names import (
34
33
  ASSEMBLY_ACTIVITY_BASE,
35
34
  ASSEMBLY_SPECIFICATION_ACTIVITY_BASE,
36
35
  DOCUMENT_ACTIVITY_BASE,
36
+ DOCUMENT_POLICY_VALIDATION_ACTIVITY_BASE,
37
37
  KNOWLEDGE_SERVICE_CONFIG_ACTIVITY_BASE,
38
38
  KNOWLEDGE_SERVICE_QUERY_ACTIVITY_BASE,
39
39
  POLICY_ACTIVITY_BASE,
40
- DOCUMENT_POLICY_VALIDATION_ACTIVITY_BASE,
41
40
  )
41
+ from julee.util.temporal.decorators import temporal_activity_registration
42
42
 
43
43
 
44
44
  @temporal_activity_registration(ASSEMBLY_ACTIVITY_BASE)
@@ -11,12 +11,14 @@ workflow.execute_activity() with the appropriate activity names, timeouts,
11
11
  and retry policies.
12
12
  """
13
13
 
14
- from julee.util.temporal.decorators import temporal_workflow_proxy
15
14
  from julee.domain.repositories.assembly import AssemblyRepository
16
15
  from julee.domain.repositories.assembly_specification import (
17
16
  AssemblySpecificationRepository,
18
17
  )
19
18
  from julee.domain.repositories.document import DocumentRepository
19
+ from julee.domain.repositories.document_policy_validation import (
20
+ DocumentPolicyValidationRepository,
21
+ )
20
22
  from julee.domain.repositories.knowledge_service_config import (
21
23
  KnowledgeServiceConfigRepository,
22
24
  )
@@ -24,20 +26,18 @@ from julee.domain.repositories.knowledge_service_query import (
24
26
  KnowledgeServiceQueryRepository,
25
27
  )
26
28
  from julee.domain.repositories.policy import PolicyRepository
27
- from julee.domain.repositories.document_policy_validation import (
28
- DocumentPolicyValidationRepository,
29
- )
30
29
 
31
30
  # Import activity name bases from shared module
32
31
  from julee.repositories.temporal.activity_names import (
33
32
  ASSEMBLY_ACTIVITY_BASE,
34
33
  ASSEMBLY_SPECIFICATION_ACTIVITY_BASE,
35
34
  DOCUMENT_ACTIVITY_BASE,
35
+ DOCUMENT_POLICY_VALIDATION_ACTIVITY_BASE,
36
36
  KNOWLEDGE_SERVICE_CONFIG_ACTIVITY_BASE,
37
37
  KNOWLEDGE_SERVICE_QUERY_ACTIVITY_BASE,
38
38
  POLICY_ACTIVITY_BASE,
39
- DOCUMENT_POLICY_VALIDATION_ACTIVITY_BASE,
40
39
  )
40
+ from julee.util.temporal.decorators import temporal_workflow_proxy
41
41
 
42
42
 
43
43
  @temporal_workflow_proxy(
@@ -9,12 +9,11 @@ appropriate implementation based on the service_api configuration.
9
9
  import logging
10
10
 
11
11
  from .knowledge_service import (
12
+ FileRegistrationResult,
12
13
  KnowledgeService,
13
14
  QueryResult,
14
- FileRegistrationResult,
15
15
  )
16
16
 
17
-
18
17
  logger = logging.getLogger(__name__)
19
18
 
20
19
 
@@ -10,23 +10,24 @@ Requirements:
10
10
  - ANTHROPIC_API_KEY environment variable must be set
11
11
  """
12
12
 
13
- import os
14
13
  import logging
14
+ import os
15
15
  import time
16
16
  import uuid
17
- from typing import Optional, List, Dict, Any
18
17
  from datetime import datetime, timezone
18
+ from typing import Any
19
19
 
20
20
  from anthropic import AsyncAnthropic
21
21
 
22
+ from julee.domain.models.document import Document
22
23
  from julee.domain.models.knowledge_service_config import (
23
24
  KnowledgeServiceConfig,
24
25
  )
25
- from julee.domain.models.document import Document
26
+
26
27
  from ..knowledge_service import (
28
+ FileRegistrationResult,
27
29
  KnowledgeService,
28
30
  QueryResult,
29
- FileRegistrationResult,
30
31
  )
31
32
 
32
33
  logger = logging.getLogger(__name__)
@@ -171,9 +172,9 @@ class AnthropicKnowledgeService(KnowledgeService):
171
172
  self,
172
173
  config: KnowledgeServiceConfig,
173
174
  query_text: str,
174
- service_file_ids: Optional[List[str]] = None,
175
- query_metadata: Optional[Dict[str, Any]] = None,
176
- assistant_prompt: Optional[str] = None,
175
+ service_file_ids: list[str] | None = None,
176
+ query_metadata: dict[str, Any] | None = None,
177
+ assistant_prompt: str | None = None,
177
178
  ) -> QueryResult:
178
179
  """Execute a query against Anthropic.
179
180
 
@@ -6,19 +6,20 @@ KnowledgeService protocol, verifying file registration and query
6
6
  execution functionality.
7
7
  """
8
8
 
9
- import pytest
10
- from unittest.mock import AsyncMock, MagicMock, patch
11
- from datetime import datetime, timezone
12
9
  import io
10
+ from datetime import datetime, timezone
11
+ from unittest.mock import AsyncMock, MagicMock, patch
12
+
13
+ import pytest
13
14
 
14
- from julee.domain.models.knowledge_service_config import (
15
- KnowledgeServiceConfig,
16
- )
17
- from julee.domain.models.document import Document, DocumentStatus
18
- from julee.domain.models.knowledge_service_config import ServiceApi
19
15
  from julee.domain.models.custom_fields.content_stream import (
20
16
  ContentStream,
21
17
  )
18
+ from julee.domain.models.document import Document, DocumentStatus
19
+ from julee.domain.models.knowledge_service_config import (
20
+ KnowledgeServiceConfig,
21
+ ServiceApi,
22
+ )
22
23
  from julee.services.knowledge_service.anthropic import (
23
24
  knowledge_service as anthropic_ks,
24
25
  )
@@ -184,7 +185,7 @@ class TestAnthropicKnowledgeService:
184
185
  ) -> None:
185
186
  """Test execute_query handles API errors gracefully."""
186
187
  mock_client = MagicMock()
187
- mock_client.messages.create = AsyncMock(side_effect=Exception("API Error"))
188
+ mock_client.messages.create = AsyncMock(side_effect=RuntimeError("API Error"))
188
189
 
189
190
  with patch(
190
191
  "julee.services.knowledge_service.anthropic.knowledge_service.AsyncAnthropic"
@@ -193,7 +194,7 @@ class TestAnthropicKnowledgeService:
193
194
 
194
195
  service = anthropic_ks.AnthropicKnowledgeService()
195
196
 
196
- with pytest.raises(Exception):
197
+ with pytest.raises(RuntimeError):
197
198
  await service.execute_query(knowledge_service_config, "Test query")
198
199
 
199
200
  @patch.dict("os.environ", {"ANTHROPIC_API_KEY": "test-key"})