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,208 @@
|
|
|
1
|
+
"""Pipeline creation commands for HexDAG CLI."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
import yaml
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.prompt import Confirm, Prompt
|
|
10
|
+
|
|
11
|
+
app = typer.Typer()
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@app.command("pipeline")
|
|
16
|
+
def create_pipeline(
|
|
17
|
+
name: Annotated[
|
|
18
|
+
str | None,
|
|
19
|
+
typer.Option(
|
|
20
|
+
"--name",
|
|
21
|
+
"-n",
|
|
22
|
+
help="Pipeline name",
|
|
23
|
+
),
|
|
24
|
+
] = None,
|
|
25
|
+
output: Annotated[
|
|
26
|
+
Path | None,
|
|
27
|
+
typer.Option(
|
|
28
|
+
"--output",
|
|
29
|
+
"-o",
|
|
30
|
+
help="Output file path (default: <name>.yaml)",
|
|
31
|
+
),
|
|
32
|
+
] = None,
|
|
33
|
+
template: Annotated[
|
|
34
|
+
str,
|
|
35
|
+
typer.Option(
|
|
36
|
+
"--template",
|
|
37
|
+
"-t",
|
|
38
|
+
help="Template type (minimal, example, full)",
|
|
39
|
+
),
|
|
40
|
+
] = "minimal",
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Create a new pipeline YAML file from a template.
|
|
43
|
+
|
|
44
|
+
Examples
|
|
45
|
+
--------
|
|
46
|
+
hexdag create pipeline
|
|
47
|
+
hexdag create pipeline --name my-pipeline
|
|
48
|
+
hexdag create pipeline --template example --output pipeline.yaml
|
|
49
|
+
"""
|
|
50
|
+
# Interactive mode if name not provided
|
|
51
|
+
if name is None:
|
|
52
|
+
name = Prompt.ask("[cyan]Pipeline name[/cyan]", default="my-pipeline")
|
|
53
|
+
|
|
54
|
+
# Determine output path
|
|
55
|
+
if output is None:
|
|
56
|
+
output = Path(f"{name}.yaml")
|
|
57
|
+
|
|
58
|
+
if output.exists():
|
|
59
|
+
if not Confirm.ask(f"[yellow]File {output} already exists. Overwrite?[/yellow]"):
|
|
60
|
+
console.print("[red]Aborted.[/red]")
|
|
61
|
+
raise typer.Exit(1)
|
|
62
|
+
|
|
63
|
+
if template == "minimal":
|
|
64
|
+
pipeline = {
|
|
65
|
+
"apiVersion": "hexdag/v1",
|
|
66
|
+
"kind": "Pipeline",
|
|
67
|
+
"metadata": {
|
|
68
|
+
"name": name,
|
|
69
|
+
"description": "TODO: Add description",
|
|
70
|
+
},
|
|
71
|
+
"spec": {
|
|
72
|
+
"nodes": [
|
|
73
|
+
{
|
|
74
|
+
"kind": "hexdag.builtin.nodes.FunctionNode",
|
|
75
|
+
"metadata": {"name": "step1"},
|
|
76
|
+
"spec": {
|
|
77
|
+
"fn": "my_module.my_function",
|
|
78
|
+
"input_mapping": {"x": "input.value"},
|
|
79
|
+
"dependencies": [],
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
elif template == "example":
|
|
86
|
+
pipeline = {
|
|
87
|
+
"apiVersion": "hexdag/v1",
|
|
88
|
+
"kind": "Pipeline",
|
|
89
|
+
"metadata": {
|
|
90
|
+
"name": name,
|
|
91
|
+
"description": "Example multi-step pipeline",
|
|
92
|
+
"version": "1.0",
|
|
93
|
+
"tags": ["example", "demo"],
|
|
94
|
+
},
|
|
95
|
+
"spec": {
|
|
96
|
+
"ports": {
|
|
97
|
+
"llm": {
|
|
98
|
+
"adapter": "hexdag.builtin.adapters.mock.MockLLM",
|
|
99
|
+
"config": {},
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"nodes": [
|
|
103
|
+
{
|
|
104
|
+
"kind": "hexdag.builtin.nodes.FunctionNode",
|
|
105
|
+
"metadata": {
|
|
106
|
+
"name": "input_processor",
|
|
107
|
+
"annotations": {"description": "Process input data"},
|
|
108
|
+
},
|
|
109
|
+
"spec": {
|
|
110
|
+
"fn": "my_module.process_input",
|
|
111
|
+
"input_mapping": {"data": "input.raw_data"},
|
|
112
|
+
"dependencies": [],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"kind": "hexdag.builtin.nodes.LLMNode",
|
|
117
|
+
"metadata": {
|
|
118
|
+
"name": "analyzer",
|
|
119
|
+
"annotations": {"description": "Analyze processed data"},
|
|
120
|
+
},
|
|
121
|
+
"spec": {
|
|
122
|
+
"prompt_template": "Analyze this data: {{input_processor}}",
|
|
123
|
+
"dependencies": ["input_processor"],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"kind": "hexdag.builtin.nodes.FunctionNode",
|
|
128
|
+
"metadata": {
|
|
129
|
+
"name": "output_formatter",
|
|
130
|
+
"annotations": {"description": "Format final output"},
|
|
131
|
+
},
|
|
132
|
+
"spec": {
|
|
133
|
+
"fn": "my_module.format_output",
|
|
134
|
+
"input_mapping": {"result": "analyzer"},
|
|
135
|
+
"dependencies": ["analyzer"],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
}
|
|
141
|
+
else: # full
|
|
142
|
+
pipeline = {
|
|
143
|
+
"apiVersion": "hexdag/v1",
|
|
144
|
+
"kind": "Pipeline",
|
|
145
|
+
"metadata": {
|
|
146
|
+
"name": name,
|
|
147
|
+
"description": "Full-featured pipeline template",
|
|
148
|
+
"version": "1.0",
|
|
149
|
+
"author": "Your Name",
|
|
150
|
+
"tags": ["production", "template"],
|
|
151
|
+
},
|
|
152
|
+
"spec": {
|
|
153
|
+
"input_schema": {
|
|
154
|
+
"type": "object",
|
|
155
|
+
"properties": {"data": {"type": "string"}},
|
|
156
|
+
"required": ["data"],
|
|
157
|
+
},
|
|
158
|
+
"ports": {
|
|
159
|
+
"llm": {
|
|
160
|
+
"adapter": "hexdag.builtin.adapters.mock.MockLLM",
|
|
161
|
+
"config": {},
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
"common_field_mappings": {"default_mapping": {"value": "input.data"}},
|
|
165
|
+
"nodes": [
|
|
166
|
+
{
|
|
167
|
+
"kind": "hexdag.builtin.nodes.FunctionNode",
|
|
168
|
+
"metadata": {
|
|
169
|
+
"name": "validator",
|
|
170
|
+
"annotations": {
|
|
171
|
+
"description": "Validate input",
|
|
172
|
+
"timeout": "5s",
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
"spec": {
|
|
176
|
+
"fn": "my_module.validate_input",
|
|
177
|
+
"input_mapping": {"data": "input.data"},
|
|
178
|
+
"output_schema": {
|
|
179
|
+
"type": "object",
|
|
180
|
+
"properties": {"valid": {"type": "boolean"}},
|
|
181
|
+
},
|
|
182
|
+
"dependencies": [],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"kind": "hexdag.builtin.nodes.LLMNode",
|
|
187
|
+
"metadata": {"name": "processor"},
|
|
188
|
+
"spec": {
|
|
189
|
+
"prompt_template": "Process: {{validator.result}}",
|
|
190
|
+
"output_schema": {
|
|
191
|
+
"type": "object",
|
|
192
|
+
"properties": {"processed": {"type": "string"}},
|
|
193
|
+
},
|
|
194
|
+
"dependencies": ["validator"],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
# Write to file
|
|
202
|
+
with Path.open(output, "w") as f:
|
|
203
|
+
yaml.dump(pipeline, f, default_flow_style=False, sort_keys=False)
|
|
204
|
+
|
|
205
|
+
console.print(f"[green]✓[/green] Created pipeline: {output}")
|
|
206
|
+
console.print("\n[cyan]Next steps:[/cyan]")
|
|
207
|
+
console.print(f" 1. Edit {output} to customize your pipeline")
|
|
208
|
+
console.print(f" 2. Validate: [bold]hexdag validate {output}[/bold]")
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"""CLI commands for MkDocs documentation."""
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
|
|
10
|
+
app = typer.Typer(help="Generate and serve documentation with MkDocs")
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.command("build")
|
|
15
|
+
def build_docs(
|
|
16
|
+
clean: bool = typer.Option(
|
|
17
|
+
False,
|
|
18
|
+
"--clean",
|
|
19
|
+
"-c",
|
|
20
|
+
help="Clean site directory before building",
|
|
21
|
+
),
|
|
22
|
+
strict: bool = typer.Option(
|
|
23
|
+
False,
|
|
24
|
+
"--strict",
|
|
25
|
+
"-s",
|
|
26
|
+
help="Enable strict mode (warnings as errors)",
|
|
27
|
+
),
|
|
28
|
+
config: Path | None = typer.Option(
|
|
29
|
+
None,
|
|
30
|
+
"--config",
|
|
31
|
+
help="Path to TOML configuration file (pyproject.toml or hexdag.toml)",
|
|
32
|
+
),
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Build documentation site with MkDocs.
|
|
35
|
+
|
|
36
|
+
Generates static HTML documentation from markdown files and the component
|
|
37
|
+
registry. The registry hooks automatically generate reference documentation
|
|
38
|
+
during the build process.
|
|
39
|
+
|
|
40
|
+
You can specify a custom TOML configuration to document your project's
|
|
41
|
+
specific components, plugins, and adapters.
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
hexdag docs build
|
|
45
|
+
hexdag docs build --clean
|
|
46
|
+
hexdag docs build --strict
|
|
47
|
+
hexdag docs build --config /path/to/myproject/pyproject.toml
|
|
48
|
+
"""
|
|
49
|
+
import os
|
|
50
|
+
|
|
51
|
+
try:
|
|
52
|
+
if config:
|
|
53
|
+
if not config.exists():
|
|
54
|
+
console.print(f"[red]✗[/red] Config file not found: {config}")
|
|
55
|
+
raise typer.Exit(1)
|
|
56
|
+
os.environ["HEXDAG_CONFIG_PATH"] = str(config.resolve())
|
|
57
|
+
console.print(
|
|
58
|
+
Panel.fit(
|
|
59
|
+
"[bold cyan]Building Documentation[/bold cyan]\n"
|
|
60
|
+
"Using MkDocs with registry hooks\n"
|
|
61
|
+
f"Config: {config}",
|
|
62
|
+
border_style="cyan",
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
else:
|
|
66
|
+
console.print(
|
|
67
|
+
Panel.fit(
|
|
68
|
+
"[bold cyan]Building Documentation[/bold cyan]\n"
|
|
69
|
+
"Using MkDocs with registry hooks",
|
|
70
|
+
border_style="cyan",
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
cmd = ["mkdocs", "build"]
|
|
75
|
+
if clean:
|
|
76
|
+
cmd.append("--clean")
|
|
77
|
+
if strict:
|
|
78
|
+
cmd.append("--strict")
|
|
79
|
+
|
|
80
|
+
result = subprocess.run(cmd, capture_output=True, text=True, env=os.environ.copy()) # nosec B603
|
|
81
|
+
|
|
82
|
+
if result.returncode == 0:
|
|
83
|
+
console.print("\n[green]✓[/green] Documentation built successfully!")
|
|
84
|
+
console.print("\n[dim]Site output: ./site/[/dim]")
|
|
85
|
+
console.print("[dim]View locally: hexdag docs serve[/dim]")
|
|
86
|
+
else:
|
|
87
|
+
console.print("\n[red]✗[/red] Build failed:")
|
|
88
|
+
console.print(result.stderr)
|
|
89
|
+
raise typer.Exit(1)
|
|
90
|
+
|
|
91
|
+
except FileNotFoundError:
|
|
92
|
+
console.print("\n[red]✗[/red] MkDocs not found. Install with:")
|
|
93
|
+
console.print(" [cyan]pip install hexdag[docs][/cyan]")
|
|
94
|
+
raise typer.Exit(1)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
console.print(f"\n[red]✗[/red] Error building documentation: {e}")
|
|
97
|
+
raise typer.Exit(1)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@app.command("serve")
|
|
101
|
+
def serve_docs(
|
|
102
|
+
port: int = typer.Option(
|
|
103
|
+
8000,
|
|
104
|
+
"--port",
|
|
105
|
+
"-p",
|
|
106
|
+
help="Port to serve on",
|
|
107
|
+
),
|
|
108
|
+
host: str = typer.Option(
|
|
109
|
+
"127.0.0.1",
|
|
110
|
+
"--host",
|
|
111
|
+
"-h",
|
|
112
|
+
help="Host to bind to",
|
|
113
|
+
),
|
|
114
|
+
watch_theme: bool = typer.Option(
|
|
115
|
+
False,
|
|
116
|
+
"--watch-theme",
|
|
117
|
+
help="Watch theme directory for changes",
|
|
118
|
+
),
|
|
119
|
+
config: Path | None = typer.Option(
|
|
120
|
+
None,
|
|
121
|
+
"--config",
|
|
122
|
+
help="Path to TOML configuration file (pyproject.toml or hexdag.toml)",
|
|
123
|
+
),
|
|
124
|
+
) -> None:
|
|
125
|
+
"""Serve documentation with live reload.
|
|
126
|
+
|
|
127
|
+
Starts MkDocs development server with live reload. The server watches for
|
|
128
|
+
changes in markdown files and automatically regenerates registry documentation.
|
|
129
|
+
|
|
130
|
+
You can specify a custom TOML configuration to document your project's
|
|
131
|
+
specific components, plugins, and adapters.
|
|
132
|
+
|
|
133
|
+
Examples:
|
|
134
|
+
hexdag docs serve
|
|
135
|
+
hexdag docs serve --port 8080
|
|
136
|
+
hexdag docs serve --watch-theme
|
|
137
|
+
hexdag docs serve --config /path/to/myproject/pyproject.toml
|
|
138
|
+
"""
|
|
139
|
+
import os
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
if config:
|
|
143
|
+
if not config.exists():
|
|
144
|
+
console.print(f"[red]✗[/red] Config file not found: {config}")
|
|
145
|
+
raise typer.Exit(1)
|
|
146
|
+
os.environ["HEXDAG_CONFIG_PATH"] = str(config.resolve())
|
|
147
|
+
console.print(
|
|
148
|
+
Panel.fit(
|
|
149
|
+
"[bold cyan]MkDocs Development Server[/bold cyan]\n"
|
|
150
|
+
f"URL: http://{host}:{port}\n"
|
|
151
|
+
"Live reload: Enabled\n"
|
|
152
|
+
f"Config: {config}",
|
|
153
|
+
border_style="cyan",
|
|
154
|
+
)
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
console.print(
|
|
158
|
+
Panel.fit(
|
|
159
|
+
"[bold cyan]MkDocs Development Server[/bold cyan]\n"
|
|
160
|
+
f"URL: http://{host}:{port}\n"
|
|
161
|
+
"Live reload: Enabled",
|
|
162
|
+
border_style="cyan",
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
cmd = ["mkdocs", "serve", "--dev-addr", f"{host}:{port}"]
|
|
167
|
+
if watch_theme:
|
|
168
|
+
cmd.append("--watch-theme")
|
|
169
|
+
|
|
170
|
+
console.print(f"\n[green]✓[/green] Starting server at [cyan]http://{host}:{port}[/cyan]")
|
|
171
|
+
console.print("\nPress [red]Ctrl+C[/red] to stop the server\n")
|
|
172
|
+
|
|
173
|
+
# Run mkdocs serve (blocking)
|
|
174
|
+
subprocess.run(cmd, env=os.environ.copy()) # nosec B603
|
|
175
|
+
|
|
176
|
+
except FileNotFoundError:
|
|
177
|
+
console.print("\n[red]✗[/red] MkDocs not found. Install with:")
|
|
178
|
+
console.print(" [cyan]pip install hexdag[docs][/cyan]")
|
|
179
|
+
raise typer.Exit(1)
|
|
180
|
+
except KeyboardInterrupt:
|
|
181
|
+
console.print("\n\n[yellow]Server stopped[/yellow]")
|
|
182
|
+
except Exception as e:
|
|
183
|
+
console.print(f"\n[red]✗[/red] Error starting server: {e}")
|
|
184
|
+
raise typer.Exit(1)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@app.command("deploy")
|
|
188
|
+
def deploy_docs(
|
|
189
|
+
remote_branch: str = typer.Option(
|
|
190
|
+
"gh-pages",
|
|
191
|
+
"--remote-branch",
|
|
192
|
+
"-b",
|
|
193
|
+
help="Remote branch to deploy to",
|
|
194
|
+
),
|
|
195
|
+
message: str | None = typer.Option(
|
|
196
|
+
None,
|
|
197
|
+
"--message",
|
|
198
|
+
"-m",
|
|
199
|
+
help="Commit message for deploy",
|
|
200
|
+
),
|
|
201
|
+
) -> None:
|
|
202
|
+
"""Deploy documentation to GitHub Pages.
|
|
203
|
+
|
|
204
|
+
Builds and deploys documentation to the specified remote branch (default: gh-pages).
|
|
205
|
+
Requires git repository with GitHub remote configured.
|
|
206
|
+
|
|
207
|
+
Examples:
|
|
208
|
+
hexdag docs deploy
|
|
209
|
+
hexdag docs deploy --message "Update docs"
|
|
210
|
+
hexdag docs deploy --remote-branch main
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
console.print(
|
|
214
|
+
Panel.fit(
|
|
215
|
+
f"[bold cyan]Deploying Documentation[/bold cyan]\nRemote branch: {remote_branch}",
|
|
216
|
+
border_style="cyan",
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
cmd = ["mkdocs", "gh-deploy", "--remote-branch", remote_branch]
|
|
221
|
+
if message:
|
|
222
|
+
cmd.extend(["--message", message])
|
|
223
|
+
|
|
224
|
+
result = subprocess.run(cmd, capture_output=True, text=True) # nosec B603
|
|
225
|
+
|
|
226
|
+
if result.returncode == 0:
|
|
227
|
+
console.print("\n[green]✓[/green] Documentation deployed successfully!")
|
|
228
|
+
else:
|
|
229
|
+
console.print("\n[red]✗[/red] Deploy failed:")
|
|
230
|
+
console.print(result.stderr)
|
|
231
|
+
raise typer.Exit(1)
|
|
232
|
+
|
|
233
|
+
except FileNotFoundError:
|
|
234
|
+
console.print("\n[red]✗[/red] MkDocs not found. Install with:")
|
|
235
|
+
console.print(" [cyan]pip install hexdag[docs][/cyan]")
|
|
236
|
+
raise typer.Exit(1)
|
|
237
|
+
except Exception as e:
|
|
238
|
+
console.print(f"\n[red]✗[/red] Error deploying documentation: {e}")
|
|
239
|
+
raise typer.Exit(1)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@app.command("new")
|
|
243
|
+
def new_page(
|
|
244
|
+
path: str = typer.Argument(..., help="Path for new page (e.g., guide/my-guide.md)"),
|
|
245
|
+
title: str | None = typer.Option(None, "--title", "-t", help="Page title"),
|
|
246
|
+
) -> None:
|
|
247
|
+
"""Create a new documentation page.
|
|
248
|
+
|
|
249
|
+
Creates a new markdown file with basic frontmatter and adds it to the
|
|
250
|
+
documentation structure.
|
|
251
|
+
|
|
252
|
+
Examples:
|
|
253
|
+
hexdag docs new guide/custom-nodes.md
|
|
254
|
+
hexdag docs new guide/advanced.md --title "Advanced Usage"
|
|
255
|
+
"""
|
|
256
|
+
docs_dir = Path("docs")
|
|
257
|
+
if not docs_dir.exists():
|
|
258
|
+
console.print(f"[red]✗[/red] Documentation directory not found: {docs_dir}")
|
|
259
|
+
raise typer.Exit(1)
|
|
260
|
+
|
|
261
|
+
file_path = docs_dir / path
|
|
262
|
+
if file_path.exists():
|
|
263
|
+
console.print(f"[red]✗[/red] File already exists: {file_path}")
|
|
264
|
+
raise typer.Exit(1)
|
|
265
|
+
|
|
266
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
267
|
+
|
|
268
|
+
# Generate title from filename if not provided
|
|
269
|
+
if not title:
|
|
270
|
+
title = file_path.stem.replace("-", " ").replace("_", " ").title()
|
|
271
|
+
|
|
272
|
+
content = f"""# {title}
|
|
273
|
+
|
|
274
|
+
Add your content here.
|
|
275
|
+
|
|
276
|
+
## Overview
|
|
277
|
+
|
|
278
|
+
...
|
|
279
|
+
|
|
280
|
+
## Examples
|
|
281
|
+
|
|
282
|
+
...
|
|
283
|
+
|
|
284
|
+
## Next Steps
|
|
285
|
+
|
|
286
|
+
...
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
file_path.write_text(content)
|
|
290
|
+
|
|
291
|
+
console.print(f"[green]✓[/green] Created new page: [cyan]{file_path}[/cyan]")
|
|
292
|
+
console.print("\nRemember to add it to [cyan]mkdocs.yml[/cyan] navigation:")
|
|
293
|
+
console.print(f" - {title}: {path}")
|