hexdag 0.7.0.dev11__tar.gz → 0.7.0.dev13__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 (363) hide show
  1. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/PKG-INFO +4 -1
  2. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/config_loader.py +10 -0
  3. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/__init__.py +6 -0
  4. hexdag-0.7.0.dev13/hexdag/compiler/plugins/adapter_definition.py +140 -0
  5. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/system_builder.py +86 -3
  6. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/yaml_builder.py +33 -1
  7. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/yaml_validator.py +129 -0
  8. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/pipeline_spawner/local.py +28 -0
  9. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/local.py +37 -3
  10. hexdag-0.7.0.dev13/hexdag/drivers/vfs/providers/sys_caps_provider.py +166 -0
  11. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/config/models.py +27 -0
  12. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/context/__init__.py +2 -0
  13. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/context/execution_context.py +14 -0
  14. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/__init__.py +4 -0
  15. hexdag-0.7.0.dev13/hexdag/kernel/domain/caps.py +248 -0
  16. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/dag.py +5 -0
  17. hexdag-0.7.0.dev13/hexdag/kernel/domain/extraction_state.py +107 -0
  18. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/pipeline_config.py +15 -3
  19. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/system_config.py +42 -0
  20. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/exceptions.py +25 -0
  21. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/expression_parser.py +75 -11
  22. hexdag-0.7.0.dev13/hexdag/kernel/lifecycle_runner.py +615 -0
  23. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/checkpoint_manager.py +36 -0
  24. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/execution_coordinator.py +96 -4
  25. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/lifecycle_manager.py +13 -4
  26. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/node_executor.py +31 -8
  27. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/__init__.py +18 -0
  28. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/events.py +168 -0
  29. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/models.py +1 -0
  30. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/orchestrator.py +32 -1
  31. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/orchestrator_factory.py +213 -0
  32. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/pipeline_runner.py +154 -4
  33. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/data_store.py +40 -0
  34. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/pipeline_spawner.py +4 -0
  35. hexdag-0.7.0.dev13/hexdag/stdlib/adapters/redis/__init__.py +22 -0
  36. hexdag-0.7.0.dev13/hexdag/stdlib/adapters/redis/redis_adapter.py +230 -0
  37. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/__init__.py +4 -0
  38. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/entity_state.py +182 -4
  39. hexdag-0.7.0.dev13/hexdag/stdlib/lib/extraction_job.py +284 -0
  40. hexdag-0.7.0.dev13/hexdag/stdlib/lib/pipeline_memory.py +101 -0
  41. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/__init__.py +2 -0
  42. hexdag-0.7.0.dev13/hexdag/stdlib/middleware/distributed_cache.py +190 -0
  43. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/__init__.py +2 -0
  44. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/agent_node.py +20 -5
  45. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/mapped_input.py +31 -10
  46. hexdag-0.7.0.dev13/hexdag/stdlib/nodes/transition_node.py +138 -0
  47. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/pyproject.toml +9 -4
  48. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/.gitignore +0 -0
  49. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/LICENSE +0 -0
  50. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/README.md +0 -0
  51. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/__init__.py +0 -0
  52. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/__main__.py +0 -0
  53. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/__init__.py +0 -0
  54. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/components.py +0 -0
  55. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/documentation.py +0 -0
  56. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/execution.py +0 -0
  57. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/export.py +0 -0
  58. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/logs.py +0 -0
  59. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/pipeline.py +0 -0
  60. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/processes.py +0 -0
  61. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/validation.py +0 -0
  62. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/api/vfs.py +0 -0
  63. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/__init__.py +0 -0
  64. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/__main__.py +0 -0
  65. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/__init__.py +0 -0
  66. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/build_cmd.py +0 -0
  67. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/create_cmd.py +0 -0
  68. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/docs_cmd.py +0 -0
  69. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/generate_types_cmd.py +0 -0
  70. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/init_cmd.py +0 -0
  71. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/lint_cmd.py +0 -0
  72. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/pipeline_cmd.py +0 -0
  73. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/plugin_dev_cmd.py +0 -0
  74. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/plugins_cmd.py +0 -0
  75. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/studio_cmd.py +0 -0
  76. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/commands/validate_cmd.py +0 -0
  77. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/cli/main.py +0 -0
  78. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/__init__.py +0 -0
  79. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/component_instantiator.py +0 -0
  80. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/include_tag.py +0 -0
  81. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/pipeline_config.py +0 -0
  82. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/config_definition.py +0 -0
  83. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/macro_definition.py +0 -0
  84. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/macro_entity.py +0 -0
  85. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/middleware_definition.py +0 -0
  86. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/plugins/node_entity.py +0 -0
  87. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/preprocessing/__init__.py +0 -0
  88. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/preprocessing/_type_guards.py +0 -0
  89. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/preprocessing/env_vars.py +0 -0
  90. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/preprocessing/include.py +0 -0
  91. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/preprocessing/template.py +0 -0
  92. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/py_tag.py +0 -0
  93. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/reference_resolver.py +0 -0
  94. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/compiler/tag_discovery.py +0 -0
  95. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/docs/__init__.py +0 -0
  96. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/docs/extractors.py +0 -0
  97. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/docs/generators.py +0 -0
  98. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/docs/models.py +0 -0
  99. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/executors/__init__.py +0 -0
  100. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/executors/local_executor.py +0 -0
  101. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/http_client/__init__.py +0 -0
  102. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/http_client/http_client.py +0 -0
  103. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/observer_manager/__init__.py +0 -0
  104. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/observer_manager/local.py +0 -0
  105. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/pipeline_spawner/__init__.py +0 -0
  106. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/__init__.py +0 -0
  107. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/providers/__init__.py +0 -0
  108. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/providers/lib_provider.py +0 -0
  109. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/providers/proc_entities_provider.py +0 -0
  110. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/providers/proc_runs_provider.py +0 -0
  111. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/drivers/vfs/providers/proc_scheduled_provider.py +0 -0
  112. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/__init__.py +0 -0
  113. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/_alias_registry.py +0 -0
  114. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/config/__init__.py +0 -0
  115. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/config/loader.py +0 -0
  116. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/configurable.py +0 -0
  117. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/discovery.py +0 -0
  118. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/agent_tools.py +0 -0
  119. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/entity_state.py +0 -0
  120. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/pipeline_run.py +0 -0
  121. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/scheduled_task.py +0 -0
  122. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/domain/vfs.py +0 -0
  123. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/lib_base.py +0 -0
  124. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/linting/__init__.py +0 -0
  125. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/linting/models.py +0 -0
  126. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/linting/pipeline_rules.py +0 -0
  127. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/linting/rules.py +0 -0
  128. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/logging.py +0 -0
  129. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/models/__init__.py +0 -0
  130. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/models/base.py +0 -0
  131. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/__init__.py +0 -0
  132. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/body_executor.py +0 -0
  133. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/__init__.py +0 -0
  134. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/adapter_lifecycle_manager.py +0 -0
  135. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/health_check_manager.py +0 -0
  136. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/input_mapper.py +0 -0
  137. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/components/secret_manager.py +0 -0
  138. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/constants.py +0 -0
  139. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/README.md +0 -0
  140. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/batching.py +0 -0
  141. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/decorators.py +0 -0
  142. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/events/observers/__init__.py +0 -0
  143. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/hook_context.py +0 -0
  144. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/hooks.py +0 -0
  145. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/port_wrappers.py +0 -0
  146. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/prompt/__init__.py +0 -0
  147. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/orchestration/prompt/template.py +0 -0
  148. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/pipeline_builder/__init__.py +0 -0
  149. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/__init__.py +0 -0
  150. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/api_call.py +0 -0
  151. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/database.py +0 -0
  152. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/detection.py +0 -0
  153. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/executor.py +0 -0
  154. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/file_storage.py +0 -0
  155. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/healthcheck.py +0 -0
  156. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/llm.py +0 -0
  157. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/memory.py +0 -0
  158. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/observer_manager.py +0 -0
  159. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/secret.py +0 -0
  160. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/tool_router.py +0 -0
  161. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/vector_search.py +0 -0
  162. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports/vfs.py +0 -0
  163. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/ports_builder.py +0 -0
  164. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/protocols.py +0 -0
  165. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/resolver.py +0 -0
  166. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/schema/__init__.py +0 -0
  167. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/schema/generator.py +0 -0
  168. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/secrets.py +0 -0
  169. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/service.py +0 -0
  170. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/system_runner.py +0 -0
  171. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/types.py +0 -0
  172. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/async_warnings.py +0 -0
  173. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/caching.py +0 -0
  174. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/input_normalization.py +0 -0
  175. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/node_timer.py +0 -0
  176. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/schema_conversion.py +0 -0
  177. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/serialization.py +0 -0
  178. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/utils/sql_validation.py +0 -0
  179. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/validation/__init__.py +0 -0
  180. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/validation/retry.py +0 -0
  181. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/validation/sanitized_types.py +0 -0
  182. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/validation/secure_json.py +0 -0
  183. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/kernel/yaml_macro.py +0 -0
  184. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/mcp_server.py +0 -0
  185. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/py.typed +0 -0
  186. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/__init__.py +0 -0
  187. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/__init__.py +0 -0
  188. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/_discovery.py +0 -0
  189. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/anthropic/__init__.py +0 -0
  190. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/anthropic/anthropic_adapter.py +0 -0
  191. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/base.py +0 -0
  192. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/__init__.py +0 -0
  193. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/csv/csv_adapter.py +0 -0
  194. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/pgvector/__init__.py +0 -0
  195. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/pgvector/pgvector_adapter.py +0 -0
  196. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/sqlalchemy/sqlalchemy_adapter.py +0 -0
  197. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/sqlite/__init__.py +0 -0
  198. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/database/sqlite/sqlite_adapter.py +0 -0
  199. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/local/README.md +0 -0
  200. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/local/__init__.py +0 -0
  201. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/__init__.py +0 -0
  202. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/collection_memory.py +0 -0
  203. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/file_memory_adapter.py +0 -0
  204. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/in_memory_memory.py +0 -0
  205. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/schemas.py +0 -0
  206. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/session_memory.py +0 -0
  207. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/sqlite_memory_adapter.py +0 -0
  208. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/memory/state_memory.py +0 -0
  209. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/README.md +0 -0
  210. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/__init__.py +0 -0
  211. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/hexdag.yaml +0 -0
  212. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/mock_database.py +0 -0
  213. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/mock_embedding.py +0 -0
  214. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/mock_http.py +0 -0
  215. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/mock/mock_llm.py +0 -0
  216. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/openai/__init__.py +0 -0
  217. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/openai/openai_adapter.py +0 -0
  218. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/secret/__init__.py +0 -0
  219. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/adapters/secret/local_secret_adapter.py +0 -0
  220. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/database_tools.py +0 -0
  221. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/observers/__init__.py +0 -0
  222. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/observers/core_observers.py +0 -0
  223. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/observers/cost_profiler.py +0 -0
  224. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/observers/models.py +0 -0
  225. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/observers/port_call_observers.py +0 -0
  226. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/process_registry.py +0 -0
  227. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/process_registry_observer.py +0 -0
  228. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/scheduler.py +0 -0
  229. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib/vfs_tools.py +0 -0
  230. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/lib_base.py +0 -0
  231. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/macros/__init__.py +0 -0
  232. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/macros/_discovery.py +0 -0
  233. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/macros/conversation_agent.py +0 -0
  234. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/macros/llm_macro.py +0 -0
  235. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/macros/reasoning_agent.py +0 -0
  236. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/compose.py +0 -0
  237. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/observable.py +0 -0
  238. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/observable_tool_router.py +0 -0
  239. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/rate_limiter.py +0 -0
  240. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/response_cache.py +0 -0
  241. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/retry.py +0 -0
  242. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/structured_output.py +0 -0
  243. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/middleware/timeout.py +0 -0
  244. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/_discovery.py +0 -0
  245. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/api_call_node.py +0 -0
  246. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/base_node_factory.py +0 -0
  247. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/checkpoint_node.py +0 -0
  248. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/composite_node.py +0 -0
  249. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/data_node.py +0 -0
  250. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/expression_node.py +0 -0
  251. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/function_node.py +0 -0
  252. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/llm_node.py +0 -0
  253. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/service_call_node.py +0 -0
  254. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/tool_call_node.py +0 -0
  255. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/nodes/tool_utils.py +0 -0
  256. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/prompts/__init__.py +0 -0
  257. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/prompts/base.py +0 -0
  258. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/prompts/chat_prompts.py +0 -0
  259. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/prompts/error_correction_prompts.py +0 -0
  260. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/stdlib/prompts/tool_prompts.py +0 -0
  261. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/__init__.py +0 -0
  262. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/build_ui.py +0 -0
  263. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/__init__.py +0 -0
  264. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/main.py +0 -0
  265. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/__init__.py +0 -0
  266. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/execute.py +0 -0
  267. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/export.py +0 -0
  268. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/files.py +0 -0
  269. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/plugins.py +0 -0
  270. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/server/routes/validate.py +0 -0
  271. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/index.html +0 -0
  272. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/package-lock.json +0 -0
  273. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/package.json +0 -0
  274. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/postcss.config.js +0 -0
  275. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/public/hexdag.svg +0 -0
  276. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/App.tsx +0 -0
  277. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/Canvas.tsx +0 -0
  278. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/ContextMenu.tsx +0 -0
  279. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/FileBrowser.tsx +0 -0
  280. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/Header.tsx +0 -0
  281. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/HexdagNode.tsx +0 -0
  282. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/NodeInspector.tsx +0 -0
  283. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/NodePalette.tsx +0 -0
  284. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/NodePortsSection.tsx +0 -0
  285. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/PluginManager.tsx +0 -0
  286. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/PortsEditor.tsx +0 -0
  287. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/PythonEditor.tsx +0 -0
  288. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/ValidationPanel.tsx +0 -0
  289. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/YamlEditor.tsx +0 -0
  290. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/components/index.ts +0 -0
  291. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/index.css +0 -0
  292. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/lib/api.ts +0 -0
  293. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/lib/nodeTemplates.ts +0 -0
  294. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/lib/store.ts +0 -0
  295. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/main.tsx +0 -0
  296. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/types/index.ts +0 -0
  297. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/src/vite-env.d.ts +0 -0
  298. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/tailwind.config.js +0 -0
  299. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/tsconfig.json +0 -0
  300. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/tsconfig.node.json +0 -0
  301. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag/studio/ui/vite.config.ts +0 -0
  302. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/.gitignore +0 -0
  303. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/README.md +0 -0
  304. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/__init__.py +0 -0
  305. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/LICENSE +0 -0
  306. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/README.md +0 -0
  307. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/__init__.py +0 -0
  308. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/adapters/__init__.py +0 -0
  309. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/adapters/blob.py +0 -0
  310. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/adapters/cosmos.py +0 -0
  311. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/adapters/keyvault.py +0 -0
  312. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/adapters/openai.py +0 -0
  313. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/pyproject.toml +0 -0
  314. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/tests/__init__.py +0 -0
  315. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/tests/test_azure_blob_adapter.py +0 -0
  316. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/tests/test_azure_cosmos_adapter.py +0 -0
  317. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/tests/test_azure_keyvault_adapter.py +0 -0
  318. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/azure/tests/test_azure_openai_adapter.py +0 -0
  319. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/README.md +0 -0
  320. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/__init__.py +0 -0
  321. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/examples/01_simple_pandas_transform.py +0 -0
  322. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/examples/02_simple_pandas_only.py +0 -0
  323. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/examples/03_file_io_pipeline.py +0 -0
  324. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/examples/test_pandas_transform.py +0 -0
  325. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag.toml +0 -0
  326. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/__init__.py +0 -0
  327. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/__init__.py +0 -0
  328. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/api_extract.py +0 -0
  329. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/base_node_factory.py +0 -0
  330. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/file_io.py +0 -0
  331. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/pandas_transform.py +0 -0
  332. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/hexdag_etl/nodes/sql_extract_load.py +0 -0
  333. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/pyproject.toml +0 -0
  334. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/test_transform.py +0 -0
  335. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/hexdag_etl/tests/test_plugin_integration.py +0 -0
  336. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/LICENSE +0 -0
  337. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/README.md +0 -0
  338. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/__init__.py +0 -0
  339. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/adapters/__init__.py +0 -0
  340. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/adapters/mysql.py +0 -0
  341. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/mysql_adapter.py +0 -0
  342. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/pyproject.toml +0 -0
  343. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/mysql_adapter/tests/test_mysql_adapter.py +0 -0
  344. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/pyproject.toml +0 -0
  345. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/README.md +0 -0
  346. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/__init__.py +0 -0
  347. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/__init__.py +0 -0
  348. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/file/__init__.py +0 -0
  349. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/file/local.py +0 -0
  350. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/sql/__init__.py +0 -0
  351. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/sql/base.py +0 -0
  352. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/sql/collection_storage.py +0 -0
  353. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/sql/mysql.py +0 -0
  354. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/sql/postgresql.py +0 -0
  355. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/vector/__init__.py +0 -0
  356. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/vector/chromadb.py +0 -0
  357. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/vector/in_memory.py +0 -0
  358. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/adapters/vector/pgvector.py +0 -0
  359. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/ports/__init__.py +0 -0
  360. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/ports/vector_store.py +0 -0
  361. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/tests/__init__.py +0 -0
  362. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/tests/test_local_file_storage.py +0 -0
  363. {hexdag-0.7.0.dev11 → hexdag-0.7.0.dev13}/hexdag_plugins/storage/tests/test_sql_adapters.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hexdag
