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
package/server/nodes/_visuals.py
CHANGED
|
@@ -1,25 +1,36 @@
|
|
|
1
1
|
"""Central handler for node visuals (icon + color).
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
Two icon sources co-exist by design (per RFC §6.5):
|
|
4
|
+
|
|
5
|
+
1. **Per-plugin ``icon.svg``** co-located with the plugin folder
|
|
6
|
+
(e.g. ``server/nodes/telegram/icon.svg``). Resolved at runtime via
|
|
7
|
+
:func:`get_plugin_icon_path`. Preferred for new plugins; served
|
|
8
|
+
by ``GET /api/schemas/nodes/{type}/icon`` (see ``routers/schemas.py``).
|
|
9
|
+
|
|
10
|
+
2. **``visuals.json``** for emoji entries and library-icon
|
|
11
|
+
(``lobehub:<brand>``) entries that don't map to a file. Resolved
|
|
12
|
+
via :func:`get_icon` / :func:`get_color`.
|
|
13
|
+
|
|
14
|
+
``BaseNode._metadata_dict`` checks the per-folder path first and
|
|
15
|
+
falls back to ``visuals.json``. The frontend resolver dispatches by
|
|
16
|
+
the wire-format prefix (URL paths route to ``<img>``; ``asset:``,
|
|
17
|
+
``lobehub:``, emoji each have their own branch).
|
|
18
|
+
|
|
19
|
+
Adding a new node:
|
|
20
|
+
- Drop ``icon.svg`` into the plugin folder, OR
|
|
21
|
+
- Add an entry to ``visuals.json`` (emoji or ``lobehub:<brand>``).
|
|
22
|
+
|
|
23
|
+
Node files do NOT declare ``icon`` or ``color`` themselves.
|
|
16
24
|
"""
|
|
17
25
|
|
|
18
26
|
from __future__ import annotations
|
|
19
27
|
|
|
28
|
+
import inspect
|
|
20
29
|
import json
|
|
21
30
|
from pathlib import Path
|
|
22
|
-
from typing import Dict
|
|
31
|
+
from typing import Dict, Optional
|
|
32
|
+
|
|
33
|
+
from services.plugin.identifiers import is_valid_node_type
|
|
23
34
|
|
|
24
35
|
|
|
25
36
|
_VISUALS_PATH = Path(__file__).resolve().parent / "visuals.json"
|
|
@@ -59,6 +70,10 @@ def get_color(node_type: str) -> str:
|
|
|
59
70
|
|
|
60
71
|
Color strings are arbitrary CSS color literals — the canvas node
|
|
61
72
|
components apply them as-is to gradients, borders, and badges.
|
|
73
|
+
|
|
74
|
+
Falls back to ``visuals.json`` for legacy entries that haven't been
|
|
75
|
+
migrated to per-plugin ``meta.json`` yet (F2 cleanup of the plugin
|
|
76
|
+
authoring RFC).
|
|
62
77
|
"""
|
|
63
78
|
entry = _VISUALS.get(node_type)
|
|
64
79
|
if not entry:
|
|
@@ -66,6 +81,123 @@ def get_color(node_type: str) -> str:
|
|
|
66
81
|
return str(entry.get("color", ""))
|
|
67
82
|
|
|
68
83
|
|
|
84
|
+
def get_plugin_meta(node_type: str, key: Optional[str] = None) -> Optional[dict | str]:
|
|
85
|
+
"""Read the plugin's co-located ``meta.json`` file.
|
|
86
|
+
|
|
87
|
+
Same folder-resolution path as :func:`get_plugin_icon_path` — uses
|
|
88
|
+
:func:`inspect.getfile` on the plugin class to locate the folder,
|
|
89
|
+
then loads ``meta.json`` if present.
|
|
90
|
+
|
|
91
|
+
Returns the value at ``key`` (str) when given, the whole dict when
|
|
92
|
+
``key`` is ``None``, or ``None`` when the file or key is absent.
|
|
93
|
+
Callers fall back to :func:`get_color` / other ``visuals.json`` keys
|
|
94
|
+
for legacy entries.
|
|
95
|
+
|
|
96
|
+
Per RFC §6.2 / F2 of the deferred follow-ups: ``meta.json`` mirrors
|
|
97
|
+
``icon.svg`` co-location so a plugin's entire visual surface area
|
|
98
|
+
lives in one folder. The previous central ``visuals.json`` color
|
|
99
|
+
map remains as a transitional fallback for entries without a
|
|
100
|
+
per-plugin ``meta.json``.
|
|
101
|
+
"""
|
|
102
|
+
from services.node_registry import get_node_class
|
|
103
|
+
|
|
104
|
+
if not is_valid_node_type(node_type):
|
|
105
|
+
return None
|
|
106
|
+
cls = get_node_class(node_type)
|
|
107
|
+
if cls is None:
|
|
108
|
+
return None
|
|
109
|
+
try:
|
|
110
|
+
plugin_dir = Path(inspect.getfile(cls)).resolve().parent
|
|
111
|
+
except (TypeError, OSError):
|
|
112
|
+
return None
|
|
113
|
+
meta_path = plugin_dir / "meta.json"
|
|
114
|
+
if not meta_path.exists():
|
|
115
|
+
return None
|
|
116
|
+
try:
|
|
117
|
+
with meta_path.open("r", encoding="utf-8") as fh:
|
|
118
|
+
data = json.load(fh)
|
|
119
|
+
except (OSError, json.JSONDecodeError):
|
|
120
|
+
return None
|
|
121
|
+
if not isinstance(data, dict):
|
|
122
|
+
return None
|
|
123
|
+
if key is None:
|
|
124
|
+
return data
|
|
125
|
+
value = data.get(key)
|
|
126
|
+
return None if value is None else str(value)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def get_plugin_icon_path(node_type: str, variant: str = "light") -> Optional[Path]:
|
|
130
|
+
"""Return the on-disk path to a plugin's co-located icon SVG.
|
|
131
|
+
|
|
132
|
+
``variant="dark"`` looks for the dark-mode SVG first and falls back
|
|
133
|
+
to the light variant when no dark file exists.
|
|
134
|
+
|
|
135
|
+
Resolution chain (first hit wins):
|
|
136
|
+
1. **Per-node-type icon** — ``<plugin_dir>/icon_<node_type>.svg``
|
|
137
|
+
(or ``icon_<node_type>.dark.svg`` for ``variant="dark"``).
|
|
138
|
+
Lets multi-node-per-plugin folders (whatsapp / telegram / stripe)
|
|
139
|
+
serve distinct icons per node type WITHOUT splitting the folder.
|
|
140
|
+
e.g. ``server/nodes/whatsapp/icon_whatsappSend.svg`` serves the
|
|
141
|
+
``whatsappSend`` node while sharing the folder with
|
|
142
|
+
``whatsappReceive`` and ``whatsappDb``.
|
|
143
|
+
2. **Shared plugin icon** — ``<plugin_dir>/icon.svg`` (or
|
|
144
|
+
``icon.dark.svg``). The original Phase 9 contract; one icon for
|
|
145
|
+
the whole folder.
|
|
146
|
+
|
|
147
|
+
Folder resolution itself:
|
|
148
|
+
1. Look up the plugin class via :func:`services.node_registry.get_node_class`.
|
|
149
|
+
2. Resolve the class's source file via ``inspect.getfile``.
|
|
150
|
+
3. The plugin folder is the file's parent directory — equally
|
|
151
|
+
correct for single-file plugins (``server/nodes/tool/calc.py``
|
|
152
|
+
→ parent ``server/nodes/tool/``) and self-contained-folder
|
|
153
|
+
plugins (``server/nodes/telegram/telegram_send.py`` → parent
|
|
154
|
+
``server/nodes/telegram/``).
|
|
155
|
+
|
|
156
|
+
Returns ``None`` when the type is unknown or no icon SVG is
|
|
157
|
+
present — caller falls back to :func:`get_icon` (visuals.json).
|
|
158
|
+
"""
|
|
159
|
+
# Local import to avoid a top-level circular dep (node_registry
|
|
160
|
+
# itself doesn't import _visuals, but plugin modules import both).
|
|
161
|
+
from services.node_registry import get_node_class
|
|
162
|
+
|
|
163
|
+
if not is_valid_node_type(node_type):
|
|
164
|
+
return None
|
|
165
|
+
cls = get_node_class(node_type)
|
|
166
|
+
if cls is None:
|
|
167
|
+
return None
|
|
168
|
+
try:
|
|
169
|
+
plugin_dir = Path(inspect.getfile(cls)).resolve().parent
|
|
170
|
+
except (TypeError, OSError):
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
# Candidate filenames in resolution order. Per-node-type first so
|
|
174
|
+
# multi-node folders can override the shared icon for specific node
|
|
175
|
+
# types. ``node_type`` is already constrained to ``NODE_TYPE_PATTERN``
|
|
176
|
+
# (``^[A-Za-z_][A-Za-z0-9_]*$``) by ``is_valid_node_type`` above --
|
|
177
|
+
# no path separators possible -- but we resolve the candidate and
|
|
178
|
+
# call ``Path.relative_to(plugin_dir)`` (which raises ``ValueError``
|
|
179
|
+
# on traversal). CodeQL's taint tracker recognises
|
|
180
|
+
# ``Path.relative_to`` as a ``py/path-injection`` sanitizer; the
|
|
181
|
+
# ``is_relative_to`` predicate it does not.
|
|
182
|
+
candidates: list[str] = []
|
|
183
|
+
if variant == "dark":
|
|
184
|
+
candidates.append(f"icon_{node_type}.dark.svg")
|
|
185
|
+
candidates.append(f"icon_{node_type}.svg")
|
|
186
|
+
if variant == "dark":
|
|
187
|
+
candidates.append("icon.dark.svg")
|
|
188
|
+
candidates.append("icon.svg")
|
|
189
|
+
|
|
190
|
+
for name in candidates:
|
|
191
|
+
candidate = (plugin_dir / name).resolve()
|
|
192
|
+
try:
|
|
193
|
+
candidate.relative_to(plugin_dir)
|
|
194
|
+
except ValueError:
|
|
195
|
+
continue
|
|
196
|
+
if candidate.exists():
|
|
197
|
+
return candidate
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
|
|
69
201
|
def get_skill(node_type: str) -> str:
|
|
70
202
|
"""Return the teaching skill folder name registered for ``node_type``.
|
|
71
203
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""CloudEvents broadcaster wrappers for agent task delegation.
|
|
2
|
+
|
|
3
|
+
Plugin-folder-owned wrappers around the cross-cutting
|
|
4
|
+
``WorkflowEvent.task_completed`` factory. The factory itself stays in
|
|
5
|
+
``services/events/envelope.py`` per RFC §6.4 — it's parametrised by
|
|
6
|
+
``task_id`` + ``agent`` + ``status`` and uniformly applies to every
|
|
7
|
+
delegated agent task, not a single-plugin shape. The broadcaster
|
|
8
|
+
wrappers below live with the agent plugin folder so the 3 callsites in
|
|
9
|
+
``services/handlers/tools.py`` (the fire-and-forget delegation
|
|
10
|
+
dispatcher) import from ``nodes.agent._events`` rather than building
|
|
11
|
+
the wire frame inline.
|
|
12
|
+
|
|
13
|
+
Delivery: a single ``dispatch.emit`` call. ``dispatch.emit`` Signals
|
|
14
|
+
running :class:`TriggerListenerWorkflow` consumers via Temporal
|
|
15
|
+
Visibility AND broadcasts the same envelope to in-process WS clients on
|
|
16
|
+
the ``task_completed`` wire-routing key — one canonical path. Pre-Wave-13
|
|
17
|
+
this also called ``broadcaster.send_custom_event`` for the legacy
|
|
18
|
+
collector path; that's dead since taskTrigger is canary-registered and
|
|
19
|
+
the deployment manager skips ``setup_event_trigger`` for canary types.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
from typing import Any, Optional
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Outer wire-routing key. FE consumers (if any) and the legacy
|
|
28
|
+
# back-compat receipt path still switch on this string; the inner
|
|
29
|
+
# envelope carries ``com.machinaos.agent.task.completed``.
|
|
30
|
+
_WIRE_ROUTING_KEY = "task_completed"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
async def broadcast_agent_task_completed(
|
|
34
|
+
*,
|
|
35
|
+
task_id: str,
|
|
36
|
+
agent_name: str,
|
|
37
|
+
agent_node_id: str,
|
|
38
|
+
parent_node_id: str,
|
|
39
|
+
workflow_id: Optional[str] = None,
|
|
40
|
+
result: Optional[str] = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
"""Broadcast a delegated agent task completing successfully."""
|
|
43
|
+
await _broadcast_task_event(
|
|
44
|
+
task_id=task_id,
|
|
45
|
+
status="completed",
|
|
46
|
+
agent_name=agent_name,
|
|
47
|
+
agent_node_id=agent_node_id,
|
|
48
|
+
parent_node_id=parent_node_id,
|
|
49
|
+
workflow_id=workflow_id,
|
|
50
|
+
result=result,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def broadcast_agent_task_failed(
|
|
55
|
+
*,
|
|
56
|
+
task_id: str,
|
|
57
|
+
agent_name: str,
|
|
58
|
+
agent_node_id: str,
|
|
59
|
+
parent_node_id: str,
|
|
60
|
+
workflow_id: Optional[str] = None,
|
|
61
|
+
error: str,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Broadcast a delegated agent task failing."""
|
|
64
|
+
await _broadcast_task_event(
|
|
65
|
+
task_id=task_id,
|
|
66
|
+
status="error",
|
|
67
|
+
agent_name=agent_name,
|
|
68
|
+
agent_node_id=agent_node_id,
|
|
69
|
+
parent_node_id=parent_node_id,
|
|
70
|
+
workflow_id=workflow_id,
|
|
71
|
+
error=error,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
async def _broadcast_task_event(
|
|
76
|
+
*,
|
|
77
|
+
task_id: str,
|
|
78
|
+
status: str, # "completed" | "error"
|
|
79
|
+
agent_name: str,
|
|
80
|
+
agent_node_id: str,
|
|
81
|
+
parent_node_id: str,
|
|
82
|
+
workflow_id: Optional[str] = None,
|
|
83
|
+
result: Optional[str] = None,
|
|
84
|
+
error: Optional[str] = None,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Single delivery path: build the envelope, route through
|
|
87
|
+
:func:`services.events.dispatch.emit`.
|
|
88
|
+
|
|
89
|
+
``emit`` does two things in one call: (a) Visibility query for
|
|
90
|
+
running :class:`TriggerListenerWorkflow` consumers tagged with
|
|
91
|
+
``EventType='com.machinaos.agent.task.completed'`` and signals each;
|
|
92
|
+
(b) direct in-process WS broadcast on the ``task_completed`` wire
|
|
93
|
+
key so any FE consumers receive the envelope. Payload shape in
|
|
94
|
+
``data`` is exactly what the taskTrigger filter reads.
|
|
95
|
+
"""
|
|
96
|
+
from services.events.dispatch import emit
|
|
97
|
+
from services.events.envelope import WorkflowEvent
|
|
98
|
+
|
|
99
|
+
payload: dict[str, Any] = {
|
|
100
|
+
"task_id": task_id,
|
|
101
|
+
"status": status,
|
|
102
|
+
"agent_name": agent_name,
|
|
103
|
+
"agent_node_id": agent_node_id,
|
|
104
|
+
"parent_node_id": parent_node_id,
|
|
105
|
+
"workflow_id": workflow_id,
|
|
106
|
+
}
|
|
107
|
+
if status == "completed" and result is not None:
|
|
108
|
+
payload["result"] = result
|
|
109
|
+
elif status == "error" and error is not None:
|
|
110
|
+
payload["error"] = error
|
|
111
|
+
|
|
112
|
+
envelope = WorkflowEvent.task_completed(
|
|
113
|
+
task_id=task_id,
|
|
114
|
+
status="completed" if status == "completed" else "error",
|
|
115
|
+
agent=agent_name,
|
|
116
|
+
data=payload,
|
|
117
|
+
)
|
|
118
|
+
await emit(envelope, wire_routing_key=_WIRE_ROUTING_KEY)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
__all__ = [
|
|
122
|
+
"broadcast_agent_task_completed",
|
|
123
|
+
"broadcast_agent_task_failed",
|
|
124
|
+
]
|
|
@@ -16,13 +16,13 @@ def std_agent_handles() -> tuple:
|
|
|
16
16
|
of the 20 agent variants. Returned as a tuple so the BaseNode
|
|
17
17
|
`handles` class attribute is immutable."""
|
|
18
18
|
return (
|
|
19
|
-
{"name": "input-skill",
|
|
20
|
-
{"name": "input-tools",
|
|
21
|
-
{"name": "input-main",
|
|
22
|
-
{"name": "input-memory", "kind": "input",
|
|
23
|
-
{"name": "input-task",
|
|
24
|
-
{"name": "output-main",
|
|
25
|
-
{"name": "output-top",
|
|
19
|
+
{"name": "input-skill", "kind": "input", "position": "bottom", "offset": "25%", "label": "Skill", "role": "skill"},
|
|
20
|
+
{"name": "input-tools", "kind": "input", "position": "bottom", "offset": "75%", "label": "Tool", "role": "tools"},
|
|
21
|
+
{"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
|
|
22
|
+
{"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory", "role": "memory"},
|
|
23
|
+
{"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
|
|
24
|
+
{"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output", "role": "main"},
|
|
25
|
+
{"name": "output-top", "kind": "output", "position": "top", "label": "Output", "role": "main"},
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
|
|
@@ -30,26 +30,12 @@ def team_lead_agent_handles() -> tuple:
|
|
|
30
30
|
"""Skill / Tool / Teammates bottom + Memory/Task/Input left + Outputs.
|
|
31
31
|
Used by orchestrator_agent and ai_employee."""
|
|
32
32
|
return (
|
|
33
|
-
{"name": "input-skill",
|
|
34
|
-
{"name": "input-tools",
|
|
35
|
-
{"name": "input-teammates", "kind": "input",
|
|
36
|
-
{"name": "input-main",
|
|
37
|
-
{"name": "input-memory",
|
|
38
|
-
{"name": "input-task",
|
|
39
|
-
{"name": "output-main",
|
|
40
|
-
{"name": "output-top",
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def deep_agent_handles() -> tuple:
|
|
45
|
-
"""Skill / Teammates / Tool bottom — used by deep_agent only."""
|
|
46
|
-
return (
|
|
47
|
-
{"name": "input-skill", "kind": "input", "position": "bottom", "offset": "30%", "label": "Skill", "role": "skill"},
|
|
48
|
-
{"name": "input-teammates", "kind": "input", "position": "bottom", "offset": "55%", "label": "Team", "role": "teammates"},
|
|
49
|
-
{"name": "input-tools", "kind": "input", "position": "bottom", "offset": "80%", "label": "Tool", "role": "tools"},
|
|
50
|
-
{"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
|
|
51
|
-
{"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory","role": "memory"},
|
|
52
|
-
{"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
|
|
53
|
-
{"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output","role": "main"},
|
|
54
|
-
{"name": "output-top", "kind": "output", "position": "top", "label": "Output","role": "main"},
|
|
33
|
+
{"name": "input-skill", "kind": "input", "position": "bottom", "offset": "20%", "label": "Skill", "role": "skill"},
|
|
34
|
+
{"name": "input-tools", "kind": "input", "position": "bottom", "offset": "50%", "label": "Tool", "role": "tools"},
|
|
35
|
+
{"name": "input-teammates", "kind": "input", "position": "bottom", "offset": "80%", "label": "Team", "role": "teammates"},
|
|
36
|
+
{"name": "input-main", "kind": "input", "position": "left", "offset": "25%", "label": "Input", "role": "main"},
|
|
37
|
+
{"name": "input-memory", "kind": "input", "position": "left", "offset": "50%", "label": "Memory", "role": "memory"},
|
|
38
|
+
{"name": "input-task", "kind": "input", "position": "left", "offset": "75%", "label": "Task", "role": "task"},
|
|
39
|
+
{"name": "output-main", "kind": "output", "position": "right", "offset": "50%", "label": "Output", "role": "main"},
|
|
40
|
+
{"name": "output-top", "kind": "output", "position": "top", "label": "Output", "role": "main"},
|
|
55
41
|
)
|
|
@@ -22,7 +22,7 @@ to ``ai_service.execute_agent(...)`` or ``ai_service.execute_chat_agent(...)``.
|
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
|
-
from typing import Any, Dict
|
|
25
|
+
from typing import Any, Dict
|
|
26
26
|
|
|
27
27
|
from core.logging import get_logger
|
|
28
28
|
from services.plugin.edge_walker import (
|
|
@@ -60,7 +60,10 @@ async def prepare_agent_call(
|
|
|
60
60
|
parameters = {**parameters, "api_key": raw_params["api_key"]}
|
|
61
61
|
|
|
62
62
|
memory_data, skill_data, tool_data, input_data, task_data = await collect_agent_connections(
|
|
63
|
-
node_id,
|
|
63
|
+
node_id,
|
|
64
|
+
context,
|
|
65
|
+
database,
|
|
66
|
+
log_prefix=log_prefix,
|
|
64
67
|
)
|
|
65
68
|
|
|
66
69
|
# Step 1: task-context injection + tool-strip.
|
|
@@ -76,8 +79,7 @@ async def prepare_agent_call(
|
|
|
76
79
|
original_tool_count = len(tool_data)
|
|
77
80
|
tool_data = []
|
|
78
81
|
logger.info(
|
|
79
|
-
f"{log_prefix} Stripped ALL {original_tool_count} tools for "
|
|
80
|
-
"task completion handling",
|
|
82
|
+
f"{log_prefix} Stripped ALL {original_tool_count} tools for " "task completion handling",
|
|
81
83
|
)
|
|
82
84
|
|
|
83
85
|
# Step 2: auto-prompt fallback.
|
|
@@ -113,31 +115,34 @@ async def prepare_agent_call(
|
|
|
113
115
|
tm_id = tm["node_id"]
|
|
114
116
|
child_tools = []
|
|
115
117
|
for child_edge in all_edges:
|
|
116
|
-
if (
|
|
117
|
-
child_edge.get("target") != tm_id
|
|
118
|
-
or child_edge.get("targetHandle") != "input-tools"
|
|
119
|
-
):
|
|
118
|
+
if child_edge.get("target") != tm_id or child_edge.get("targetHandle") != "input-tools":
|
|
120
119
|
continue
|
|
121
120
|
child_id = child_edge.get("source")
|
|
122
121
|
child_node = next(
|
|
123
|
-
(n for n in all_nodes if n.get("id") == child_id),
|
|
122
|
+
(n for n in all_nodes if n.get("id") == child_id),
|
|
123
|
+
None,
|
|
124
124
|
)
|
|
125
125
|
if not child_node:
|
|
126
126
|
continue
|
|
127
|
-
child_tools.append(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"label"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
127
|
+
child_tools.append(
|
|
128
|
+
{
|
|
129
|
+
"node_id": child_id,
|
|
130
|
+
"node_type": child_node.get("type"),
|
|
131
|
+
"label": child_node.get("data", {}).get(
|
|
132
|
+
"label",
|
|
133
|
+
child_node.get("type"),
|
|
134
|
+
),
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
tool_data.append(
|
|
138
|
+
{
|
|
139
|
+
"node_id": tm_id,
|
|
140
|
+
"node_type": tm["node_type"],
|
|
141
|
+
"label": tm["label"],
|
|
142
|
+
"parameters": tm.get("parameters", {}),
|
|
143
|
+
"child_tools": child_tools,
|
|
144
|
+
}
|
|
145
|
+
)
|
|
141
146
|
logger.info(f"[Teams] Added {len(teammates)} teammates as delegation tools")
|
|
142
147
|
|
|
143
148
|
from services.status_broadcaster import get_status_broadcaster
|
|
@@ -152,5 +157,3 @@ async def prepare_agent_call(
|
|
|
152
157
|
"context": context,
|
|
153
158
|
"database": database,
|
|
154
159
|
}
|
|
155
|
-
|
|
156
|
-
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""Specialized agent base — subclass + set 5 attrs to mint a new agent.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
/ tool / productivity / payments / consumer / autonomous
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
All specialized agents (android / coding / web / task / social / travel
|
|
4
|
+
/ tool / productivity / payments / consumer / autonomous) share the
|
|
5
|
+
``handle_chat_agent`` execution path. The only differences are display
|
|
6
|
+
name, icon, colour, subtitle, description. Each agent gets its own file
|
|
7
|
+
under ``nodes/agent/`` so the user can find ``android_agent.py``
|
|
8
|
+
directly — but the body lives here so changing the dispatch path is a
|
|
9
|
+
one-file edit.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
@@ -36,14 +36,23 @@ class SpecializedAgentParams(BaseModel):
|
|
|
36
36
|
},
|
|
37
37
|
)
|
|
38
38
|
provider: Literal[
|
|
39
|
-
"openai",
|
|
40
|
-
"
|
|
39
|
+
"openai",
|
|
40
|
+
"anthropic",
|
|
41
|
+
"gemini",
|
|
42
|
+
"openrouter",
|
|
43
|
+
"groq",
|
|
44
|
+
"cerebras",
|
|
45
|
+
"deepseek",
|
|
46
|
+
"kimi",
|
|
47
|
+
"mistral",
|
|
41
48
|
# Local-server providers — see ai_agent.Params for the proxy_url
|
|
42
49
|
# rationale. Same fix; same reason.
|
|
43
|
-
"ollama",
|
|
50
|
+
"ollama",
|
|
51
|
+
"lmstudio",
|
|
44
52
|
] = "openai"
|
|
45
53
|
model: str = Field(
|
|
46
|
-
default="",
|
|
54
|
+
default="",
|
|
55
|
+
json_schema_extra={"placeholder": "Select a model..."},
|
|
47
56
|
)
|
|
48
57
|
system_message: Optional[str] = Field(
|
|
49
58
|
default="You are a helpful assistant",
|
|
@@ -54,14 +63,18 @@ class SpecializedAgentParams(BaseModel):
|
|
|
54
63
|
# default=None so an unset value falls through to ``agent.default_temperature``
|
|
55
64
|
# in server/config/llm_defaults.json (resolved by _resolve_temperature).
|
|
56
65
|
temperature: Optional[float] = Field(
|
|
57
|
-
default=None,
|
|
66
|
+
default=None,
|
|
67
|
+
ge=0.0,
|
|
68
|
+
le=2.0,
|
|
58
69
|
json_schema_extra={"group": "options"},
|
|
59
70
|
)
|
|
60
71
|
# default=None so an unset value is absent from the dumped dict and the
|
|
61
72
|
# backend (_resolve_max_tokens) falls through to the per-model default
|
|
62
73
|
# in server/config/llm_defaults.json instead of being silently capped.
|
|
63
74
|
max_tokens: Optional[int] = Field(
|
|
64
|
-
default=None,
|
|
75
|
+
default=None,
|
|
76
|
+
ge=1,
|
|
77
|
+
le=200000,
|
|
65
78
|
json_schema_extra={"group": "options"},
|
|
66
79
|
)
|
|
67
80
|
|
|
@@ -117,9 +130,11 @@ class SpecializedAgentBase(ActionNode, abstract=True):
|
|
|
117
130
|
ai_service = get_ai_service()
|
|
118
131
|
database = get_database()
|
|
119
132
|
kwargs = await prepare_agent_call(
|
|
120
|
-
node_id=ctx.node_id,
|
|
133
|
+
node_id=ctx.node_id,
|
|
134
|
+
node_type=self.type,
|
|
121
135
|
parameters=params.model_dump(),
|
|
122
|
-
context=ctx.raw,
|
|
136
|
+
context=ctx.raw,
|
|
137
|
+
database=database,
|
|
123
138
|
log_prefix=f"[{self.type}]",
|
|
124
139
|
)
|
|
125
140
|
response = await ai_service.execute_chat_agent(ctx.node_id, **kwargs)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"""AI Agent — Wave 11.C migration (
|
|
1
|
+
"""AI Agent — Wave 11.C migration (tool-calling agent).
|
|
2
2
|
|
|
3
|
-
Tool-calling
|
|
3
|
+
Tool-calling agent with memory, skills, and iterative
|
|
4
4
|
reasoning. Delegates execution to ``handlers/ai.handle_ai_agent`` —
|
|
5
|
-
that body owns the
|
|
5
|
+
that body owns the agent-loop construction + tool binding +
|
|
6
6
|
streaming + memory persistence + delegation.
|
|
7
7
|
"""
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ from pydantic import BaseModel, ConfigDict, Field
|
|
|
14
14
|
|
|
15
15
|
from services.plugin import ActionNode, NodeContext, Operation, TaskQueue
|
|
16
16
|
|
|
17
|
-
from
|
|
17
|
+
from .._handles import STD_AGENT_HINTS, std_agent_handles
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class AIAgentParams(BaseModel):
|
|
@@ -39,17 +39,26 @@ class AIAgentParams(BaseModel):
|
|
|
39
39
|
},
|
|
40
40
|
)
|
|
41
41
|
provider: Literal[
|
|
42
|
-
"openai",
|
|
43
|
-
"
|
|
42
|
+
"openai",
|
|
43
|
+
"anthropic",
|
|
44
|
+
"gemini",
|
|
45
|
+
"openrouter",
|
|
46
|
+
"groq",
|
|
47
|
+
"cerebras",
|
|
48
|
+
"deepseek",
|
|
49
|
+
"kimi",
|
|
50
|
+
"mistral",
|
|
44
51
|
# Local-server providers — agent execution reads
|
|
45
52
|
# ``{provider}_proxy`` to point the LangChain client at the
|
|
46
53
|
# user's localhost server. Without these entries the dropdown
|
|
47
54
|
# silently falls back to ``"openai"`` and execute_agent ends
|
|
48
55
|
# up calling api.openai.com instead.
|
|
49
|
-
"ollama",
|
|
56
|
+
"ollama",
|
|
57
|
+
"lmstudio",
|
|
50
58
|
] = "openai"
|
|
51
59
|
model: str = Field(
|
|
52
|
-
default="",
|
|
60
|
+
default="",
|
|
61
|
+
json_schema_extra={"placeholder": "Select a model..."},
|
|
53
62
|
)
|
|
54
63
|
system_message: Optional[str] = Field(
|
|
55
64
|
default="You are a helpful assistant",
|
|
@@ -60,14 +69,18 @@ class AIAgentParams(BaseModel):
|
|
|
60
69
|
# default=None so an unset value falls through to ``agent.default_temperature``
|
|
61
70
|
# in server/config/llm_defaults.json (resolved by _resolve_temperature).
|
|
62
71
|
temperature: Optional[float] = Field(
|
|
63
|
-
default=None,
|
|
72
|
+
default=None,
|
|
73
|
+
ge=0.0,
|
|
74
|
+
le=2.0,
|
|
64
75
|
json_schema_extra={"numberStepSize": 0.1, "group": "options"},
|
|
65
76
|
)
|
|
66
77
|
# default=None so an unset value is absent from the dumped dict and the
|
|
67
78
|
# backend (_resolve_max_tokens) falls through to the per-model default
|
|
68
79
|
# in server/config/llm_defaults.json instead of being silently capped.
|
|
69
80
|
max_tokens: Optional[int] = Field(
|
|
70
|
-
default=None,
|
|
81
|
+
default=None,
|
|
82
|
+
ge=1,
|
|
83
|
+
le=200000,
|
|
71
84
|
json_schema_extra={"group": "options"},
|
|
72
85
|
)
|
|
73
86
|
|
|
@@ -98,10 +111,11 @@ class AIAgentOutput(BaseModel):
|
|
|
98
111
|
class AIAgentNode(ActionNode):
|
|
99
112
|
type = "aiAgent"
|
|
100
113
|
display_name = "AI Agent"
|
|
101
|
-
subtitle = "
|
|
114
|
+
subtitle = "AI Agent"
|
|
102
115
|
group = ("agent",)
|
|
103
|
-
description = "
|
|
116
|
+
description = "AI agent with tool calling, memory, and iterative reasoning"
|
|
104
117
|
component_kind = "agent"
|
|
118
|
+
tool_name = "delegate_to_ai_agent"
|
|
105
119
|
handles = std_agent_handles()
|
|
106
120
|
ui_hints = STD_AGENT_HINTS
|
|
107
121
|
annotations = {"destructive": False, "readonly": False, "open_world": True}
|
|
@@ -117,19 +131,21 @@ class AIAgentNode(ActionNode):
|
|
|
117
131
|
Pre-dispatch flow (edge walk + task inject + prompt fallback)
|
|
118
132
|
lives in :mod:`nodes.agent._inline`. This method just calls
|
|
119
133
|
``AIService.execute_agent`` with the prepared kwargs. The
|
|
120
|
-
underlying
|
|
121
|
-
|
|
134
|
+
underlying agent loop + tool binding + memory I/O + streaming
|
|
135
|
+
hooks stay in AIService.
|
|
122
136
|
"""
|
|
123
137
|
from services.plugin.deps import get_ai_service, get_database
|
|
124
138
|
|
|
125
|
-
from
|
|
139
|
+
from .._inline import prepare_agent_call
|
|
126
140
|
|
|
127
141
|
ai_service = get_ai_service()
|
|
128
142
|
database = get_database()
|
|
129
143
|
kwargs = await prepare_agent_call(
|
|
130
|
-
node_id=ctx.node_id,
|
|
144
|
+
node_id=ctx.node_id,
|
|
145
|
+
node_type=self.type,
|
|
131
146
|
parameters=params.model_dump(),
|
|
132
|
-
context=ctx.raw,
|
|
147
|
+
context=ctx.raw,
|
|
148
|
+
database=database,
|
|
133
149
|
log_prefix="[AI Agent]",
|
|
134
150
|
)
|
|
135
151
|
# ``execute_agent`` raises ``NodeUserError`` directly for typed
|