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,347 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Plug,
|
|
4
|
+
Package,
|
|
5
|
+
Loader2,
|
|
6
|
+
CheckCircle2,
|
|
7
|
+
XCircle,
|
|
8
|
+
ChevronDown,
|
|
9
|
+
ChevronRight,
|
|
10
|
+
Key,
|
|
11
|
+
Database,
|
|
12
|
+
HardDrive,
|
|
13
|
+
Brain,
|
|
14
|
+
RefreshCw,
|
|
15
|
+
X,
|
|
16
|
+
} from 'lucide-react'
|
|
17
|
+
import { listPlugins, type PluginInfo, type PluginAdapter, type PluginNode } from '../lib/api'
|
|
18
|
+
|
|
19
|
+
interface PluginManagerProps {
|
|
20
|
+
isOpen: boolean
|
|
21
|
+
onClose: () => void
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function PluginManager({ isOpen, onClose }: PluginManagerProps) {
|
|
25
|
+
const [plugins, setPlugins] = useState<PluginInfo[]>([])
|
|
26
|
+
const [isLoading, setIsLoading] = useState(true)
|
|
27
|
+
const [expandedPlugins, setExpandedPlugins] = useState<Set<string>>(new Set())
|
|
28
|
+
const [activeTab, setActiveTab] = useState<'all' | 'adapters' | 'nodes'>('all')
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (isOpen) {
|
|
32
|
+
loadPlugins()
|
|
33
|
+
}
|
|
34
|
+
}, [isOpen])
|
|
35
|
+
|
|
36
|
+
const loadPlugins = async () => {
|
|
37
|
+
try {
|
|
38
|
+
setIsLoading(true)
|
|
39
|
+
const data = await listPlugins()
|
|
40
|
+
setPlugins(data)
|
|
41
|
+
// Expand first plugin by default
|
|
42
|
+
if (data.length > 0) {
|
|
43
|
+
setExpandedPlugins(new Set([data[0].name]))
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Failed to load plugins:', error)
|
|
47
|
+
} finally {
|
|
48
|
+
setIsLoading(false)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const togglePlugin = (name: string) => {
|
|
53
|
+
setExpandedPlugins((prev) => {
|
|
54
|
+
const next = new Set(prev)
|
|
55
|
+
if (next.has(name)) {
|
|
56
|
+
next.delete(name)
|
|
57
|
+
} else {
|
|
58
|
+
next.add(name)
|
|
59
|
+
}
|
|
60
|
+
return next
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const getAdapterIcon = (adapter: PluginAdapter) => {
|
|
65
|
+
const portType = adapter.port_type.toLowerCase()
|
|
66
|
+
if (portType === 'llm') return Brain
|
|
67
|
+
if (portType === 'secret') return Key
|
|
68
|
+
if (portType === 'memory' || portType === 'database') return Database
|
|
69
|
+
if (portType === 'storage') return HardDrive
|
|
70
|
+
return Package
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const getPortTypeColor = (portType: string) => {
|
|
74
|
+
const type = portType.toLowerCase()
|
|
75
|
+
if (type === 'llm') return '#6366f1'
|
|
76
|
+
if (type === 'secret') return '#f59e0b'
|
|
77
|
+
if (type === 'memory') return '#14b8a6'
|
|
78
|
+
if (type === 'database') return '#ec4899'
|
|
79
|
+
if (type === 'storage') return '#22c55e'
|
|
80
|
+
return '#6b7280'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!isOpen) return null
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
|
|
87
|
+
<div className="bg-hex-surface border border-hex-border rounded-lg shadow-2xl w-[800px] max-h-[80vh] flex flex-col">
|
|
88
|
+
{/* Header */}
|
|
89
|
+
<div className="flex items-center justify-between p-4 border-b border-hex-border">
|
|
90
|
+
<div className="flex items-center gap-3">
|
|
91
|
+
<div className="w-10 h-10 rounded-lg bg-hex-accent/20 flex items-center justify-center">
|
|
92
|
+
<Plug size={20} className="text-hex-accent" />
|
|
93
|
+
</div>
|
|
94
|
+
<div>
|
|
95
|
+
<h2 className="text-lg font-semibold text-hex-text">Plugin Manager</h2>
|
|
96
|
+
<p className="text-xs text-hex-text-muted">
|
|
97
|
+
Manage hexdag plugins and their components
|
|
98
|
+
</p>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
<div className="flex items-center gap-2">
|
|
102
|
+
<button
|
|
103
|
+
onClick={loadPlugins}
|
|
104
|
+
disabled={isLoading}
|
|
105
|
+
className="p-2 rounded hover:bg-hex-border/50 transition-colors text-hex-text-muted hover:text-hex-text"
|
|
106
|
+
>
|
|
107
|
+
<RefreshCw size={16} className={isLoading ? 'animate-spin' : ''} />
|
|
108
|
+
</button>
|
|
109
|
+
<button
|
|
110
|
+
onClick={onClose}
|
|
111
|
+
className="p-2 rounded hover:bg-hex-border/50 transition-colors text-hex-text-muted hover:text-hex-text"
|
|
112
|
+
>
|
|
113
|
+
<X size={16} />
|
|
114
|
+
</button>
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{/* Tabs */}
|
|
119
|
+
<div className="flex border-b border-hex-border px-4">
|
|
120
|
+
{(['all', 'adapters', 'nodes'] as const).map((tab) => (
|
|
121
|
+
<button
|
|
122
|
+
key={tab}
|
|
123
|
+
onClick={() => setActiveTab(tab)}
|
|
124
|
+
className={`px-4 py-2 text-xs font-medium border-b-2 transition-colors ${
|
|
125
|
+
activeTab === tab
|
|
126
|
+
? 'text-hex-accent border-hex-accent'
|
|
127
|
+
: 'text-hex-text-muted border-transparent hover:text-hex-text'
|
|
128
|
+
}`}
|
|
129
|
+
>
|
|
130
|
+
{tab.charAt(0).toUpperCase() + tab.slice(1)}
|
|
131
|
+
</button>
|
|
132
|
+
))}
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{/* Content */}
|
|
136
|
+
<div className="flex-1 overflow-y-auto p-4">
|
|
137
|
+
{isLoading ? (
|
|
138
|
+
<div className="flex items-center justify-center h-40">
|
|
139
|
+
<Loader2 size={24} className="animate-spin text-hex-accent" />
|
|
140
|
+
<span className="ml-2 text-hex-text-muted">Loading plugins...</span>
|
|
141
|
+
</div>
|
|
142
|
+
) : plugins.length === 0 ? (
|
|
143
|
+
<div className="flex flex-col items-center justify-center h-40 text-center">
|
|
144
|
+
<Package size={48} className="text-hex-text-muted opacity-30 mb-4" />
|
|
145
|
+
<p className="text-hex-text-muted">No plugins found</p>
|
|
146
|
+
<p className="text-xs text-hex-text-muted mt-1">
|
|
147
|
+
Add plugins to the hexdag_plugins/ directory
|
|
148
|
+
</p>
|
|
149
|
+
</div>
|
|
150
|
+
) : (
|
|
151
|
+
<div className="space-y-3">
|
|
152
|
+
{plugins.map((plugin) => (
|
|
153
|
+
<PluginCard
|
|
154
|
+
key={plugin.name}
|
|
155
|
+
plugin={plugin}
|
|
156
|
+
isExpanded={expandedPlugins.has(plugin.name)}
|
|
157
|
+
onToggle={() => togglePlugin(plugin.name)}
|
|
158
|
+
activeTab={activeTab}
|
|
159
|
+
getAdapterIcon={getAdapterIcon}
|
|
160
|
+
getPortTypeColor={getPortTypeColor}
|
|
161
|
+
/>
|
|
162
|
+
))}
|
|
163
|
+
</div>
|
|
164
|
+
)}
|
|
165
|
+
</div>
|
|
166
|
+
|
|
167
|
+
{/* Footer */}
|
|
168
|
+
<div className="px-4 py-3 border-t border-hex-border bg-hex-bg/50">
|
|
169
|
+
<p className="text-[10px] text-hex-text-muted text-center">
|
|
170
|
+
Plugins are automatically discovered from hexdag_plugins/ and installed packages
|
|
171
|
+
</p>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface PluginCardProps {
|
|
179
|
+
plugin: PluginInfo
|
|
180
|
+
isExpanded: boolean
|
|
181
|
+
onToggle: () => void
|
|
182
|
+
activeTab: 'all' | 'adapters' | 'nodes'
|
|
183
|
+
getAdapterIcon: (adapter: PluginAdapter) => typeof Package
|
|
184
|
+
getPortTypeColor: (portType: string) => string
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function PluginCard({
|
|
188
|
+
plugin,
|
|
189
|
+
isExpanded,
|
|
190
|
+
onToggle,
|
|
191
|
+
activeTab,
|
|
192
|
+
getAdapterIcon,
|
|
193
|
+
getPortTypeColor,
|
|
194
|
+
}: PluginCardProps) {
|
|
195
|
+
const showAdapters = activeTab === 'all' || activeTab === 'adapters'
|
|
196
|
+
const showNodes = activeTab === 'all' || activeTab === 'nodes'
|
|
197
|
+
|
|
198
|
+
return (
|
|
199
|
+
<div className="border border-hex-border rounded-lg overflow-hidden">
|
|
200
|
+
{/* Plugin Header */}
|
|
201
|
+
<button
|
|
202
|
+
onClick={onToggle}
|
|
203
|
+
className="w-full flex items-center gap-3 p-3 hover:bg-hex-border/30 transition-colors"
|
|
204
|
+
>
|
|
205
|
+
{isExpanded ? (
|
|
206
|
+
<ChevronDown size={14} className="text-hex-text-muted" />
|
|
207
|
+
) : (
|
|
208
|
+
<ChevronRight size={14} className="text-hex-text-muted" />
|
|
209
|
+
)}
|
|
210
|
+
<div className="w-8 h-8 rounded bg-green-500/20 flex items-center justify-center">
|
|
211
|
+
<Plug size={16} className="text-green-500" />
|
|
212
|
+
</div>
|
|
213
|
+
<div className="flex-1 text-left">
|
|
214
|
+
<div className="flex items-center gap-2">
|
|
215
|
+
<span className="text-sm font-medium text-hex-text">{plugin.name}</span>
|
|
216
|
+
<span className="text-[10px] px-1.5 py-0.5 rounded bg-hex-border text-hex-text-muted">
|
|
217
|
+
v{plugin.version}
|
|
218
|
+
</span>
|
|
219
|
+
</div>
|
|
220
|
+
<p className="text-xs text-hex-text-muted truncate">{plugin.description}</p>
|
|
221
|
+
</div>
|
|
222
|
+
<div className="flex items-center gap-4 text-hex-text-muted">
|
|
223
|
+
<div className="flex items-center gap-1 text-xs">
|
|
224
|
+
<Key size={12} />
|
|
225
|
+
<span>{plugin.adapters.length}</span>
|
|
226
|
+
</div>
|
|
227
|
+
<div className="flex items-center gap-1 text-xs">
|
|
228
|
+
<Package size={12} />
|
|
229
|
+
<span>{plugin.nodes.length}</span>
|
|
230
|
+
</div>
|
|
231
|
+
{plugin.enabled ? (
|
|
232
|
+
<CheckCircle2 size={16} className="text-green-500" />
|
|
233
|
+
) : (
|
|
234
|
+
<XCircle size={16} className="text-red-500" />
|
|
235
|
+
)}
|
|
236
|
+
</div>
|
|
237
|
+
</button>
|
|
238
|
+
|
|
239
|
+
{/* Expanded Content */}
|
|
240
|
+
{isExpanded && (
|
|
241
|
+
<div className="border-t border-hex-border bg-hex-bg/50 p-3 space-y-4">
|
|
242
|
+
{/* Adapters */}
|
|
243
|
+
{showAdapters && plugin.adapters.length > 0 && (
|
|
244
|
+
<div>
|
|
245
|
+
<h4 className="text-xs font-medium text-hex-text-muted mb-2 flex items-center gap-2">
|
|
246
|
+
<Key size={12} />
|
|
247
|
+
Adapters ({plugin.adapters.length})
|
|
248
|
+
</h4>
|
|
249
|
+
<div className="grid grid-cols-2 gap-2">
|
|
250
|
+
{plugin.adapters.map((adapter, idx) => {
|
|
251
|
+
const Icon = getAdapterIcon(adapter)
|
|
252
|
+
const color = getPortTypeColor(adapter.port_type)
|
|
253
|
+
return (
|
|
254
|
+
<div
|
|
255
|
+
key={idx}
|
|
256
|
+
className="flex items-start gap-2 p-2 rounded bg-hex-surface border border-hex-border"
|
|
257
|
+
>
|
|
258
|
+
<div
|
|
259
|
+
className="w-7 h-7 rounded flex items-center justify-center flex-shrink-0"
|
|
260
|
+
style={{ backgroundColor: `${color}20` }}
|
|
261
|
+
>
|
|
262
|
+
<Icon size={14} style={{ color }} />
|
|
263
|
+
</div>
|
|
264
|
+
<div className="flex-1 min-w-0">
|
|
265
|
+
<div className="text-xs font-medium text-hex-text truncate">
|
|
266
|
+
{adapter.name}
|
|
267
|
+
</div>
|
|
268
|
+
<div className="text-[10px] text-hex-text-muted truncate">
|
|
269
|
+
{adapter.description}
|
|
270
|
+
</div>
|
|
271
|
+
<div className="flex items-center gap-2 mt-1">
|
|
272
|
+
<span
|
|
273
|
+
className="text-[9px] px-1 py-0.5 rounded"
|
|
274
|
+
style={{
|
|
275
|
+
backgroundColor: `${color}20`,
|
|
276
|
+
color: color,
|
|
277
|
+
}}
|
|
278
|
+
>
|
|
279
|
+
{adapter.port_type}
|
|
280
|
+
</span>
|
|
281
|
+
{adapter.secrets.length > 0 && (
|
|
282
|
+
<span className="text-[9px] px-1 py-0.5 rounded bg-amber-500/20 text-amber-500">
|
|
283
|
+
{adapter.secrets.length} secrets
|
|
284
|
+
</span>
|
|
285
|
+
)}
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
)
|
|
290
|
+
})}
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
)}
|
|
294
|
+
|
|
295
|
+
{/* Nodes */}
|
|
296
|
+
{showNodes && plugin.nodes.length > 0 && (
|
|
297
|
+
<div>
|
|
298
|
+
<h4 className="text-xs font-medium text-hex-text-muted mb-2 flex items-center gap-2">
|
|
299
|
+
<Package size={12} />
|
|
300
|
+
Nodes ({plugin.nodes.length})
|
|
301
|
+
</h4>
|
|
302
|
+
<div className="grid grid-cols-2 gap-2">
|
|
303
|
+
{plugin.nodes.map((node, idx) => (
|
|
304
|
+
<NodeCard key={idx} node={node} />
|
|
305
|
+
))}
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
)}
|
|
309
|
+
|
|
310
|
+
{/* No content message */}
|
|
311
|
+
{((activeTab === 'adapters' && plugin.adapters.length === 0) ||
|
|
312
|
+
(activeTab === 'nodes' && plugin.nodes.length === 0)) && (
|
|
313
|
+
<p className="text-xs text-hex-text-muted text-center py-4">
|
|
314
|
+
No {activeTab} in this plugin
|
|
315
|
+
</p>
|
|
316
|
+
)}
|
|
317
|
+
</div>
|
|
318
|
+
)}
|
|
319
|
+
</div>
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function NodeCard({ node }: { node: PluginNode }) {
|
|
324
|
+
return (
|
|
325
|
+
<div className="flex items-start gap-2 p-2 rounded bg-hex-surface border border-hex-border">
|
|
326
|
+
<div
|
|
327
|
+
className="w-7 h-7 rounded flex items-center justify-center flex-shrink-0"
|
|
328
|
+
style={{ backgroundColor: `${node.color}20` }}
|
|
329
|
+
>
|
|
330
|
+
<Package size={14} style={{ color: node.color }} />
|
|
331
|
+
</div>
|
|
332
|
+
<div className="flex-1 min-w-0">
|
|
333
|
+
<div className="text-xs font-medium text-hex-text truncate">{node.name}</div>
|
|
334
|
+
<div className="text-[10px] text-hex-text-muted truncate">{node.description}</div>
|
|
335
|
+
<span
|
|
336
|
+
className="inline-block text-[9px] px-1 py-0.5 rounded mt-1"
|
|
337
|
+
style={{
|
|
338
|
+
backgroundColor: `${node.color}20`,
|
|
339
|
+
color: node.color,
|
|
340
|
+
}}
|
|
341
|
+
>
|
|
342
|
+
{node.kind}
|
|
343
|
+
</span>
|
|
344
|
+
</div>
|
|
345
|
+
</div>
|
|
346
|
+
)
|
|
347
|
+
}
|