3
- Version: 0.7.0.dev11
3
+ Version: 0.7.0.dev13
4
4
  Summary: Lightweight DAG orchestration framework with enterprise pipeline capabilities
5
5
  Project-URL: Homepage, https://hexdag.ai
6
6
  Project-URL: Repository, https://github.com/omniviser/hexdag
@@ -41,6 +41,7 @@ Requires-Dist: nbformat>=5.9.0; extra == 'all'
41
41
  Requires-Dist: openai>=1.0.0; extra == 'all'
42
42
  Requires-Dist: pandas>=2.1.0; extra == 'all'
43
43
  Requires-Dist: pgvector>=0.3.0; extra == 'all'
44
+ Requires-Dist: redis>=5.0.0; extra == 'all'
44
45
  Requires-Dist: sqlalchemy>=2.0.0; extra == 'all'
45
46
  Provides-Extra: anthropic
46
47
  Requires-Dist: anthropic>=0.25.0; extra == 'anthropic'
@@ -58,6 +59,8 @@ Requires-Dist: nbformat>=5.9.0; extra == 'notebooks'
58
59
  Requires-Dist: pandas>=2.1.0; extra == 'notebooks'
59
60
  Provides-Extra: openai
60
61
  Requires-Dist: openai>=1.0.0; extra == 'openai'
