contextsynapse 1.0.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 (776) hide show
  1. contextsynapse/__init__.py +107 -0
  2. contextsynapse/__main__.py +9 -0
  3. contextsynapse/a2a/__init__.py +28 -0
  4. contextsynapse/a2a/client.py +120 -0
  5. contextsynapse/a2a/discovery.py +128 -0
  6. contextsynapse/a2a/handlers.py +164 -0
  7. contextsynapse/a2a/models.py +246 -0
  8. contextsynapse/a2a/streaming.py +92 -0
  9. contextsynapse/a2a/task_manager.py +275 -0
  10. contextsynapse/adapters/__init__.py +98 -0
  11. contextsynapse/adapters/_base.py +298 -0
  12. contextsynapse/adapters/autogen/__init__.py +4 -0
  13. contextsynapse/adapters/autogen/tools.py +34 -0
  14. contextsynapse/adapters/crewai/__init__.py +4 -0
  15. contextsynapse/adapters/crewai/tools.py +63 -0
  16. contextsynapse/adapters/langchain/__init__.py +19 -0
  17. contextsynapse/adapters/langchain/message_history.py +17 -0
  18. contextsynapse/adapters/langchain/retriever.py +158 -0
  19. contextsynapse/adapters/langchain/tools.py +43 -0
  20. contextsynapse/adapters/langgraph/__init__.py +21 -0
  21. contextsynapse/adapters/langgraph/checkpoint.py +223 -0
  22. contextsynapse/adapters/langgraph/context_tools.py +341 -0
  23. contextsynapse/adapters/langgraph/message_history.py +138 -0
  24. contextsynapse/adapters/langgraph/tools.py +43 -0
  25. contextsynapse/adapters/llamaindex/__init__.py +4 -0
  26. contextsynapse/adapters/llamaindex/tools.py +64 -0
  27. contextsynapse/adapters/openai/__init__.py +24 -0
  28. contextsynapse/adapters/openai/tools.py +206 -0
  29. contextsynapse/adapters/pydantic_ai/__init__.py +4 -0
  30. contextsynapse/adapters/pydantic_ai/tools.py +36 -0
  31. contextsynapse/adapters/swarm/__init__.py +4 -0
  32. contextsynapse/adapters/swarm/tools.py +44 -0
  33. contextsynapse/agents/__init__.py +6 -0
  34. contextsynapse/agents/auto_capture.py +80 -0
  35. contextsynapse/agents/dispatcher.py +299 -0
  36. contextsynapse/agents/notifications.py +112 -0
  37. contextsynapse/aiql/__init__.py +71 -0
  38. contextsynapse/aiql/cache.py +341 -0
  39. contextsynapse/aiql/compiler/__init__.py +62 -0
  40. contextsynapse/aiql/compiler/optimizer.py +126 -0
  41. contextsynapse/aiql/compiler/planner.py +366 -0
  42. contextsynapse/aiql/compiler/statistics.py +235 -0
  43. contextsynapse/aiql/compiler/validator.py +425 -0
  44. contextsynapse/aiql/engine/__init__.py +11 -0
  45. contextsynapse/aiql/engine/chunk_storage.py +2584 -0
  46. contextsynapse/aiql/engine/executor.py +7737 -0
  47. contextsynapse/aiql/engine/extraction_integration.py +442 -0
  48. contextsynapse/aiql/engine/graph_builder.py +405 -0
  49. contextsynapse/aiql/engine/node_creation_from_normalized.py +691 -0
  50. contextsynapse/aiql/engine/performance_monitor.py +289 -0
  51. contextsynapse/aiql/engine/postprocessing.py +365 -0
  52. contextsynapse/aiql/engine/ray_stage_executors.py +918 -0
  53. contextsynapse/aiql/engine/redis_cache.py +106 -0
  54. contextsynapse/aiql/engine/streaming_json.py +366 -0
  55. contextsynapse/aiql/engine/streaming_parquet.py +568 -0
  56. contextsynapse/aiql/engine/streaming_ray_chunking.py +419 -0
  57. contextsynapse/aiql/grammar/__init__.py +14 -0
  58. contextsynapse/aiql/grammar/aiql_grammar.py +1822 -0
  59. contextsynapse/aiql/grammar/base.py +71 -0
  60. contextsynapse/aiql/parser/__init__.py +46 -0
  61. contextsynapse/aiql/parser/aiql_parser.py +11330 -0
  62. contextsynapse/aiql/parser/base_parser.py +47 -0
  63. contextsynapse/api/__init__.py +5 -0
  64. contextsynapse/api/a2a_router.py +233 -0
  65. contextsynapse/api/admin_router.py +140 -0
  66. contextsynapse/api/agent_worker_router.py +978 -0
  67. contextsynapse/api/algorithms_router.py +317 -0
  68. contextsynapse/api/api.py +4144 -0
  69. contextsynapse/api/audit.py +204 -0
  70. contextsynapse/api/auth.py +441 -0
  71. contextsynapse/api/auth_router.py +537 -0
  72. contextsynapse/api/billing.py +261 -0
  73. contextsynapse/api/billing_router.py +275 -0
  74. contextsynapse/api/boundary_router.py +452 -0
  75. contextsynapse/api/cognition_router.py +116 -0
  76. contextsynapse/api/connector_router.py +237 -0
  77. contextsynapse/api/context_router.py +1619 -0
  78. contextsynapse/api/dashboard_router.py +11367 -0
  79. contextsynapse/api/errors.py +183 -0
  80. contextsynapse/api/events.py +88 -0
  81. contextsynapse/api/experiment_bootstrap.py +321 -0
  82. contextsynapse/api/experiment_orchestrator.py +1078 -0
  83. contextsynapse/api/experiment_router.py +2089 -0
  84. contextsynapse/api/feature_gate.py +89 -0
  85. contextsynapse/api/federation_router.py +108 -0
  86. contextsynapse/api/integrations.py +567 -0
  87. contextsynapse/api/integrations_router.py +461 -0
  88. contextsynapse/api/intelligence_router.py +1028 -0
  89. contextsynapse/api/metering.py +155 -0
  90. contextsynapse/api/metrics.py +112 -0
  91. contextsynapse/api/models.py +38 -0
  92. contextsynapse/api/monitoring_router.py +174 -0
  93. contextsynapse/api/pipeline_router.py +1437 -0
  94. contextsynapse/api/playground_conn.py +116 -0
  95. contextsynapse/api/projects_router.py +131 -0
  96. contextsynapse/api/queries_router.py +282 -0
  97. contextsynapse/api/quota.py +95 -0
  98. contextsynapse/api/rate_limit.py +64 -0
  99. contextsynapse/api/search_router.py +261 -0
  100. contextsynapse/api/shield_router.py +447 -0
  101. contextsynapse/api/tenant_guard.py +103 -0
  102. contextsynapse/api/tenant_quotas.py +231 -0
  103. contextsynapse/api/tenants.py +305 -0
  104. contextsynapse/api/users.py +646 -0
  105. contextsynapse/api/v1.py +167 -0
  106. contextsynapse/api/vertical_builder_router.py +387 -0
  107. contextsynapse/benchmark/__init__.py +15 -0
  108. contextsynapse/benchmark/__main__.py +64 -0
  109. contextsynapse/benchmark/agents.py +338 -0
  110. contextsynapse/benchmark/live_ab.py +338 -0
  111. contextsynapse/benchmark/reporter.py +149 -0
  112. contextsynapse/benchmark/runner.py +264 -0
  113. contextsynapse/benchmark/savings.py +266 -0
  114. contextsynapse/benchmark/token_counter.py +212 -0
  115. contextsynapse/benchmark/workloads.py +289 -0
  116. contextsynapse/buffer/__init__.py +154 -0
  117. contextsynapse/buffer/base.py +257 -0
  118. contextsynapse/buffer/duckdb_buffer.py +246 -0
  119. contextsynapse/buffer/file_buffer.py +229 -0
  120. contextsynapse/buffer/lmdb_buffer.py +286 -0
  121. contextsynapse/buffer/local_buffer.py +154 -0
  122. contextsynapse/buffer/redis_buffer.py +211 -0
  123. contextsynapse/buffer/sqlite_buffer.py +266 -0
  124. contextsynapse/cache.py +2 -0
  125. contextsynapse/cli/__init__.py +40 -0
  126. contextsynapse/cli/cli.py +475 -0
  127. contextsynapse/cli/config_cli.py +177 -0
  128. contextsynapse/cli/scaffold.py +465 -0
  129. contextsynapse/cognition/__init__.py +31 -0
  130. contextsynapse/cognition/derivation.py +55 -0
  131. contextsynapse/cognition/events.py +135 -0
  132. contextsynapse/cognition/feedback.py +52 -0
  133. contextsynapse/cognition/hallucination.py +90 -0
  134. contextsynapse/cognition/invalidation.py +70 -0
  135. contextsynapse/cognition/read_tracker.py +50 -0
  136. contextsynapse/collaboration.py +2 -0
  137. contextsynapse/comparison.py +2 -0
  138. contextsynapse/config/__init__.py +10 -0
  139. contextsynapse/config/connectors/amfi_nav.yaml +18 -0
  140. contextsynapse/config/connectors/auto_sector.yaml +20 -0
  141. contextsynapse/config/connectors/banking_sector.yaml +20 -0
  142. contextsynapse/config/connectors/energy_sector.yaml +20 -0
  143. contextsynapse/config/connectors/fmcg_sector.yaml +20 -0
  144. contextsynapse/config/connectors/nsdl_fpi.yaml +9 -0
  145. contextsynapse/config/connectors/nse_price.yaml +61 -0
  146. contextsynapse/config/connectors/pharma_sector.yaml +20 -0
  147. contextsynapse/config/connectors/rbi_dbie.yaml +12 -0
  148. contextsynapse/config/context_presets/ai_research.json +25 -0
  149. contextsynapse/config/context_presets/chatgpt_conversations.json +19 -0
  150. contextsynapse/config/context_presets/claude_conversations.json +19 -0
  151. contextsynapse/config/context_presets/legal_compliance.json +21 -0
  152. contextsynapse/config/context_presets/meeting_notes.json +21 -0
  153. contextsynapse/config/context_presets/slack_engineering.json +21 -0
  154. contextsynapse/config/context_presets/tech_climate.json +24 -0
  155. contextsynapse/config/context_presets/toi_politics.json +25 -0
  156. contextsynapse/config/database_config.py +453 -0
  157. contextsynapse/config/deployment.py +221 -0
  158. contextsynapse/config/gpt_action_schema.json +164 -0
  159. contextsynapse/config/indicators/india_macro.yaml +213 -0
  160. contextsynapse/config/logging_config.py +88 -0
  161. contextsynapse/config/mode_config.py +223 -0
  162. contextsynapse/config/schemas/api_spec.yaml +48 -0
  163. contextsynapse/config/schemas/architecture_doc.yaml +51 -0
  164. contextsynapse/config/schemas/chat_history.yaml +90 -0
  165. contextsynapse/config/schemas/chatgpt_conversation.yaml +101 -0
  166. contextsynapse/config/schemas/claude_conversation.yaml +148 -0
  167. contextsynapse/config/schemas/contract.yaml +48 -0
  168. contextsynapse/config/schemas/conversation.yaml +167 -0
  169. contextsynapse/config/schemas/database.yaml +74 -0
  170. contextsynapse/config/schemas/decision.yaml +72 -0
  171. contextsynapse/config/schemas/ecommerce.yaml +56 -0
  172. contextsynapse/config/schemas/education.yaml +42 -0
  173. contextsynapse/config/schemas/healthcare.yaml +133 -0
  174. contextsynapse/config/schemas/hr_document.yaml +48 -0
  175. contextsynapse/config/schemas/invoice.yaml +40 -0
  176. contextsynapse/config/schemas/knowledge_base.yaml +75 -0
  177. contextsynapse/config/schemas/legal.yaml +42 -0
  178. contextsynapse/config/schemas/marketing_content.yaml +48 -0
  179. contextsynapse/config/schemas/meeting_notes.yaml +51 -0
  180. contextsynapse/config/schemas/news_article.yaml +61 -0
  181. contextsynapse/config/schemas/real_estate.yaml +49 -0
  182. contextsynapse/config/schemas/requirements_doc.yaml +48 -0
  183. contextsynapse/config/schemas/research_paper.yaml +56 -0
  184. contextsynapse/config/schemas/resume.yaml +49 -0
  185. contextsynapse/config/schemas/retail.yaml +42 -0
  186. contextsynapse/config/schemas/rule_meta.yaml +173 -0
  187. contextsynapse/config/schemas/rules.yaml +72 -0
  188. contextsynapse/config/schemas/screener_meta.yaml +236 -0
  189. contextsynapse/config/schemas/sdlc.yaml +103 -0
  190. contextsynapse/config/schemas/session_graph.yaml +172 -0
  191. contextsynapse/config/schemas/support_ticket.yaml +48 -0
  192. contextsynapse/config/schemas/web.yaml +64 -0
  193. contextsynapse/config/sensors/earnings_calendar.yaml +52 -0
  194. contextsynapse/config/sensors/global_risk.yaml +53 -0
  195. contextsynapse/config/sensors/government_policy.yaml +54 -0
  196. contextsynapse/config/sensors/supply_chain.yaml +50 -0
  197. contextsynapse/config/sensors/templates/behavioral.yaml +56 -0
  198. contextsynapse/config/sensors/templates/equity_sentiment.yaml +48 -0
  199. contextsynapse/config/sensors/templates/global_macro.yaml +47 -0
  200. contextsynapse/config/sensors/templates/market_data.yaml +118 -0
  201. contextsynapse/config/sensors/templates/sector_technical.yaml +47 -0
  202. contextsynapse/config/sensors/weather.yaml +52 -0
  203. contextsynapse/config/storage_strategy.py +202 -0
  204. contextsynapse/config/templates/competitive_intel.yaml +39 -0
  205. contextsynapse/config/templates/geopolitical_risk.yaml +46 -0
  206. contextsynapse/config/templates/market_analysis.yaml +58 -0
  207. contextsynapse/connectors/__init__.py +15 -0
  208. contextsynapse/connectors/api_router.py +121 -0
  209. contextsynapse/connectors/base.py +357 -0
  210. contextsynapse/connectors/financial/audio.py +170 -0
  211. contextsynapse/connectors/financial/youtube.py +272 -0
  212. contextsynapse/connectors/github.py +164 -0
  213. contextsynapse/connectors/jira.py +120 -0
  214. contextsynapse/connectors/kafka_connector.py +124 -0
  215. contextsynapse/connectors/pipeline_connector.py +747 -0
  216. contextsynapse/connectors/registry.py +116 -0
  217. contextsynapse/connectors/scheduler.py +87 -0
  218. contextsynapse/connectors/universal.py +360 -0
  219. contextsynapse/context/__init__.py +96 -0
  220. contextsynapse/context/__main__.py +4 -0
  221. contextsynapse/context/acl.py +125 -0
  222. contextsynapse/context/agent_card.py +201 -0
  223. contextsynapse/context/agent_memory.py +814 -0
  224. contextsynapse/context/agents.py +472 -0
  225. contextsynapse/context/agents_redis.py +391 -0
  226. contextsynapse/context/assembled.py +204 -0
  227. contextsynapse/context/attribution.py +113 -0
  228. contextsynapse/context/blob.py +184 -0
  229. contextsynapse/context/boundaries.py +187 -0
  230. contextsynapse/context/boundary.py +507 -0
  231. contextsynapse/context/bundle.py +155 -0
  232. contextsynapse/context/cli.py +519 -0
  233. contextsynapse/context/collaboration.py +165 -0
  234. contextsynapse/context/compiler.py +604 -0
  235. contextsynapse/context/composite.py +536 -0
  236. contextsynapse/context/compression.py +147 -0
  237. contextsynapse/context/context_manager.py +888 -0
  238. contextsynapse/context/context_schema.py +90 -0
  239. contextsynapse/context/context_schema.yaml +105 -0
  240. contextsynapse/context/context_units.py +891 -0
  241. contextsynapse/context/conversation.py +488 -0
  242. contextsynapse/context/dedup.py +207 -0
  243. contextsynapse/context/document_processor.py +698 -0
  244. contextsynapse/context/embedding_hooks.py +338 -0
  245. contextsynapse/context/execution_schema.py +274 -0
  246. contextsynapse/context/fan_out.py +138 -0
  247. contextsynapse/context/frozen.py +80 -0
  248. contextsynapse/context/gravity.py +227 -0
  249. contextsynapse/context/hub.py +1401 -0
  250. contextsynapse/context/ingest.py +391 -0
  251. contextsynapse/context/injection.py +226 -0
  252. contextsynapse/context/interaction_graphifier.py +562 -0
  253. contextsynapse/context/layers.py +574 -0
  254. contextsynapse/context/projection.py +1195 -0
  255. contextsynapse/context/promotion.py +634 -0
  256. contextsynapse/context/proof.py +131 -0
  257. contextsynapse/context/propagation.py +577 -0
  258. contextsynapse/context/pubsub.py +135 -0
  259. contextsynapse/context/quality.py +1054 -0
  260. contextsynapse/context/quality_tracker.py +270 -0
  261. contextsynapse/context/scoping.py +370 -0
  262. contextsynapse/context/seed.py +992 -0
  263. contextsynapse/context/session.py +1142 -0
  264. contextsynapse/context/session_graph.py +593 -0
  265. contextsynapse/context/session_memory.py +309 -0
  266. contextsynapse/context/session_resolver.py +111 -0
  267. contextsynapse/context/skill_learning.py +237 -0
  268. contextsynapse/context/smart_budget.py +129 -0
  269. contextsynapse/context/source_policy.py +242 -0
  270. contextsynapse/context/store_factory.py +53 -0
  271. contextsynapse/context/sync.py +648 -0
  272. contextsynapse/context/token.py +236 -0
  273. contextsynapse/context/vector_integration.py +297 -0
  274. contextsynapse/context/webhooks.py +194 -0
  275. contextsynapse/context/working_memory.py +224 -0
  276. contextsynapse/core/__init__.py +18 -0
  277. contextsynapse/core/archiver.py +237 -0
  278. contextsynapse/core/change_stream.py +282 -0
  279. contextsynapse/core/checkpoint.py +310 -0
  280. contextsynapse/core/cloud_storage.py +387 -0
  281. contextsynapse/core/context_state.py +651 -0
  282. contextsynapse/core/cron.py +324 -0
  283. contextsynapse/core/datasource.py +643 -0
  284. contextsynapse/core/db.py +289 -0
  285. contextsynapse/core/federation.py +283 -0
  286. contextsynapse/core/graph_coordinator.py +201 -0
  287. contextsynapse/core/graph_intelligence.py +388 -0
  288. contextsynapse/core/graph_structures.py +106 -0
  289. contextsynapse/core/graph_sync.py +157 -0
  290. contextsynapse/core/hybrid_graph_storage.py +2998 -0
  291. contextsynapse/core/lifecycle.py +691 -0
  292. contextsynapse/core/multiworker.py +378 -0
  293. contextsynapse/core/pruning.py +312 -0
  294. contextsynapse/core/redis_registry.py +524 -0
  295. contextsynapse/core/registry.py +1043 -0
  296. contextsynapse/core/registry_factory.py +51 -0
  297. contextsynapse/core/registry_metadata.py +294 -0
  298. contextsynapse/core/replay.py +354 -0
  299. contextsynapse/core/replication.py +339 -0
  300. contextsynapse/core/time_travel.py +260 -0
  301. contextsynapse/core/write_behind.py +152 -0
  302. contextsynapse/core/write_context.py +39 -0
  303. contextsynapse/db/__init__.py +1 -0
  304. contextsynapse/db/postgres.py +267 -0
  305. contextsynapse/db/profile.py +236 -0
  306. contextsynapse/db/rules.py +328 -0
  307. contextsynapse/demo/__init__.py +0 -0
  308. contextsynapse/demo/report.py +147 -0
  309. contextsynapse/demo/runner.py +520 -0
  310. contextsynapse/demo/scenario.py +165 -0
  311. contextsynapse/demo/session_demo.py +280 -0
  312. contextsynapse/demo/session_report.py +143 -0
  313. contextsynapse/demo/universal_runner.py +257 -0
  314. contextsynapse/engine/__init__.py +15 -0
  315. contextsynapse/engine/core.py +555 -0
  316. contextsynapse/extraction/__init__.py +69 -0
  317. contextsynapse/extraction/cli.py +274 -0
  318. contextsynapse/extraction/config.py +107 -0
  319. contextsynapse/extraction/examples/example_usage.py +118 -0
  320. contextsynapse/extraction/examples/sample_manifest.json +53 -0
  321. contextsynapse/extraction/examples/sample_normalized.json +185 -0
  322. contextsynapse/extraction/extract_engine.py +440 -0
  323. contextsynapse/extraction/extractors/__init__.py +37 -0
  324. contextsynapse/extraction/extractors/chat_export_extractor.py +189 -0
  325. contextsynapse/extraction/extractors/csv_extractor.py +83 -0
  326. contextsynapse/extraction/extractors/docx_extractor.py +129 -0
  327. contextsynapse/extraction/extractors/excel_extractor.py +152 -0
  328. contextsynapse/extraction/extractors/html_extractor.py +146 -0
  329. contextsynapse/extraction/extractors/pdf_extractor.py +635 -0
  330. contextsynapse/extraction/extractors/pdf_extractor_layoutparser.py +408 -0
  331. contextsynapse/extraction/extractors/register_extractors.py +63 -0
  332. contextsynapse/extraction/extractors/text_extractor.py +65 -0
  333. contextsynapse/extraction/extractors/txt_extractor.py +120 -0
  334. contextsynapse/extraction/extractors/website_extractor.py +246 -0
  335. contextsynapse/extraction/fact_extractor.py +236 -0
  336. contextsynapse/extraction/file_manager.py +353 -0
  337. contextsynapse/extraction/hierarchy.py +239 -0
  338. contextsynapse/extraction/id_generator.py +450 -0
  339. contextsynapse/extraction/layout_detector.py +409 -0
  340. contextsynapse/extraction/llm_entity_extractor.py +301 -0
  341. contextsynapse/extraction/normalized_store.py +480 -0
  342. contextsynapse/extraction/normalizer.py +594 -0
  343. contextsynapse/extraction/parquet_writer.py +598 -0
  344. contextsynapse/extraction/post_processors/__init__.py +40 -0
  345. contextsynapse/extraction/post_processors/column_reorganizer.py +507 -0
  346. contextsynapse/extraction/ray_normalization.py +233 -0
  347. contextsynapse/extraction/ray_runner.py +207 -0
  348. contextsynapse/extraction/redis_schema_registry.py +222 -0
  349. contextsynapse/extraction/registry.py +204 -0
  350. contextsynapse/extraction/schema_loader.py +663 -0
  351. contextsynapse/extraction/schema_registry.py +230 -0
  352. contextsynapse/extraction/semantic_normalizer.py +245 -0
  353. contextsynapse/extraction/version_manager.py +314 -0
  354. contextsynapse/gateway/__init__.py +24 -0
  355. contextsynapse/gateway/action_emitter.py +212 -0
  356. contextsynapse/gateway/cost_tracker.py +508 -0
  357. contextsynapse/gateway/gateway.py +377 -0
  358. contextsynapse/gateway/policy.py +303 -0
  359. contextsynapse/governance/__init__.py +13 -0
  360. contextsynapse/governance/layer.py +513 -0
  361. contextsynapse/ingestion/__init__.py +15 -0
  362. contextsynapse/ingestion/amplifier.py +288 -0
  363. contextsynapse/ingestion/async_ingest.py +463 -0
  364. contextsynapse/ingestion/chunker.py +303 -0
  365. contextsynapse/ingestion/chunking.py +58 -0
  366. contextsynapse/ingestion/cleaner.py +190 -0
  367. contextsynapse/ingestion/cleanse.py +252 -0
  368. contextsynapse/ingestion/connectors/__init__.py +38 -0
  369. contextsynapse/ingestion/connectors/base.py +300 -0
  370. contextsynapse/ingestion/connectors/chatgpt_memory.py +247 -0
  371. contextsynapse/ingestion/connectors/claude_memory.py +274 -0
  372. contextsynapse/ingestion/connectors/sap_ingestor.py +208 -0
  373. contextsynapse/ingestion/content_detector.py +80 -0
  374. contextsynapse/ingestion/content_monitor.py +502 -0
  375. contextsynapse/ingestion/dedup.py +106 -0
  376. contextsynapse/ingestion/feed.py +640 -0
  377. contextsynapse/ingestion/filters.py +461 -0
  378. contextsynapse/ingestion/graph_builder.py +705 -0
  379. contextsynapse/ingestion/input_classifier.py +307 -0
  380. contextsynapse/ingestion/job_manager.py +571 -0
  381. contextsynapse/ingestion/llm_extractor.py +610 -0
  382. contextsynapse/ingestion/orchestrator.py +116 -0
  383. contextsynapse/ingestion/parsers/__init__.py +19 -0
  384. contextsynapse/ingestion/parsers/graph_parser_registry.py +103 -0
  385. contextsynapse/ingestion/parsers/graphml_parser.py +141 -0
  386. contextsynapse/ingestion/parsers/jsonld_parser.py +171 -0
  387. contextsynapse/ingestion/parsers/rdf_parser.py +150 -0
  388. contextsynapse/ingestion/pipeline_context.py +228 -0
  389. contextsynapse/ingestion/pipeline_store.py +1195 -0
  390. contextsynapse/ingestion/queue.py +133 -0
  391. contextsynapse/ingestion/reprocess.py +179 -0
  392. contextsynapse/ingestion/scenario_router.py +224 -0
  393. contextsynapse/ingestion/schema_extractor.py +759 -0
  394. contextsynapse/ingestion/schema_validator.py +274 -0
  395. contextsynapse/ingestion/sdlc_ingest.py +87 -0
  396. contextsynapse/ingestion/smart_ingest.py +2451 -0
  397. contextsynapse/ingestion/source_connector.py +171 -0
  398. contextsynapse/ingestion/stage_executor.py +2095 -0
  399. contextsynapse/ingestion/stages/__init__.py +9 -0
  400. contextsynapse/ingestion/stages/tabular_to_graph.py +289 -0
  401. contextsynapse/ingestion/strategies.py +386 -0
  402. contextsynapse/ingestion/universal/__init__.py +4 -0
  403. contextsynapse/ingestion/universal/_operator_registry.py +59 -0
  404. contextsynapse/ingestion/universal/ingest_content.py +32 -0
  405. contextsynapse/ingestion/universal/operators/__init__.py +1 -0
  406. contextsynapse/ingestion/universal/operators/base.py +19 -0
  407. contextsynapse/ingestion/universal/operators/build_edges.py +75 -0
  408. contextsynapse/ingestion/universal/operators/cluster_topics.py +397 -0
  409. contextsynapse/ingestion/universal/operators/deduplicate.py +45 -0
  410. contextsynapse/ingestion/universal/operators/detect_signals.py +90 -0
  411. contextsynapse/ingestion/universal/operators/embed.py +80 -0
  412. contextsynapse/ingestion/universal/operators/extract_entities.py +253 -0
  413. contextsynapse/ingestion/universal/operators/extract_preferences.py +117 -0
  414. contextsynapse/ingestion/universal/operators/filter_content.py +69 -0
  415. contextsynapse/ingestion/universal/operators/index_bm25.py +52 -0
  416. contextsynapse/ingestion/universal/operators/infer_domains.py +69 -0
  417. contextsynapse/ingestion/universal/operators/link_cross_reference.py +210 -0
  418. contextsynapse/ingestion/universal/operators/parse_records.py +66 -0
  419. contextsynapse/ingestion/universal/operators/resolve_entities.py +261 -0
  420. contextsynapse/ingestion/universal/operators/scanners/__init__.py +16 -0
  421. contextsynapse/ingestion/universal/operators/scanners/edges.py +173 -0
  422. contextsynapse/ingestion/universal/operators/scanners/git.py +187 -0
  423. contextsynapse/ingestion/universal/operators/scanners/github.py +135 -0
  424. contextsynapse/ingestion/universal/operators/scanners/github_api.py +509 -0
  425. contextsynapse/ingestion/universal/operators/scanners/helpers.py +67 -0
  426. contextsynapse/ingestion/universal/operators/scanners/jira.py +65 -0
  427. contextsynapse/ingestion/universal/operators/scanners/llm_enrichment.py +82 -0
  428. contextsynapse/ingestion/universal/operators/scanners/repo.py +149 -0
  429. contextsynapse/ingestion/universal/operators/sdlc_scan.py +213 -0
  430. contextsynapse/ingestion/universal/operators/spec_scanner.py +149 -0
  431. contextsynapse/ingestion/universal/operators/store_documents.py +72 -0
  432. contextsynapse/ingestion/universal/operators/synthesize_cu.py +180 -0
  433. contextsynapse/ingestion/universal/operators/validate_gate.py +65 -0
  434. contextsynapse/ingestion/universal/parsers/__init__.py +5 -0
  435. contextsynapse/ingestion/universal/parsers/record_parser.py +203 -0
  436. contextsynapse/ingestion/universal/parsers/turn_parser.py +329 -0
  437. contextsynapse/ingestion/universal/shared_signals.py +161 -0
  438. contextsynapse/ingestion/universal/stage_executor.py +219 -0
  439. contextsynapse/ingestion/web_crawler.py +265 -0
  440. contextsynapse/intelligence/__init__.py +53 -0
  441. contextsynapse/intelligence/alerts.py +198 -0
  442. contextsynapse/intelligence/collector.py +655 -0
  443. contextsynapse/intelligence/comparison.py +198 -0
  444. contextsynapse/intelligence/config.py +56 -0
  445. contextsynapse/intelligence/conflict_detector.py +182 -0
  446. contextsynapse/intelligence/context_gaps.py +192 -0
  447. contextsynapse/intelligence/context_radar.py +135 -0
  448. contextsynapse/intelligence/correlation_engine.py +416 -0
  449. contextsynapse/intelligence/correlation_template.py +120 -0
  450. contextsynapse/intelligence/dedup.py +296 -0
  451. contextsynapse/intelligence/event_bus.py +91 -0
  452. contextsynapse/intelligence/feedback_loop.py +101 -0
  453. contextsynapse/intelligence/freshness.py +307 -0
  454. contextsynapse/intelligence/fundamental_feed.py +551 -0
  455. contextsynapse/intelligence/geo_data.py +170 -0
  456. contextsynapse/intelligence/geo_reference.py +112 -0
  457. contextsynapse/intelligence/graph_fusion.py +465 -0
  458. contextsynapse/intelligence/heuristics.py +176 -0
  459. contextsynapse/intelligence/impact_tracker.py +336 -0
  460. contextsynapse/intelligence/macro_indicators.py +319 -0
  461. contextsynapse/intelligence/ocr.py +104 -0
  462. contextsynapse/intelligence/persistence.py +267 -0
  463. contextsynapse/intelligence/pipeline_health.py +130 -0
  464. contextsynapse/intelligence/price_feed.py +221 -0
  465. contextsynapse/intelligence/rate_limiter.py +130 -0
  466. contextsynapse/intelligence/reactive.py +411 -0
  467. contextsynapse/intelligence/runtime_context.py +390 -0
  468. contextsynapse/intelligence/sentiment_decay.py +426 -0
  469. contextsynapse/intelligence/session.py +277 -0
  470. contextsynapse/intelligence/signal_hierarchy.py +438 -0
  471. contextsynapse/intelligence/signals.py +185 -0
  472. contextsynapse/intelligence/source_watcher.py +132 -0
  473. contextsynapse/intelligence/table_enricher.py +256 -0
  474. contextsynapse/intelligence/tagger.py +319 -0
  475. contextsynapse/intelligence/timeseries.py +209 -0
  476. contextsynapse/intelligence/tracker.py +318 -0
  477. contextsynapse/intelligence/watchdog.py +392 -0
  478. contextsynapse/intelligence/watchdog_manager.py +263 -0
  479. contextsynapse/intelligence/webhook_receiver.py +165 -0
  480. contextsynapse/intelligence/weight_learner.py +234 -0
  481. contextsynapse/llm/__init__.py +8 -0
  482. contextsynapse/llm/client.py +348 -0
  483. contextsynapse/llm/rate_limiter.py +166 -0
  484. contextsynapse/logging_config.py +2 -0
  485. contextsynapse/marketplace/__init__.py +7 -0
  486. contextsynapse/marketplace/registry.py +173 -0
  487. contextsynapse/mcp/__init__.py +11 -0
  488. contextsynapse/mcp/__main__.py +4 -0
  489. contextsynapse/mcp/auth_middleware.py +212 -0
  490. contextsynapse/mcp/connection_pool.py +128 -0
  491. contextsynapse/mcp/server.py +986 -0
  492. contextsynapse/mcp/session_context.py +67 -0
  493. contextsynapse/memory/__init__.py +34 -0
  494. contextsynapse/memory/engine.py +475 -0
  495. contextsynapse/memory/temporal.py +327 -0
  496. contextsynapse/metadata/__init__.py +12 -0
  497. contextsynapse/metadata/metadata_db.py +272 -0
  498. contextsynapse/metadata/metadata_query_tool.py +300 -0
  499. contextsynapse/metadata/metadata_tracker.py +425 -0
  500. contextsynapse/models/__init__.py +27 -0
  501. contextsynapse/models/embedding_service.py +360 -0
  502. contextsynapse/models/model_registry.py +228 -0
  503. contextsynapse/multiworker.py +2 -0
  504. contextsynapse/pipelines/__init__.py +1 -0
  505. contextsynapse/pipelines/executor.py +851 -0
  506. contextsynapse/pipelines/filters.py +189 -0
  507. contextsynapse/pipelines/models.py +176 -0
  508. contextsynapse/pipelines/scheduler.py +268 -0
  509. contextsynapse/playground/__init__.py +1 -0
  510. contextsynapse/playground/templates.py +85 -0
  511. contextsynapse/plugins/__init__.py +43 -0
  512. contextsynapse/plugins/api.py +66 -0
  513. contextsynapse/plugins/base.py +350 -0
  514. contextsynapse/plugins/domain_interface.py +508 -0
  515. contextsynapse/plugins/domain_loader.py +241 -0
  516. contextsynapse/plugins/loader.py +148 -0
  517. contextsynapse/plugins/registry.py +265 -0
  518. contextsynapse/project/__init__.py +11 -0
  519. contextsynapse/project/code_context.py +807 -0
  520. contextsynapse/project/connectors/__init__.py +4 -0
  521. contextsynapse/project/connectors/github_connector.py +113 -0
  522. contextsynapse/project/connectors/jira_connector.py +160 -0
  523. contextsynapse/project/graph.py +1023 -0
  524. contextsynapse/project/project_context.py +545 -0
  525. contextsynapse/project/scanner_registry.py +61 -0
  526. contextsynapse/project/schema_manager.py +322 -0
  527. contextsynapse/project/schemas/knowledge.yaml +59 -0
  528. contextsynapse/project/schemas/sdlc.yaml +369 -0
  529. contextsynapse/project/sdlc_schema.py +172 -0
  530. contextsynapse/project/spec_parser.py +85 -0
  531. contextsynapse/project/task_lock.py +181 -0
  532. contextsynapse/project/task_stream.py +203 -0
  533. contextsynapse/project/team_tools.py +537 -0
  534. contextsynapse/py.typed +0 -0
  535. contextsynapse/realtime/__init__.py +6 -0
  536. contextsynapse/realtime/collaboration.py +147 -0
  537. contextsynapse/rules/__init__.py +10 -0
  538. contextsynapse/rules/engine.py +116 -0
  539. contextsynapse/rules/evaluators/__init__.py +6 -0
  540. contextsynapse/rules/evaluators/aggregate.py +205 -0
  541. contextsynapse/rules/evaluators/custom.py +170 -0
  542. contextsynapse/rules/evaluators/pre_action.py +125 -0
  543. contextsynapse/rules/evaluators/temporal.py +129 -0
  544. contextsynapse/rules/loader.py +52 -0
  545. contextsynapse/rules/models.py +124 -0
  546. contextsynapse/rules/universal.py +393 -0
  547. contextsynapse/scheduler.py +229 -0
  548. contextsynapse/schema/__init__.py +42 -0
  549. contextsynapse/schema/compiler.py +252 -0
  550. contextsynapse/schema/composer.py +158 -0
  551. contextsynapse/schema/dedup.py +73 -0
  552. contextsynapse/schema/derivation.py +172 -0
  553. contextsynapse/schema/sdl.py +326 -0
  554. contextsynapse/schema/validation_gate.py +124 -0
  555. contextsynapse/sdk/__init__.py +63 -0
  556. contextsynapse/sdk/agent.py +214 -0
  557. contextsynapse/sdk/client.py +269 -0
  558. contextsynapse/sdk/exceptions.py +23 -0
  559. contextsynapse/sdk/models.py +78 -0
  560. contextsynapse/sdk/session.py +408 -0
  561. contextsynapse/sdk/tracked.py +218 -0
  562. contextsynapse/sdk/worker.py +266 -0
  563. contextsynapse/sdk/workspace_client.py +98 -0
  564. contextsynapse/sdk/ws.py +41 -0
  565. contextsynapse/search/__init__.py +20 -0
  566. contextsynapse/search/embedding_cache.py +140 -0
  567. contextsynapse/search/enhanced_search.py +152 -0
  568. contextsynapse/search/fulltext.py +130 -0
  569. contextsynapse/search/graph_search.py +634 -0
  570. contextsynapse/search/lmdb_index.py +1218 -0
  571. contextsynapse/search/nl_to_aiql.py +199 -0
  572. contextsynapse/search/rag.py +1346 -0
  573. contextsynapse/search/rag_cache.py +167 -0
  574. contextsynapse/search/reasoning_chain.py +231 -0
  575. contextsynapse/search/redis_search.py +207 -0
  576. contextsynapse/search/retrieval_quality.py +314 -0
  577. contextsynapse/search/semantic_query.py +455 -0
  578. contextsynapse/search/text_resolver.py +159 -0
  579. contextsynapse/search/whoosh_search.py +373 -0
  580. contextsynapse/security/__init__.py +17 -0
  581. contextsynapse/security/audit.py +297 -0
  582. contextsynapse/security/audit_logger.py +97 -0
  583. contextsynapse/security/audit_trail.py +270 -0
  584. contextsynapse/security/auth_unified.py +284 -0
  585. contextsynapse/security/auto_tagger.py +230 -0
  586. contextsynapse/security/data_security.py +218 -0
  587. contextsynapse/security/encryption.py +207 -0
  588. contextsynapse/security/identity.py +447 -0
  589. contextsynapse/security/jwt_identity.py +59 -0
  590. contextsynapse/security/middleware.py +336 -0
  591. contextsynapse/security/pii.py +233 -0
  592. contextsynapse/security/rbac.py +96 -0
  593. contextsynapse/security/rls.py +205 -0
  594. contextsynapse/security/sanitize.py +233 -0
  595. contextsynapse/security/scoped_encryption.py +131 -0
  596. contextsynapse/security/tenant.py +401 -0
  597. contextsynapse/shield/__init__.py +21 -0
  598. contextsynapse/shield/anomaly.py +56 -0
  599. contextsynapse/shield/permissions.py +99 -0
  600. contextsynapse/shield/profile.py +103 -0
  601. contextsynapse/shield/shield.py +108 -0
  602. contextsynapse/shield/trust_engine.py +69 -0
  603. contextsynapse/skills/__init__.py +14 -0
  604. contextsynapse/skills/engine.py +233 -0
  605. contextsynapse/skills/loader.py +59 -0
  606. contextsynapse/skills/models.py +139 -0
  607. contextsynapse/storage/__init__.py +7 -0
  608. contextsynapse/storage/cache.py +208 -0
  609. contextsynapse/storage/columnar_store_v2.py +178 -0
  610. contextsynapse/storage/csr_graph_storage.py +587 -0
  611. contextsynapse/storage/csr_store.py +388 -0
  612. contextsynapse/storage/document_store.py +491 -0
  613. contextsynapse/storage/hnsw_index.py +294 -0
  614. contextsynapse/storage/hybrid_store_v2.py +278 -0
  615. contextsynapse/storage/lmdb_graph_storage.py +366 -0
  616. contextsynapse/storage/migration.py +279 -0
  617. contextsynapse/storage/namespace_store.py +346 -0
  618. contextsynapse/storage/pure_graph_storage.py +185 -0
  619. contextsynapse/storage/redis_graph_adapter.py +186 -0
  620. contextsynapse/storage/redis_graph_storage.py +375 -0
  621. contextsynapse/storage/router/__init__.py +29 -0
  622. contextsynapse/storage/router/duckdb_store.py +398 -0
  623. contextsynapse/storage/router/factory.py +83 -0
  624. contextsynapse/storage/router/interface.py +125 -0
  625. contextsynapse/storage/router/postgres_store.py +339 -0
  626. contextsynapse/storage/router/resolver.py +192 -0
  627. contextsynapse/storage/router/router.py +300 -0
  628. contextsynapse/storage/single_file_storage.py +391 -0
  629. contextsynapse/storage/storage_manager.py +214 -0
  630. contextsynapse/storage/storage_query_optimizer.py +314 -0
  631. contextsynapse/storage/wal.py +359 -0
  632. contextsynapse/temporal/__init__.py +0 -0
  633. contextsynapse/temporal/storage.py +106 -0
  634. contextsynapse/tests/__init__.py +11 -0
  635. contextsynapse/tests/regression/__init__.py +1 -0
  636. contextsynapse/tests/regression/add_metadata.py +395 -0
  637. contextsynapse/tests/regression/add_skip_flags.py +85 -0
  638. contextsynapse/tests/regression/cases/test_basic_create_node.yaml +20 -0
  639. contextsynapse/tests/regression/cases/test_basic_select.yaml +21 -0
  640. contextsynapse/tests/regression/cases/test_blockchain_audit_trail.yaml +37 -0
  641. contextsynapse/tests/regression/cases/test_blockchain_audit_trail_filtered.yaml +39 -0
  642. contextsynapse/tests/regression/cases/test_blockchain_blocks_range.yaml +39 -0
  643. contextsynapse/tests/regression/cases/test_blockchain_get_block.yaml +35 -0
  644. contextsynapse/tests/regression/cases/test_blockchain_latest_block.yaml +35 -0
  645. contextsynapse/tests/regression/cases/test_blockchain_length.yaml +37 -0
  646. contextsynapse/tests/regression/cases/test_blockchain_merkle_root.yaml +37 -0
  647. contextsynapse/tests/regression/cases/test_blockchain_verify.yaml +35 -0
  648. contextsynapse/tests/regression/cases/test_blockchain_verify_block.yaml +35 -0
  649. contextsynapse/tests/regression/cases/test_create_edge.yaml +28 -0
  650. contextsynapse/tests/regression/cases/test_delete_edge_basic.yaml +29 -0
  651. contextsynapse/tests/regression/cases/test_delete_node_basic.yaml +29 -0
  652. contextsynapse/tests/regression/cases/test_evaluation_mrr.yaml +40 -0
  653. contextsynapse/tests/regression/cases/test_evaluation_ndcg.yaml +40 -0
  654. contextsynapse/tests/regression/cases/test_evaluation_precision.yaml +40 -0
  655. contextsynapse/tests/regression/cases/test_evaluation_recall.yaml +40 -0
  656. contextsynapse/tests/regression/cases/test_group_by_basic.yaml +56 -0
  657. contextsynapse/tests/regression/cases/test_match_node_basic.yaml +29 -0
  658. contextsynapse/tests/regression/cases/test_match_node_with_order_limit.yaml +31 -0
  659. contextsynapse/tests/regression/cases/test_namespace_switch.yaml +18 -0
  660. contextsynapse/tests/regression/cases/test_pipeline_cascaded.yaml +61 -0
  661. contextsynapse/tests/regression/cases/test_pipeline_fixed_size_chunking.yaml +48 -0
  662. contextsynapse/tests/regression/cases/test_pipeline_gpt4_chunking.yaml +54 -0
  663. contextsynapse/tests/regression/cases/test_pipeline_hybrid_indexing.yaml +57 -0
  664. contextsynapse/tests/regression/cases/test_pipeline_large_embedding.yaml +52 -0
  665. contextsynapse/tests/regression/cases/test_pipeline_paragraph_chunking.yaml +49 -0
  666. contextsynapse/tests/regression/cases/test_pipeline_recursive_chunking.yaml +47 -0
  667. contextsynapse/tests/regression/cases/test_pipeline_run_pipeline.yaml +56 -0
  668. contextsynapse/tests/regression/cases/test_pipeline_section_based_chunking.yaml +53 -0
  669. contextsynapse/tests/regression/cases/test_pipeline_semantic_chunking.yaml +51 -0
  670. contextsynapse/tests/regression/cases/test_pipeline_with_entity_extraction.yaml +57 -0
  671. contextsynapse/tests/regression/cases/test_pipeline_with_relationships.yaml +62 -0
  672. contextsynapse/tests/regression/cases/test_rag_evaluation.yaml +38 -0
  673. contextsynapse/tests/regression/cases/test_rag_graph_bfs_with_eval.yaml +48 -0
  674. contextsynapse/tests/regression/cases/test_rag_graph_centrality.yaml +40 -0
  675. contextsynapse/tests/regression/cases/test_rag_graph_centrality_eval.yaml +35 -0
  676. contextsynapse/tests/regression/cases/test_rag_graph_community.yaml +40 -0
  677. contextsynapse/tests/regression/cases/test_rag_graph_community_eval.yaml +35 -0
  678. contextsynapse/tests/regression/cases/test_rag_graph_dfs_with_eval.yaml +35 -0
  679. contextsynapse/tests/regression/cases/test_rag_graph_multi_hop_eval.yaml +35 -0
  680. contextsynapse/tests/regression/cases/test_rag_graph_path.yaml +40 -0
  681. contextsynapse/tests/regression/cases/test_rag_graph_search_basic.yaml +38 -0
  682. contextsynapse/tests/regression/cases/test_rag_graph_search_bfs.yaml +52 -0
  683. contextsynapse/tests/regression/cases/test_rag_graph_search_dfs.yaml +41 -0
  684. contextsynapse/tests/regression/cases/test_rag_graph_search_multi_hop.yaml +43 -0
  685. contextsynapse/tests/regression/cases/test_rag_graph_search_shortest_path.yaml +41 -0
  686. contextsynapse/tests/regression/cases/test_rag_graph_search_weighted.yaml +43 -0
  687. contextsynapse/tests/regression/cases/test_rag_graph_shortest_path_eval.yaml +35 -0
  688. contextsynapse/tests/regression/cases/test_rag_graph_traversal.yaml +30 -0
  689. contextsynapse/tests/regression/cases/test_rag_graph_weighted_eval.yaml +35 -0
  690. contextsynapse/tests/regression/cases/test_rag_hybrid_search.yaml +33 -0
  691. contextsynapse/tests/regression/cases/test_rag_hybrid_with_prompt_embedding.yaml +44 -0
  692. contextsynapse/tests/regression/cases/test_rag_keyword_search.yaml +32 -0
  693. contextsynapse/tests/regression/cases/test_rag_multi_hop_graph.yaml +32 -0
  694. contextsynapse/tests/regression/cases/test_rag_path_based.yaml +34 -0
  695. contextsynapse/tests/regression/cases/test_rag_profile_based.yaml +32 -0
  696. contextsynapse/tests/regression/cases/test_rag_vector_search.yaml +32 -0
  697. contextsynapse/tests/regression/cases/test_rag_weighted_graph.yaml +34 -0
  698. contextsynapse/tests/regression/cases/test_rag_weighted_hybrid.yaml +31 -0
  699. contextsynapse/tests/regression/cases/test_semantic_boundary_chunking.yaml +57 -0
  700. contextsynapse/tests/regression/cases/test_semantic_boundary_detection.yaml +33 -0
  701. contextsynapse/tests/regression/cases/test_semantic_hash_function.yaml +30 -0
  702. contextsynapse/tests/regression/cases/test_semantic_hash_with_model.yaml +31 -0
  703. contextsynapse/tests/regression/cases/test_tcs_ingestion_fixed_size.yaml +44 -0
  704. contextsynapse/tests/regression/cases/test_tcs_ingestion_recursive.yaml +46 -0
  705. contextsynapse/tests/regression/cases/test_tcs_ingestion_section.yaml +46 -0
  706. contextsynapse/tests/regression/cases/test_tcs_ingestion_semantic.yaml +44 -0
  707. contextsynapse/tests/regression/cases/test_time_travel_as_of.yaml +35 -0
  708. contextsynapse/tests/regression/cases/test_time_travel_at_commit.yaml +33 -0
  709. contextsynapse/tests/regression/cases/test_time_travel_at_timestamp.yaml +33 -0
  710. contextsynapse/tests/regression/cases/test_time_travel_for_system_time_all.yaml +37 -0
  711. contextsynapse/tests/regression/cases/test_time_travel_versions_between.yaml +39 -0
  712. contextsynapse/tests/regression/cases/test_traverse_basic.yaml +31 -0
  713. contextsynapse/tests/regression/cases/test_traverse_max_depth.yaml +34 -0
  714. contextsynapse/tests/regression/cases/test_update_edge_basic.yaml +29 -0
  715. contextsynapse/tests/regression/evaluation_metrics.py +227 -0
  716. contextsynapse/tests/regression/regression_runner.py +1081 -0
  717. contextsynapse/tests/regression/setup_regression_data.py +212 -0
  718. contextsynapse/tests/regression/test_basic_only.py +84 -0
  719. contextsynapse/tests/regression/test_namespace_creation.py +29 -0
  720. contextsynapse/tests/regression/test_single_fix.py +61 -0
  721. contextsynapse/tests/regression/test_single_query.py +20 -0
  722. contextsynapse/tests/regression/validate_test_syntax.py +179 -0
  723. contextsynapse/tests/test_advanced_features.py +347 -0
  724. contextsynapse/tests/test_aiql_summary.py +283 -0
  725. contextsynapse/tests/test_all_aiql_queries.py +948 -0
  726. contextsynapse/tests/test_all_create_queries.py +213 -0
  727. contextsynapse/tests/test_api_vs_native.py +280 -0
  728. contextsynapse/tests/test_chunking_dedup.py +199 -0
  729. contextsynapse/tests/test_connectors.py +171 -0
  730. contextsynapse/tests/test_edges_and_match.py +202 -0
  731. contextsynapse/tests/test_extraction_pipeline_integration.py +581 -0
  732. contextsynapse/tests/test_name_property.py +224 -0
  733. contextsynapse/tests/test_node_edge_metadata.py +250 -0
  734. contextsynapse/tests/test_playground_conn.py +114 -0
  735. contextsynapse/tests/test_query_cache.py +213 -0
  736. contextsynapse/tests/test_source_policy_auth.py +348 -0
  737. contextsynapse/tests/test_temporal_and_domain.py +224 -0
  738. contextsynapse/tests/test_time_travel_e2e.py +571 -0
  739. contextsynapse/tests/test_traversal_and_aggregation.py +275 -0
  740. contextsynapse/tools/__init__.py +36 -0
  741. contextsynapse/tools/a2a_tools.py +106 -0
  742. contextsynapse/tools/cognition_tools.py +118 -0
  743. contextsynapse/tools/context.py +905 -0
  744. contextsynapse/tools/formatting.py +92 -0
  745. contextsynapse/tools/gateway_tools.py +186 -0
  746. contextsynapse/tools/graph.py +1700 -0
  747. contextsynapse/tools/intelligence.py +235 -0
  748. contextsynapse/tools/memory.py +118 -0
  749. contextsynapse/tools/registry.py +373 -0
  750. contextsynapse/tools/shield_tools.py +159 -0
  751. contextsynapse/tools/tasks.py +341 -0
  752. contextsynapse/tools/workspace_tools.py +124 -0
  753. contextsynapse/utils/__init__.py +15 -0
  754. contextsynapse/utils/config_loader.py +198 -0
  755. contextsynapse/utils/env_loader.py +156 -0
  756. contextsynapse/utils/file_utils.py +288 -0
  757. contextsynapse/utils/logging_optimizer.py +119 -0
  758. contextsynapse/vector/__init__.py +30 -0
  759. contextsynapse/vector/chroma_vector_store.py +152 -0
  760. contextsynapse/vector/custom_vector_store.py +537 -0
  761. contextsynapse/vector/faiss_vector_store.py +296 -0
  762. contextsynapse/vector/qdrant_vector_store.py +163 -0
  763. contextsynapse/vector/vector_db.py +953 -0
  764. contextsynapse/vector/vector_db_manager.py +197 -0
  765. contextsynapse/workspace/__init__.py +27 -0
  766. contextsynapse/workspace/base.py +94 -0
  767. contextsynapse/workspace/git.py +228 -0
  768. contextsynapse/workspace/github.py +78 -0
  769. contextsynapse/workspace/local.py +73 -0
  770. contextsynapse/workspace/tools.py +222 -0
  771. contextsynapse-1.0.0.dist-info/METADATA +847 -0
  772. contextsynapse-1.0.0.dist-info/RECORD +776 -0
  773. contextsynapse-1.0.0.dist-info/WHEEL +5 -0
  774. contextsynapse-1.0.0.dist-info/entry_points.txt +4 -0
  775. contextsynapse-1.0.0.dist-info/licenses/LICENSE +200 -0
  776. contextsynapse-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,488 @@
