techai-webutils 0.0.1__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 (309) hide show
  1. techai_webutils-0.0.1/PKG-INFO +108 -0
  2. techai_webutils-0.0.1/README.md +62 -0
  3. techai_webutils-0.0.1/pyproject.toml +188 -0
  4. techai_webutils-0.0.1/pyproject.toml.orig +269 -0
  5. techai_webutils-0.0.1/src/techai_webutils/__init__.py +5 -0
  6. techai_webutils-0.0.1/src/techai_webutils/clients/__init__.py +8 -0
  7. techai_webutils-0.0.1/src/techai_webutils/clients/audit/__init__.py +9 -0
  8. techai_webutils-0.0.1/src/techai_webutils/clients/audit/builder.py +80 -0
  9. techai_webutils-0.0.1/src/techai_webutils/clients/audit/stub/__init__.py +5 -0
  10. techai_webutils-0.0.1/src/techai_webutils/clients/audit/stub/sink.py +29 -0
  11. techai_webutils-0.0.1/src/techai_webutils/clients/cache/__init__.py +35 -0
  12. techai_webutils-0.0.1/src/techai_webutils/clients/cache/builder.py +88 -0
  13. techai_webutils-0.0.1/src/techai_webutils/clients/cache/decorators.py +285 -0
  14. techai_webutils-0.0.1/src/techai_webutils/clients/cache/envelope.py +51 -0
  15. techai_webutils-0.0.1/src/techai_webutils/clients/cache/local/__init__.py +5 -0
  16. techai_webutils-0.0.1/src/techai_webutils/clients/cache/local/cache.py +70 -0
  17. techai_webutils-0.0.1/src/techai_webutils/clients/cache/null/__init__.py +5 -0
  18. techai_webutils-0.0.1/src/techai_webutils/clients/cache/null/cache.py +31 -0
  19. techai_webutils-0.0.1/src/techai_webutils/clients/cache/redis/__init__.py +6 -0
  20. techai_webutils-0.0.1/src/techai_webutils/clients/cache/redis/cache.py +95 -0
  21. techai_webutils-0.0.1/src/techai_webutils/clients/cache/types.py +27 -0
  22. techai_webutils-0.0.1/src/techai_webutils/clients/chunking/__init__.py +13 -0
  23. techai_webutils-0.0.1/src/techai_webutils/clients/chunking/factory.py +49 -0
  24. techai_webutils-0.0.1/src/techai_webutils/clients/chunking/fixed/__init__.py +5 -0
  25. techai_webutils-0.0.1/src/techai_webutils/clients/chunking/fixed/chunker.py +71 -0
  26. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/__init__.py +9 -0
  27. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/ai_enricher.py +472 -0
  28. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/event_stack.py +104 -0
  29. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/job_stack.py +77 -0
  30. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/metrics_proxy.py +130 -0
  31. techai_webutils-0.0.1/src/techai_webutils/clients/decorators/proxy.py +481 -0
  32. techai_webutils-0.0.1/src/techai_webutils/clients/email/__init__.py +13 -0
  33. techai_webutils-0.0.1/src/techai_webutils/clients/email/builder.py +73 -0
  34. techai_webutils-0.0.1/src/techai_webutils/clients/email/noop/__init__.py +5 -0
  35. techai_webutils-0.0.1/src/techai_webutils/clients/email/noop/provider.py +19 -0
  36. techai_webutils-0.0.1/src/techai_webutils/clients/email/ses/__init__.py +5 -0
  37. techai_webutils-0.0.1/src/techai_webutils/clients/email/ses/provider.py +33 -0
  38. techai_webutils-0.0.1/src/techai_webutils/clients/email/smtp/__init__.py +5 -0
  39. techai_webutils-0.0.1/src/techai_webutils/clients/email/smtp/provider.py +27 -0
  40. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/__init__.py +13 -0
  41. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/builder.py +70 -0
  42. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/ollama/__init__.py +5 -0
  43. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/ollama/provider.py +72 -0
  44. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/stub/__init__.py +5 -0
  45. techai_webutils-0.0.1/src/techai_webutils/clients/embedding/stub/provider.py +57 -0
  46. techai_webutils-0.0.1/src/techai_webutils/clients/facts/__init__.py +9 -0
  47. techai_webutils-0.0.1/src/techai_webutils/clients/facts/builder.py +91 -0
  48. techai_webutils-0.0.1/src/techai_webutils/clients/facts/messaging/__init__.py +5 -0
  49. techai_webutils-0.0.1/src/techai_webutils/clients/facts/messaging/publisher.py +189 -0
  50. techai_webutils-0.0.1/src/techai_webutils/clients/facts/stub/__init__.py +5 -0
  51. techai_webutils-0.0.1/src/techai_webutils/clients/facts/stub/publisher.py +20 -0
  52. techai_webutils-0.0.1/src/techai_webutils/clients/jobs/__init__.py +23 -0
  53. techai_webutils-0.0.1/src/techai_webutils/clients/jobs/builder.py +30 -0
  54. techai_webutils-0.0.1/src/techai_webutils/clients/jobs/config.py +28 -0
  55. techai_webutils-0.0.1/src/techai_webutils/clients/jobs/memory/__init__.py +18 -0
  56. techai_webutils-0.0.1/src/techai_webutils/clients/jobs/memory/backend.py +92 -0
  57. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/__init__.py +6 -0
  58. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/bedrock/__init__.py +7 -0
  59. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/bedrock/ingestor.py +212 -0
  60. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/builder.py +58 -0
  61. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/decorators.py +271 -0
  62. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/mapping.py +73 -0
  63. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/noop/__init__.py +5 -0
  64. techai_webutils-0.0.1/src/techai_webutils/clients/kb_ingestion/noop/ingestor.py +68 -0
  65. techai_webutils-0.0.1/src/techai_webutils/clients/llm/__init__.py +5 -0
  66. techai_webutils-0.0.1/src/techai_webutils/clients/llm/bedrock/__init__.py +5 -0
  67. techai_webutils-0.0.1/src/techai_webutils/clients/llm/bedrock/provider.py +250 -0
  68. techai_webutils-0.0.1/src/techai_webutils/clients/llm/builder.py +94 -0
  69. techai_webutils-0.0.1/src/techai_webutils/clients/llm/decorators.py +188 -0
  70. techai_webutils-0.0.1/src/techai_webutils/clients/llm/ollama/__init__.py +5 -0
  71. techai_webutils-0.0.1/src/techai_webutils/clients/llm/ollama/provider.py +209 -0
  72. techai_webutils-0.0.1/src/techai_webutils/clients/llm/stub/__init__.py +5 -0
  73. techai_webutils-0.0.1/src/techai_webutils/clients/llm/stub/provider.py +103 -0
  74. techai_webutils-0.0.1/src/techai_webutils/clients/lock/__init__.py +28 -0
  75. techai_webutils-0.0.1/src/techai_webutils/clients/lock/builder.py +92 -0
  76. techai_webutils-0.0.1/src/techai_webutils/clients/lock/memory/__init__.py +5 -0
  77. techai_webutils-0.0.1/src/techai_webutils/clients/lock/memory/lock.py +46 -0
  78. techai_webutils-0.0.1/src/techai_webutils/clients/lock/postgres/__init__.py +5 -0
  79. techai_webutils-0.0.1/src/techai_webutils/clients/lock/postgres/lock.py +216 -0
  80. techai_webutils-0.0.1/src/techai_webutils/clients/lock/runner.py +39 -0
  81. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/__init__.py +23 -0
  82. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/builder.py +72 -0
  83. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/config.py +49 -0
  84. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/memory/__init__.py +7 -0
  85. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/memory/broker.py +31 -0
  86. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/memory/publisher.py +40 -0
  87. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/memory/subscriber.py +73 -0
  88. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/sqs/__init__.py +11 -0
  89. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/sqs/sqs_publisher.py +97 -0
  90. techai_webutils-0.0.1/src/techai_webutils/clients/messaging/sqs/sqs_subscriber.py +136 -0
  91. techai_webutils-0.0.1/src/techai_webutils/clients/metadata/__init__.py +14 -0
  92. techai_webutils-0.0.1/src/techai_webutils/clients/metadata/factory.py +49 -0
  93. techai_webutils-0.0.1/src/techai_webutils/clients/metadata/langdetect/__init__.py +13 -0
  94. techai_webutils-0.0.1/src/techai_webutils/clients/metadata/langdetect/extractor.py +70 -0
  95. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/__init__.py +14 -0
  96. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/factory.py +61 -0
  97. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/isolated/__init__.py +23 -0
  98. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/isolated/detect.py +109 -0
  99. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/isolated/isolated.py +274 -0
  100. techai_webutils-0.0.1/src/techai_webutils/clients/parsing/isolated/markitdown_parser.py +243 -0
  101. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/__init__.py +37 -0
  102. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/bedrock/__init__.py +17 -0
  103. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/bedrock/engine.py +230 -0
  104. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/builder.py +250 -0
  105. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/filtering.py +158 -0
  106. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/stub/__init__.py +5 -0
  107. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/stub/engine.py +42 -0
  108. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/vector/__init__.py +5 -0
  109. techai_webutils-0.0.1/src/techai_webutils/clients/retrieval/vector/engine.py +99 -0
  110. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/__init__.py +14 -0
  111. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/builder.py +43 -0
  112. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/__init__.py +5 -0
  113. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/client.py +51 -0
  114. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/errors.py +92 -0
  115. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/__init__.py +35 -0
  116. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/auth.py +125 -0
  117. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/builder.py +81 -0
  118. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/circuit_breaker.py +70 -0
  119. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/logging.py +57 -0
  120. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/metrics.py +42 -0
  121. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/retry.py +63 -0
  122. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/server_builder.py +612 -0
  123. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/timeout.py +56 -0
  124. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/tracing.py +41 -0
  125. techai_webutils-0.0.1/src/techai_webutils/clients/rpc/grpc/interceptors/tracing_server.py +159 -0
  126. techai_webutils-0.0.1/src/techai_webutils/clients/splitting/__init__.py +13 -0
  127. techai_webutils-0.0.1/src/techai_webutils/clients/splitting/factory.py +48 -0
  128. techai_webutils-0.0.1/src/techai_webutils/clients/splitting/kb_unit/__init__.py +8 -0
  129. techai_webutils-0.0.1/src/techai_webutils/clients/splitting/kb_unit/splitter.py +156 -0
  130. techai_webutils-0.0.1/src/techai_webutils/clients/storage/__init__.py +21 -0
  131. techai_webutils-0.0.1/src/techai_webutils/clients/storage/builder.py +55 -0
  132. techai_webutils-0.0.1/src/techai_webutils/clients/storage/config.py +46 -0
  133. techai_webutils-0.0.1/src/techai_webutils/clients/storage/memory/__init__.py +5 -0
  134. techai_webutils-0.0.1/src/techai_webutils/clients/storage/memory/client.py +90 -0
  135. techai_webutils-0.0.1/src/techai_webutils/clients/storage/s3/__init__.py +10 -0
  136. techai_webutils-0.0.1/src/techai_webutils/clients/storage/s3/s3_client.py +242 -0
  137. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/__init__.py +17 -0
  138. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/builder.py +91 -0
  139. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/cost.py +69 -0
  140. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/redis/__init__.py +5 -0
  141. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/redis/ledger.py +321 -0
  142. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/stub/__init__.py +5 -0
  143. techai_webutils-0.0.1/src/techai_webutils/clients/token_ledger/stub/ledger.py +38 -0
  144. techai_webutils-0.0.1/src/techai_webutils/clients/transport/__init__.py +5 -0
  145. techai_webutils-0.0.1/src/techai_webutils/clients/transport/grpc/__init__.py +9 -0
  146. techai_webutils-0.0.1/src/techai_webutils/clients/transport/grpc/server.py +180 -0
  147. techai_webutils-0.0.1/src/techai_webutils/clients/vector/__init__.py +13 -0
  148. techai_webutils-0.0.1/src/techai_webutils/clients/vector/builder.py +66 -0
  149. techai_webutils-0.0.1/src/techai_webutils/clients/vector/composition.py +78 -0
  150. techai_webutils-0.0.1/src/techai_webutils/clients/vector/qdrant/__init__.py +5 -0
  151. techai_webutils-0.0.1/src/techai_webutils/clients/vector/qdrant/store.py +216 -0
  152. techai_webutils-0.0.1/src/techai_webutils/clients/vector/stub/__init__.py +5 -0
  153. techai_webutils-0.0.1/src/techai_webutils/clients/vector/stub/store.py +112 -0
  154. techai_webutils-0.0.1/src/techai_webutils/clients/vector_kb/__init__.py +15 -0
  155. techai_webutils-0.0.1/src/techai_webutils/clients/vector_kb/builder.py +61 -0
  156. techai_webutils-0.0.1/src/techai_webutils/clients/vector_kb/vector/__init__.py +5 -0
  157. techai_webutils-0.0.1/src/techai_webutils/clients/vector_kb/vector/knowledge_base.py +190 -0
  158. techai_webutils-0.0.1/src/techai_webutils/controllers/__init__.py +26 -0
  159. techai_webutils-0.0.1/src/techai_webutils/controllers/adapt.py +72 -0
  160. techai_webutils-0.0.1/src/techai_webutils/controllers/base.py +115 -0
  161. techai_webutils-0.0.1/src/techai_webutils/controllers/decorators.py +255 -0
  162. techai_webutils-0.0.1/src/techai_webutils/core/__init__.py +1 -0
  163. techai_webutils-0.0.1/src/techai_webutils/core/domain/__init__.py +20 -0
  164. techai_webutils-0.0.1/src/techai_webutils/core/domain/metadata.py +28 -0
  165. techai_webutils-0.0.1/src/techai_webutils/core/domain/parser.py +92 -0
  166. techai_webutils-0.0.1/src/techai_webutils/core/domain/splitter.py +39 -0
  167. techai_webutils-0.0.1/src/techai_webutils/core/domain_types/__init__.py +25 -0
  168. techai_webutils-0.0.1/src/techai_webutils/core/domain_types/types.py +136 -0
  169. techai_webutils-0.0.1/src/techai_webutils/core/errors/__init__.py +39 -0
  170. techai_webutils-0.0.1/src/techai_webutils/core/errors/errors.py +276 -0
  171. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/__init__.py +187 -0
  172. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/adaptive_throttler.py +31 -0
  173. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/audit.py +84 -0
  174. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/bulkhead.py +32 -0
  175. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/byte_cache.py +35 -0
  176. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/cache.py +54 -0
  177. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/chunker.py +21 -0
  178. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/circuit_breaker.py +41 -0
  179. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/config_loader.py +41 -0
  180. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/crud_service.py +75 -0
  181. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/dedup.py +26 -0
  182. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/dlq.py +41 -0
  183. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/document.py +64 -0
  184. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/email.py +19 -0
  185. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/embedding.py +38 -0
  186. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/execution.py +291 -0
  187. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/fact_publisher.py +26 -0
  188. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/hedger.py +29 -0
  189. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/jobs.py +82 -0
  190. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/kb_ingestion.py +156 -0
  191. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/knowledge_base.py +82 -0
  192. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/leader.py +23 -0
  193. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/lifecycle.py +75 -0
  194. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/llm.py +124 -0
  195. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/lock.py +56 -0
  196. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/logger.py +47 -0
  197. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/messaging.py +69 -0
  198. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/metadata.py +22 -0
  199. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/metrics.py +83 -0
  200. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/op_service.py +25 -0
  201. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/parser.py +35 -0
  202. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/pipeline.py +47 -0
  203. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/rate_limiter.py +22 -0
  204. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/repository.py +85 -0
  205. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/retrier.py +25 -0
  206. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/retrieval.py +166 -0
  207. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/service.py +55 -0
  208. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/splitter.py +23 -0
  209. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/storage.py +90 -0
  210. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/store.py +55 -0
  211. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/token_ledger.py +136 -0
  212. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/tracer.py +55 -0
  213. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/vector_store.py +94 -0
  214. techai_webutils-0.0.1/src/techai_webutils/core/interfaces/workflow.py +48 -0
  215. techai_webutils-0.0.1/src/techai_webutils/core/types/__init__.py +5 -0
  216. techai_webutils-0.0.1/src/techai_webutils/core/types/aws_client.py +24 -0
  217. techai_webutils-0.0.1/src/techai_webutils/core/types/fact.py +98 -0
  218. techai_webutils-0.0.1/src/techai_webutils/execution/__init__.py +49 -0
  219. techai_webutils-0.0.1/src/techai_webutils/execution/engine/__init__.py +5 -0
  220. techai_webutils-0.0.1/src/techai_webutils/execution/engine/fan_out.py +111 -0
  221. techai_webutils-0.0.1/src/techai_webutils/execution/engine/run.py +63 -0
  222. techai_webutils-0.0.1/src/techai_webutils/execution/executor/__init__.py +36 -0
  223. techai_webutils-0.0.1/src/techai_webutils/execution/executor/asyncio_executor.py +43 -0
  224. techai_webutils-0.0.1/src/techai_webutils/execution/executor/factory.py +93 -0
  225. techai_webutils-0.0.1/src/techai_webutils/execution/executor/pooled.py +155 -0
  226. techai_webutils-0.0.1/src/techai_webutils/execution/executor/ray_executor.py +62 -0
  227. techai_webutils-0.0.1/src/techai_webutils/execution/executor/ray_runtime.py +45 -0
  228. techai_webutils-0.0.1/src/techai_webutils/execution/executor/real_ray_pool.py +140 -0
  229. techai_webutils-0.0.1/src/techai_webutils/execution/executor/real_ray_runtime.py +124 -0
  230. techai_webutils-0.0.1/src/techai_webutils/execution/executor/resilient_ray_runtime.py +99 -0
  231. techai_webutils-0.0.1/src/techai_webutils/execution/gate/__init__.py +19 -0
  232. techai_webutils-0.0.1/src/techai_webutils/execution/gate/gate.py +151 -0
  233. techai_webutils-0.0.1/src/techai_webutils/execution/job/__init__.py +5 -0
  234. techai_webutils-0.0.1/src/techai_webutils/execution/job/conditional.py +47 -0
  235. techai_webutils-0.0.1/src/techai_webutils/execution/job/decorators/__init__.py +5 -0
  236. techai_webutils-0.0.1/src/techai_webutils/execution/job/decorators/builder.py +216 -0
  237. techai_webutils-0.0.1/src/techai_webutils/execution/job/job.py +216 -0
  238. techai_webutils-0.0.1/src/techai_webutils/foundation/__init__.py +1 -0
  239. techai_webutils-0.0.1/src/techai_webutils/foundation/config/__init__.py +35 -0
  240. techai_webutils-0.0.1/src/techai_webutils/foundation/config/bridge.py +289 -0
  241. techai_webutils-0.0.1/src/techai_webutils/foundation/config/config_loader.py +83 -0
  242. techai_webutils-0.0.1/src/techai_webutils/foundation/config/loader.py +121 -0
  243. techai_webutils-0.0.1/src/techai_webutils/foundation/config/settings.py +191 -0
  244. techai_webutils-0.0.1/src/techai_webutils/foundation/decorator.py +333 -0
  245. techai_webutils-0.0.1/src/techai_webutils/foundation/errors/__init__.py +1 -0
  246. techai_webutils-0.0.1/src/techai_webutils/foundation/errors/errors.py +142 -0
  247. techai_webutils-0.0.1/src/techai_webutils/foundation/lifecycle.py +70 -0
  248. techai_webutils-0.0.1/src/techai_webutils/foundation/logger/__init__.py +33 -0
  249. techai_webutils-0.0.1/src/techai_webutils/foundation/logger/builder.py +74 -0
  250. techai_webutils-0.0.1/src/techai_webutils/foundation/logger/logger.py +315 -0
  251. techai_webutils-0.0.1/src/techai_webutils/foundation/logger/redact.py +29 -0
  252. techai_webutils-0.0.1/src/techai_webutils/foundation/logger/stdlib_logger.py +132 -0
  253. techai_webutils-0.0.1/src/techai_webutils/foundation/metrics/__init__.py +31 -0
  254. techai_webutils-0.0.1/src/techai_webutils/foundation/metrics/builder.py +71 -0
  255. techai_webutils-0.0.1/src/techai_webutils/foundation/metrics/execution_observer.py +92 -0
  256. techai_webutils-0.0.1/src/techai_webutils/foundation/metrics/metrics.py +285 -0
  257. techai_webutils-0.0.1/src/techai_webutils/foundation/metrics/null_metrics.py +72 -0
  258. techai_webutils-0.0.1/src/techai_webutils/foundation/middleware/__init__.py +19 -0
  259. techai_webutils-0.0.1/src/techai_webutils/foundation/middleware/chain.py +35 -0
  260. techai_webutils-0.0.1/src/techai_webutils/foundation/middleware/http_observability.py +209 -0
  261. techai_webutils-0.0.1/src/techai_webutils/foundation/middleware/request_id.py +61 -0
  262. techai_webutils-0.0.1/src/techai_webutils/foundation/observability.py +69 -0
  263. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/__init__.py +27 -0
  264. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/adaptive_throttler.py +91 -0
  265. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/async_circuit_breaker.py +97 -0
  266. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/async_retry.py +105 -0
  267. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/aws_boundary.py +62 -0
  268. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/budget.py +59 -0
  269. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/bulkhead.py +198 -0
  270. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/circuit_breaker.py +142 -0
  271. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/classify.py +150 -0
  272. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/dedup.py +36 -0
  273. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/dlq.py +67 -0
  274. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/grpc_boundary.py +119 -0
  275. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/hedge.py +96 -0
  276. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/leader.py +22 -0
  277. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/per_key_rate_limiter.py +74 -0
  278. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/rate_limiter.py +64 -0
  279. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/retry.py +72 -0
  280. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/sqs_dlq.py +89 -0
  281. techai_webutils-0.0.1/src/techai_webutils/foundation/resilience/timeout.py +35 -0
  282. techai_webutils-0.0.1/src/techai_webutils/foundation/tracer/__init__.py +39 -0
  283. techai_webutils-0.0.1/src/techai_webutils/foundation/tracer/builder.py +81 -0
  284. techai_webutils-0.0.1/src/techai_webutils/foundation/tracer/conversation.py +98 -0
  285. techai_webutils-0.0.1/src/techai_webutils/foundation/tracer/null_tracer.py +42 -0
  286. techai_webutils-0.0.1/src/techai_webutils/foundation/tracer/tracer.py +160 -0
  287. techai_webutils-0.0.1/src/techai_webutils/pipelines/__init__.py +24 -0
  288. techai_webutils-0.0.1/src/techai_webutils/pipelines/base.py +89 -0
  289. techai_webutils-0.0.1/src/techai_webutils/pipelines/citations.py +57 -0
  290. techai_webutils-0.0.1/src/techai_webutils/pipelines/decorators.py +324 -0
  291. techai_webutils-0.0.1/src/techai_webutils/pipelines/generator.py +73 -0
  292. techai_webutils-0.0.1/src/techai_webutils/pipelines/rewriter.py +55 -0
  293. techai_webutils-0.0.1/src/techai_webutils/py.typed +0 -0
  294. techai_webutils-0.0.1/src/techai_webutils/repos/__init__.py +21 -0
  295. techai_webutils-0.0.1/src/techai_webutils/repos/cursor.py +51 -0
  296. techai_webutils-0.0.1/src/techai_webutils/repos/decorators/__init__.py +5 -0
  297. techai_webutils-0.0.1/src/techai_webutils/repos/decorators/builder.py +539 -0
  298. techai_webutils-0.0.1/src/techai_webutils/repos/errors/__init__.py +5 -0
  299. techai_webutils-0.0.1/src/techai_webutils/repos/errors/mapper.py +68 -0
  300. techai_webutils-0.0.1/src/techai_webutils/repos/repository.py +54 -0
  301. techai_webutils-0.0.1/src/techai_webutils/services/__init__.py +11 -0
  302. techai_webutils-0.0.1/src/techai_webutils/services/base.py +9 -0
  303. techai_webutils-0.0.1/src/techai_webutils/services/crud_service.py +50 -0
  304. techai_webutils-0.0.1/src/techai_webutils/services/decorators/__init__.py +5 -0
  305. techai_webutils-0.0.1/src/techai_webutils/services/decorators/builder.py +332 -0
  306. techai_webutils-0.0.1/src/techai_webutils/services/op_builder.py +226 -0
  307. techai_webutils-0.0.1/src/techai_webutils/workflows/__init__.py +24 -0
  308. techai_webutils-0.0.1/src/techai_webutils/workflows/base.py +90 -0
  309. techai_webutils-0.0.1/src/techai_webutils/workflows/decorators.py +338 -0
