machinaos 0.0.78 → 0.0.80
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 +74 -5
- package/{workflows/AI Assistant_workflow-1778504793388-ou1m1tz2x.json → .machina/workflows/AI Assistant_example_workflow-1779017037684-e2e5da7a.json } +164 -105
- package/{workflows/AI Employee_example_workflow-1777720598005-u4cm858dv.json → .machina/workflows/AI Employee_example_workflow-1779102911870-cbc76c82.json } +582 -328
- package/{workflows/Claude Assistant_workflow-1778380124051-mdibn807c.json → .machina/workflows/Claude Assistant_example_workflow-1779095939967-2369cff4.json } +152 -83
- package/README.md +5 -2
- package/bin/cli.js +2 -2
- package/{machina → cli}/__main__.py +11 -7
- package/cli/_common.py +122 -0
- package/cli/buildenv.py +40 -0
- package/cli/cli.py +204 -0
- package/{machina → cli}/colors.py +10 -2
- package/cli/commands/__init__.py +1 -0
- package/cli/commands/_temporal_specs.py +59 -0
- package/{machina → cli}/commands/build.py +35 -45
- package/cli/commands/clean.py +141 -0
- package/cli/commands/daemon/__init__.py +47 -0
- package/cli/commands/daemon/_state.py +97 -0
- package/cli/commands/daemon/restart.py +14 -0
- package/cli/commands/daemon/start.py +49 -0
- package/cli/commands/daemon/status.py +20 -0
- package/cli/commands/daemon/stop.py +22 -0
- package/{machina → cli}/commands/dev.py +32 -42
- package/{machina → cli}/commands/docs.py +13 -11
- package/{machina → cli}/commands/start.py +69 -62
- package/{machina → cli}/commands/stop.py +7 -10
- package/{machina → cli}/commands/version.py +12 -6
- package/cli/config.py +170 -0
- package/cli/platform_.py +169 -0
- package/{machina → cli}/ports.py +42 -3
- package/{machina → cli}/run.py +29 -2
- package/{machina → cli}/supervisor.py +29 -12
- package/{machina → cli}/tcp.py +6 -2
- package/{machina → cli}/tree.py +38 -11
- package/client/dist/assets/{ActionBar-Du2MSFSz.js → ActionBar-Cjr3TF7g.js} +1 -1
- package/client/dist/assets/{ApiKeyInput-k2LBmBjb.js → ApiKeyInput-DIJE2PVA.js} +1 -1
- package/client/dist/assets/{ApiKeyPanel-C_bV9U0X.js → ApiKeyPanel-CPmye7uh.js} +1 -1
- package/client/dist/assets/{ApiUsageSection-CmVfwZzL.js → ApiUsageSection-TF_7gH2D.js} +1 -1
- package/client/dist/assets/{EmailPanel-CeKIMGu-.js → EmailPanel-Bs-xvbKR.js} +1 -1
- package/client/dist/assets/{OAuthPanel-KA3t3Q2K.js → OAuthPanel-BDtVJhAV.js} +1 -1
- package/client/dist/assets/{QrPairingPanel-NgNpJNuk.js → QrPairingPanel-BwJehTuZ.js} +1 -1
- package/client/dist/assets/{RateLimitSection-Du5YNVIA.js → RateLimitSection-CfNOoPIS.js} +1 -1
- package/client/dist/assets/{StatusCard-DNLyayXc.js → StatusCard-DkwIrgdP.js} +1 -1
- package/client/dist/assets/index-P2FzntoL.js +165 -0
- package/client/dist/index.html +1 -1
- package/client/package.json +1 -1
- package/client/src/Dashboard.tsx +128 -76
- package/client/src/adapters/nodeSpecToDescription.ts +7 -0
- package/client/src/assets/icons/index.test.ts +10 -0
- package/client/src/assets/icons/index.ts +16 -3
- package/client/src/components/AIAgentNode.tsx +8 -8
- package/client/src/components/ParameterRenderer.tsx +6 -3
- package/client/src/components/SkillEditorModal.tsx +1 -0
- package/client/src/components/credentials/panels/EmailPanel.tsx +2 -0
- package/client/src/components/credentials/sections/ProviderDefaultsSection.tsx +2 -0
- package/client/src/components/credentials/sections/RateLimitSection.tsx +1 -0
- package/client/src/components/icons/AIProviderIcons.tsx +1 -0
- package/client/src/components/maps/GoogleMapsPicker.tsx +1 -0
- package/client/src/components/parameterPanel/InputSection.tsx +1 -0
- package/client/src/components/parameterPanel/MasterSkillEditor.tsx +1 -0
- package/client/src/components/parameterPanel/OutputSection.tsx +1 -0
- package/client/src/components/ui/ComponentPalette.tsx +1 -0
- package/client/src/components/ui/MapSelector.tsx +1 -0
- package/client/src/components/ui/NodeContextMenu.tsx +3 -3
- package/client/src/components/ui/SettingsPanel.tsx +1 -0
- package/client/src/components/ui/action-button.tsx +1 -0
- package/client/src/components/ui/badge.tsx +1 -0
- package/client/src/components/ui/button.tsx +1 -0
- package/client/src/components/ui/form.tsx +1 -0
- package/client/src/components/ui/tabs.tsx +1 -0
- package/client/src/contexts/AuthContext.tsx +1 -0
- package/client/src/contexts/ThemeContext.tsx +1 -0
- package/client/src/contexts/WebSocketContext.tsx +104 -34
- package/client/src/hooks/__tests__/useApiKeys.test.ts +2 -2
- package/client/src/hooks/useReactFlowNodes.ts +1 -0
- package/client/src/hooks/useWorkflowValidation.ts +142 -0
- package/client/src/lib/nodeSpec.ts +1 -0
- package/client/src/test/providers.tsx +1 -0
- package/client/src/types/__tests__/cloudEvents.test.ts +5 -2
- package/client/src/types/cloudEvents.ts +19 -7
- package/client/src/utils/nodeUtils.ts +1 -1
- package/client/src/utils/workflow.ts +8 -2
- package/client/src/utils/workflowExport.ts +60 -3
- package/package.json +24 -23
- package/scripts/install.js +16 -27
- package/scripts/migrate_icons.py +3 -1
- package/scripts/migrate_skill_icons.py +6 -7
- package/scripts/postinstall.js +11 -9
- package/server/config/ai_cli_providers.json +2 -3
- package/server/config/credential_providers.json +15 -15
- package/server/config/llm_defaults.json +1 -1
- package/server/config/model_registry.json +416 -611
- package/server/constants.py +285 -223
- package/server/core/__init__.py +1 -1
- package/server/core/cache.py +9 -29
- package/server/core/cleanup.py +12 -24
- package/server/core/config.py +148 -24
- package/server/core/container.py +68 -59
- package/server/core/credential_backends.py +5 -13
- package/server/core/credentials_database.py +13 -43
- package/server/core/database.py +292 -353
- package/server/core/health.py +4 -5
- package/server/core/logging.py +241 -87
- package/server/core/paths.py +285 -0
- package/server/core/tracing.py +2 -8
- package/server/gunicorn.conf.py +1 -0
- package/server/main.py +150 -74
- package/server/middleware/auth.py +18 -24
- package/server/models/__init__.py +1 -1
- package/server/models/auth.py +5 -12
- package/server/models/database.py +36 -68
- package/server/models/node_metadata.py +25 -18
- package/server/nodejs/dist/index.js +107 -0
- package/server/nodes/README.md +11 -5
- package/server/nodes/__init__.py +1 -1
- package/server/nodes/_visuals.py +146 -14
- package/server/nodes/agent/_events.py +124 -0
- package/server/nodes/agent/_handles.py +15 -29
- package/server/nodes/agent/_inline.py +28 -25
- package/server/nodes/agent/_specialized.py +30 -15
- package/server/nodes/agent/{ai_agent.py → ai_agent/__init__.py} +33 -17
- package/server/nodes/agent/ai_agent/meta.json +3 -0
- package/server/nodes/agent/{ai_employee.py → ai_employee/__init__.py} +5 -2
- package/server/nodes/agent/ai_employee/meta.json +3 -0
- package/server/nodes/agent/{android_agent.py → android_agent/__init__.py} +1 -1
- package/server/nodes/agent/android_agent/meta.json +3 -0
- package/server/nodes/agent/{autonomous_agent.py → autonomous_agent/__init__.py} +2 -1
- package/server/nodes/agent/autonomous_agent/meta.json +3 -0
- package/server/nodes/agent/{chat_agent.py → chat_agent/__init__.py} +29 -12
- package/server/nodes/agent/chat_agent/meta.json +3 -0
- package/server/nodes/agent/{claude_code_agent.py → claude_code_agent/__init__.py} +192 -95
- package/server/nodes/agent/claude_code_agent/_handlers.py +169 -0
- package/server/{services/claude_oauth.py → nodes/agent/claude_code_agent/_oauth.py} +26 -13
- package/server/nodes/agent/claude_code_agent/_pool.py +1020 -0
- package/server/nodes/agent/claude_code_agent/_provider.py +513 -0
- package/server/nodes/agent/claude_code_agent/_skills.py +245 -0
- package/server/nodes/agent/claude_code_agent/meta.json +3 -0
- package/server/nodes/agent/{codex_agent.py → codex_agent/__init__.py} +26 -35
- package/server/nodes/agent/codex_agent/meta.json +3 -0
- package/server/nodes/agent/{coding_agent.py → coding_agent/__init__.py} +1 -1
- package/server/nodes/agent/coding_agent/meta.json +3 -0
- package/server/nodes/agent/{consumer_agent.py → consumer_agent/__init__.py} +1 -1
- package/server/nodes/agent/consumer_agent/meta.json +3 -0
- package/server/nodes/agent/{orchestrator_agent.py → orchestrator_agent/__init__.py} +5 -2
- package/server/nodes/agent/orchestrator_agent/meta.json +3 -0
- package/server/nodes/agent/{payments_agent.py → payments_agent/__init__.py} +1 -1
- package/server/nodes/agent/payments_agent/meta.json +3 -0
- package/server/nodes/agent/{productivity_agent.py → productivity_agent/__init__.py} +1 -1
- package/server/nodes/agent/productivity_agent/meta.json +3 -0
- package/server/nodes/agent/{rlm_agent.py → rlm_agent/__init__.py} +18 -17
- package/server/nodes/agent/rlm_agent/meta.json +3 -0
- package/server/nodes/agent/{social_agent.py → social_agent/__init__.py} +1 -1
- package/server/nodes/agent/social_agent/meta.json +3 -0
- package/server/nodes/agent/{task_agent.py → task_agent/__init__.py} +1 -1
- package/server/nodes/agent/task_agent/meta.json +3 -0
- package/server/nodes/agent/{tool_agent.py → tool_agent/__init__.py} +1 -1
- package/server/nodes/agent/tool_agent/meta.json +3 -0
- package/server/nodes/agent/{travel_agent.py → travel_agent/__init__.py} +1 -1
- package/server/nodes/agent/travel_agent/meta.json +3 -0
- package/server/nodes/agent/{web_agent.py → web_agent/__init__.py} +1 -1
- package/server/nodes/agent/web_agent/meta.json +3 -0
- package/server/nodes/android/__init__.py +24 -0
- package/server/nodes/android/_base.py +93 -76
- package/server/nodes/android/_dispatcher.py +140 -223
- package/server/nodes/android/_events.py +154 -0
- package/server/nodes/android/_handlers.py +13 -7
- package/server/nodes/android/_option_loaders.py +1 -4
- package/server/nodes/android/_refresh.py +27 -37
- package/server/nodes/android/_relay/broadcaster.py +25 -41
- package/server/nodes/android/_relay/client.py +23 -42
- package/server/nodes/android/_relay/manager.py +1 -0
- package/server/nodes/android/_relay/protocol.py +6 -0
- package/server/nodes/android/_router.py +48 -133
- package/server/nodes/android/{airplane_mode_control.py → airplane_mode_control/__init__.py} +2 -1
- package/server/nodes/android/airplane_mode_control/meta.json +3 -0
- package/server/nodes/android/{app_launcher.py → app_launcher/__init__.py} +2 -1
- package/server/nodes/android/app_launcher/meta.json +3 -0
- package/server/nodes/android/{app_list.py → app_list/__init__.py} +2 -1
- package/server/nodes/android/app_list/meta.json +3 -0
- package/server/nodes/android/{audio_automation.py → audio_automation/__init__.py} +2 -1
- package/server/nodes/android/audio_automation/meta.json +3 -0
- package/server/nodes/android/{battery_monitor.py → battery_monitor/__init__.py} +2 -1
- package/server/nodes/android/battery_monitor/meta.json +3 -0
- package/server/nodes/android/{bluetooth_automation.py → bluetooth_automation/__init__.py} +2 -1
- package/server/nodes/android/bluetooth_automation/meta.json +3 -0
- package/server/nodes/android/{camera_control.py → camera_control/__init__.py} +2 -1
- package/server/nodes/android/camera_control/meta.json +3 -0
- package/server/nodes/android/{device_state_automation.py → device_state_automation/__init__.py} +2 -1
- package/server/nodes/android/device_state_automation/meta.json +3 -0
- package/server/nodes/android/{environmental_sensors.py → environmental_sensors/__init__.py} +2 -1
- package/server/nodes/android/environmental_sensors/meta.json +3 -0
- package/server/nodes/android/{location.py → location/__init__.py} +2 -1
- package/server/nodes/android/location/meta.json +3 -0
- package/server/nodes/android/{media_control.py → media_control/__init__.py} +2 -1
- package/server/nodes/android/media_control/meta.json +3 -0
- package/server/nodes/android/{motion_detection.py → motion_detection/__init__.py} +2 -1
- package/server/nodes/android/motion_detection/meta.json +3 -0
- package/server/nodes/android/{network_monitor.py → network_monitor/__init__.py} +2 -1
- package/server/nodes/android/network_monitor/meta.json +3 -0
- package/server/nodes/android/{screen_control_automation.py → screen_control_automation/__init__.py} +2 -1
- package/server/nodes/android/screen_control_automation/meta.json +3 -0
- package/server/nodes/android/{system_info.py → system_info/__init__.py} +2 -1
- package/server/nodes/android/system_info/meta.json +3 -0
- package/server/nodes/android/{wifi_automation.py → wifi_automation/__init__.py} +2 -1
- package/server/nodes/android/wifi_automation/meta.json +3 -0
- package/server/nodes/browser/__init__.py +22 -1
- package/server/nodes/browser/_install.py +63 -0
- package/server/nodes/browser/_service.py +21 -25
- package/server/nodes/browser/{browser.py → browser/__init__.py} +58 -25
- package/server/nodes/browser/browser/meta.json +3 -0
- package/server/nodes/chat/{chat_history.py → chat_history/__init__.py} +2 -4
- package/server/nodes/chat/chat_history/meta.json +3 -0
- package/server/nodes/chat/{chat_send.py → chat_send/__init__.py} +2 -4
- package/server/nodes/chat/chat_send/icon.svg +1 -0
- package/server/nodes/chat/chat_send/meta.json +3 -0
- package/server/nodes/code/_base.py +1 -1
- package/server/nodes/code/{javascript_executor.py → javascript_executor/__init__.py} +5 -5
- package/server/nodes/code/javascript_executor/meta.json +3 -0
- package/server/nodes/code/{python_executor.py → python_executor/__init__.py} +32 -14
- package/server/nodes/code/python_executor/meta.json +3 -0
- package/server/nodes/code/{typescript_executor.py → typescript_executor/__init__.py} +5 -5
- package/server/nodes/code/typescript_executor/meta.json +3 -0
- package/server/nodes/document/{document_parser.py → document_parser/__init__.py} +26 -15
- package/server/nodes/document/document_parser/meta.json +3 -0
- package/server/nodes/document/{embedding_generator.py → embedding_generator/__init__.py} +16 -9
- package/server/nodes/document/embedding_generator/meta.json +3 -0
- package/server/nodes/document/{file_downloader.py → file_downloader/__init__.py} +30 -20
- package/server/nodes/document/file_downloader/meta.json +3 -0
- package/server/nodes/document/{http_scraper.py → http_scraper/__init__.py} +31 -21
- package/server/nodes/document/http_scraper/meta.json +3 -0
- package/server/nodes/document/{text_chunker.py → text_chunker/__init__.py} +17 -12
- package/server/nodes/document/text_chunker/meta.json +3 -0
- package/server/nodes/document/{vector_store.py → vector_store/__init__.py} +88 -72
- package/server/nodes/document/vector_store/meta.json +3 -0
- package/server/nodes/email/__init__.py +9 -2
- package/server/nodes/email/_events.py +54 -0
- package/server/nodes/email/_filters.py +3 -3
- package/server/nodes/email/_himalaya.py +95 -50
- package/server/nodes/email/_service.py +23 -13
- package/server/nodes/email/{email_read.py → email_read/__init__.py} +23 -11
- package/server/nodes/email/email_read/icon.svg +6 -0
- package/server/nodes/email/email_read/meta.json +3 -0
- package/server/nodes/email/{email_receive.py → email_receive/__init__.py} +45 -23
- package/server/nodes/email/email_receive/meta.json +3 -0
- package/server/nodes/email/{email_send.py → email_send/__init__.py} +13 -7
- package/server/nodes/email/email_send/meta.json +3 -0
- package/server/nodes/filesystem/_backend.py +1 -5
- package/server/nodes/filesystem/{file_modify.py → file_modify/__init__.py} +10 -5
- package/server/nodes/filesystem/file_modify/meta.json +3 -0
- package/server/nodes/filesystem/{file_read.py → file_read/__init__.py} +7 -3
- package/server/nodes/filesystem/file_read/meta.json +3 -0
- package/server/nodes/filesystem/{fs_search.py → fs_search/__init__.py} +11 -3
- package/server/nodes/filesystem/fs_search/meta.json +3 -0
- package/server/nodes/filesystem/{shell.py → shell/__init__.py} +12 -5
- package/server/nodes/filesystem/shell/meta.json +3 -0
- package/server/nodes/google/__init__.py +12 -0
- package/server/nodes/google/_auth_helper.py +7 -13
- package/server/nodes/google/_base.py +14 -11
- package/server/nodes/google/_credentials.py +2 -1
- package/server/nodes/google/_events.py +47 -0
- package/server/nodes/google/_filters.py +3 -3
- package/server/nodes/google/_gmail.py +70 -47
- package/server/nodes/google/_handlers.py +3 -1
- package/server/nodes/google/_oauth.py +25 -11
- package/server/nodes/google/_option_loaders.py +9 -30
- package/server/nodes/google/_refresh.py +8 -12
- package/server/nodes/google/_router.py +4 -5
- package/server/nodes/google/{calendar.py → calendar/__init__.py} +87 -64
- package/server/nodes/google/calendar/meta.json +3 -0
- package/server/nodes/google/{contacts.py → contacts/__init__.py} +84 -72
- package/server/nodes/google/contacts/meta.json +3 -0
- package/server/nodes/google/{drive.py → drive/__init__.py} +87 -72
- package/server/nodes/google/drive/meta.json +3 -0
- package/server/nodes/google/{gmail.py → gmail/__init__.py} +73 -39
- package/server/nodes/google/gmail/meta.json +3 -0
- package/server/nodes/google/{gmail_receive.py → gmail_receive/__init__.py} +31 -24
- package/server/nodes/google/gmail_receive/icon.svg +7 -0
- package/server/nodes/google/gmail_receive/meta.json +3 -0
- package/server/nodes/google/google.svg +7 -0
- package/server/nodes/google/{sheets.py → sheets/__init__.py} +54 -42
- package/server/nodes/google/sheets/meta.json +3 -0
- package/server/nodes/google/{tasks.py → tasks/__init__.py} +56 -43
- package/server/nodes/google/tasks/meta.json +3 -0
- package/server/nodes/groups.py +28 -28
- package/server/nodes/location/__init__.py +31 -1
- package/server/nodes/location/_credentials.py +1 -6
- package/server/nodes/location/_service.py +88 -107
- package/server/nodes/location/{gmaps_create.py → gmaps_create/__init__.py} +6 -6
- package/server/nodes/location/gmaps_create/meta.json +3 -0
- package/server/nodes/location/{gmaps_locations.py → gmaps_locations/__init__.py} +8 -6
- package/server/nodes/location/gmaps_locations/meta.json +3 -0
- package/server/nodes/location/{gmaps_nearby_places.py → gmaps_nearby_places/__init__.py} +8 -6
- package/server/nodes/location/gmaps_nearby_places/meta.json +3 -0
- package/server/nodes/model/_base.py +10 -7
- package/server/nodes/model/_credentials.py +10 -10
- package/server/nodes/model/_local_validator.py +28 -24
- package/server/nodes/model/{anthropic_chat_model.py → anthropic_chat_model/__init__.py} +5 -3
- package/server/nodes/model/anthropic_chat_model/meta.json +3 -0
- package/server/nodes/model/{cerebras_chat_model.py → cerebras_chat_model/__init__.py} +5 -3
- package/server/nodes/model/cerebras_chat_model/meta.json +3 -0
- package/server/nodes/model/{deepseek_chat_model.py → deepseek_chat_model/__init__.py} +8 -4
- package/server/nodes/model/deepseek_chat_model/meta.json +3 -0
- package/server/nodes/model/{gemini_chat_model.py → gemini_chat_model/__init__.py} +5 -3
- package/server/nodes/model/gemini_chat_model/meta.json +3 -0
- package/server/nodes/model/{groq_chat_model.py → groq_chat_model/__init__.py} +2 -2
- package/server/nodes/model/groq_chat_model/meta.json +3 -0
- package/server/nodes/model/{kimi_chat_model.py → kimi_chat_model/__init__.py} +2 -2
- package/server/nodes/model/kimi_chat_model/meta.json +3 -0
- package/server/nodes/model/{lmstudio_chat_model.py → lmstudio_chat_model/__init__.py} +2 -2
- package/server/nodes/model/lmstudio_chat_model/meta.json +3 -0
- package/server/nodes/model/{mistral_chat_model.py → mistral_chat_model/__init__.py} +2 -2
- package/server/nodes/model/mistral_chat_model/meta.json +3 -0
- package/server/nodes/model/{ollama_chat_model.py → ollama_chat_model/__init__.py} +2 -2
- package/server/nodes/model/ollama_chat_model/meta.json +3 -0
- package/server/nodes/model/{openai_chat_model.py → openai_chat_model/__init__.py} +8 -4
- package/server/nodes/model/openai_chat_model/meta.json +3 -0
- package/server/nodes/model/{openrouter_chat_model.py → openrouter_chat_model/__init__.py} +8 -4
- package/server/nodes/model/openrouter_chat_model/meta.json +3 -0
- package/server/nodes/proxy/_usage.py +14 -15
- package/server/nodes/proxy/{proxy_config.py → proxy_config/__init__.py} +39 -30
- package/server/nodes/proxy/proxy_config/meta.json +3 -0
- package/server/nodes/proxy/{proxy_request.py → proxy_request/__init__.py} +30 -16
- package/server/nodes/proxy/proxy_request/meta.json +3 -0
- package/server/nodes/proxy/{proxy_status.py → proxy_status/__init__.py} +2 -0
- package/server/nodes/proxy/proxy_status/meta.json +3 -0
- package/server/nodes/scheduler/{cron_scheduler.py → cron_scheduler/__init__.py} +96 -23
- package/server/nodes/scheduler/cron_scheduler/_workflow.py +155 -0
- package/server/nodes/scheduler/cron_scheduler/meta.json +3 -0
- package/server/nodes/scheduler/{timer.py → timer/__init__.py} +6 -5
- package/server/nodes/scheduler/timer/meta.json +3 -0
- package/server/nodes/scraper/_credentials.py +0 -1
- package/server/nodes/scraper/{apify_actor.py → apify_actor/__init__.py} +44 -35
- package/server/nodes/scraper/apify_actor/icon.svg +5 -0
- package/server/nodes/scraper/apify_actor/meta.json +3 -0
- package/server/nodes/scraper/{crawlee_scraper.py → crawlee_scraper/__init__.py} +96 -57
- package/server/nodes/scraper/crawlee_scraper/meta.json +3 -0
- package/server/nodes/search/{brave_search.py → brave_search/__init__.py} +6 -5
- package/server/nodes/search/brave_search/icon.svg +3 -0
- package/server/nodes/search/brave_search/meta.json +3 -0
- package/server/nodes/search/{duckduckgo_search.py → duckduckgo_search/__init__.py} +17 -6
- package/server/nodes/search/duckduckgo_search/meta.json +3 -0
- package/server/nodes/search/{perplexity_search.py → perplexity_search/__init__.py} +4 -5
- package/server/nodes/search/perplexity_search/icon.svg +3 -0
- package/server/nodes/search/perplexity_search/meta.json +3 -0
- package/server/nodes/search/{serper_search.py → serper_search/__init__.py} +32 -25
- package/server/nodes/search/serper_search/icon.svg +3 -0
- package/server/nodes/search/serper_search/meta.json +3 -0
- package/server/nodes/skill/__init__.py +21 -1
- package/server/nodes/skill/_expander.py +75 -0
- package/server/nodes/skill/{master_skill.py → master_skill/__init__.py} +2 -8
- package/server/nodes/skill/master_skill/_events.py +84 -0
- package/server/nodes/skill/master_skill/meta.json +3 -0
- package/server/nodes/skill/{simple_memory.py → simple_memory/__init__.py} +8 -16
- package/server/nodes/skill/simple_memory/meta.json +3 -0
- package/server/nodes/social/_base.py +223 -231
- package/server/nodes/social/{social_receive.py → social_receive/__init__.py} +38 -13
- package/server/nodes/social/social_receive/meta.json +3 -0
- package/server/nodes/social/{social_send.py → social_send/__init__.py} +71 -29
- package/server/nodes/social/social_send/icon.svg +1 -0
- package/server/nodes/social/social_send/meta.json +3 -0
- package/server/nodes/stripe/__init__.py +7 -3
- package/server/nodes/stripe/_credentials.py +0 -1
- package/server/nodes/stripe/_handlers.py +18 -7
- package/server/nodes/stripe/_install.py +14 -15
- package/server/nodes/stripe/_source.py +5 -5
- package/server/nodes/stripe/icon.svg +1 -0
- package/server/nodes/stripe/meta.json +3 -0
- package/server/nodes/stripe/stripe_action.py +4 -4
- package/server/nodes/stripe/stripe_receive.py +6 -9
- package/server/nodes/telegram/__init__.py +13 -0
- package/server/nodes/telegram/_credentials.py +2 -7
- package/server/nodes/telegram/_events.py +167 -0
- package/server/nodes/telegram/_filters.py +3 -11
- package/server/nodes/telegram/_handlers.py +17 -7
- package/server/nodes/telegram/_refresh.py +24 -34
- package/server/nodes/telegram/_service.py +29 -45
- package/server/nodes/telegram/meta.json +3 -0
- package/server/nodes/telegram/telegram.svg +3 -0
- package/server/nodes/telegram/telegram_receive.py +38 -18
- package/server/nodes/telegram/telegram_send.py +21 -19
- package/server/nodes/text/{file_handler.py → file_handler/__init__.py} +7 -1
- package/server/nodes/text/file_handler/meta.json +3 -0
- package/server/nodes/text/{text_generator.py → text_generator/__init__.py} +2 -1
- package/server/nodes/text/text_generator/meta.json +3 -0
- package/server/nodes/tool/{agent_builder.py → agent_builder/__init__.py} +105 -100
- package/server/nodes/tool/agent_builder/_events.py +91 -0
- package/server/nodes/tool/agent_builder/meta.json +3 -0
- package/server/nodes/tool/{calculator_tool.py → calculator_tool/__init__.py} +19 -7
- package/server/nodes/tool/calculator_tool/meta.json +3 -0
- package/server/nodes/tool/{current_time_tool.py → current_time_tool/__init__.py} +6 -4
- package/server/nodes/tool/current_time_tool/meta.json +3 -0
- package/server/nodes/tool/{task_manager.py → task_manager/__init__.py} +17 -18
- package/server/nodes/tool/task_manager/meta.json +3 -0
- package/server/nodes/tool/{write_todos.py → write_todos/__init__.py} +20 -6
- package/server/nodes/tool/write_todos/meta.json +3 -0
- package/server/nodes/trigger/{chat_trigger.py → chat_trigger/__init__.py} +11 -7
- package/server/nodes/trigger/chat_trigger/_events.py +53 -0
- package/server/nodes/trigger/chat_trigger/meta.json +3 -0
- package/server/nodes/trigger/{task_trigger.py → task_trigger/__init__.py} +10 -7
- package/server/nodes/trigger/task_trigger/meta.json +3 -0
- package/server/nodes/trigger/{webhook_trigger.py → webhook_trigger/__init__.py} +10 -7
- package/server/nodes/trigger/webhook_trigger/_events.py +54 -0
- package/server/nodes/trigger/webhook_trigger/meta.json +3 -0
- package/server/nodes/twitter/__init__.py +7 -1
- package/server/nodes/twitter/_base.py +86 -61
- package/server/nodes/twitter/_credentials.py +7 -5
- package/server/nodes/twitter/_events.py +101 -0
- package/server/nodes/twitter/_filters.py +9 -9
- package/server/nodes/twitter/_handlers.py +3 -1
- package/server/nodes/twitter/_oauth.py +1 -2
- package/server/nodes/twitter/_refresh.py +8 -12
- package/server/nodes/twitter/{twitter_receive.py → twitter_receive/__init__.py} +7 -7
- package/server/nodes/twitter/twitter_receive/icon.svg +1 -0
- package/server/nodes/twitter/twitter_receive/meta.json +3 -0
- package/server/nodes/twitter/{twitter_search.py → twitter_search/__init__.py} +16 -11
- package/server/nodes/twitter/twitter_search/icon.svg +1 -0
- package/server/nodes/twitter/twitter_search/meta.json +3 -0
- package/server/nodes/twitter/{twitter_send.py → twitter_send/__init__.py} +60 -27
- package/server/nodes/twitter/twitter_send/icon.svg +1 -0
- package/server/nodes/twitter/twitter_send/meta.json +3 -0
- package/server/nodes/twitter/{twitter_user.py → twitter_user/__init__.py} +34 -19
- package/server/nodes/twitter/twitter_user/icon.svg +1 -0
- package/server/nodes/twitter/twitter_user/meta.json +3 -0
- package/server/nodes/utility/{console.py → console/__init__.py} +17 -22
- package/server/nodes/utility/console/meta.json +3 -0
- package/server/nodes/utility/{http_request.py → http_request/__init__.py} +9 -6
- package/server/nodes/utility/http_request/meta.json +3 -0
- package/server/nodes/utility/{process_manager.py → process_manager/__init__.py} +10 -6
- package/server/nodes/utility/process_manager/meta.json +3 -0
- package/server/nodes/utility/team_monitor/meta.json +3 -0
- package/server/nodes/utility/{webhook_response.py → webhook_response/__init__.py} +12 -7
- package/server/nodes/utility/webhook_response/meta.json +3 -0
- package/server/nodes/visuals.json +69 -251
- package/server/nodes/whatsapp/__init__.py +24 -0
- package/server/nodes/whatsapp/_base.py +283 -338
- package/server/nodes/whatsapp/_credentials.py +44 -0
- package/server/nodes/whatsapp/_events.py +277 -0
- package/server/nodes/whatsapp/_filters.py +36 -37
- package/server/nodes/whatsapp/_handlers.py +2 -0
- package/server/nodes/whatsapp/_option_loaders.py +1 -3
- package/server/nodes/whatsapp/_refresh.py +13 -18
- package/server/nodes/whatsapp/_runtime.py +9 -6
- package/server/nodes/whatsapp/_service.py +89 -152
- package/server/nodes/whatsapp/meta.json +3 -0
- package/server/nodes/whatsapp/whatsapp_db.py +116 -54
- package/server/nodes/whatsapp/whatsapp_receive.py +30 -13
- package/server/nodes/whatsapp/whatsapp_send.py +60 -37
- package/server/nodes/workflow/{start.py → start/__init__.py} +1 -4
- package/server/nodes/workflow/start/meta.json +3 -0
- package/server/package-lock.json +3 -3
- package/server/package.json +3 -0
- package/server/pyproject.toml +39 -10
- package/server/requirements.txt +3 -5
- package/server/routers/__init__.py +1 -1
- package/server/routers/auth.py +16 -56
- package/server/routers/database.py +27 -50
- package/server/routers/nodejs_compat.py +25 -87
- package/server/routers/schemas.py +66 -2
- package/server/routers/webhook.py +12 -12
- package/server/routers/websocket.py +312 -1716
- package/server/routers/workflow.py +28 -53
- package/server/scripts/smoke_test_skills.py +178 -0
- package/server/services/__init__.py +1 -1
- package/server/services/_supervisor/process.py +9 -3
- package/server/services/_supervisor/registry.py +3 -3
- package/server/services/_supervisor/util.py +1 -1
- package/server/services/agent_team.py +15 -43
- package/server/services/agent_teams/__init__.py +17 -0
- package/server/services/agent_teams/handlers.py +195 -0
- package/server/services/ai.py +853 -1108
- package/server/services/auth.py +10 -34
- package/server/services/chat_client.py +5 -34
- package/server/services/circuit_breaker.py +2 -6
- package/server/services/cli_agent/__init__.py +28 -4
- package/server/services/cli_agent/_cli_auth.py +61 -0
- package/server/services/cli_agent/_handlers.py +24 -183
- package/server/services/cli_agent/config.py +5 -8
- package/server/services/cli_agent/factory.py +168 -22
- package/server/services/cli_agent/jsonl_watcher.py +380 -0
- package/server/services/cli_agent/lockfile.py +9 -2
- package/server/services/cli_agent/mcp_server.py +110 -34
- package/server/services/cli_agent/protocol.py +37 -19
- package/server/services/cli_agent/providers/__init__.py +8 -4
- package/server/services/cli_agent/providers/google_gemini.py +11 -5
- package/server/services/cli_agent/providers/openai_codex.py +34 -34
- package/server/services/cli_agent/service.py +245 -83
- package/server/services/cli_agent/session.py +409 -229
- package/server/services/cli_agent/transports/__init__.py +47 -0
- package/server/services/cli_agent/transports/base.py +111 -0
- package/server/services/cli_agent/transports/posix.py +196 -0
- package/server/services/cli_agent/transports/windows.py +189 -0
- package/server/services/cli_agent/types.py +45 -18
- package/server/services/cli_agent/workflow_tools.py +28 -15
- package/server/services/compaction.py +68 -52
- package/server/services/credential_registry.py +6 -20
- package/server/services/credentials/__init__.py +18 -0
- package/server/services/credentials/handlers.py +196 -0
- package/server/services/deployment/__init__.py +12 -1
- package/server/services/deployment/canary_registry.py +137 -0
- package/server/services/deployment/handlers.py +382 -0
- package/server/services/deployment/manager.py +653 -163
- package/server/services/deployment/poll_registry.py +2 -6
- package/server/services/deployment/state.py +2 -0
- package/server/services/deployment/triggers.py +87 -93
- package/server/services/event_waiter.py +47 -54
- package/server/services/events/__init__.py +11 -0
- package/server/services/events/admin_handlers.py +368 -0
- package/server/services/events/daemon.py +3 -1
- package/server/services/events/dispatch.py +188 -0
- package/server/services/events/envelope.py +264 -45
- package/server/services/events/oauth_lifecycle.py +98 -42
- package/server/services/events/triggers.py +3 -13
- package/server/services/events/verifiers/hmac_basic.py +1 -1
- package/server/services/events/verifiers/standard_webhooks.py +2 -4
- package/server/services/events/webhook.py +2 -3
- package/server/services/example_loader.py +73 -15
- package/server/services/execution/cache.py +36 -76
- package/server/services/execution/conditions.py +7 -20
- package/server/services/execution/dlq.py +20 -24
- package/server/services/execution/executor.py +234 -265
- package/server/services/execution/models.py +40 -46
- package/server/services/execution/recovery.py +23 -46
- package/server/services/handlers/__init__.py +12 -16
- package/server/services/handlers/todo.py +3 -6
- package/server/services/handlers/tools.py +143 -194
- package/server/services/handlers/triggers.py +24 -23
- package/server/services/llm/config.py +10 -1
- package/server/services/llm/factory.py +16 -4
- package/server/services/llm/messages.py +1 -5
- package/server/services/llm/protocol.py +9 -1
- package/server/services/llm/providers/anthropic.py +23 -12
- package/server/services/llm/providers/gemini.py +43 -22
- package/server/services/llm/providers/openai.py +14 -6
- package/server/services/llm/providers/openrouter.py +6 -1
- package/server/services/markdown_formatter.py +1 -2
- package/server/services/memory/__init__.py +2 -2
- package/server/services/memory/jsonl.py +6 -2
- package/server/services/memory/markdown.py +6 -6
- package/server/services/memory/state.py +6 -5
- package/server/services/memory_store.py +8 -12
- package/server/services/model_registry.py +22 -20
- package/server/services/node_executor.py +85 -80
- package/server/services/node_output_schemas.py +4 -7
- package/server/services/node_registry.py +40 -4
- package/server/services/node_spec.py +3 -7
- package/server/services/nodejs_client.py +4 -14
- package/server/services/oauth_utils.py +11 -7
- package/server/services/parameter_resolver.py +30 -36
- package/server/services/plugin/base.py +321 -38
- package/server/services/plugin/connection.py +12 -7
- package/server/services/plugin/credential.py +80 -22
- package/server/services/plugin/edge_walker.py +128 -105
- package/server/services/plugin/identifiers.py +48 -0
- package/server/services/plugin/interceptor.py +1 -1
- package/server/services/plugin/oauth.py +25 -21
- package/server/services/plugin/operation.py +1 -1
- package/server/services/plugin/polling.py +151 -26
- package/server/services/plugin/registry.py +52 -4
- package/server/services/plugin/routing.py +6 -9
- package/server/services/plugin/scaling.py +36 -18
- package/server/services/plugin/service_factories.py +95 -0
- package/server/services/plugin/shutdown_hooks.py +103 -0
- package/server/services/plugin/social_provider_registry.py +80 -0
- package/server/services/plugin/ws.py +2 -1
- package/server/services/pricing.py +26 -40
- package/server/services/pricing_handlers.py +90 -0
- package/server/services/process_service.py +33 -32
- package/server/services/proxy/models.py +15 -9
- package/server/services/proxy/service.py +26 -40
- package/server/services/rlm/adapters.py +43 -40
- package/server/services/rlm/constants.py +9 -9
- package/server/services/rlm/service.py +57 -45
- package/server/services/scheduler.py +8 -39
- package/server/services/settings/__init__.py +16 -0
- package/server/services/settings/handlers.py +275 -0
- package/server/services/skill_loader.py +53 -45
- package/server/services/skill_prompt.py +8 -6
- package/server/services/skills/__init__.py +23 -0
- package/server/services/skills/handlers.py +479 -0
- package/server/services/status_broadcaster.py +314 -291
- package/server/services/temporal/__init__.py +22 -1
- package/server/services/temporal/_handlers.py +65 -0
- package/server/services/temporal/_install.py +158 -0
- package/server/services/temporal/_refresh.py +57 -0
- package/server/services/temporal/_retry_policies.py +85 -0
- package/server/services/temporal/_runtime.py +181 -0
- package/server/services/temporal/_supervised_runtime.py +102 -0
- package/server/services/temporal/activities.py +168 -11
- package/server/services/temporal/agent_activities.py +683 -0
- package/server/services/temporal/agent_workflow.py +601 -0
- package/server/services/temporal/client.py +58 -13
- package/server/services/temporal/executor.py +2 -3
- package/server/services/temporal/plugin_activities.py +37 -2
- package/server/services/temporal/plugin_registry.py +82 -0
- package/server/services/temporal/polling_trigger_workflow.py +267 -0
- package/server/services/temporal/schedules.py +220 -0
- package/server/services/temporal/search_attributes.py +177 -0
- package/server/services/temporal/trigger_listener_workflow.py +378 -0
- package/server/services/temporal/worker.py +111 -18
- package/server/services/temporal/workflow.py +259 -40
- package/server/services/temporal/ws_client.py +22 -11
- package/server/services/text.py +14 -28
- package/server/services/tracked_http.py +29 -49
- package/server/services/user_auth.py +7 -21
- package/server/services/workflow.py +28 -20
- package/server/services/workflow_import.py +351 -0
- package/server/services/workflow_ops.py +4 -0
- package/server/services/workflow_storage/__init__.py +18 -0
- package/server/services/workflow_storage/handlers.py +132 -0
- package/server/services/workflow_validator.py +209 -0
- package/server/services/ws_handler_registry.py +80 -9
- package/server/skills/assistant/agent-builder-skill/SKILL.md +6 -6
- package/server/tests/conftest.py +54 -3
- package/server/tests/credentials/test_auth_service.py +9 -21
- package/server/tests/credentials/test_credential_broadcasts.py +116 -22
- package/server/tests/credentials/test_credentials_database.py +12 -38
- package/server/tests/credentials/test_encryption.py +3 -9
- package/server/tests/credentials/test_google_oauth.py +1 -3
- package/server/tests/credentials/test_oauth_utils.py +31 -38
- package/server/tests/credentials/test_twitter_oauth.py +1 -3
- package/server/tests/credentials/test_websocket_handlers.py +37 -72
- package/server/tests/fixtures/tool_names_snapshot.json +78 -0
- package/server/tests/llm/test_factory.py +12 -4
- package/server/tests/llm/test_providers.py +25 -32
- package/server/tests/llm/test_wiring.py +27 -22
- package/server/tests/nodes/_compat.py +4 -5
- package/server/tests/nodes/_harness.py +31 -24
- package/server/tests/nodes/_mocks.py +2 -6
- package/server/tests/nodes/test_agent_builder.py +43 -35
- package/server/tests/nodes/test_ai_agents.py +29 -24
- package/server/tests/nodes/test_ai_chat_models.py +3 -9
- package/server/tests/nodes/test_ai_tools.py +29 -24
- package/server/tests/nodes/test_android.py +34 -64
- package/server/tests/nodes/test_chat_utility.py +2 -2
- package/server/tests/nodes/test_code_fs_process.py +26 -84
- package/server/tests/nodes/test_document.py +23 -47
- package/server/tests/nodes/test_email.py +88 -51
- package/server/tests/nodes/test_google_workspace.py +26 -20
- package/server/tests/nodes/test_http_proxy.py +43 -89
- package/server/tests/nodes/test_search.py +3 -9
- package/server/tests/nodes/test_specialized_agents.py +58 -162
- package/server/tests/nodes/test_stripe_plugin.py +25 -5
- package/server/tests/nodes/test_telegram_social.py +33 -37
- package/server/tests/nodes/test_twitter.py +59 -150
- package/server/tests/nodes/test_web_automation.py +21 -51
- package/server/tests/nodes/test_whatsapp.py +13 -19
- package/server/tests/nodes/test_workflow_triggers.py +16 -45
- package/server/tests/services/cli_agent/test_claude_session_events.py +201 -0
- package/server/tests/services/cli_agent/test_jsonl_watcher.py +190 -0
- package/server/tests/services/cli_agent/test_mcp_server.py +67 -29
- package/server/tests/services/cli_agent/test_providers.py +236 -47
- package/server/tests/services/cli_agent/test_service.py +9 -7
- package/server/tests/services/memory/test_jsonl.py +30 -25
- package/server/tests/services/test_events.py +26 -7
- package/server/tests/services/test_identifiers.py +122 -0
- package/server/tests/services/test_process_lifecycle.py +129 -0
- package/server/tests/services/test_supervisor.py +0 -1
- package/server/tests/temporal/__init__.py +0 -0
- package/server/tests/temporal/test_agent_workflow.py +215 -0
- package/server/tests/temporal/test_dispatch.py +231 -0
- package/server/tests/test_admin_handlers.py +394 -0
- package/server/tests/test_auto_skill.py +4 -2
- package/server/tests/test_canary_registry.py +310 -0
- package/server/tests/test_chat_trigger_canary_producer.py +101 -0
- package/server/tests/test_cloudevents_node_parameters.py +129 -0
- package/server/tests/test_credential_icon.py +115 -0
- package/server/tests/test_cron_canary.py +511 -0
- package/server/tests/test_deployment_canary_listener.py +692 -0
- package/server/tests/test_event_framework_phase_a.py +537 -0
- package/server/tests/test_no_raw_prints.py +131 -0
- package/server/tests/test_node_spec.py +196 -103
- package/server/tests/test_parameter_resolver.py +20 -20
- package/server/tests/test_plugin_contract.py +76 -49
- package/server/tests/test_plugin_helpers.py +0 -1
- package/server/tests/test_plugin_self_containment.py +40 -47
- package/server/tests/test_polling_trigger_workflow.py +572 -0
- package/server/tests/test_retry_policies.py +146 -0
- package/server/tests/test_service_factories.py +168 -0
- package/server/tests/test_shutdown_hooks.py +199 -0
- package/server/tests/test_social_provider_registry.py +177 -0
- package/server/tests/test_status_broadcasts.py +214 -63
- package/server/tests/test_task_trigger_canary_producer.py +131 -0
- package/server/tests/test_telegram_trigger_canary_producer.py +113 -0
- package/server/tests/test_tool_registry.py +110 -0
- package/server/tests/test_trigger_listener_workflow.py +365 -0
- package/server/tests/test_whatsapp_trigger_canary_producer.py +164 -0
- package/server/tests/test_workflow_ops.py +1 -3
- package/server/tests/test_workflow_validator.py +791 -0
- package/server/uv.lock +3539 -0
- package/client/dist/assets/index-DQ0nwhec.js +0 -257
- package/client/src/assets/icons/apify/index.ts +0 -19
- package/client/src/assets/icons/browser/index.ts +0 -17
- package/client/src/assets/icons/email/index.ts +0 -22
- package/client/src/assets/icons/google/index.ts +0 -34
- package/client/src/assets/icons/llm/deepseek.svg +0 -1
- package/client/src/assets/icons/llm/index.ts +0 -18
- package/client/src/assets/icons/llm/kimi.svg +0 -1
- package/client/src/assets/icons/llm/mistral.svg +0 -1
- package/client/src/assets/icons/search/index.ts +0 -28
- package/client/src/assets/icons/telegram/index.ts +0 -19
- package/machina/buildenv.py +0 -44
- package/machina/cli.py +0 -55
- package/machina/commands/__init__.py +0 -1
- package/machina/commands/clean.py +0 -80
- package/machina/commands/daemon.py +0 -150
- package/machina/config.py +0 -93
- package/machina/platform_.py +0 -37
- package/machina/pyproject.toml +0 -33
- package/server/nodes/agent/deep_agent.py +0 -103
- package/server/services/agents/__init__.py +0 -9
- package/server/services/agents/adapters.py +0 -199
- package/server/services/agents/constants.py +0 -10
- package/server/services/agents/service.py +0 -297
- package/server/services/cli_agent/providers/anthropic_claude.py +0 -419
- /package/{machina → cli}/README.md +0 -0
- /package/{machina → cli}/__init__.py +0 -0
- /package/{client/src/assets/icons/apify → server/credentials/icons}/apify.svg +0 -0
- /package/{client/src/assets/icons/search/brave.svg → server/credentials/icons/brave_search.svg} +0 -0
- /package/{client/src/assets/icons/email/read.svg → server/credentials/icons/email_himalaya.svg} +0 -0
- /package/{client/src/assets/icons/search → server/credentials/icons}/perplexity.svg +0 -0
- /package/{client/src/assets/icons/search/google.svg → server/credentials/icons/serper.svg} +0 -0
- /package/{client/src/assets → server/credentials}/icons/stripe.svg +0 -0
- /package/{client/src/assets/icons/twitter/x.svg → server/credentials/icons/twitter.svg} +0 -0
- /package/{client/src/assets/icons/browser/chrome.svg → server/nodes/browser/browser/icon.svg} +0 -0
- /package/{client/src/assets/icons/chat/chat.svg → server/nodes/chat/chat_history/icon.svg} +0 -0
- /package/{client/src/assets/icons/code/javascript.svg → server/nodes/code/javascript_executor/icon.svg} +0 -0
- /package/{client/src/assets/icons/code/python.svg → server/nodes/code/python_executor/icon.svg} +0 -0
- /package/{client/src/assets/icons/code/typescript.svg → server/nodes/code/typescript_executor/icon.svg} +0 -0
- /package/{client/src/assets/icons/email/receive.svg → server/nodes/email/email_receive/icon.svg} +0 -0
- /package/{client/src/assets/icons/email/send.svg → server/nodes/email/email_send/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/calendar.svg → server/nodes/google/calendar/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/contacts.svg → server/nodes/google/contacts/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/drive.svg → server/nodes/google/drive/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/gmail.svg → server/nodes/google/gmail/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/sheets.svg → server/nodes/google/sheets/icon.svg} +0 -0
- /package/{client/src/assets/icons/google/tasks.svg → server/nodes/google/tasks/icon.svg} +0 -0
- /package/{client/src/assets/icons/search/duckduckgo.svg → server/nodes/search/duckduckgo_search/icon.svg} +0 -0
- /package/{client/src/assets/icons/social/social.svg → server/nodes/social/social_receive/icon.svg} +0 -0
- /package/{client/src/assets/icons/telegram/telegram.svg → server/nodes/telegram/icon.svg} +0 -0
- /package/server/nodes/utility/{team_monitor.py → team_monitor/__init__.py} +0 -0
- /package/{client/src/assets/icons/whatsapp/whatsapp-db.svg → server/nodes/whatsapp/icon_whatsappDb.svg} +0 -0
- /package/{client/src/assets/icons/whatsapp/whatsapp-receive.svg → server/nodes/whatsapp/icon_whatsappReceive.svg} +0 -0
- /package/{client/src/assets/icons/whatsapp/whatsapp-send.svg → server/nodes/whatsapp/icon_whatsappSend.svg} +0 -0
- /package/{client/src/assets/icons → server/nodes}/whatsapp/whatsapp.svg +0 -0
|
@@ -20,11 +20,12 @@ from __future__ import annotations
|
|
|
20
20
|
|
|
21
21
|
import time
|
|
22
22
|
from datetime import datetime, timezone
|
|
23
|
-
from typing import Any, Awaitable, Callable, ClassVar, Dict,
|
|
23
|
+
from typing import Any, Awaitable, Callable, ClassVar, Dict, Optional, Sequence, Type
|
|
24
24
|
|
|
25
|
+
from opentelemetry import trace
|
|
25
26
|
from pydantic import BaseModel, ValidationError
|
|
26
27
|
|
|
27
|
-
from core.logging import get_logger
|
|
28
|
+
from core.logging import get_logger, log_context
|
|
28
29
|
from services.plugin.connection import Connection
|
|
29
30
|
from services.plugin.context import NodeContext
|
|
30
31
|
from services.plugin.credential import Credential
|
|
@@ -39,6 +40,7 @@ from services.plugin.scaling import (
|
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
logger = get_logger(__name__)
|
|
43
|
+
tracer = trace.get_tracer(__name__)
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
class NodeUserError(Exception):
|
|
@@ -120,8 +122,6 @@ class BaseNode:
|
|
|
120
122
|
version: ClassVar[int] = 1
|
|
121
123
|
display_name: ClassVar[str] = ""
|
|
122
124
|
subtitle: ClassVar[str] = ""
|
|
123
|
-
icon: ClassVar[str] = ""
|
|
124
|
-
color: ClassVar[str] = ""
|
|
125
125
|
group: ClassVar[Sequence[str]] = ()
|
|
126
126
|
description: ClassVar[str] = ""
|
|
127
127
|
handles: ClassVar[Sequence[Dict[str, Any]]] = ()
|
|
@@ -144,6 +144,23 @@ class BaseNode:
|
|
|
144
144
|
component_kind: ClassVar[str] = "generic"
|
|
145
145
|
usable_as_tool: ClassVar[bool] = False
|
|
146
146
|
|
|
147
|
+
# Wave 12 D5: LLM-visible name + description for plugins surfaced as
|
|
148
|
+
# AI tools (ToolNode subclasses, ActionNodes marked usable_as_tool=True,
|
|
149
|
+
# SpecializedAgentBase subclasses).
|
|
150
|
+
#
|
|
151
|
+
# ``tool_name`` is genuinely distinct from ``type`` (camelCase → snake;
|
|
152
|
+
# e.g. ``calculatorTool`` → ``calculator``, ``pythonExecutor`` →
|
|
153
|
+
# ``python_code``); plugins declare it when they want an LLM-facing
|
|
154
|
+
# name that differs from the registry key.
|
|
155
|
+
#
|
|
156
|
+
# ``tool_description`` defaults to falling back to ``cls.description``
|
|
157
|
+
# at resolve time — plugins ONLY override when the LLM-facing variant
|
|
158
|
+
# needs to differ materially from the human-facing description
|
|
159
|
+
# (writeTodos' instruction-heavy prompt, pythonExecutor's available-
|
|
160
|
+
# libraries hint, specialized agents' ONE-SHOT pattern, etc.).
|
|
161
|
+
tool_name: ClassVar[str] = ""
|
|
162
|
+
tool_description: ClassVar[str] = ""
|
|
163
|
+
|
|
147
164
|
# Set by __init_subclass__: {op_name: OperationSpec}
|
|
148
165
|
_operations: ClassVar[Dict[str, OperationSpec]] = {}
|
|
149
166
|
# Flag so concrete subclasses auto-register; abstract kinds don't.
|
|
@@ -170,16 +187,40 @@ class BaseNode:
|
|
|
170
187
|
# the canvas.
|
|
171
188
|
# Subclasses opt out by explicitly setting either flag to False
|
|
172
189
|
# on the class.
|
|
173
|
-
is_tool_oriented =
|
|
174
|
-
cls.usable_as_tool or cls.component_kind == "tool"
|
|
175
|
-
)
|
|
190
|
+
is_tool_oriented = cls.usable_as_tool or cls.component_kind == "tool"
|
|
176
191
|
if is_tool_oriented:
|
|
177
192
|
if "hide_input_handle" not in cls.__dict__:
|
|
178
193
|
cls.hide_input_handle = True
|
|
179
194
|
if "hide_output_handle" not in cls.__dict__:
|
|
180
195
|
cls.hide_output_handle = True
|
|
196
|
+
# Wave 12 D5: auto-derive ``tool_name`` / ``tool_description`` for
|
|
197
|
+
# agents (component_kind=="agent") that don't declare their own.
|
|
198
|
+
# Pattern is parametric — every agent surfaces as
|
|
199
|
+
# ``delegate_to_<type>`` to the parent LLM. Subclasses with a
|
|
200
|
+
# distinct delegation contract (autonomous_agent's Code Mode hint,
|
|
201
|
+
# orchestrator_agent / ai_employee's "Coordinates multiple agents",
|
|
202
|
+
# rlm_agent's REPL note, claude_code_agent's coding note) override
|
|
203
|
+
# ``tool_description`` directly on the class.
|
|
204
|
+
if cls.component_kind == "agent":
|
|
205
|
+
if "tool_name" not in cls.__dict__:
|
|
206
|
+
cls.tool_name = f"delegate_to_{cls.type}"
|
|
207
|
+
if "tool_description" not in cls.__dict__:
|
|
208
|
+
agent_label = cls.display_name or cls.type
|
|
209
|
+
cls.tool_description = (
|
|
210
|
+
f"ONE-SHOT delegation to {agent_label}. Call ONCE per "
|
|
211
|
+
f"task, returns task_id immediately. Agent works in "
|
|
212
|
+
f"background - do NOT re-call."
|
|
213
|
+
)
|
|
181
214
|
# Eager registry write — same four registries as @register_node.
|
|
215
|
+
# ORDER MATTERS: register_node_class MUST precede register_node so
|
|
216
|
+
# that cls._metadata_dict() (evaluated as the metadata argument)
|
|
217
|
+
# can resolve the plugin folder via get_node_class(cls.type) inside
|
|
218
|
+
# get_plugin_icon_path. Without this order the icon falls through
|
|
219
|
+
# to visuals.json — defeating the per-plugin icon.svg endpoint
|
|
220
|
+
# (RFC §6.5 / Phase 6).
|
|
182
221
|
from services.node_registry import register_node, register_node_class
|
|
222
|
+
|
|
223
|
+
register_node_class(cls)
|
|
183
224
|
register_node(
|
|
184
225
|
type=cls.type,
|
|
185
226
|
metadata=cls._metadata_dict(),
|
|
@@ -187,7 +228,6 @@ class BaseNode:
|
|
|
187
228
|
output_model=cls.Output if cls.Output is not _EmptyOutput else None,
|
|
188
229
|
handler=cls._make_legacy_handler(),
|
|
189
230
|
)
|
|
190
|
-
register_node_class(cls)
|
|
191
231
|
|
|
192
232
|
# ---- metadata projection ---------------------------------------------
|
|
193
233
|
|
|
@@ -196,15 +236,29 @@ class BaseNode:
|
|
|
196
236
|
"""Project class attributes onto the :data:`NodeMetadata` TypedDict
|
|
197
237
|
expected by the existing node_spec emitter.
|
|
198
238
|
|
|
199
|
-
|
|
200
|
-
``
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
239
|
+
Icon resolution (per RFC §6.5):
|
|
240
|
+
1. Per-plugin ``icon.svg`` co-located with the plugin folder —
|
|
241
|
+
emitted as a URL routed through ``GET /api/schemas/nodes/<type>/icon``.
|
|
242
|
+
2. Fallback to ``visuals.json`` (emoji / ``lobehub:<brand>``).
|
|
243
|
+
|
|
244
|
+
Color resolution (per RFC §6.6 / F2):
|
|
245
|
+
1. Per-plugin ``meta.json`` ``color`` field, co-located with the
|
|
246
|
+
plugin folder. Mirrors icon co-location.
|
|
247
|
+
2. Fallback to ``visuals.json`` for legacy entries that have
|
|
248
|
+
not been migrated yet.
|
|
204
249
|
"""
|
|
205
|
-
from nodes._visuals import
|
|
206
|
-
|
|
207
|
-
|
|
250
|
+
from nodes._visuals import (
|
|
251
|
+
get_icon,
|
|
252
|
+
get_color,
|
|
253
|
+
get_plugin_icon_path,
|
|
254
|
+
get_plugin_meta,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
if get_plugin_icon_path(cls.type) is not None:
|
|
258
|
+
icon = f"/api/schemas/nodes/{cls.type}/icon"
|
|
259
|
+
else:
|
|
260
|
+
icon = get_icon(cls.type)
|
|
261
|
+
color = get_plugin_meta(cls.type, "color") or get_color(cls.type)
|
|
208
262
|
meta: Dict[str, Any] = {
|
|
209
263
|
"displayName": cls.display_name or cls.type,
|
|
210
264
|
"icon": icon,
|
|
@@ -242,6 +296,7 @@ class BaseNode:
|
|
|
242
296
|
(redundant — class is already the dispatch target) and route
|
|
243
297
|
through :meth:`execute`.
|
|
244
298
|
"""
|
|
299
|
+
|
|
245
300
|
async def _legacy(
|
|
246
301
|
node_id: str,
|
|
247
302
|
node_type: str,
|
|
@@ -256,7 +311,8 @@ class BaseNode:
|
|
|
256
311
|
connection_factory=_make_connection_factory(cls, context),
|
|
257
312
|
)
|
|
258
313
|
return await instance.execute(node_id, parameters, ctx)
|
|
259
|
-
|
|
314
|
+
|
|
315
|
+
_legacy.__node_class__ = cls # type: ignore[attr-defined]
|
|
260
316
|
_legacy.__qualname__ = f"{cls.__qualname__}._legacy_handler"
|
|
261
317
|
return _legacy
|
|
262
318
|
|
|
@@ -271,9 +327,58 @@ class BaseNode:
|
|
|
271
327
|
"""Universal entry point. Validate params → dispatch op →
|
|
272
328
|
wrap result. Subclasses (TriggerNode, ToolNode) override to
|
|
273
329
|
change the return shape or lifetime.
|
|
330
|
+
|
|
331
|
+
The body runs under two ambient contexts:
|
|
332
|
+
|
|
333
|
+
- :func:`core.logging.log_context` binds ``node_id`` /
|
|
334
|
+
``node_type`` / ``workflow_id`` to every log record emitted
|
|
335
|
+
while the operation runs, via ``structlog.contextvars``.
|
|
336
|
+
Survives ``asyncio.gather`` child tasks (stdlib
|
|
337
|
+
``contextvars`` is task-local).
|
|
338
|
+
- An OpenTelemetry span named ``node.{type}.execute`` so
|
|
339
|
+
per-plugin latency / failures show up in any tracer backend
|
|
340
|
+
without per-plugin instrumentation. Span attributes carry
|
|
341
|
+
the same identifiers as the log context.
|
|
274
342
|
"""
|
|
275
343
|
start_time = time.time()
|
|
344
|
+
workflow_id_attr: Optional[str] = None
|
|
345
|
+
if isinstance(context.raw, dict):
|
|
346
|
+
workflow_id_attr = context.raw.get("workflow_id")
|
|
276
347
|
|
|
348
|
+
log_fields: Dict[str, Any] = {
|
|
349
|
+
"node_id": node_id,
|
|
350
|
+
"node_type": self.type,
|
|
351
|
+
}
|
|
352
|
+
if workflow_id_attr is not None:
|
|
353
|
+
log_fields["workflow_id"] = workflow_id_attr
|
|
354
|
+
|
|
355
|
+
async with log_context(**log_fields):
|
|
356
|
+
with tracer.start_as_current_span(
|
|
357
|
+
f"node.{self.type}.execute",
|
|
358
|
+
attributes={
|
|
359
|
+
"node.id": node_id,
|
|
360
|
+
"node.type": self.type,
|
|
361
|
+
**({"workflow.id": workflow_id_attr} if workflow_id_attr else {}),
|
|
362
|
+
},
|
|
363
|
+
):
|
|
364
|
+
return await self._execute_body(
|
|
365
|
+
node_id=node_id,
|
|
366
|
+
parameters=parameters,
|
|
367
|
+
context=context,
|
|
368
|
+
start_time=start_time,
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
async def _execute_body(
|
|
372
|
+
self,
|
|
373
|
+
*,
|
|
374
|
+
node_id: str,
|
|
375
|
+
parameters: Dict[str, Any],
|
|
376
|
+
context: NodeContext,
|
|
377
|
+
start_time: float,
|
|
378
|
+
) -> Dict[str, Any]:
|
|
379
|
+
"""The actual execute pipeline — extracted so :meth:`execute`
|
|
380
|
+
stays a thin shell around the ambient log-context + span. Kept
|
|
381
|
+
method-private; callers should always go through :meth:`execute`."""
|
|
277
382
|
# Stash the raw (pre-validation) parameters dict in context.raw
|
|
278
383
|
# so plugins can recover values the Pydantic extra="ignore" policy
|
|
279
384
|
# would drop — e.g. ``api_key`` injected by node_executor's
|
|
@@ -303,8 +408,62 @@ class BaseNode:
|
|
|
303
408
|
try:
|
|
304
409
|
result = await self._run_operation(op_spec, params_obj, context)
|
|
305
410
|
except PermissionError as e:
|
|
411
|
+
# Credential.resolve() raises PermissionError annotated with
|
|
412
|
+
# .provider / .reason / .auth attributes (see
|
|
413
|
+
# services/plugin/credential.py). When .provider is present,
|
|
414
|
+
# emit a CloudEvents-typed broadcast via
|
|
415
|
+
# ``broadcast_credential_event`` — the existing wire used by
|
|
416
|
+
# every credential mutation. The envelope rides as a
|
|
417
|
+
# WorkflowEvent with type ``credential.{auth}.runtime_failed``
|
|
418
|
+
# so frontend consumers can glob-match ``credential.*.*``
|
|
419
|
+
# without inventing a new wire-frame key. Surface a
|
|
420
|
+
# ``credential`` block in the operation response so the user
|
|
421
|
+
# gets a structured error envelope rather than a raw string.
|
|
422
|
+
provider = getattr(e, "provider", None)
|
|
423
|
+
reason = getattr(e, "reason", "denied")
|
|
424
|
+
auth = getattr(e, "auth", "api_key")
|
|
425
|
+
# Normalize "oauth2" -> "oauth" so the event type aligns with
|
|
426
|
+
# the existing CloudEvents naming (``credential.oauth.connected``,
|
|
427
|
+
# ``credential.oauth.disconnected``, ``credential.oauth.validated``).
|
|
428
|
+
auth_kind = "oauth" if auth == "oauth2" else auth
|
|
429
|
+
workflow_id: Optional[str] = None
|
|
430
|
+
if isinstance(context.raw, dict):
|
|
431
|
+
workflow_id = context.raw.get("workflow_id")
|
|
432
|
+
if provider:
|
|
433
|
+
try:
|
|
434
|
+
from services.status_broadcaster import get_status_broadcaster
|
|
435
|
+
|
|
436
|
+
broadcaster = get_status_broadcaster()
|
|
437
|
+
await broadcaster.broadcast_credential_event(
|
|
438
|
+
event_type=f"credential.{auth_kind}.runtime_failed",
|
|
439
|
+
provider=provider,
|
|
440
|
+
workflow_id=workflow_id,
|
|
441
|
+
reason=reason,
|
|
442
|
+
node_id=node_id,
|
|
443
|
+
error=str(e),
|
|
444
|
+
)
|
|
445
|
+
except Exception:
|
|
446
|
+
# Broadcast failure must never mask the original error.
|
|
447
|
+
logger.debug(
|
|
448
|
+
"[%s] failed to broadcast credential runtime failure for %s",
|
|
449
|
+
self.type,
|
|
450
|
+
provider,
|
|
451
|
+
exc_info=True,
|
|
452
|
+
)
|
|
453
|
+
extra: Optional[Dict[str, Any]] = None
|
|
454
|
+
if provider:
|
|
455
|
+
extra = {
|
|
456
|
+
"credential": {
|
|
457
|
+
"provider": provider,
|
|
458
|
+
"reason": reason,
|
|
459
|
+
"remediation": "add_key" if reason == "missing" else "reconnect",
|
|
460
|
+
}
|
|
461
|
+
}
|
|
306
462
|
return self._wrap_error(
|
|
307
|
-
start_time=start_time,
|
|
463
|
+
start_time=start_time,
|
|
464
|
+
error=str(e),
|
|
465
|
+
error_type="PermissionDeniedError",
|
|
466
|
+
extra=extra,
|
|
308
467
|
)
|
|
309
468
|
except NodeUserError as e:
|
|
310
469
|
# Expected, user-correctable: log a single WARN line so it
|
|
@@ -312,9 +471,7 @@ class BaseNode:
|
|
|
312
471
|
# LLM gets the message in the structured response and can
|
|
313
472
|
# retry with corrected input.
|
|
314
473
|
logger.warning("[%s] %s op %s: %s", self.type, op_name, type(e).__name__, e)
|
|
315
|
-
return self._wrap_error(
|
|
316
|
-
start_time=start_time, error=str(e), error_type="NodeUserError"
|
|
317
|
-
)
|
|
474
|
+
return self._wrap_error(start_time=start_time, error=str(e), error_type="NodeUserError")
|
|
318
475
|
except Exception as e:
|
|
319
476
|
logger.exception("[%s] operation %s failed", self.type, op_name)
|
|
320
477
|
return self._wrap_error(start_time=start_time, error=str(e), error_type=type(e).__name__)
|
|
@@ -383,14 +540,15 @@ class BaseNode:
|
|
|
383
540
|
# is expected to be empty.
|
|
384
541
|
if not self.credentials:
|
|
385
542
|
raise RuntimeError(
|
|
386
|
-
f"Node {self.type} op {spec.name} has routing but no "
|
|
387
|
-
"credentials declared — routing needs a Connection."
|
|
543
|
+
f"Node {self.type} op {spec.name} has routing but no " "credentials declared — routing needs a Connection."
|
|
388
544
|
)
|
|
389
545
|
cred = self.credentials[0]
|
|
390
546
|
conn = ctx.connection(cred.id)
|
|
391
547
|
try:
|
|
392
548
|
return await execute_routing(
|
|
393
|
-
spec.routing,
|
|
549
|
+
spec.routing,
|
|
550
|
+
params=params_obj.model_dump(),
|
|
551
|
+
connection=conn,
|
|
394
552
|
)
|
|
395
553
|
finally:
|
|
396
554
|
await conn.aclose()
|
|
@@ -413,24 +571,40 @@ class BaseNode:
|
|
|
413
571
|
}
|
|
414
572
|
|
|
415
573
|
def _wrap_error(
|
|
416
|
-
self,
|
|
574
|
+
self,
|
|
575
|
+
*,
|
|
576
|
+
start_time: float,
|
|
577
|
+
error: str,
|
|
578
|
+
error_type: str = "Error",
|
|
579
|
+
extra: Optional[Dict[str, Any]] = None,
|
|
417
580
|
) -> Dict[str, Any]:
|
|
418
|
-
|
|
581
|
+
envelope: Dict[str, Any] = {
|
|
419
582
|
"success": False,
|
|
420
583
|
"error": error,
|
|
421
584
|
"error_type": error_type,
|
|
422
585
|
"execution_time": round(time.time() - start_time, 3),
|
|
423
586
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
424
587
|
}
|
|
588
|
+
if extra:
|
|
589
|
+
envelope.update(extra)
|
|
590
|
+
return envelope
|
|
425
591
|
|
|
426
592
|
# ---- Temporal ---------------------------------------------------------
|
|
427
593
|
|
|
428
594
|
@classmethod
|
|
429
595
|
def as_activity(cls):
|
|
430
596
|
"""Wrap this node as a ``@activity.defn`` callable for Temporal
|
|
431
|
-
worker registration (
|
|
597
|
+
worker registration (F4.A). Stable activity name:
|
|
432
598
|
``node.{type}.v{version}``.
|
|
433
599
|
|
|
600
|
+
Accepts the same ``context`` dict shape as the legacy
|
|
601
|
+
``execute_node_activity`` so the orchestrator can swap by name
|
|
602
|
+
without reshaping the payload. Delegates to
|
|
603
|
+
``workflow_service.execute_node(...)`` — same execution pipeline
|
|
604
|
+
the WebSocket path uses — so status broadcasts, parameter
|
|
605
|
+
fetching, NodeContext build, and error handling all match. The
|
|
606
|
+
Temporal worker shares the FastAPI process, so direct DI works.
|
|
607
|
+
|
|
434
608
|
Returns the decorated async function; the worker collects these
|
|
435
609
|
into ``activities=[...]``.
|
|
436
610
|
"""
|
|
@@ -439,17 +613,122 @@ class BaseNode:
|
|
|
439
613
|
activity_name = f"node.{cls.type}.v{cls.version}"
|
|
440
614
|
|
|
441
615
|
@activity.defn(name=activity_name)
|
|
442
|
-
async def _node_activity(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
616
|
+
async def _node_activity(context: Dict[str, Any]) -> Dict[str, Any]:
|
|
617
|
+
from datetime import datetime
|
|
618
|
+
from core.container import container
|
|
619
|
+
from services.status_broadcaster import get_status_broadcaster
|
|
620
|
+
|
|
621
|
+
node_id = context["node_id"]
|
|
622
|
+
workflow_id = context.get("workflow_id")
|
|
623
|
+
broadcaster = get_status_broadcaster()
|
|
624
|
+
|
|
625
|
+
# Pre-executed trigger nodes — return cached output without dispatching.
|
|
626
|
+
if context.get("pre_executed"):
|
|
627
|
+
activity.logger.debug(f"Node {node_id} pre-executed; passthrough")
|
|
628
|
+
result = {
|
|
629
|
+
"success": True,
|
|
630
|
+
"node_id": node_id,
|
|
631
|
+
"node_type": cls.type,
|
|
632
|
+
"result": context.get("trigger_output", {}),
|
|
633
|
+
"pre_executed": True,
|
|
634
|
+
"timestamp": datetime.now().isoformat(),
|
|
635
|
+
}
|
|
636
|
+
await broadcaster.update_node_status(
|
|
637
|
+
node_id,
|
|
638
|
+
"success",
|
|
639
|
+
result,
|
|
640
|
+
workflow_id=workflow_id,
|
|
641
|
+
)
|
|
642
|
+
return result
|
|
643
|
+
|
|
644
|
+
# Disabled nodes — skip.
|
|
645
|
+
node_data = context.get("node_data", {})
|
|
646
|
+
if node_data.get("disabled"):
|
|
647
|
+
activity.logger.debug(f"Node {node_id} disabled; skipping")
|
|
648
|
+
result = {
|
|
649
|
+
"success": True,
|
|
650
|
+
"node_id": node_id,
|
|
651
|
+
"node_type": cls.type,
|
|
652
|
+
"skipped": True,
|
|
653
|
+
"reason": "disabled",
|
|
654
|
+
"timestamp": datetime.now().isoformat(),
|
|
655
|
+
}
|
|
656
|
+
await broadcaster.update_node_status(
|
|
657
|
+
node_id,
|
|
658
|
+
"skipped",
|
|
659
|
+
{"disabled": True},
|
|
660
|
+
workflow_id=workflow_id,
|
|
661
|
+
)
|
|
662
|
+
return result
|
|
663
|
+
|
|
664
|
+
# Broadcast executing — UI cyan-glow.
|
|
665
|
+
await broadcaster.update_node_status(
|
|
666
|
+
node_id,
|
|
667
|
+
"executing",
|
|
668
|
+
{"node_type": cls.type},
|
|
669
|
+
workflow_id=workflow_id,
|
|
451
670
|
)
|
|
452
|
-
|
|
671
|
+
|
|
672
|
+
try:
|
|
673
|
+
# Heartbeat the long-running side of the pipeline.
|
|
674
|
+
activity.heartbeat(f"Executing {cls.type}: {node_id}")
|
|
675
|
+
|
|
676
|
+
# Delegate to the same pipeline the WS handler uses. Parameters
|
|
677
|
+
# are read from DB inside execute_node (handler-specific). The
|
|
678
|
+
# legacy execute_node_activity does this via a WS roundtrip;
|
|
679
|
+
# per-type activities skip the loopback because the worker
|
|
680
|
+
# shares the FastAPI process.
|
|
681
|
+
workflow_service = container.workflow_service()
|
|
682
|
+
result = await workflow_service.execute_node(
|
|
683
|
+
node_id=node_id,
|
|
684
|
+
node_type=cls.type,
|
|
685
|
+
parameters=node_data,
|
|
686
|
+
nodes=context.get("nodes", []),
|
|
687
|
+
edges=context.get("edges", []),
|
|
688
|
+
session_id=context.get("session_id", "default"),
|
|
689
|
+
workflow_id=workflow_id,
|
|
690
|
+
outputs=context.get("inputs", {}),
|
|
691
|
+
)
|
|
692
|
+
|
|
693
|
+
result["node_id"] = node_id
|
|
694
|
+
result["node_type"] = cls.type
|
|
695
|
+
result["timestamp"] = datetime.now().isoformat()
|
|
696
|
+
|
|
697
|
+
if result.get("success"):
|
|
698
|
+
activity.logger.info(f"Node {node_id} succeeded")
|
|
699
|
+
await broadcaster.update_node_status(
|
|
700
|
+
node_id,
|
|
701
|
+
"success",
|
|
702
|
+
result.get("result", {}),
|
|
703
|
+
workflow_id=workflow_id,
|
|
704
|
+
)
|
|
705
|
+
await broadcaster.update_node_output(
|
|
706
|
+
node_id,
|
|
707
|
+
result.get("result", {}),
|
|
708
|
+
workflow_id=workflow_id,
|
|
709
|
+
)
|
|
710
|
+
else:
|
|
711
|
+
activity.logger.warning(f"Node {node_id} failed: {result.get('error')}")
|
|
712
|
+
await broadcaster.update_node_status(
|
|
713
|
+
node_id,
|
|
714
|
+
"error",
|
|
715
|
+
{"error": result.get("error")},
|
|
716
|
+
workflow_id=workflow_id,
|
|
717
|
+
)
|
|
718
|
+
|
|
719
|
+
activity.heartbeat(f"Node {node_id} completed")
|
|
720
|
+
return result
|
|
721
|
+
|
|
722
|
+
except Exception as e:
|
|
723
|
+
error_msg = f"{type(e).__name__}: {e}"
|
|
724
|
+
activity.logger.error(f"Node {node_id} crashed: {error_msg}")
|
|
725
|
+
await broadcaster.update_node_status(
|
|
726
|
+
node_id,
|
|
727
|
+
"error",
|
|
728
|
+
{"error": error_msg},
|
|
729
|
+
workflow_id=workflow_id,
|
|
730
|
+
)
|
|
731
|
+
raise
|
|
453
732
|
|
|
454
733
|
return _node_activity
|
|
455
734
|
|
|
@@ -457,6 +736,7 @@ class BaseNode:
|
|
|
457
736
|
# ---------------------------------------------------------------------------
|
|
458
737
|
# Connection factory — avoids circular import with NodeContext.
|
|
459
738
|
|
|
739
|
+
|
|
460
740
|
def _make_connection_factory(
|
|
461
741
|
node_cls: Type[BaseNode],
|
|
462
742
|
context: Dict[str, Any],
|
|
@@ -475,7 +755,10 @@ def _make_connection_factory(
|
|
|
475
755
|
f"but tried to use it. Add it to the `credentials` class attribute."
|
|
476
756
|
)
|
|
477
757
|
return Connection(
|
|
478
|
-
cred_cls,
|
|
758
|
+
cred_cls,
|
|
759
|
+
user_id=user_id,
|
|
760
|
+
session_id=session_id,
|
|
761
|
+
node_id=node_id,
|
|
479
762
|
)
|
|
480
763
|
|
|
481
764
|
return factory
|
|
@@ -106,16 +106,21 @@ class Connection:
|
|
|
106
106
|
if _retry_on_auth and response.status_code in (401, 403):
|
|
107
107
|
logger.debug(
|
|
108
108
|
"[Connection] auth retry for %s (%s) status=%s",
|
|
109
|
-
self.credential_id,
|
|
109
|
+
self.credential_id,
|
|
110
|
+
method,
|
|
111
|
+
response.status_code,
|
|
110
112
|
)
|
|
111
113
|
await self.refresh()
|
|
112
114
|
secrets = await self.credentials()
|
|
113
|
-
req_retry = self._cred_cls.inject(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
req_retry = self._cred_cls.inject(
|
|
116
|
+
secrets,
|
|
117
|
+
{
|
|
118
|
+
"headers": dict(headers or {}),
|
|
119
|
+
"params": dict(params or {}),
|
|
120
|
+
**({"json": json} if json is not None else {}),
|
|
121
|
+
**({"data": data} if data is not None else {}),
|
|
122
|
+
},
|
|
123
|
+
)
|
|
119
124
|
response = await client.request(method, url, **req_retry)
|
|
120
125
|
|
|
121
126
|
return response
|