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
|
@@ -12,10 +12,11 @@ This enables massive horizontal scaling and multi-tenant distribution.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
from datetime import timedelta
|
|
15
|
-
from typing import Any, Dict, List, Set
|
|
15
|
+
from typing import Any, Dict, List, Optional, Set
|
|
16
16
|
|
|
17
17
|
from temporalio import workflow
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
from ._retry_policies import DEFAULT_ACTIVITY_RETRY
|
|
19
20
|
|
|
20
21
|
# Config handles - nodes connecting via these are config nodes (not executed)
|
|
21
22
|
# AI Agent handles: input-memory, input-tools, input-model, input-task, input-teammates
|
|
@@ -38,6 +39,38 @@ SKILL_NODE_TYPES = {
|
|
|
38
39
|
"masterSkill",
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
# F4.B: agent types that migrate to AgentWorkflow (Temporal child workflow).
|
|
43
|
+
# When ``temporal_agent_workflow_enabled`` is True the orchestrator schedules
|
|
44
|
+
# AgentWorkflow for these node types instead of an activity. Tool calls
|
|
45
|
+
# inside the agent loop become per-type activities (F4.A path).
|
|
46
|
+
#
|
|
47
|
+
# Excluded: ``rlm_agent``, ``claude_code_agent``. Their internal session
|
|
48
|
+
# state (RLM REPL / Claude CLI --resume with stable cwd) requires
|
|
49
|
+
# single-process continuity and breaks across activity boundaries. They
|
|
50
|
+
# continue via F4.A per-type activities.
|
|
51
|
+
AGENT_WORKFLOW_TYPES = frozenset(
|
|
52
|
+
[
|
|
53
|
+
"aiAgent",
|
|
54
|
+
"chatAgent",
|
|
55
|
+
# Specialized agents (12)
|
|
56
|
+
"android_agent",
|
|
57
|
+
"coding_agent",
|
|
58
|
+
"web_agent",
|
|
59
|
+
"task_agent",
|
|
60
|
+
"social_agent",
|
|
61
|
+
"travel_agent",
|
|
62
|
+
"tool_agent",
|
|
63
|
+
"productivity_agent",
|
|
64
|
+
"payments_agent",
|
|
65
|
+
"consumer_agent",
|
|
66
|
+
"autonomous_agent",
|
|
67
|
+
# Team leads (2)
|
|
68
|
+
"orchestrator_agent",
|
|
69
|
+
"ai_employee",
|
|
70
|
+
]
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
41
74
|
@workflow.defn(sandboxed=False)
|
|
42
75
|
class MachinaWorkflow:
|
|
43
76
|
"""Distributed workflow orchestrator.
|
|
@@ -50,8 +83,95 @@ class MachinaWorkflow:
|
|
|
50
83
|
- Per-node retry policies
|
|
51
84
|
- Config node filtering (tools, memory, services)
|
|
52
85
|
- Multi-tenant support via tenant_id in context
|
|
86
|
+
- Wave 12 A7: event-framework signal handler — receives Temporal
|
|
87
|
+
Signals from ``services/events/dispatch.py:emit`` and parks
|
|
88
|
+
pending events in ``_matched_events`` for trigger nodes to
|
|
89
|
+
consume via ``workflow.wait_condition(_has_event_matching, ...)``.
|
|
90
|
+
Per-run dedup via ``_seen_event_ids`` (reconstructed
|
|
91
|
+
deterministically from Event History on replay).
|
|
53
92
|
"""
|
|
54
93
|
|
|
94
|
+
def __init__(self) -> None:
|
|
95
|
+
# Wave 12 A7: per-run event-framework state. Populated by the
|
|
96
|
+
# ``on_event`` signal handler; consumed by Phase C1's
|
|
97
|
+
# ``wait_condition`` predicate in the trigger-waiter rewrite.
|
|
98
|
+
# Today these stay empty unless the event-framework feature
|
|
99
|
+
# flag is on AND a producer signals this workflow.
|
|
100
|
+
self._seen_event_ids: Set[str] = set()
|
|
101
|
+
self._matched_events: List[Dict[str, Any]] = []
|
|
102
|
+
|
|
103
|
+
@workflow.signal
|
|
104
|
+
async def on_event(self, event_payload: Dict[str, Any]) -> None:
|
|
105
|
+
"""Wave 12 A7: receive an event from ``services.events.dispatch.emit``.
|
|
106
|
+
|
|
107
|
+
Drops duplicates by ``event.id`` (per-run dedup — the set is
|
|
108
|
+
reconstructed deterministically from Event History on replay).
|
|
109
|
+
Matching events are queued for the workflow body to consume via
|
|
110
|
+
:meth:`_has_event_matching` in a ``wait_condition`` (wired in
|
|
111
|
+
Phase C1).
|
|
112
|
+
"""
|
|
113
|
+
event_id = event_payload.get("id")
|
|
114
|
+
if not event_id:
|
|
115
|
+
workflow.logger.warning("on_event: skipping malformed envelope without 'id'")
|
|
116
|
+
return
|
|
117
|
+
if event_id in self._seen_event_ids:
|
|
118
|
+
workflow.logger.debug(f"on_event: dedup hit for event.id={event_id}")
|
|
119
|
+
return
|
|
120
|
+
self._seen_event_ids.add(event_id)
|
|
121
|
+
self._matched_events.append(event_payload)
|
|
122
|
+
workflow.logger.info(
|
|
123
|
+
f"on_event: queued event.id={event_id} " f"type={event_payload.get('type', '?')} " f"(matched={len(self._matched_events)})"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def _has_event_matching(self, predicate=None) -> bool:
|
|
127
|
+
"""Wave 12 A7: ``wait_condition`` predicate for trigger nodes.
|
|
128
|
+
|
|
129
|
+
Returns True when at least one queued event matches the optional
|
|
130
|
+
``predicate(event_payload) -> bool``. Defaults to "any event
|
|
131
|
+
queued" — most trigger nodes filter further by inspecting the
|
|
132
|
+
envelope after pop.
|
|
133
|
+
|
|
134
|
+
Used by Phase C1's trigger-waiter rewrite to replace the
|
|
135
|
+
in-process ``asyncio.Future`` waiter:
|
|
136
|
+
|
|
137
|
+
await workflow.wait_condition(
|
|
138
|
+
lambda: self._has_event_matching(my_filter),
|
|
139
|
+
timeout=...,
|
|
140
|
+
)
|
|
141
|
+
event = self._pop_matching_event(my_filter)
|
|
142
|
+
"""
|
|
143
|
+
if not self._matched_events:
|
|
144
|
+
return False
|
|
145
|
+
if predicate is None:
|
|
146
|
+
return True
|
|
147
|
+
return any(predicate(e) for e in self._matched_events)
|
|
148
|
+
|
|
149
|
+
def _pop_matching_event(self, predicate=None) -> Optional[Dict[str, Any]]:
|
|
150
|
+
"""Wave 12 A7: dequeue the first event that satisfies ``predicate``.
|
|
151
|
+
|
|
152
|
+
Pairs with :meth:`_has_event_matching` — Phase C1 trigger
|
|
153
|
+
waiters call ``wait_condition`` on the predicate, then pop the
|
|
154
|
+
actual envelope here. FIFO order: the predicate is evaluated
|
|
155
|
+
against the head of ``_matched_events`` first, so events
|
|
156
|
+
arrive in the order Temporal delivered the signals (and on
|
|
157
|
+
replay, the order Event History records them — deterministic).
|
|
158
|
+
|
|
159
|
+
Returns ``None`` if no queued event matches; callers should
|
|
160
|
+
only reach this method after ``wait_condition`` resolves, in
|
|
161
|
+
which case at least one match exists. The ``None`` return path
|
|
162
|
+
exists for defensive symmetry — never silently raises mid-
|
|
163
|
+
replay.
|
|
164
|
+
|
|
165
|
+
Determinism note: list mutation inside a workflow is safe per
|
|
166
|
+
Temporal's Python SDK contract (the workflow's local state is
|
|
167
|
+
rebuilt from Event History on replay; the same signals deliver
|
|
168
|
+
the same envelopes, so the same pops happen in the same order).
|
|
169
|
+
"""
|
|
170
|
+
for idx, event in enumerate(self._matched_events):
|
|
171
|
+
if predicate is None or predicate(event):
|
|
172
|
+
return self._matched_events.pop(idx)
|
|
173
|
+
return None
|
|
174
|
+
|
|
55
175
|
@workflow.run
|
|
56
176
|
async def run(self, workflow_data: Dict[str, Any]) -> Dict[str, Any]:
|
|
57
177
|
"""Execute workflow by orchestrating node activities.
|
|
@@ -73,9 +193,7 @@ class MachinaWorkflow:
|
|
|
73
193
|
workflow_id = workflow_data.get("workflow_id")
|
|
74
194
|
tenant_id = workflow_data.get("tenant_id")
|
|
75
195
|
|
|
76
|
-
workflow.logger.info(
|
|
77
|
-
f"Starting workflow orchestration: {len(nodes)} nodes, {len(edges)} edges"
|
|
78
|
-
)
|
|
196
|
+
workflow.logger.info(f"Starting workflow orchestration: {len(nodes)} nodes, {len(edges)} edges")
|
|
79
197
|
|
|
80
198
|
if not nodes:
|
|
81
199
|
return {
|
|
@@ -89,8 +207,7 @@ class MachinaWorkflow:
|
|
|
89
207
|
exec_nodes, exec_edges = self._filter_executable_graph(nodes, edges)
|
|
90
208
|
|
|
91
209
|
workflow.logger.info(
|
|
92
|
-
f"After filtering: {len(exec_nodes)} executable nodes "
|
|
93
|
-
f"(filtered {len(nodes) - len(exec_nodes)} config nodes)"
|
|
210
|
+
f"After filtering: {len(exec_nodes)} executable nodes " f"(filtered {len(nodes) - len(exec_nodes)} config nodes)"
|
|
94
211
|
)
|
|
95
212
|
|
|
96
213
|
# 2. Build dependency maps
|
|
@@ -108,9 +225,10 @@ class MachinaWorkflow:
|
|
|
108
225
|
for node in exec_nodes:
|
|
109
226
|
if node.get("_pre_executed"):
|
|
110
227
|
node_id = node["id"]
|
|
228
|
+
trigger_output = node.get("_trigger_output", {})
|
|
111
229
|
outputs[node_id] = {
|
|
112
230
|
"success": True,
|
|
113
|
-
"result":
|
|
231
|
+
"result": trigger_output,
|
|
114
232
|
"pre_executed": True,
|
|
115
233
|
}
|
|
116
234
|
completed.add(node_id)
|
|
@@ -118,14 +236,35 @@ class MachinaWorkflow:
|
|
|
118
236
|
pre_executed_count += 1
|
|
119
237
|
workflow.logger.info(f"Pre-executed trigger: {node_id}")
|
|
120
238
|
|
|
239
|
+
# Persist the trigger output to the workflow output
|
|
240
|
+
# store so ParameterResolver can resolve
|
|
241
|
+
# ``{{triggerNodeName.field}}`` in downstream nodes.
|
|
242
|
+
# Pre-executed nodes bypass NodeExecutor.execute (the
|
|
243
|
+
# normal write site), so without this activity the
|
|
244
|
+
# legacy path's ``_store_output(trigger_node_id, ...)``
|
|
245
|
+
# behaviour is missing on the canary path and templates
|
|
246
|
+
# against the trigger silently resolve to empty.
|
|
247
|
+
# Skip the persist for non-firing siblings — their
|
|
248
|
+
# ``_trigger_output`` is ``{not_triggered: True}``, no
|
|
249
|
+
# downstream template should resolve against them.
|
|
250
|
+
if not trigger_output.get("not_triggered"):
|
|
251
|
+
await workflow.execute_activity(
|
|
252
|
+
"store_node_output_activity",
|
|
253
|
+
{
|
|
254
|
+
"node_id": node_id,
|
|
255
|
+
"session_id": session_id,
|
|
256
|
+
"result": trigger_output,
|
|
257
|
+
},
|
|
258
|
+
start_to_close_timeout=timedelta(seconds=10),
|
|
259
|
+
)
|
|
260
|
+
|
|
121
261
|
workflow.logger.info(f"Pre-executed: {pre_executed_count}, To execute: {len(node_map) - pre_executed_count}")
|
|
122
262
|
|
|
123
|
-
# 5. Retry policy for node activities
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
)
|
|
263
|
+
# 5. Retry policy for node activities. Wave 12 D1: imported
|
|
264
|
+
# shared constant declares ``non_retryable_error_types`` so
|
|
265
|
+
# NodeUserError fails fast instead of burning 3 retries on
|
|
266
|
+
# user-correctable failures.
|
|
267
|
+
retry_policy = DEFAULT_ACTIVITY_RETRY
|
|
129
268
|
|
|
130
269
|
# 6. Continuous scheduling loop
|
|
131
270
|
loop_count = 0
|
|
@@ -144,9 +283,7 @@ class MachinaWorkflow:
|
|
|
144
283
|
# Trigger nodes are event listeners - scheduling them as activities
|
|
145
284
|
# would block indefinitely waiting for external events.
|
|
146
285
|
if node_type in TRIGGER_NODE_TYPES and not node.get("_pre_executed"):
|
|
147
|
-
workflow.logger.warning(
|
|
148
|
-
f"Skipping non-pre-executed trigger: {node_id} ({node_type})"
|
|
149
|
-
)
|
|
286
|
+
workflow.logger.warning(f"Skipping non-pre-executed trigger: {node_id} ({node_type})")
|
|
150
287
|
outputs[node_id] = {
|
|
151
288
|
"success": True,
|
|
152
289
|
"result": {"not_triggered": True},
|
|
@@ -172,18 +309,47 @@ class MachinaWorkflow:
|
|
|
172
309
|
"trigger_output": node.get("_trigger_output"),
|
|
173
310
|
}
|
|
174
311
|
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
312
|
+
# F4.B: agent-as-child-workflow takes precedence over the
|
|
313
|
+
# activity path for the 15 migrating agent types when its
|
|
314
|
+
# flag is on. Tool calls inside the agent loop become
|
|
315
|
+
# per-type activities (F4.A path) automatically.
|
|
316
|
+
dispatch = self._resolve_dispatch(node_type)
|
|
317
|
+
if dispatch["kind"] == "child_workflow":
|
|
318
|
+
# ``workflow.start_child_workflow`` is ``async def`` —
|
|
319
|
+
# awaiting it returns the ``ChildWorkflowHandle`` once
|
|
320
|
+
# the child has been started by the server (fast; not
|
|
321
|
+
# blocking on child completion). The handle is a
|
|
322
|
+
# Task-like with ``.done()`` so it slots into the same
|
|
323
|
+
# FIRST_COMPLETED loop as activity handles.
|
|
324
|
+
handle = await workflow.start_child_workflow(
|
|
325
|
+
dispatch["name"],
|
|
326
|
+
args=[context],
|
|
327
|
+
# Child workflow execution timeout: agent loops can run
|
|
328
|
+
# 10+ minutes with multiple LLM turns. Set generously.
|
|
329
|
+
execution_timeout=timedelta(hours=1),
|
|
330
|
+
run_timeout=timedelta(hours=1),
|
|
331
|
+
)
|
|
332
|
+
running[node_id] = handle
|
|
333
|
+
workflow.logger.info(f"Scheduled child workflow for node: {node_id} " f"(workflow={dispatch['name']})")
|
|
334
|
+
else:
|
|
335
|
+
# F4.A activity path: per-type when the plugin class is
|
|
336
|
+
# registered AND the per-type flag is on; legacy
|
|
337
|
+
# execute_node_activity otherwise.
|
|
338
|
+
start_kwargs: Dict[str, Any] = dict(
|
|
339
|
+
args=[context],
|
|
340
|
+
start_to_close_timeout=timedelta(minutes=10),
|
|
341
|
+
heartbeat_timeout=timedelta(minutes=2),
|
|
342
|
+
retry_policy=retry_policy,
|
|
343
|
+
)
|
|
344
|
+
if dispatch.get("queue") is not None:
|
|
345
|
+
start_kwargs["task_queue"] = dispatch["queue"]
|
|
346
|
+
|
|
347
|
+
handle = workflow.start_activity(dispatch["name"], **start_kwargs)
|
|
348
|
+
running[node_id] = handle
|
|
349
|
+
workflow.logger.info(
|
|
350
|
+
f"Scheduled activity for node: {node_id} "
|
|
351
|
+
f"(activity={dispatch['name']}, queue={dispatch.get('queue') or 'default'})"
|
|
352
|
+
)
|
|
187
353
|
|
|
188
354
|
# Exit if nothing running and nothing ready
|
|
189
355
|
if not running:
|
|
@@ -213,10 +379,7 @@ class MachinaWorkflow:
|
|
|
213
379
|
# Build final result
|
|
214
380
|
success = len(errors) == 0 and len(completed) == len(node_map)
|
|
215
381
|
|
|
216
|
-
workflow.logger.info(
|
|
217
|
-
f"Workflow complete: success={success}, "
|
|
218
|
-
f"executed={len(execution_trace)}/{len(node_map)}"
|
|
219
|
-
)
|
|
382
|
+
workflow.logger.info(f"Workflow complete: success={success}, " f"executed={len(execution_trace)}/{len(node_map)}")
|
|
220
383
|
|
|
221
384
|
return {
|
|
222
385
|
"success": success,
|
|
@@ -238,6 +401,65 @@ class MachinaWorkflow:
|
|
|
238
401
|
inputs[dep_id] = outputs[dep_id].get("result", {})
|
|
239
402
|
return inputs
|
|
240
403
|
|
|
404
|
+
def _resolve_dispatch(self, node_type: str) -> Dict[str, Any]:
|
|
405
|
+
"""Resolve dispatch kind for a node type.
|
|
406
|
+
|
|
407
|
+
Returns one of:
|
|
408
|
+
- ``{"kind": "child_workflow", "name": "AgentWorkflow"}`` — when
|
|
409
|
+
F4.B is enabled AND node_type is in ``AGENT_WORKFLOW_TYPES``.
|
|
410
|
+
- ``{"kind": "activity", "name": <activity_name>, "queue": <queue|None>}``
|
|
411
|
+
— F4.A per-type activity OR legacy fallback, depending on
|
|
412
|
+
``temporal_per_type_dispatch``.
|
|
413
|
+
|
|
414
|
+
Deterministic: all lookups go through frozen dicts (Settings,
|
|
415
|
+
_NODE_CLASS_REGISTRY, AGENT_WORKFLOW_TYPES). Safe inside
|
|
416
|
+
``MachinaWorkflow.run`` per the workflow-definition contract.
|
|
417
|
+
"""
|
|
418
|
+
from core.config import Settings
|
|
419
|
+
|
|
420
|
+
settings = Settings()
|
|
421
|
+
if getattr(settings, "temporal_agent_workflow_enabled", False) and node_type in AGENT_WORKFLOW_TYPES:
|
|
422
|
+
return {"kind": "child_workflow", "name": "AgentWorkflow"}
|
|
423
|
+
|
|
424
|
+
name, queue = self._resolve_activity(node_type)
|
|
425
|
+
return {"kind": "activity", "name": name, "queue": queue}
|
|
426
|
+
|
|
427
|
+
def _resolve_activity(self, node_type: str) -> tuple[str, str | None]:
|
|
428
|
+
"""Resolve (activity_name, task_queue) for a node type.
|
|
429
|
+
|
|
430
|
+
F4.A: when ``settings.temporal_per_type_dispatch`` is on AND the
|
|
431
|
+
plugin class is registered, returns
|
|
432
|
+
``("node.{type}.v{version}", None)`` so the activity is scheduled
|
|
433
|
+
by per-type name but stays on the workflow's default task queue.
|
|
434
|
+
The default queue is what ``TemporalWorkerManager`` polls today;
|
|
435
|
+
per-queue routing (``cls.task_queue``) becomes meaningful only
|
|
436
|
+
once ``TemporalWorkerPool`` is wired with one worker per queue
|
|
437
|
+
— until then, returning ``cls.task_queue`` would schedule the
|
|
438
|
+
activity to a queue no worker polls and the workflow would hang.
|
|
439
|
+
|
|
440
|
+
Falls back to ``("execute_node_activity", None)`` when:
|
|
441
|
+
- the flag is off (preserves pre-F4.A behavior exactly), OR
|
|
442
|
+
- the node type isn't registered as a BaseNode subclass
|
|
443
|
+
(covers legacy types still on the metadata-only path).
|
|
444
|
+
|
|
445
|
+
Determinism: lookups go through frozen module-level dicts
|
|
446
|
+
(``_NODE_CLASS_REGISTRY``, ``Settings``) — no I/O. Safe inside
|
|
447
|
+
``MachinaWorkflow.run`` per the workflow-definition contract.
|
|
448
|
+
Imports are inside the method to keep the workflow module's
|
|
449
|
+
top-level import set minimal and to avoid import-cycle drift.
|
|
450
|
+
"""
|
|
451
|
+
from core.config import Settings
|
|
452
|
+
from services.node_registry import get_node_class
|
|
453
|
+
|
|
454
|
+
if not Settings().temporal_per_type_dispatch:
|
|
455
|
+
return "execute_node_activity", None
|
|
456
|
+
|
|
457
|
+
cls = get_node_class(node_type)
|
|
458
|
+
if cls is None:
|
|
459
|
+
return "execute_node_activity", None
|
|
460
|
+
|
|
461
|
+
return f"node.{cls.type}.v{cls.version}", None
|
|
462
|
+
|
|
241
463
|
async def _wait_any_complete(self, running: Dict[str, Any]) -> tuple:
|
|
242
464
|
"""Wait for any activity to complete, return (node_id, result).
|
|
243
465
|
|
|
@@ -260,9 +482,7 @@ class MachinaWorkflow:
|
|
|
260
482
|
[h for _, h in items]
|
|
261
483
|
|
|
262
484
|
# Use asyncio.wait pattern via workflow.wait
|
|
263
|
-
await workflow.wait_condition(
|
|
264
|
-
lambda: any(h.done() for _, h in items)
|
|
265
|
-
)
|
|
485
|
+
await workflow.wait_condition(lambda: any(h.done() for _, h in items))
|
|
266
486
|
|
|
267
487
|
# Find the completed one
|
|
268
488
|
for node_id, handle in items:
|
|
@@ -313,10 +533,9 @@ class MachinaWorkflow:
|
|
|
313
533
|
# Filter nodes and edges
|
|
314
534
|
exec_nodes = [n for n in nodes if n["id"] not in config_ids]
|
|
315
535
|
exec_edges = [
|
|
316
|
-
e
|
|
317
|
-
|
|
318
|
-
and e.get("target") not in config_ids
|
|
319
|
-
and e.get("targetHandle", "") not in CONFIG_HANDLES
|
|
536
|
+
e
|
|
537
|
+
for e in edges
|
|
538
|
+
if e.get("source") not in config_ids and e.get("target") not in config_ids and e.get("targetHandle", "") not in CONFIG_HANDLES
|
|
320
539
|
]
|
|
321
540
|
|
|
322
541
|
return exec_nodes, exec_edges
|
|
@@ -22,11 +22,15 @@ from core.config import Settings
|
|
|
22
22
|
|
|
23
23
|
logger = get_logger(__name__)
|
|
24
24
|
|
|
25
|
-
# Load settings
|
|
26
|
-
_settings = Settings()
|
|
27
|
-
WS_URL = f"ws://{_settings.host}:{_settings.port}/ws/internal"
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
def _default_ws_url() -> str:
|
|
27
|
+
"""Resolve the activity-side WS URL from current ``Settings``.
|
|
28
|
+
|
|
29
|
+
Deferred to first call so module import doesn't require the full env
|
|
30
|
+
surface — same rationale as ``activities._resolve_urls``.
|
|
31
|
+
"""
|
|
32
|
+
settings = Settings()
|
|
33
|
+
return f"ws://{settings.host}:{settings.port}/ws/internal"
|
|
30
34
|
|
|
31
35
|
|
|
32
36
|
class WSConnectionPool:
|
|
@@ -41,8 +45,8 @@ class WSConnectionPool:
|
|
|
41
45
|
avoiding the ConcurrencyError that occurs when sharing a single connection.
|
|
42
46
|
"""
|
|
43
47
|
|
|
44
|
-
def __init__(self, url: str =
|
|
45
|
-
self.url = url
|
|
48
|
+
def __init__(self, url: Optional[str] = None, pool_size: int = 100):
|
|
49
|
+
self.url = url if url is not None else _default_ws_url()
|
|
46
50
|
self.pool_size = pool_size
|
|
47
51
|
self._session: Optional[aiohttp.ClientSession] = None
|
|
48
52
|
self._lock = asyncio.Lock()
|
|
@@ -65,7 +69,10 @@ class WSConnectionPool:
|
|
|
65
69
|
connector=connector,
|
|
66
70
|
timeout=timeout,
|
|
67
71
|
)
|
|
68
|
-
|
|
72
|
+
logger.info(
|
|
73
|
+
"Created shared session",
|
|
74
|
+
pool_size=self.pool_size,
|
|
75
|
+
)
|
|
69
76
|
return self._session
|
|
70
77
|
|
|
71
78
|
@asynccontextmanager
|
|
@@ -115,7 +122,7 @@ class WSConnectionPool:
|
|
|
115
122
|
try:
|
|
116
123
|
async with self.connection() as ws:
|
|
117
124
|
await ws.send_json(message)
|
|
118
|
-
|
|
125
|
+
logger.debug("Sent execute_node", node_id=node_id)
|
|
119
126
|
|
|
120
127
|
# Wait for response with matching request_id
|
|
121
128
|
async with asyncio.timeout(timeout):
|
|
@@ -123,7 +130,11 @@ class WSConnectionPool:
|
|
|
123
130
|
if msg.type == aiohttp.WSMsgType.TEXT:
|
|
124
131
|
response = json.loads(msg.data)
|
|
125
132
|
if response.get("request_id") == request_id:
|
|
126
|
-
|
|
133
|
+
logger.debug(
|
|
134
|
+
"Received response",
|
|
135
|
+
node_id=node_id,
|
|
136
|
+
success=response.get("success"),
|
|
137
|
+
)
|
|
127
138
|
return response
|
|
128
139
|
elif msg.type == aiohttp.WSMsgType.ERROR:
|
|
129
140
|
raise Exception(f"WebSocket error: {ws.exception()}")
|
|
@@ -141,7 +152,7 @@ class WSConnectionPool:
|
|
|
141
152
|
"""Close the connection pool."""
|
|
142
153
|
if self._session and not self._session.closed:
|
|
143
154
|
await self._session.close()
|
|
144
|
-
|
|
155
|
+
logger.info("Session closed")
|
|
145
156
|
|
|
146
157
|
|
|
147
158
|
# Global connection pool instance
|
|
@@ -206,7 +217,7 @@ async def close_ws_client() -> None:
|
|
|
206
217
|
class TemporalWSClient:
|
|
207
218
|
"""Backwards compatibility wrapper around WSConnectionPool."""
|
|
208
219
|
|
|
209
|
-
def __init__(self, url: str =
|
|
220
|
+
def __init__(self, url: Optional[str] = None):
|
|
210
221
|
self._pool = WSConnectionPool(url=url)
|
|
211
222
|
|
|
212
223
|
@property
|
package/server/services/text.py
CHANGED
|
@@ -20,24 +20,15 @@ class TextService:
|
|
|
20
20
|
start_time = time.time()
|
|
21
21
|
|
|
22
22
|
try:
|
|
23
|
-
text = parameters.get(
|
|
24
|
-
include_timestamp = parameters.get(
|
|
23
|
+
text = parameters.get("text", "Hello World")
|
|
24
|
+
include_timestamp = parameters.get("include_timestamp", True)
|
|
25
25
|
|
|
26
|
-
result_data = {
|
|
27
|
-
"text": text,
|
|
28
|
-
"length": len(text),
|
|
29
|
-
"nodeId": node_id
|
|
30
|
-
}
|
|
26
|
+
result_data = {"text": text, "length": len(text), "nodeId": node_id}
|
|
31
27
|
|
|
32
28
|
if include_timestamp:
|
|
33
29
|
result_data["timestamp"] = datetime.now().isoformat()
|
|
34
30
|
|
|
35
|
-
result = {
|
|
36
|
-
"type": "text",
|
|
37
|
-
"data": result_data,
|
|
38
|
-
"nodeId": node_id,
|
|
39
|
-
"timestamp": datetime.now().isoformat()
|
|
40
|
-
}
|
|
31
|
+
result = {"type": "text", "data": result_data, "nodeId": node_id, "timestamp": datetime.now().isoformat()}
|
|
41
32
|
|
|
42
33
|
log_execution_time(logger, "text_generator", start_time, time.time())
|
|
43
34
|
|
|
@@ -47,7 +38,7 @@ class TextService:
|
|
|
47
38
|
"node_type": "textGenerator",
|
|
48
39
|
"result": result,
|
|
49
40
|
"execution_time": time.time() - start_time,
|
|
50
|
-
"timestamp": datetime.now().isoformat()
|
|
41
|
+
"timestamp": datetime.now().isoformat(),
|
|
51
42
|
}
|
|
52
43
|
|
|
53
44
|
except Exception as e:
|
|
@@ -58,7 +49,7 @@ class TextService:
|
|
|
58
49
|
"node_type": "textGenerator",
|
|
59
50
|
"error": str(e),
|
|
60
51
|
"execution_time": time.time() - start_time,
|
|
61
|
-
"timestamp": datetime.now().isoformat()
|
|
52
|
+
"timestamp": datetime.now().isoformat(),
|
|
62
53
|
}
|
|
63
54
|
|
|
64
55
|
async def execute_file_handler(self, node_id: str, parameters: Dict[str, Any]) -> Dict[str, Any]:
|
|
@@ -66,9 +57,9 @@ class TextService:
|
|
|
66
57
|
start_time = time.time()
|
|
67
58
|
|
|
68
59
|
try:
|
|
69
|
-
file_type = parameters.get(
|
|
70
|
-
file_content = parameters.get(
|
|
71
|
-
file_name = parameters.get(
|
|
60
|
+
file_type = parameters.get("file_type", "generic")
|
|
61
|
+
file_content = parameters.get("content", "")
|
|
62
|
+
file_name = parameters.get("file_name", "untitled.txt")
|
|
72
63
|
|
|
73
64
|
# Basic file processing
|
|
74
65
|
result_data = {
|
|
@@ -78,16 +69,11 @@ class TextService:
|
|
|
78
69
|
"size": len(file_content),
|
|
79
70
|
"processed": True,
|
|
80
71
|
"processingType": file_type,
|
|
81
|
-
"nodeId": node_id
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
result = {
|
|
85
|
-
"type": "file",
|
|
86
|
-
"data": result_data,
|
|
87
72
|
"nodeId": node_id,
|
|
88
|
-
"timestamp": datetime.now().isoformat()
|
|
89
73
|
}
|
|
90
74
|
|
|
75
|
+
result = {"type": "file", "data": result_data, "nodeId": node_id, "timestamp": datetime.now().isoformat()}
|
|
76
|
+
|
|
91
77
|
log_execution_time(logger, "file_handler", start_time, time.time())
|
|
92
78
|
|
|
93
79
|
return {
|
|
@@ -96,7 +82,7 @@ class TextService:
|
|
|
96
82
|
"node_type": "fileHandler",
|
|
97
83
|
"result": result,
|
|
98
84
|
"execution_time": time.time() - start_time,
|
|
99
|
-
"timestamp": datetime.now().isoformat()
|
|
85
|
+
"timestamp": datetime.now().isoformat(),
|
|
100
86
|
}
|
|
101
87
|
|
|
102
88
|
except Exception as e:
|
|
@@ -107,5 +93,5 @@ class TextService:
|
|
|
107
93
|
"node_type": "fileHandler",
|
|
108
94
|
"error": str(e),
|
|
109
95
|
"execution_time": time.time() - start_time,
|
|
110
|
-
"timestamp": datetime.now().isoformat()
|
|
111
|
-
}
|
|
96
|
+
"timestamp": datetime.now().isoformat(),
|
|
97
|
+
}
|