kailash 0.4.0__tar.gz → 0.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. {kailash-0.4.0/src/kailash.egg-info → kailash-0.4.1}/PKG-INFO +4 -1
  2. {kailash-0.4.0 → kailash-0.4.1}/README.md +3 -0
  3. {kailash-0.4.0 → kailash-0.4.1}/pyproject.toml +1 -1
  4. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/__init__.py +4 -4
  5. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/__init__.py +2 -0
  6. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/__init__.py +9 -2
  7. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/audit_log.py +1 -1
  8. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/security_event.py +7 -3
  9. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/ai_providers.py +247 -40
  10. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/llm_agent.py +29 -3
  11. kailash-0.4.1/src/kailash/nodes/ai/vision_utils.py +148 -0
  12. kailash-0.4.1/src/kailash/nodes/alerts/__init__.py +26 -0
  13. kailash-0.4.1/src/kailash/nodes/alerts/base.py +234 -0
  14. kailash-0.4.1/src/kailash/nodes/alerts/discord.py +499 -0
  15. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/streaming.py +8 -8
  16. kailash-0.4.1/src/kailash/nodes/security/audit_log.py +103 -0
  17. kailash-0.4.1/src/kailash/nodes/security/security_event.py +133 -0
  18. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/security.py +1 -1
  19. {kailash-0.4.0 → kailash-0.4.1/src/kailash.egg-info}/PKG-INFO +4 -1
  20. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/SOURCES.txt +4 -0
  21. kailash-0.4.0/src/kailash/nodes/security/audit_log.py +0 -91
  22. kailash-0.4.0/src/kailash/nodes/security/security_event.py +0 -132
  23. {kailash-0.4.0 → kailash-0.4.1}/LICENSE +0 -0
  24. {kailash-0.4.0 → kailash-0.4.1}/MANIFEST.in +0 -0
  25. {kailash-0.4.0 → kailash-0.4.1}/setup.cfg +0 -0
  26. {kailash-0.4.0 → kailash-0.4.1}/setup.py +0 -0
  27. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/__main__.py +0 -0
  28. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/access_control/__init__.py +0 -0
  29. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/access_control/managers.py +0 -0
  30. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/access_control/rule_evaluators.py +0 -0
  31. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/access_control.py +0 -0
  32. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/access_control_abac.py +0 -0
  33. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/auth.py +0 -0
  34. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/custom_nodes.py +0 -0
  35. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/custom_nodes_secure.py +0 -0
  36. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/gateway.py +0 -0
  37. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/mcp_integration.py +0 -0
  38. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/studio.py +0 -0
  39. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/api/workflow_api.py +0 -0
  40. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/cli/__init__.py +0 -0
  41. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/cli/commands.py +0 -0
  42. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/config/__init__.py +0 -0
  43. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/config/database_config.py +0 -0
  44. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/database/__init__.py +0 -0
  45. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/database/execution_pipeline.py +0 -0
  46. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/manifest.py +0 -0
  47. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/__init__.py +0 -0
  48. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/ai_registry_server.py +0 -0
  49. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/client.py +0 -0
  50. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/client_new.py +0 -0
  51. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/server.py +0 -0
  52. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/server_enhanced.py +0 -0
  53. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/servers/ai_registry.py +0 -0
  54. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/utils/__init__.py +0 -0
  55. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/utils/cache.py +0 -0
  56. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/utils/config.py +0 -0
  57. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/utils/formatters.py +0 -0
  58. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/mcp/utils/metrics.py +0 -0
  59. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/__init__.py +0 -0
  60. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/auth/__init__.py +0 -0
  61. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/auth/access_control.py +0 -0
  62. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/auth/auth_manager.py +0 -0
  63. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/auth/jwt_auth.py +0 -0
  64. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/auth/kailash_jwt_auth.py +0 -0
  65. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/communication/__init__.py +0 -0
  66. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/communication/ai_chat.py +0 -0
  67. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/communication/api_gateway.py +0 -0
  68. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/communication/events.py +0 -0
  69. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/communication/realtime.py +0 -0
  70. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/core/__init__.py +0 -0
  71. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/core/agent_ui.py +0 -0
  72. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/core/schema.py +0 -0
  73. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/core/workflows.py +0 -0
  74. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/__init__.py +0 -0
  75. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/base.py +0 -0
  76. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/base_models.py +0 -0
  77. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/enums.py +0 -0
  78. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/migrations.py +0 -0
  79. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/models.py +0 -0
  80. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/repositories.py +0 -0
  81. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/database/session_manager.py +0 -0
  82. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/mcp/__init__.py +0 -0
  83. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/mcp/client_integration.py +0 -0
  84. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/middleware/mcp/enhanced_server.py +0 -0
  85. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/permission_check.py +0 -0
  86. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/role_management.py +0 -0
  87. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/admin/user_management.py +0 -0
  88. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/__init__.py +0 -0
  89. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/a2a.py +0 -0
  90. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/agents.py +0 -0
  91. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/embedding_generator.py +0 -0
  92. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/intelligent_agent_orchestrator.py +0 -0
  93. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/iterative_llm_agent.py +0 -0
  94. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/models.py +0 -0
  95. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/ai/self_organizing.py +0 -0
  96. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/__init__.py +0 -0
  97. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/auth.py +0 -0
  98. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/graphql.py +0 -0
  99. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/http.py +0 -0
  100. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/monitoring.py +0 -0
  101. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/rate_limiting.py +0 -0
  102. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/rest.py +0 -0
  103. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/api/security.py +0 -0
  104. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/__init__.py +0 -0
  105. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/directory_integration.py +0 -0
  106. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/enterprise_auth_provider.py +0 -0
  107. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/mfa.py +0 -0
  108. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/risk_assessment.py +0 -0
  109. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/session_management.py +0 -0
  110. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/auth/sso.py +0 -0
  111. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/base.py +0 -0
  112. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/base_async.py +0 -0
  113. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/base_cycle_aware.py +0 -0
  114. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/base_with_acl.py +0 -0
  115. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/code/__init__.py +0 -0
  116. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/code/python.py +0 -0
  117. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/compliance/__init__.py +0 -0
  118. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/compliance/data_retention.py +0 -0
  119. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/compliance/gdpr.py +0 -0
  120. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/__init__.py +0 -0
  121. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/async_connection.py +0 -0
  122. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/async_sql.py +0 -0
  123. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/async_vector.py +0 -0
  124. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/directory.py +0 -0
  125. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/event_generation.py +0 -0
  126. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/file_discovery.py +0 -0
  127. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/readers.py +0 -0
  128. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/retrieval.py +0 -0
  129. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/sharepoint_graph.py +0 -0
  130. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/sources.py +0 -0
  131. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/sql.py +0 -0
  132. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/vector_db.py +0 -0
  133. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/data/writers.py +0 -0
  134. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/enterprise/__init__.py +0 -0
  135. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/enterprise/batch_processor.py +0 -0
  136. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/enterprise/data_lineage.py +0 -0
  137. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/__init__.py +0 -0
  138. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/async_operations.py +0 -0
  139. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/convergence.py +0 -0
  140. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/loop.py +0 -0
  141. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/operations.py +0 -0
  142. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/logic/workflow.py +0 -0
  143. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/mixins/__init__.py +0 -0
  144. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/mixins/event_emitter.py +0 -0
  145. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/mixins/mcp.py +0 -0
  146. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/mixins/security.py +0 -0
  147. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/mixins.py +0 -0
  148. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/monitoring/__init__.py +0 -0
  149. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/monitoring/performance_benchmark.py +0 -0
  150. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/__init__.py +0 -0
  151. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/advanced.py +0 -0
  152. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/agentic.py +0 -0
  153. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/conversational.py +0 -0
  154. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/evaluation.py +0 -0
  155. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/federated.py +0 -0
  156. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/graph.py +0 -0
  157. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/multimodal.py +0 -0
  158. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/optimized.py +0 -0
  159. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/privacy.py +0 -0
  160. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/query_processing.py +0 -0
  161. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/realtime.py +0 -0
  162. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/registry.py +0 -0
  163. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/router.py +0 -0
  164. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/similarity.py +0 -0
  165. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/strategies.py +0 -0
  166. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/rag/workflows.py +0 -0
  167. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/__init__.py +0 -0
  168. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/abac_evaluator.py +0 -0
  169. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/behavior_analysis.py +0 -0
  170. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/credential_manager.py +0 -0
  171. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/rotating_credentials.py +0 -0
  172. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/security/threat_detection.py +0 -0
  173. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/testing/__init__.py +0 -0
  174. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/testing/credential_testing.py +0 -0
  175. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/transform/__init__.py +0 -0
  176. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/transform/chunkers.py +0 -0
  177. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/transform/formatters.py +0 -0
  178. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/transform/processors.py +0 -0
  179. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/nodes/validation.py +0 -0
  180. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/__init__.py +0 -0
  181. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/access_controlled.py +0 -0
  182. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/async_local.py +0 -0
  183. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/docker.py +0 -0
  184. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/local.py +0 -0
  185. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/parallel.py +0 -0
  186. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/parallel_cyclic.py +0 -0
  187. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/runner.py +0 -0
  188. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/runtime/testing.py +0 -0
  189. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/sdk_exceptions.py +0 -0
  190. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/__init__.py +0 -0
  191. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/manager.py +0 -0
  192. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/metrics_collector.py +0 -0
  193. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/models.py +0 -0
  194. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/storage/__init__.py +0 -0
  195. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/storage/base.py +0 -0
  196. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/storage/database.py +0 -0
  197. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/tracking/storage/filesystem.py +0 -0
  198. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/__init__.py +0 -0
  199. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/export.py +0 -0
  200. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/migrations/__init__.py +0 -0
  201. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/migrations/generator.py +0 -0
  202. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/migrations/models.py +0 -0
  203. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/migrations/runner.py +0 -0
  204. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/secure_logging.py +0 -0
  205. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/utils/templates.py +0 -0
  206. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/visualization/__init__.py +0 -0
  207. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/visualization/api.py +0 -0
  208. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/visualization/dashboard.py +0 -0
  209. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/visualization/performance.py +0 -0
  210. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/visualization/reports.py +0 -0
  211. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/__init__.py +0 -0
  212. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/builder.py +0 -0
  213. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/convergence.py +0 -0
  214. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_analyzer.py +0 -0
  215. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_builder.py +0 -0
  216. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_config.py +0 -0
  217. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_debugger.py +0 -0
  218. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_exceptions.py +0 -0
  219. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_profiler.py +0 -0
  220. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cycle_state.py +0 -0
  221. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/cyclic_runner.py +0 -0
  222. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/graph.py +0 -0
  223. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/mermaid_visualizer.py +0 -0
  224. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/migration.py +0 -0
  225. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/mock_registry.py +0 -0
  226. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/resilience.py +0 -0
  227. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/runner.py +0 -0
  228. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/safety.py +0 -0
  229. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/state.py +0 -0
  230. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/templates.py +0 -0
  231. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/validation.py +0 -0
  232. {kailash-0.4.0 → kailash-0.4.1}/src/kailash/workflow/visualization.py +0 -0
  233. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/dependency_links.txt +0 -0
  234. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/entry_points.txt +0 -0
  235. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/not-zip-safe +0 -0
  236. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/requires.txt +0 -0
  237. {kailash-0.4.0 → kailash-0.4.1}/src/kailash.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kailash
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: Python SDK for the Kailash container-node architecture
5
5
  Home-page: https://github.com/integrum/kailash-python-sdk
