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,888 @@
1
+ """
2
+ Context Manager
3
+ ===============
4
+ Independent, first-class Context entities backed by graph namespaces.
5
+
6
+ A Context is a curated, typed knowledge store that wraps a graph namespace
7
+ with metadata, access control, and lifecycle management.
8
+
9
+ Architecture:
10
+ Graph (storage engine) → Context (curation layer) → Session (collaboration)
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import json
16
+ import logging
17
+ import re
18
+ import secrets
19
+ import sqlite3
20
+ from dataclasses import dataclass, field, asdict
21
+ from datetime import datetime, timezone
22
+ from pathlib import Path
23
+ from typing import Any, Dict, List, Optional
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ CONTEXT_NS_PREFIX = ""
28
+
29
+ VALID_CONTEXT_TYPES = {"user", "system", "knowledge_base", "document", "web", "generated", "software_dev"}
30
+ VALID_SENSITIVITIES = {"public", "internal", "confidential", "restricted"}
31
+ VALID_STATUSES = {"active", "archived", "deleted"}
32
+
33
+ from .context_schema import get_categories as _get_schema_categories
34
+
35
+
36
+ @dataclass
37
+ class Context:
38
+ """A first-class context entity."""
39
+ context_id: str
40
+ name: str
41
+ description: str
42
+ context_type: str # user | system | knowledge_base | document | web | generated
43
+ graph_namespace: str
44
+ source: str # manual | document:<file> | web:<url> | session:<id>
45
+ sensitivity: str # public | internal | confidential | restricted
46
+ owner_id: Optional[str]
47
+ status: str # active | archived | deleted
48
+ item_count: int
49
+ estimated_tokens: int
50
+ embedding_model: Optional[str] # e.g. "text-embedding-3-small", "all-MiniLM-L6-v2"
51
+ embedding_dimension: Optional[int] # e.g. 384, 768, 1536
52
+ tags: List[str] = field(default_factory=list)
53
+ created_at: str = ""
54
+ updated_at: str = ""
55
+ config: Dict[str, Any] = field(default_factory=dict)
56
+
57
+ @property
58
+ def security_config(self) -> Dict[str, Any]:
59
+ """Get the security configuration for this context.
60
+
61
+ Stored in config['security']. Returns defaults if not set.
62
+ """
63
+ defaults = {
64
+ "pii_detection": True,
65
+ "auto_tagging": True,
66
+ "encryption": False,
67
+ "redaction_mode": "mask",
68
+ "encrypt_fields": ["email", "phone", "ssn"],
69
+ }
70
+ return {**defaults, **self.config.get("security", {})}
71
+
72
+ @security_config.setter
73
+ def security_config(self, value: Dict[str, Any]):
74
+ self.config["security"] = value
75
+
76
+ def to_dict(self) -> Dict[str, Any]:
77
+ return asdict(self)
78
+
79
+
80
+ def _slugify(name: str) -> str:
81
+ """Create a safe namespace slug from a context name."""
82
+ slug = re.sub(r"[^a-zA-Z0-9_-]", "_", name.lower().strip())
83
+ return slug[:64]
84
+
85
+
86
+ class ContextManager:
87
+ """
88
+ Manages independent Context entities backed by graph namespaces.
89
+
90
+ Each Context maps to a graph namespace via GraphRegistry.
91
+ SQLite-backed, same pattern as ContextSessionManager.
92
+ """
93
+
94
+ _SCHEMA = """
95
+ CREATE TABLE IF NOT EXISTS contexts (
96
+ context_id TEXT PRIMARY KEY,
97
+ name TEXT NOT NULL,
98
+ description TEXT DEFAULT '',
99
+ context_type TEXT NOT NULL DEFAULT 'knowledge_base',
100
+ graph_namespace TEXT NOT NULL UNIQUE,
101
+ source TEXT DEFAULT 'manual',
102
+ sensitivity TEXT DEFAULT 'public',
103
+ owner_id TEXT,
104
+ status TEXT DEFAULT 'active',
105
+ item_count INTEGER DEFAULT 0,
106
+ estimated_tokens INTEGER DEFAULT 0,
107
+ embedding_model TEXT,
108
+ embedding_dimension INTEGER,
109
+ tags TEXT DEFAULT '[]',
110
+ created_at TEXT NOT NULL,
111
+ updated_at TEXT NOT NULL,
112
+ config TEXT DEFAULT '{}'
113
+ );
114
+
115
+ CREATE INDEX IF NOT EXISTS idx_contexts_status ON contexts(status);
116
+ CREATE INDEX IF NOT EXISTS idx_contexts_type ON contexts(context_type);
117
+ CREATE INDEX IF NOT EXISTS idx_contexts_owner ON contexts(owner_id);
118
+ CREATE INDEX IF NOT EXISTS idx_contexts_namespace ON contexts(graph_namespace);
119
+ """
120
+
121
+ def __init__(self, db_path: str = "contextcore_data/context.db", graph_registry=None):
122
+ self._db_path = Path(db_path)
123
+ self._db_path.parent.mkdir(parents=True, exist_ok=True)
124
+ self._conn = sqlite3.connect(str(self._db_path), check_same_thread=False)
125
+ self._conn.row_factory = sqlite3.Row
126
+ self._conn.executescript(self._SCHEMA)
127
+ self._migrate_embedding_columns()
128
+ self._graph_registry = graph_registry
129
+
130
+ def _migrate_embedding_columns(self):
131
+ """Add embedding and tags columns if missing (for existing DBs)."""
132
+ try:
133
+ self._conn.execute("SELECT embedding_model FROM contexts LIMIT 1")
134
+ except sqlite3.OperationalError:
135
+ self._conn.execute("ALTER TABLE contexts ADD COLUMN embedding_model TEXT")
136
+ self._conn.execute("ALTER TABLE contexts ADD COLUMN embedding_dimension INTEGER")
137
+ self._conn.commit()
138
+ try:
139
+ self._conn.execute("SELECT tags FROM contexts LIMIT 1")
140
+ except sqlite3.OperationalError:
141
+ self._conn.execute("ALTER TABLE contexts ADD COLUMN tags TEXT DEFAULT '[]'")
142
+ self._conn.commit()
143
+
144
+ # ------------------------------------------------------------------
145
+ # CRUD
146
+ # ------------------------------------------------------------------
147
+
148
+ def create_context(
149
+ self,
150
+ name: str,
151
+ context_type: str = "knowledge_base",
152
+ description: str = "",
153
+ source: str = "manual",
154
+ sensitivity: str = "public",
155
+ owner_id: Optional[str] = None,
156
+ embedding_model: Optional[str] = None,
157
+ embedding_dimension: Optional[int] = None,
158
+ tags: Optional[List[str]] = None,
159
+ config: Optional[Dict[str, Any]] = None,
160
+ _graph_namespace: Optional[str] = None,
161
+ ) -> Context:
162
+ """Create a new context with a backing graph namespace."""
163
+ if context_type not in VALID_CONTEXT_TYPES:
164
+ raise ValueError(f"Invalid context_type: {context_type}")
165
+ if sensitivity not in VALID_SENSITIVITIES:
166
+ raise ValueError(f"Invalid sensitivity: {sensitivity}")
167
+
168
+ # Enforce unique context names (case-insensitive)
169
+ existing = self._conn.execute(
170
+ "SELECT context_id FROM contexts WHERE LOWER(name) = LOWER(?) AND status != 'deleted'",
171
+ (name,),
172
+ ).fetchone()
173
+ if existing:
174
+ raise ValueError(f"A context named '{name}' already exists")
175
+
176
+ context_id = secrets.token_hex(12)
177
+ now = datetime.now(timezone.utc).isoformat()
178
+
179
+ # Use provided namespace or generate from context name
180
+ if _graph_namespace:
181
+ ns = _graph_namespace
182
+ else:
183
+ ns = _slugify(name)
184
+ # Only collide if another context already owns this namespace
185
+ # (don't check graph registry — unrelated graphs like 'default' would cause false collisions)
186
+ existing_ns = self._conn.execute(
187
+ "SELECT context_id FROM contexts WHERE graph_namespace = ?", (ns,)
188
+ ).fetchone()
189
+ if existing_ns:
190
+ ns = f"{ns}_{context_id[:6]}"
191
+
192
+ # Purge any stale soft-deleted rows that hold this namespace
193
+ # (legacy data from before hard-delete was implemented)
194
+ self._conn.execute(
195
+ "DELETE FROM contexts WHERE graph_namespace = ? AND status = 'deleted'",
196
+ (ns,),
197
+ )
198
+ self._conn.commit()
199
+
200
+ # Create backing graph namespace with root Context node
201
+ if self._graph_registry:
202
+ if not _graph_namespace:
203
+ self._graph_registry.create_graph(ns)
204
+ try:
205
+ from ..core.graph_structures import GraphNode
206
+ db = self._graph_registry.get_graph(ns)
207
+ if not db:
208
+ db = self._graph_registry.create_graph(ns)
209
+ db.add_node(GraphNode(
210
+ id=context_id,
211
+ label="Context",
212
+ properties={
213
+ "name": name,
214
+ "context_type": context_type,
215
+ "description": description[:200] if description else "",
216
+ "sensitivity": sensitivity,
217
+ "created_at": now,
218
+ },
219
+ ), write_through=True)
220
+
221
+ # Create ALL category nodes under Context root (from schema)
222
+ from ..core.graph_structures import GraphEdge
223
+ schema_cats = _get_schema_categories()
224
+ for cat_key, (cat_label, cat_edge, _children) in schema_cats.items():
225
+ cat_node_id = f"{context_id}_{cat_key}"
226
+ db.add_node(GraphNode(
227
+ id=cat_node_id,
228
+ label=cat_label,
229
+ properties={
230
+ "name": f"{name} — {cat_label}",
231
+ "category": cat_key,
232
+ "created_at": now,
233
+ },
234
+ ), write_through=True)
235
+ db.add_edge(GraphEdge(
236
+ id=f"{context_id}_to_{cat_key}",
237
+ source=context_id,
238
+ target=cat_node_id,
239
+ label=cat_edge,
240
+ properties={},
241
+ ))
242
+
243
+ # ── Search index pointer nodes ──
244
+ # VectorIndex — tells search tools where embeddings live
245
+ vec_node_id = f"{context_id}_vector_index"
246
+ vec_collection = f"{ns}_passages"
247
+ db.add_node(GraphNode(
248
+ id=vec_node_id, label="VectorIndex",
249
+ properties={
250
+ "name": f"Vector Index: {name}",
251
+ "context_id": context_id,
252
+ "collection": vec_collection,
253
+ "embedding_model": embedding_model or "",
254
+ "embedding_dimension": embedding_dimension or 0,
255
+ "status": "pending", # becomes "active" after EMBED stage
256
+ "count": 0,
257
+ "created_at": now,
258
+ },
259
+ ), write_through=True)
260
+ db.add_edge(GraphEdge(
261
+ id=f"{context_id}_to_vector_index",
262
+ source=context_id, target=vec_node_id,
263
+ label="HAS_INDEX", properties={"index_type": "vector"},
264
+ ))
265
+
266
+ # BM25Index — tells search tools where full-text index lives
267
+ bm25_node_id = f"{context_id}_bm25_index"
268
+ safe_ns = ns.replace(":", "_")
269
+ bm25_path = f"contextcore_data/bm25_index/{safe_ns}"
270
+ db.add_node(GraphNode(
271
+ id=bm25_node_id, label="BM25Index",
272
+ properties={
273
+ "name": f"BM25 Index: {name}",
274
+ "context_id": context_id,
275
+ "index_path": bm25_path,
276
+ "graph_namespace": ns,
277
+ "status": "pending", # becomes "active" after INDEX_BM25 stage
278
+ "count": 0,
279
+ "created_at": now,
280
+ },
281
+ ), write_through=True)
282
+ db.add_edge(GraphEdge(
283
+ id=f"{context_id}_to_bm25_index",
284
+ source=context_id, target=bm25_node_id,
285
+ label="HAS_INDEX", properties={"index_type": "bm25"},
286
+ ))
287
+
288
+ # Save to disk (synchronous)
289
+ self._graph_registry.save_graph(ns, create_checkpoint=False)
290
+ except Exception as e:
291
+ logging.getLogger(__name__).debug("Failed to create root context node: %s", e)
292
+
293
+ merged_config = config or {}
294
+
295
+ # Software dev context: seed ProjectSpec node linked to root Context
296
+ if context_type == "software_dev" and self._graph_registry:
297
+ try:
298
+ db = self._graph_registry.get_graph(ns)
299
+ if db:
300
+ import uuid as _uuid
301
+ from ..core.graph_structures import GraphNode, GraphEdge
302
+ spec_id = str(_uuid.uuid4())
303
+ stack = merged_config.get("stack", {})
304
+ rules = merged_config.get("rules", [])
305
+ spec_text = merged_config.get("spec", description)
306
+ db.add_node(GraphNode(
307
+ id=spec_id, label="ProjectSpec",
308
+ properties={
309
+ "name": name,
310
+ "spec": spec_text,
311
+ "stack": json.dumps(stack) if isinstance(stack, dict) else str(stack),
312
+ "rules": json.dumps(rules) if isinstance(rules, list) else str(rules),
313
+ "repo": merged_config.get("repo", ""),
314
+ "status": "active",
315
+ "created_at": now,
316
+ },
317
+ ), write_through=True)
318
+ # Link: Context ──HAS_SPEC──► ProjectSpec
319
+ db.add_edge(GraphEdge(
320
+ id=str(_uuid.uuid4()), source=context_id, target=spec_id,
321
+ label="HAS_SPEC", properties={},
322
+ ))
323
+ # Store metadata in namespace store
324
+ try:
325
+ from ..storage.namespace_store import NamespaceStore
326
+ ns_store = NamespaceStore(ns)
327
+ ns_store.set_metadata("spec", spec_text)
328
+ ns_store.set_metadata("stack", stack)
329
+ ns_store.set_metadata("rules", rules)
330
+ ns_store.close()
331
+ except Exception:
332
+ pass
333
+ except Exception as e:
334
+ logging.getLogger(__name__).warning("Failed to seed code context: %s", e)
335
+
336
+ ctx = Context(
337
+ context_id=context_id,
338
+ name=name,
339
+ description=description,
340
+ context_type=context_type,
341
+ graph_namespace=ns,
342
+ source=source,
343
+ sensitivity=sensitivity,
344
+ owner_id=owner_id,
345
+ status="active",
346
+ item_count=0,
347
+ estimated_tokens=0,
348
+ embedding_model=embedding_model,
349
+ embedding_dimension=embedding_dimension,
350
+ tags=tags or [],
351
+ created_at=now,
352
+ updated_at=now,
353
+ config=merged_config,
354
+ )
355
+
356
+ self._conn.execute(
357
+ "INSERT INTO contexts "
358
+ "(context_id, name, description, context_type, graph_namespace, "
359
+ "source, sensitivity, owner_id, status, item_count, estimated_tokens, "
360
+ "embedding_model, embedding_dimension, tags, "
361
+ "created_at, updated_at, config) "
362
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
363
+ (
364
+ ctx.context_id, ctx.name, ctx.description, ctx.context_type,
365
+ ctx.graph_namespace, ctx.source, ctx.sensitivity, ctx.owner_id,
366
+ ctx.status, ctx.item_count, ctx.estimated_tokens,
367
+ ctx.embedding_model, ctx.embedding_dimension,
368
+ json.dumps(ctx.tags),
369
+ ctx.created_at, ctx.updated_at, json.dumps(ctx.config),
370
+ ),
371
+ )
372
+ self._conn.commit()
373
+
374
+ # Graph-first: register context + connect to its type node
375
+ if self._graph_registry:
376
+ try:
377
+ from ..core.graph_structures import GraphNode, GraphEdge
378
+ import uuid as _uuid
379
+ default_graph = self._graph_registry.get_graph("default") or self._graph_registry.create_graph("default")
380
+
381
+ # Ensure ContextType node exists (one per type, reused)
382
+ type_node_id = f"context_type_{context_type}"
383
+ existing_type = None
384
+ for n in default_graph.get_all_nodes():
385
+ if getattr(n, 'id', '') == type_node_id:
386
+ existing_type = n
387
+ break
388
+ if not existing_type:
389
+ default_graph.add_node(GraphNode(
390
+ id=type_node_id,
391
+ label="ContextType",
392
+ properties={"name": context_type, "label": context_type.replace("_", " ").title()},
393
+ ), write_through=True)
394
+
395
+ # Create Context node
396
+ default_graph.add_node(GraphNode(
397
+ id=ctx.context_id,
398
+ label="Context",
399
+ properties={
400
+ "name": ctx.name,
401
+ "context_type": ctx.context_type,
402
+ "graph_namespace": ctx.graph_namespace,
403
+ "description": ctx.description[:200] if ctx.description else "",
404
+ "sensitivity": ctx.sensitivity,
405
+ "status": ctx.status,
406
+ "created_at": ctx.created_at,
407
+ },
408
+ ), write_through=True)
409
+
410
+ # Connect: Context ──IS_TYPE──► ContextType
411
+ default_graph.add_edge(GraphEdge(
412
+ id=str(_uuid.uuid4()),
413
+ source=ctx.context_id,
414
+ target=type_node_id,
415
+ label="IS_TYPE",
416
+ properties={},
417
+ ))
418
+ except Exception as e:
419
+ logging.getLogger(__name__).debug("Failed to register context in default graph: %s", e)
420
+
421
+ return ctx
422
+
423
+ def ensure_boundaries(self, context_id: str) -> Optional[Dict[str, Any]]:
424
+ """Ensure a context has boundary nodes; seed them if missing.
425
+
426
+ Returns the boundary IDs dict, or None if the context doesn't exist.
427
+ """
428
+ ctx = self.get_context(context_id)
429
+ if not ctx:
430
+ return None
431
+
432
+ existing = ctx.config.get("_boundary_ids")
433
+ if existing:
434
+ return existing
435
+
436
+ if not self._graph_registry:
437
+ return None
438
+
439
+ db = self._graph_registry.get_graph(ctx.graph_namespace)
440
+ if not db:
441
+ return None
442
+
443
+ try:
444
+ from .boundaries import seed_boundary_nodes
445
+ boundary_ids = seed_boundary_nodes(db, ctx.context_id, ctx.name)
446
+ self._graph_registry.save_graph(ctx.graph_namespace, create_checkpoint=False)
447
+ # Persist to context config
448
+ new_config = dict(ctx.config)
449
+ new_config["_boundary_ids"] = boundary_ids
450
+ self.update_context(context_id, config=new_config)
451
+ return boundary_ids
452
+ except Exception as e:
453
+ logging.getLogger(__name__).warning("Failed to ensure boundaries for %s: %s", context_id, e)
454
+ return None
455
+
456
+ def get_context(self, context_id: str) -> Optional[Context]:
457
+ row = self._conn.execute(
458
+ "SELECT * FROM contexts WHERE context_id = ? AND status != 'deleted'",
459
+ (context_id,),
460
+ ).fetchone()
461
+ return self._row_to_context(row) if row else None
462
+
463
+ def get_by_graph_namespace(self, namespace: str) -> Optional[Context]:
464
+ row = self._conn.execute(
465
+ "SELECT * FROM contexts WHERE graph_namespace = ? AND status != 'deleted'",
466
+ (namespace,),
467
+ ).fetchone()
468
+ return self._row_to_context(row) if row else None
469
+
470
+ def list_contexts(
471
+ self,
472
+ context_type: Optional[str] = None,
473
+ status: str = "active",
474
+ owner_id: Optional[str] = None,
475
+ search: Optional[str] = None,
476
+ tag: Optional[str] = None,
477
+ ) -> List[Context]:
478
+ query = "SELECT * FROM contexts WHERE status = ?"
479
+ params: list = [status]
480
+
481
+ if context_type:
482
+ query += " AND context_type = ?"
483
+ params.append(context_type)
484
+ if owner_id:
485
+ query += " AND owner_id = ?"
486
+ params.append(owner_id)
487
+ if search:
488
+ query += " AND (name LIKE ? OR description LIKE ? OR tags LIKE ?)"
489
+ like = f"%{search}%"
490
+ params.extend([like, like, like])
491
+ if tag:
492
+ query += " AND tags LIKE ?"
493
+ params.append(f'%"{tag}"%')
494
+
495
+ query += " ORDER BY updated_at DESC"
496
+ rows = self._conn.execute(query, params).fetchall()
497
+ return [self._row_to_context(r) for r in rows]
498
+
499
+ def update_context(self, context_id: str, **fields) -> Optional[Context]:
500
+ """Update mutable fields on a context."""
501
+ allowed = {"name", "description", "sensitivity", "context_type", "source", "config", "status", "embedding_model", "embedding_dimension", "tags"}
502
+ updates = {k: v for k, v in fields.items() if k in allowed and v is not None}
503
+ if not updates:
504
+ return self.get_context(context_id)
505
+
506
+ now = datetime.now(timezone.utc).isoformat()
507
+ updates["updated_at"] = now
508
+
509
+ # Serialize config/tags if present
510
+ if "config" in updates and isinstance(updates["config"], dict):
511
+ updates["config"] = json.dumps(updates["config"])
512
+ if "tags" in updates and isinstance(updates["tags"], list):
513
+ updates["tags"] = json.dumps(updates["tags"])
514
+
515
+ set_clause = ", ".join(f"{k} = ?" for k in updates)
516
+ values = list(updates.values()) + [context_id]
517
+
518
+ self._conn.execute(
519
+ f"UPDATE contexts SET {set_clause} WHERE context_id = ?",
520
+ values,
521
+ )
522
+ self._conn.commit()
523
+ return self.get_context(context_id)
524
+
525
+ # ------------------------------------------------------------------
526
+ # Per-context extraction schema overrides
527
+ # ------------------------------------------------------------------
528
+
529
+ def get_extraction_schema(self, context_id: str) -> Optional[str]:
530
+ """Get the custom extraction schema YAML for a context, or None for default."""
531
+ ctx = self.get_context(context_id)
532
+ if not ctx:
533
+ return None
534
+ return ctx.config.get("extraction_schema_yaml")
535
+
536
+ def set_extraction_schema(self, context_id: str, schema_yaml: str) -> bool:
537
+ """Set a custom extraction schema YAML on a context."""
538
+ ctx = self.get_context(context_id)
539
+ if not ctx:
540
+ return False
541
+ new_config = dict(ctx.config)
542
+ new_config["extraction_schema_yaml"] = schema_yaml
543
+ self.update_context(context_id, config=new_config)
544
+ return True
545
+
546
+ def clear_extraction_schema(self, context_id: str) -> bool:
547
+ """Remove the custom extraction schema, reverting to the type default."""
548
+ ctx = self.get_context(context_id)
549
+ if not ctx:
550
+ return False
551
+ new_config = dict(ctx.config)
552
+ new_config.pop("extraction_schema_yaml", None)
553
+ self.update_context(context_id, config=new_config)
554
+ return True
555
+
556
+ def delete_context(self, context_id: str) -> bool:
557
+ """Delete a context — cascades to its backing graph."""
558
+ ctx = self.get_context(context_id)
559
+ if not ctx:
560
+ return False
561
+
562
+ now = datetime.now(timezone.utc).isoformat()
563
+
564
+ # 1. Delete backing graph (memory + files)
565
+ if self._graph_registry and ctx.graph_namespace:
566
+ try:
567
+ self._graph_registry.delete_graph(ctx.graph_namespace, delete_files=True)
568
+ except Exception as e:
569
+ logging.getLogger(__name__).debug("Failed to delete backing graph: %s", e)
570
+
571
+ # 2. Hard-delete from SQLite (graph files already gone, soft-delete
572
+ # leaves the UNIQUE graph_namespace occupied and blocks re-creation)
573
+ cur = self._conn.execute(
574
+ "DELETE FROM contexts WHERE context_id = ?",
575
+ (context_id,),
576
+ )
577
+ self._conn.commit()
578
+ return cur.rowcount > 0
579
+
580
+ # ------------------------------------------------------------------
581
+ # Content operations
582
+ # ------------------------------------------------------------------
583
+
584
+ def add_text(
585
+ self,
586
+ context_id: str,
587
+ content: str,
588
+ role: str = "user",
589
+ label: Optional[str] = None,
590
+ sensitivity: str = "public",
591
+ tags: Optional[List[str]] = None,
592
+ ) -> Optional[Dict[str, Any]]:
593
+ """Add a text item to the context's backing graph as a node."""
594
+ ctx = self.get_context(context_id)
595
+ if not ctx:
596
+ return None
597
+
598
+ if not self._graph_registry:
599
+ return None
600
+
601
+ db = self._graph_registry.get_graph(ctx.graph_namespace)
602
+ if not db:
603
+ self._graph_registry.create_graph(ctx.graph_namespace)
604
+ db = self._graph_registry.get_graph(ctx.graph_namespace)
605
+
606
+ if not db:
607
+ return None
608
+
609
+ from ..core.graph_structures import GraphNode, GraphEdge
610
+ import uuid
611
+ node_id = str(uuid.uuid4())
612
+ node = GraphNode(
613
+ id=node_id,
614
+ label="ContextItem",
615
+ properties={
616
+ "content": content,
617
+ "role": role,
618
+ "label": label or "",
619
+ "sensitivity": sensitivity,
620
+ "tags": json.dumps(tags or []),
621
+ "created_at": datetime.now(timezone.utc).isoformat(),
622
+ },
623
+ )
624
+ db.add_node(node, write_through=True)
625
+
626
+ # Link to type node (KnowledgeBase etc.) or Context root
627
+ type_node_id = f"{context_id}_knowledge"
628
+ parent_id = type_node_id if db.get_node(type_node_id) else context_id
629
+ db.add_edge(GraphEdge(
630
+ id=str(uuid.uuid4()),
631
+ source=parent_id,
632
+ target=node_id,
633
+ label="HAS_CONTENT",
634
+ properties={"role": role},
635
+ ))
636
+
637
+ # Persist graph
638
+ try:
639
+ self._graph_registry.save_graph(ctx.graph_namespace, create_checkpoint=False)
640
+ except Exception as e:
641
+ logger.warning("Failed to persist context graph %s: %s", ctx.graph_namespace, e)
642
+
643
+ # Update stats
644
+ self._refresh_stats(context_id, db)
645
+
646
+ return {
647
+ "node_id": str(node.id),
648
+ "content": content[:100],
649
+ "role": role,
650
+ "label": label,
651
+ }
652
+
653
+ # Node labels relevant to each context type. When a context has a
654
+ # declared type we only return nodes whose label is in this set so
655
+ # the UI stays focused. ``None`` means "show everything".
656
+ # Connector-related node types shared across all context types
657
+ _CONNECTOR_LABELS = {
658
+ "Connector", "SyncRun", "DatabaseSchema", "Table", "Column", "Index", "ForeignKey",
659
+ "Repository", "Issue", "PullRequest", "File", "Contributor",
660
+ "JiraProject", "Sprint", "Component", "User",
661
+ "APIEndpoint", "ResponseField",
662
+ "SFObject", "SFField", "SFRelationship",
663
+ "SAPModule", "SAPTable", "SAPField",
664
+ "SNTable", "SNField",
665
+ }
666
+
667
+ _TYPE_RELEVANT_LABELS: Dict[str, Optional[set]] = {
668
+ "knowledge_base": {"Document", "Passage", "TextChunk", "Chunk", "Fact", "Concept", "Topic", "Knowledge"} | _CONNECTOR_LABELS,
669
+ "software_dev": {"CodeFile", "CodeModule", "Document", "Passage", "TextChunk", "Chunk", "Module", "Class",
670
+ "Function", "Component", "Service", "Schema", "API", "Endpoint",
671
+ "GitHubIssue", "GitHubPR", "Contributor", "RepoMeta",
672
+ "ArchDecision", "KnownIssue", "TestCase", "APIContract",
673
+ "Requirement", "UserStory", "Goal", "ChangeRecord"} | _CONNECTOR_LABELS,
674
+ "rules": {"Document", "Passage", "TextChunk", "Chunk", "Rule", "Constraint", "Standard", "Policy", "Fact"} | _CONNECTOR_LABELS,
675
+ "database": {"Table", "Column", "Schema", "Index", "View", "Document", "Passage", "TextChunk", "Chunk",
676
+ "Entity", "Relationship"} | _CONNECTOR_LABELS,
677
+ "decision": {"Decision", "Document", "Passage", "TextChunk", "Chunk", "Fact", "ADR", "TradeOff"} | _CONNECTOR_LABELS,
678
+ "web": {"Document", "Passage", "TextChunk", "Chunk", "WebPage", "Link", "Fact"} | _CONNECTOR_LABELS,
679
+ }
680
+
681
+ def get_items(self, context_id: str, category: Optional[str] = None,
682
+ show_all: bool = False, max_tokens: Optional[int] = None,
683
+ query: Optional[str] = None) -> List[Dict[str, Any]]:
684
+ """Get content items from a context's backing graph.
685
+
686
+ Args:
687
+ context_id: The context to query.
688
+ category: Optional category filter.
689
+ show_all: If True, bypass context-type filtering.
690
+ max_tokens: If set, return items up to this token budget (most relevant first).
691
+ query: If set with max_tokens, rank items by relevance to this query.
692
+
693
+ Returns:
694
+ List of item dicts, excluding structural boundary nodes.
695
+ """
696
+ from .boundaries import BOUNDARY_NODE_LABELS
697
+
698
+ ctx = self.get_context(context_id)
699
+ if not ctx or not self._graph_registry:
700
+ return []
701
+
702
+ ns = ctx.graph_namespace
703
+ db = self._graph_registry.get_graph(ns)
704
+ if not db:
705
+ logger.warning("get_items: graph '%s' not found for context '%s'", ns, context_id)
706
+ return []
707
+
708
+ # Determine which labels to show based on context type
709
+ relevant_labels = None
710
+ if not show_all:
711
+ # Try schema-driven labels first
712
+ try:
713
+ from contextsynapse.project.schema_manager import get_schema_manager
714
+ schema_labels = get_schema_manager().get_consumer_hint(
715
+ ns, "context_filter_labels", None
716
+ )
717
+ if schema_labels is not None:
718
+ relevant_labels = set(schema_labels) | self._CONNECTOR_LABELS
719
+ except Exception:
720
+ pass
721
+ # Fall back to hardcoded per-context-type labels
722
+ if relevant_labels is None:
723
+ relevant_labels = self._TYPE_RELEVANT_LABELS.get(ctx.context_type)
724
+
725
+ nodes = db.get_all_nodes()
726
+ items = []
727
+ for node in nodes:
728
+ if isinstance(node, dict):
729
+ props = node
730
+ node_label = props.get("label", "")
731
+ else:
732
+ node_label = getattr(node, "label", "")
733
+ props = getattr(node, "properties", {}) or {}
734
+ props["node_id"] = str(getattr(node, "id", ""))
735
+ props["label_type"] = node_label
736
+
737
+ # Skip structural boundary nodes
738
+ if node_label in BOUNDARY_NODE_LABELS:
739
+ continue
740
+
741
+ # Filter by context-type-relevant labels
742
+ if relevant_labels and node_label not in relevant_labels:
743
+ continue
744
+
745
+ # Apply category filter
746
+ if category and props.get("category") != category:
747
+ continue
748
+
749
+ items.append(props)
750
+
751
+ # Token-budgeted retrieval with relevance ranking
752
+ if max_tokens and items:
753
+ if query:
754
+ # Score by keyword relevance to query
755
+ q_terms = query.lower().split()
756
+ scored = []
757
+ for item in items:
758
+ text = " ".join(str(v) for v in item.values()).lower()
759
+ score = sum(1 for t in q_terms if t in text) / max(len(q_terms), 1)
760
+ scored.append((item, score))
761
+ scored.sort(key=lambda x: x[1], reverse=True)
762
+ items = [s[0] for s in scored]
763
+
764
+ # Early stopping at token budget
765
+ result = []
766
+ tokens_used = 0
767
+ for item in items:
768
+ content = item.get("content") or item.get("description") or item.get("statement") or ""
769
+ item_tokens = max(1, len(str(content)) // 4)
770
+ if tokens_used + item_tokens > max_tokens:
771
+ break
772
+ result.append(item)
773
+ tokens_used += item_tokens
774
+ return result
775
+
776
+ return items
777
+
778
+ def refresh_stats(self, context_id: str) -> Optional[Context]:
779
+ """Recount items and estimate tokens from the backing graph."""
780
+ ctx = self.get_context(context_id)
781
+ if not ctx or not self._graph_registry:
782
+ return ctx
783
+
784
+ ns = ctx.graph_namespace
785
+ db = self._graph_registry.get_graph(ns)
786
+ if not db:
787
+ logger.warning("refresh_stats: graph '%s' not found for context '%s'", ns, context_id)
788
+ if db:
789
+ self._refresh_stats(context_id, db)
790
+
791
+ return self.get_context(context_id)
792
+
793
+ def _refresh_stats(self, context_id: str, db):
794
+ """Internal: update item_count and estimated_tokens from graph."""
795
+ from .boundaries import BOUNDARY_NODE_LABELS
796
+
797
+ ctx = self.get_context(context_id)
798
+ relevant_labels = self._TYPE_RELEVANT_LABELS.get(ctx.context_type) if ctx else None
799
+
800
+ nodes = db.get_all_nodes()
801
+ item_count = 0
802
+ total_chars = 0
803
+
804
+ for node in nodes:
805
+ if isinstance(node, dict):
806
+ node_label = node.get("label", "")
807
+ content = node.get("content", "")
808
+ else:
809
+ node_label = getattr(node, "label", "")
810
+ props = getattr(node, "properties", {}) or {}
811
+ content = props.get("content", "")
812
+
813
+ # Exclude structural boundary nodes from stats
814
+ if node_label in BOUNDARY_NODE_LABELS:
815
+ continue
816
+
817
+ # Only count type-relevant nodes
818
+ if relevant_labels and node_label not in relevant_labels:
819
+ continue
820
+
821
+ item_count += 1
822
+ total_chars += len(str(content))
823
+
824
+ estimated_tokens = int(total_chars / 4.0) # ~4 chars per token
825
+ now = datetime.now(timezone.utc).isoformat()
826
+
827
+ self._conn.execute(
828
+ "UPDATE contexts SET item_count = ?, estimated_tokens = ?, updated_at = ? "
829
+ "WHERE context_id = ?",
830
+ (item_count, estimated_tokens, now, context_id),
831
+ )
832
+ self._conn.commit()
833
+
834
+ # ------------------------------------------------------------------
835
+ # Migration
836
+ # ------------------------------------------------------------------
837
+
838
+ def migrate_session_contexts(self, session_manager) -> int:
839
+ """One-time migration: wrap each session's graph namespace as a Context.
840
+
841
+ Returns the number of contexts created.
842
+ """
843
+ created = 0
844
+ for session in session_manager.list_sessions():
845
+ existing = self.get_by_graph_namespace(session.graph_namespace)
846
+ if not existing:
847
+ try:
848
+ self.create_context(
849
+ name=session.name,
850
+ context_type="generated",
851
+ description=f"Auto-migrated from session '{session.name}'",
852
+ source=f"session:{session.session_id}",
853
+ owner_id=session.owner_agent_id,
854
+ _graph_namespace=session.graph_namespace,
855
+ )
856
+ created += 1
857
+ except Exception as e:
858
+ logger.warning("Failed to migrate session '%s': %s", session.name, e)
859
+ return created
860
+
861
+ # ------------------------------------------------------------------
862
+ # Helpers
863
+ # ------------------------------------------------------------------
864
+
865
+ def _row_to_context(self, row: sqlite3.Row) -> Context:
866
+ return Context(
867
+ context_id=row["context_id"],
868
+ name=row["name"],
869
+ description=row["description"],
870
+ context_type=row["context_type"],
871
+ graph_namespace=row["graph_namespace"],
872
+ source=row["source"],
873
+ sensitivity=row["sensitivity"],
874
+ owner_id=row["owner_id"],
875
+ status=row["status"],
876
+ item_count=row["item_count"],
877
+ estimated_tokens=row["estimated_tokens"],
878
+ embedding_model=row["embedding_model"],
879
+ embedding_dimension=row["embedding_dimension"],
880
+ tags=json.loads(row["tags"]) if row["tags"] else [],
881
+ created_at=row["created_at"],
882
+ updated_at=row["updated_at"],
883
+ config=json.loads(row["config"]) if row["config"] else {},
884
+ )
885
+
886
+ def close(self):
887
+ if self._conn:
888
+ self._conn.close()