hexdag 0.5.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hexdag/__init__.py +116 -0
- hexdag/__main__.py +30 -0
- hexdag/adapters/executors/__init__.py +5 -0
- hexdag/adapters/executors/local_executor.py +316 -0
- hexdag/builtin/__init__.py +6 -0
- hexdag/builtin/adapters/__init__.py +51 -0
- hexdag/builtin/adapters/anthropic/__init__.py +5 -0
- hexdag/builtin/adapters/anthropic/anthropic_adapter.py +151 -0
- hexdag/builtin/adapters/database/__init__.py +6 -0
- hexdag/builtin/adapters/database/csv/csv_adapter.py +249 -0
- hexdag/builtin/adapters/database/pgvector/__init__.py +5 -0
- hexdag/builtin/adapters/database/pgvector/pgvector_adapter.py +478 -0
- hexdag/builtin/adapters/database/sqlalchemy/sqlalchemy_adapter.py +252 -0
- hexdag/builtin/adapters/database/sqlite/__init__.py +5 -0
- hexdag/builtin/adapters/database/sqlite/sqlite_adapter.py +410 -0
- hexdag/builtin/adapters/local/README.md +59 -0
- hexdag/builtin/adapters/local/__init__.py +7 -0
- hexdag/builtin/adapters/local/local_observer_manager.py +696 -0
- hexdag/builtin/adapters/memory/__init__.py +47 -0
- hexdag/builtin/adapters/memory/file_memory_adapter.py +297 -0
- hexdag/builtin/adapters/memory/in_memory_memory.py +216 -0
- hexdag/builtin/adapters/memory/schemas.py +57 -0
- hexdag/builtin/adapters/memory/session_memory.py +178 -0
- hexdag/builtin/adapters/memory/sqlite_memory_adapter.py +215 -0
- hexdag/builtin/adapters/memory/state_memory.py +280 -0
- hexdag/builtin/adapters/mock/README.md +89 -0
- hexdag/builtin/adapters/mock/__init__.py +15 -0
- hexdag/builtin/adapters/mock/hexdag.toml +50 -0
- hexdag/builtin/adapters/mock/mock_database.py +225 -0
- hexdag/builtin/adapters/mock/mock_embedding.py +223 -0
- hexdag/builtin/adapters/mock/mock_llm.py +177 -0
- hexdag/builtin/adapters/mock/mock_tool_adapter.py +192 -0
- hexdag/builtin/adapters/mock/mock_tool_router.py +232 -0
- hexdag/builtin/adapters/openai/__init__.py +5 -0
- hexdag/builtin/adapters/openai/openai_adapter.py +634 -0
- hexdag/builtin/adapters/secret/__init__.py +7 -0
- hexdag/builtin/adapters/secret/local_secret_adapter.py +248 -0
- hexdag/builtin/adapters/unified_tool_router.py +280 -0
- hexdag/builtin/macros/__init__.py +17 -0
- hexdag/builtin/macros/conversation_agent.py +390 -0
- hexdag/builtin/macros/llm_macro.py +151 -0
- hexdag/builtin/macros/reasoning_agent.py +423 -0
- hexdag/builtin/macros/tool_macro.py +380 -0
- hexdag/builtin/nodes/__init__.py +38 -0
- hexdag/builtin/nodes/_discovery.py +123 -0
- hexdag/builtin/nodes/agent_node.py +696 -0
- hexdag/builtin/nodes/base_node_factory.py +242 -0
- hexdag/builtin/nodes/composite_node.py +926 -0
- hexdag/builtin/nodes/data_node.py +201 -0
- hexdag/builtin/nodes/expression_node.py +487 -0
- hexdag/builtin/nodes/function_node.py +454 -0
- hexdag/builtin/nodes/llm_node.py +491 -0
- hexdag/builtin/nodes/loop_node.py +920 -0
- hexdag/builtin/nodes/mapped_input.py +518 -0
- hexdag/builtin/nodes/port_call_node.py +269 -0
- hexdag/builtin/nodes/tool_call_node.py +195 -0
- hexdag/builtin/nodes/tool_utils.py +390 -0
- hexdag/builtin/prompts/__init__.py +68 -0
- hexdag/builtin/prompts/base.py +422 -0
- hexdag/builtin/prompts/chat_prompts.py +303 -0
- hexdag/builtin/prompts/error_correction_prompts.py +320 -0
- hexdag/builtin/prompts/tool_prompts.py +160 -0
- hexdag/builtin/tools/builtin_tools.py +84 -0
- hexdag/builtin/tools/database_tools.py +164 -0
- hexdag/cli/__init__.py +17 -0
- hexdag/cli/__main__.py +7 -0
- hexdag/cli/commands/__init__.py +27 -0
- hexdag/cli/commands/build_cmd.py +812 -0
- hexdag/cli/commands/create_cmd.py +208 -0
- hexdag/cli/commands/docs_cmd.py +293 -0
- hexdag/cli/commands/generate_types_cmd.py +252 -0
- hexdag/cli/commands/init_cmd.py +188 -0
- hexdag/cli/commands/pipeline_cmd.py +494 -0
- hexdag/cli/commands/plugin_dev_cmd.py +529 -0
- hexdag/cli/commands/plugins_cmd.py +441 -0
- hexdag/cli/commands/studio_cmd.py +101 -0
- hexdag/cli/commands/validate_cmd.py +221 -0
- hexdag/cli/main.py +84 -0
- hexdag/core/__init__.py +83 -0
- hexdag/core/config/__init__.py +20 -0
- hexdag/core/config/loader.py +479 -0
- hexdag/core/config/models.py +150 -0
- hexdag/core/configurable.py +294 -0
- hexdag/core/context/__init__.py +37 -0
- hexdag/core/context/execution_context.py +378 -0
- hexdag/core/docs/__init__.py +26 -0
- hexdag/core/docs/extractors.py +678 -0
- hexdag/core/docs/generators.py +890 -0
- hexdag/core/docs/models.py +120 -0
- hexdag/core/domain/__init__.py +10 -0
- hexdag/core/domain/dag.py +1225 -0
- hexdag/core/exceptions.py +234 -0
- hexdag/core/expression_parser.py +569 -0
- hexdag/core/logging.py +449 -0
- hexdag/core/models/__init__.py +17 -0
- hexdag/core/models/base.py +138 -0
- hexdag/core/orchestration/__init__.py +46 -0
- hexdag/core/orchestration/body_executor.py +481 -0
- hexdag/core/orchestration/components/__init__.py +97 -0
- hexdag/core/orchestration/components/adapter_lifecycle_manager.py +113 -0
- hexdag/core/orchestration/components/checkpoint_manager.py +134 -0
- hexdag/core/orchestration/components/execution_coordinator.py +360 -0
- hexdag/core/orchestration/components/health_check_manager.py +176 -0
- hexdag/core/orchestration/components/input_mapper.py +143 -0
- hexdag/core/orchestration/components/lifecycle_manager.py +583 -0
- hexdag/core/orchestration/components/node_executor.py +377 -0
- hexdag/core/orchestration/components/secret_manager.py +202 -0
- hexdag/core/orchestration/components/wave_executor.py +158 -0
- hexdag/core/orchestration/constants.py +17 -0
- hexdag/core/orchestration/events/README.md +312 -0
- hexdag/core/orchestration/events/__init__.py +104 -0
- hexdag/core/orchestration/events/batching.py +330 -0
- hexdag/core/orchestration/events/decorators.py +139 -0
- hexdag/core/orchestration/events/events.py +573 -0
- hexdag/core/orchestration/events/observers/__init__.py +30 -0
- hexdag/core/orchestration/events/observers/core_observers.py +690 -0
- hexdag/core/orchestration/events/observers/models.py +111 -0
- hexdag/core/orchestration/events/taxonomy.py +269 -0
- hexdag/core/orchestration/hook_context.py +237 -0
- hexdag/core/orchestration/hooks.py +437 -0
- hexdag/core/orchestration/models.py +418 -0
- hexdag/core/orchestration/orchestrator.py +910 -0
- hexdag/core/orchestration/orchestrator_factory.py +275 -0
- hexdag/core/orchestration/port_wrappers.py +327 -0
- hexdag/core/orchestration/prompt/__init__.py +32 -0
- hexdag/core/orchestration/prompt/template.py +332 -0
- hexdag/core/pipeline_builder/__init__.py +21 -0
- hexdag/core/pipeline_builder/component_instantiator.py +386 -0
- hexdag/core/pipeline_builder/include_tag.py +265 -0
- hexdag/core/pipeline_builder/pipeline_config.py +133 -0
- hexdag/core/pipeline_builder/py_tag.py +223 -0
- hexdag/core/pipeline_builder/tag_discovery.py +268 -0
- hexdag/core/pipeline_builder/yaml_builder.py +1196 -0
- hexdag/core/pipeline_builder/yaml_validator.py +569 -0
- hexdag/core/ports/__init__.py +65 -0
- hexdag/core/ports/api_call.py +133 -0
- hexdag/core/ports/database.py +489 -0
- hexdag/core/ports/embedding.py +215 -0
- hexdag/core/ports/executor.py +237 -0
- hexdag/core/ports/file_storage.py +117 -0
- hexdag/core/ports/healthcheck.py +87 -0
- hexdag/core/ports/llm.py +551 -0
- hexdag/core/ports/memory.py +70 -0
- hexdag/core/ports/observer_manager.py +130 -0
- hexdag/core/ports/secret.py +145 -0
- hexdag/core/ports/tool_router.py +94 -0
- hexdag/core/ports_builder.py +623 -0
- hexdag/core/protocols.py +273 -0
- hexdag/core/resolver.py +304 -0
- hexdag/core/schema/__init__.py +9 -0
- hexdag/core/schema/generator.py +742 -0
- hexdag/core/secrets.py +242 -0
- hexdag/core/types.py +413 -0
- hexdag/core/utils/async_warnings.py +206 -0
- hexdag/core/utils/schema_conversion.py +78 -0
- hexdag/core/utils/sql_validation.py +86 -0
- hexdag/core/validation/secure_json.py +148 -0
- hexdag/core/yaml_macro.py +517 -0
- hexdag/mcp_server.py +3120 -0
- hexdag/studio/__init__.py +10 -0
- hexdag/studio/build_ui.py +92 -0
- hexdag/studio/server/__init__.py +1 -0
- hexdag/studio/server/main.py +100 -0
- hexdag/studio/server/routes/__init__.py +9 -0
- hexdag/studio/server/routes/execute.py +208 -0
- hexdag/studio/server/routes/export.py +558 -0
- hexdag/studio/server/routes/files.py +207 -0
- hexdag/studio/server/routes/plugins.py +419 -0
- hexdag/studio/server/routes/validate.py +220 -0
- hexdag/studio/ui/index.html +13 -0
- hexdag/studio/ui/package-lock.json +2992 -0
- hexdag/studio/ui/package.json +31 -0
- hexdag/studio/ui/postcss.config.js +6 -0
- hexdag/studio/ui/public/hexdag.svg +5 -0
- hexdag/studio/ui/src/App.tsx +251 -0
- hexdag/studio/ui/src/components/Canvas.tsx +408 -0
- hexdag/studio/ui/src/components/ContextMenu.tsx +187 -0
- hexdag/studio/ui/src/components/FileBrowser.tsx +123 -0
- hexdag/studio/ui/src/components/Header.tsx +181 -0
- hexdag/studio/ui/src/components/HexdagNode.tsx +193 -0
- hexdag/studio/ui/src/components/NodeInspector.tsx +512 -0
- hexdag/studio/ui/src/components/NodePalette.tsx +262 -0
- hexdag/studio/ui/src/components/NodePortsSection.tsx +403 -0
- hexdag/studio/ui/src/components/PluginManager.tsx +347 -0
- hexdag/studio/ui/src/components/PortsEditor.tsx +481 -0
- hexdag/studio/ui/src/components/PythonEditor.tsx +195 -0
- hexdag/studio/ui/src/components/ValidationPanel.tsx +105 -0
- hexdag/studio/ui/src/components/YamlEditor.tsx +196 -0
- hexdag/studio/ui/src/components/index.ts +8 -0
- hexdag/studio/ui/src/index.css +92 -0
- hexdag/studio/ui/src/main.tsx +10 -0
- hexdag/studio/ui/src/types/index.ts +123 -0
- hexdag/studio/ui/src/vite-env.d.ts +1 -0
- hexdag/studio/ui/tailwind.config.js +29 -0
- hexdag/studio/ui/tsconfig.json +37 -0
- hexdag/studio/ui/tsconfig.node.json +13 -0
- hexdag/studio/ui/vite.config.ts +35 -0
- hexdag/visualization/__init__.py +69 -0
- hexdag/visualization/dag_visualizer.py +1020 -0
- hexdag-0.5.0.dev1.dist-info/METADATA +369 -0
- hexdag-0.5.0.dev1.dist-info/RECORD +261 -0
- hexdag-0.5.0.dev1.dist-info/WHEEL +4 -0
- hexdag-0.5.0.dev1.dist-info/entry_points.txt +4 -0
- hexdag-0.5.0.dev1.dist-info/licenses/LICENSE +190 -0
- hexdag_plugins/.gitignore +43 -0
- hexdag_plugins/README.md +73 -0
- hexdag_plugins/__init__.py +1 -0
- hexdag_plugins/azure/LICENSE +21 -0
- hexdag_plugins/azure/README.md +414 -0
- hexdag_plugins/azure/__init__.py +21 -0
- hexdag_plugins/azure/azure_blob_adapter.py +450 -0
- hexdag_plugins/azure/azure_cosmos_adapter.py +383 -0
- hexdag_plugins/azure/azure_keyvault_adapter.py +314 -0
- hexdag_plugins/azure/azure_openai_adapter.py +415 -0
- hexdag_plugins/azure/pyproject.toml +107 -0
- hexdag_plugins/azure/tests/__init__.py +1 -0
- hexdag_plugins/azure/tests/test_azure_blob_adapter.py +350 -0
- hexdag_plugins/azure/tests/test_azure_cosmos_adapter.py +323 -0
- hexdag_plugins/azure/tests/test_azure_keyvault_adapter.py +330 -0
- hexdag_plugins/azure/tests/test_azure_openai_adapter.py +329 -0
- hexdag_plugins/hexdag_etl/README.md +168 -0
- hexdag_plugins/hexdag_etl/__init__.py +53 -0
- hexdag_plugins/hexdag_etl/examples/01_simple_pandas_transform.py +270 -0
- hexdag_plugins/hexdag_etl/examples/02_simple_pandas_only.py +149 -0
- hexdag_plugins/hexdag_etl/examples/03_file_io_pipeline.py +109 -0
- hexdag_plugins/hexdag_etl/examples/test_pandas_transform.py +84 -0
- hexdag_plugins/hexdag_etl/hexdag.toml +25 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/__init__.py +48 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/__init__.py +13 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/api_extract.py +230 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/base_node_factory.py +181 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/file_io.py +415 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/outlook.py +492 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/pandas_transform.py +563 -0
- hexdag_plugins/hexdag_etl/hexdag_etl/nodes/sql_extract_load.py +112 -0
- hexdag_plugins/hexdag_etl/pyproject.toml +82 -0
- hexdag_plugins/hexdag_etl/test_transform.py +54 -0
- hexdag_plugins/hexdag_etl/tests/test_plugin_integration.py +62 -0
- hexdag_plugins/mysql_adapter/LICENSE +21 -0
- hexdag_plugins/mysql_adapter/README.md +224 -0
- hexdag_plugins/mysql_adapter/__init__.py +6 -0
- hexdag_plugins/mysql_adapter/mysql_adapter.py +408 -0
- hexdag_plugins/mysql_adapter/pyproject.toml +93 -0
- hexdag_plugins/mysql_adapter/tests/test_mysql_adapter.py +259 -0
- hexdag_plugins/storage/README.md +184 -0
- hexdag_plugins/storage/__init__.py +19 -0
- hexdag_plugins/storage/file/__init__.py +5 -0
- hexdag_plugins/storage/file/local.py +325 -0
- hexdag_plugins/storage/ports/__init__.py +5 -0
- hexdag_plugins/storage/ports/vector_store.py +236 -0
- hexdag_plugins/storage/sql/__init__.py +7 -0
- hexdag_plugins/storage/sql/base.py +187 -0
- hexdag_plugins/storage/sql/mysql.py +27 -0
- hexdag_plugins/storage/sql/postgresql.py +27 -0
- hexdag_plugins/storage/tests/__init__.py +1 -0
- hexdag_plugins/storage/tests/test_local_file_storage.py +161 -0
- hexdag_plugins/storage/tests/test_sql_adapters.py +212 -0
- hexdag_plugins/storage/vector/__init__.py +7 -0
- hexdag_plugins/storage/vector/chromadb.py +223 -0
- hexdag_plugins/storage/vector/in_memory.py +285 -0
- hexdag_plugins/storage/vector/pgvector.py +502 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""Pipeline validation command for HexDAG CLI."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated, Any
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
import yaml
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.panel import Panel
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
|
|
12
|
+
from hexdag.core.pipeline_builder.yaml_validator import YamlValidator
|
|
13
|
+
|
|
14
|
+
app = typer.Typer()
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@app.command()
|
|
19
|
+
def validate(
|
|
20
|
+
yaml_file: Annotated[
|
|
21
|
+
Path,
|
|
22
|
+
typer.Argument(
|
|
23
|
+
help="Path to YAML pipeline file to validate",
|
|
24
|
+
exists=True,
|
|
25
|
+
file_okay=True,
|
|
26
|
+
dir_okay=False,
|
|
27
|
+
readable=True,
|
|
28
|
+
),
|
|
29
|
+
],
|
|
30
|
+
explain: Annotated[
|
|
31
|
+
bool,
|
|
32
|
+
typer.Option(
|
|
33
|
+
"--explain",
|
|
34
|
+
"-e",
|
|
35
|
+
help="Show detailed explanation of validation process",
|
|
36
|
+
),
|
|
37
|
+
] = False,
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Validate a YAML pipeline file against node schemas.
|
|
40
|
+
|
|
41
|
+
This command validates:
|
|
42
|
+
- YAML syntax and structure
|
|
43
|
+
- Manifest format (apiVersion, kind, metadata, spec)
|
|
44
|
+
- Node types and their schemas
|
|
45
|
+
- Required fields and constraints
|
|
46
|
+
- Dependency references
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
hexdag validate pipeline.yaml
|
|
51
|
+
hexdag validate pipeline.yaml --explain
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
# Read YAML file
|
|
55
|
+
try:
|
|
56
|
+
with Path.open(yaml_file) as f:
|
|
57
|
+
content = f.read()
|
|
58
|
+
config = yaml.safe_load(content)
|
|
59
|
+
except yaml.YAMLError as e:
|
|
60
|
+
console.print(f"[red]✗ YAML Syntax Error:[/red] {e}")
|
|
61
|
+
raise typer.Exit(1) from e
|
|
62
|
+
except OSError as e:
|
|
63
|
+
console.print(f"[red]✗ File Error:[/red] {e}")
|
|
64
|
+
raise typer.Exit(1) from e
|
|
65
|
+
|
|
66
|
+
# Validate using YamlValidator
|
|
67
|
+
validator = YamlValidator()
|
|
68
|
+
result = validator.validate(config)
|
|
69
|
+
|
|
70
|
+
# Display results
|
|
71
|
+
console.print()
|
|
72
|
+
if result.is_valid:
|
|
73
|
+
console.print(f"[green]✓ Validation successful:[/green] {yaml_file}")
|
|
74
|
+
else:
|
|
75
|
+
console.print(f"[red]✗ Validation failed:[/red] {yaml_file}")
|
|
76
|
+
|
|
77
|
+
# Show warnings
|
|
78
|
+
if result.warnings:
|
|
79
|
+
console.print()
|
|
80
|
+
console.print("[yellow]Warnings:[/yellow]")
|
|
81
|
+
for warning in result.warnings:
|
|
82
|
+
console.print(f" [yellow]⚠[/yellow] {warning}")
|
|
83
|
+
|
|
84
|
+
# Show errors
|
|
85
|
+
if result.errors:
|
|
86
|
+
console.print()
|
|
87
|
+
console.print("[red]Errors:[/red]")
|
|
88
|
+
for error in result.errors:
|
|
89
|
+
console.print(f" [red]✗[/red] {error}")
|
|
90
|
+
|
|
91
|
+
# Show suggestions
|
|
92
|
+
if result.suggestions:
|
|
93
|
+
console.print()
|
|
94
|
+
console.print("[blue]Suggestions:[/blue]")
|
|
95
|
+
for suggestion in result.suggestions:
|
|
96
|
+
console.print(f" [blue]ℹ[/blue] {suggestion}")
|
|
97
|
+
|
|
98
|
+
# Explain mode - show validation details
|
|
99
|
+
if explain:
|
|
100
|
+
console.print()
|
|
101
|
+
_explain_validation(config, result)
|
|
102
|
+
|
|
103
|
+
console.print()
|
|
104
|
+
|
|
105
|
+
# Exit with error code if validation failed
|
|
106
|
+
if not result.is_valid:
|
|
107
|
+
raise typer.Exit(1)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _explain_validation(config: dict, result: Any) -> None:
|
|
111
|
+
"""Show detailed explanation of validation process."""
|
|
112
|
+
console.print(Panel("[bold]Validation Process Explanation[/bold]", border_style="blue"))
|
|
113
|
+
|
|
114
|
+
# Show manifest structure
|
|
115
|
+
console.print("\n[bold cyan]1. Manifest Structure[/bold cyan]")
|
|
116
|
+
manifest_table = Table(show_header=True, border_style="cyan")
|
|
117
|
+
manifest_table.add_column("Field", style="green")
|
|
118
|
+
manifest_table.add_column("Value", style="white")
|
|
119
|
+
manifest_table.add_column("Status", style="yellow")
|
|
120
|
+
|
|
121
|
+
api_version = config.get("apiVersion", "missing")
|
|
122
|
+
kind = config.get("kind", "missing")
|
|
123
|
+
name = config.get("metadata", {}).get("name", "missing")
|
|
124
|
+
|
|
125
|
+
manifest_table.add_row(
|
|
126
|
+
"apiVersion",
|
|
127
|
+
str(api_version),
|
|
128
|
+
"[green]✓[/green]" if api_version != "missing" else "[red]✗[/red]",
|
|
129
|
+
)
|
|
130
|
+
manifest_table.add_row(
|
|
131
|
+
"kind", str(kind), "[green]✓[/green]" if kind != "missing" else "[red]✗[/red]"
|
|
132
|
+
)
|
|
133
|
+
manifest_table.add_row(
|
|
134
|
+
"metadata.name",
|
|
135
|
+
str(name),
|
|
136
|
+
"[green]✓[/green]" if name != "missing" else "[red]✗[/red]",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
console.print(manifest_table)
|
|
140
|
+
|
|
141
|
+
# Show node validation
|
|
142
|
+
if nodes := config.get("spec", {}).get("nodes", []):
|
|
143
|
+
console.print("\n[bold cyan]2. Node Validation[/bold cyan]")
|
|
144
|
+
node_table = Table(show_header=True, border_style="cyan")
|
|
145
|
+
node_table.add_column("Node", style="green")
|
|
146
|
+
node_table.add_column("Type", style="blue")
|
|
147
|
+
node_table.add_column("Schema", style="white")
|
|
148
|
+
node_table.add_column("Status", style="yellow")
|
|
149
|
+
|
|
150
|
+
for i, node in enumerate(nodes):
|
|
151
|
+
node_name = node.get("metadata", {}).get("name", f"node_{i}")
|
|
152
|
+
node_kind = node.get("kind", "unknown")
|
|
153
|
+
|
|
154
|
+
# Parse namespace and type
|
|
155
|
+
if ":" in node_kind:
|
|
156
|
+
namespace, node_type = node_kind.split(":", 1)
|
|
157
|
+
else:
|
|
158
|
+
namespace = "core"
|
|
159
|
+
node_type = node_kind
|
|
160
|
+
|
|
161
|
+
# Remove _node suffix if present
|
|
162
|
+
if node_type.endswith("_node"):
|
|
163
|
+
node_type = node_type[:-5]
|
|
164
|
+
|
|
165
|
+
# Check if node type is known
|
|
166
|
+
from hexdag.core.pipeline_builder.yaml_validator import KNOWN_NODE_TYPES
|
|
167
|
+
|
|
168
|
+
qualified_type = f"{namespace}:{node_type}"
|
|
169
|
+
if qualified_type in KNOWN_NODE_TYPES or node_type in KNOWN_NODE_TYPES:
|
|
170
|
+
schema_status = "[green]✓[/green] Known type"
|
|
171
|
+
elif "." in node_kind:
|
|
172
|
+
schema_status = "[blue]ℹ[/blue] Module path"
|
|
173
|
+
else:
|
|
174
|
+
schema_status = "[yellow]?[/yellow] Unknown type"
|
|
175
|
+
|
|
176
|
+
node_has_error = any(node_name in str(error) for error in result.errors)
|
|
177
|
+
status = "[red]✗[/red]" if node_has_error else "[green]✓[/green]"
|
|
178
|
+
|
|
179
|
+
node_table.add_row(node_name, f"{namespace}:{node_type}", schema_status, status)
|
|
180
|
+
|
|
181
|
+
console.print(node_table)
|
|
182
|
+
|
|
183
|
+
# Show dependency graph
|
|
184
|
+
if nodes:
|
|
185
|
+
console.print("\n[bold cyan]3. Dependency Graph[/bold cyan]")
|
|
186
|
+
dep_table = Table(show_header=True, border_style="cyan")
|
|
187
|
+
dep_table.add_column("Node", style="green")
|
|
188
|
+
dep_table.add_column("Dependencies", style="blue")
|
|
189
|
+
dep_table.add_column("Status", style="yellow")
|
|
190
|
+
|
|
191
|
+
all_node_names = {node.get("metadata", {}).get("name") for node in nodes}
|
|
192
|
+
all_node_names.discard(None)
|
|
193
|
+
|
|
194
|
+
for node in nodes:
|
|
195
|
+
node_name = node.get("metadata", {}).get("name", "unknown")
|
|
196
|
+
deps = node.get("spec", {}).get("dependencies", [])
|
|
197
|
+
|
|
198
|
+
if not deps:
|
|
199
|
+
dep_str = "-"
|
|
200
|
+
status = "[green]✓[/green]"
|
|
201
|
+
else:
|
|
202
|
+
dep_str = ", ".join(str(d) for d in deps)
|
|
203
|
+
if invalid_deps := [d for d in deps if d not in all_node_names]:
|
|
204
|
+
status = f"[red]✗[/red] Invalid: {', '.join(invalid_deps)}"
|
|
205
|
+
else:
|
|
206
|
+
status = "[green]✓[/green]"
|
|
207
|
+
|
|
208
|
+
dep_table.add_row(node_name, dep_str, status)
|
|
209
|
+
|
|
210
|
+
console.print(dep_table)
|
|
211
|
+
|
|
212
|
+
# Show validation summary
|
|
213
|
+
console.print("\n[bold cyan]4. Summary[/bold cyan]")
|
|
214
|
+
summary_text = f"""
|
|
215
|
+
Total Nodes: {len(nodes)}
|
|
216
|
+
Errors: {len(result.errors)}
|
|
217
|
+
Warnings: {len(result.warnings)}
|
|
218
|
+
Suggestions: {len(result.suggestions)}
|
|
219
|
+
Valid: {"[green]Yes[/green]" if result.is_valid else "[red]No[/red]"}
|
|
220
|
+
"""
|
|
221
|
+
console.print(Panel(summary_text.strip(), border_style="blue"))
|
hexdag/cli/main.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""HexDAG CLI - Main entrypoint."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
except ImportError:
|
|
9
|
+
print("Error: CLI dependencies not installed.")
|
|
10
|
+
print("Please install with:")
|
|
11
|
+
print(" pip install hexdag[cli]")
|
|
12
|
+
print(" or")
|
|
13
|
+
print(" uv pip install hexdag[cli]")
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
|
|
16
|
+
from hexdag.cli.commands import (
|
|
17
|
+
build_cmd,
|
|
18
|
+
create_cmd,
|
|
19
|
+
docs_cmd,
|
|
20
|
+
generate_types_cmd,
|
|
21
|
+
init_cmd,
|
|
22
|
+
pipeline_cmd,
|
|
23
|
+
plugin_dev_cmd,
|
|
24
|
+
plugins_cmd,
|
|
25
|
+
studio_cmd,
|
|
26
|
+
validate_cmd,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
app = typer.Typer(
|
|
30
|
+
name="hexdag",
|
|
31
|
+
help="HexDAG - Lightweight DAG orchestration framework with hexagonal architecture.",
|
|
32
|
+
no_args_is_help=True,
|
|
33
|
+
rich_markup_mode="rich",
|
|
34
|
+
pretty_exceptions_enable=False,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
console = Console()
|
|
38
|
+
|
|
39
|
+
app.add_typer(init_cmd.app, name="init", help="Initialize a new HexDAG project")
|
|
40
|
+
app.add_typer(plugins_cmd.app, name="plugins", help="Manage plugins and adapters")
|
|
41
|
+
app.add_typer(plugin_dev_cmd.app, name="plugin", help="Plugin development commands")
|
|
42
|
+
app.add_typer(pipeline_cmd.app, name="pipeline", help="Pipeline validation and execution")
|
|
43
|
+
app.add_typer(create_cmd.app, name="create", help="Create pipeline templates from schemas")
|
|
44
|
+
app.add_typer(docs_cmd.app, name="docs", help="Generate and serve documentation")
|
|
45
|
+
app.add_typer(studio_cmd.app, name="studio", help="Visual editor for pipelines")
|
|
46
|
+
|
|
47
|
+
app.command(name="build", help="Build Docker containers for pipelines")(build_cmd.build)
|
|
48
|
+
app.command(name="validate", help="Validate YAML pipeline files")(validate_cmd.validate)
|
|
49
|
+
app.command(name="generate-types", help="Generate type stubs from YAML pipelines")(
|
|
50
|
+
generate_types_cmd.generate_types
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@app.callback(invoke_without_command=True)
|
|
55
|
+
def callback(
|
|
56
|
+
ctx: typer.Context,
|
|
57
|
+
version: bool = typer.Option(
|
|
58
|
+
False,
|
|
59
|
+
"--version",
|
|
60
|
+
"-v",
|
|
61
|
+
help="Show version and exit",
|
|
62
|
+
),
|
|
63
|
+
) -> None:
|
|
64
|
+
"""HexDAG CLI - Modular DAG orchestration framework."""
|
|
65
|
+
if version:
|
|
66
|
+
# Read version from package metadata
|
|
67
|
+
try:
|
|
68
|
+
from importlib.metadata import version as get_version
|
|
69
|
+
|
|
70
|
+
pkg_version = get_version("hexdag")
|
|
71
|
+
except Exception:
|
|
72
|
+
pkg_version = "0.1.0" # Fallback
|
|
73
|
+
|
|
74
|
+
console.print(f"[bold blue]HexDAG[/bold blue] version [green]{pkg_version}[/green]")
|
|
75
|
+
raise typer.Exit(code=0)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main() -> None:
|
|
79
|
+
"""Main CLI entrypoint."""
|
|
80
|
+
app()
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
if __name__ == "__main__":
|
|
84
|
+
main()
|
hexdag/core/__init__.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""HexDAG Core - Hexagonal Architecture for DAG Orchestration.
|
|
2
|
+
|
|
3
|
+
The registry-free architecture uses Python's import system directly:
|
|
4
|
+
- Components are plain Python classes
|
|
5
|
+
- YAML uses full module paths (hexdag.builtin.nodes.LLMNode)
|
|
6
|
+
- resolve() imports classes dynamically
|
|
7
|
+
|
|
8
|
+
Example usage:
|
|
9
|
+
from hexdag.core.resolver import resolve
|
|
10
|
+
|
|
11
|
+
# Resolve component by module path
|
|
12
|
+
NodeClass = resolve("hexdag.builtin.nodes.LLMNode")
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from hexdag.core.configurable import (
|
|
16
|
+
SecretField,
|
|
17
|
+
)
|
|
18
|
+
from hexdag.core.context import (
|
|
19
|
+
ExecutionContext,
|
|
20
|
+
clear_execution_context,
|
|
21
|
+
get_observer_manager,
|
|
22
|
+
get_port,
|
|
23
|
+
get_ports,
|
|
24
|
+
get_run_id,
|
|
25
|
+
set_observer_manager,
|
|
26
|
+
set_ports,
|
|
27
|
+
set_run_id,
|
|
28
|
+
)
|
|
29
|
+
from hexdag.core.exceptions import (
|
|
30
|
+
ConfigurationError,
|
|
31
|
+
DependencyError,
|
|
32
|
+
HexDAGError,
|
|
33
|
+
OrchestratorError,
|
|
34
|
+
ResourceNotFoundError,
|
|
35
|
+
TypeMismatchError,
|
|
36
|
+
ValidationError,
|
|
37
|
+
)
|
|
38
|
+
from hexdag.core.protocols import (
|
|
39
|
+
ComponentWithExecute,
|
|
40
|
+
ConfigurablePort,
|
|
41
|
+
DictConvertible,
|
|
42
|
+
HealthCheckable,
|
|
43
|
+
SchemaProvider,
|
|
44
|
+
has_execute_method,
|
|
45
|
+
is_dict_convertible,
|
|
46
|
+
is_schema_type,
|
|
47
|
+
)
|
|
48
|
+
from hexdag.core.resolver import resolve, resolve_function
|
|
49
|
+
|
|
50
|
+
__all__ = [
|
|
51
|
+
# Module Resolution
|
|
52
|
+
"resolve",
|
|
53
|
+
"resolve_function",
|
|
54
|
+
# Secret helper
|
|
55
|
+
"SecretField",
|
|
56
|
+
# Execution Context
|
|
57
|
+
"ExecutionContext",
|
|
58
|
+
"clear_execution_context",
|
|
59
|
+
"get_observer_manager",
|
|
60
|
+
"get_port",
|
|
61
|
+
"get_ports",
|
|
62
|
+
"get_run_id",
|
|
63
|
+
"set_observer_manager",
|
|
64
|
+
"set_ports",
|
|
65
|
+
"set_run_id",
|
|
66
|
+
# Exceptions
|
|
67
|
+
"HexDAGError",
|
|
68
|
+
"ConfigurationError",
|
|
69
|
+
"ValidationError",
|
|
70
|
+
"ResourceNotFoundError",
|
|
71
|
+
"DependencyError",
|
|
72
|
+
"TypeMismatchError",
|
|
73
|
+
"OrchestratorError",
|
|
74
|
+
# Protocols
|
|
75
|
+
"ComponentWithExecute",
|
|
76
|
+
"ConfigurablePort",
|
|
77
|
+
"DictConvertible",
|
|
78
|
+
"HealthCheckable",
|
|
79
|
+
"SchemaProvider",
|
|
80
|
+
"has_execute_method",
|
|
81
|
+
"is_dict_convertible",
|
|
82
|
+
"is_schema_type",
|
|
83
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Configuration loading and management for HexDAG."""
|
|
2
|
+
|
|
3
|
+
from hexdag.core.config.loader import (
|
|
4
|
+
ConfigLoader,
|
|
5
|
+
clear_config_cache,
|
|
6
|
+
config_to_manifest_entries,
|
|
7
|
+
get_default_config,
|
|
8
|
+
load_config,
|
|
9
|
+
)
|
|
10
|
+
from hexdag.core.config.models import HexDAGConfig, ManifestEntry
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"ConfigLoader",
|
|
14
|
+
"HexDAGConfig",
|
|
15
|
+
"ManifestEntry",
|
|
16
|
+
"clear_config_cache",
|
|
17
|
+
"config_to_manifest_entries",
|
|
18
|
+
"get_default_config",
|
|
19
|
+
"load_config",
|
|
20
|
+
]
|