62
+ Provides-Extra: redis
63
+ Requires-Dist: redis>=5.0.0; extra == 'redis'
61
64
  Provides-Extra: storage-all
62
65
  Requires-Dist: aiomysql>=0.2.0; extra == 'storage-all'
63
66
  Requires-Dist: aiosqlite>=0.20.0; extra == 'storage-all'
@@ -29,6 +29,7 @@ from hexdag.kernel.config.models import (
29
29
  HexDAGConfig,
30
30
  LoggingConfig,
31
31
  ManifestEntry,
32
+ MCPPermissions,
32
33
  )
33
34
  from hexdag.kernel.logging import get_logger
34
35
  from hexdag.kernel.orchestration.models import OrchestratorConfig
@@ -377,6 +378,15 @@ class ConfigLoader:
377
378
  config.caps = DefaultCaps(
378
379
  default_set=caps_data.get("default_set"),
379
380
  deny=caps_data.get("deny"),
381
+ profiles=caps_data.get("profiles"),
382
+ )
383
+
384
+ # Parse MCP permissions
385
+ if "mcp_permissions" in data:
386
+ mcp_data = data["mcp_permissions"]
387
+ config.mcp_permissions = MCPPermissions(
388
+ default_profile=mcp_data.get("default_profile", "read-only"),
389
+ client_profiles=mcp_data.get("client_profiles", {}),
380
390
  )