1
+ """
2
+ Conversation Store
3
+ ==================
4
+ Key-value backed conversation management for context sessions.
5
+
6
+ Each conversation is an ordered sequence of messages tied to a session,
7
+ with an embedded KV store for fast state/metadata lookup.
8
+
9
+ Usage::
10
+
11
+ from contextsynapse.context.conversation import ConversationStore
12
+
13
+ store = ConversationStore()
14
+ conv = store.create(session_id="abc123", title="Research Chat")
15
+ store.append_message(conv.conversation_id, role="user", content="Hello")
16
+ store.append_message(conv.conversation_id, role="assistant", content="Hi there!")
17
+
18
+ history = store.get_history(conv.conversation_id)
19
+ store.set_kv(conv.conversation_id, "intent", "research")
20
+ intent = store.get_kv(conv.conversation_id, "intent")
21
+
22
+ # Export to ContextHub for LLM consumption
23
+ hub = store.to_hub(conv.conversation_id, system_prompt="You are helpful.")
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import json
29
+ import logging
30
+ import os
31
+ import sqlite3
32
+ import uuid
33
+ from dataclasses import dataclass, field
34
+ from datetime import datetime, timezone
35
+ from typing import Any, Dict, List, Optional
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ def _utcnow() -> str:
41
+ return datetime.now(timezone.utc).isoformat()
42
+
43
+
44
+ @dataclass
45
+ class ConversationMessage:
46
+ """A single message in a conversation."""
47
+ message_id: str
48
+ conversation_id: str
49
+ turn_index: int
50
+ role: str # user | assistant | system | tool
51
+ content: str
52
+ agent_id: Optional[str] = None
53
+ created_at: str = field(default_factory=_utcnow)
54
+ metadata: Dict[str, Any] = field(default_factory=dict)
55
+
56
+ def to_dict(self) -> Dict[str, Any]:
57
+ return {
58
+ "message_id": self.message_id,
59
+ "conversation_id": self.conversation_id,
60
+ "turn_index": self.turn_index,
61
+ "role": self.role,
62
+ "content": self.content,
63
+ "agent_id": self.agent_id,
64
+ "created_at": self.created_at,
65
+ "metadata": self.metadata,
66
+ }
67
+
68
+
69
+ @dataclass
70
+ class Conversation:
71
+ """A conversation with metadata and optional TTL."""
72
+ conversation_id: str
73
+ session_id: str
74
+ title: Optional[str] = None
75
+ created_at: str = field(default_factory=_utcnow)
76
+ updated_at: str = field(default_factory=_utcnow)
77
+ metadata: Dict[str, Any] = field(default_factory=dict)
78
+ status: str = "active" # active | archived | deleted
79
+ ttl_seconds: Optional[int] = None
80
+ messages: List[ConversationMessage] = field(default_factory=list)
81
+
82
+ def to_dict(self) -> Dict[str, Any]:
83
+ return {
84
+ "conversation_id": self.conversation_id,
85
+ "session_id": self.session_id,
86
+ "title": self.title,
87
+ "created_at": self.created_at,
88
+ "updated_at": self.updated_at,
89
+ "metadata": self.metadata,
90
+ "status": self.status,
91
+ "ttl_seconds": self.ttl_seconds,
92
+ "message_count": len(self.messages),
93
+ }
94
+
95
+
96
+ class ConversationStore:
97
+ """
98
+ SQLite-backed conversation store with KV support.
99
+
100
+ Tables:
101
+ - ``conversations`` — conversation metadata
102
+ - ``conversation_messages`` — ordered messages
103
+ - ``conversation_kv`` — arbitrary key-value pairs per conversation
104
+ """
105
+
106
+ def __init__(self, db_path: str = "contextcore_data/context.db"):
107
+ self._db_path = db_path
108
+ os.makedirs(os.path.dirname(db_path) or ".", exist_ok=True)
109
+ self._conn = sqlite3.connect(db_path, check_same_thread=False)
110
+ self._conn.row_factory = sqlite3.Row
111
+ self._conn.execute("PRAGMA journal_mode=WAL")
112
+ self._create_tables()
113
+
114
+ def _create_tables(self):
115
+ with self._conn:
116
+ self._conn.executescript("""
117
+ CREATE TABLE IF NOT EXISTS conversations (
118
+ conversation_id TEXT PRIMARY KEY,
119
+ session_id TEXT NOT NULL,
120
+ title TEXT,
121
+ created_at TEXT NOT NULL,
122
+ updated_at TEXT NOT NULL,
123
+ metadata TEXT DEFAULT '{}',
124
+ status TEXT DEFAULT 'active',
125
+ ttl_seconds INTEGER DEFAULT NULL
126
+ );
127
+
128
+ CREATE TABLE IF NOT EXISTS conversation_messages (
129
+ message_id TEXT PRIMARY KEY,
130
+ conversation_id TEXT NOT NULL,
131
+ turn_index INTEGER NOT NULL,
132
+ role TEXT NOT NULL,
133
+ content TEXT NOT NULL,
134
+ agent_id TEXT,
135
+ created_at TEXT NOT NULL,
136
+ metadata TEXT DEFAULT '{}',
137
+ UNIQUE(conversation_id, turn_index)
138
+ );
139
+
140
+ CREATE TABLE IF NOT EXISTS conversation_kv (
141
+ conversation_id TEXT NOT NULL,
142
+ key TEXT NOT NULL,
143
+ value TEXT NOT NULL,
144
+ updated_at TEXT NOT NULL,
145
+ PRIMARY KEY (conversation_id, key)
146
+ );
147
+
148
+ CREATE INDEX IF NOT EXISTS idx_conv_session
149
+ ON conversations(session_id);
150
+ CREATE INDEX IF NOT EXISTS idx_conv_status
151
+ ON conversations(status);
152
+ CREATE INDEX IF NOT EXISTS idx_convmsg_conv
153
+ ON conversation_messages(conversation_id);
154
+ CREATE INDEX IF NOT EXISTS idx_convkv_conv
155
+ ON conversation_kv(conversation_id);
156
+ """)
157
+
158
+ # ------------------------------------------------------------------
159
+ # Conversation CRUD
160
+ # ------------------------------------------------------------------
161
+
162
+ def create(
163
+ self,
164
+ session_id: str,
165
+ title: Optional[str] = None,
166
+ metadata: Optional[Dict[str, Any]] = None,
167
+ ttl_seconds: Optional[int] = None,
168
+ ) -> Conversation:
169
+ """Create a new conversation."""
170
+ conv_id = uuid.uuid4().hex[:12]
171
+ now = _utcnow()
172
+ meta_json = json.dumps(metadata or {})
173
+
174
+ with self._conn:
175
+ self._conn.execute(
176
+ """INSERT INTO conversations
177
+ (conversation_id, session_id, title, created_at, updated_at,
178
+ metadata, status, ttl_seconds)
179
+ VALUES (?, ?, ?, ?, ?, ?, 'active', ?)""",
180
+ (conv_id, session_id, title, now, now, meta_json, ttl_seconds),
181
+ )
182
+
183
+ return Conversation(
184
+ conversation_id=conv_id,
185
+ session_id=session_id,
186
+ title=title,
187
+ created_at=now,
188
+ updated_at=now,
189
+ metadata=metadata or {},
190
+ status="active",
191
+ ttl_seconds=ttl_seconds,
192
+ )
193
+
194
+ def get(self, conversation_id: str, include_messages: bool = True) -> Optional[Conversation]:
195
+ """Get a conversation by ID. Returns None if not found or expired."""
196
+ row = self._conn.execute(
197
+ "SELECT * FROM conversations WHERE conversation_id = ?",
198
+ (conversation_id,),
199
+ ).fetchone()
200
+
201
+ if not row:
202
+ return None
203
+
204
+ conv = self._row_to_conversation(row)
205
+
206
+ # Lazy TTL check
207
+ if conv.ttl_seconds is not None and conv.status == "active":
208
+ created = datetime.fromisoformat(conv.created_at)
209
+ age = (datetime.now(timezone.utc) - created).total_seconds()
210
+ if age > conv.ttl_seconds:
211
+ self.archive(conversation_id)
212
+ conv.status = "archived"
213
+
214
+ if conv.status == "deleted":
215
+ return None
216
+
217
+ if include_messages:
218
+ conv.messages = self.get_history(conversation_id)
219
+
220
+ return conv
221
+
222
+ def list_conversations(
223
+ self,
224
+ session_id: str,
225
+ status: str = "active",
226
+ ) -> List[Conversation]:
227
+ """List conversations for a session."""
228
+ rows = self._conn.execute(
229
+ "SELECT * FROM conversations WHERE session_id = ? AND status = ? ORDER BY updated_at DESC",
230
+ (session_id, status),
231
+ ).fetchall()
232
+ return [self._row_to_conversation(r) for r in rows]
233
+
234
+ def archive(self, conversation_id: str) -> bool:
235
+ """Archive a conversation."""
236
+ with self._conn:
237
+ cur = self._conn.execute(
238
+ "UPDATE conversations SET status = 'archived', updated_at = ? WHERE conversation_id = ?",
239
+ (_utcnow(), conversation_id),
240
+ )
241
+ return cur.rowcount > 0
242
+
243
+ def delete(self, conversation_id: str) -> bool:
244
+ """Soft-delete a conversation."""
245
+ with self._conn:
246
+ cur = self._conn.execute(
247
+ "UPDATE conversations SET status = 'deleted', updated_at = ? WHERE conversation_id = ?",
248
+ (_utcnow(), conversation_id),
249
+ )
250
+ return cur.rowcount > 0
251
+
252
+ # ------------------------------------------------------------------
253
+ # Message operations
254
+ # ------------------------------------------------------------------
255
+
256
+ def append_message(
257
+ self,
258
+ conversation_id: str,
259
+ role: str,
260
+ content: str,
261
+ agent_id: Optional[str] = None,
262
+ metadata: Optional[Dict[str, Any]] = None,
263
+ ) -> ConversationMessage:
264
+ """Append a message to the conversation."""
265
+ msg_id = uuid.uuid4().hex[:12]
266
+ now = _utcnow()
267
+ meta_json = json.dumps(metadata or {})
268
+
269
+ with self._conn:
270
+ # Get next turn_index
271
+ row = self._conn.execute(
272
+ "SELECT COALESCE(MAX(turn_index), -1) + 1 FROM conversation_messages WHERE conversation_id = ?",
273
+ (conversation_id,),
274
+ ).fetchone()
275
+ turn_index = row[0]
276
+
277
+ self._conn.execute(
278
+ """INSERT INTO conversation_messages
279
+ (message_id, conversation_id, turn_index, role, content,
280
+ agent_id, created_at, metadata)
281
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)""",
282
+ (msg_id, conversation_id, turn_index, role, content, agent_id, now, meta_json),
283
+ )
284
+
285
+ # Touch conversation updated_at
286
+ self._conn.execute(
287
+ "UPDATE conversations SET updated_at = ? WHERE conversation_id = ?",
288
+ (now, conversation_id),
289
+ )
290
+
291
+ return ConversationMessage(
292
+ message_id=msg_id,
293
+ conversation_id=conversation_id,
294
+ turn_index=turn_index,
295
+ role=role,
296
+ content=content,
297
+ agent_id=agent_id,
298
+ created_at=now,
299
+ metadata=metadata or {},
300
+ )
301
+
302
+ def get_history(
303
+ self,
304
+ conversation_id: str,
305
+ limit: Optional[int] = None,
306
+ offset: int = 0,
307
+ ) -> List[ConversationMessage]:
308
+ """Get message history for a conversation."""
309
+ sql = "SELECT * FROM conversation_messages WHERE conversation_id = ? ORDER BY turn_index ASC"
310
+ params: list = [conversation_id]
311
+
312
+ if limit is not None:
313
+ sql += " LIMIT ? OFFSET ?"
314
+ params.extend([limit, offset])
315
+ elif offset > 0:
316
+ sql += " LIMIT -1 OFFSET ?"
317
+ params.append(offset)
318
+
319
+ rows = self._conn.execute(sql, params).fetchall()
320
+ return [self._row_to_message(r) for r in rows]
321
+
322
+ def get_last_n(self, conversation_id: str, n: int) -> List[ConversationMessage]:
323
+ """Get the last N messages of a conversation."""
324
+ rows = self._conn.execute(
325
+ """SELECT * FROM (
326
+ SELECT * FROM conversation_messages
327
+ WHERE conversation_id = ?
328
+ ORDER BY turn_index DESC
329
+ LIMIT ?
330
+ ) ORDER BY turn_index ASC""",
331
+ (conversation_id, n),
332
+ ).fetchall()
333
+ return [self._row_to_message(r) for r in rows]
334
+
335
+ def get_message(self, message_id: str) -> Optional[ConversationMessage]:
336
+ """Get a single message by ID."""
337
+ row = self._conn.execute(
338
+ "SELECT * FROM conversation_messages WHERE message_id = ?",
339
+ (message_id,),
340
+ ).fetchone()
341
+ return self._row_to_message(row) if row else None
342
+
343
+ def message_count(self, conversation_id: str) -> int:
344
+ """Count messages in a conversation."""
345
+ row = self._conn.execute(
346
+ "SELECT COUNT(*) FROM conversation_messages WHERE conversation_id = ?",
347
+ (conversation_id,),
348
+ ).fetchone()
349
+ return row[0]
350
+
351
+ # ------------------------------------------------------------------
352
+ # KV store operations
353
+ # ------------------------------------------------------------------
354
+
355
+ def set_kv(self, conversation_id: str, key: str, value: Any) -> None:
356
+ """Set a key-value pair for a conversation."""
357
+ now = _utcnow()
358
+ val_json = json.dumps(value)
359
+ with self._conn:
360
+ self._conn.execute(
361
+ """INSERT OR REPLACE INTO conversation_kv
362
+ (conversation_id, key, value, updated_at)
363
+ VALUES (?, ?, ?, ?)""",
364
+ (conversation_id, key, val_json, now),
365
+ )
366
+
367
+ def get_kv(self, conversation_id: str, key: str) -> Optional[Any]:
368
+ """Get a value by key. Returns None if not found."""
369
+ row = self._conn.execute(
370
+ "SELECT value FROM conversation_kv WHERE conversation_id = ? AND key = ?",
371
+ (conversation_id, key),
372
+ ).fetchone()
373
+ if row is None:
374
+ return None
375
+ return json.loads(row[0])
376
+
377
+ def get_all_kv(self, conversation_id: str) -> Dict[str, Any]:
378
+ """Get all KV pairs for a conversation."""
379
+ rows = self._conn.execute(
380
+ "SELECT key, value FROM conversation_kv WHERE conversation_id = ?",
381
+ (conversation_id,),
382
+ ).fetchall()
383
+ return {r[0]: json.loads(r[1]) for r in rows}
384
+
385
+ def delete_kv(self, conversation_id: str, key: str) -> bool:
386
+ """Delete a KV pair."""
387
+ with self._conn:
388
+ cur = self._conn.execute(
389
+ "DELETE FROM conversation_kv WHERE conversation_id = ? AND key = ?",
390
+ (conversation_id, key),
391
+ )
392
+ return cur.rowcount > 0
393
+
394
+ # ------------------------------------------------------------------
395
+ # TTL / expiry
396
+ # ------------------------------------------------------------------
397
+
398
+ def cleanup_expired(self) -> int:
399
+ """Archive all conversations past their TTL. Returns count archived."""
400
+ now = datetime.now(timezone.utc)
401
+ rows = self._conn.execute(
402
+ "SELECT conversation_id, created_at, ttl_seconds FROM conversations WHERE status = 'active' AND ttl_seconds IS NOT NULL",
403
+ ).fetchall()
404
+
405
+ archived = 0
406
+ for row in rows:
407
+ created = datetime.fromisoformat(row[1])
408
+ age = (now - created).total_seconds()
409
+ if age > row[2]:
410
+ self.archive(row[0])
411
+ archived += 1
412
+
413
+ if archived:
414
+ logger.info(f"Cleaned up {archived} expired conversations")
415
+ return archived
416
+
417
+ # ------------------------------------------------------------------
418
+ # ContextHub integration
419
+ # ------------------------------------------------------------------
420
+
421
+ def to_hub(
422
+ self,
423
+ conversation_id: str,
424
+ system_prompt: Optional[str] = None,
425
+ last_n: Optional[int] = None,
426
+ ):
427
+ """
428
+ Convert a conversation into a ContextHub for LLM consumption.
429
+
430
+ Maps message roles: system → SYSTEM, user → USER,
431
+ assistant → ASSISTANT, tool → USER.
432
+ """
433
+ from .hub import ContextHub, ContextRole
434
+
435
+ hub = ContextHub(system_prompt=system_prompt)
436
+
437
+ if last_n:
438
+ messages = self.get_last_n(conversation_id, last_n)
439
+ else:
440
+ messages = self.get_history(conversation_id)
441
+
442
+ role_map = {
443
+ "system": ContextRole.SYSTEM,
444
+ "user": ContextRole.USER,
445
+ "assistant": ContextRole.ASSISTANT,
446
+ "tool": ContextRole.TOOL,
447
+ }
448
+
449
+ for msg in messages:
450
+ # Skip system prompt from conversation if we already added one
451
+ if msg.role == "system" and system_prompt:
452
+ continue
453
+ hub.add_text(
454
+ msg.content,
455
+ role=role_map.get(msg.role, ContextRole.USER),
456
+ label=f"Turn {msg.turn_index}",
457
+ metadata={"message_id": msg.message_id, "agent_id": msg.agent_id},
458
+ )
459
+
460
+ return hub
461
+
462
+ # ------------------------------------------------------------------
463
+ # Helpers
464
+ # ------------------------------------------------------------------
465
+
466
+ def _row_to_conversation(self, row) -> Conversation:
467
+ return Conversation(
468
+ conversation_id=row["conversation_id"],
469
+ session_id=row["session_id"],
470
+ title=row["title"],
471
+ created_at=row["created_at"],
472
+ updated_at=row["updated_at"],
473
+ metadata=json.loads(row["metadata"] or "{}"),
474
+ status=row["status"],
475
+ ttl_seconds=row["ttl_seconds"],
476
+ )
477
+
478
+ def _row_to_message(self, row) -> ConversationMessage:
479
+ return ConversationMessage(
480
+ message_id=row["message_id"],
481
+ conversation_id=row["conversation_id"],
482
+ turn_index=row["turn_index"],
483
+ role=row["role"],
484
+ content=row["content"],
485
+ agent_id=row["agent_id"],
486
+ created_at=row["created_at"],
487
+ metadata=json.loads(row["metadata"] or "{}"),
488
+ )
@@ -0,0 +1,207 @@
1
+ """
2
+ Context Deduplication
3
+ =====================
4
+ Prevents context pollution by detecting duplicate or near-duplicate content
5
+ before it enters a session.
6
+
7
+ Two layers of protection:
8
+
9
+ 1. **Content hash** (exact) — SHA-256 of normalised text.
10
+ Catches exact duplicates and trivial reformattings (whitespace, case).
11
+
12
+ 2. **Semantic similarity** (fuzzy) — cosine similarity between embeddings.
13
+ Catches paraphrases, rewordings, and near-duplicates.
14
+
15
+ Usage::
16
+
17
+ dedup = ContextDedup(vector_store=my_vector_store)
18
+ result = dedup.check(session_id, "Alice is the CEO of Acme Corp")
19
+ if result.is_duplicate:
20
+ print(f"Duplicate of {result.matched_id} (score={result.score})")
21
+ else:
22
+ # safe to ingest
23
+ dedup.register(session_id, node_id, text)
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import hashlib
29
+ import json
30
+ import logging
31
+ import re
32
+ import sqlite3
33
+ from dataclasses import dataclass
34
+ from datetime import datetime, timezone
35
+ from pathlib import Path
36
+ from typing import Any, Dict, List, Optional
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+ # Semantic similarity threshold — items above this score are considered duplicates
41
+ DEFAULT_SEMANTIC_THRESHOLD = 0.92
42
+
43
+
44
+ @dataclass
45
+ class DedupResult:
46
+ """Result of a deduplication check."""
47
+ is_duplicate: bool
48
+ match_type: Optional[str] = None # "exact" | "semantic" | None
49
+ matched_id: Optional[str] = None # node_id of the existing item
50
+ score: float = 0.0 # similarity score (1.0 = exact)
51
+ matched_hash: Optional[str] = None
52
+
53
+
54
+ class ContextDedup:
55
+ """
56
+ Dual-layer deduplication for context sessions.
57
+
58
+ Maintains a per-session hash index (SQLite) for exact matches and uses
59
+ the SessionVectorStore for semantic similarity detection.
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ vector_store=None,
65
+ db_path: str = "contextcore_data/context.db",
66
+ semantic_threshold: float = DEFAULT_SEMANTIC_THRESHOLD,
67
+ ):
68
+ self._vector_store = vector_store
69
+ self._threshold = semantic_threshold
70
+
71
+ # Hash index — stored in the shared context.db
72
+ self._db_path = Path(db_path)
73
+ self._db_path.parent.mkdir(parents=True, exist_ok=True)
74
+ self._conn = sqlite3.connect(str(self._db_path), check_same_thread=False)
75
+ self._conn.row_factory = sqlite3.Row
76
+ self._conn.executescript("""
77
+ CREATE TABLE IF NOT EXISTS content_hashes (
78
+ session_id TEXT NOT NULL,
79
+ node_id TEXT NOT NULL,
80
+ content_hash TEXT NOT NULL,
81
+ normalised_hash TEXT NOT NULL,
82
+ char_count INTEGER,
83
+ created_at TEXT NOT NULL,
84
+ PRIMARY KEY (session_id, content_hash)
85
+ );
86
+ CREATE INDEX IF NOT EXISTS idx_hashes_session ON content_hashes(session_id);
87
+ CREATE INDEX IF NOT EXISTS idx_hashes_normalised ON content_hashes(session_id, normalised_hash);
88
+ """)
89
+
90
+ # ------------------------------------------------------------------
91
+ # Public API
92
+ # ------------------------------------------------------------------
93
+
94
+ def check(self, session_id: str, text: str) -> DedupResult:
95
+ """
96
+ Check whether ``text`` is a duplicate of something already in the session.
97
+
98
+ Returns a DedupResult. If ``is_duplicate`` is True, the caller should
99
+ skip ingestion.
100
+ """
101
+ # Layer 1: exact content hash
102
+ content_hash = self._hash_text(text)
103
+ normalised_hash = self._hash_normalised(text)
104
+
105
+ row = self._conn.execute(
106
+ "SELECT node_id FROM content_hashes WHERE session_id = ? AND content_hash = ?",
107
+ (session_id, content_hash),
108
+ ).fetchone()
109
+ if row:
110
+ return DedupResult(
111
+ is_duplicate=True,
112
+ match_type="exact",
113
+ matched_id=row["node_id"],
114
+ score=1.0,
115
+ matched_hash=content_hash,
116
+ )
117
+
118
+ # Also check normalised hash (catches whitespace/case diffs)
119
+ row = self._conn.execute(
120
+ "SELECT node_id FROM content_hashes WHERE session_id = ? AND normalised_hash = ?",
121
+ (session_id, normalised_hash),
122
+ ).fetchone()
123
+ if row:
124
+ return DedupResult(
125
+ is_duplicate=True,
126
+ match_type="exact",
127
+ matched_id=row["node_id"],
128
+ score=0.99,
129
+ matched_hash=normalised_hash,
130
+ )
131
+
132
+ # Layer 2: semantic similarity via vector store
133
+ if self._vector_store and self._vector_store.available:
134
+ results = self._vector_store.search(
135
+ session_id=session_id,
136
+ query=text,
137
+ k=1, # just need the top match
138
+ )
139
+ if results:
140
+ top = results[0]
141
+ score = top.get("score", 0)
142
+ if score >= self._threshold:
143
+ return DedupResult(
144
+ is_duplicate=True,
145
+ match_type="semantic",
146
+ matched_id=top.get("node_id"),
147
+ score=score,
148
+ )
149
+
150
+ return DedupResult(is_duplicate=False)
151
+
152
+ def register(self, session_id: str, node_id: str, text: str) -> str:
153
+ """
154
+ Register a piece of content as ingested.
155
+
156
+ Call this AFTER successfully ingesting (and optionally embedding) the
157
+ content so future checks will catch duplicates.
158
+
159
+ Returns the content hash.
160
+ """
161
+ content_hash = self._hash_text(text)
162
+ normalised_hash = self._hash_normalised(text)
163
+ now = datetime.now(timezone.utc).isoformat()
164
+
165
+ self._conn.execute(
166
+ "INSERT OR IGNORE INTO content_hashes "
167
+ "(session_id, node_id, content_hash, normalised_hash, char_count, created_at) "
168
+ "VALUES (?, ?, ?, ?, ?, ?)",
169
+ (session_id, node_id, content_hash, normalised_hash, len(text), now),
170
+ )
171
+ self._conn.commit()
172
+ return content_hash
173
+
174
+ def get_hash_count(self, session_id: str) -> int:
175
+ """How many unique content hashes are in a session."""
176
+ row = self._conn.execute(
177
+ "SELECT COUNT(*) as cnt FROM content_hashes WHERE session_id = ?",
178
+ (session_id,),
179
+ ).fetchone()
180
+ return row["cnt"] if row else 0
181
+
182
+ def clear_session(self, session_id: str) -> int:
183
+ """Remove all hashes for a session. Returns count deleted."""
184
+ cur = self._conn.execute(
185
+ "DELETE FROM content_hashes WHERE session_id = ?", (session_id,),
186
+ )
187
+ self._conn.commit()
188
+ return cur.rowcount
189
+
190
+ # ------------------------------------------------------------------
191
+ # Hashing internals
192
+ # ------------------------------------------------------------------
193
+
194
+ @staticmethod
195
+ def _hash_text(text: str) -> str:
196
+ """SHA-256 of raw text."""
197
+ return hashlib.sha256(text.encode("utf-8")).hexdigest()
198
+
199
+ @staticmethod
200
+ def _hash_normalised(text: str) -> str:
201
+ """SHA-256 of normalised text (lowercase, collapsed whitespace, stripped)."""
202
+ normalised = re.sub(r"\s+", " ", text.lower().strip())
203
+ return hashlib.sha256(normalised.encode("utf-8")).hexdigest()
204
+
205
+ def close(self):
206
+ if self._conn:
207
+ self._conn.close()