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,992 @@
1
+ """Context Seed Engine — seeds entity contexts using multiple context layers.
2
+
3
+ Unlike single-domain seeding, this engine:
4
+ 1. Asks ALL registered layers if they know about the entity
5
+ 2. Merges knowledge from every layer that responds
6
+ 3. Builds a unified schema from all contributing layers
7
+ 4. Sets up cross-layer dependency edges
8
+ 5. Recommends sensors from all relevant layers
9
+
10
+ Example: seeding "Reliance"
11
+ - finance layer: stock data, earnings schema, price sensor
12
+ - macro layer: GDP dependency, RBI regulation
13
+ - supply_chain layer: crude oil input, ethylene supply
14
+ - psychology layer: retail herding patterns
15
+ - weather layer: monsoon impact on retail segment
16
+
17
+ All combined into ONE entity context with edges to shared entities.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import json
23
+ import logging
24
+ import re
25
+ import uuid
26
+ from dataclasses import asdict, dataclass, field
27
+ from datetime import datetime, timezone
28
+ from typing import Any, Dict, List, Optional
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ # ---------------------------------------------------------------------------
34
+ # Result data class
35
+ # ---------------------------------------------------------------------------
36
+
37
+
38
+ @dataclass
39
+ class SeedResult:
40
+ """Complete result of seeding a new entity context via multiple layers."""
41
+
42
+ entity: str
43
+ contributing_layers: List[str] # which layers enriched this entity
44
+ discovery: dict # merged discovery from all layers + LLM
45
+ schema: dict # merged node types and edge types
46
+ dependency_map: dict # all dependencies across layers
47
+ pipeline_recommendations: list # suggested data feeds with reasons
48
+ sensor_suggestions: list # sensors to activate with reasons
49
+ cross_layer_connections: list # edges to shared/meta entities
50
+ estimated_signal_sources: int
51
+ llm_used: bool
52
+ timestamp: str
53
+
54
+ def summary(self) -> str:
55
+ """Human-readable summary of the seed result."""
56
+ lines = [
57
+ f"Entity: {self.entity}",
58
+ f"Layers: {', '.join(self.contributing_layers) or 'none'}",
59
+ f"LLM used: {self.llm_used}",
60
+ f"Schema: {len(self.schema.get('node_types', []))} node types, "
61
+ f"{len(self.schema.get('edge_types', []))} edge types",
62
+ f"Dependencies: {sum(len(v) for v in self.dependency_map.values() if isinstance(v, list))} total",
63
+ f"Pipelines: {len(self.pipeline_recommendations)}",
64
+ f"Sensors: {len(self.sensor_suggestions)}",
65
+ f"Cross-layer connections: {len(self.cross_layer_connections)}",
66
+ f"Estimated signal sources: {self.estimated_signal_sources}",
67
+ ]
68
+ return "\n".join(lines)
69
+
70
+ def to_dict(self) -> Dict[str, Any]:
71
+ return asdict(self)
72
+
73
+
74
+ # ---------------------------------------------------------------------------
75
+ # Context Seed Engine
76
+ # ---------------------------------------------------------------------------
77
+
78
+
79
+ class ContextSeedEngine:
80
+ """Seeds entity contexts using ALL available context layers.
81
+
82
+ The engine asks every registered layer whether it knows about the
83
+ entity, collects and merges their knowledge, optionally enriches
84
+ via LLM, and produces a unified context seed that includes schema,
85
+ dependency map, pipeline recommendations, and sensor suggestions
86
+ from ALL contributing layers.
87
+
88
+ Usage::
89
+
90
+ from contextsynapse.context.layers import ContextLayer
91
+ from contextsynapse.context.seed import ContextSeedEngine
92
+
93
+ layers = [
94
+ ContextLayer.from_yaml("layers/finance.yaml"),
95
+ ContextLayer.from_yaml("layers/macro.yaml"),
96
+ ContextLayer.from_yaml("layers/supply_chain.yaml"),
97
+ ]
98
+ engine = ContextSeedEngine(registry=my_registry, layers=layers)
99
+ result = engine.seed("Reliance Industries", sector="Conglomerate")
100
+ engine.apply(result)
101
+ """
102
+
103
+ def __init__(
104
+ self,
105
+ registry,
106
+ layers: Optional[List] = None,
107
+ llm_client=None,
108
+ ):
109
+ """
110
+ Args:
111
+ registry: GraphRegistry (or RedisGraphRegistry) for graph access.
112
+ layers: List of ContextLayer instances. If None, attempts to
113
+ load all registered layers via plugin discovery.
114
+ llm_client: Optional LLM client with ``generate_json()`` method.
115
+ If None, uses layer data only (no LLM cost).
116
+ """
117
+ self.registry = registry
118
+ self.llm_client = llm_client
119
+
120
+ if layers is not None:
121
+ self.layers = list(layers)
122
+ else:
123
+ self.layers = self._discover_layers()
124
+
125
+ # ------------------------------------------------------------------
126
+ # Public API
127
+ # ------------------------------------------------------------------
128
+
129
+ def seed(
130
+ self,
131
+ entity_name: str,
132
+ entity_type: str = "company",
133
+ ticker: Optional[str] = None,
134
+ sector: Optional[str] = None,
135
+ exchange: str = "NSE",
136
+ extra_context: str = "",
137
+ ) -> SeedResult:
138
+ """Seed an entity context using all available layers.
139
+
140
+ Steps:
141
+ 1. Ask each layer: do you know about this entity?
142
+ 2. For layers that respond, collect their entity data
143
+ 3. If LLM available, run discovery with merged prompt
144
+ 4. Generate schema from all contributing layers
145
+ 5. Build dependency map from discovery + layer cross-edges
146
+ 6. Generate pipeline recommendations (each with WHY)
147
+ 7. Generate sensor suggestions (each with REASON)
148
+ 8. Identify cross-layer connections
149
+
150
+ Args:
151
+ entity_name: Human-readable entity name.
152
+ entity_type: Type of entity (default "company").
153
+ ticker: Optional identifier.
154
+ sector: Optional sector override. Auto-classified if omitted.
155
+ exchange: Market identifier (default "NSE").
156
+ extra_context: Additional text context for LLM discovery.
157
+
158
+ Returns:
159
+ SeedResult with all seeding artifacts.
160
+ """
161
+ now = datetime.now(timezone.utc).isoformat()
162
+
163
+ # Step 1+2: Ask all layers and collect knowledge
164
+ contributing_layers: List[str] = []
165
+ merged_entity_data: Dict[str, Any] = {}
166
+
167
+ for layer in self.layers:
168
+ if layer.enriches(entity_name):
169
+ contributing_layers.append(layer.layer_id)
170
+ layer_data = layer.get_entity_data(entity_name)
171
+ if layer_data:
172
+ # Merge: later layers extend, don't overwrite lists
173
+ _merge_dicts(merged_entity_data, layer_data, layer.layer_id)
174
+
175
+ # Auto-classify sector from layers if not provided
176
+ if not sector:
177
+ for layer in self.layers:
178
+ if layer.layer_id in contributing_layers:
179
+ classified = layer.classify(entity_name)
180
+ if classified and classified != "uncategorized":
181
+ sector = classified
182
+ break
183
+ if not sector:
184
+ sector = merged_entity_data.get("sector", "unknown")
185
+
186
+ entity_info = {
187
+ "entity_name": entity_name,
188
+ "entity_type": entity_type,
189
+ "ticker": ticker or merged_entity_data.get("ticker", ""),
190
+ "sector": sector,
191
+ "exchange": exchange,
192
+ "extra_context": extra_context,
193
+ }
194
+
195
+ # Step 3: LLM discovery (optional) merged with layer data
196
+ discovery, llm_used = self._discover(entity_info, merged_entity_data)
197
+
198
+ # Step 4: Merge schema from all contributing layers
199
+ schema = self._merge_schema(contributing_layers)
200
+
201
+ # Step 5: Build dependency map from discovery + layer cross-edges
202
+ dependency_map = self._build_dependency_map(discovery, contributing_layers)
203
+
204
+ # Step 6: Pipeline recommendations from all layers
205
+ pipeline_recs = self._generate_pipeline_recommendations(
206
+ entity_name, dependency_map, sector, contributing_layers
207
+ )
208
+
209
+ # Step 7: Sensor suggestions from all contributing layers
210
+ sensor_suggestions = self._generate_sensor_suggestions(
211
+ entity_name, sector, contributing_layers
212
+ )
213
+
214
+ # Step 8: Cross-layer connections
215
+ cross_layer_connections = self._find_cross_layer_connections(
216
+ entity_name, entity_type, contributing_layers
217
+ )
218
+
219
+ # Estimate total source count
220
+ estimated_sources = (
221
+ len(pipeline_recs)
222
+ + sum(1 for s in sensor_suggestions if s.get("activate"))
223
+ + len(cross_layer_connections)
224
+ )
225
+
226
+ return SeedResult(
227
+ entity=entity_name,
228
+ contributing_layers=contributing_layers,
229
+ discovery=discovery,
230
+ schema=schema,
231
+ dependency_map=dependency_map,
232
+ pipeline_recommendations=pipeline_recs,
233
+ sensor_suggestions=sensor_suggestions,
234
+ cross_layer_connections=cross_layer_connections,
235
+ estimated_signal_sources=estimated_sources,
236
+ llm_used=llm_used,
237
+ timestamp=now,
238
+ )
239
+
240
+ def apply(self, seed_result: SeedResult, context_manager=None) -> Dict[str, Any]:
241
+ """Apply seed result to the graph.
242
+
243
+ Creates:
244
+ - Entity root node
245
+ - KB nodes (people, brands, aliases)
246
+ - Dependency nodes + edges
247
+ - Schema definition node
248
+ - Cross-layer edges to shared entities
249
+ - SeedManifest node
250
+
251
+ Args:
252
+ seed_result: The SeedResult from seed().
253
+ context_manager: Optional ContextManager for formal context creation.
254
+
255
+ Returns:
256
+ Dict with {namespace, nodes_created, edges_created}.
257
+ """
258
+ from contextsynapse.core.graph_structures import GraphEdge, GraphNode
259
+
260
+ entity_slug = _slugify(seed_result.entity)
261
+ namespace = entity_slug
262
+
263
+ # Get or create graph
264
+ graph = self.registry.get_graph(namespace, load_if_missing=True)
265
+ if graph is None:
266
+ graph = self.registry.create_graph(namespace)
267
+
268
+ nodes_created = 0
269
+ edges_created = 0
270
+
271
+ # --- Entity root node ---
272
+ entity_root_id = f"{entity_slug}_root"
273
+ graph.add_node(GraphNode(
274
+ id=entity_root_id,
275
+ label="Entity",
276
+ properties={
277
+ "name": seed_result.entity,
278
+ "contributing_layers": seed_result.contributing_layers,
279
+ "sector": seed_result.discovery.get("sector", ""),
280
+ "seeded_at": seed_result.timestamp,
281
+ },
282
+ ))
283
+ nodes_created += 1
284
+
285
+ # --- People ---
286
+ for person in seed_result.discovery.get("people", []):
287
+ name = person if isinstance(person, str) else person.get("name", str(person))
288
+ title = "" if isinstance(person, str) else person.get("title", "")
289
+ pid = f"{entity_slug}_person_{_slugify(name)}"
290
+ graph.add_node(GraphNode(
291
+ id=pid,
292
+ label="Person",
293
+ properties={"name": name, "title": title, "entity": seed_result.entity},
294
+ ))
295
+ graph.add_edge(GraphEdge(
296
+ id=f"e_{entity_root_id}_{pid}",
297
+ source=entity_root_id,
298
+ target=pid,
299
+ label="HAS_PERSON",
300
+ ))
301
+ nodes_created += 1
302
+ edges_created += 1
303
+
304
+ # --- Brands / subsidiaries ---
305
+ for brand in seed_result.discovery.get("brands", []):
306
+ name = brand if isinstance(brand, str) else brand.get("name", str(brand))
307
+ bid = f"{entity_slug}_brand_{_slugify(name)}"
308
+ graph.add_node(GraphNode(
309
+ id=bid,
310
+ label="Brand",
311
+ properties={"name": name, "entity": seed_result.entity},
312
+ ))
313
+ graph.add_edge(GraphEdge(
314
+ id=f"e_{entity_root_id}_{bid}",
315
+ source=entity_root_id,
316
+ target=bid,
317
+ label="HAS_BRAND",
318
+ ))
319
+ nodes_created += 1
320
+ edges_created += 1
321
+
322
+ # --- Aliases ---
323
+ aliases = seed_result.discovery.get("aliases", [])
324
+ if aliases:
325
+ alias_id = f"{entity_slug}_aliases"
326
+ graph.add_node(GraphNode(
327
+ id=alias_id,
328
+ label="AliasSet",
329
+ properties={"aliases": aliases, "entity": seed_result.entity},
330
+ ))
331
+ graph.add_edge(GraphEdge(
332
+ id=f"e_{entity_root_id}_{alias_id}",
333
+ source=entity_root_id,
334
+ target=alias_id,
335
+ label="HAS_ALIASES",
336
+ ))
337
+ nodes_created += 1
338
+ edges_created += 1
339
+
340
+ # --- Dependency map nodes ---
341
+ dep_label_map = {
342
+ "supply_chain": ("SupplyChainInput", "DEPENDS_ON"),
343
+ "regulatory": ("Regulator", "REGULATED_BY"),
344
+ "competitive": ("Competitor", "COMPETES_WITH"),
345
+ "macro": ("MacroDependency", "AFFECTED_BY"),
346
+ }
347
+ for category, (node_label, edge_label) in dep_label_map.items():
348
+ for dep in seed_result.dependency_map.get(category, []):
349
+ dep_name = dep if isinstance(dep, str) else dep.get("name", str(dep))
350
+ dep_layer = "" if isinstance(dep, str) else dep.get("layer", "")
351
+ dep_id = f"{entity_slug}_{category}_{_slugify(dep_name)}"
352
+ dep_props = {
353
+ "name": dep_name,
354
+ "category": category,
355
+ "entity": seed_result.entity,
356
+ }
357
+ if dep_layer:
358
+ dep_props["source_layer"] = dep_layer
359
+ if isinstance(dep, dict):
360
+ dep_props.update({k: v for k, v in dep.items() if k not in ("name", "layer")})
361
+
362
+ graph.add_node(GraphNode(
363
+ id=dep_id,
364
+ label=node_label,
365
+ properties=dep_props,
366
+ ))
367
+ graph.add_edge(GraphEdge(
368
+ id=f"e_{entity_root_id}_{dep_id}",
369
+ source=entity_root_id,
370
+ target=dep_id,
371
+ label=edge_label,
372
+ ))
373
+ nodes_created += 1
374
+ edges_created += 1
375
+
376
+ # --- Cross-layer connection nodes ---
377
+ for conn in seed_result.cross_layer_connections:
378
+ shared_name = conn.get("shared_entity", "")
379
+ if not shared_name:
380
+ continue
381
+ shared_id = f"shared_{_slugify(shared_name)}"
382
+ # Create shared entity node (idempotent — add_node can upsert)
383
+ graph.add_node(GraphNode(
384
+ id=shared_id,
385
+ label="SharedEntity",
386
+ properties={
387
+ "name": shared_name,
388
+ "entity_type": conn.get("entity_type", ""),
389
+ "linked_layers": conn.get("layers", []),
390
+ },
391
+ ))
392
+ edge_type = conn.get("edge_type", "CONNECTED_TO")
393
+ graph.add_edge(GraphEdge(
394
+ id=f"e_{entity_root_id}_{shared_id}",
395
+ source=entity_root_id,
396
+ target=shared_id,
397
+ label=edge_type,
398
+ properties={
399
+ "propagation_weight": conn.get("propagation_weight", 0.7),
400
+ },
401
+ ))
402
+ nodes_created += 1
403
+ edges_created += 1
404
+
405
+ # --- Schema node ---
406
+ schema_id = f"{entity_slug}_schema"
407
+ graph.add_node(GraphNode(
408
+ id=schema_id,
409
+ label="SchemaDefinition",
410
+ properties={
411
+ "entity": seed_result.entity,
412
+ "contributing_layers": seed_result.contributing_layers,
413
+ "schema": json.dumps(seed_result.schema),
414
+ "created_at": seed_result.timestamp,
415
+ },
416
+ ))
417
+ nodes_created += 1
418
+
419
+ # --- SeedManifest node ---
420
+ manifest_id = f"{entity_slug}_seed_manifest"
421
+ graph.add_node(GraphNode(
422
+ id=manifest_id,
423
+ label="SeedManifest",
424
+ properties={
425
+ "entity": seed_result.entity,
426
+ "contributing_layers": seed_result.contributing_layers,
427
+ "llm_used": seed_result.llm_used,
428
+ "estimated_signal_sources": seed_result.estimated_signal_sources,
429
+ "pipeline_count": len(seed_result.pipeline_recommendations),
430
+ "sensor_count": len(seed_result.sensor_suggestions),
431
+ "cross_layer_count": len(seed_result.cross_layer_connections),
432
+ "dependency_count": sum(
433
+ len(v) for v in seed_result.dependency_map.values()
434
+ if isinstance(v, list)
435
+ ),
436
+ "seeded_at": seed_result.timestamp,
437
+ "seed_result_json": json.dumps(seed_result.to_dict()),
438
+ },
439
+ ))
440
+ nodes_created += 1
441
+
442
+ # Optionally create a formal Context
443
+ if context_manager is not None:
444
+ try:
445
+ layer_tags = list(seed_result.contributing_layers) + ["auto-seeded"]
446
+ context_manager.create_context(
447
+ name=seed_result.entity,
448
+ description=(
449
+ f"Auto-seeded context for {seed_result.entity} "
450
+ f"(layers: {', '.join(seed_result.contributing_layers)})"
451
+ ),
452
+ context_type="knowledge_base",
453
+ source="seed:multi_layer",
454
+ sensitivity="internal",
455
+ tags=layer_tags,
456
+ graph_namespace=namespace,
457
+ )
458
+ except Exception as exc:
459
+ logger.warning(
460
+ "Could not create formal context for '%s': %s",
461
+ seed_result.entity, exc,
462
+ )
463
+
464
+ logger.info(
465
+ "Applied seed for '%s' [layers: %s]: %d nodes, %d edges in namespace '%s'",
466
+ seed_result.entity,
467
+ ", ".join(seed_result.contributing_layers),
468
+ nodes_created,
469
+ edges_created,
470
+ namespace,
471
+ )
472
+
473
+ return {
474
+ "namespace": namespace,
475
+ "nodes_created": nodes_created,
476
+ "edges_created": edges_created,
477
+ }
478
+
479
+ def seed_shared_entity(
480
+ self, entity_name: str, entity_type: str
481
+ ) -> Dict[str, Any]:
482
+ """Seed a shared/meta entity that acts as a bridge across layers.
483
+
484
+ Shared entities (e.g. "crude_oil", "interest_rates", "monsoon")
485
+ exist in a dedicated ``_shared`` namespace and are referenced by
486
+ multiple entity contexts via cross-layer edges.
487
+
488
+ Args:
489
+ entity_name: Name of the shared entity.
490
+ entity_type: Type label (e.g. "commodity", "policy", "weather").
491
+
492
+ Returns:
493
+ Dict with {namespace, node_id, contributing_layers}.
494
+ """
495
+ from contextsynapse.core.graph_structures import GraphNode
496
+
497
+ namespace = "_shared"
498
+ graph = self.registry.get_graph(namespace, load_if_missing=True)
499
+ if graph is None:
500
+ graph = self.registry.create_graph(namespace)
501
+
502
+ node_id = f"shared_{_slugify(entity_name)}"
503
+
504
+ # Determine which layers know about this shared entity
505
+ contributing = [
506
+ layer.layer_id for layer in self.layers
507
+ if layer.enriches(entity_name)
508
+ ]
509
+
510
+ graph.add_node(GraphNode(
511
+ id=node_id,
512
+ label="SharedEntity",
513
+ properties={
514
+ "name": entity_name,
515
+ "entity_type": entity_type,
516
+ "contributing_layers": contributing,
517
+ "seeded_at": datetime.now(timezone.utc).isoformat(),
518
+ },
519
+ ))
520
+
521
+ logger.info(
522
+ "Seeded shared entity '%s' (%s) in _shared namespace, layers: %s",
523
+ entity_name, entity_type, ", ".join(contributing) or "none",
524
+ )
525
+
526
+ return {
527
+ "namespace": namespace,
528
+ "node_id": node_id,
529
+ "contributing_layers": contributing,
530
+ }
531
+
532
+ def get_seeded_entities(self) -> List[Dict[str, Any]]:
533
+ """List all seeded entities with their contributing layers.
534
+
535
+ Scans the registry for graphs that contain a SeedManifest node.
536
+ """
537
+ results = []
538
+ graphs = self.registry.list_graphs()
539
+ for graph_info in graphs:
540
+ namespace = graph_info.get("name", "")
541
+ if not namespace or namespace.startswith("_"):
542
+ continue
543
+
544
+ graph = self.registry.get_graph(namespace, load_if_missing=False)
545
+ if graph is None:
546
+ continue
547
+
548
+ try:
549
+ manifests = graph.get_all_nodes(label="SeedManifest")
550
+ except Exception:
551
+ continue
552
+
553
+ for node in manifests:
554
+ props = node.properties or {}
555
+ results.append({
556
+ "entity": props.get("entity", namespace),
557
+ "namespace": namespace,
558
+ "contributing_layers": props.get("contributing_layers", []),
559
+ "llm_used": props.get("llm_used", False),
560
+ "estimated_signal_sources": props.get("estimated_signal_sources", 0),
561
+ "seeded_at": props.get("seeded_at", ""),
562
+ })
563
+
564
+ return results
565
+
566
+ # ------------------------------------------------------------------
567
+ # Internal: discovery
568
+ # ------------------------------------------------------------------
569
+
570
+ def _discover(
571
+ self,
572
+ entity_info: Dict[str, Any],
573
+ merged_layer_data: Dict[str, Any],
574
+ ) -> tuple:
575
+ """Attempt LLM discovery merged with layer data.
576
+
577
+ Returns:
578
+ (discovery_dict, llm_used_bool)
579
+ """
580
+ # Try LLM discovery if client available and any layer has a seed prompt
581
+ if self.llm_client:
582
+ seed_prompts = [
583
+ layer.seed_prompt_template
584
+ for layer in self.layers
585
+ if layer.seed_prompt_template
586
+ ]
587
+ if seed_prompts:
588
+ try:
589
+ llm_result = self._llm_discover(entity_info, seed_prompts)
590
+ if llm_result and isinstance(llm_result, dict):
591
+ # Merge LLM result with layer data (layer data takes priority for lists)
592
+ merged = dict(llm_result)
593
+ _merge_dicts(merged, merged_layer_data, source="layer_data")
594
+ logger.info(
595
+ "LLM discovery succeeded for '%s' (%d keys)",
596
+ entity_info["entity_name"],
597
+ len(merged),
598
+ )
599
+ return merged, True
600
+ except Exception as exc:
601
+ logger.warning(
602
+ "LLM discovery failed for '%s': %s — using layer data",
603
+ entity_info["entity_name"],
604
+ exc,
605
+ )
606
+
607
+ # Fallback: use merged layer data only
608
+ if merged_layer_data:
609
+ logger.info(
610
+ "Using layer data for '%s' (%d keys)",
611
+ entity_info["entity_name"],
612
+ len(merged_layer_data),
613
+ )
614
+ return merged_layer_data, False
615
+
616
+ # Minimal discovery
617
+ logger.info(
618
+ "No discovery data for '%s', using entity info only",
619
+ entity_info["entity_name"],
620
+ )
621
+ return {
622
+ "name": entity_info["entity_name"],
623
+ "entity_type": entity_info.get("entity_type", "unknown"),
624
+ "sector": entity_info.get("sector", "unknown"),
625
+ "ticker": entity_info.get("ticker", ""),
626
+ "people": [],
627
+ "brands": [],
628
+ "aliases": [],
629
+ "supply_chain_inputs": [],
630
+ "regulators": [],
631
+ "competitors": [],
632
+ "macro_dependencies": [],
633
+ }, False
634
+
635
+ def _llm_discover(
636
+ self,
637
+ entity_info: Dict[str, Any],
638
+ seed_prompts: List[str],
639
+ ) -> Dict[str, Any]:
640
+ """Call LLM with merged seed prompts from all layers."""
641
+ # Combine prompts from all layers
642
+ combined_prompt = "\n\n".join(seed_prompts)
643
+ for key, value in entity_info.items():
644
+ combined_prompt = combined_prompt.replace("{{ " + key + " }}", str(value))
645
+ combined_prompt = combined_prompt.replace("{{" + key + "}}", str(value))
646
+ combined_prompt = combined_prompt.replace("{" + key + "}", str(value))
647
+
648
+ system = (
649
+ "You are a multi-domain knowledge expert. "
650
+ "Return a JSON object with discovery data for the entity. "
651
+ "Include: people (key people with name+title), brands (subsidiaries/brands), "
652
+ "aliases (alternative names/tickers), supply_chain_inputs (upstream dependencies), "
653
+ "regulators (regulatory bodies), competitors (direct competitors), "
654
+ "macro_dependencies (macro factors), sector (industry sector), "
655
+ "key_entities (other relevant entities)."
656
+ )
657
+
658
+ return self.llm_client.generate_json(combined_prompt, system=system)
659
+
660
+ # ------------------------------------------------------------------
661
+ # Internal: schema merging
662
+ # ------------------------------------------------------------------
663
+
664
+ def _merge_schema(self, contributing_layer_ids: List[str]) -> Dict[str, Any]:
665
+ """Merge node and edge schemas from all contributing layers."""
666
+ node_types: List[Dict[str, Any]] = []
667
+ edge_types: List[Dict[str, Any]] = []
668
+ seen_node_types: set = set()
669
+ seen_edge_types: set = set()
670
+
671
+ for layer in self.layers:
672
+ if layer.layer_id not in contributing_layer_ids:
673
+ continue
674
+
675
+ for ns in layer.node_schemas:
676
+ if ns.type_name not in seen_node_types:
677
+ node_types.append(ns.to_dict())
678
+ seen_node_types.add(ns.type_name)
679
+
680
+ for es in layer.edge_schemas:
681
+ key = (es.edge_type, tuple(es.from_types), tuple(es.to_types))
682
+ if key not in seen_edge_types:
683
+ edge_types.append(es.to_dict())
684
+ seen_edge_types.add(key)
685
+
686
+ return {
687
+ "node_types": node_types,
688
+ "edge_types": edge_types,
689
+ "contributing_layers": list(contributing_layer_ids),
690
+ }
691
+
692
+ # ------------------------------------------------------------------
693
+ # Internal: dependency map
694
+ # ------------------------------------------------------------------
695
+
696
+ def _build_dependency_map(
697
+ self,
698
+ discovery: Dict[str, Any],
699
+ contributing_layer_ids: List[str],
700
+ ) -> Dict[str, List]:
701
+ """Extract dependency categories from discovery data + layer cross-edges."""
702
+ dep_map: Dict[str, List] = {
703
+ "supply_chain": [],
704
+ "regulatory": [],
705
+ "competitive": [],
706
+ "macro": [],
707
+ }
708
+
709
+ # From discovery data (same logic as before)
710
+ key_mapping = {
711
+ "supply_chain": ("supply_chain_inputs", "supply_chain", "inputs", "upstream"),
712
+ "regulatory": ("regulators", "regulatory_bodies", "regulatory"),
713
+ "competitive": ("competitors", "competition", "competitive"),
714
+ "macro": ("macro_dependencies", "macro_factors", "macro"),
715
+ }
716
+
717
+ for category, keys in key_mapping.items():
718
+ for key in keys:
719
+ items = discovery.get(key, [])
720
+ if items:
721
+ dep_map[category] = _normalize_list(items)
722
+ break
723
+
724
+ # Enrich with cross-layer edge definitions
725
+ for layer in self.layers:
726
+ if layer.layer_id not in contributing_layer_ids:
727
+ continue
728
+ for cle in layer.cross_layer_edges:
729
+ dep_entry = {
730
+ "name": cle.from_entity_type,
731
+ "edge_type": cle.edge_type,
732
+ "propagation_weight": cle.propagation_weight,
733
+ "description": cle.description,
734
+ "layer": layer.layer_id,
735
+ }
736
+ # Categorize the cross-layer edge
737
+ if cle.edge_type in ("DEPENDS_ON", "SUPPLIES_TO"):
738
+ dep_map["supply_chain"].append(dep_entry)
739
+ elif cle.edge_type in ("REGULATED_BY",):
740
+ dep_map["regulatory"].append(dep_entry)
741
+ elif cle.edge_type in ("COMPETES_WITH",):
742
+ dep_map["competitive"].append(dep_entry)
743
+ else:
744
+ dep_map["macro"].append(dep_entry)
745
+
746
+ return dep_map
747
+
748
+ # ------------------------------------------------------------------
749
+ # Internal: pipeline recommendations
750
+ # ------------------------------------------------------------------
751
+
752
+ def _generate_pipeline_recommendations(
753
+ self,
754
+ entity_name: str,
755
+ dependency_map: Dict[str, List],
756
+ sector: str,
757
+ contributing_layer_ids: List[str],
758
+ ) -> List[Dict[str, Any]]:
759
+ """Generate pipeline recommendations from dependencies."""
760
+ recommendations = []
761
+
762
+ category_config = {
763
+ "supply_chain": {
764
+ "source_type": "news",
765
+ "interval": "6h",
766
+ "priority": "high",
767
+ "why_template": "Supply chain disruption in {dep} directly impacts {entity}",
768
+ },
769
+ "regulatory": {
770
+ "source_type": "regulatory_filing",
771
+ "interval": "daily",
772
+ "priority": "high",
773
+ "why_template": "Regulatory actions by {dep} affect compliance posture of {entity}",
774
+ },
775
+ "competitive": {
776
+ "source_type": "news",
777
+ "interval": "12h",
778
+ "priority": "medium",
779
+ "why_template": "Competitive moves by {dep} affect market position of {entity}",
780
+ },
781
+ "macro": {
782
+ "source_type": "data_feed",
783
+ "interval": "daily",
784
+ "priority": "medium",
785
+ "why_template": "{dep} is a macro factor influencing {entity} performance",
786
+ },
787
+ }
788
+
789
+ for category, deps in dependency_map.items():
790
+ config = category_config.get(category, {
791
+ "source_type": "news",
792
+ "interval": "daily",
793
+ "priority": "low",
794
+ "why_template": "{dep} is related to {entity}",
795
+ })
796
+
797
+ for dep in deps:
798
+ dep_name = dep if isinstance(dep, str) else dep.get("name", str(dep))
799
+ dep_layer = "" if isinstance(dep, str) else dep.get("layer", "")
800
+ search_terms = [dep_name, entity_name]
801
+
802
+ recommendations.append({
803
+ "name": f"{_slugify(dep_name)}_{category}_pipeline",
804
+ "source_type": config["source_type"],
805
+ "interval": config["interval"],
806
+ "search_terms": search_terms,
807
+ "priority": config["priority"],
808
+ "why": config["why_template"].format(dep=dep_name, entity=entity_name),
809
+ "category": category,
810
+ "source_layer": dep_layer,
811
+ })
812
+
813
+ return recommendations
814
+
815
+ # ------------------------------------------------------------------
816
+ # Internal: sensor suggestions
817
+ # ------------------------------------------------------------------
818
+
819
+ def _generate_sensor_suggestions(
820
+ self,
821
+ entity_name: str,
822
+ sector: str,
823
+ contributing_layer_ids: List[str],
824
+ ) -> List[Dict[str, Any]]:
825
+ """Collect sensor suggestions from all contributing layers."""
826
+ suggestions = []
827
+
828
+ for layer in self.layers:
829
+ if layer.layer_id not in contributing_layer_ids:
830
+ continue
831
+
832
+ relevant_sensors = layer.get_sensors_for(entity_name, sector=sector)
833
+ for sensor in relevant_sensors:
834
+ suggestions.append({
835
+ "sensor": sensor.name,
836
+ "activate": True,
837
+ "reason": (
838
+ f"{sensor.description} — relevant to {entity_name} "
839
+ f"(from {layer.layer_id} layer)"
840
+ ),
841
+ "interval": sensor.interval,
842
+ "type": sensor.sensor_type,
843
+ "layer": layer.layer_id,
844
+ "weight": sensor.weight,
845
+ })
846
+
847
+ # Also include sensors from the layer that were NOT relevant,
848
+ # with activate=False for transparency
849
+ all_sensor_names = {s.name for s in layer.sensors}
850
+ relevant_names = {s.name for s in relevant_sensors}
851
+ for sensor in layer.sensors:
852
+ if sensor.name not in relevant_names:
853
+ suggestions.append({
854
+ "sensor": sensor.name,
855
+ "activate": False,
856
+ "reason": (
857
+ f"{sensor.name} has low relevance to {entity_name} "
858
+ f"— skip to save cost (from {layer.layer_id} layer)"
859
+ ),
860
+ "interval": sensor.interval,
861
+ "type": sensor.sensor_type,
862
+ "layer": layer.layer_id,
863
+ "weight": sensor.weight,
864
+ })
865
+
866
+ return suggestions
867
+
868
+ # ------------------------------------------------------------------
869
+ # Internal: cross-layer connections
870
+ # ------------------------------------------------------------------
871
+
872
+ def _find_cross_layer_connections(
873
+ self,
874
+ entity_name: str,
875
+ entity_type: str,
876
+ contributing_layer_ids: List[str],
877
+ ) -> List[Dict[str, Any]]:
878
+ """Identify cross-layer connections for this entity.
879
+
880
+ Looks at all cross_layer_edges from contributing layers and finds
881
+ shared entities that this entity should connect to.
882
+ """
883
+ connections = []
884
+ seen_shared: set = set()
885
+
886
+ for layer in self.layers:
887
+ if layer.layer_id not in contributing_layer_ids:
888
+ continue
889
+
890
+ for cle in layer.cross_layer_edges:
891
+ # If entity type matches the edge's to_entity_type,
892
+ # the from_entity_type is a shared entity to connect to
893
+ if cle.to_entity_type == entity_type or cle.to_entity_type in ("*", "any"):
894
+ shared_key = f"{cle.from_entity_type}:{cle.edge_type}"
895
+ if shared_key not in seen_shared:
896
+ connections.append({
897
+ "shared_entity": cle.from_entity_type,
898
+ "entity_type": cle.from_entity_type,
899
+ "edge_type": cle.edge_type,
900
+ "propagation_weight": cle.propagation_weight,
901
+ "description": cle.description,
902
+ "layers": [layer.layer_id],
903
+ })
904
+ seen_shared.add(shared_key)
905
+
906
+ # If entity type matches the edge's from_entity_type,
907
+ # the to_entity_type is downstream
908
+ if cle.from_entity_type == entity_type or cle.from_entity_type in ("*", "any"):
909
+ shared_key = f"{cle.to_entity_type}:{cle.edge_type}"
910
+ if shared_key not in seen_shared:
911
+ connections.append({
912
+ "shared_entity": cle.to_entity_type,
913
+ "entity_type": cle.to_entity_type,
914
+ "edge_type": cle.edge_type,
915
+ "propagation_weight": cle.propagation_weight,
916
+ "description": cle.description,
917
+ "layers": [layer.layer_id],
918
+ })
919
+ seen_shared.add(shared_key)
920
+
921
+ return connections
922
+
923
+ # ------------------------------------------------------------------
924
+ # Internal: layer discovery
925
+ # ------------------------------------------------------------------
926
+
927
+ def _discover_layers(self) -> List:
928
+ """Attempt to load layers via plugin discovery (best-effort)."""
929
+ try:
930
+ from contextsynapse.plugins.loader import discover_plugins
931
+ plugins = discover_plugins()
932
+ # Look for plugins that expose context layers
933
+ layers = []
934
+ for plugin in plugins:
935
+ if hasattr(plugin, "get_context_layers"):
936
+ layers.extend(plugin.get_context_layers())
937
+ return layers
938
+ except Exception as exc:
939
+ logger.debug("No layers discovered via plugins: %s", exc)
940
+ return []
941
+
942
+
943
+ # ---------------------------------------------------------------------------
944
+ # Helpers
945
+ # ---------------------------------------------------------------------------
946
+
947
+
948
+ def _slugify(text: str) -> str:
949
+ """Convert text to a URL/ID-safe slug."""
950
+ slug = text.lower().strip()
951
+ slug = re.sub(r"[^a-z0-9]+", "_", slug)
952
+ slug = slug.strip("_")
953
+ return slug or "entity"
954
+
955
+
956
+ def _normalize_list(items) -> List:
957
+ """Ensure items is a list of dicts or strings."""
958
+ if not isinstance(items, list):
959
+ return [items] if items else []
960
+ result = []
961
+ for item in items:
962
+ if isinstance(item, (str, dict)):
963
+ result.append(item)
964
+ else:
965
+ result.append(str(item))
966
+ return result
967
+
968
+
969
+ def _merge_dicts(
970
+ target: Dict[str, Any],
971
+ source: Dict[str, Any],
972
+ source_label: str = "",
973
+ ) -> None:
974
+ """Merge source into target, extending lists instead of overwriting."""
975
+ for key, value in source.items():
976
+ if key in target:
977
+ existing = target[key]
978
+ if isinstance(existing, list) and isinstance(value, list):
979
+ # Extend lists, avoiding exact duplicates
980
+ existing_set = {
981
+ json.dumps(v, sort_keys=True) if isinstance(v, dict) else str(v)
982
+ for v in existing
983
+ }
984
+ for v in value:
985
+ v_key = json.dumps(v, sort_keys=True) if isinstance(v, dict) else str(v)
986
+ if v_key not in existing_set:
987
+ existing.append(v)
988
+ elif isinstance(existing, dict) and isinstance(value, dict):
989
+ _merge_dicts(existing, value, source_label)
990
+ # For scalar values, keep the existing value (first layer wins)
991
+ else:
992
+ target[key] = value