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
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"""Telegram Send — Wave 11.C migration.
|
|
2
2
|
|
|
3
3
|
Workflow-only ActionNode (no AI-tool exposure). The Telegram bot
|
|
4
|
-
token lives in ``auth_service`` under ``
|
|
5
|
-
|
|
6
|
-
thin-migration; 11.E
|
|
4
|
+
token lives in ``auth_service`` under the ``telegram`` credential id
|
|
5
|
+
(was ``telegram_bot_token`` pre-rename). Plugin delegates to the
|
|
6
|
+
legacy ``handle_telegram_send`` handler during thin-migration; 11.E
|
|
7
|
+
converts to a declarative ``TelegramCredential``.
|
|
7
8
|
"""
|
|
8
9
|
|
|
9
10
|
from __future__ import annotations
|
|
10
11
|
|
|
11
|
-
from typing import Any,
|
|
12
|
+
from typing import Any, Literal, Optional
|
|
12
13
|
|
|
13
14
|
from pydantic import BaseModel, ConfigDict, Field
|
|
14
15
|
|
|
@@ -116,10 +117,7 @@ class TelegramSendParams(BaseModel):
|
|
|
116
117
|
# ===== OPTIONS =====
|
|
117
118
|
parse_mode: Literal["Auto", "", "HTML", "Markdown", "MarkdownV2"] = Field(
|
|
118
119
|
default="Auto",
|
|
119
|
-
description=(
|
|
120
|
-
"Auto converts LLM markdown to Telegram HTML. "
|
|
121
|
-
"Empty string = no parse mode (raw text)."
|
|
122
|
-
),
|
|
120
|
+
description=("Auto converts LLM markdown to Telegram HTML. " "Empty string = no parse mode (raw text)."),
|
|
123
121
|
json_schema_extra={
|
|
124
122
|
"displayOptions": {"show": {"message_type": ["text", "photo", "document"]}},
|
|
125
123
|
},
|
|
@@ -152,10 +150,8 @@ class TelegramSendNode(ActionNode):
|
|
|
152
150
|
description = "Send text, photo, document, location, or contact via Telegram bot"
|
|
153
151
|
component_kind = "square"
|
|
154
152
|
handles = (
|
|
155
|
-
{"name": "input-main", "kind": "input", "position": "left",
|
|
156
|
-
|
|
157
|
-
{"name": "output-main", "kind": "output", "position": "right",
|
|
158
|
-
"label": "Output", "role": "main"},
|
|
153
|
+
{"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
|
|
154
|
+
{"name": "output-main", "kind": "output", "position": "right", "label": "Output", "role": "main"},
|
|
159
155
|
)
|
|
160
156
|
annotations = {"destructive": False, "readonly": False, "open_world": True}
|
|
161
157
|
credentials = (TelegramCredential,)
|
|
@@ -183,6 +179,7 @@ class TelegramSendNode(ActionNode):
|
|
|
183
179
|
if not chat_id:
|
|
184
180
|
try:
|
|
185
181
|
from services.plugin.deps import get_auth_service
|
|
182
|
+
|
|
186
183
|
saved = await get_auth_service().get_api_key("telegram_owner_chat_id")
|
|
187
184
|
if saved:
|
|
188
185
|
owner_id = int(saved)
|
|
@@ -216,21 +213,27 @@ class TelegramSendNode(ActionNode):
|
|
|
216
213
|
if not params.text:
|
|
217
214
|
raise RuntimeError("text is required for text message")
|
|
218
215
|
result = await service.send_message(
|
|
219
|
-
text=params.text,
|
|
216
|
+
text=params.text,
|
|
217
|
+
parse_mode=parse_mode,
|
|
218
|
+
**common,
|
|
220
219
|
)
|
|
221
220
|
elif mt == "photo":
|
|
222
221
|
if not params.media_url:
|
|
223
222
|
raise RuntimeError("media_url is required for photo message")
|
|
224
223
|
result = await service.send_photo(
|
|
225
|
-
photo=params.media_url,
|
|
226
|
-
|
|
224
|
+
photo=params.media_url,
|
|
225
|
+
caption=params.caption or None,
|
|
226
|
+
parse_mode=parse_mode,
|
|
227
|
+
**common,
|
|
227
228
|
)
|
|
228
229
|
elif mt == "document":
|
|
229
230
|
if not params.media_url:
|
|
230
231
|
raise RuntimeError("media_url is required for document message")
|
|
231
232
|
result = await service.send_document(
|
|
232
|
-
document=params.media_url,
|
|
233
|
-
|
|
233
|
+
document=params.media_url,
|
|
234
|
+
caption=params.caption or None,
|
|
235
|
+
parse_mode=parse_mode,
|
|
236
|
+
**common,
|
|
234
237
|
)
|
|
235
238
|
elif mt == "location":
|
|
236
239
|
if params.latitude is None or params.longitude is None:
|
|
@@ -257,8 +260,7 @@ class TelegramSendNode(ActionNode):
|
|
|
257
260
|
raise RuntimeError(f"Unsupported message type: {mt}")
|
|
258
261
|
|
|
259
262
|
log.info(
|
|
260
|
-
f"[Telegram] Message sent: type={mt}, chat={chat_id}, "
|
|
261
|
-
f"msg_id={result.get('message_id')}",
|
|
263
|
+
f"[Telegram] Message sent: type={mt}, chat={chat_id}, " f"msg_id={result.get('message_id')}",
|
|
262
264
|
)
|
|
263
265
|
return {
|
|
264
266
|
"message_id": result.get("message_id"),
|
|
@@ -17,7 +17,13 @@ from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
|
|
|
17
17
|
|
|
18
18
|
class FileHandlerParams(BaseModel):
|
|
19
19
|
file_type: Literal[
|
|
20
|
-
"generic",
|
|
20
|
+
"generic",
|
|
21
|
+
"markdown",
|
|
22
|
+
"text",
|
|
23
|
+
"json",
|
|
24
|
+
"csv",
|
|
25
|
+
"html",
|
|
26
|
+
"xml",
|
|
21
27
|
] = Field(
|
|
22
28
|
default="generic",
|
|
23
29
|
description="Content type tag used for downstream processing hints.",
|
|
@@ -48,7 +48,8 @@ class TextGeneratorNode(ActionNode):
|
|
|
48
48
|
|
|
49
49
|
text_service = get_text_service()
|
|
50
50
|
response = await text_service.execute_text_generator(
|
|
51
|
-
ctx.node_id,
|
|
51
|
+
ctx.node_id,
|
|
52
|
+
params.model_dump(),
|
|
52
53
|
)
|
|
53
54
|
if response.get("success"):
|
|
54
55
|
return response.get("result") or response
|
|
@@ -19,10 +19,10 @@ The five operations are pure canvas mutations:
|
|
|
19
19
|
* ``create_workflow`` -- persist a fresh empty workflow + return its
|
|
20
20
|
workflow_id.
|
|
21
21
|
|
|
22
|
-
Each mutation pushes a ``workflow_ops_apply`` event via
|
|
23
|
-
``
|
|
24
|
-
|
|
25
|
-
mid-run does NOT add a callable tool to the current
|
|
22
|
+
Each mutation pushes a ``workflow_ops_apply`` event via the plugin's
|
|
23
|
+
``_events.broadcast_workflow_ops`` wrapper so the live canvas updates.
|
|
24
|
+
The agent loop binds tools at the start of each turn, so a mutation
|
|
25
|
+
made mid-run does NOT add a callable tool to the current turn; the
|
|
26
26
|
agent's NEXT invocation rediscovers it. Each summary string ends
|
|
27
27
|
with "Available on your next turn" so the LLM doesn't loop trying
|
|
28
28
|
to call something that isn't there yet.
|
|
@@ -58,7 +58,7 @@ _TOOL_OUTPUT_HANDLE = "output-main"
|
|
|
58
58
|
_MASTER_SKILL_TYPE = "masterSkill"
|
|
59
59
|
_MASTER_SKILL_LABEL = "Master Skill"
|
|
60
60
|
_AGENT_BUILDER_TYPE = "agentBuilder"
|
|
61
|
-
_TEAM_LEAD_TYPES = frozenset({"orchestrator_agent", "ai_employee"
|
|
61
|
+
_TEAM_LEAD_TYPES = frozenset({"orchestrator_agent", "ai_employee"})
|
|
62
62
|
_DENIED_TOOL_TYPES = frozenset({_AGENT_BUILDER_TYPE, _MASTER_SKILL_TYPE})
|
|
63
63
|
_KEY_PARAM_FIELDS = ("provider", "model", "operation", "url", "query")
|
|
64
64
|
_SKILLS_DIR = Path(__file__).resolve().parents[2] / "skills"
|
|
@@ -70,20 +70,25 @@ _SKILLS_DIR = Path(__file__).resolve().parents[2] / "skills"
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
async def _broadcast(workflow_id: Optional[str], caller_id: str, ops: List[Dict[str, Any]]) -> None:
|
|
73
|
-
"""Push a workflow_ops_apply event so the live canvas updates.
|
|
73
|
+
"""Push a workflow_ops_apply event so the live canvas updates.
|
|
74
|
+
|
|
75
|
+
Wave 12 B10: routes through plugin _events.py wrapper.
|
|
76
|
+
"""
|
|
74
77
|
if not ops:
|
|
75
78
|
return
|
|
76
79
|
try:
|
|
77
|
-
from
|
|
78
|
-
|
|
79
|
-
await
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
from ._events import broadcast_workflow_ops
|
|
81
|
+
|
|
82
|
+
await broadcast_workflow_ops(
|
|
83
|
+
workflow_id=workflow_id,
|
|
84
|
+
caller_node_id=caller_id,
|
|
85
|
+
operations=ops,
|
|
82
86
|
)
|
|
83
87
|
logger.info(
|
|
84
|
-
"[agentBuilder] broadcast workflow_ops_apply: workflow_id=%s "
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
"[agentBuilder] broadcast workflow_ops_apply: workflow_id=%s " "caller=%s ops=%s",
|
|
89
|
+
workflow_id,
|
|
90
|
+
caller_id,
|
|
91
|
+
[op.get("type") for op in ops],
|
|
87
92
|
)
|
|
88
93
|
except Exception as exc:
|
|
89
94
|
logger.warning(f"[agentBuilder] broadcast failed: {exc}", exc_info=True)
|
|
@@ -92,17 +97,14 @@ async def _broadcast(workflow_id: Optional[str], caller_id: str, ops: List[Dict[
|
|
|
92
97
|
def _allowed_tool_types() -> set[str]:
|
|
93
98
|
"""Tool nodes the LLM may spawn -- excludes the builder + masterSkill."""
|
|
94
99
|
return {
|
|
95
|
-
ntype
|
|
96
|
-
|
|
97
|
-
and ntype not in _DENIED_TOOL_TYPES
|
|
100
|
+
ntype
|
|
101
|
+
for ntype, cls in registered_node_classes().items()
|
|
102
|
+
if getattr(cls, "component_kind", "") == "tool" and ntype not in _DENIED_TOOL_TYPES
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
|
|
101
106
|
def _allowed_subagent_types() -> set[str]:
|
|
102
|
-
return {
|
|
103
|
-
ntype for ntype, cls in registered_node_classes().items()
|
|
104
|
-
if getattr(cls, "component_kind", "") == "agent"
|
|
105
|
-
}
|
|
107
|
+
return {ntype for ntype, cls in registered_node_classes().items() if getattr(cls, "component_kind", "") == "agent"}
|
|
106
108
|
|
|
107
109
|
|
|
108
110
|
def _is_team_lead(node_type: str) -> bool:
|
|
@@ -150,21 +152,20 @@ def _resolve_caller(ctx: NodeContext) -> str:
|
|
|
150
152
|
"""
|
|
151
153
|
self_id = ctx.node_id
|
|
152
154
|
for edge in ctx.edges or []:
|
|
153
|
-
if (
|
|
154
|
-
edge.get("source") == self_id
|
|
155
|
-
and edge.get("targetHandle") == _TOOL_HANDLE
|
|
156
|
-
):
|
|
155
|
+
if edge.get("source") == self_id and edge.get("targetHandle") == _TOOL_HANDLE:
|
|
157
156
|
target = edge.get("target")
|
|
158
157
|
if target:
|
|
159
158
|
logger.info(
|
|
160
|
-
"[agentBuilder] caller resolved via input-tools edge: "
|
|
161
|
-
|
|
159
|
+
"[agentBuilder] caller resolved via input-tools edge: " "self=%s -> agent=%s",
|
|
160
|
+
self_id,
|
|
161
|
+
target,
|
|
162
162
|
)
|
|
163
163
|
return target
|
|
164
164
|
logger.info(
|
|
165
|
-
"[agentBuilder] no input-tools edge found from %s; "
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
"[agentBuilder] no input-tools edge found from %s; " "falling back to self as caller (canvas: %d nodes, %d edges)",
|
|
166
|
+
self_id,
|
|
167
|
+
len(ctx.nodes or []),
|
|
168
|
+
len(ctx.edges or []),
|
|
168
169
|
)
|
|
169
170
|
return self_id
|
|
170
171
|
|
|
@@ -179,10 +180,12 @@ def _log_op_entry(op: str, ctx: NodeContext, **fields: Any) -> None:
|
|
|
179
180
|
edges = ctx.edges or []
|
|
180
181
|
extra = " ".join(f"{k}={v!r}" for k, v in fields.items() if v not in (None, ""))
|
|
181
182
|
logger.info(
|
|
182
|
-
"[agentBuilder.%s] workflow_id=%s self=%s nodes=%d edges=%d "
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
"[agentBuilder.%s] workflow_id=%s self=%s nodes=%d edges=%d " "raw_keys=%s%s",
|
|
184
|
+
op,
|
|
185
|
+
ctx.workflow_id,
|
|
186
|
+
ctx.node_id,
|
|
187
|
+
len(nodes),
|
|
188
|
+
len(edges),
|
|
186
189
|
sorted((ctx.raw or {}).keys()),
|
|
187
190
|
f" {extra}" if extra else "",
|
|
188
191
|
)
|
|
@@ -227,10 +230,7 @@ class AgentBuilderParams(BaseModel):
|
|
|
227
230
|
# add_skill
|
|
228
231
|
skill_folder: str = Field(
|
|
229
232
|
default="",
|
|
230
|
-
description=(
|
|
231
|
-
"For add_skill: skill folder name under server/skills/** "
|
|
232
|
-
"(e.g. 'http-request-skill', 'memory-skill')."
|
|
233
|
-
),
|
|
233
|
+
description=("For add_skill: skill folder name under server/skills/** " "(e.g. 'http-request-skill', 'memory-skill')."),
|
|
234
234
|
json_schema_extra={"displayOptions": {"show": {"operation": ["add_skill"]}}},
|
|
235
235
|
)
|
|
236
236
|
|
|
@@ -241,7 +241,7 @@ class AgentBuilderParams(BaseModel):
|
|
|
241
241
|
"For add_subagent: agent node type to spawn (e.g. "
|
|
242
242
|
"'coding_agent', 'web_agent'). Must be component_kind='agent' "
|
|
243
243
|
"and not a team-lead. Caller must itself be a team-lead "
|
|
244
|
-
"(orchestrator_agent / ai_employee
|
|
244
|
+
"(orchestrator_agent / ai_employee)."
|
|
245
245
|
),
|
|
246
246
|
json_schema_extra={"displayOptions": {"show": {"operation": ["add_subagent"]}}},
|
|
247
247
|
)
|
|
@@ -296,11 +296,11 @@ class AgentBuilderNode(ToolNode):
|
|
|
296
296
|
"agent calls operations through the standard tool path."
|
|
297
297
|
)
|
|
298
298
|
component_kind = "tool"
|
|
299
|
+
tool_name = "agent_builder"
|
|
300
|
+
tool_description = "Inspect and modify the workflow canvas at runtime. Operations: inspect_canvas (read current nodes/edges), spawn_tool (add a tool node + wire it), enable_skill (add a skill folder to a connected masterSkill), add_delegate_agent (add a specialized agent), create_workflow (spawn a brand-new workflow)."
|
|
299
301
|
handles = (
|
|
300
|
-
{"name": "input-main", "kind": "input", "position": "left",
|
|
301
|
-
|
|
302
|
-
{"name": "output-tool", "kind": "output", "position": "top",
|
|
303
|
-
"label": "Tool", "role": "tools"},
|
|
302
|
+
{"name": "input-main", "kind": "input", "position": "left", "label": "Input", "role": "main"},
|
|
303
|
+
{"name": "output-tool", "kind": "output", "position": "top", "label": "Tool", "role": "tools"},
|
|
304
304
|
)
|
|
305
305
|
ui_hints = {"isToolPanel": True, "hideRunButton": True}
|
|
306
306
|
annotations = {"destructive": False, "readonly": False, "open_world": True}
|
|
@@ -313,7 +313,9 @@ class AgentBuilderNode(ToolNode):
|
|
|
313
313
|
|
|
314
314
|
@Operation("inspect_canvas")
|
|
315
315
|
async def inspect_canvas(
|
|
316
|
-
self,
|
|
316
|
+
self,
|
|
317
|
+
ctx: NodeContext,
|
|
318
|
+
params: AgentBuilderParams,
|
|
317
319
|
) -> AgentBuilderOutput:
|
|
318
320
|
_log_op_entry("inspect_canvas", ctx)
|
|
319
321
|
nodes = list(ctx.nodes or [])
|
|
@@ -345,7 +347,8 @@ class AgentBuilderNode(ToolNode):
|
|
|
345
347
|
"source_type": type_by_id.get(e.get("source")),
|
|
346
348
|
"target_handle": e.get("targetHandle"),
|
|
347
349
|
}
|
|
348
|
-
for e in edges
|
|
350
|
+
for e in edges
|
|
351
|
+
if e.get("target") == caller_id
|
|
349
352
|
]
|
|
350
353
|
outgoing = [
|
|
351
354
|
{
|
|
@@ -353,7 +356,8 @@ class AgentBuilderNode(ToolNode):
|
|
|
353
356
|
"target_type": type_by_id.get(e.get("target")),
|
|
354
357
|
"source_handle": e.get("sourceHandle"),
|
|
355
358
|
}
|
|
356
|
-
for e in edges
|
|
359
|
+
for e in edges
|
|
360
|
+
if e.get("source") == caller_id
|
|
357
361
|
]
|
|
358
362
|
|
|
359
363
|
tools = [c for c in incoming if c["target_handle"] == _TOOL_HANDLE]
|
|
@@ -380,7 +384,9 @@ class AgentBuilderNode(ToolNode):
|
|
|
380
384
|
|
|
381
385
|
@Operation("add_tool")
|
|
382
386
|
async def add_tool(
|
|
383
|
-
self,
|
|
387
|
+
self,
|
|
388
|
+
ctx: NodeContext,
|
|
389
|
+
params: AgentBuilderParams,
|
|
384
390
|
) -> AgentBuilderOutput:
|
|
385
391
|
_log_op_entry("add_tool", ctx, node_type=params.node_type)
|
|
386
392
|
node_type = (params.node_type or "").strip()
|
|
@@ -395,10 +401,7 @@ class AgentBuilderNode(ToolNode):
|
|
|
395
401
|
sample = ", ".join(sorted(allowed)[:10])
|
|
396
402
|
return AgentBuilderOutput(
|
|
397
403
|
operation="add_tool",
|
|
398
|
-
summary=(
|
|
399
|
-
f"add_tool: '{node_type}' is not an allowed tool type. "
|
|
400
|
-
f"Examples of allowed types: {sample}..."
|
|
401
|
-
),
|
|
404
|
+
summary=(f"add_tool: '{node_type}' is not an allowed tool type. " f"Examples of allowed types: {sample}..."),
|
|
402
405
|
operations=[],
|
|
403
406
|
)
|
|
404
407
|
|
|
@@ -406,13 +409,17 @@ class AgentBuilderNode(ToolNode):
|
|
|
406
409
|
client_ref = f"new_{node_type}"
|
|
407
410
|
ops = [
|
|
408
411
|
workflow_ops.add_node(
|
|
409
|
-
client_ref,
|
|
412
|
+
client_ref,
|
|
413
|
+
node_type,
|
|
414
|
+
{},
|
|
410
415
|
label=node_type,
|
|
411
416
|
position=workflow_ops.anchored(caller_id, offset_x=200, offset_y=80),
|
|
412
417
|
),
|
|
413
418
|
workflow_ops.add_edge(
|
|
414
|
-
{"client_ref": client_ref},
|
|
415
|
-
|
|
419
|
+
{"client_ref": client_ref},
|
|
420
|
+
caller_id,
|
|
421
|
+
source_handle=_TOOL_OUTPUT_HANDLE,
|
|
422
|
+
target_handle=_TOOL_HANDLE,
|
|
416
423
|
),
|
|
417
424
|
]
|
|
418
425
|
await _broadcast(ctx.workflow_id, caller_id, ops)
|
|
@@ -426,7 +433,9 @@ class AgentBuilderNode(ToolNode):
|
|
|
426
433
|
|
|
427
434
|
@Operation("add_skill")
|
|
428
435
|
async def add_skill(
|
|
429
|
-
self,
|
|
436
|
+
self,
|
|
437
|
+
ctx: NodeContext,
|
|
438
|
+
params: AgentBuilderParams,
|
|
430
439
|
) -> AgentBuilderOutput:
|
|
431
440
|
_log_op_entry("add_skill", ctx, skill_folder=params.skill_folder)
|
|
432
441
|
skill = (params.skill_folder or "").strip()
|
|
@@ -448,27 +457,25 @@ class AgentBuilderNode(ToolNode):
|
|
|
448
457
|
caller_id = _resolve_caller(ctx)
|
|
449
458
|
|
|
450
459
|
skill_edge = next(
|
|
451
|
-
(e for e in edges if e.get("target") == caller_id
|
|
452
|
-
and e.get("targetHandle") == _SKILL_HANDLE),
|
|
460
|
+
(e for e in edges if e.get("target") == caller_id and e.get("targetHandle") == _SKILL_HANDLE),
|
|
453
461
|
None,
|
|
454
462
|
)
|
|
455
463
|
master_skill = None
|
|
456
464
|
if skill_edge:
|
|
457
465
|
master_skill = next(
|
|
458
|
-
(n for n in nodes if n.get("id") == skill_edge.get("source")
|
|
459
|
-
and n.get("type") == _MASTER_SKILL_TYPE),
|
|
466
|
+
(n for n in nodes if n.get("id") == skill_edge.get("source") and n.get("type") == _MASTER_SKILL_TYPE),
|
|
460
467
|
None,
|
|
461
468
|
)
|
|
462
469
|
|
|
463
470
|
if master_skill:
|
|
464
|
-
existing = (
|
|
465
|
-
((master_skill.get("data") or {}).get("parameters") or {})
|
|
466
|
-
.get("skills_config") or {}
|
|
467
|
-
)
|
|
471
|
+
existing = ((master_skill.get("data") or {}).get("parameters") or {}).get("skills_config") or {}
|
|
468
472
|
new_config = _toggle_skill(existing, skill, True)
|
|
469
|
-
ops = [
|
|
470
|
-
|
|
471
|
-
|
|
473
|
+
ops = [
|
|
474
|
+
workflow_ops.set_node_parameters(
|
|
475
|
+
master_skill["id"],
|
|
476
|
+
{"skills_config": new_config},
|
|
477
|
+
)
|
|
478
|
+
]
|
|
472
479
|
await _broadcast(ctx.workflow_id, caller_id, ops)
|
|
473
480
|
return AgentBuilderOutput(
|
|
474
481
|
operation="add_skill",
|
|
@@ -480,23 +487,23 @@ class AgentBuilderNode(ToolNode):
|
|
|
480
487
|
client_ref = "new_master_skill"
|
|
481
488
|
ops = [
|
|
482
489
|
workflow_ops.add_node(
|
|
483
|
-
client_ref,
|
|
490
|
+
client_ref,
|
|
491
|
+
_MASTER_SKILL_TYPE,
|
|
484
492
|
{"skills_config": new_config},
|
|
485
493
|
label=_MASTER_SKILL_LABEL,
|
|
486
494
|
position=workflow_ops.anchored(caller_id, offset_x=-60, offset_y=220),
|
|
487
495
|
),
|
|
488
496
|
workflow_ops.add_edge(
|
|
489
|
-
{"client_ref": client_ref},
|
|
490
|
-
|
|
497
|
+
{"client_ref": client_ref},
|
|
498
|
+
caller_id,
|
|
499
|
+
source_handle=_SKILL_OUTPUT_HANDLE,
|
|
500
|
+
target_handle=_SKILL_HANDLE,
|
|
491
501
|
),
|
|
492
502
|
]
|
|
493
503
|
await _broadcast(ctx.workflow_id, caller_id, ops)
|
|
494
504
|
return AgentBuilderOutput(
|
|
495
505
|
operation="add_skill",
|
|
496
|
-
summary=(
|
|
497
|
-
f"Created Master Skill node and enabled '{skill}'. "
|
|
498
|
-
"Available on your next turn."
|
|
499
|
-
),
|
|
506
|
+
summary=(f"Created Master Skill node and enabled '{skill}'. " "Available on your next turn."),
|
|
500
507
|
operations=ops,
|
|
501
508
|
)
|
|
502
509
|
|
|
@@ -504,7 +511,9 @@ class AgentBuilderNode(ToolNode):
|
|
|
504
511
|
|
|
505
512
|
@Operation("add_subagent")
|
|
506
513
|
async def add_subagent(
|
|
507
|
-
self,
|
|
514
|
+
self,
|
|
515
|
+
ctx: NodeContext,
|
|
516
|
+
params: AgentBuilderParams,
|
|
508
517
|
) -> AgentBuilderOutput:
|
|
509
518
|
_log_op_entry("add_subagent", ctx, agent_type=params.agent_type)
|
|
510
519
|
agent_type = (params.agent_type or "").strip()
|
|
@@ -524,10 +533,7 @@ class AgentBuilderNode(ToolNode):
|
|
|
524
533
|
leads = ", ".join(sorted(_TEAM_LEAD_TYPES))
|
|
525
534
|
return AgentBuilderOutput(
|
|
526
535
|
operation="add_subagent",
|
|
527
|
-
summary=(
|
|
528
|
-
f"add_subagent: only team-lead agents ({leads}) can spawn "
|
|
529
|
-
f"delegates. This agent is '{caller_type}'."
|
|
530
|
-
),
|
|
536
|
+
summary=(f"add_subagent: only team-lead agents ({leads}) can spawn " f"delegates. This agent is '{caller_type}'."),
|
|
531
537
|
operations=[],
|
|
532
538
|
)
|
|
533
539
|
allowed = _allowed_subagent_types()
|
|
@@ -535,41 +541,36 @@ class AgentBuilderNode(ToolNode):
|
|
|
535
541
|
sample = ", ".join(sorted(allowed)[:10])
|
|
536
542
|
return AgentBuilderOutput(
|
|
537
543
|
operation="add_subagent",
|
|
538
|
-
summary=(
|
|
539
|
-
f"add_subagent: '{agent_type}' is not an allowed agent "
|
|
540
|
-
f"type. Examples: {sample}..."
|
|
541
|
-
),
|
|
544
|
+
summary=(f"add_subagent: '{agent_type}' is not an allowed agent " f"type. Examples: {sample}..."),
|
|
542
545
|
operations=[],
|
|
543
546
|
)
|
|
544
547
|
if _is_team_lead(agent_type):
|
|
545
548
|
return AgentBuilderOutput(
|
|
546
549
|
operation="add_subagent",
|
|
547
|
-
summary=(
|
|
548
|
-
f"add_subagent: cannot spawn another team-lead "
|
|
549
|
-
f"('{agent_type}'); pick a specialized agent instead."
|
|
550
|
-
),
|
|
550
|
+
summary=(f"add_subagent: cannot spawn another team-lead " f"('{agent_type}'); pick a specialized agent instead."),
|
|
551
551
|
operations=[],
|
|
552
552
|
)
|
|
553
553
|
|
|
554
554
|
client_ref = f"new_{agent_type}"
|
|
555
555
|
ops = [
|
|
556
556
|
workflow_ops.add_node(
|
|
557
|
-
client_ref,
|
|
557
|
+
client_ref,
|
|
558
|
+
agent_type,
|
|
559
|
+
{},
|
|
558
560
|
label=agent_type,
|
|
559
561
|
position=workflow_ops.anchored(caller_id, offset_x=300, offset_y=200),
|
|
560
562
|
),
|
|
561
563
|
workflow_ops.add_edge(
|
|
562
|
-
{"client_ref": client_ref},
|
|
563
|
-
|
|
564
|
+
{"client_ref": client_ref},
|
|
565
|
+
caller_id,
|
|
566
|
+
source_handle=_TEAMMATES_OUTPUT_HANDLE,
|
|
567
|
+
target_handle=_TEAMMATES_HANDLE,
|
|
564
568
|
),
|
|
565
569
|
]
|
|
566
570
|
await _broadcast(ctx.workflow_id, caller_id, ops)
|
|
567
571
|
return AgentBuilderOutput(
|
|
568
572
|
operation="add_subagent",
|
|
569
|
-
summary=(
|
|
570
|
-
f"Added '{agent_type}' as a teammate. Available on your "
|
|
571
|
-
"next turn (configure provider/model first)."
|
|
572
|
-
),
|
|
573
|
+
summary=(f"Added '{agent_type}' as a teammate. Available on your " "next turn (configure provider/model first)."),
|
|
573
574
|
operations=ops,
|
|
574
575
|
)
|
|
575
576
|
|
|
@@ -577,10 +578,13 @@ class AgentBuilderNode(ToolNode):
|
|
|
577
578
|
|
|
578
579
|
@Operation("create_workflow")
|
|
579
580
|
async def create_workflow(
|
|
580
|
-
self,
|
|
581
|
+
self,
|
|
582
|
+
ctx: NodeContext,
|
|
583
|
+
params: AgentBuilderParams,
|
|
581
584
|
) -> AgentBuilderOutput:
|
|
582
585
|
_log_op_entry(
|
|
583
|
-
"create_workflow",
|
|
586
|
+
"create_workflow",
|
|
587
|
+
ctx,
|
|
584
588
|
workflow_name=params.workflow_name,
|
|
585
589
|
workflow_description=params.workflow_description,
|
|
586
590
|
)
|
|
@@ -611,9 +615,13 @@ class AgentBuilderNode(ToolNode):
|
|
|
611
615
|
}
|
|
612
616
|
|
|
613
617
|
from services.plugin.deps import get_database
|
|
618
|
+
|
|
614
619
|
database = get_database()
|
|
615
620
|
ok = await database.save_workflow(
|
|
616
|
-
workflow_id,
|
|
621
|
+
workflow_id,
|
|
622
|
+
name,
|
|
623
|
+
workflow_data,
|
|
624
|
+
description=description or None,
|
|
617
625
|
)
|
|
618
626
|
if not ok:
|
|
619
627
|
return AgentBuilderOutput(
|
|
@@ -622,9 +630,6 @@ class AgentBuilderNode(ToolNode):
|
|
|
622
630
|
)
|
|
623
631
|
return AgentBuilderOutput(
|
|
624
632
|
operation="create_workflow",
|
|
625
|
-
summary=(
|
|
626
|
-
f"Created workflow '{name}' (id: {workflow_id}). "
|
|
627
|
-
"User can switch to it from the toast notification."
|
|
628
|
-
),
|
|
633
|
+
summary=(f"Created workflow '{name}' (id: {workflow_id}). " "User can switch to it from the toast notification."),
|
|
629
634
|
workflow_id=workflow_id,
|
|
630
635
|
)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""CloudEvents factory + broadcaster wrapper for agent_builder.
|
|
2
|
+
|
|
3
|
+
Per RFC plugin_authoring_rfc.md §6.4: plugin-specific factories live in
|
|
4
|
+
the plugin folder.
|
|
5
|
+
|
|
6
|
+
This is NOT a trigger event — it's a canvas-mutation broadcast consumed
|
|
7
|
+
by the frontend's ``useWorkflowOpsListener`` hook. The wire format is
|
|
8
|
+
flat (``{workflow_id, caller_node_id, operations}``) for FE back-compat;
|
|
9
|
+
the typed envelope is constructed for parity with the other plugin
|
|
10
|
+
``_events.py`` modules but not consumed today.
|
|
11
|
+
|
|
12
|
+
Delivery: direct WS broadcast (no ``dispatch.emit`` — no
|
|
13
|
+
:class:`TriggerListenerWorkflow` consumer exists for canvas mutations,
|
|
14
|
+
and no legacy ``event_waiter`` waiter listens on ``workflow_ops_apply``
|
|
15
|
+
either). Pre-Wave-13 this routed through ``send_custom_event`` which
|
|
16
|
+
also called ``event_waiter.dispatch_async`` — that dispatch was dead.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import Any, Dict, List, Optional
|
|
22
|
+
|
|
23
|
+
from services.events.envelope import WorkflowEvent
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Flat wire-routing key consumed by ``client/src/hooks/useWorkflowOpsListener``.
|
|
27
|
+
_WIRE_ROUTING_KEY = "workflow_ops_apply"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def workflow_ops_applied(
|
|
31
|
+
*,
|
|
32
|
+
workflow_id: Optional[str],
|
|
33
|
+
caller_node_id: str,
|
|
34
|
+
operations: List[Dict[str, Any]],
|
|
35
|
+
) -> WorkflowEvent:
|
|
36
|
+
"""Canvas-mutation envelope. ``subject`` is the caller node id so
|
|
37
|
+
consumers can route per-builder."""
|
|
38
|
+
return WorkflowEvent(
|
|
39
|
+
source="machinaos://nodes/agent_builder",
|
|
40
|
+
type="com.machinaos.workflow.ops.applied",
|
|
41
|
+
subject=caller_node_id,
|
|
42
|
+
workflow_id=workflow_id,
|
|
43
|
+
data={
|
|
44
|
+
"workflow_id": workflow_id,
|
|
45
|
+
"caller_node_id": caller_node_id,
|
|
46
|
+
"operations": list(operations),
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def broadcast_workflow_ops(
|
|
52
|
+
*,
|
|
53
|
+
workflow_id: Optional[str],
|
|
54
|
+
caller_node_id: str,
|
|
55
|
+
operations: List[Dict[str, Any]],
|
|
56
|
+
) -> None:
|
|
57
|
+
"""Broadcast a canvas-mutation event for the FE to apply.
|
|
58
|
+
|
|
59
|
+
Flat payload (FE back-compat with ``useWorkflowOpsListener``); the
|
|
60
|
+
typed envelope is constructed for audit/future migration but not
|
|
61
|
+
on the wire today.
|
|
62
|
+
"""
|
|
63
|
+
if not operations:
|
|
64
|
+
return
|
|
65
|
+
from services.status_broadcaster import get_status_broadcaster
|
|
66
|
+
|
|
67
|
+
broadcaster = get_status_broadcaster()
|
|
68
|
+
payload = {
|
|
69
|
+
"workflow_id": workflow_id,
|
|
70
|
+
"caller_node_id": caller_node_id,
|
|
71
|
+
"operations": list(operations),
|
|
72
|
+
}
|
|
73
|
+
# Envelope constructed for parity / future migration; not on the
|
|
74
|
+
# wire today because FE listener reads the flat shape.
|
|
75
|
+
_ = workflow_ops_applied(
|
|
76
|
+
workflow_id=workflow_id,
|
|
77
|
+
caller_node_id=caller_node_id,
|
|
78
|
+
operations=operations,
|
|
79
|
+
)
|
|
80
|
+
await broadcaster.broadcast(
|
|
81
|
+
{
|
|
82
|
+
"type": _WIRE_ROUTING_KEY,
|
|
83
|
+
"data": payload,
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
__all__ = [
|
|
89
|
+
"broadcast_workflow_ops",
|
|
90
|
+
"workflow_ops_applied",
|
|
91
|
+
]
|