kubiya-control-plane-api 0.9.15__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 (479) hide show
  1. control_plane_api/LICENSE +676 -0
  2. control_plane_api/README.md +350 -0
  3. control_plane_api/__init__.py +4 -0
  4. control_plane_api/__version__.py +8 -0
  5. control_plane_api/alembic/README +1 -0
  6. control_plane_api/alembic/env.py +121 -0
  7. control_plane_api/alembic/script.py.mako +28 -0
  8. control_plane_api/alembic/versions/2613c65c3dbe_initial_database_setup.py +32 -0
  9. control_plane_api/alembic/versions/2df520d4927d_merge_heads.py +28 -0
  10. control_plane_api/alembic/versions/43abf98d6a01_add_paused_status_to_executions.py +73 -0
  11. control_plane_api/alembic/versions/6289854264cb_merge_multiple_heads.py +28 -0
  12. control_plane_api/alembic/versions/6a4d4dc3d8dc_generate_execution_transitions.py +50 -0
  13. control_plane_api/alembic/versions/87d11cf0a783_add_disconnected_status_to_worker_.py +44 -0
  14. control_plane_api/alembic/versions/add_ephemeral_queue_support.py +85 -0
  15. control_plane_api/alembic/versions/add_model_type_to_llm_models.py +31 -0
  16. control_plane_api/alembic/versions/add_plan_executions_table.py +114 -0
  17. control_plane_api/alembic/versions/add_trace_span_tables.py +154 -0
  18. control_plane_api/alembic/versions/add_user_info_to_traces.py +36 -0
  19. control_plane_api/alembic/versions/adjusting_foreign_keys.py +32 -0
  20. control_plane_api/alembic/versions/b4983d976db2_initial_tables.py +1128 -0
  21. control_plane_api/alembic/versions/d181a3b40e71_rename_custom_metadata_to_metadata_in_.py +50 -0
  22. control_plane_api/alembic/versions/df9117888e82_add_missing_columns.py +82 -0
  23. control_plane_api/alembic/versions/f25de6ad895a_missing_migrations.py +34 -0
  24. control_plane_api/alembic/versions/f71305fb69b9_fix_ephemeral_queue_deletion_foreign_key.py +54 -0
  25. control_plane_api/alembic/versions/mark_local_exec_queues_as_ephemeral.py +68 -0
  26. control_plane_api/alembic.ini +148 -0
  27. control_plane_api/api/index.py +12 -0
  28. control_plane_api/app/__init__.py +11 -0
  29. control_plane_api/app/activities/__init__.py +20 -0
  30. control_plane_api/app/activities/agent_activities.py +384 -0
  31. control_plane_api/app/activities/plan_generation_activities.py +499 -0
  32. control_plane_api/app/activities/team_activities.py +424 -0
  33. control_plane_api/app/activities/temporal_cloud_activities.py +588 -0
  34. control_plane_api/app/config/__init__.py +35 -0
  35. control_plane_api/app/config/api_config.py +469 -0
  36. control_plane_api/app/config/config_loader.py +224 -0
  37. control_plane_api/app/config/model_pricing.py +323 -0
  38. control_plane_api/app/config/storage_config.py +159 -0
  39. control_plane_api/app/config.py +115 -0
  40. control_plane_api/app/controllers/__init__.py +0 -0
  41. control_plane_api/app/controllers/execution_environment_controller.py +1315 -0
  42. control_plane_api/app/database.py +135 -0
  43. control_plane_api/app/exceptions.py +408 -0
  44. control_plane_api/app/lib/__init__.py +11 -0
  45. control_plane_api/app/lib/environment.py +65 -0
  46. control_plane_api/app/lib/event_bus/__init__.py +17 -0
  47. control_plane_api/app/lib/event_bus/base.py +136 -0
  48. control_plane_api/app/lib/event_bus/manager.py +335 -0
  49. control_plane_api/app/lib/event_bus/providers/__init__.py +6 -0
  50. control_plane_api/app/lib/event_bus/providers/http_provider.py +166 -0
  51. control_plane_api/app/lib/event_bus/providers/nats_provider.py +324 -0
  52. control_plane_api/app/lib/event_bus/providers/redis_provider.py +233 -0
  53. control_plane_api/app/lib/event_bus/providers/websocket_provider.py +497 -0
  54. control_plane_api/app/lib/job_executor.py +330 -0
  55. control_plane_api/app/lib/kubiya_client.py +293 -0
  56. control_plane_api/app/lib/litellm_pricing.py +166 -0
  57. control_plane_api/app/lib/mcp_validation.py +163 -0
  58. control_plane_api/app/lib/nats/__init__.py +13 -0
  59. control_plane_api/app/lib/nats/credentials_manager.py +288 -0
  60. control_plane_api/app/lib/nats/listener.py +374 -0
  61. control_plane_api/app/lib/planning_prompt_builder.py +153 -0
  62. control_plane_api/app/lib/planning_tools/__init__.py +41 -0
  63. control_plane_api/app/lib/planning_tools/agents.py +409 -0
  64. control_plane_api/app/lib/planning_tools/agno_toolkit.py +836 -0
  65. control_plane_api/app/lib/planning_tools/base.py +119 -0
  66. control_plane_api/app/lib/planning_tools/cognitive_memory_tools.py +403 -0
  67. control_plane_api/app/lib/planning_tools/context_graph_tools.py +545 -0
  68. control_plane_api/app/lib/planning_tools/environments.py +218 -0
  69. control_plane_api/app/lib/planning_tools/knowledge.py +204 -0
  70. control_plane_api/app/lib/planning_tools/models.py +93 -0
  71. control_plane_api/app/lib/planning_tools/planning_service.py +646 -0
  72. control_plane_api/app/lib/planning_tools/resources.py +242 -0
  73. control_plane_api/app/lib/planning_tools/teams.py +334 -0
  74. control_plane_api/app/lib/policy_enforcer_client.py +1016 -0
  75. control_plane_api/app/lib/redis_client.py +803 -0
  76. control_plane_api/app/lib/sqlalchemy_utils.py +486 -0
  77. control_plane_api/app/lib/state_transition_tools/__init__.py +7 -0
  78. control_plane_api/app/lib/state_transition_tools/execution_context.py +388 -0
  79. control_plane_api/app/lib/storage/__init__.py +20 -0
  80. control_plane_api/app/lib/storage/base_provider.py +274 -0
  81. control_plane_api/app/lib/storage/provider_factory.py +157 -0
  82. control_plane_api/app/lib/storage/vercel_blob_provider.py +468 -0
  83. control_plane_api/app/lib/supabase.py +71 -0
  84. control_plane_api/app/lib/supabase_utils.py +138 -0
  85. control_plane_api/app/lib/task_planning/__init__.py +138 -0
  86. control_plane_api/app/lib/task_planning/agent_factory.py +308 -0
  87. control_plane_api/app/lib/task_planning/agents.py +389 -0
  88. control_plane_api/app/lib/task_planning/cache.py +218 -0
  89. control_plane_api/app/lib/task_planning/entity_resolver.py +273 -0
  90. control_plane_api/app/lib/task_planning/helpers.py +293 -0
  91. control_plane_api/app/lib/task_planning/hooks.py +474 -0
  92. control_plane_api/app/lib/task_planning/models.py +503 -0
  93. control_plane_api/app/lib/task_planning/plan_validator.py +166 -0
  94. control_plane_api/app/lib/task_planning/planning_workflow.py +2911 -0
  95. control_plane_api/app/lib/task_planning/runner.py +656 -0
  96. control_plane_api/app/lib/task_planning/streaming_hook.py +213 -0
  97. control_plane_api/app/lib/task_planning/workflow.py +424 -0
  98. control_plane_api/app/lib/templating/__init__.py +88 -0
  99. control_plane_api/app/lib/templating/compiler.py +278 -0
  100. control_plane_api/app/lib/templating/engine.py +178 -0
  101. control_plane_api/app/lib/templating/parsers/__init__.py +29 -0
  102. control_plane_api/app/lib/templating/parsers/base.py +96 -0
  103. control_plane_api/app/lib/templating/parsers/env.py +85 -0
  104. control_plane_api/app/lib/templating/parsers/graph.py +112 -0
  105. control_plane_api/app/lib/templating/parsers/secret.py +87 -0
  106. control_plane_api/app/lib/templating/parsers/simple.py +81 -0
  107. control_plane_api/app/lib/templating/resolver.py +366 -0
  108. control_plane_api/app/lib/templating/types.py +214 -0
  109. control_plane_api/app/lib/templating/validator.py +201 -0
  110. control_plane_api/app/lib/temporal_client.py +232 -0
  111. control_plane_api/app/lib/temporal_credentials_cache.py +178 -0
  112. control_plane_api/app/lib/temporal_credentials_service.py +203 -0
  113. control_plane_api/app/lib/validation/__init__.py +24 -0
  114. control_plane_api/app/lib/validation/runtime_validation.py +388 -0
  115. control_plane_api/app/main.py +531 -0
  116. control_plane_api/app/middleware/__init__.py +10 -0
  117. control_plane_api/app/middleware/auth.py +645 -0
  118. control_plane_api/app/middleware/exception_handler.py +267 -0
  119. control_plane_api/app/middleware/prometheus_middleware.py +173 -0
  120. control_plane_api/app/middleware/rate_limiting.py +384 -0
  121. control_plane_api/app/middleware/request_id.py +202 -0
  122. control_plane_api/app/models/__init__.py +40 -0
  123. control_plane_api/app/models/agent.py +90 -0
  124. control_plane_api/app/models/analytics.py +206 -0
  125. control_plane_api/app/models/associations.py +107 -0
  126. control_plane_api/app/models/auth_user.py +73 -0
  127. control_plane_api/app/models/context.py +161 -0
  128. control_plane_api/app/models/custom_integration.py +99 -0
  129. control_plane_api/app/models/environment.py +64 -0
  130. control_plane_api/app/models/execution.py +125 -0
  131. control_plane_api/app/models/execution_transition.py +50 -0
  132. control_plane_api/app/models/job.py +159 -0
  133. control_plane_api/app/models/llm_model.py +78 -0
  134. control_plane_api/app/models/orchestration.py +66 -0
  135. control_plane_api/app/models/plan_execution.py +102 -0
  136. control_plane_api/app/models/presence.py +49 -0
  137. control_plane_api/app/models/project.py +61 -0
  138. control_plane_api/app/models/project_management.py +85 -0
  139. control_plane_api/app/models/session.py +29 -0
  140. control_plane_api/app/models/skill.py +155 -0
  141. control_plane_api/app/models/system_tables.py +43 -0
  142. control_plane_api/app/models/task_planning.py +372 -0
  143. control_plane_api/app/models/team.py +86 -0
  144. control_plane_api/app/models/trace.py +257 -0
  145. control_plane_api/app/models/user_profile.py +54 -0
  146. control_plane_api/app/models/worker.py +221 -0
  147. control_plane_api/app/models/workflow.py +161 -0
  148. control_plane_api/app/models/workspace.py +50 -0
  149. control_plane_api/app/observability/__init__.py +177 -0
  150. control_plane_api/app/observability/context_logging.py +475 -0
  151. control_plane_api/app/observability/decorators.py +337 -0
  152. control_plane_api/app/observability/local_span_processor.py +702 -0
  153. control_plane_api/app/observability/metrics.py +303 -0
  154. control_plane_api/app/observability/middleware.py +246 -0
  155. control_plane_api/app/observability/optional.py +115 -0
  156. control_plane_api/app/observability/tracing.py +382 -0
  157. control_plane_api/app/policies/README.md +149 -0
  158. control_plane_api/app/policies/approved_users.rego +62 -0
  159. control_plane_api/app/policies/business_hours.rego +51 -0
  160. control_plane_api/app/policies/rate_limiting.rego +100 -0
  161. control_plane_api/app/policies/tool_enforcement/README.md +336 -0
  162. control_plane_api/app/policies/tool_enforcement/bash_command_validation.rego +71 -0
  163. control_plane_api/app/policies/tool_enforcement/business_hours_enforcement.rego +82 -0
  164. control_plane_api/app/policies/tool_enforcement/mcp_tool_allowlist.rego +58 -0
  165. control_plane_api/app/policies/tool_enforcement/production_safeguards.rego +80 -0
  166. control_plane_api/app/policies/tool_enforcement/role_based_tool_access.rego +44 -0
  167. control_plane_api/app/policies/tool_restrictions.rego +86 -0
  168. control_plane_api/app/routers/__init__.py +4 -0
  169. control_plane_api/app/routers/agents.py +382 -0
  170. control_plane_api/app/routers/agents_v2.py +1598 -0
  171. control_plane_api/app/routers/analytics.py +1310 -0
  172. control_plane_api/app/routers/auth.py +59 -0
  173. control_plane_api/app/routers/client_config.py +57 -0
  174. control_plane_api/app/routers/context_graph.py +561 -0
  175. control_plane_api/app/routers/context_manager.py +577 -0
  176. control_plane_api/app/routers/custom_integrations.py +490 -0
  177. control_plane_api/app/routers/enforcer.py +132 -0
  178. control_plane_api/app/routers/environment_context.py +252 -0
  179. control_plane_api/app/routers/environments.py +761 -0
  180. control_plane_api/app/routers/execution_environment.py +847 -0
  181. control_plane_api/app/routers/executions/__init__.py +28 -0
  182. control_plane_api/app/routers/executions/router.py +286 -0
  183. control_plane_api/app/routers/executions/services/__init__.py +22 -0
  184. control_plane_api/app/routers/executions/services/demo_worker_health.py +156 -0
  185. control_plane_api/app/routers/executions/services/status_service.py +420 -0
  186. control_plane_api/app/routers/executions/services/test_worker_health.py +480 -0
  187. control_plane_api/app/routers/executions/services/worker_health.py +514 -0
  188. control_plane_api/app/routers/executions/streaming/__init__.py +22 -0
  189. control_plane_api/app/routers/executions/streaming/deduplication.py +352 -0
  190. control_plane_api/app/routers/executions/streaming/event_buffer.py +353 -0
  191. control_plane_api/app/routers/executions/streaming/event_formatter.py +964 -0
  192. control_plane_api/app/routers/executions/streaming/history_loader.py +588 -0
  193. control_plane_api/app/routers/executions/streaming/live_source.py +693 -0
  194. control_plane_api/app/routers/executions/streaming/streamer.py +849 -0
  195. control_plane_api/app/routers/executions.py +4888 -0
  196. control_plane_api/app/routers/health.py +165 -0
  197. control_plane_api/app/routers/health_v2.py +394 -0
  198. control_plane_api/app/routers/integration_templates.py +496 -0
  199. control_plane_api/app/routers/integrations.py +287 -0
  200. control_plane_api/app/routers/jobs.py +1809 -0
  201. control_plane_api/app/routers/metrics.py +517 -0
  202. control_plane_api/app/routers/models.py +82 -0
  203. control_plane_api/app/routers/models_v2.py +628 -0
  204. control_plane_api/app/routers/plan_executions.py +1481 -0
  205. control_plane_api/app/routers/plan_generation_async.py +304 -0
  206. control_plane_api/app/routers/policies.py +669 -0
  207. control_plane_api/app/routers/presence.py +234 -0
  208. control_plane_api/app/routers/projects.py +987 -0
  209. control_plane_api/app/routers/runners.py +379 -0
  210. control_plane_api/app/routers/runtimes.py +172 -0
  211. control_plane_api/app/routers/secrets.py +171 -0
  212. control_plane_api/app/routers/skills.py +1010 -0
  213. control_plane_api/app/routers/skills_definitions.py +140 -0
  214. control_plane_api/app/routers/storage.py +456 -0
  215. control_plane_api/app/routers/task_planning.py +611 -0
  216. control_plane_api/app/routers/task_queues.py +650 -0
  217. control_plane_api/app/routers/team_context.py +274 -0
  218. control_plane_api/app/routers/teams.py +1747 -0
  219. control_plane_api/app/routers/templates.py +248 -0
  220. control_plane_api/app/routers/traces.py +571 -0
  221. control_plane_api/app/routers/websocket_client.py +479 -0
  222. control_plane_api/app/routers/websocket_executions_status.py +437 -0
  223. control_plane_api/app/routers/websocket_gateway.py +323 -0
  224. control_plane_api/app/routers/websocket_traces.py +576 -0
  225. control_plane_api/app/routers/worker_queues.py +2555 -0
  226. control_plane_api/app/routers/worker_websocket.py +419 -0
  227. control_plane_api/app/routers/workers.py +1004 -0
  228. control_plane_api/app/routers/workflows.py +204 -0
  229. control_plane_api/app/runtimes/__init__.py +6 -0
  230. control_plane_api/app/runtimes/validation.py +344 -0
  231. control_plane_api/app/schemas/__init__.py +1 -0
  232. control_plane_api/app/schemas/job_schemas.py +302 -0
  233. control_plane_api/app/schemas/mcp_schemas.py +311 -0
  234. control_plane_api/app/schemas/template_schemas.py +133 -0
  235. control_plane_api/app/schemas/trace_schemas.py +168 -0
  236. control_plane_api/app/schemas/worker_queue_observability_schemas.py +165 -0
  237. control_plane_api/app/services/__init__.py +1 -0
  238. control_plane_api/app/services/agno_planning_strategy.py +233 -0
  239. control_plane_api/app/services/agno_service.py +838 -0
  240. control_plane_api/app/services/claude_code_planning_service.py +203 -0
  241. control_plane_api/app/services/context_graph_client.py +224 -0
  242. control_plane_api/app/services/custom_integration_service.py +415 -0
  243. control_plane_api/app/services/integration_resolution_service.py +345 -0
  244. control_plane_api/app/services/litellm_service.py +394 -0
  245. control_plane_api/app/services/plan_generator.py +79 -0
  246. control_plane_api/app/services/planning_strategy.py +66 -0
  247. control_plane_api/app/services/planning_strategy_factory.py +118 -0
  248. control_plane_api/app/services/policy_service.py +615 -0
  249. control_plane_api/app/services/state_transition_service.py +755 -0
  250. control_plane_api/app/services/storage_service.py +593 -0
  251. control_plane_api/app/services/temporal_cloud_provisioning.py +150 -0
  252. control_plane_api/app/services/toolsets/context_graph_skill.py +432 -0
  253. control_plane_api/app/services/trace_retention.py +354 -0
  254. control_plane_api/app/services/worker_queue_metrics_service.py +190 -0
  255. control_plane_api/app/services/workflow_cancellation_manager.py +135 -0
  256. control_plane_api/app/services/workflow_operations_service.py +611 -0
  257. control_plane_api/app/skills/__init__.py +100 -0
  258. control_plane_api/app/skills/base.py +239 -0
  259. control_plane_api/app/skills/builtin/__init__.py +37 -0
  260. control_plane_api/app/skills/builtin/agent_communication/__init__.py +8 -0
  261. control_plane_api/app/skills/builtin/agent_communication/skill.py +246 -0
  262. control_plane_api/app/skills/builtin/code_ingestion/__init__.py +4 -0
  263. control_plane_api/app/skills/builtin/code_ingestion/skill.py +267 -0
  264. control_plane_api/app/skills/builtin/cognitive_memory/__init__.py +4 -0
  265. control_plane_api/app/skills/builtin/cognitive_memory/skill.py +174 -0
  266. control_plane_api/app/skills/builtin/contextual_awareness/__init__.py +4 -0
  267. control_plane_api/app/skills/builtin/contextual_awareness/skill.py +387 -0
  268. control_plane_api/app/skills/builtin/data_visualization/__init__.py +4 -0
  269. control_plane_api/app/skills/builtin/data_visualization/skill.py +154 -0
  270. control_plane_api/app/skills/builtin/docker/__init__.py +4 -0
  271. control_plane_api/app/skills/builtin/docker/skill.py +104 -0
  272. control_plane_api/app/skills/builtin/file_generation/__init__.py +4 -0
  273. control_plane_api/app/skills/builtin/file_generation/skill.py +94 -0
  274. control_plane_api/app/skills/builtin/file_system/__init__.py +4 -0
  275. control_plane_api/app/skills/builtin/file_system/skill.py +110 -0
  276. control_plane_api/app/skills/builtin/knowledge_api/__init__.py +5 -0
  277. control_plane_api/app/skills/builtin/knowledge_api/skill.py +124 -0
  278. control_plane_api/app/skills/builtin/python/__init__.py +4 -0
  279. control_plane_api/app/skills/builtin/python/skill.py +92 -0
  280. control_plane_api/app/skills/builtin/remote_filesystem/__init__.py +5 -0
  281. control_plane_api/app/skills/builtin/remote_filesystem/skill.py +170 -0
  282. control_plane_api/app/skills/builtin/shell/__init__.py +4 -0
  283. control_plane_api/app/skills/builtin/shell/skill.py +161 -0
  284. control_plane_api/app/skills/builtin/slack/__init__.py +3 -0
  285. control_plane_api/app/skills/builtin/slack/skill.py +302 -0
  286. control_plane_api/app/skills/builtin/workflow_executor/__init__.py +4 -0
  287. control_plane_api/app/skills/builtin/workflow_executor/skill.py +469 -0
  288. control_plane_api/app/skills/business_intelligence.py +189 -0
  289. control_plane_api/app/skills/config.py +63 -0
  290. control_plane_api/app/skills/loaders/__init__.py +14 -0
  291. control_plane_api/app/skills/loaders/base.py +73 -0
  292. control_plane_api/app/skills/loaders/filesystem_loader.py +199 -0
  293. control_plane_api/app/skills/registry.py +125 -0
  294. control_plane_api/app/utils/helpers.py +12 -0
  295. control_plane_api/app/utils/workflow_executor.py +354 -0
  296. control_plane_api/app/workflows/__init__.py +11 -0
  297. control_plane_api/app/workflows/agent_execution.py +520 -0
  298. control_plane_api/app/workflows/agent_execution_with_skills.py +223 -0
  299. control_plane_api/app/workflows/namespace_provisioning.py +326 -0
  300. control_plane_api/app/workflows/plan_generation.py +254 -0
  301. control_plane_api/app/workflows/team_execution.py +442 -0
  302. control_plane_api/scripts/seed_models.py +240 -0
  303. control_plane_api/scripts/validate_existing_tool_names.py +492 -0
  304. control_plane_api/shared/__init__.py +8 -0
  305. control_plane_api/shared/version.py +17 -0
  306. control_plane_api/test_deduplication.py +274 -0
  307. control_plane_api/test_executor_deduplication_e2e.py +309 -0
  308. control_plane_api/test_job_execution_e2e.py +283 -0
  309. control_plane_api/test_real_integration.py +193 -0
  310. control_plane_api/version.py +38 -0
  311. control_plane_api/worker/__init__.py +0 -0
  312. control_plane_api/worker/activities/__init__.py +0 -0
  313. control_plane_api/worker/activities/agent_activities.py +1585 -0
  314. control_plane_api/worker/activities/approval_activities.py +234 -0
  315. control_plane_api/worker/activities/job_activities.py +199 -0
  316. control_plane_api/worker/activities/runtime_activities.py +1167 -0
  317. control_plane_api/worker/activities/skill_activities.py +282 -0
  318. control_plane_api/worker/activities/team_activities.py +479 -0
  319. control_plane_api/worker/agent_runtime_server.py +370 -0
  320. control_plane_api/worker/binary_manager.py +333 -0
  321. control_plane_api/worker/config/__init__.py +31 -0
  322. control_plane_api/worker/config/worker_config.py +273 -0
  323. control_plane_api/worker/control_plane_client.py +1491 -0
  324. control_plane_api/worker/examples/analytics_integration_example.py +362 -0
  325. control_plane_api/worker/health_monitor.py +159 -0
  326. control_plane_api/worker/metrics.py +237 -0
  327. control_plane_api/worker/models/__init__.py +1 -0
  328. control_plane_api/worker/models/error_events.py +105 -0
  329. control_plane_api/worker/models/inputs.py +89 -0
  330. control_plane_api/worker/runtimes/__init__.py +35 -0
  331. control_plane_api/worker/runtimes/agent_runtime/runtime.py +485 -0
  332. control_plane_api/worker/runtimes/agno/__init__.py +34 -0
  333. control_plane_api/worker/runtimes/agno/config.py +248 -0
  334. control_plane_api/worker/runtimes/agno/hooks.py +385 -0
  335. control_plane_api/worker/runtimes/agno/mcp_builder.py +195 -0
  336. control_plane_api/worker/runtimes/agno/runtime.py +1063 -0
  337. control_plane_api/worker/runtimes/agno/utils.py +163 -0
  338. control_plane_api/worker/runtimes/base.py +979 -0
  339. control_plane_api/worker/runtimes/claude_code/__init__.py +38 -0
  340. control_plane_api/worker/runtimes/claude_code/cleanup.py +184 -0
  341. control_plane_api/worker/runtimes/claude_code/client_pool.py +529 -0
  342. control_plane_api/worker/runtimes/claude_code/config.py +829 -0
  343. control_plane_api/worker/runtimes/claude_code/hooks.py +482 -0
  344. control_plane_api/worker/runtimes/claude_code/litellm_proxy.py +1702 -0
  345. control_plane_api/worker/runtimes/claude_code/mcp_builder.py +467 -0
  346. control_plane_api/worker/runtimes/claude_code/mcp_discovery.py +558 -0
  347. control_plane_api/worker/runtimes/claude_code/runtime.py +1546 -0
  348. control_plane_api/worker/runtimes/claude_code/tool_mapper.py +403 -0
  349. control_plane_api/worker/runtimes/claude_code/utils.py +149 -0
  350. control_plane_api/worker/runtimes/factory.py +173 -0
  351. control_plane_api/worker/runtimes/model_utils.py +107 -0
  352. control_plane_api/worker/runtimes/validation.py +93 -0
  353. control_plane_api/worker/services/__init__.py +1 -0
  354. control_plane_api/worker/services/agent_communication_tools.py +908 -0
  355. control_plane_api/worker/services/agent_executor.py +485 -0
  356. control_plane_api/worker/services/agent_executor_v2.py +793 -0
  357. control_plane_api/worker/services/analytics_collector.py +457 -0
  358. control_plane_api/worker/services/analytics_service.py +464 -0
  359. control_plane_api/worker/services/approval_tools.py +310 -0
  360. control_plane_api/worker/services/approval_tools_agno.py +207 -0
  361. control_plane_api/worker/services/cancellation_manager.py +177 -0
  362. control_plane_api/worker/services/code_ingestion_tools.py +465 -0
  363. control_plane_api/worker/services/contextual_awareness_tools.py +405 -0
  364. control_plane_api/worker/services/data_visualization.py +834 -0
  365. control_plane_api/worker/services/event_publisher.py +531 -0
  366. control_plane_api/worker/services/jira_tools.py +257 -0
  367. control_plane_api/worker/services/remote_filesystem_tools.py +498 -0
  368. control_plane_api/worker/services/runtime_analytics.py +328 -0
  369. control_plane_api/worker/services/session_service.py +365 -0
  370. control_plane_api/worker/services/skill_context_enhancement.py +181 -0
  371. control_plane_api/worker/services/skill_factory.py +471 -0
  372. control_plane_api/worker/services/system_prompt_enhancement.py +410 -0
  373. control_plane_api/worker/services/team_executor.py +715 -0
  374. control_plane_api/worker/services/team_executor_v2.py +1866 -0
  375. control_plane_api/worker/services/tool_enforcement.py +254 -0
  376. control_plane_api/worker/services/workflow_executor/__init__.py +52 -0
  377. control_plane_api/worker/services/workflow_executor/event_processor.py +287 -0
  378. control_plane_api/worker/services/workflow_executor/event_publisher.py +210 -0
  379. control_plane_api/worker/services/workflow_executor/executors/__init__.py +15 -0
  380. control_plane_api/worker/services/workflow_executor/executors/base.py +270 -0
  381. control_plane_api/worker/services/workflow_executor/executors/json_executor.py +50 -0
  382. control_plane_api/worker/services/workflow_executor/executors/python_executor.py +50 -0
  383. control_plane_api/worker/services/workflow_executor/models.py +142 -0
  384. control_plane_api/worker/services/workflow_executor_tools.py +1748 -0
  385. control_plane_api/worker/skills/__init__.py +12 -0
  386. control_plane_api/worker/skills/builtin/context_graph_search/README.md +213 -0
  387. control_plane_api/worker/skills/builtin/context_graph_search/__init__.py +5 -0
  388. control_plane_api/worker/skills/builtin/context_graph_search/agno_impl.py +808 -0
  389. control_plane_api/worker/skills/builtin/context_graph_search/skill.yaml +67 -0
  390. control_plane_api/worker/skills/builtin/contextual_awareness/__init__.py +4 -0
  391. control_plane_api/worker/skills/builtin/contextual_awareness/agno_impl.py +62 -0
  392. control_plane_api/worker/skills/builtin/data_visualization/agno_impl.py +18 -0
  393. control_plane_api/worker/skills/builtin/data_visualization/skill.yaml +84 -0
  394. control_plane_api/worker/skills/builtin/docker/agno_impl.py +65 -0
  395. control_plane_api/worker/skills/builtin/docker/skill.yaml +60 -0
  396. control_plane_api/worker/skills/builtin/file_generation/agno_impl.py +47 -0
  397. control_plane_api/worker/skills/builtin/file_generation/skill.yaml +64 -0
  398. control_plane_api/worker/skills/builtin/file_system/agno_impl.py +32 -0
  399. control_plane_api/worker/skills/builtin/file_system/skill.yaml +54 -0
  400. control_plane_api/worker/skills/builtin/knowledge_api/__init__.py +4 -0
  401. control_plane_api/worker/skills/builtin/knowledge_api/agno_impl.py +50 -0
  402. control_plane_api/worker/skills/builtin/knowledge_api/skill.yaml +66 -0
  403. control_plane_api/worker/skills/builtin/python/agno_impl.py +25 -0
  404. control_plane_api/worker/skills/builtin/python/skill.yaml +60 -0
  405. control_plane_api/worker/skills/builtin/schema_fix_mixin.py +260 -0
  406. control_plane_api/worker/skills/builtin/shell/agno_impl.py +31 -0
  407. control_plane_api/worker/skills/builtin/shell/skill.yaml +60 -0
  408. control_plane_api/worker/skills/builtin/slack/__init__.py +3 -0
  409. control_plane_api/worker/skills/builtin/slack/agno_impl.py +1282 -0
  410. control_plane_api/worker/skills/builtin/slack/skill.yaml +276 -0
  411. control_plane_api/worker/skills/builtin/workflow_executor/agno_impl.py +62 -0
  412. control_plane_api/worker/skills/builtin/workflow_executor/skill.yaml +79 -0
  413. control_plane_api/worker/skills/loaders/__init__.py +5 -0
  414. control_plane_api/worker/skills/loaders/base.py +23 -0
  415. control_plane_api/worker/skills/loaders/filesystem_loader.py +357 -0
  416. control_plane_api/worker/skills/registry.py +208 -0
  417. control_plane_api/worker/tests/__init__.py +1 -0
  418. control_plane_api/worker/tests/conftest.py +12 -0
  419. control_plane_api/worker/tests/e2e/__init__.py +0 -0
  420. control_plane_api/worker/tests/e2e/test_context_graph_real_api.py +338 -0
  421. control_plane_api/worker/tests/e2e/test_context_graph_templates_e2e.py +523 -0
  422. control_plane_api/worker/tests/e2e/test_enforcement_e2e.py +344 -0
  423. control_plane_api/worker/tests/e2e/test_execution_flow.py +571 -0
  424. control_plane_api/worker/tests/e2e/test_single_execution_mode.py +656 -0
  425. control_plane_api/worker/tests/integration/__init__.py +0 -0
  426. control_plane_api/worker/tests/integration/test_builtin_skills_fixes.py +245 -0
  427. control_plane_api/worker/tests/integration/test_context_graph_search_integration.py +365 -0
  428. control_plane_api/worker/tests/integration/test_control_plane_integration.py +308 -0
  429. control_plane_api/worker/tests/integration/test_hook_enforcement_integration.py +579 -0
  430. control_plane_api/worker/tests/integration/test_scheduled_job_workflow.py +237 -0
  431. control_plane_api/worker/tests/integration/test_system_prompt_enhancement_integration.py +343 -0
  432. control_plane_api/worker/tests/unit/__init__.py +0 -0
  433. control_plane_api/worker/tests/unit/test_builtin_skill_autoload.py +396 -0
  434. control_plane_api/worker/tests/unit/test_context_graph_search.py +450 -0
  435. control_plane_api/worker/tests/unit/test_context_graph_templates.py +403 -0
  436. control_plane_api/worker/tests/unit/test_control_plane_client.py +401 -0
  437. control_plane_api/worker/tests/unit/test_control_plane_client_jobs.py +345 -0
  438. control_plane_api/worker/tests/unit/test_job_activities.py +353 -0
  439. control_plane_api/worker/tests/unit/test_skill_context_enhancement.py +321 -0
  440. control_plane_api/worker/tests/unit/test_system_prompt_enhancement.py +415 -0
  441. control_plane_api/worker/tests/unit/test_tool_enforcement.py +324 -0
  442. control_plane_api/worker/utils/__init__.py +1 -0
  443. control_plane_api/worker/utils/chunk_batcher.py +330 -0
  444. control_plane_api/worker/utils/environment.py +65 -0
  445. control_plane_api/worker/utils/error_publisher.py +260 -0
  446. control_plane_api/worker/utils/event_batcher.py +256 -0
  447. control_plane_api/worker/utils/logging_config.py +335 -0
  448. control_plane_api/worker/utils/logging_helper.py +326 -0
  449. control_plane_api/worker/utils/parameter_validator.py +120 -0
  450. control_plane_api/worker/utils/retry_utils.py +60 -0
  451. control_plane_api/worker/utils/streaming_utils.py +665 -0
  452. control_plane_api/worker/utils/tool_validation.py +332 -0
  453. control_plane_api/worker/utils/workspace_manager.py +163 -0
  454. control_plane_api/worker/websocket_client.py +393 -0
  455. control_plane_api/worker/worker.py +1297 -0
  456. control_plane_api/worker/workflows/__init__.py +0 -0
  457. control_plane_api/worker/workflows/agent_execution.py +909 -0
  458. control_plane_api/worker/workflows/scheduled_job_wrapper.py +332 -0
  459. control_plane_api/worker/workflows/team_execution.py +611 -0
  460. kubiya_control_plane_api-0.9.15.dist-info/METADATA +354 -0
  461. kubiya_control_plane_api-0.9.15.dist-info/RECORD +479 -0
  462. kubiya_control_plane_api-0.9.15.dist-info/WHEEL +5 -0
  463. kubiya_control_plane_api-0.9.15.dist-info/entry_points.txt +5 -0
  464. kubiya_control_plane_api-0.9.15.dist-info/licenses/LICENSE +676 -0
  465. kubiya_control_plane_api-0.9.15.dist-info/top_level.txt +3 -0
  466. scripts/__init__.py +1 -0
  467. scripts/migrations.py +39 -0
  468. scripts/seed_worker_queues.py +128 -0
  469. scripts/setup_agent_runtime.py +142 -0
  470. worker_internal/__init__.py +1 -0
  471. worker_internal/planner/__init__.py +1 -0
  472. worker_internal/planner/activities.py +1499 -0
  473. worker_internal/planner/agent_tools.py +197 -0
  474. worker_internal/planner/event_models.py +148 -0
  475. worker_internal/planner/event_publisher.py +67 -0
  476. worker_internal/planner/models.py +199 -0
  477. worker_internal/planner/retry_logic.py +134 -0
  478. worker_internal/planner/worker.py +300 -0
  479. worker_internal/planner/workflows.py +970 -0