381
391
 
382
392
  return config
@@ -1,20 +1,26 @@
1
1
  """Entity plugins for the YAML pipeline builder.
2
2
 
3
3
  These plugins build specific entity types from YAML configuration:
4
+ - AdapterDefinitionPlugin: Process Adapter definitions (kind: Adapter)
4
5
  - ConfigDefinitionPlugin: Process Config definitions (kind: Config)
5
6
  - MacroDefinitionPlugin: Process Macro definitions (kind: Macro)
6
7
  - MacroEntityPlugin: Expand macro invocations into subgraphs
8
+ - MiddlewareDefinitionPlugin: Process Middleware definitions (kind: Middleware)
7
9
  - NodeEntityPlugin: Build regular nodes (llm_node, function_node, etc.)
8
10
  """
9
11
 
12
+ from hexdag.compiler.plugins.adapter_definition import AdapterDefinitionPlugin
10
13
  from hexdag.compiler.plugins.config_definition import ConfigDefinitionPlugin
11
14
  from hexdag.compiler.plugins.macro_definition import MacroDefinitionPlugin
12
15
  from hexdag.compiler.plugins.macro_entity import MacroEntityPlugin
16
+ from hexdag.compiler.plugins.middleware_definition import MiddlewareDefinitionPlugin
13
17
  from hexdag.compiler.plugins.node_entity import NodeEntityPlugin
14
18
 
15
19
  __all__ = [
20
+ "AdapterDefinitionPlugin",
16
21
  "ConfigDefinitionPlugin",
17
22
  "MacroDefinitionPlugin",
18
23
  "MacroEntityPlugin",
24
+ "MiddlewareDefinitionPlugin",
19
25
  "NodeEntityPlugin",
20
26
  ]