6
6
  Author: Integrum
@@ -116,6 +116,7 @@ Dynamic: requires-python
116
116
  - 📈 **High Performance**: Optimized execution engine supporting 100,000+ iteration workflows
117
117
  - 📁 **Complete Finance Workflow Library (v0.3.1)**: Production-ready financial workflows with AI analysis
118
118
  - 💼 **Enterprise Workflow Patterns**: Credit risk, portfolio optimization, trading signals, fraud detection
119
+ - 🔔 **Production Alert System**: Rich Discord alerts with rate limiting, retry logic, and rich embed support
119
120
  - 🏭 **Session 067 Enhancements**: Business workflow templates, data lineage tracking, automatic credential rotation
120
121
  - 🔄 **Zero-Downtime Operations**: Automatic credential rotation with enterprise notifications and audit trails
121
122
  - 🌉 **Enterprise Middleware (v0.4.0)**: Production-ready middleware architecture with real-time agent-frontend communication, dynamic workflows, and AI chat integration
@@ -174,6 +175,7 @@ pip install kailash[user-management]
174
175
  # Everything
175
176
  pip install kailash[all]
176
177
  ```
178
+ >>>>>>> origin/main
177
179
 
178
180
  ## 🎯 Who Is This For?
179
181
 
@@ -522,6 +524,7 @@ api.run()
522
524
  - **API**: RESTClientNode, GraphQLNode, AuthNode, HTTPRequestNode
523
525
  - **Logic**: SwitchNode, MergeNode, ConvergenceCheckerNode
524
526
  - **Code**: PythonCodeNode, WorkflowNode
527
+ - **Alerts**: DiscordAlertNode with rich embeds and rate limiting
525
528
  - **Security**: EnhancedAccessControlManager (ABAC with 16 operators)
526
529
 
527
530
  ### Runtimes
@@ -42,6 +42,7 @@
42
42
  - 📈 **High Performance**: Optimized execution engine supporting 100,000+ iteration workflows
43
43
  - 📁 **Complete Finance Workflow Library (v0.3.1)**: Production-ready financial workflows with AI analysis
44
44
  - 💼 **Enterprise Workflow Patterns**: Credit risk, portfolio optimization, trading signals, fraud detection
45
+ - 🔔 **Production Alert System**: Rich Discord alerts with rate limiting, retry logic, and rich embed support
45
46
  - 🏭 **Session 067 Enhancements**: Business workflow templates, data lineage tracking, automatic credential rotation
46
47
  - 🔄 **Zero-Downtime Operations**: Automatic credential rotation with enterprise notifications and audit trails
47
48
  - 🌉 **Enterprise Middleware (v0.4.0)**: Production-ready middleware architecture with real-time agent-frontend communication, dynamic workflows, and AI chat integration
@@ -100,6 +101,7 @@ pip install kailash[user-management]
100
101
  # Everything
101
102
  pip install kailash[all]
102
103
  ```