@@ -0,0 +1,834 @@
1
+ """
2
+ Data Visualization Tools for Agent Control Plane Worker
3
+
4
+ This module provides tools for agents to create diagrams and visualizations
5
+ using Mermaid syntax. The tools emit special events that the UI can parse
6
+ and render as interactive diagrams.
7
+
8
+ Event Format:
9
+ The tool emits events in the following format:
10
+
11
+ <<DIAGRAM_START>>
12
+ ```mermaid
13
+ [mermaid diagram code]
14
+ ```
15
+ <<DIAGRAM_END>>
16
+
17
+ This format allows the UI to:
18
+ 1. Detect diagram events via <<DIAGRAM_START>> and <<DIAGRAM_END>> markers
19
+ 2. Extract the Mermaid syntax between the markers
20
+ 3. Render the diagram using a Mermaid renderer component
21
+ """
22
+
23
+ import json
24
+ import re
25
+ from typing import Optional, Callable, Any, Dict, List
26
+ from agno.tools import Toolkit
27
+ from control_plane_api.worker.skills.builtin.schema_fix_mixin import SchemaFixMixin
28
+
29
+ import structlog
30
+
31
+ logger = structlog.get_logger(__name__)
32
+
33
+
34
+ # Mermaid syntax validation patterns
35
+ MERMAID_DIAGRAM_TYPES = {
36
+ 'flowchart': r'^flowchart\s+(TD|TB|BT|RL|LR)',
37
+ 'graph': r'^graph\s+(TD|TB|BT|RL|LR)',
38
+ 'sequenceDiagram': r'^sequenceDiagram',
39
+ 'classDiagram': r'^classDiagram',
40
+ 'stateDiagram': r'^stateDiagram(-v2)?',
41
+ 'erDiagram': r'^erDiagram',
42
+ 'journey': r'^journey',
43
+ 'gantt': r'^gantt',
44
+ 'pie': r'^pie',
45
+ 'gitGraph': r'^gitGraph',
46
+ 'mindmap': r'^mindmap',
47
+ 'timeline': r'^timeline',
48
+ 'quadrantChart': r'^quadrantChart',
49
+ }
50
+
51
+ # Forbidden patterns that could cause rendering issues
52
+ FORBIDDEN_PATTERNS = [
53
+ r'<script', # No script tags
54
+ r'javascript:', # No javascript: URLs
55
+ r'on\w+\s*=', # No event handlers
56
+ r'eval\(', # No eval
57
+ r'\.innerHTML', # No innerHTML manipulation
58
+ ]
59
+
60
+
61
+ class MermaidValidator:
62
+ """Validates Mermaid diagram syntax to ensure safe and correct rendering."""
63
+
64
+ @staticmethod
65
+ def validate_syntax(diagram_code: str, expected_type: Optional[str] = None) -> tuple[bool, Optional[str]]:
66
+ """
67
+ Validate Mermaid diagram syntax.
68
+
69
+ Args:
70
+ diagram_code: The Mermaid diagram code to validate
71
+ expected_type: Optional expected diagram type (e.g., 'flowchart', 'sequenceDiagram')
72
+
73
+ Returns:
74
+ Tuple of (is_valid, error_message)
75
+ """
76
+ if not diagram_code or not diagram_code.strip():
77
+ return False, "Diagram code is empty"
78
+
79
+ # Check for forbidden patterns
80
+ for pattern in FORBIDDEN_PATTERNS:
81
+ if re.search(pattern, diagram_code, re.IGNORECASE):
82
+ return False, f"Forbidden pattern detected: {pattern}"
83
+
84
+ # Check for valid diagram type
85
+ diagram_lines = [line.strip() for line in diagram_code.strip().split('\n') if line.strip()]
86
+ if not diagram_lines:
87
+ return False, "No content in diagram"
88
+
89
+ # Skip metadata lines (---...---)
90
+ first_code_line = None
91
+ in_metadata = False
92
+ for line in diagram_lines:
93
+ if line == '---':
94
+ in_metadata = not in_metadata
95
+ continue
96
+ if not in_metadata and line:
97
+ first_code_line = line
98
+ break
99
+
100
+ if not first_code_line:
101
+ return False, "No diagram definition found"
102
+
103
+ # Validate diagram type
104
+ found_valid_type = False
105
+ detected_type = None
106
+ for diagram_type, pattern in MERMAID_DIAGRAM_TYPES.items():
107
+ if re.match(pattern, first_code_line, re.IGNORECASE):
108
+ found_valid_type = True
109
+ detected_type = diagram_type
110
+ break
111
+
112
+ if not found_valid_type:
113
+ return False, f"Invalid diagram type. First line: {first_code_line[:50]}"
114
+
115
+ # If expected type provided, verify it matches
116
+ if expected_type and detected_type:
117
+ if expected_type.lower() not in detected_type.lower():
118
+ return False, f"Expected {expected_type} but detected {detected_type}"
119
+
120
+ # Check for balanced brackets/parentheses (basic structural validation)
121
+ open_chars = {'(': 0, '[': 0, '{': 0}
122
+ close_chars = {')': '(', ']': '[', '}': '{'}
123
+ stack = []
124
+
125
+ for char in diagram_code:
126
+ if char in open_chars:
127
+ stack.append(char)
128
+ elif char in close_chars:
129
+ if not stack or stack[-1] != close_chars[char]:
130
+ # Don't fail on unbalanced - just warn
131
+ logger.warning(f"Potentially unbalanced brackets in diagram")
132
+ elif stack:
133
+ stack.pop()
134
+
135
+ return True, None
136
+
137
+ @staticmethod
138
+ def sanitize_content(content: str) -> str:
139
+ """
140
+ Sanitize diagram content to remove potentially problematic characters.
141
+
142
+ Args:
143
+ content: Content to sanitize
144
+
145
+ Returns:
146
+ Sanitized content
147
+ """
148
+ # Remove null bytes
149
+ content = content.replace('\x00', '')
150
+
151
+ # Normalize line endings
152
+ content = content.replace('\r\n', '\n').replace('\r', '\n')
153
+
154
+ # Remove excessive whitespace while preserving structure
155
+ lines = content.split('\n')
156
+ cleaned_lines = []
157
+ for line in lines:
158
+ # Preserve indentation but trim trailing spaces
159
+ cleaned_line = line.rstrip()
160
+ cleaned_lines.append(cleaned_line)
161
+
162
+ return '\n'.join(cleaned_lines)
163
+
164
+
165
+ class DataVisualizationTools(SchemaFixMixin, Toolkit):
166
+ """
167
+ Data Visualization toolkit for creating diagrams using Mermaid syntax.
168
+
169
+ Agents can use these tools to create various types of diagrams for:
170
+ - Data analysis and BI intelligence
171
+ - System architecture visualization
172
+ - Process flows and workflows
173
+ - Database schemas and ER diagrams
174
+ - Project timelines and Gantt charts
175
+ """
176
+
177
+ def __init__(
178
+ self,
179
+ max_diagram_size: int = 50000,
180
+ enable_flowchart: bool = True,
181
+ enable_sequence: bool = True,
182
+ enable_class_diagram: bool = True,
183
+ enable_er_diagram: bool = True,
184
+ enable_gantt: bool = True,
185
+ enable_pie_chart: bool = True,
186
+ enable_state_diagram: bool = True,
187
+ enable_git_graph: bool = True,
188
+ enable_user_journey: bool = True,
189
+ enable_quadrant_chart: bool = True,
190
+ stream_callback: Optional[Callable[[str], None]] = None,
191
+ **kwargs # Accept additional parameters like execution_id
192
+ ):
193
+ """
194
+ Initialize DataVisualizationTools.
195
+
196
+ Args:
197
+ max_diagram_size: Maximum size of diagram in characters
198
+ enable_*: Enable/disable specific diagram types
199
+ **kwargs: Additional configuration (e.g., execution_id)
200
+ stream_callback: Optional callback for streaming output
201
+ """
202
+ super().__init__(name="data_visualization")
203
+
204
+ self.max_diagram_size = max_diagram_size
205
+ self.enable_flowchart = enable_flowchart
206
+ self.enable_sequence = enable_sequence
207
+ self.enable_class_diagram = enable_class_diagram
208
+ self.enable_er_diagram = enable_er_diagram
209
+ self.enable_gantt = enable_gantt
210
+ self.enable_pie_chart = enable_pie_chart
211
+ self.enable_state_diagram = enable_state_diagram
212
+ self.enable_git_graph = enable_git_graph
213
+ self.enable_user_journey = enable_user_journey
214
+ self.enable_quadrant_chart = enable_quadrant_chart
215
+ self.stream_callback = stream_callback
216
+
217
+ # Register all enabled tools
218
+ if enable_flowchart:
219
+ self.register(self.create_flowchart)
220
+ if enable_sequence:
221
+ self.register(self.create_sequence_diagram)
222
+ if enable_class_diagram:
223
+ self.register(self.create_class_diagram)
224
+ if enable_er_diagram:
225
+ self.register(self.create_er_diagram)
226
+ if enable_gantt:
227
+ self.register(self.create_gantt_chart)
228
+ if enable_pie_chart:
229
+ self.register(self.create_pie_chart)
230
+ if enable_state_diagram:
231
+ self.register(self.create_state_diagram)
232
+ if enable_git_graph:
233
+ self.register(self.create_git_graph)
234
+ if enable_user_journey:
235
+ self.register(self.create_user_journey)
236
+ if enable_quadrant_chart:
237
+ self.register(self.create_quadrant_chart)
238
+
239
+ # Generic create_diagram tool
240
+ self.register(self.create_diagram)
241
+
242
+ # Fix: Rebuild function schemas with proper parameters
243
+ self._rebuild_function_schemas()
244
+
245
+ def _emit_diagram(
246
+ self,
247
+ diagram_code: str,
248
+ diagram_type: str,
249
+ validate: bool = True,
250
+ auto_fix: bool = True
251
+ ) -> str:
252
+ """
253
+ Emit a diagram event with proper formatting for UI parsing.
254
+ Includes validation, sanitization, and error handling.
255
+
256
+ Args:
257
+ diagram_code: Mermaid diagram code
258
+ diagram_type: Type of diagram (for logging/metadata)
259
+ validate: Whether to validate the diagram syntax (default: True)
260
+ auto_fix: Whether to attempt auto-fixing common issues (default: True)
261
+
262
+ Returns:
263
+ Formatted diagram event string or error message
264
+ """
265
+ try:
266
+ # Sanitize content
267
+ sanitized_code = MermaidValidator.sanitize_content(diagram_code)
268
+
269
+ # Validate size
270
+ if len(sanitized_code) > self.max_diagram_size:
271
+ error_msg = f"Error: Diagram exceeds maximum size of {self.max_diagram_size} characters (current: {len(sanitized_code)})"
272
+ logger.error(f"[DataVisualization] {error_msg}")
273
+ return error_msg
274
+
275
+ # Validate syntax if enabled
276
+ if validate:
277
+ is_valid, error_message = MermaidValidator.validate_syntax(
278
+ sanitized_code,
279
+ expected_type=diagram_type
280
+ )
281
+
282
+ if not is_valid:
283
+ if auto_fix:
284
+ # Attempt to fix common issues
285
+ fixed_code = self._attempt_fix(sanitized_code, diagram_type)
286
+ if fixed_code:
287
+ # Re-validate fixed code
288
+ is_valid, error_message = MermaidValidator.validate_syntax(
289
+ fixed_code,
290
+ expected_type=diagram_type
291
+ )
292
+ if is_valid:
293
+ logger.info(f"[DataVisualization] Auto-fixed diagram syntax issue")
294
+ sanitized_code = fixed_code
295
+ else:
296
+ error_msg = f"Error: Invalid diagram syntax - {error_message}\n\nAttempted auto-fix failed. Please check your Mermaid syntax."
297
+ logger.error(f"[DataVisualization] {error_msg}")
298
+ return error_msg
299
+ else:
300
+ error_msg = f"Error: Invalid diagram syntax - {error_message}"
301
+ logger.error(f"[DataVisualization] {error_msg}")
302
+ return error_msg
303
+
304
+ # Log successful validation
305
+ logger.info(
306
+ f"[DataVisualization] Emitting {diagram_type} diagram "
307
+ f"({len(sanitized_code)} chars)"
308
+ )
309
+
310
+ # Format the diagram event
311
+ output = f"""<<DIAGRAM_START>>
312
+ ```mermaid
313
+ {sanitized_code.strip()}
314
+ ```
315
+ <<DIAGRAM_END>>"""
316
+
317
+ # Stream if callback provided
318
+ if self.stream_callback:
319
+ try:
320
+ self.stream_callback(output)
321
+ except Exception as stream_error:
322
+ logger.error(
323
+ f"[DataVisualization] Stream callback failed: {stream_error}"
324
+ )
325
+ # Continue anyway - the output is still returned
326
+
327
+ return output
328
+
329
+ except Exception as e:
330
+ error_msg = f"Error: Failed to emit diagram - {str(e)}"
331
+ logger.error(f"[DataVisualization] {error_msg}", exc_info=True)
332
+ return error_msg
333
+
334
+ def _attempt_fix(self, diagram_code: str, diagram_type: str) -> Optional[str]:
335
+ """
336
+ Attempt to auto-fix common diagram syntax issues.
337
+
338
+ Args:
339
+ diagram_code: The diagram code with issues
340
+ diagram_type: The type of diagram
341
+
342
+ Returns:
343
+ Fixed diagram code or None if can't be fixed
344
+ """
345
+ try:
346
+ lines = diagram_code.split('\n')
347
+ fixed_lines = []
348
+
349
+ for line in lines:
350
+ # Remove trailing semicolons (common mistake)
351
+ if line.rstrip().endswith(';'):
352
+ line = line.rstrip()[:-1]
353
+
354
+ # Fix common arrow syntax issues
355
+ line = line.replace('-->', '-->').replace('--->', '-->')
356
+
357
+ fixed_lines.append(line)
358
+
359
+ return '\n'.join(fixed_lines)
360
+ except Exception as e:
361
+ logger.warning(f"[DataVisualization] Auto-fix failed: {e}")
362
+ return None
363
+
364
+ def create_diagram(
365
+ self, diagram_code: str, diagram_type: str = "flowchart"
366
+ ) -> str:
367
+ """
368
+ Create a diagram from Mermaid syntax.
369
+
370
+ Args:
371
+ diagram_code: Complete Mermaid diagram code
372
+ diagram_type: Type of diagram (for metadata)
373
+
374
+ Returns:
375
+ Success message with diagram event
376
+
377
+ Example:
378
+ create_diagram('''
379
+ flowchart TD
380
+ A[Start] --> B{Decision}
381
+ B -->|Yes| C[Action 1]
382
+ B -->|No| D[Action 2]
383
+ ''', 'flowchart')
384
+ """
385
+ return self._emit_diagram(diagram_code, diagram_type)
386
+
387
+ def create_flowchart(
388
+ self,
389
+ title: str,
390
+ nodes: str,
391
+ direction: str = "TD",
392
+ ) -> str:
393
+ """
394
+ Create a flowchart diagram with automatic validation and error recovery.
395
+
396
+ Args:
397
+ title: Title of the flowchart
398
+ nodes: Mermaid flowchart node definitions
399
+ direction: Direction (TD=top-down, LR=left-right, RL=right-left, BT=bottom-top)
400
+
401
+ Returns:
402
+ Success message with diagram event or error message
403
+
404
+ Example:
405
+ create_flowchart(
406
+ title="User Login Flow",
407
+ nodes='''
408
+ A[User] --> B[Login Page]
409
+ B --> C{Valid?}
410
+ C -->|Yes| D[Dashboard]
411
+ C -->|No| E[Error]
412
+ ''',
413
+ direction="TD"
414
+ )
415
+ """
416
+ try:
417
+ # Validate direction parameter
418
+ valid_directions = ['TD', 'TB', 'BT', 'RL', 'LR']
419
+ direction = direction.upper()
420
+ if direction not in valid_directions:
421
+ logger.warning(
422
+ f"[DataVisualization] Invalid direction '{direction}', "
423
+ f"defaulting to 'TD'. Valid: {valid_directions}"
424
+ )
425
+ direction = 'TD'
426
+
427
+ # Sanitize title
428
+ title = title.replace('"', "'").strip()
429
+ if not title:
430
+ title = "Flowchart"
431
+
432
+ # Build diagram
433
+ diagram = f"""---
434
+ title: {title}
435
+ ---
436
+ flowchart {direction}
437
+ {nodes.strip()}"""
438
+
439
+ return self._emit_diagram(diagram, "flowchart")
440
+
441
+ except Exception as e:
442
+ error_msg = f"Error creating flowchart: {str(e)}"
443
+ logger.error(f"[DataVisualization] {error_msg}", exc_info=True)
444
+ return error_msg
445
+
446
+ def create_sequence_diagram(
447
+ self,
448
+ title: str,
449
+ participants: list[str],
450
+ interactions: str,
451
+ ) -> str:
452
+ """
453
+ Create a sequence diagram.
454
+
455
+ Args:
456
+ title: Title of the sequence diagram
457
+ participants: List of participant names
458
+ interactions: Mermaid sequence diagram interactions
459
+
460
+ Returns:
461
+ Success message with diagram event
462
+
463
+ Example:
464
+ create_sequence_diagram(
465
+ title="API Authentication Flow",
466
+ participants=["Client", "API", "Database"],
467
+ interactions='''
468
+ Client->>API: POST /login
469
+ API->>Database: Verify credentials
470
+ Database-->>API: User data
471
+ API-->>Client: JWT token
472
+ '''
473
+ )
474
+ """
475
+ participant_defs = "\n".join([f" participant {p}" for p in participants])
476
+ diagram = f"""---
477
+ title: {title}
478
+ ---
479
+ sequenceDiagram
480
+ {participant_defs}
481
+ {interactions.strip()}"""
482
+ return self._emit_diagram(diagram, "sequence")
483
+
484
+ def create_class_diagram(
485
+ self,
486
+ title: str,
487
+ classes: str,
488
+ ) -> str:
489
+ """
490
+ Create a class diagram.
491
+
492
+ Args:
493
+ title: Title of the class diagram
494
+ classes: Mermaid class diagram definitions
495
+
496
+ Returns:
497
+ Success message with diagram event
498
+
499
+ Example:
500
+ create_class_diagram(
501
+ title="User Management System",
502
+ classes='''
503
+ class User {
504
+ +String name
505
+ +String email
506
+ +login()
507
+ +logout()
508
+ }
509
+ class Admin {
510
+ +String permissions
511
+ +deleteUser()
512
+ }
513
+ User <|-- Admin
514
+ '''
515
+ )
516
+ """
517
+ diagram = f"""---
518
+ title: {title}
519
+ ---
520
+ classDiagram
521
+ {classes.strip()}"""
522
+ return self._emit_diagram(diagram, "class")
523
+
524
+ def create_er_diagram(
525
+ self,
526
+ title: str,
527
+ entities: str,
528
+ ) -> str:
529
+ """
530
+ Create an Entity-Relationship diagram.
531
+
532
+ Args:
533
+ title: Title of the ER diagram
534
+ entities: Mermaid ER diagram definitions
535
+
536
+ Returns:
537
+ Success message with diagram event
538
+
539
+ Example:
540
+ create_er_diagram(
541
+ title="E-commerce Database Schema",
542
+ entities='''
543
+ CUSTOMER ||--o{ ORDER : places
544
+ ORDER ||--|{ LINE-ITEM : contains
545
+ PRODUCT ||--o{ LINE-ITEM : includes
546
+ '''
547
+ )
548
+ """
549
+ diagram = f"""---
550
+ title: {title}
551
+ ---
552
+ erDiagram
553
+ {entities.strip()}"""
554
+ return self._emit_diagram(diagram, "er")
555
+
556
+ def create_gantt_chart(
557
+ self,
558
+ title: str,
559
+ tasks: str,
560
+ date_format: str = "YYYY-MM-DD",
561
+ ) -> str:
562
+ """
563
+ Create a Gantt chart.
564
+
565
+ Args:
566
+ title: Title of the Gantt chart
567
+ tasks: Mermaid Gantt chart task definitions
568
+ date_format: Date format (default: YYYY-MM-DD)
569
+
570
+ Returns:
571
+ Success message with diagram event
572
+
573
+ Example:
574
+ create_gantt_chart(
575
+ title="Project Timeline",
576
+ tasks='''
577
+ section Planning
578
+ Requirements : 2024-01-01, 2w
579
+ Design : 2024-01-15, 1w
580
+ section Development
581
+ Backend : 2024-01-22, 3w
582
+ Frontend : 2024-02-05, 3w
583
+ '''
584
+ )
585
+ """
586
+ diagram = f"""---
587
+ title: {title}
588
+ ---
589
+ gantt
590
+ dateFormat {date_format}
591
+ {tasks.strip()}"""
592
+ return self._emit_diagram(diagram, "gantt")
593
+
594
+ def create_pie_chart(
595
+ self,
596
+ title: str,
597
+ data: dict[str, float],
598
+ ) -> str:
599
+ """
600
+ Create a pie chart with data validation.
601
+
602
+ Args:
603
+ title: Title of the pie chart
604
+ data: Dictionary of label: value pairs
605
+
606
+ Returns:
607
+ Success message with diagram event or error message
608
+
609
+ Example:
610
+ create_pie_chart(
611
+ title="Revenue by Product",
612
+ data={
613
+ "Product A": 35.5,
614
+ "Product B": 28.3,
615
+ "Product C": 20.1,
616
+ "Product D": 16.1
617
+ }
618
+ )
619
+ """
620
+ try:
621
+ # Validate data
622
+ if not data or not isinstance(data, dict):
623
+ return "Error: Pie chart data must be a non-empty dictionary"
624
+
625
+ if len(data) == 0:
626
+ return "Error: Pie chart must have at least one data point"
627
+
628
+ if len(data) > 50:
629
+ logger.warning(
630
+ f"[DataVisualization] Pie chart has {len(data)} slices, "
631
+ "which may be hard to read. Consider grouping data."
632
+ )
633
+
634
+ # Validate and sanitize data
635
+ validated_data = {}
636
+ for label, value in data.items():
637
+ # Sanitize label
638
+ clean_label = str(label).replace('"', "'").strip()
639
+ if not clean_label:
640
+ clean_label = "Unnamed"
641
+
642
+ # Validate value
643
+ try:
644
+ numeric_value = float(value)
645
+ if numeric_value < 0:
646
+ logger.warning(
647
+ f"[DataVisualization] Negative value for '{clean_label}': {numeric_value}, "
648
+ "using absolute value"
649
+ )
650
+ numeric_value = abs(numeric_value)
651
+ validated_data[clean_label] = numeric_value
652
+ except (ValueError, TypeError):
653
+ logger.warning(
654
+ f"[DataVisualization] Invalid value for '{clean_label}': {value}, skipping"
655
+ )
656
+ continue
657
+
658
+ if not validated_data:
659
+ return "Error: No valid data points after validation"
660
+
661
+ # Sanitize title
662
+ title = title.replace('"', "'").strip()
663
+ if not title:
664
+ title = "Pie Chart"
665
+
666
+ # Build diagram
667
+ data_lines = "\n".join(
668
+ [f' "{label}" : {value}' for label, value in validated_data.items()]
669
+ )
670
+ diagram = f"""---
671
+ title: {title}
672
+ ---
673
+ pie
674
+ {data_lines}"""
675
+
676
+ return self._emit_diagram(diagram, "pie")
677
+
678
+ except Exception as e:
679
+ error_msg = f"Error creating pie chart: {str(e)}"
680
+ logger.error(f"[DataVisualization] {error_msg}", exc_info=True)
681
+ return error_msg
682
+
683
+ def create_state_diagram(
684
+ self,
685
+ title: str,
686
+ states: str,
687
+ ) -> str:
688
+ """
689
+ Create a state diagram.
690
+
691
+ Args:
692
+ title: Title of the state diagram
693
+ states: Mermaid state diagram definitions
694
+
695
+ Returns:
696
+ Success message with diagram event
697
+
698
+ Example:
699
+ create_state_diagram(
700
+ title="Order Processing States",
701
+ states='''
702
+ [*] --> Pending
703
+ Pending --> Processing : Payment received
704
+ Processing --> Shipped : Items packed
705
+ Shipped --> Delivered : Delivery confirmed
706
+ Delivered --> [*]
707
+ Processing --> Cancelled : Cancel request
708
+ Cancelled --> [*]
709
+ '''
710
+ )
711
+ """
712
+ diagram = f"""---
713
+ title: {title}
714
+ ---
715
+ stateDiagram-v2
716
+ {states.strip()}"""
717
+ return self._emit_diagram(diagram, "state")
718
+
719
+ def create_git_graph(
720
+ self,
721
+ title: str,
722
+ commits: str,
723
+ ) -> str:
724
+ """
725
+ Create a Git graph diagram.
726
+
727
+ Args:
728
+ title: Title of the Git graph
729
+ commits: Mermaid Git graph commit definitions
730
+
731
+ Returns:
732
+ Success message with diagram event
733
+
734
+ Example:
735
+ create_git_graph(
736
+ title="Feature Branch Workflow",
737
+ commits='''
738
+ commit
739
+ branch develop
740
+ checkout develop
741
+ commit
742
+ branch feature
743
+ checkout feature
744
+ commit
745
+ commit
746
+ checkout develop
747
+ merge feature
748
+ checkout main
749
+ merge develop
750
+ '''
751
+ )
752
+ """
753
+ diagram = f"""---
754
+ title: {title}
755
+ ---
756
+ gitGraph
757
+ {commits.strip()}"""
758
+ return self._emit_diagram(diagram, "git")
759
+
760
+ def create_user_journey(
761
+ self,
762
+ title: str,
763
+ journey: str,
764
+ ) -> str:
765
+ """
766
+ Create a user journey diagram.
767
+
768
+ Args:
769
+ title: Title of the user journey
770
+ journey: Mermaid user journey definitions
771
+
772
+ Returns:
773
+ Success message with diagram event
774
+
775
+ Example:
776
+ create_user_journey(
777
+ title="Customer Onboarding Journey",
778
+ journey='''
779
+ section Sign up
780
+ Visit website: 5: User
781
+ Create account: 3: User
782
+ section Getting Started
783
+ Complete profile: 4: User
784
+ First purchase: 5: User
785
+ '''
786
+ )
787
+ """
788
+ diagram = f"""---
789
+ title: {title}
790
+ ---
791
+ journey
792
+ {journey.strip()}"""
793
+ return self._emit_diagram(diagram, "journey")
794
+
795
+ def create_quadrant_chart(
796
+ self,
797
+ title: str,
798
+ x_axis: str,
799
+ y_axis: str,
800
+ items: str,
801
+ ) -> str:
802
+ """
803
+ Create a quadrant chart.
804
+
805
+ Args:
806
+ title: Title of the quadrant chart
807
+ x_axis: X-axis label (left --> right)
808
+ y_axis: Y-axis label (bottom --> top)
809
+ items: Mermaid quadrant chart item definitions
810
+
811
+ Returns:
812
+ Success message with diagram event
813
+
814
+ Example:
815
+ create_quadrant_chart(
816
+ title="Product Priority Matrix",
817
+ x_axis="Effort",
818
+ y_axis="Impact",
819
+ items='''
820
+ Feature A: [0.8, 0.9]
821
+ Feature B: [0.3, 0.7]
822
+ Feature C: [0.6, 0.4]
823
+ Feature D: [0.2, 0.2]
824
+ '''
825
+ )
826
+ """
827
+ diagram = f"""---
828
+ title: {title}
829
+ ---
830
+ quadrantChart
831
+ x-axis {x_axis}
832
+ y-axis {y_axis}
833
+ {items.strip()}"""
834
+ return self._emit_diagram(diagram, "quadrant")