@@ -0,0 +1,140 @@
1
+ """Plugin for handling Adapter definitions (kind: Adapter).
2
+
3
+ Standalone ``kind: Adapter`` manifests define reusable adapter configurations
4
+ that can be referenced by name from ``spec.ports.<name>.ref``.
5
+
6
+ Example YAML::
7
+
8
+ apiVersion: hexdag/v1
9
+ kind: Adapter
10
+ metadata:
11
+ name: production-openai
12
+ description: Production OpenAI with low temperature
13
+ spec:
14
+ class: hexdag.stdlib.adapters.openai.OpenAIAdapter
15
+ config:
16
+ model: gpt-4o
17
+ temperature: 0.3
18
+ api_key: ${OPENAI_API_KEY}
19
+
20
+ Reference in a pipeline::
21
+
22
+ spec:
23
+ ports:
24
+ llm:
25
+ ref: production-openai
26
+ config: # optional overrides merged on top
27
+ temperature: 0.9
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ from typing import TYPE_CHECKING, Any
33
+
34
+ from hexdag.kernel.exceptions import YamlPipelineBuilderError
35
+ from hexdag.kernel.logging import get_logger
36
+
37
+ if TYPE_CHECKING:
38
+ from hexdag.compiler.yaml_builder import YamlPipelineBuilder
39
+ from hexdag.kernel.domain.dag import DirectedGraph, NodeSpec
40
+
41
+ logger = get_logger(__name__)
42
+
43
+ # Module-level registry for named adapter definitions
44
+ _adapter_registry: dict[str, dict[str, Any]] = {}
45
+
46
+
47
+ def get_adapter_definition(name: str) -> dict[str, Any] | None:
48
+ """Look up a registered adapter definition by name.
49
+
50
+ Parameters
51
+ ----------
52
+ name : str
53
+ Adapter name (from ``metadata.name``)
54
+
55
+ Returns
56
+ -------
57
+ dict[str, Any] | None
58
+ Adapter definition dict with ``class`` and ``config`` keys,
59
+ or None if not registered
60
+ """
61
+ return _adapter_registry.get(name)
62
+
63
+
64
+ def clear_adapter_registry() -> None:
65
+ """Clear all registered adapter definitions (for testing)."""
66
+ _adapter_registry.clear()
67
+
68
+
69
+ class AdapterDefinitionPlugin:
70
+ """Plugin for handling Adapter definitions (kind: Adapter).
71
+
72
+ Processes ``kind: Adapter`` YAML documents and registers the
73
+ adapter configuration for later reference by name. Does not add
74
+ nodes to the graph.
75
+ """
76
+
77
+ def can_handle(self, node_config: dict[str, Any]) -> bool:
78
+ """Handle Adapter kind."""
79
+ return node_config.get("kind") == "Adapter"
80
+
81
+ def build(
82
+ self, node_config: dict[str, Any], builder: YamlPipelineBuilder, graph: DirectedGraph
83
+ ) -> NodeSpec | None:
84
+ """Register named adapter definition.
85
+
86
+ Parameters
87
+ ----------
88
+ node_config : dict[str, Any]
89
+ Adapter definition configuration
90
+ builder : YamlPipelineBuilder
91
+ Builder instance (unused)
92
+ graph : DirectedGraph
93
+ Graph instance (unused — definitions don't add nodes)
94
+
95
+ Returns
96
+ -------
97
+ None
98
+ Adapter definitions don't add nodes to the graph
99
+ """
100
+ metadata = node_config.get("metadata", {})
101
+ name = metadata.get("name")
102
+ if not name:
103
+ raise YamlPipelineBuilderError("Adapter definition missing 'metadata.name'")
104
+
105
+ spec = node_config.get("spec", {})
106
+ adapter_class = spec.get("class")
107
+
108
+ if not adapter_class:
109
+ raise YamlPipelineBuilderError(
110
+ f"Adapter '{name}' missing 'spec.class'. "
111
+ f"Adapter definitions must specify the adapter class module path."
112
+ )
113
+
114
+ if not isinstance(adapter_class, str):
115
+ raise YamlPipelineBuilderError(
116
+ f"Adapter '{name}' spec.class must be a module path string, "
117
+ f"got {type(adapter_class).__name__}"
118
+ )
119
+
120
+ config = spec.get("config", {})
121
+ if not isinstance(config, dict):
122
+ raise YamlPipelineBuilderError(
123
+ f"Adapter '{name}' spec.config must be a dict, got {type(config).__name__}"
124
+ )
125
+
126
+ capabilities = spec.get("capabilities")
127
+
128
+ entry: dict[str, Any] = {"class": adapter_class, "config": config}
129
+ if capabilities is not None:
130
+ entry["capabilities"] = capabilities
131
+
132
+ _adapter_registry[name] = entry
133
+
134
+ logger.info(
135
+ "Registered adapter definition '{}' (class={})",
136
+ name,
137
+ adapter_class,
138
+ )
139
+
140
+ return None
@@ -125,6 +125,12 @@ class SystemBuilder:
125
125
  "ports": spec.get("ports", {}),
126
126
  "policies": spec.get("policies", {}),
127
127
  "services": spec.get("services", {}),
128
+ "state_machines": spec.get("state_machines", {}),
129
+ "states": spec.get("states", {}),
130
+ "on_transition": spec.get("on_transition", {}),
131
+ "observers": spec.get("observers", []),
132
+ "memory": spec.get("memory", {}),
133
+ "gc": spec.get("gc", {}),
128
134
  })
129
135
  except Exception as e:
130
136
  raise SystemBuildError(f"System validation error: {e}") from e
@@ -132,15 +138,23 @@ class SystemBuilder:
132
138
  # 5. Validate pipeline paths exist
133
139
  self._validate_pipeline_paths(system_config, resolved_base)
134
140
 
135
- # 6. Validate pipe DAG is acyclic
136
- self._validate_no_cycles(system_config)
141
+ # 6. Validate pipe DAG is acyclic (only for non-lifecycle systems)
142
+ if not system_config.is_lifecycle:
143
+ self._validate_no_cycles(system_config)
144
+
145
+ # 7. Validate lifecycle constraints (if state machines declared)
146
+ if system_config.is_lifecycle:
147
+ self._validate_lifecycle(system_config)
137
148
 
138
149
  system_name = metadata.get("name", "unnamed")
150
+ mode = "lifecycle" if system_config.is_lifecycle else "dag"
139
151
  logger.info(
140
- "Built system '{}': {} processes, {} pipes",
152
+ "Built system '{}' ({}): {} processes, {} pipes, {} state machines",
141
153
  system_name,
154
+ mode,
142
155
  len(system_config.processes),
143
156
  len(system_config.pipes),
157
+ len(system_config.state_machines),
144
158
  )
145
159
 
146
160
  return system_config
@@ -201,6 +215,75 @@ class SystemBuilder:
201
215
  "Cycle detected in pipe DAG. Processes must form a directed acyclic graph."
202
216
  )
203
217
 
218
+ @staticmethod
219
+ def _validate_lifecycle(config: SystemConfig) -> None:
220
+ """Validate lifecycle-mode constraints.
221
+
222
+ Ensures that ``states`` and ``on_transition`` reference valid
223
+ process names and valid state machine states.
224
+
225
+ Raises
226
+ ------
227
+ SystemBuildError
228
+ If lifecycle configuration is invalid.
229
+ """
230
+ process_names = set(config.process_names)
231
+
232
+ # Collect all valid states from state machines
233
+ all_states: set[str] = set()
234
+ for sm_spec in config.state_machines.values():
235
+ transitions = sm_spec.get("transitions", {})
236
+ for from_state, targets in transitions.items():
237
+ all_states.add(from_state)
238
+ if isinstance(targets, list):
239
+ for t in targets:
240
+ if isinstance(t, str):
241
+ all_states.add(t)
242
+ elif isinstance(t, dict) and "to" in t:
243
+ all_states.add(t["to"])
244
+ initial = sm_spec.get("initial")
245
+ if initial:
246
+ all_states.add(initial)
247
+
248
+ # Validate spec.states references
249
+ for state_name, state_spec in config.states.items():
250
+ if state_name not in all_states:
251
+ raise SystemBuildError(
252
+ f"spec.states references unknown state '{state_name}'. "
253
+ f"Valid states: {sorted(all_states)}"
254
+ )
255
+ on_enter = state_spec.get("on_enter")
256
+ if on_enter and on_enter not in process_names:
257
+ raise SystemBuildError(
258
+ f"State '{state_name}' references unknown process "
259
+ f"'{on_enter}'. Declared processes: {sorted(process_names)}"
260
+ )
261
+
262
+ # Validate spec.on_transition references
263
+ for transition_key, transition_spec in config.on_transition.items():
264
+ parts = [p.strip() for p in transition_key.split("->")]
265
+ if len(parts) != 2: # noqa: PLR2004
266
+ raise SystemBuildError(
267
+ f"Invalid on_transition key '{transition_key}'. "
268
+ "Expected format: 'FROM_STATE -> TO_STATE'"
269
+ )
270
+ from_state, to_state = parts
271
+ if from_state not in all_states:
272
+ raise SystemBuildError(
273
+ f"on_transition '{transition_key}' references unknown state '{from_state}'"
274
+ )
275
+ if to_state not in all_states:
276
+ raise SystemBuildError(
277
+ f"on_transition '{transition_key}' references unknown state '{to_state}'"
278
+ )
279
+ process_name = transition_spec.get("process")
280
+ if process_name and process_name not in process_names:
281
+ raise SystemBuildError(
282
+ f"on_transition '{transition_key}' references unknown "
283
+ f"process '{process_name}'. "
284
+ f"Declared processes: {sorted(process_names)}"
285
+ )
286
+
204
287
  @staticmethod
205
288
  def topological_order(config: SystemConfig) -> list[str]:
206
289
  """Compute topological execution order from the pipe DAG.
@@ -20,6 +20,7 @@ import yaml
20
20
 
21
21
  # Re-export extracted classes for backward compatibility.
22
22
  # Existing code that imports from ``yaml_builder`` continues to work.
23
+ from hexdag.compiler.plugins.adapter_definition import AdapterDefinitionPlugin # noqa: F401
23
24
  from hexdag.compiler.plugins.config_definition import ConfigDefinitionPlugin # noqa: F401
24
25
  from hexdag.compiler.plugins.macro_definition import MacroDefinitionPlugin # noqa: F401
25
26
  from hexdag.compiler.plugins.macro_entity import MacroEntityPlugin # noqa: F401
@@ -158,6 +159,7 @@ class YamlPipelineBuilder:
158
159
 
159
160
  # Entity plugins (build specific entity types)
160
161
  self.entity_plugins.append(ConfigDefinitionPlugin()) # Process Config definitions
162
+ self.entity_plugins.append(AdapterDefinitionPlugin()) # Process Adapter definitions
161
163
  self.entity_plugins.append(MiddlewareDefinitionPlugin()) # Process Middleware definitions
162
164
  self.entity_plugins.append(MacroDefinitionPlugin()) # Process Macro definitions
163
165
  self.entity_plugins.append(MacroEntityPlugin()) # Then macro invocations
@@ -230,6 +232,13 @@ class YamlPipelineBuilder:
230
232
  if not isinstance(plugin, TemplatePlugin):
231
233
  processed_doc = plugin.process(processed_doc)
232
234
  self._process_config_definition(processed_doc)
235
+ elif kind == "Adapter":
236
+ # Process Adapter definition
237
+ processed_doc = doc
238
+ for plugin in self.preprocess_plugins:
239
+ if not isinstance(plugin, TemplatePlugin):
240
+ processed_doc = plugin.process(processed_doc)
241
+ self._process_adapter_definition(processed_doc)
233
242
  elif kind == "Middleware":
234
243
  # Process Middleware definition
235
244
  processed_doc = doc
@@ -308,7 +317,9 @@ class YamlPipelineBuilder:
308
317
  """
309
318
  # Filter out Config, Macro, and Middleware definitions - they're processed separately
310
319
  pipeline_docs = [
311
- doc for doc in documents if doc.get("kind") not in ("Macro", "Config", "Middleware")
320
+ doc
321
+ for doc in documents
322
+ if doc.get("kind") not in ("Macro", "Config", "Middleware", "Adapter")
312
323
  ]
313
324
 
314
325
  if not pipeline_docs:
@@ -416,6 +427,27 @@ class YamlPipelineBuilder:
416
427
 
417
428
  middleware_plugin.build(middleware_doc, self, temp_graph)
418
429
 
430
+ def _process_adapter_definition(self, adapter_doc: dict[str, Any]) -> None:
431
+ """Process a kind: Adapter document and register its definition.
432
+
433
+ Parameters
434
+ ----------
435
+ adapter_doc : dict[str, Any]
436
+ Validated Adapter document
437
+ """
438
+ temp_graph = DirectedGraph()
439
+
440
+ adapter_plugin = next(
441
+ (p for p in self.entity_plugins if isinstance(p, AdapterDefinitionPlugin)), None
442
+ )
443
+
444
+ if adapter_plugin is None:
445
+ raise YamlPipelineBuilderError(
446
+ "AdapterDefinitionPlugin not found. Cannot process Adapter definitions."
447
+ )
448
+
449
+ adapter_plugin.build(adapter_doc, self, temp_graph)
450
+
419
451
  def _process_macro_definitions(self, macro_configs: list[dict[str, Any]]) -> None:
420
452
  """Process macro definitions and register them.
421
453
 
@@ -1,10 +1,13 @@
1
1
  """YAML Pipeline Validator - Validates pipeline configurations."""
2
2
 
3
+ import difflib
3
4
  from collections.abc import Iterator
4
5
  from typing import Any
5
6
 
7
+ from hexdag.compiler.reference_resolver import _BUILTIN_NAMES, _NODE_FIELD_RE, _RESERVED_PREFIXES
6
8
  from hexdag.kernel.domain.dag import DirectedGraph
7
9
  from hexdag.kernel.domain.pipeline_config import BaseNodeConfig
10
+ from hexdag.kernel.expression_parser import ALLOWED_FUNCTIONS
8
11
 
9
12
  # Separator for namespace:name format
10
13
  NAMESPACE_SEPARATOR = ":"
@@ -319,6 +322,9 @@ class YamlValidator:
319
322
  # Reuse cached node_ids and macro_instances for dependency validation
320
323
  self._validate_dependencies_with_cache(nodes, result, node_ids, macro_instances)
321
324
 
325
+ # Validate expression/mapping naming to prevent ambiguous resolution
326
+ self._validate_naming_collisions(nodes, result, node_ids, macro_instances)
327
+
322
328
  return result
323
329
 
324
330
  def _validate_manifest_structure(self, config: Any, result: ValidationReport) -> None:
@@ -368,6 +374,14 @@ class YamlValidator:
368
374
  # Skip pipeline-specific validation for Middleware kind
369
375
  return
370
376
 
377
+ if kind == "Adapter":
378
+ # Adapter has: metadata, spec.class (no nodes)
379
+ spec = config.get("spec", {})
380
+ if not isinstance(spec, dict) or "class" not in spec:
381
+ result.add_error("Adapter definition must contain 'spec.class' field")
382
+ # Skip pipeline-specific validation for Adapter kind
383
+ return
384
+
371
385
  # For Pipeline and other kinds, validate spec
372
386
  if "spec" not in config:
373
387
  result.add_error("Configuration must contain 'spec' field")
@@ -639,3 +653,118 @@ class YamlValidator:
639
653
  # Check for cycles using DirectedGraph's public static method
640
654
  if cycle_message := DirectedGraph.detect_cycle(dependency_graph):
641
655
  result.add_error(cycle_message)
656
+
657
+ def _validate_naming_collisions(
658
+ self,
659
+ nodes: list[dict[str, Any]],
660
+ result: ValidationReport,
661
+ node_ids: set[str],
662
+ macro_instances: set[str],
663
+ ) -> None:
664
+ """Validate that expression variables and input_mapping aliases don't collide.
665
+
666
+ Checks (all hard errors):
667
+ 1. Expression variable name == node name
668
+ 2. Expression variable name == builtin function name
669
+ 3. input_mapping alias == node name
670
+ 4. First path segment in input_mapping/expressions is a known reference
671
+ """
672
+ builtin_names = frozenset(ALLOWED_FUNCTIONS.keys())
673
+
674
+ for node in nodes:
675
+ node_id = node.get("metadata", {}).get("name")
676
+ if not node_id:
677
+ continue
678
+
679
+ spec = node.get("spec", {})
680
+ expressions = spec.get("expressions", {})
681
+ input_mapping = spec.get("input_mapping", {})
682
+
683
+ if not isinstance(expressions, dict):
684
+ expressions = {}
685
+ if not isinstance(input_mapping, dict):
686
+ input_mapping = {}
687
+
688
+ # Check 1: Expression variable names vs node names
689
+ for var_name in expressions:
690
+ if var_name in node_ids:
691
+ result.add_error(
692
+ f"Node '{node_id}': Expression variable '{var_name}' "
693
+ f"collides with node '{var_name}'. Rename the variable "
694
+ f"or the node to avoid ambiguous resolution."
695
+ )
696
+
697
+ # Check 2: Expression variable names vs builtin functions
698
+ for var_name in expressions:
699
+ if var_name in builtin_names:
700
+ result.add_error(
701
+ f"Node '{node_id}': Expression variable '{var_name}' "
702
+ f"collides with built-in function '{var_name}'. "
703
+ f"Choose a different variable name."
704
+ )
705
+
706
+ # Check 3: input_mapping alias vs node names
707
+ for alias in input_mapping:
708
+ if alias in node_ids:
709
+ result.add_error(
710
+ f"Node '{node_id}': input_mapping alias '{alias}' "
711
+ f"collides with node '{alias}'. Choose a different alias."
712
+ )
713
+
714
+ # Check 4: First path segment validation in expressions
715
+ # Build the set of valid first segments for this node
716
+ valid_first_segments = (
717
+ node_ids
718
+ | set(expressions.keys())
719
+ | set(input_mapping.keys())
720
+ | _RESERVED_PREFIXES
721
+ | _BUILTIN_NAMES
722
+ | {"input", "state"}
723
+ )
724
+
725
+ for var_name, expr in expressions.items():
726
+ if not isinstance(expr, str):
727
+ continue
728
+ self._check_first_segments(
729
+ expr, var_name, node_id, valid_first_segments, node_ids, macro_instances, result
730
+ )
731
+
732
+ for alias, source in input_mapping.items():
733
+ if not isinstance(source, str):
734
+ continue
735
+ # Skip $input references and expressions
736
+ if source.startswith("$input") or source == "$input":
737
+ continue
738
+ self._check_first_segments(
739
+ source, alias, node_id, valid_first_segments, node_ids, macro_instances, result
740
+ )
741
+
742
+ @staticmethod
743
+ def _check_first_segments(
744
+ text: str,
745
+ field_name: str,
746
+ node_id: str,
747
+ valid_first_segments: set[str],
748
+ node_ids: set[str],
749
+ macro_instances: set[str],
750
+ result: "ValidationReport",
751
+ ) -> None:
752
+ """Check that first path segments in text are known references."""
753
+ for match in _NODE_FIELD_RE.finditer(text):
754
+ candidate = match.group(1)
755
+ if candidate in _RESERVED_PREFIXES or candidate in _BUILTIN_NAMES:
756
+ continue
757
+ if candidate in valid_first_segments:
758
+ continue
759
+ # Check if candidate is a macro-expanded node name
760
+ if any(candidate.startswith(f"{mi}_") for mi in macro_instances):
761
+ continue
762
+ # Unknown first segment — likely a typo
763
+ close_matches = difflib.get_close_matches(candidate, sorted(node_ids), n=3, cutoff=0.6)
764
+ suggestion = ""
765
+ if close_matches:
766
+ suggestion = f" Did you mean: {', '.join(close_matches)}?"
767
+ result.add_error(
768
+ f"Node '{node_id}': Unknown reference '{candidate}' "
769
+ f"in field '{field_name}'.{suggestion}"
770
+ )
@@ -15,6 +15,7 @@ from uuid import uuid4
15
15
  from hexdag.kernel.logging import get_logger
16
16
 
17
17
  if TYPE_CHECKING:
18
+ from hexdag.kernel.domain.caps import CapSet
18
19
  from hexdag.kernel.pipeline_runner import PipelineRunner
19
20
 
20
21
  logger = get_logger(__name__)
@@ -46,9 +47,11 @@ class LocalPipelineSpawner:
46
47
  self,
47
48
  runner: PipelineRunner,
48
49
  pipeline_dir: str | None = None,
50
+ cap_set: CapSet | None = None,
49
51
  ) -> None:
