machinaos 0.0.1
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.
- package/.env.template +71 -0
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/bin/cli.js +159 -0
- package/client/.dockerignore +45 -0
- package/client/Dockerfile +68 -0
- package/client/eslint.config.js +29 -0
- package/client/index.html +13 -0
- package/client/nginx.conf +66 -0
- package/client/package.json +48 -0
- package/client/src/App.tsx +27 -0
- package/client/src/Dashboard.tsx +1173 -0
- package/client/src/ParameterPanel.tsx +301 -0
- package/client/src/components/AIAgentNode.tsx +321 -0
- package/client/src/components/APIKeyValidator.tsx +118 -0
- package/client/src/components/ClaudeChatModelNode.tsx +18 -0
- package/client/src/components/ConditionalEdge.tsx +189 -0
- package/client/src/components/CredentialsModal.tsx +306 -0
- package/client/src/components/EdgeConditionEditor.tsx +443 -0
- package/client/src/components/GeminiChatModelNode.tsx +18 -0
- package/client/src/components/GenericNode.tsx +357 -0
- package/client/src/components/LocationParameterPanel.tsx +154 -0
- package/client/src/components/ModelNode.tsx +286 -0
- package/client/src/components/OpenAIChatModelNode.tsx +18 -0
- package/client/src/components/OutputPanel.tsx +471 -0
- package/client/src/components/ParameterRenderer.tsx +1874 -0
- package/client/src/components/SkillEditorModal.tsx +417 -0
- package/client/src/components/SquareNode.tsx +797 -0
- package/client/src/components/StartNode.tsx +250 -0
- package/client/src/components/ToolkitNode.tsx +365 -0
- package/client/src/components/TriggerNode.tsx +463 -0
- package/client/src/components/auth/LoginPage.tsx +247 -0
- package/client/src/components/auth/ProtectedRoute.tsx +59 -0
- package/client/src/components/base/BaseChatModelNode.tsx +271 -0
- package/client/src/components/icons/AIProviderIcons.tsx +50 -0
- package/client/src/components/maps/GoogleMapsPicker.tsx +137 -0
- package/client/src/components/maps/MapsPreviewPanel.tsx +110 -0
- package/client/src/components/maps/index.ts +26 -0
- package/client/src/components/parameterPanel/InputSection.tsx +1094 -0
- package/client/src/components/parameterPanel/LocationPanelLayout.tsx +65 -0
- package/client/src/components/parameterPanel/MapsSection.tsx +92 -0
- package/client/src/components/parameterPanel/MiddleSection.tsx +571 -0
- package/client/src/components/parameterPanel/OutputSection.tsx +81 -0
- package/client/src/components/parameterPanel/ParameterPanelLayout.tsx +82 -0
- package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +436 -0
- package/client/src/components/parameterPanel/index.ts +42 -0
- package/client/src/components/shared/DataPanel.tsx +142 -0
- package/client/src/components/shared/JSONTreeRenderer.tsx +106 -0
- package/client/src/components/ui/AIResultModal.tsx +204 -0
- package/client/src/components/ui/AndroidSettingsPanel.tsx +401 -0
- package/client/src/components/ui/CodeEditor.tsx +81 -0
- package/client/src/components/ui/CollapsibleSection.tsx +88 -0
- package/client/src/components/ui/ComponentItem.tsx +154 -0
- package/client/src/components/ui/ComponentPalette.tsx +321 -0
- package/client/src/components/ui/ConsolePanel.tsx +1074 -0
- package/client/src/components/ui/ErrorBoundary.tsx +196 -0
- package/client/src/components/ui/InputNodesPanel.tsx +204 -0
- package/client/src/components/ui/MapSelector.tsx +314 -0
- package/client/src/components/ui/Modal.tsx +149 -0
- package/client/src/components/ui/NodeContextMenu.tsx +192 -0
- package/client/src/components/ui/NodeOutputPanel.tsx +1150 -0
- package/client/src/components/ui/OutputDisplayPanel.tsx +381 -0
- package/client/src/components/ui/SettingsPanel.tsx +243 -0
- package/client/src/components/ui/TopToolbar.tsx +736 -0
- package/client/src/components/ui/WhatsAppSettingsPanel.tsx +345 -0
- package/client/src/components/ui/WorkflowSidebar.tsx +294 -0
- package/client/src/config/antdTheme.ts +186 -0
- package/client/src/config/api.ts +54 -0
- package/client/src/contexts/AuthContext.tsx +221 -0
- package/client/src/contexts/ThemeContext.tsx +42 -0
- package/client/src/contexts/WebSocketContext.tsx +1971 -0
- package/client/src/factories/baseChatModelFactory.ts +256 -0
- package/client/src/hooks/useAndroidOperations.ts +164 -0
- package/client/src/hooks/useApiKeyValidation.ts +107 -0
- package/client/src/hooks/useApiKeys.ts +238 -0
- package/client/src/hooks/useAppTheme.ts +17 -0
- package/client/src/hooks/useComponentPalette.ts +51 -0
- package/client/src/hooks/useCopyPaste.ts +155 -0
- package/client/src/hooks/useDragAndDrop.ts +124 -0
- package/client/src/hooks/useDragVariable.ts +88 -0
- package/client/src/hooks/useExecution.ts +313 -0
- package/client/src/hooks/useParameterPanel.ts +176 -0
- package/client/src/hooks/useReactFlowNodes.ts +189 -0
- package/client/src/hooks/useToolSchema.ts +209 -0
- package/client/src/hooks/useWhatsApp.ts +196 -0
- package/client/src/hooks/useWorkflowManagement.ts +46 -0
- package/client/src/index.css +315 -0
- package/client/src/main.tsx +19 -0
- package/client/src/nodeDefinitions/aiAgentNodes.ts +336 -0
- package/client/src/nodeDefinitions/aiModelNodes.ts +340 -0
- package/client/src/nodeDefinitions/androidDeviceNodes.ts +140 -0
- package/client/src/nodeDefinitions/androidServiceNodes.ts +383 -0
- package/client/src/nodeDefinitions/chatNodes.ts +135 -0
- package/client/src/nodeDefinitions/codeNodes.ts +54 -0
- package/client/src/nodeDefinitions/documentNodes.ts +379 -0
- package/client/src/nodeDefinitions/index.ts +15 -0
- package/client/src/nodeDefinitions/locationNodes.ts +463 -0
- package/client/src/nodeDefinitions/schedulerNodes.ts +220 -0
- package/client/src/nodeDefinitions/skillNodes.ts +211 -0
- package/client/src/nodeDefinitions/toolNodes.ts +198 -0
- package/client/src/nodeDefinitions/utilityNodes.ts +284 -0
- package/client/src/nodeDefinitions/whatsappNodes.ts +865 -0
- package/client/src/nodeDefinitions/workflowNodes.ts +41 -0
- package/client/src/nodeDefinitions.ts +104 -0
- package/client/src/schemas/workflowSchema.ts +264 -0
- package/client/src/services/dynamicParameterService.ts +96 -0
- package/client/src/services/execution/aiAgentExecutionService.ts +35 -0
- package/client/src/services/executionService.ts +232 -0
- package/client/src/services/workflowApi.ts +91 -0
- package/client/src/store/useAppStore.ts +582 -0
- package/client/src/styles/theme.ts +508 -0
- package/client/src/styles/zIndex.ts +17 -0
- package/client/src/types/ComponentTypes.ts +39 -0
- package/client/src/types/EdgeCondition.ts +231 -0
- package/client/src/types/INodeProperties.ts +288 -0
- package/client/src/types/NodeTypes.ts +28 -0
- package/client/src/utils/formatters.ts +33 -0
- package/client/src/utils/googleMapsLoader.ts +140 -0
- package/client/src/utils/locationUtils.ts +85 -0
- package/client/src/utils/nodeUtils.ts +31 -0
- package/client/src/utils/workflow.ts +30 -0
- package/client/src/utils/workflowExport.ts +120 -0
- package/client/src/vite-env.d.ts +12 -0
- package/client/tailwind.config.js +60 -0
- package/client/tsconfig.json +25 -0
- package/client/tsconfig.node.json +11 -0
- package/client/vite.config.js +35 -0
- package/docker-compose.prod.yml +107 -0
- package/docker-compose.yml +104 -0
- package/docs-MachinaOs/README.md +85 -0
- package/docs-MachinaOs/deployment/docker.mdx +228 -0
- package/docs-MachinaOs/deployment/production.mdx +345 -0
- package/docs-MachinaOs/docs.json +75 -0
- package/docs-MachinaOs/faq.mdx +309 -0
- package/docs-MachinaOs/favicon.svg +5 -0
- package/docs-MachinaOs/installation.mdx +160 -0
- package/docs-MachinaOs/introduction.mdx +114 -0
- package/docs-MachinaOs/logo/dark.svg +6 -0
- package/docs-MachinaOs/logo/light.svg +6 -0
- package/docs-MachinaOs/nodes/ai-agent.mdx +216 -0
- package/docs-MachinaOs/nodes/ai-models.mdx +240 -0
- package/docs-MachinaOs/nodes/android.mdx +411 -0
- package/docs-MachinaOs/nodes/overview.mdx +181 -0
- package/docs-MachinaOs/nodes/schedulers.mdx +316 -0
- package/docs-MachinaOs/nodes/webhooks.mdx +330 -0
- package/docs-MachinaOs/nodes/whatsapp.mdx +305 -0
- package/docs-MachinaOs/quickstart.mdx +119 -0
- package/docs-MachinaOs/tutorials/ai-agent-workflow.mdx +177 -0
- package/docs-MachinaOs/tutorials/android-automation.mdx +242 -0
- package/docs-MachinaOs/tutorials/first-workflow.mdx +134 -0
- package/docs-MachinaOs/tutorials/whatsapp-automation.mdx +185 -0
- package/nul +0 -0
- package/package.json +70 -0
- package/scripts/build.js +158 -0
- package/scripts/check-ports.ps1 +33 -0
- package/scripts/clean.js +40 -0
- package/scripts/docker.js +93 -0
- package/scripts/kill-port.ps1 +154 -0
- package/scripts/start.js +210 -0
- package/scripts/stop.js +325 -0
- package/server/.dockerignore +44 -0
- package/server/Dockerfile +45 -0
- package/server/constants.py +249 -0
- package/server/core/__init__.py +1 -0
- package/server/core/cache.py +461 -0
- package/server/core/config.py +128 -0
- package/server/core/container.py +99 -0
- package/server/core/database.py +1211 -0
- package/server/core/logging.py +314 -0
- package/server/main.py +289 -0
- package/server/middleware/__init__.py +5 -0
- package/server/middleware/auth.py +89 -0
- package/server/models/__init__.py +1 -0
- package/server/models/auth.py +52 -0
- package/server/models/cache.py +24 -0
- package/server/models/database.py +211 -0
- package/server/models/nodes.py +455 -0
- package/server/package.json +9 -0
- package/server/pyproject.toml +72 -0
- package/server/requirements.txt +83 -0
- package/server/routers/__init__.py +1 -0
- package/server/routers/android.py +294 -0
- package/server/routers/auth.py +203 -0
- package/server/routers/database.py +151 -0
- package/server/routers/maps.py +142 -0
- package/server/routers/nodejs_compat.py +289 -0
- package/server/routers/webhook.py +90 -0
- package/server/routers/websocket.py +2127 -0
- package/server/routers/whatsapp.py +761 -0
- package/server/routers/workflow.py +200 -0
- package/server/services/__init__.py +1 -0
- package/server/services/ai.py +2415 -0
- package/server/services/android/__init__.py +27 -0
- package/server/services/android/broadcaster.py +114 -0
- package/server/services/android/client.py +608 -0
- package/server/services/android/manager.py +78 -0
- package/server/services/android/protocol.py +165 -0
- package/server/services/android_service.py +588 -0
- package/server/services/auth.py +131 -0
- package/server/services/chat_client.py +160 -0
- package/server/services/deployment/__init__.py +12 -0
- package/server/services/deployment/manager.py +706 -0
- package/server/services/deployment/state.py +47 -0
- package/server/services/deployment/triggers.py +275 -0
- package/server/services/event_waiter.py +785 -0
- package/server/services/execution/__init__.py +77 -0
- package/server/services/execution/cache.py +769 -0
- package/server/services/execution/conditions.py +373 -0
- package/server/services/execution/dlq.py +132 -0
- package/server/services/execution/executor.py +1351 -0
- package/server/services/execution/models.py +531 -0
- package/server/services/execution/recovery.py +235 -0
- package/server/services/handlers/__init__.py +126 -0
- package/server/services/handlers/ai.py +355 -0
- package/server/services/handlers/android.py +260 -0
- package/server/services/handlers/code.py +278 -0
- package/server/services/handlers/document.py +598 -0
- package/server/services/handlers/http.py +193 -0
- package/server/services/handlers/polyglot.py +105 -0
- package/server/services/handlers/tools.py +845 -0
- package/server/services/handlers/triggers.py +107 -0
- package/server/services/handlers/utility.py +822 -0
- package/server/services/handlers/whatsapp.py +476 -0
- package/server/services/maps.py +289 -0
- package/server/services/memory_store.py +103 -0
- package/server/services/node_executor.py +375 -0
- package/server/services/parameter_resolver.py +218 -0
- package/server/services/polyglot_client.py +169 -0
- package/server/services/scheduler.py +155 -0
- package/server/services/skill_loader.py +417 -0
- package/server/services/status_broadcaster.py +826 -0
- package/server/services/temporal/__init__.py +23 -0
- package/server/services/temporal/activities.py +344 -0
- package/server/services/temporal/client.py +76 -0
- package/server/services/temporal/executor.py +147 -0
- package/server/services/temporal/worker.py +251 -0
- package/server/services/temporal/workflow.py +355 -0
- package/server/services/temporal/ws_client.py +236 -0
- package/server/services/text.py +111 -0
- package/server/services/user_auth.py +172 -0
- package/server/services/websocket_client.py +29 -0
- package/server/services/workflow.py +597 -0
- package/server/skills/android-skill/SKILL.md +82 -0
- package/server/skills/assistant-personality/SKILL.md +45 -0
- package/server/skills/code-skill/SKILL.md +140 -0
- package/server/skills/http-skill/SKILL.md +161 -0
- package/server/skills/maps-skill/SKILL.md +170 -0
- package/server/skills/memory-skill/SKILL.md +154 -0
- package/server/skills/scheduler-skill/SKILL.md +84 -0
- package/server/skills/whatsapp-skill/SKILL.md +283 -0
- package/server/uv.lock +2916 -0
- package/server/whatsapp-rpc/.dockerignore +30 -0
- package/server/whatsapp-rpc/Dockerfile +44 -0
- package/server/whatsapp-rpc/Dockerfile.web +17 -0
- package/server/whatsapp-rpc/README.md +139 -0
- package/server/whatsapp-rpc/cli.js +95 -0
- package/server/whatsapp-rpc/configs/config.yaml +7 -0
- package/server/whatsapp-rpc/docker-compose.yml +35 -0
- package/server/whatsapp-rpc/docs/API.md +410 -0
- package/server/whatsapp-rpc/go.mod +67 -0
- package/server/whatsapp-rpc/go.sum +203 -0
- package/server/whatsapp-rpc/package.json +30 -0
- package/server/whatsapp-rpc/schema.json +1294 -0
- package/server/whatsapp-rpc/scripts/clean.cjs +66 -0
- package/server/whatsapp-rpc/scripts/cli.js +162 -0
- package/server/whatsapp-rpc/src/go/cmd/server/main.go +91 -0
- package/server/whatsapp-rpc/src/go/config/config.go +49 -0
- package/server/whatsapp-rpc/src/go/rpc/rpc.go +446 -0
- package/server/whatsapp-rpc/src/go/rpc/server.go +112 -0
- package/server/whatsapp-rpc/src/go/whatsapp/history.go +166 -0
- package/server/whatsapp-rpc/src/go/whatsapp/messages.go +390 -0
- package/server/whatsapp-rpc/src/go/whatsapp/service.go +2130 -0
- package/server/whatsapp-rpc/src/go/whatsapp/types.go +261 -0
- package/server/whatsapp-rpc/src/python/pyproject.toml +15 -0
- package/server/whatsapp-rpc/src/python/whatsapp_rpc/__init__.py +4 -0
- package/server/whatsapp-rpc/src/python/whatsapp_rpc/client.py +427 -0
- package/server/whatsapp-rpc/web/app.py +609 -0
- package/server/whatsapp-rpc/web/requirements.txt +6 -0
- package/server/whatsapp-rpc/web/rpc_client.py +427 -0
- package/server/whatsapp-rpc/web/static/openapi.yaml +59 -0
- package/server/whatsapp-rpc/web/templates/base.html +150 -0
- package/server/whatsapp-rpc/web/templates/contacts.html +240 -0
- package/server/whatsapp-rpc/web/templates/dashboard.html +320 -0
- package/server/whatsapp-rpc/web/templates/groups.html +328 -0
- package/server/whatsapp-rpc/web/templates/messages.html +465 -0
- package/server/whatsapp-rpc/web/templates/messaging.html +681 -0
- package/server/whatsapp-rpc/web/templates/send.html +259 -0
- package/server/whatsapp-rpc/web/templates/settings.html +459 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge Condition Types for Runtime Conditional Branching
|
|
3
|
+
*
|
|
4
|
+
* Based on Prefect-style dynamic workflow branching.
|
|
5
|
+
* Conditions are evaluated against node output at runtime to determine
|
|
6
|
+
* which workflow paths to follow.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Supported comparison operators for edge conditions.
|
|
11
|
+
* Matches backend operators in server/services/execution/conditions.py
|
|
12
|
+
*/
|
|
13
|
+
export type ConditionOperator =
|
|
14
|
+
// Equality operators
|
|
15
|
+
| 'eq' // Equal (==)
|
|
16
|
+
| 'neq' // Not equal (!=)
|
|
17
|
+
// Comparison operators (numeric)
|
|
18
|
+
| 'gt' // Greater than (>)
|
|
19
|
+
| 'lt' // Less than (<)
|
|
20
|
+
| 'gte' // Greater than or equal (>=)
|
|
21
|
+
| 'lte' // Less than or equal (<=)
|
|
22
|
+
// String/list contains
|
|
23
|
+
| 'contains' // String/list contains value
|
|
24
|
+
| 'not_contains' // String/list does not contain value
|
|
25
|
+
// Existence checks
|
|
26
|
+
| 'exists' // Field exists and is not None
|
|
27
|
+
| 'not_exists' // Field does not exist or is None
|
|
28
|
+
// Empty checks
|
|
29
|
+
| 'is_empty' // Field is empty (None, "", [], {})
|
|
30
|
+
| 'is_not_empty' // Field is not empty
|
|
31
|
+
// Regex match
|
|
32
|
+
| 'matches' // Regex pattern match
|
|
33
|
+
// List membership
|
|
34
|
+
| 'in' // Value is in list
|
|
35
|
+
| 'not_in' // Value is not in list
|
|
36
|
+
// String prefix/suffix
|
|
37
|
+
| 'starts_with' // String starts with value
|
|
38
|
+
| 'ends_with' // String ends with value
|
|
39
|
+
// Boolean checks
|
|
40
|
+
| 'is_true' // Value is truthy
|
|
41
|
+
| 'is_false' // Value is falsy
|
|
42
|
+
// Type checks
|
|
43
|
+
| 'is_string' // Value is a string
|
|
44
|
+
| 'is_number' // Value is a number
|
|
45
|
+
| 'is_boolean' // Value is a boolean
|
|
46
|
+
| 'is_array' // Value is an array
|
|
47
|
+
| 'is_object'; // Value is an object
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Metadata for each operator - used by UI to render appropriate controls.
|
|
51
|
+
*/
|
|
52
|
+
export interface OperatorMetadata {
|
|
53
|
+
label: string;
|
|
54
|
+
description: string;
|
|
55
|
+
requiresValue: boolean;
|
|
56
|
+
valueType?: 'string' | 'number' | 'boolean' | 'array' | 'any';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Registry of all operators with their metadata.
|
|
61
|
+
* Matches OPERATORS dict in server/services/execution/conditions.py
|
|
62
|
+
*/
|
|
63
|
+
export const OPERATORS: Record<ConditionOperator, OperatorMetadata> = {
|
|
64
|
+
// Equality
|
|
65
|
+
eq: { label: 'Equals', description: 'Value equals target', requiresValue: true, valueType: 'any' },
|
|
66
|
+
neq: { label: 'Not Equals', description: 'Value does not equal target', requiresValue: true, valueType: 'any' },
|
|
67
|
+
// Comparison
|
|
68
|
+
gt: { label: 'Greater Than', description: 'Value is greater than target', requiresValue: true, valueType: 'number' },
|
|
69
|
+
lt: { label: 'Less Than', description: 'Value is less than target', requiresValue: true, valueType: 'number' },
|
|
70
|
+
gte: { label: 'Greater or Equal', description: 'Value is greater than or equal to target', requiresValue: true, valueType: 'number' },
|
|
71
|
+
lte: { label: 'Less or Equal', description: 'Value is less than or equal to target', requiresValue: true, valueType: 'number' },
|
|
72
|
+
// Contains
|
|
73
|
+
contains: { label: 'Contains', description: 'String/list contains value', requiresValue: true, valueType: 'string' },
|
|
74
|
+
not_contains: { label: 'Does Not Contain', description: 'String/list does not contain value', requiresValue: true, valueType: 'string' },
|
|
75
|
+
// Existence
|
|
76
|
+
exists: { label: 'Exists', description: 'Field exists and is not null', requiresValue: false },
|
|
77
|
+
not_exists: { label: 'Does Not Exist', description: 'Field does not exist or is null', requiresValue: false },
|
|
78
|
+
// Empty
|
|
79
|
+
is_empty: { label: 'Is Empty', description: 'Value is empty (null, "", [], {})', requiresValue: false },
|
|
80
|
+
is_not_empty: { label: 'Is Not Empty', description: 'Value is not empty', requiresValue: false },
|
|
81
|
+
// Regex
|
|
82
|
+
matches: { label: 'Matches Regex', description: 'Value matches regex pattern', requiresValue: true, valueType: 'string' },
|
|
83
|
+
// List membership
|
|
84
|
+
in: { label: 'In List', description: 'Value is in list', requiresValue: true, valueType: 'array' },
|
|
85
|
+
not_in: { label: 'Not In List', description: 'Value is not in list', requiresValue: true, valueType: 'array' },
|
|
86
|
+
// String prefix/suffix
|
|
87
|
+
starts_with: { label: 'Starts With', description: 'String starts with value', requiresValue: true, valueType: 'string' },
|
|
88
|
+
ends_with: { label: 'Ends With', description: 'String ends with value', requiresValue: true, valueType: 'string' },
|
|
89
|
+
// Boolean
|
|
90
|
+
is_true: { label: 'Is True', description: 'Value is truthy', requiresValue: false },
|
|
91
|
+
is_false: { label: 'Is False', description: 'Value is falsy', requiresValue: false },
|
|
92
|
+
// Type checks
|
|
93
|
+
is_string: { label: 'Is String', description: 'Value is a string', requiresValue: false },
|
|
94
|
+
is_number: { label: 'Is Number', description: 'Value is a number', requiresValue: false },
|
|
95
|
+
is_boolean: { label: 'Is Boolean', description: 'Value is a boolean', requiresValue: false },
|
|
96
|
+
is_array: { label: 'Is Array', description: 'Value is an array', requiresValue: false },
|
|
97
|
+
is_object: { label: 'Is Object', description: 'Value is an object', requiresValue: false },
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Single edge condition - evaluated against source node output.
|
|
102
|
+
*/
|
|
103
|
+
export interface EdgeCondition {
|
|
104
|
+
/** Output field to check (supports dot notation: "result.status", "items.0.name") */
|
|
105
|
+
field: string;
|
|
106
|
+
/** Comparison operator */
|
|
107
|
+
operator: ConditionOperator;
|
|
108
|
+
/** Value to compare against (required for operators with requiresValue: true) */
|
|
109
|
+
value?: string | number | boolean | any[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Extended edge data with condition support.
|
|
114
|
+
* Used in edge.data field for conditional branching.
|
|
115
|
+
*/
|
|
116
|
+
export interface ConditionalEdgeData {
|
|
117
|
+
/** Optional condition for this edge */
|
|
118
|
+
condition?: EdgeCondition;
|
|
119
|
+
/** Display label for the edge (shown on canvas) */
|
|
120
|
+
label?: string;
|
|
121
|
+
/** Logic for multiple conditions (future enhancement) */
|
|
122
|
+
conditionLogic?: 'and' | 'or';
|
|
123
|
+
/** Additional conditions (future enhancement) */
|
|
124
|
+
additionalConditions?: EdgeCondition[];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* React Flow edge with conditional data.
|
|
129
|
+
* Extends the base Edge type with typed data property.
|
|
130
|
+
*/
|
|
131
|
+
export interface ConditionalEdge {
|
|
132
|
+
id: string;
|
|
133
|
+
source: string;
|
|
134
|
+
target: string;
|
|
135
|
+
sourceHandle?: string | null;
|
|
136
|
+
targetHandle?: string | null;
|
|
137
|
+
type?: string;
|
|
138
|
+
animated?: boolean;
|
|
139
|
+
style?: React.CSSProperties;
|
|
140
|
+
className?: string;
|
|
141
|
+
data?: ConditionalEdgeData;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Props for the EdgeConditionEditor component.
|
|
146
|
+
*/
|
|
147
|
+
export interface EdgeConditionEditorProps {
|
|
148
|
+
/** The edge being edited */
|
|
149
|
+
edge: ConditionalEdge;
|
|
150
|
+
/** Callback when condition is updated */
|
|
151
|
+
onConditionChange: (condition: EdgeCondition | undefined) => void;
|
|
152
|
+
/** Callback when label is updated */
|
|
153
|
+
onLabelChange: (label: string | undefined) => void;
|
|
154
|
+
/** Available fields from source node output (for autocomplete) */
|
|
155
|
+
availableFields?: string[];
|
|
156
|
+
/** Callback to close the editor */
|
|
157
|
+
onClose: () => void;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get operators that don't require a value input.
|
|
162
|
+
*/
|
|
163
|
+
export function getNoValueOperators(): ConditionOperator[] {
|
|
164
|
+
return (Object.keys(OPERATORS) as ConditionOperator[]).filter(
|
|
165
|
+
op => !OPERATORS[op].requiresValue
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get operators that require a value input.
|
|
171
|
+
*/
|
|
172
|
+
export function getValueOperators(): ConditionOperator[] {
|
|
173
|
+
return (Object.keys(OPERATORS) as ConditionOperator[]).filter(
|
|
174
|
+
op => OPERATORS[op].requiresValue
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get operators grouped by category.
|
|
180
|
+
*/
|
|
181
|
+
export function getOperatorsByCategory(): Record<string, ConditionOperator[]> {
|
|
182
|
+
return {
|
|
183
|
+
'Equality': ['eq', 'neq'],
|
|
184
|
+
'Comparison': ['gt', 'lt', 'gte', 'lte'],
|
|
185
|
+
'Contains': ['contains', 'not_contains'],
|
|
186
|
+
'Existence': ['exists', 'not_exists'],
|
|
187
|
+
'Empty': ['is_empty', 'is_not_empty'],
|
|
188
|
+
'Pattern': ['matches', 'starts_with', 'ends_with'],
|
|
189
|
+
'List': ['in', 'not_in'],
|
|
190
|
+
'Boolean': ['is_true', 'is_false'],
|
|
191
|
+
'Type': ['is_string', 'is_number', 'is_boolean', 'is_array', 'is_object'],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format condition for display (edge label).
|
|
197
|
+
*/
|
|
198
|
+
export function formatConditionLabel(condition: EdgeCondition): string {
|
|
199
|
+
const op = OPERATORS[condition.operator];
|
|
200
|
+
if (!op) return '';
|
|
201
|
+
|
|
202
|
+
if (!op.requiresValue) {
|
|
203
|
+
return `${condition.field} ${op.label.toLowerCase()}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const valueStr = Array.isArray(condition.value)
|
|
207
|
+
? `[${condition.value.join(', ')}]`
|
|
208
|
+
: String(condition.value);
|
|
209
|
+
|
|
210
|
+
return `${condition.field} ${op.label.toLowerCase()} ${valueStr}`;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Validate a condition object.
|
|
215
|
+
*/
|
|
216
|
+
export function validateCondition(condition: EdgeCondition): { valid: boolean; error?: string } {
|
|
217
|
+
if (!condition.field || condition.field.trim() === '') {
|
|
218
|
+
return { valid: false, error: 'Field is required' };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!condition.operator || !OPERATORS[condition.operator]) {
|
|
222
|
+
return { valid: false, error: 'Invalid operator' };
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const op = OPERATORS[condition.operator];
|
|
226
|
+
if (op.requiresValue && (condition.value === undefined || condition.value === '')) {
|
|
227
|
+
return { valid: false, error: 'Value is required for this operator' };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { valid: true };
|
|
231
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// Modern n8n-inspired node property system
|
|
2
|
+
// Clean implementation with n8n-compatible data flow
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// DATA FLOW INTERFACES - n8n-compatible data passing between nodes
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
// Binary data interface for files, images, documents, etc.
|
|
9
|
+
export interface IBinaryData {
|
|
10
|
+
mimeType: string;
|
|
11
|
+
fileName?: string;
|
|
12
|
+
directory?: string;
|
|
13
|
+
fileExtension?: string;
|
|
14
|
+
fileSize?: number;
|
|
15
|
+
data: string; // Base64 encoded data
|
|
16
|
+
id?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Core data structure that flows between nodes (n8n-compatible)
|
|
20
|
+
export interface INodeExecutionData {
|
|
21
|
+
json: Record<string, any>; // Main JSON data
|
|
22
|
+
binary?: Record<string, IBinaryData>; // Binary attachments (files, images, etc.)
|
|
23
|
+
pairedItem?: {
|
|
24
|
+
item: number;
|
|
25
|
+
input?: number;
|
|
26
|
+
};
|
|
27
|
+
error?: Error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Input/Output connection types
|
|
31
|
+
export type NodeConnectionType =
|
|
32
|
+
| 'main' // Standard data connection
|
|
33
|
+
| 'trigger' // Trigger/start connection
|
|
34
|
+
| 'ai' // AI service responses
|
|
35
|
+
| 'file' // File data
|
|
36
|
+
| 'binary' // Binary data specific
|
|
37
|
+
| 'webhook'; // Webhook data
|
|
38
|
+
|
|
39
|
+
// Enhanced output definition with data structure info
|
|
40
|
+
export interface INodeOutputDefinition {
|
|
41
|
+
name: string;
|
|
42
|
+
displayName: string;
|
|
43
|
+
type: NodeConnectionType;
|
|
44
|
+
description: string;
|
|
45
|
+
maxConnections?: number; // How many nodes can connect to this output
|
|
46
|
+
dataStructure?: {
|
|
47
|
+
// Expected JSON structure this output provides
|
|
48
|
+
properties: Record<string, {
|
|
49
|
+
type: 'string' | 'number' | 'boolean' | 'object' | 'array';
|
|
50
|
+
description?: string;
|
|
51
|
+
required?: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
binaryData?: boolean; // Whether this output includes binary data
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Enhanced input definition
|
|
58
|
+
export interface INodeInputDefinition {
|
|
59
|
+
name: string;
|
|
60
|
+
displayName: string;
|
|
61
|
+
type: NodeConnectionType;
|
|
62
|
+
description: string;
|
|
63
|
+
required?: boolean;
|
|
64
|
+
maxConnections?: number; // How many connections this input accepts
|
|
65
|
+
acceptedDataTypes?: string[]; // What kind of data this input can handle
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// PROPERTY DEFINITION INTERFACES
|
|
70
|
+
// ============================================================================
|
|
71
|
+
|
|
72
|
+
export interface INodePropertyOption {
|
|
73
|
+
name: string;
|
|
74
|
+
value: string | number | boolean;
|
|
75
|
+
label?: string;
|
|
76
|
+
description?: string;
|
|
77
|
+
action?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface INodePropertyCollection {
|
|
81
|
+
displayName: string;
|
|
82
|
+
name: string;
|
|
83
|
+
values: INodeProperties[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface INodePropertyTypeOptions {
|
|
87
|
+
loadOptionsMethod?: string;
|
|
88
|
+
loadOptionsDependsOn?: string[];
|
|
89
|
+
multipleValues?: boolean;
|
|
90
|
+
multipleValueButtonText?: string;
|
|
91
|
+
maxValue?: number;
|
|
92
|
+
minValue?: number;
|
|
93
|
+
numberStepSize?: number;
|
|
94
|
+
password?: boolean;
|
|
95
|
+
rows?: number;
|
|
96
|
+
editor?: 'code' | 'json' | 'html' | 'sql';
|
|
97
|
+
editorLanguage?: string;
|
|
98
|
+
// Dynamic parameter options
|
|
99
|
+
dynamicOptions?: boolean;
|
|
100
|
+
dependsOn?: string[];
|
|
101
|
+
// File input options
|
|
102
|
+
accept?: string; // MIME types or file extensions (e.g., 'image/*', '.pdf,.doc')
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface INodePropertyDisplayOptions {
|
|
106
|
+
show?: Record<string, any[]>;
|
|
107
|
+
hide?: Record<string, any[]>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface INodePropertyValidation {
|
|
111
|
+
type?: 'regex' | 'email' | 'url' | 'json' | 'apiKey';
|
|
112
|
+
pattern?: string;
|
|
113
|
+
message?: string;
|
|
114
|
+
// API Key validation specific properties
|
|
115
|
+
provider?: string;
|
|
116
|
+
showValidateButton?: boolean;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Core property interface - modern n8n-inspired design
|
|
120
|
+
export interface INodeProperties {
|
|
121
|
+
displayName: string;
|
|
122
|
+
name: string;
|
|
123
|
+
type:
|
|
124
|
+
| 'string'
|
|
125
|
+
| 'number'
|
|
126
|
+
| 'boolean'
|
|
127
|
+
| 'options'
|
|
128
|
+
| 'multiOptions'
|
|
129
|
+
| 'collection'
|
|
130
|
+
| 'fixedCollection'
|
|
131
|
+
| 'color'
|
|
132
|
+
| 'dateTime'
|
|
133
|
+
| 'json'
|
|
134
|
+
| 'notice'
|
|
135
|
+
| 'hidden'
|
|
136
|
+
| 'resourceLocator'
|
|
137
|
+
| 'code'
|
|
138
|
+
| 'file';
|
|
139
|
+
|
|
140
|
+
default?: any;
|
|
141
|
+
description?: string;
|
|
142
|
+
placeholder?: string;
|
|
143
|
+
required?: boolean;
|
|
144
|
+
noDataExpression?: boolean;
|
|
145
|
+
|
|
146
|
+
options?: INodePropertyOption[] | INodePropertyCollection[];
|
|
147
|
+
typeOptions?: INodePropertyTypeOptions;
|
|
148
|
+
displayOptions?: INodePropertyDisplayOptions;
|
|
149
|
+
validation?: INodePropertyValidation[];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface INodeCredentialDescription {
|
|
153
|
+
name: string;
|
|
154
|
+
required?: boolean;
|
|
155
|
+
displayName?: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Resource definition for Resource-Operation pattern
|
|
159
|
+
export interface INodeResourceDefinition {
|
|
160
|
+
name: string;
|
|
161
|
+
displayName: string;
|
|
162
|
+
icon?: string;
|
|
163
|
+
description?: string;
|
|
164
|
+
operations: INodeOperationDefinition[];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export interface INodeOperationDefinition {
|
|
168
|
+
name: string;
|
|
169
|
+
displayName: string;
|
|
170
|
+
description?: string;
|
|
171
|
+
action?: string;
|
|
172
|
+
properties: INodeProperties[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
// Main node type description interface
|
|
177
|
+
export interface INodeTypeDescription {
|
|
178
|
+
displayName: string;
|
|
179
|
+
name: string;
|
|
180
|
+
icon: string;
|
|
181
|
+
group: string[];
|
|
182
|
+
version: number;
|
|
183
|
+
subtitle?: string;
|
|
184
|
+
description: string;
|
|
185
|
+
keywords?: string[];
|
|
186
|
+
defaults: {
|
|
187
|
+
name: string;
|
|
188
|
+
color?: string;
|
|
189
|
+
};
|
|
190
|
+
inputs: string[] | INodeInputDefinition[];
|
|
191
|
+
outputs: string[] | INodeOutputDefinition[];
|
|
192
|
+
properties: INodeProperties[];
|
|
193
|
+
credentials?: INodeCredentialDescription[];
|
|
194
|
+
resources?: INodeResourceDefinition[];
|
|
195
|
+
methods?: {
|
|
196
|
+
loadOptions?: Record<string, (this: any) => Promise<INodePropertyOption[]>>;
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Node type interface that nodes must implement
|
|
201
|
+
export interface INodeType {
|
|
202
|
+
description: INodeTypeDescription;
|
|
203
|
+
methods?: {
|
|
204
|
+
loadOptions?: Record<string, () => Promise<INodePropertyOption[]>>;
|
|
205
|
+
};
|
|
206
|
+
execute?(inputData: INodeExecutionData[][]): Promise<INodeExecutionData[][]>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Execution context for nodes
|
|
210
|
+
export interface IExecuteContext {
|
|
211
|
+
nodeId: string;
|
|
212
|
+
nodeType?: string; // Add nodeType to context
|
|
213
|
+
parameters: Record<string, any>;
|
|
214
|
+
inputData: INodeExecutionData[][];
|
|
215
|
+
workflow: {
|
|
216
|
+
id: string;
|
|
217
|
+
name: string;
|
|
218
|
+
};
|
|
219
|
+
connectionType?: NodeConnectionType;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// HELPER FUNCTIONS FOR DATA FLOW
|
|
224
|
+
// ============================================================================
|
|
225
|
+
|
|
226
|
+
// Helper to create execution data in n8n format
|
|
227
|
+
export function createNodeExecutionData(json: Record<string, any>, binary?: Record<string, IBinaryData>): INodeExecutionData {
|
|
228
|
+
return {
|
|
229
|
+
json,
|
|
230
|
+
binary,
|
|
231
|
+
pairedItem: { item: 0 }
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Helper to create simple text output
|
|
236
|
+
export function createTextOutput(text: string, additionalData?: Record<string, any>): INodeExecutionData[] {
|
|
237
|
+
return [{
|
|
238
|
+
json: {
|
|
239
|
+
text,
|
|
240
|
+
...additionalData
|
|
241
|
+
}
|
|
242
|
+
}];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Helper to create file output
|
|
246
|
+
export function createFileOutput(filePath: string, fileName: string, mimeType: string, additionalData?: Record<string, any>): INodeExecutionData[] {
|
|
247
|
+
return [{
|
|
248
|
+
json: {
|
|
249
|
+
fileName,
|
|
250
|
+
filePath,
|
|
251
|
+
mimeType,
|
|
252
|
+
...additionalData
|
|
253
|
+
},
|
|
254
|
+
binary: {
|
|
255
|
+
file: {
|
|
256
|
+
data: '', // Would be populated with actual file data
|
|
257
|
+
fileName,
|
|
258
|
+
mimeType,
|
|
259
|
+
fileSize: 0
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Helper to create AI response output
|
|
266
|
+
export function createAIOutput(response: string, model: string, usage?: any, additionalData?: Record<string, any>): INodeExecutionData[] {
|
|
267
|
+
return [{
|
|
268
|
+
json: {
|
|
269
|
+
response,
|
|
270
|
+
model,
|
|
271
|
+
usage,
|
|
272
|
+
timestamp: new Date().toISOString(),
|
|
273
|
+
...additionalData
|
|
274
|
+
}
|
|
275
|
+
}];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Helper to create location output
|
|
279
|
+
export function createLocationOutput(latitude: number, longitude: number, additionalData?: Record<string, any>): INodeExecutionData[] {
|
|
280
|
+
return [{
|
|
281
|
+
json: {
|
|
282
|
+
latitude,
|
|
283
|
+
longitude,
|
|
284
|
+
timestamp: new Date().toISOString(),
|
|
285
|
+
...additionalData
|
|
286
|
+
}
|
|
287
|
+
}];
|
|
288
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface NodeParameter {
|
|
2
|
+
name: string;
|
|
3
|
+
displayName: string;
|
|
4
|
+
type: 'string' | 'number' | 'boolean' | 'select' | 'slider' | 'percentage' | 'file' | 'text' | 'array' | 'options' | 'multiOptions' | 'collection' | 'fixedCollection' | 'color' | 'dateTime' | 'notice' | 'hidden' | 'resourceLocator' | 'code' | 'json';
|
|
5
|
+
default?: any;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
options?: Array<{ value: any; label?: string; name?: string }>;
|
|
9
|
+
min?: number;
|
|
10
|
+
max?: number;
|
|
11
|
+
step?: number;
|
|
12
|
+
required?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface NodeOutput {
|
|
16
|
+
name: string;
|
|
17
|
+
displayName: string;
|
|
18
|
+
type: 'string' | 'number' | 'boolean' | 'file' | 'array' | 'object' | string;
|
|
19
|
+
description: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export interface NodeData {
|
|
24
|
+
label?: string;
|
|
25
|
+
disabled?: boolean; // Skip execution when true (n8n-style disable)
|
|
26
|
+
customIcon?: string; // Custom icon: emoji, text, or image URL (http://, https://, data:, or /)
|
|
27
|
+
[key: string]: any;
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Common utility functions for formatting and clipboard operations
|
|
2
|
+
import { message } from 'antd';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copy text to clipboard with error handling
|
|
6
|
+
*/
|
|
7
|
+
export const copyToClipboard = async (data: any, successMessage?: string): Promise<boolean> => {
|
|
8
|
+
try {
|
|
9
|
+
const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
10
|
+
await navigator.clipboard.writeText(text);
|
|
11
|
+
if (successMessage) {
|
|
12
|
+
message.success(successMessage);
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error('Failed to copy to clipboard:', error);
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Format object as JSON string
|
|
23
|
+
*/
|
|
24
|
+
export const formatJson = (obj: any, compact: boolean = false): string => {
|
|
25
|
+
return JSON.stringify(obj, null, compact ? 0 : 2);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Format timestamp to locale string
|
|
30
|
+
*/
|
|
31
|
+
export const formatTimestamp = (timestamp: string | number | Date): string => {
|
|
32
|
+
return new Date(timestamp).toLocaleString();
|
|
33
|
+
};
|