104
+ >>>>>>> origin/main
103
105
 
104
106
  ## 🎯 Who Is This For?
105
107
 
@@ -448,6 +450,7 @@ api.run()
448
450
  - **API**: RESTClientNode, GraphQLNode, AuthNode, HTTPRequestNode
449
451
  - **Logic**: SwitchNode, MergeNode, ConvergenceCheckerNode
450
452
  - **Code**: PythonCodeNode, WorkflowNode
453
+ - **Alerts**: DiscordAlertNode with rich embeds and rate limiting
451
454
  - **Security**: EnhancedAccessControlManager (ABAC with 16 operators)
452
455
 
453
456
  ### Runtimes
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kailash"
7
- version = "0.4.0"
7
+ version = "0.4.1"
8
8
  description = "Python SDK for the Kailash container-node architecture"
9
9
  authors = [
10
10
  {name = "Integrum", email = "info@integrum.com"}
@@ -3,9 +3,9 @@
3
3
  The Kailash SDK provides a comprehensive framework for creating nodes and workflows
4
4
  that align with container-node architecture while allowing rapid prototyping.
5
5
 
6
- New in v0.4.0: Enterprise middleware architecture with real-time agent-frontend
7
- communication, dynamic workflows, AI chat integration, and production-ready
8
- session management. Complete refactor from monolithic to composable middleware.
6
+ New in v0.4.1: Production-ready Alert Nodes with Discord integration and
7
+ AI Provider Vision Support. Rich Discord alerts with embeds, rate limiting,
8
+ and universal vision capabilities across OpenAI, Anthropic, and Ollama providers.
9
9
  """
10
10
 
11
11
  from kailash.nodes.base import Node, NodeMetadata, NodeParameter
@@ -34,7 +34,7 @@ except ImportError:
34
34
  # For backward compatibility
35
35
  WorkflowGraph = Workflow
36
36
 
37
- __version__ = "0.4.0"
37
+ __version__ = "0.4.1"
38
38
 
39
39
  __all__ = [
40
40
  # Core workflow components
@@ -3,6 +3,7 @@
3
3
  # Import all node modules to ensure registration
4
4
  from kailash.nodes import (
5
5
  ai,
6
+ alerts,
6
7
  api,
7
8
  auth,
8
9
  code,
@@ -33,6 +34,7 @@ __all__ = [
33
34
  "PythonCodeNode",
34
35
  # Node modules
35
36
  "ai",
37
+ "alerts",
36
38
  "api",
37
39
  "auth",
38
40
  "code",
@@ -19,17 +19,24 @@ Core Components:
19
19
  - SecurityEventNode: Security incident tracking
20
20
  """
21
21
 
22
- from .audit_log import AuditLogNode
22
+ from .audit_log import EnterpriseAuditLogNode
23
23
  from .permission_check import PermissionCheckNode
24
24
  from .role_management import RoleManagementNode
25
- from .security_event import SecurityEventNode
25
+ from .security_event import EnterpriseSecurityEventNode
26
26
  from .user_management import UserManagementNode
27
27
 
28
+ # For backward compatibility, expose both old and new names
29
+ AuditLogNode = EnterpriseAuditLogNode
30
+ SecurityEventNode = EnterpriseSecurityEventNode
31
+
28
32
  __all__ = [
29
33
  # Core admin nodes
30
34
  "UserManagementNode",
31
35
  "RoleManagementNode",
32
36
  "PermissionCheckNode",
37
+ "EnterpriseAuditLogNode",
38
+ "EnterpriseSecurityEventNode",
39
+ # Backward compatibility aliases
33
40
  "AuditLogNode",
34
41
  "SecurityEventNode",
35
42
  ]
@@ -127,7 +127,7 @@ class AuditEvent:
127
127
 
128
128
 
129
129
  @register_node()
130
- class AuditLogNode(Node):
130
+ class EnterpriseAuditLogNode(Node):
131
131
  """Enterprise audit logging node with comprehensive compliance features.
132
132
 
133
133
  This node provides comprehensive audit logging capabilities including:
@@ -24,7 +24,11 @@ from enum import Enum
24
24
  from typing import Any, Dict, List, Optional, Tuple
25
25
 
26
26
  from kailash.access_control import UserContext
27
- from kailash.nodes.admin.audit_log import AuditEventType, AuditLogNode, AuditSeverity
27
+ from kailash.nodes.admin.audit_log import (
28
+ AuditEventType,
29
+ AuditSeverity,
30
+ EnterpriseAuditLogNode,
31
+ )
28
32
  from kailash.nodes.base import Node, NodeParameter, register_node
29
33
  from kailash.nodes.data import AsyncSQLDatabaseNode
30
34
  from kailash.sdk_exceptions import NodeExecutionError, NodeValidationError
@@ -169,7 +173,7 @@ class SecurityIncident:
169
173
 
170
174
 
171
175
  @register_node()
172
- class SecurityEventNode(Node):
176
+ class EnterpriseSecurityEventNode(Node):
173
177
  """Enterprise security event monitoring and incident response node.
174
178
 
175
179
  This node provides comprehensive security event processing including:
@@ -412,7 +416,7 @@ class SecurityEventNode(Node):
412
416
  self._db_node = AsyncSQLDatabaseNode(name="security_event_db", **db_config)
413
417
 
414
418
  # Initialize audit logging node
415
- self._audit_node = AuditLogNode(database_config=db_config)
419
+ self._audit_node = EnterpriseAuditLogNode(database_config=db_config)
416
420
 
417
421
  def _create_event(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
418
422
  """Create a new security event with risk scoring."""
@@ -8,7 +8,11 @@ separation between LLM and embedding capabilities.
8
8
 
9
9
  import hashlib
10
10
  from abc import ABC, abstractmethod
11
- from typing import Any
11
+ from typing import Any, Dict, List, Union
12
+
13
+ # Type definitions for flexible message content
14
+ MessageContent = Union[str, List[Dict[str, Any]]]
15
+ Message = Dict[str, Union[str, MessageContent]]
12
16
 
13
17
 
14
18
  class BaseAIProvider(ABC):
@@ -205,12 +209,14 @@ class LLMProvider(BaseAIProvider):
205
209
  self._capabilities["chat"] = True
206
210
 
207
211
  @abstractmethod
208
- def chat(self, messages: list[dict[str, str]], **kwargs) -> dict[str, Any]:
212
+ def chat(self, messages: List[Message], **kwargs) -> dict[str, Any]:
209
213
  """
210
214
  Generate a chat completion using the provider's LLM.
211
215
 
212
216
  Args:
213
217
  messages: Conversation messages in OpenAI format
218
+ Can be simple: [{"role": "user", "content": "text"}]
219
+ Or complex: [{"role": "user", "content": [{"type": "text", "text": "..."}, {"type": "image", "path": "..."}]}]
214
220
  **kwargs: Provider-specific parameters
215
221
 
216
222
  Returns:
@@ -391,7 +397,7 @@ class OllamaProvider(UnifiedAIProvider):
391
397
 
392
398
  return self._available
393
399
 
394
- def chat(self, messages: list[dict[str, str]], **kwargs) -> dict[str, Any]:
400
+ def chat(self, messages: List[Message], **kwargs) -> dict[str, Any]:
395
401
  """Generate a chat completion using Ollama.
396
402
 
397
403
  Args:
@@ -435,8 +441,50 @@ class OllamaProvider(UnifiedAIProvider):
435
441
  # Remove None values
436
442
  options = {k: v for k, v in options.items() if v is not None}
437
443
 
444
+ # Process messages for vision content
445
+ processed_messages = []
446
+
447
+ for msg in messages:
448
+ if isinstance(msg.get("content"), list):
449
+ # Complex content with potential images
450
+ text_parts = []
451
+ images = []
452
+
453
+ for item in msg["content"]:
454
+ if item["type"] == "text":
455
+ text_parts.append(item["text"])
456
+ elif item["type"] == "image":
457
+ # Lazy load vision utilities
458
+ from .vision_utils import encode_image
459
+
460
+ if "path" in item:
461
+ # For file paths, read the file directly
462
+ with open(item["path"], "rb") as f:
463
+ images.append(f.read())
464
+ else:
465
+ # For base64, decode it to bytes
466
+ import base64
467
+
468
+ base64_data = item.get("base64", "")
469
+ images.append(base64.b64decode(base64_data))
470
+
471
+ # Ollama expects images as part of the message
472
+ message_dict = {
473
+ "role": msg["role"],
474
+ "content": " ".join(text_parts),
475
+ }
476
+ if images:
477
+ message_dict["images"] = images
478
+
479
+ processed_messages.append(message_dict)
480
+ else:
481
+ # Simple string content (backward compatible)
482
+ processed_messages.append(msg)
483
+
438
484
  # Call Ollama
439
- response = ollama.chat(model=model, messages=messages, options=options)
485
+ response = ollama.chat(
486
+ model=model, messages=processed_messages, options=options
487
+ )
440
488
 
441
489
  # Format response to match standard structure
442
490
  return {
@@ -545,11 +593,18 @@ class OpenAIProvider(UnifiedAIProvider):
545
593
  - Install openai package: `pip install openai`
546
594
 
547
595
  Supported LLM models:
548
- - gpt-4-turbo (latest GPT-4 Turbo)
549
- - gpt-4 (standard GPT-4)
550
- - gpt-4-32k (32k context window)
551
- - gpt-3.5-turbo (latest GPT-3.5)
552
- - gpt-3.5-turbo-16k (16k context window)
596
+ - o4-mini (latest, vision support, recommended)
597
+ - o3 (reasoning model)
598
+
599
+ Note: This provider uses max_completion_tokens parameter compatible with
600
+ latest OpenAI models. Older models (gpt-4, gpt-3.5-turbo) are not supported.
601
+
602
+ Generation Config Parameters:
603
+ - max_completion_tokens (int): Maximum tokens to generate (recommended)
604
+ - max_tokens (int): Deprecated, use max_completion_tokens instead
605
+ - temperature (float): Sampling temperature (0-2)
606
+ - top_p (float): Nucleus sampling probability
607
+ - Other standard OpenAI parameters
553
608
 
554
609
  Supported embedding models:
555
610
  - text-embedding-3-large (3072 dimensions, configurable)
@@ -572,19 +627,22 @@ class OpenAIProvider(UnifiedAIProvider):
572
627
 
573
628
  return self._available
574
629
 
575
- def chat(self, messages: list[dict[str, str]], **kwargs) -> dict[str, Any]:
630
+ def chat(self, messages: List[Message], **kwargs) -> dict[str, Any]:
576
631
  """
577
632
  Generate a chat completion using OpenAI.
578
633
 
579
634
  Supported kwargs:
580
- - model (str): OpenAI model name (default: "gpt-4")
581
- - generation_config (dict): Generation parameters
635
+ - model (str): OpenAI model name (default: "o4-mini")
636
+ - generation_config (dict): Generation parameters including:
637
+ - max_completion_tokens (int): Max tokens to generate (recommended)
638
+ - max_tokens (int): Deprecated, use max_completion_tokens
639
+ - temperature, top_p, frequency_penalty, presence_penalty, etc.
582
640
  - tools (List[Dict]): Function/tool definitions for function calling
583
641
  """
584
642
  try:
585
643
  import openai
586
644
 
587
- model = kwargs.get("model", "gpt-4")
645
+ model = kwargs.get("model", "o4-mini")
588
646
  generation_config = kwargs.get("generation_config", {})
589
647
  tools = kwargs.get("tools", [])
590
648
 
@@ -592,13 +650,86 @@ class OpenAIProvider(UnifiedAIProvider):
592
650
  if self._client is None:
593
651
  self._client = openai.OpenAI()
594
652
 
653
+ # Process messages for vision content
654
+ processed_messages = []
655
+ for msg in messages:
656
+ if isinstance(msg.get("content"), list):
657
+ # Complex content with potential images
658
+ processed_content = []
659
+ for item in msg["content"]:
660
+ if item.get("type") == "text":
661
+ processed_content.append(
662
+ {"type": "text", "text": item.get("text", "")}
663
+ )
664
+ elif item.get("type") == "image":
665
+ # Lazy load vision utilities
666
+ from .vision_utils import (
667
+ encode_image,
668
+ get_media_type,
669
+ validate_image_size,
670
+ )
671
+
672
+ if "path" in item:
673
+ # Validate image size
674
+ is_valid, error_msg = validate_image_size(item["path"])
675
+ if not is_valid:
676
+ raise ValueError(
677
+ f"Image validation failed: {error_msg}"
678
+ )
679
+
680
+ base64_image = encode_image(item["path"])
681
+ media_type = get_media_type(item["path"])
682
+ elif "base64" in item:
683
+ base64_image = item["base64"]
684
+ media_type = item.get("media_type", "image/jpeg")
685
+ else:
686
+ raise ValueError(
687
+ "Image item must have either 'path' or 'base64' field"
688
+ )
689
+
690
+ processed_content.append(
691
+ {
692
+ "type": "image_url",
693
+ "image_url": {
694
+ "url": f"data:{media_type};base64,{base64_image}"
695
+ },
696
+ }
697
+ )
698
+
699
+ processed_messages.append(
700
+ {"role": msg.get("role", "user"), "content": processed_content}
701
+ )
702
+ else:
703
+ # Simple string content (backward compatible)
704
+ processed_messages.append(msg)
705
+
706
+ # Handle max tokens parameter - support both old and new names
707
+ max_completion = generation_config.get(
708
+ "max_completion_tokens"
709
+ ) or generation_config.get("max_tokens", 500)
710
+
711
+ # Show deprecation warning if using old parameter
712
+ # TODO: remove the max_tokens in the future.
713
+ if (
714
+ "max_tokens" in generation_config
715
+ and "max_completion_tokens" not in generation_config
716
+ ):
717
+ import warnings
718
+
719
+ warnings.warn(
720
+ "'max_tokens' is deprecated and will be removed in v0.5.0. "
721
+ "Please use 'max_completion_tokens' instead.",
722
+ DeprecationWarning,
723
+ stacklevel=3,
724
+ )
725
+
595
726
  # Prepare request
596
727
  request_params = {
597
728
  "model": model,
598
- "messages": messages,
599
- "temperature": generation_config.get("temperature", 0.7),
600
- "max_tokens": generation_config.get("max_tokens", 500),
601
- "top_p": generation_config.get("top_p", 0.9),
729
+ "messages": processed_messages,
730
+ "temperature": generation_config.get("temperature", 1.0),
731
+ "max_completion_tokens": max_completion, # Always use new parameter
732
+ "top_p": generation_config.get("top_p", 1.0),
602
733
  "frequency_penalty": generation_config.get("frequency_penalty"),
603
734
  "presence_penalty": generation_config.get("presence_penalty"),
604
735
  "stop": generation_config.get("stop"),
@@ -649,6 +780,15 @@ class OpenAIProvider(UnifiedAIProvider):
649
780
  raise RuntimeError(
650
781
  "OpenAI library not installed. Install with: pip install openai"
651
782
  )
783
+ except openai.BadRequestError as e:
784
+ # Provide helpful error message for unsupported models or parameters
785
+ if "max_tokens" in str(e):
786
+ raise RuntimeError(
787
+ "This OpenAI provider requires models that support max_completion_tokens. "
788
+ "Please use o4-mini, o3 "
789
+ "Older models like gpt-4o or gpt-3.5-turbo are not supported."
790
+ )
791
+ raise RuntimeError(f"OpenAI API error: {str(e)}")
652
792
  except Exception as e:
653
793
  raise RuntimeError(f"OpenAI error: {str(e)}")
654
794
 
@@ -772,7 +912,7 @@ class AnthropicProvider(LLMProvider):
772
912
 
773
913
  return self._available
774
914
 
775
- def chat(self, messages: list[dict[str, str]], **kwargs) -> dict[str, Any]:
915
+ def chat(self, messages: List[Message], **kwargs) -> dict[str, Any]:
776
916
  """Generate a chat completion using Anthropic."""
777
917
  try:
778
918
  import anthropic
@@ -790,22 +930,75 @@ class AnthropicProvider(LLMProvider):
790
930
 
791
931
  for msg in messages:
792
932
  if msg["role"] == "system":
793
- system_message = msg["content"]
933
+ # System messages are always text
934
+ system_message = (
935
+ msg["content"]
936
+ if isinstance(msg["content"], str)
937
+ else str(msg["content"])
938
+ )
794
939
  else:
795
- user_messages.append(msg)
796
-
797
- # Call Anthropic
798
- response = self._client.messages.create(
799
- model=model,
800
- messages=user_messages,
801
- system=system_message,
802
- max_tokens=generation_config.get("max_tokens", 500),
803
- temperature=generation_config.get("temperature", 0.7),
804
- top_p=generation_config.get("top_p"),
805
- top_k=generation_config.get("top_k"),
806
- stop_sequences=generation_config.get("stop_sequences"),
807
- metadata=generation_config.get("metadata"),
808
- )
940
+ # Process potentially complex content
941
+ if isinstance(msg.get("content"), list):
942
+ # Complex content with potential images
943
+ content_parts = []
944
+
945
+ for item in msg["content"]:
946
+ if item["type"] == "text":
947
+ content_parts.append(
948
+ {"type": "text", "text": item["text"]}
949
+ )
950
+ elif item["type"] == "image":
951
+ # Lazy load vision utilities
952
+ from .vision_utils import encode_image, get_media_type
953
+
954
+ if "path" in item:
955
+ base64_image = encode_image(item["path"])
956
+ media_type = get_media_type(item["path"])
957
+ else:
958
+ base64_image = item.get("base64", "")
959
+ media_type = item.get("media_type", "image/jpeg")
960
+
961
+ content_parts.append(
962
+ {
963
+ "type": "image",
964
+ "source": {
965
+ "type": "base64",
966
+ "media_type": media_type,
967
+ "data": base64_image,
968
+ },
969
+ }
970
+ )
971
+
972
+ user_messages.append(
973
+ {"role": msg["role"], "content": content_parts}
974
+ )
975
+ else:
976
+ # Simple string content (backward compatible)
977
+ user_messages.append(msg)
978
+
979
+ # Call Anthropic - build kwargs to avoid passing None values
980
+ create_kwargs = {
981
+ "model": model,
982
+ "messages": user_messages,
983
+ "max_tokens": generation_config.get("max_tokens", 500),
984
+ "temperature": generation_config.get("temperature", 0.7),
985
+ }
986
+
987
+ # Only add optional parameters if they have valid values
988
+ if system_message is not None:
989
+ create_kwargs["system"] = system_message
990
+ if generation_config.get("top_p") is not None:
991
+ create_kwargs["top_p"] = generation_config.get("top_p")
992
+ if generation_config.get("top_k") is not None:
993
+ create_kwargs["top_k"] = generation_config.get("top_k")
994
+ if generation_config.get("stop_sequences") is not None:
995
+ create_kwargs["stop_sequences"] = generation_config.get(
996
+ "stop_sequences"
997
+ )
998
+ if generation_config.get("metadata") is not None:
999
+ create_kwargs["metadata"] = generation_config.get("metadata")
1000
+
1001
+ response = self._client.messages.create(**create_kwargs)
809
1002
 
810
1003
  # Format response
811
1004
  return {
@@ -1232,16 +1425,33 @@ class MockProvider(UnifiedAIProvider):
1232
1425
  """Mock provider is always available."""
1233
1426
  return True
1234
1427
 
1235
- def chat(self, messages: list[dict[str, str]], **kwargs) -> dict[str, Any]:
1428
+ def chat(self, messages: List[Message], **kwargs) -> dict[str, Any]:
1236
1429
  """Generate mock LLM response."""
1237
1430
  last_user_message = ""
1431
+ has_images = False
1432
+
1238
1433
  for msg in reversed(messages):
1239
1434
  if msg.get("role") == "user":
1240
- last_user_message = msg.get("content", "")
1435
+ content = msg.get("content", "")
1436
+ # Handle complex content with images
1437
+ if isinstance(content, list):
1438
+ text_parts = []
1439
+ for item in content:
1440
+ if item.get("type") == "text":
1441
+ text_parts.append(item.get("text", ""))
1442
+ elif item.get("type") == "image":
1443
+ has_images = True
1444
+ last_user_message = " ".join(text_parts)
1445
+ else:
1446
+ last_user_message = content
1241
1447
  break
1242
1448
 
1243
1449
  # Generate contextual mock response
1244
- if "analyze" in last_user_message.lower():
1450
+ if has_images:
1451
+ response_content = (
1452
+ "I can see the image(s) you've provided. [Mock vision response]"
1453
+ )
1454
+ elif "analyze" in last_user_message.lower():
1245
1455
  response_content = "Based on the provided data and context, I can see several key patterns..."
1246
1456
  elif "create" in last_user_message.lower():
1247
1457
  response_content = "I'll help you create that. Based on the requirements..."
@@ -1259,10 +1469,7 @@ class MockProvider(UnifiedAIProvider):
1259
1469
  "tool_calls": [],
1260
1470
  "finish_reason": "stop",
1261
1471
  "usage": {
1262
- "prompt_tokens": len(
1263
- " ".join(msg.get("content", "") for msg in messages)
1264
- )
1265
- // 4,
1472
+ "prompt_tokens": 100, # Mock value
1266
1473
  "completion_tokens": len(response_content) // 4,
1267
1474
  "total_tokens": 0, # Will be calculated
1268
1475
  },
@@ -1412,13 +1412,28 @@ class LLMAgentNode(Node):
1412
1412
  ) -> dict[str, Any]:
1413
1413
  """Generate mock LLM response for testing."""
1414
1414
  last_user_message = ""
1415
+ has_images = False
1416
+
1415
1417
  for msg in reversed(messages):
1416
1418
  if msg.get("role") == "user":
1417
- last_user_message = msg.get("content", "")
1419
+ content = msg.get("content", "")
1420
+ # Handle complex content with images
1421
+ if isinstance(content, list):
1422
+ text_parts = []
1423
+ for item in content:
1424
+ if item.get("type") == "text":
1425
+ text_parts.append(item.get("text", ""))
1426
+ elif item.get("type") == "image":
1427
+ has_images = True
1428
+ last_user_message = " ".join(text_parts)
1429
+ else:
1430
+ last_user_message = content
1418
1431
  break
1419
1432
 
1420
1433
  # Generate contextual mock response
1421
- if "analyze" in last_user_message.lower():
1434
+ if has_images:
1435
+ response_content = "I can see the image(s) you've provided. Based on my analysis, [Mock vision response for testing]"
1436
+ elif "analyze" in last_user_message.lower():
1422
1437
  response_content = "Based on the provided data and context, I can see several key patterns: 1) Customer engagement has increased by 15% this quarter, 2) Product A shows the highest conversion rate, and 3) There are opportunities for improvement in the onboarding process."
1423
1438
  elif (
1424
1439
  "create" in last_user_message.lower()
@@ -1458,7 +1473,18 @@ class LLMAgentNode(Node):
1458
1473
  "finish_reason": "stop" if not tool_calls else "tool_calls",
1459
1474
  "usage": {
1460
1475
  "prompt_tokens": len(
1461
- " ".join(msg.get("content", "") for msg in messages)
1476
+ " ".join(
1477
+ (
1478
+ msg.get("content", "")
1479
+ if isinstance(msg.get("content"), str)
1480
+ else " ".join(
1481
+ item.get("text", "")
1482
+ for item in msg.get("content", [])
1483
+ if item.get("type") == "text"
1484
+ )
1485
+ )
1486
+ for msg in messages
1487
+ )
1462
1488
  )
1463
1489
  // 4,
1464
1490
  "completion_tokens": len(response_content) // 4,