50
52
  self._runner = runner
51
53
  self._pipeline_dir = pipeline_dir
54
+ self._cap_set: CapSet | None = cap_set
52
55
  self._runs: dict[str, _RunState] = {}
53
56
  self._tasks: dict[str, asyncio.Task[dict[str, Any]]] = {}
54
57
 
@@ -62,12 +65,22 @@ class LocalPipelineSpawner:
62
65
  parent_run_id: str | None = None,
63
66
  wait: bool = False,
64
67
  timeout: float | None = None,
68
+ cap_set: CapSet | None = None,
65
69
  ) -> str:
66
70
  """Spawn a pipeline run.
67
71
 
68
72
  If ``wait=True``, blocks until the pipeline completes (or times out).
69
73
  Otherwise, runs in the background and returns immediately.
74
+
75
+ If ``cap_set`` is provided, the child's effective capabilities are
76
+ the intersection of the parent spawner's caps and the requested caps
77
+ (narrowing-only — the child can never have more caps than the parent).
70
78
  """
79
+ # Compute effective child caps via narrowing chain
80
+ effective_caps = self._narrow_caps(cap_set)
81
+ # Store for future use when we pass caps to child runners
82
+ _ = effective_caps # reserved for child runner integration
83
+
71
84
  run_id = str(uuid4())
72
85
  self._runs[run_id] = _RunState(
73
86
  run_id=run_id,
@@ -160,6 +173,21 @@ class LocalPipelineSpawner:
160
173
  # Internal
161
174
  # ------------------------------------------------------------------
162
175
 
176
+ def _narrow_caps(self, child_caps: CapSet | None) -> CapSet | None:
177
+ """Compute effective child capabilities via narrowing chain.
178
+
179
+ If neither the spawner nor the caller provides caps, returns None
180
+ (unrestricted). If only one side provides caps, uses that. If both
181
+ provide caps, intersects (narrows).
182
+ """
183
+ if self._cap_set is None and child_caps is None:
184
+ return None
185
+ if self._cap_set is None:
186
+ return child_caps
187
+ if child_caps is None:
188
+ return self._cap_set
189
+ return self._cap_set.intersect(child_caps)
190
+
163
191
  async def _execute(
164
192
  self,
165
193
  run_id: str,