@@ -0,0 +1,108 @@
1
+ Metadata-Version: 2.3
2
+ Name: techai-webutils
3
+ Version: 0.0.1
4
+ Summary: techai-webutils
5
+ Author: Tech AI at Georgia Institute of Technology
6
+ License: MIT
7
+ Classifier: Operating System :: MacOS
8
+ Classifier: Operating System :: Microsoft :: Windows
9
+ Classifier: Operating System :: POSIX :: Linux
10
+ Classifier: Programming Language :: Python
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Requires-Dist: aiobotocore>=3.5.0
13
+ Requires-Dist: aiosmtplib>=3.0.0
14
+ Requires-Dist: fastapi>=0.136.0
15
+ Requires-Dist: grpcio>=1.80.0
16
+ Requires-Dist: grpcio-health-checking>=1.80.0
17
+ Requires-Dist: grpcio-reflection>=1.80.0
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: opentelemetry-api>=1.41.0
20
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.41.0
21
+ Requires-Dist: opentelemetry-sdk>=1.41.0
22
+ Requires-Dist: prometheus-client>=0.25.0
23
+ Requires-Dist: pydantic>=2.13.3
24
+ Requires-Dist: pydantic-settings>=2.14.1
25
+ Requires-Dist: qdrant-client>=1.12.0
26
+ Requires-Dist: pyyaml>=6.0.3
27
+ Requires-Dist: redis>=7.4.0
28
+ Requires-Dist: structlog>=25.5.0
29
+ Requires-Dist: tenacity>=9.1.4
30
+ Requires-Dist: uvicorn>=0.48.0
31
+ Requires-Dist: protovalidate>=2.0.0,<3
32
+ Requires-Dist: langdetect>=1.0.9 ; extra == 'langdetect'
33
+ Requires-Dist: markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.6 ; extra == 'parsing'
34
+ Requires-Dist: pymupdf>=1.28.0 ; extra == 'parsing'
35
+ Requires-Dist: asyncpg>=0.30.0 ; extra == 'postgres'
36
+ Requires-Dist: ray==2.56.1 ; extra == 'ray'
37
+ Requires-Python: >=3.12
38
+ Project-URL: Homepage, https://github.com/gt-tech-ai/knowledge-engine-toolkit
39
+ Project-URL: Documentation, https://github.com/gt-tech-ai/knowledge-engine-toolkit
40
+ Project-URL: Repository, https://github.com/gt-tech-ai/knowledge-engine-toolkit
41
+ Provides-Extra: langdetect
42
+ Provides-Extra: parsing
43
+ Provides-Extra: postgres
44
+ Provides-Extra: ray
45
+ Description-Content-Type: text/markdown
46
+
47
+ # techai-webutils
48
+
49
+ **Development:**
50
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
51
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
52
+ [![pytest](https://img.shields.io/badge/pytest-enabled-brightgreen)](https://docs.pytest.org/)
53
+ [![CI](https://github.com/gt-tech-ai/knowledge-engine-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/gt-tech-ai/knowledge-engine-toolkit/actions/workflows/ci.yml)
54
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/gt-tech-ai/knowledge-engine-toolkit?color=dark-green)](https://github.com/gt-tech-ai/knowledge-engine-toolkit/commits/main/)
55
+
56
+ <!-- Content above this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
57
+
58
+ ## Overview
59
+
60
+ `techai_webutils` is the Python mirror of the knowledge-engine-toolkit's Go substrate. It follows the same
61
+ layers (`core` → `foundation` (+ `execution`) → `clients` → `repos` → `services` → `pipelines` →
62
+ `workflows` → `controllers`) and the same rules, described in the repository's
63
+ [ARCHITECTURE.md](https://github.com/gt-tech-ai/knowledge-engine-toolkit/blob/main/ARCHITECTURE.md). Every
64
+ swappable component is a `Kind` + a config + a `new_<type>_from_config` factory, so switching a
65
+ backend (memory → S3, stub → Bedrock, asyncio → Ray) is a configuration change.
66
+
67
+ ### How to use `techai_webutils`
68
+
69
+ ```bash
70
+ uv add techai-webutils # or: pip install techai-webutils
71
+ uv add "techai-webutils[postgres]" # optional backends: ray, postgres, parsing, langdetect
72
+ ```
73
+
74
+ Build a component from its config at your composition root and inject it:
75
+
76
+ ```python
77
+ from techai_webutils.clients.storage import (
78
+ S3Config,
79
+ StorageConfig,
80
+ StorageKind,
81
+ new_storage_from_config,
82
+ )
83
+
84
+ config = StorageConfig(
85
+ kind=StorageKind.MEMORY, # StorageKind.S3 in a deployment: same code, different config
86
+ s3=S3Config(endpoint="", bucket="documents", region="us-east-1"),
87
+ )
88
+ storage = new_storage_from_config(config)
89
+ ```
90
+
91
+ The base install already includes the AWS, gRPC, FastAPI, Qdrant, Redis and OpenTelemetry clients.
92
+ The `ray`, `postgres`, `parsing` and `langdetect` extras are imported only when their backend is
93
+ selected, so a service installs just the extras its configuration uses.
94
+
95
+ Load layered YAML config (`base.yaml` → `{env}.yaml` → `secrets.yaml`) under an env prefix of
96
+ your own, and give your settings class the same `env_prefix`:
97
+
98
+ ```python
99
+ from techai_webutils.foundation.config import initialize_config
100
+
101
+ initialize_config("config", env_prefix="MYAPP")
102
+ ```
103
+
104
+ Set a prefix: without one, config keys are exported under bare names (`AWS_REGION`, `DEBUG`) that
105
+ collide with ambient variables, such as the service links Kubernetes injects
106
+ (`REDIS_PORT=tcp://…`).
107
+
108
+ <!-- Content below this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
@@ -0,0 +1,62 @@
1
+ # techai-webutils
2
+
3
+ **Development:**
4
+ [![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
5
+ [![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
6
+ [![pytest](https://img.shields.io/badge/pytest-enabled-brightgreen)](https://docs.pytest.org/)
7
+ [![CI](https://github.com/gt-tech-ai/knowledge-engine-toolkit/actions/workflows/ci.yml/badge.svg)](https://github.com/gt-tech-ai/knowledge-engine-toolkit/actions/workflows/ci.yml)
8
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/gt-tech-ai/knowledge-engine-toolkit?color=dark-green)](https://github.com/gt-tech-ai/knowledge-engine-toolkit/commits/main/)
9
+
10
+ <!-- Content above this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
11
+
12
+ ## Overview
13
+
14
+ `techai_webutils` is the Python mirror of the knowledge-engine-toolkit's Go substrate. It follows the same
15
+ layers (`core` → `foundation` (+ `execution`) → `clients` → `repos` → `services` → `pipelines` →
16
+ `workflows` → `controllers`) and the same rules, described in the repository's
17
+ [ARCHITECTURE.md](https://github.com/gt-tech-ai/knowledge-engine-toolkit/blob/main/ARCHITECTURE.md). Every
18
+ swappable component is a `Kind` + a config + a `new_<type>_from_config` factory, so switching a
19
+ backend (memory → S3, stub → Bedrock, asyncio → Ray) is a configuration change.
20
+
21
+ ### How to use `techai_webutils`
22
+
23
+ ```bash
24
+ uv add techai-webutils # or: pip install techai-webutils
25
+ uv add "techai-webutils[postgres]" # optional backends: ray, postgres, parsing, langdetect
26
+ ```
27
+
28
+ Build a component from its config at your composition root and inject it:
29
+
30
+ ```python
31
+ from techai_webutils.clients.storage import (
32
+ S3Config,
33
+ StorageConfig,
34
+ StorageKind,
35
+ new_storage_from_config,
36
+ )
37
+
38
+ config = StorageConfig(
39
+ kind=StorageKind.MEMORY, # StorageKind.S3 in a deployment: same code, different config
40
+ s3=S3Config(endpoint="", bucket="documents", region="us-east-1"),
41
+ )
42
+ storage = new_storage_from_config(config)
43
+ ```
44
+
45
+ The base install already includes the AWS, gRPC, FastAPI, Qdrant, Redis and OpenTelemetry clients.
46
+ The `ray`, `postgres`, `parsing` and `langdetect` extras are imported only when their backend is
47
+ selected, so a service installs just the extras its configuration uses.
48
+
49
+ Load layered YAML config (`base.yaml` → `{env}.yaml` → `secrets.yaml`) under an env prefix of
50
+ your own, and give your settings class the same `env_prefix`:
51
+
52
+ ```python
53
+ from techai_webutils.foundation.config import initialize_config
54
+
55
+ initialize_config("config", env_prefix="MYAPP")
56
+ ```
57
+
58
+ Set a prefix: without one, config keys are exported under bare names (`AWS_REGION`, `DEBUG`) that
59
+ collide with ambient variables, such as the service links Kubernetes injects
60
+ (`REDIS_PORT=tcp://…`).
61
+
62
+ <!-- Content below this delimiter will be copied to the generated README.md file. DO NOT REMOVE THIS COMMENT, as it will cause regeneration to fail. -->
@@ -0,0 +1,188 @@
1
+ [project]
2
+ name = "techai-webutils"
3
+ version = "0.0.1"
4
+ description = "techai-webutils"
5
+ readme = "README.md"
6
+ requires-python = ">= 3.12"
7
+ dependencies = [
8
+ "aiobotocore>=3.5.0",
9
+ "aiosmtplib>=3.0.0",
10
+ "fastapi>=0.136.0",
11
+ "grpcio>=1.80.0",
12
+ "grpcio-health-checking>=1.80.0",
13
+ "grpcio-reflection>=1.80.0",
14
+ "httpx>=0.28.1",
15
+ "opentelemetry-api>=1.41.0",
16
+ "opentelemetry-exporter-otlp-proto-grpc>=1.41.0",
17
+ "opentelemetry-sdk>=1.41.0",
18
+ "prometheus-client>=0.25.0",
19
+ "pydantic>=2.13.3",
20
+ "pydantic-settings>=2.14.1",
21
+ "qdrant-client>=1.12.0",
22
+ "pyyaml>=6.0.3",
23
+ "redis>=7.4.0",
24
+ "structlog>=25.5.0",
25
+ "tenacity>=9.1.4",
26
+ "uvicorn>=0.48.0",
27
+ "protovalidate>=2.0.0,<3",
28
+ ]
29
+ classifiers = [
30
+ "Operating System :: MacOS",
31
+ "Operating System :: Microsoft :: Windows",
32
+ "Operating System :: POSIX :: Linux",
33
+ "Programming Language :: Python",
34
+ "Programming Language :: Python :: 3.12",
35
+ ]
36
+
37
+ [[project.authors]]
38
+ name = "Tech AI at Georgia Institute of Technology"
39
+
40
+ [project.optional-dependencies]
41
+ ray = ["ray==2.56.1"]
42
+ postgres = ["asyncpg>=0.30.0"]
43
+ parsing = [
44
+ "markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.6",
45
+ "pymupdf>=1.28.0",
46
+ ]
47
+ langdetect = ["langdetect>=1.0.9"]
48
+
49
+ [project.license]
50
+ text = "MIT"
51
+
52
+ [project.urls]
53
+ Homepage = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
54
+ Documentation = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
55
+ Repository = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
56
+
57
+ [build-system]
58
+ requires = ["uv_build>=0.11.15,<0.12.0"]
59
+ build-backend = "uv_build"
60
+
61
+ [dependency-groups]
62
+ dev = [
63
+ "autogitsemver>=0.9.13",
64
+ "pytest>=9.0.3",
65
+ "pytest-asyncio>=1.0.0",
66
+ "pytest-cov>=7.1.0",
67
+ "ray==2.56.1",
68
+ "ruff==0.16.9",
69
+ "basedpyright==1.40.1",
70
+ "asyncpg>=0.30.0",
71
+ "markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.6",
72
+ "pymupdf>=1.28.0",
73
+ "langdetect>=1.0.9",
74
+ "testcontainers[postgres,redis]>=4.14.2",
75
+ "ty>=0.0.38",
76
+ "hypothesis>=6.168.5",
77
+ "asyncpg-stubs==0.31.3",
78
+ "types-aiobotocore-lite[s3,sesv2,sqs]==3.9.0",
79
+ ]
80
+
81
+ [tool.pytest.ini_options]
82
+ addopts = "--verbose -vv --capture=no --strict-markers --cov=techai_webutils --cov-report html --cov-report term --cov-report xml:coverage.xml --cov-fail-under=90.0"
83
+ markers = [
84
+ "integration: real-dependency tests via testcontainers (Docker required); deselected in the unit run",
85
+ "slow: slow tests, deselected with --fast",
86
+ ]
87
+
88
+ [tool.coverage.run]
89
+ relative_files = true
90
+ data_file = "coverage_unit.dat"
91
+
92
+ [tool.coverage.report]
93
+ omit = [
94
+ "*/clients/transport/grpc/server.py",
95
+ "*/clients/rpc/grpc/interceptors/tracing.py",
96
+ "*/clients/rpc/grpc/interceptors/tracing_server.py",
97
+ "*/clients/messaging/sqs/sqs_publisher.py",
98
+ "*/clients/messaging/sqs/sqs_subscriber.py",
99
+ "*/foundation/resilience/sqs_dlq.py",
100
+ "*/clients/storage/s3/s3_client.py",
101
+ "*/clients/llm/bedrock/*.py",
102
+ "*/clients/retrieval/bedrock/*.py",
103
+ "*/clients/kb_ingestion/bedrock/*.py",
104
+ "*/clients/email/ses/provider.py",
105
+ "*/clients/email/smtp/provider.py",
106
+ "*/clients/cache/redis/cache.py",
107
+ "*/foundation/tracer/tracer.py",
108
+ "*/foundation/observability.py",
109
+ "*/execution/executor/real_ray_runtime.py",
110
+ ]
111
+
112
+ [tool.ruff]
113
+ line-length = 90
114
+ preview = true
115
+
116
+ [tool.ruff.lint]
117
+ select = ["ALL"]
118
+ ignore = [
119
+ "missing-type-args",
120
+ "missing-type-kwargs",
121
+ "blind-except",
122
+ "missing-trailing-comma",
123
+ "missing-copyright-notice",
124
+ "undocumented-magic-method",
125
+ "undocumented-public-init",
126
+ "blank-line-after-function",
127
+ "incorrect-blank-line-before-class",
128
+ "multi-line-summary-second-line",
129
+ "DOC",
130
+ "line-too-long",
131
+ "line-contains-todo",
132
+ "FURB",
133
+ "invalid-function-name",
134
+ "invalid-module-name",
135
+ "pytest-fixture-autouse",
136
+ "unnecessary-paren-on-raise-exception",
137
+ "noqa-comments",
138
+ "runtime-cast-value",
139
+ "missing-todo-author",
140
+ "missing-todo-link",
141
+ "raise-vanilla-class",
142
+ "try-consider-else",
143
+ "f-string",
144
+ ]
145
+
146
+ [tool.ruff.lint.isort]
147
+ known-first-party = ["techai_webutils"]
148
+
149
+ [tool.ruff.lint.per-file-ignores]
150
+ "src/techai_webutils/clients/llm/bedrock/*.py" = ["invalid-argument-name"]
151
+ "src/techai_webutils/clients/retrieval/bedrock/*.py" = ["invalid-argument-name"]
152
+ "src/techai_webutils/clients/kb_ingestion/bedrock/*.py" = ["invalid-argument-name"]
153
+ "**/tests/**" = [
154
+ "S",
155
+ "magic-value-comparison",
156
+ "missing-type-function-argument",
157
+ "no-self-use",
158
+ "implicit-namespace-package",
159
+ "import-outside-top-level",
160
+ ]
161
+
162
+ [tool.ruff.lint.mccabe]
163
+ max-complexity = 15
164
+
165
+ [tool.ruff.lint.pylint]
166
+ max-args = 10
167
+ max-branches = 20
168
+ max-returns = 20
169
+
170
+ [tool.pyright]
171
+ pythonVersion = "3.12"
172
+ typeCheckingMode = "strict"
173
+ include = [
174
+ "src/techai_webutils",
175
+ "tests",
176
+ ]
177
+
178
+ [[tool.pyright.executionEnvironments]]
179
+ root = "tests"
180
+ reportUnknownMemberType = "none"
181
+ reportUnknownArgumentType = "none"
182
+ reportUnknownVariableType = "none"
183
+ reportUnknownParameterType = "none"
184
+ reportUnknownLambdaType = "none"
185
+ reportAttributeAccessIssue = "none"
186
+
187
+ [tool.uv.build-backend]
188
+ module-name = "techai_webutils"
@@ -0,0 +1,269 @@
1
+ [project]
2
+ name = "techai-webutils"
3
+ version = "0.0.1"
4
+ # ^^^^^
5
+ # Wheel names will be generated according to this value. Do not manually modify this value; instead
6
+ # update it according to committed changes by running this command from the root of the repository:
7
+ #
8
+ # uv run python -m AutoGitSemVer.scripts.UpdatePythonVersion ./pyproject.toml ./src
9
+
10
+ description = "techai-webutils"
11
+ readme = "README.md"
12
+ authors = [
13
+ { name = "Tech AI at Georgia Institute of Technology" }
14
+ ]
15
+ requires-python = ">= 3.12"
16
+ dependencies = [
17
+ "aiobotocore>=3.5.0",
18
+ # aiosmtplib: async SMTP send for the SMTP email backend (clients/email/smtp); lazy-imported by
19
+ # new_email_from_config only on the SMTP path. Peer of aiobotocore (the SES backend's transport).
20
+ "aiosmtplib>=3.0.0",
21
+ "fastapi>=0.136.0",
22
+ "grpcio>=1.80.0",
23
+ "grpcio-health-checking>=1.80.0",
24
+ "grpcio-reflection>=1.80.0",
25
+ "httpx>=0.28.1",
26
+ "opentelemetry-api>=1.41.0",
27
+ "opentelemetry-exporter-otlp-proto-grpc>=1.41.0",
28
+ "opentelemetry-sdk>=1.41.0",
29
+ "prometheus-client>=0.25.0",
30
+ "pydantic>=2.13.3",
31
+ "pydantic-settings>=2.14.1",
32
+ "qdrant-client>=1.12.0",
33
+ "pyyaml>=6.0.3",
34
+ "redis>=7.4.0",
35
+ "structlog>=25.5.0",
36
+ "tenacity>=9.1.4",
37
+ "uvicorn>=0.48.0",
38
+ "protovalidate>=2.0.0,<3",
39
+ ]
40
+ classifiers = [
41
+ "Operating System :: MacOS",
42
+ "Operating System :: Microsoft :: Windows",
43
+ "Operating System :: POSIX :: Linux",
44
+ "Programming Language :: Python",
45
+ "Programming Language :: Python :: 3.12",
46
+ ]
47
+
48
+ [project.optional-dependencies]
49
+ # Distributed execution backend (RayExecutor + RealRayRuntime). Optional and heavy:
50
+ # only a deployable that runs distributed batches installs `techai-webutils[ray]`. The default
51
+ # asyncio path (AsyncioExecutor) never pulls Ray — the RayRuntime protocol and
52
+ # RayExecutor carry no `ray` import; only RealRayRuntime does, imported lazily by
53
+ # `executor_from_config` when `ExecutorConfig.kind` is `ray`.
54
+ #
55
+ # ⚠ Ray requires the driver and the cluster to run the SAME version. Pinned EXACTLY to match the
56
+ # Ray testcontainer in the integration tests (rayproject/ray:2.56.1-py312) — `ray://` rejects a
57
+ # version mismatch, so a consumer's Ray cluster image must match this pin too. Bump this pin and the
58
+ # dev-group `ray` pin below together when upgrading Ray.
59
+ ray = ["ray==2.56.1"]
60
+
61
+ # Cross-pod single-writer lock backend (PostgresAdvisoryLock). Optional: only a deployable
62
+ # that needs the cross-pod lock installs `techai-webutils[postgres]`. The default in-memory lock
63
+ # never pulls asyncpg — the `postgres` backend impl is imported lazily by `new_lock_from_config`
64
+ # when `LockConfig.kind` is `postgres`.
65
+ postgres = ["asyncpg>=0.30.0"]
66
+
67
+ # Document-parsing backend (the `isolated` parser: MarkItDown + pymupdf). Optional and heavy: only a
68
+ # parse-running deployable installs `techai-webutils[parsing]`. The
69
+ # `clients/parsing` factory + interface never import these — the `isolated` backend imports them
70
+ # lazily inside its parse methods / the forkserver, so the default import graph never pulls them.
71
+ parsing = ["markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.6", "pymupdf>=1.28.0"]
72
+
73
+ # Language-detection backend (the `langdetect` MetadataExtractor). Optional: only a
74
+ # deployable that extracts document metadata installs `techai-webutils[langdetect]`. The `clients/metadata`
75
+ # factory never imports it — the `langdetect` backend subpackage is imported lazily by
76
+ # `metadata_extractor_from_config`, so the default import graph never pulls it.
77
+ langdetect = ["langdetect>=1.0.9"]
78
+
79
+ [project.license]
80
+ text = "MIT"
81
+
82
+ [project.urls]
83
+ Homepage = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
84
+ Documentation = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
85
+ Repository = "https://github.com/gt-tech-ai/knowledge-engine-toolkit"
86
+
87
+ [build-system]
88
+ requires = ["uv_build>=0.11.15,<0.12.0"]
89
+ build-backend = "uv_build"
90
+
91
+ [dependency-groups]
92
+ dev = [
93
+ "autogitsemver>=0.9.13",
94
+ "pytest>=9.0.3",
95
+ "pytest-asyncio>=1.0.0",
96
+ "pytest-cov>=7.1.0",
97
+ # Installed in dev/CI so basedpyright can resolve RealRayRuntime's `import ray` and the real-Ray
98
+ # integration tests (@pytest.mark.integration) can run against a Ray testcontainer; production
99
+ # consumers pull it via the `ray` extra, not this group. Pinned EXACTLY to the same version as the
100
+ # `ray` extra so the ray:// driver matches the cluster (see the extra above).
101
+ "ray==2.56.1",
102
+ "ruff==0.16.9",
103
+ "basedpyright==1.40.1",
104
+ # asyncpg in dev so basedpyright resolves `import asyncpg` in the postgres lock backend and the
105
+ # real-Postgres integration test can run; production consumers pull it via the `postgres` extra.
106
+ "asyncpg>=0.30.0",
107
+ # markitdown + pymupdf in dev so basedpyright resolves the `isolated` parser backend's lazy
108
+ # imports and its parity tests (real conversion + real subprocess isolation) run; production
109
+ # consumers pull them via the `parsing` extra.
110
+ "markitdown[docx,pdf,pptx,xls,xlsx]>=0.1.6",
111
+ "pymupdf>=1.28.0",
112
+ # langdetect in dev so basedpyright resolves the `langdetect` metadata backend and its parity
113
+ # tests run; production consumers pull it via the `langdetect` extra.
114
+ "langdetect>=1.0.9",
115
+ "testcontainers[postgres,redis]>=4.14.2",
116
+ "ty>=0.0.38",
117
+ # hypothesis drives the property tests (e.g. the token-ledger Decimal cost arithmetic).
118
+ "hypothesis>=6.168.5",
119
+ "asyncpg-stubs==0.31.3",
120
+ "types-aiobotocore-lite[s3,sesv2,sqs]==3.9.0",
121
+ ]
122
+
123
+ [tool.pytest.ini_options]
124
+ # tests/ is put on sys.path by pytest's default prepend import mode (there is no
125
+ # tests/__init__.py). Test doubles are built inline with unittest.mock in each
126
+ # test (spec-bound to the real core interfaces), so no shared test-double package
127
+ # and no pythonpath directive are needed.
128
+ # Hand-written unit coverage is gated at >=90%. The denominator excludes the
129
+ # integration-only external wrappers (gRPC server factory + OTel tracing
130
+ # interceptors, SQS/S3/Redis clients, OTel tracer/observability): they are carved
131
+ # out below (covered by the integration suite, the Python equivalent of Go's
132
+ # unit-only carve-outs); the genuinely unit-testable interceptor logic is tested
133
+ # instead of excluded.
134
+ addopts = "--verbose -vv --capture=no --strict-markers --cov=techai_webutils --cov-report html --cov-report term --cov-report xml:coverage.xml --cov-fail-under=90.0"
135
+ # Registered markers (enforced by --strict-markers, so a typo'd/unregistered marker
136
+ # now errors instead of silently passing). `integration` tests need a Docker daemon
137
+ # (testcontainers) and are deselected from the default unit run via `-m "not integration"`.
138
+ markers = [
139
+ "integration: real-dependency tests via testcontainers (Docker required); deselected in the unit run",
140
+ "slow: slow tests, deselected with --fast",
141
+ ]
142
+
143
+ [tool.coverage.run]
144
+ # relative_files + a distinct (non-hidden) data file let an optional combined
145
+ # coverage gate merge this unit dataset with an integration dataset (see
146
+ # .coveragerc.combined). The unit run writes coverage_unit.dat; an integration run
147
+ # can write coverage_integration.dat, and `coverage combine` +
148
+ # `coverage report --rcfile .coveragerc.combined` merges them. No CI job runs that
149
+ # combined gate — it is a local check.
150
+ relative_files = true
151
+ data_file = "coverage_unit.dat"
152
+
153
+ [tool.coverage.report]
154
+ # Excluded from the UNIT denominator (>=90% gate is over hand-written, unit-testable
155
+ # logic). Each entry is either test infrastructure or a thin external-dependency
156
+ # wrapper whose uncovered lines are the real network/SDK calls — exercised by the
157
+ # integration suite, not unit tests. Mirrors Go's unit-only carve-out set.
158
+ #
159
+ # This omit is at REPORT time (not [run]) so the unit run still MEASURES the
160
+ # wrappers — their partial unit coverage then lands in coverage_unit.dat and can
161
+ # merge into the optional combined gate (.coveragerc.combined), which counts them.
162
+ omit = [
163
+ "*/clients/transport/grpc/server.py", # gRPC server factory (binds/serves) — integration
164
+ "*/clients/rpc/grpc/interceptors/tracing.py", # OTel client span wiring — integration/runtime
165
+ "*/clients/rpc/grpc/interceptors/tracing_server.py", # OTel server span wiring — integration/runtime
166
+ "*/clients/messaging/sqs/sqs_publisher.py", # boto3 SQS send — integration (ElasticMQ)
167
+ "*/clients/messaging/sqs/sqs_subscriber.py", # boto3 SQS receive loop — integration (ElasticMQ)
168
+ "*/foundation/resilience/sqs_dlq.py", # boto3 SQS DLQ send — integration (ElasticMQ)
169
+ "*/clients/storage/s3/s3_client.py", # boto3 S3 client — integration (MinIO)
170
+ "*/clients/llm/bedrock/*.py", # aiobotocore bedrock-runtime wrapper — integration/runtime
171
+ "*/clients/retrieval/bedrock/*.py", # aiobotocore bedrock-agent-runtime wrapper — integration/runtime
172
+ "*/clients/kb_ingestion/bedrock/*.py", # aiobotocore bedrock-agent KB ingestion — integration/runtime
173
+ "*/clients/email/ses/provider.py", # aiobotocore SESv2 send — E2E only (staging/prod SES)
174
+ "*/clients/email/smtp/provider.py", # aiosmtplib SMTP send — E2E only (dev Mailpit)
175
+ "*/clients/cache/redis/cache.py", # aioredis wrapper — integration (Redis)
176
+ "*/foundation/tracer/tracer.py", # OTel tracer SDK init — integration/runtime
177
+ "*/foundation/observability.py", # OTel observability bootstrap — integration/runtime
178
+ "*/execution/executor/real_ray_runtime.py", # ray.init + @ray.remote wrapper — integration (real Ray)
179
+ ]
180
+
181
+ [tool.ruff]
182
+ line-length = 90
183
+
184
+ # preview = true enables ruff's preview rules for BOTH `ruff check` and
185
+ # `ruff format` (it is a top-level key, not scoped to [lint]).
186
+ preview = true
187
+
188
+ [tool.ruff.lint]
189
+ select = ["ALL"]
190
+
191
+ ignore = [
192
+ "missing-type-args", # Missing type annotation for `*args`
193
+ "missing-type-kwargs", # Missing type annotation for `**kwargs`
194
+ "blind-except", # Do not catch blind exception: `Exception`
195
+ "missing-trailing-comma", # Trailing comma missing
196
+ "missing-copyright-notice", # flake8-copyright: repo does not use file copyright headers
197
+ "undocumented-magic-method", # Missing docstring in magic method
198
+ "undocumented-public-init", # Missing docstring in `__init__` method
199
+ "blank-line-after-function", # No blank lines allowed after function docstring
200
+ "incorrect-blank-line-before-class", # 1 blank line before class docstring (conflicts with D211; ruff keeps D211)
201
+ "multi-line-summary-second-line", # Multi-line summary on second line (conflicts with D212; ruff keeps D212)
202
+ "DOC", # pydoclint family (preview): listed as "Consider", not adopted
203
+ "line-too-long", # Line too long
204
+ "line-contains-todo", # Line contains TODO, consider resolving the issue
205
+ "FURB", # refurb family (preview): listed as "Consider", not adopted
206
+ "invalid-function-name", # Function name `xxx` should be lowercase
207
+ "invalid-module-name", # Invalid module name
208
+ "pytest-fixture-autouse", # flake8-pytest-style (preview, no assigned rule code so it cannot be suppressed per-line via `# noqa`): autouse is a deliberate cross-cutting test pattern here — per-test env isolation and the integration-suite Docker gate — so this opinionated preview rule is deferred like DOC/FURB.
209
+ "unnecessary-paren-on-raise-exception", # Unnecessary parentheses on raise exception
210
+ "noqa-comments", # noqa-comments (preview): opinionated/stylistic rule preferring `# ruff: ignore[...]` over `# noqa`; ruff itself sanctions disabling it. We keep the universal, tool-agnostic `# noqa: <CODE>` form.
211
+ "runtime-cast-value", # Add quotes to type expression in `typing.cast()`
212
+ "missing-todo-author", # Missing author in TODO
213
+ "missing-todo-link", # Missing issue link for this TODO
214
+ "raise-vanilla-class", # Create your own exception
215
+ "try-consider-else", # Consider moving this statement to an `else` block
216
+ "f-string", # Use f-string instead of `format` call
217
+ ]
218
+
219
+ [tool.ruff.lint.isort]
220
+ known-first-party = ["techai_webutils"]
221
+
222
+ [tool.ruff.lint.per-file-ignores]
223
+ # The bedrock clients mirror the AWS bedrock-runtime / bedrock-agent-runtime / bedrock-agent APIs, whose
224
+ # keyword params are camelCase (knowledgeBaseId, modelId, retrievalQuery, dataSourceId, …) — N803 does
225
+ # not apply to a wire mirror.
226
+ "src/techai_webutils/clients/llm/bedrock/*.py" = ["invalid-argument-name"]
227
+ "src/techai_webutils/clients/retrieval/bedrock/*.py" = ["invalid-argument-name"]
228
+ "src/techai_webutils/clients/kb_ingestion/bedrock/*.py" = ["invalid-argument-name"]
229
+ # Each entry is a rule wrong-by-design for the whole test tree.
230
+ "**/tests/**" = [
231
+ "S", # flake8-bandit: bandit is the dedicated security gate and excludes tests; fixtures use fake credentials and intentionally exercise flagged patterns (assert, e2e subprocess, bind-all in local config)
232
+ "magic-value-comparison", # magic-value comparisons are expected in test assertions
233
+ "missing-type-function-argument", # test fixtures/params need no redundant annotations (types still resolve under basedpyright)
234
+ "no-self-use", # pytest groups tests as methods on a class; `self` is required by the collector even when unused
235
+ "implicit-namespace-package", # test trees are flat implicit-namespace packages (no __init__.py), collected by pytest
236
+ "import-outside-top-level", # tests import the concrete implementation under test locally to keep each case's deps explicit
237
+ ]
238
+
239
+ [tool.ruff.lint.mccabe]
240
+ max-complexity = 15
241
+
242
+ [tool.ruff.lint.pylint]
243
+ max-args = 10
244
+ max-branches = 20
245
+ max-returns = 20
246
+
247
+ # Strict type-checking over src and tests. include is an allowlist, so tests are analyzed
248
+ # only because they are listed here.
249
+ [tool.pyright]
250
+ pythonVersion = "3.12"
251
+ typeCheckingMode = "strict"
252
+ include = ["src/techai_webutils", "tests"]
253
+
254
+ # Mock-noise relaxation for the test tree: pytest fixtures and unittest.mock doubles are
255
+ # intentionally untyped, so the reportUnknown* family and the mock attribute-access probes
256
+ # (.assert_called_once / .await_args_list, which resolve on an autospec'd MethodType, not on
257
+ # the Mock) are pure noise there. src/ stays fully strict, and every other strict diagnostic
258
+ # (argument types, optional access, private usage) is still enforced in tests.
259
+ [[tool.pyright.executionEnvironments]]
260
+ root = "tests"
261
+ reportUnknownMemberType = "none"
262
+ reportUnknownArgumentType = "none"
263
+ reportUnknownVariableType = "none"
264
+ reportUnknownParameterType = "none"
265
+ reportUnknownLambdaType = "none"
266
+ reportAttributeAccessIssue = "none"
267
+
268
+ [tool.uv.build-backend]
269
+ module-name = "techai_webutils"
@@ -0,0 +1,5 @@
1
+ """TechAI web utilities shared library."""
2
+
3
+ from importlib.metadata import version
4
+
5
+ __version__ = version("techai_webutils")
@@ -0,0 +1,8 @@
1
+ """Clients layer - external system integration abstractions.
2
+
3
+ This layer contains gRPC client/server factories, decorators, messaging (SQS),
4
+ storage (S3), cache decorators, and integration code for external systems.
5
+
6
+ Clients implements the third tier (ARCHITECTURE.md#layers-and-import-direction):
7
+ core -> foundation -> clients -> repos -> services -> pipelines -> workflows -> controllers
8
+ """
@@ -0,0 +1,9 @@
1
+ """AI audit records: a config-selected ``AuditSink`` (``stub`` built in; durable sinks injected)."""
2
+
3
+ from techai_webutils.clients.audit.builder import (
4
+ AuditSinkConfig,
5
+ AuditSinkKind,
6
+ new_audit_sink_from_config,
7
+ )
8
+
9
+ __all__ = ["AuditSinkConfig", "AuditSinkKind", "new_audit_sink_from_config"]