machinaos 0.0.76 → 0.0.78
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/README.md +143 -107
- package/client/dist/assets/ActionBar-Du2MSFSz.js +1 -0
- package/client/dist/assets/ApiKeyInput-k2LBmBjb.js +1 -0
- package/client/dist/assets/ApiKeyPanel-C_bV9U0X.js +1 -0
- package/client/dist/assets/ApiUsageSection-CmVfwZzL.js +1 -0
- package/client/dist/assets/EmailPanel-CeKIMGu-.js +1 -0
- package/client/dist/assets/OAuthPanel-KA3t3Q2K.js +1 -0
- package/client/dist/assets/QrPairingPanel-NgNpJNuk.js +1 -0
- package/client/dist/assets/RateLimitSection-Du5YNVIA.js +1 -0
- package/client/dist/assets/StatusCard-DNLyayXc.js +1 -0
- package/client/dist/assets/index-DQ0nwhec.js +257 -0
- package/client/dist/assets/index-DxmbVskS.css +1 -0
- package/client/dist/assets/vendor-flow-CZmBvHRo.js +1 -0
- package/client/dist/assets/vendor-icons-CVrPjN2Q.js +22 -0
- package/client/dist/assets/vendor-markdown-CRou3yQ5.js +62 -0
- package/client/dist/assets/vendor-misc-C4VxKHs5.js +1 -0
- package/client/dist/assets/vendor-query-SzWcOU0G.js +1 -0
- package/client/dist/assets/vendor-radix-Dnos29jG.js +56 -0
- package/client/dist/assets/vendor-react-DvWIbVx0.js +1 -0
- package/client/dist/index.html +37 -3
- package/client/index.html +28 -1
- package/client/package.json +44 -40
- package/client/src/App.tsx +2 -0
- package/client/src/Dashboard.tsx +157 -45
- package/client/src/ParameterPanel.tsx +3 -5
- package/client/src/adapters/nodeSpecToDescription.ts +1 -0
- package/client/src/assets/icons/NodeIcon.tsx +32 -0
- package/client/src/assets/icons/index.ts +4 -0
- package/client/src/assets/icons/stripe.svg +1 -0
- package/client/src/assets/icons/themedGlyphs.ts +404 -0
- package/client/src/components/AIAgentNode.tsx +77 -53
- package/client/src/components/GenericNode.tsx +34 -52
- package/client/src/components/OutputPanel.tsx +64 -147
- package/client/src/components/ParameterRenderer.tsx +5 -3
- package/client/src/components/SkillEditorModal.tsx +9 -18
- package/client/src/components/SquareNode.tsx +97 -115
- package/client/src/components/StartNode.tsx +32 -42
- package/client/src/components/SvgFilterDefs.tsx +54 -0
- package/client/src/components/TeamMonitorNode.tsx +12 -14
- package/client/src/components/ToolkitNode.tsx +35 -60
- package/client/src/components/TriggerNode.tsx +43 -77
- package/client/src/components/__tests__/CredentialsModal.test.tsx +49 -45
- package/client/src/components/credentials/CredentialsModal.tsx +98 -30
- package/client/src/components/credentials/CredentialsPalette.tsx +73 -5
- package/client/src/components/credentials/catalogueAdapter.ts +17 -1
- package/client/src/components/credentials/panels/ApiKeyPanel.tsx +102 -37
- package/client/src/components/credentials/panels/EmailPanel.tsx +7 -19
- package/client/src/components/credentials/panels/OAuthPanel.tsx +5 -1
- package/client/src/components/credentials/panels/QrPairingPanel.tsx +1 -3
- package/client/src/components/credentials/primitives/ActionBar.tsx +7 -11
- package/client/src/components/credentials/primitives/OAuthConnect.tsx +19 -28
- package/client/src/components/credentials/sections/ProviderDefaultsSection.tsx +24 -3
- package/client/src/components/credentials/types.ts +12 -2
- package/client/src/components/credentials/useCredentialPanel.ts +43 -19
- package/client/src/components/icons/AIProviderIcons.tsx +16 -0
- package/client/src/components/onboarding/OnboardingWizard.tsx +23 -63
- package/client/src/components/onboarding/nodeRoleClasses.ts +23 -0
- package/client/src/components/onboarding/steps/CanvasStep.tsx +15 -21
- package/client/src/components/onboarding/steps/ConceptsStep.tsx +2 -11
- package/client/src/components/onboarding/steps/GetStartedStep.tsx +2 -10
- package/client/src/components/parameterPanel/InputSection.tsx +9 -7
- package/client/src/components/parameterPanel/MasterSkillEditor.tsx +84 -198
- package/client/src/components/parameterPanel/MiddleSection.tsx +57 -80
- package/client/src/components/parameterPanel/ToolSchemaEditor.tsx +31 -25
- package/client/src/components/parameterPanel/__tests__/InputSection.test.tsx +7 -2
- package/client/src/components/ui/AIResultModal.tsx +1 -1
- package/client/src/components/ui/CollapsibleSection.tsx +9 -5
- package/client/src/components/ui/CommandPalette.tsx +147 -0
- package/client/src/components/ui/CommandPaletteHost.tsx +189 -0
- package/client/src/components/ui/ComponentItem.tsx +13 -7
- package/client/src/components/ui/ComponentPalette.tsx +24 -13
- package/client/src/components/ui/ConsolePanel.tsx +19 -11
- package/client/src/components/ui/DropCap.tsx +28 -0
- package/client/src/components/ui/EditableNodeLabel.tsx +10 -2
- package/client/src/components/ui/InputNodesPanel.tsx +1 -1
- package/client/src/components/ui/Modal.tsx +38 -6
- package/client/src/components/ui/OutputDisplayPanel.tsx +1 -1
- package/client/src/components/ui/SettingsPanel.tsx +42 -13
- package/client/src/components/ui/StatusBar.tsx +108 -0
- package/client/src/components/ui/ThemeSwitcher.tsx +109 -0
- package/client/src/components/ui/TopToolbar.tsx +42 -25
- package/client/src/components/ui/WorkflowSidebar.tsx +32 -16
- package/client/src/components/ui/action-button.tsx +40 -15
- package/client/src/components/ui/button.tsx +24 -1
- package/client/src/components/ui/dropdown-menu.tsx +24 -2
- package/client/src/components/ui/input.tsx +19 -2
- package/client/src/components/ui/select.tsx +15 -0
- package/client/src/components/ui/textarea.tsx +15 -2
- package/client/src/contexts/AuthContext.tsx +148 -109
- package/client/src/contexts/ThemeContext.tsx +93 -17
- package/client/src/contexts/WebSocketContext.tsx +373 -206
- package/client/src/contexts/__tests__/AuthContext.test.tsx +221 -0
- package/client/src/hooks/__tests__/useDragVariable.test.ts +7 -1
- package/client/src/hooks/__tests__/useWorkflowOpsListener.test.ts +142 -0
- package/client/src/hooks/useAppTheme.ts +209 -7
- package/client/src/hooks/useAutoSkillEdges.ts +7 -2
- package/client/src/hooks/useCatalogueQuery.ts +67 -1
- package/client/src/hooks/useDragVariable.ts +1 -1
- package/client/src/hooks/useNodeAllowlist.ts +115 -8
- package/client/src/hooks/useOnboarding.ts +20 -8
- package/client/src/hooks/useParameterPanel.ts +2 -1
- package/client/src/hooks/useReactFlowNodes.ts +2 -1
- package/client/src/hooks/useSound.ts +185 -0
- package/client/src/hooks/useWorkflowManagement.ts +6 -8
- package/client/src/hooks/useWorkflowOpsListener.ts +90 -0
- package/client/src/index.css +65 -3
- package/client/src/lib/__tests__/connectionConfig.test.ts +91 -0
- package/client/src/lib/aiModelProviders.ts +8 -0
- package/client/src/lib/connectionConfig.ts +107 -0
- package/client/src/lib/queryPersist.ts +13 -5
- package/client/src/lib/sound.ts +393 -0
- package/client/src/main.tsx +20 -0
- package/client/src/store/useAppStore.ts +26 -0
- package/client/src/styles/canvasAnimations.ts +37 -36
- package/client/src/styles/theme.ts +36 -20
- package/client/src/test/setup.ts +1 -0
- package/client/src/themes/atomic.css +253 -0
- package/client/src/themes/base.css +373 -0
- package/client/src/themes/cyber.css +890 -0
- package/client/src/themes/dark.css +70 -0
- package/client/src/themes/edo.css +246 -0
- package/client/src/themes/greek.css +293 -0
- package/client/src/themes/light.css +78 -0
- package/client/src/themes/plague.css +253 -0
- package/client/src/themes/renaissance.css +727 -0
- package/client/src/themes/rot.css +249 -0
- package/client/src/themes/steampunk.css +272 -0
- package/client/src/themes/surveillance.css +289 -0
- package/client/src/themes/wasteland.css +250 -0
- package/client/src/types/INodeProperties.ts +5 -0
- package/client/src/types/NodeTypes.ts +11 -1
- package/client/src/types/__tests__/cloudEvents.test.ts +99 -0
- package/client/src/types/cloudEvents.ts +78 -0
- package/client/src/vite-env.d.ts +7 -0
- package/client/tsconfig.json +1 -1
- package/client/vite.config.js +62 -2
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/machina/commands/build.py +51 -7
- package/machina/pyproject.toml +4 -0
- package/machina/supervisor.py +12 -2
- package/machina/tree.py +71 -21
- package/package.json +4 -4
- package/scripts/install.js +16 -1
- package/server/config/ai_cli_providers.json +54 -0
- package/server/config/credential_providers.json +109 -2
- package/server/config/llm_defaults.json +24 -0
- package/server/config/model_registry.json +338 -499
- package/server/config/node_allowlist.json +16 -1
- package/server/config/pricing.json +8 -0
- package/server/constants.py +38 -15
- package/server/core/container.py +2 -2
- package/server/core/credentials_database.py +35 -2
- package/server/core/logging.py +4 -3
- package/server/main.py +99 -13
- package/server/models/node_metadata.py +1 -0
- package/server/nodejs/package.json +8 -6
- package/server/nodejs/src/index.ts +22 -5
- package/server/nodes/README.md +31 -4
- package/server/nodes/agent/_inline.py +2 -0
- package/server/nodes/agent/_specialized.py +6 -3
- package/server/nodes/agent/ai_agent.py +13 -3
- package/server/nodes/agent/chat_agent.py +6 -3
- package/server/nodes/agent/claude_code_agent.py +287 -75
- package/server/nodes/agent/codex_agent.py +239 -0
- package/server/nodes/agent/deep_agent.py +3 -3
- package/server/nodes/agent/rlm_agent.py +3 -3
- package/server/nodes/android/__init__.py +31 -1
- package/server/nodes/android/_base.py +9 -5
- package/server/{services/android_service.py → nodes/android/_dispatcher.py} +2 -2
- package/server/nodes/android/_handlers.py +154 -0
- package/server/nodes/android/_option_loaders.py +44 -0
- package/server/nodes/android/_refresh.py +127 -0
- package/server/{services/android → nodes/android/_relay}/client.py +4 -4
- package/server/{routers/android.py → nodes/android/_router.py} +27 -8
- package/server/nodes/browser/browser.py +2 -2
- package/server/nodes/code/_base.py +6 -2
- package/server/nodes/code/_claude_code.py +134 -0
- package/server/nodes/document/embedding_generator.py +3 -3
- package/server/nodes/document/http_scraper.py +3 -3
- package/server/nodes/document/vector_store.py +5 -5
- package/server/nodes/email/__init__.py +11 -1
- package/server/nodes/email/_filters.py +21 -0
- package/server/{services/himalaya_service.py → nodes/email/_himalaya.py} +6 -10
- package/server/{services/email_service.py → nodes/email/_service.py} +9 -13
- package/server/nodes/email/email_read.py +1 -1
- package/server/nodes/email/email_receive.py +54 -5
- package/server/nodes/email/email_send.py +1 -1
- package/server/nodes/filesystem/shell.py +24 -1
- package/server/nodes/google/__init__.py +55 -1
- package/server/{services/handlers/google_auth.py → nodes/google/_auth_helper.py} +8 -5
- package/server/nodes/google/_base.py +2 -2
- package/server/nodes/google/_credentials.py +5 -5
- package/server/nodes/google/_filters.py +25 -0
- package/server/nodes/google/_handlers.py +57 -0
- package/server/{services/google_oauth.py → nodes/google/_oauth.py} +195 -162
- package/server/nodes/google/_option_loaders.py +107 -0
- package/server/nodes/google/_refresh.py +66 -0
- package/server/nodes/google/_router.py +131 -0
- package/server/nodes/google/gmail_receive.py +41 -4
- package/server/nodes/groups.py +1 -0
- package/server/nodes/location/_credentials.py +45 -1
- package/server/{services/maps.py → nodes/location/_service.py} +18 -3
- package/server/nodes/location/gmaps_create.py +4 -4
- package/server/nodes/location/gmaps_locations.py +4 -4
- package/server/nodes/location/gmaps_nearby_places.py +4 -4
- package/server/nodes/model/_base.py +8 -3
- package/server/nodes/model/_credentials.py +96 -8
- package/server/nodes/model/_local_validator.py +345 -0
- package/server/nodes/model/lmstudio_chat_model.py +23 -0
- package/server/nodes/model/ollama_chat_model.py +25 -0
- package/server/nodes/proxy/_usage.py +2 -2
- package/server/nodes/proxy/proxy_config.py +14 -14
- package/server/nodes/proxy/proxy_request.py +4 -4
- package/server/nodes/scraper/_credentials.py +29 -1
- package/server/nodes/scraper/apify_actor.py +9 -9
- package/server/nodes/scraper/crawlee_scraper.py +5 -5
- package/server/nodes/search/brave_search.py +4 -0
- package/server/nodes/search/perplexity_search.py +9 -0
- package/server/nodes/search/serper_search.py +3 -0
- package/server/nodes/skill/simple_memory.py +12 -0
- package/server/nodes/social/_base.py +2 -2
- package/server/nodes/stripe/__init__.py +46 -0
- package/server/nodes/stripe/_credentials.py +33 -0
- package/server/nodes/stripe/_handlers.py +270 -0
- package/server/nodes/stripe/_install.py +127 -0
- package/server/nodes/stripe/_source.py +174 -0
- package/server/nodes/stripe/stripe_action.py +81 -0
- package/server/nodes/stripe/stripe_receive.py +92 -0
- package/server/nodes/telegram/_credentials.py +52 -1
- package/server/nodes/telegram/_handlers.py +19 -18
- package/server/nodes/telegram/_service.py +134 -32
- package/server/nodes/telegram/telegram_send.py +5 -6
- package/server/nodes/text/file_handler.py +2 -2
- package/server/nodes/text/text_generator.py +2 -2
- package/server/nodes/tool/agent_builder.py +630 -0
- package/server/nodes/tool/task_manager.py +144 -2
- package/server/nodes/twitter/__init__.py +38 -1
- package/server/nodes/twitter/_base.py +7 -7
- package/server/nodes/twitter/_credentials.py +1 -1
- package/server/nodes/twitter/_filters.py +37 -0
- package/server/nodes/twitter/_handlers.py +77 -0
- package/server/nodes/twitter/_oauth.py +124 -0
- package/server/nodes/twitter/_refresh.py +78 -0
- package/server/nodes/twitter/_router.py +29 -0
- package/server/nodes/twitter/twitter_receive.py +4 -0
- package/server/nodes/visuals.json +64 -19
- package/server/nodes/whatsapp/__init__.py +45 -5
- package/server/nodes/whatsapp/_base.py +3 -3
- package/server/nodes/whatsapp/_filters.py +137 -0
- package/server/nodes/whatsapp/_handlers.py +167 -0
- package/server/nodes/whatsapp/_option_loaders.py +68 -0
- package/server/nodes/whatsapp/_refresh.py +62 -0
- package/server/nodes/whatsapp/_runtime.py +1 -1
- package/server/pyproject.toml +29 -7
- package/server/routers/schemas.py +2 -2
- package/server/routers/webhook.py +26 -9
- package/server/routers/websocket.py +149 -810
- package/server/services/ai.py +89 -8
- package/server/services/auth.py +220 -43
- package/server/services/claude_oauth.py +126 -100
- package/server/services/cli_agent/__init__.py +78 -0
- package/server/services/cli_agent/_handlers.py +237 -0
- package/server/services/cli_agent/config.py +112 -0
- package/server/services/cli_agent/factory.py +48 -0
- package/server/services/cli_agent/lockfile.py +141 -0
- package/server/services/cli_agent/mcp_server.py +482 -0
- package/server/services/cli_agent/protocol.py +173 -0
- package/server/services/cli_agent/providers/__init__.py +9 -0
- package/server/services/cli_agent/providers/anthropic_claude.py +419 -0
- package/server/services/cli_agent/providers/google_gemini.py +80 -0
- package/server/services/cli_agent/providers/openai_codex.py +310 -0
- package/server/services/cli_agent/service.py +607 -0
- package/server/services/cli_agent/session.py +618 -0
- package/server/services/cli_agent/types.py +227 -0
- package/server/services/cli_agent/workflow_tools.py +233 -0
- package/server/services/credential_registry.py +26 -1
- package/server/services/deployment/manager.py +26 -145
- package/server/services/deployment/poll_registry.py +59 -0
- package/server/services/event_waiter.py +76 -246
- package/server/services/events/__init__.py +54 -0
- package/server/services/events/cli.py +78 -0
- package/server/services/events/daemon.py +163 -0
- package/server/services/events/envelope.py +281 -0
- package/server/services/events/lifecycle.py +99 -0
- package/server/services/events/oauth_lifecycle.py +534 -0
- package/server/services/events/polling.py +60 -0
- package/server/services/events/push.py +36 -0
- package/server/services/events/source.py +63 -0
- package/server/services/events/triggers.py +118 -0
- package/server/services/events/verifiers/__init__.py +25 -0
- package/server/services/events/verifiers/base.py +28 -0
- package/server/services/events/verifiers/github.py +25 -0
- package/server/services/events/verifiers/hmac_basic.py +32 -0
- package/server/services/events/verifiers/standard_webhooks.py +47 -0
- package/server/services/events/verifiers/stripe.py +42 -0
- package/server/services/events/webhook.py +105 -0
- package/server/services/handlers/tools.py +28 -186
- package/server/services/llm/config.py +7 -0
- package/server/services/llm/factory.py +8 -2
- package/server/services/memory/__init__.py +52 -0
- package/server/services/memory/jsonl.py +80 -0
- package/server/services/memory/markdown.py +65 -0
- package/server/services/memory/state.py +112 -0
- package/server/services/memory/vector_store.py +40 -0
- package/server/services/model_registry.py +76 -0
- package/server/services/node_allowlist.py +71 -15
- package/server/services/node_executor.py +2 -2
- package/server/services/node_output_schemas.py +21 -10
- package/server/services/node_spec.py +1 -1
- package/server/services/oauth_utils.py +1 -1
- package/server/services/plugin/__init__.py +2 -0
- package/server/services/plugin/base.py +44 -2
- package/server/services/plugin/credential.py +288 -1
- package/server/services/plugin/deps.py +105 -0
- package/server/services/plugin/edge_walker.py +12 -4
- package/server/services/plugin/oauth.py +381 -0
- package/server/services/plugin/polling.py +247 -0
- package/server/services/plugin/registry.py +145 -0
- package/server/services/plugin/singleton.py +65 -0
- package/server/services/plugin/ws.py +81 -0
- package/server/services/process_service.py +31 -2
- package/server/services/status_broadcaster.py +155 -238
- package/server/services/temporal/workflow.py +7 -7
- package/server/services/workflow.py +21 -3
- package/server/services/ws_handler_registry.py +111 -28
- package/server/skills/GUIDE.md +16 -1
- package/server/skills/assistant/agent-builder-skill/SKILL.md +166 -0
- package/server/skills/payments_agent/stripe-skill/SKILL.md +306 -0
- package/server/tests/credentials/test_auth_service.py +16 -9
- package/server/tests/credentials/test_credential_broadcasts.py +219 -0
- package/server/tests/credentials/test_google_oauth.py +6 -6
- package/server/tests/credentials/test_oauth_utils.py +1 -1
- package/server/tests/credentials/test_twitter_oauth.py +2 -2
- package/server/tests/credentials/test_websocket_handlers.py +44 -20
- package/server/tests/llm/test_factory.py +1 -0
- package/server/tests/llm/test_wiring.py +5 -1
- package/server/tests/nodes/_compat.py +24 -24
- package/server/tests/nodes/test_agent_builder.py +439 -0
- package/server/tests/nodes/test_ai_tools.py +18 -14
- package/server/tests/nodes/test_code_fs_process.py +17 -8
- package/server/tests/nodes/test_email.py +10 -9
- package/server/tests/nodes/test_google_workspace.py +2 -2
- package/server/tests/nodes/test_specialized_agents.py +100 -53
- package/server/tests/nodes/test_stripe_plugin.py +293 -0
- package/server/tests/nodes/test_telegram_social.py +4 -4
- package/server/tests/nodes/test_twitter.py +1 -1
- package/server/tests/nodes/test_web_automation.py +2 -2
- package/server/tests/nodes/test_whatsapp.py +9 -9
- package/server/tests/services/cli_agent/__init__.py +0 -0
- package/server/tests/services/cli_agent/test_mcp_server.py +432 -0
- package/server/tests/services/cli_agent/test_providers.py +358 -0
- package/server/tests/services/cli_agent/test_service.py +298 -0
- package/server/tests/services/memory/__init__.py +0 -0
- package/server/tests/services/memory/test_jsonl.py +188 -0
- package/server/tests/services/test_events.py +333 -0
- package/server/tests/test_node_spec.py +56 -16
- package/server/tests/test_plugin_helpers.py +116 -0
- package/server/tests/test_plugin_self_containment.py +486 -0
- package/server/tests/test_status_broadcasts.py +425 -0
- package/workflows/{AI Assistant_workflow-1777421105154-0m4snkzjf.json → AI Assistant_workflow-1778504793388-ou1m1tz2x.json } +70 -266
- package/workflows/{AI Employee_workflow-1777720598005-u4cm858dv.json → AI Employee_example_workflow-1777720598005-u4cm858dv.json } +112 -112
- package/workflows/Claude Assistant_workflow-1778380124051-mdibn807c.json +709 -0
- package/client/dist/assets/ActionBar-vzPpSR77.js +0 -1
- package/client/dist/assets/ApiKeyInput-Ds7AKFe8.js +0 -1
- package/client/dist/assets/ApiKeyPanel-gfblELep.js +0 -1
- package/client/dist/assets/ApiUsageSection-BMNWTe2r.js +0 -1
- package/client/dist/assets/EmailPanel-B1Om64p5.js +0 -1
- package/client/dist/assets/OAuthPanel-CXyQYGBz.js +0 -1
- package/client/dist/assets/QrPairingPanel-BgNuI1we.js +0 -1
- package/client/dist/assets/RateLimitSection-YYK8sx1T.js +0 -1
- package/client/dist/assets/StatusCard-DuYA5hJR.js +0 -1
- package/client/dist/assets/index-D9tZfgvi.js +0 -363
- package/client/dist/assets/index-al7snTkG.css +0 -1
- package/client/src/components/credentials/providers.tsx +0 -177
- package/server/routers/google.py +0 -277
- package/server/routers/maps.py +0 -142
- package/server/routers/twitter.py +0 -365
- package/server/services/claude_code_service.py +0 -106
- package/server/services/memory.py +0 -159
- package/server/services/node_option_loaders/__init__.py +0 -77
- package/server/services/node_option_loaders/android_loaders.py +0 -55
- package/server/services/node_option_loaders/google_loaders.py +0 -97
- package/server/services/node_option_loaders/whatsapp_loaders.py +0 -69
- package/server/services/twitter_oauth.py +0 -411
- package/server/services/websocket_client.py +0 -29
- /package/server/{services/android → nodes/android/_relay}/__init__.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/broadcaster.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/manager.py +0 -0
- /package/server/{services/android → nodes/android/_relay}/protocol.py +0 -0
- /package/server/{services/browser_service.py → nodes/browser/_service.py} +0 -0
- /package/server/{services/whatsapp_service.py → nodes/whatsapp/_service.py} +0 -0
- /package/server/skills/{task_agent → assistant}/write-todos-skill/SKILL.md +0 -0
|
@@ -1 +1,55 @@
|
|
|
1
|
-
"""Plugins for the 'google' palette group.
|
|
1
|
+
"""Plugins for the 'google' palette group.
|
|
2
|
+
|
|
3
|
+
Self-contained plugin folder (Wave 11.H pattern). One folder owns
|
|
4
|
+
the entire Google Workspace surface:
|
|
5
|
+
|
|
6
|
+
- 6 service plugins — ``gmail.py``, ``calendar.py``, ``drive.py``,
|
|
7
|
+
``sheets.py``, ``tasks.py``, ``contacts.py``, plus
|
|
8
|
+
``gmail_receive.py`` for the polling trigger.
|
|
9
|
+
- ``_credentials.py`` — :class:`GoogleCredential` (OAuth2). The
|
|
10
|
+
6 service plugins all reference this single credential class.
|
|
11
|
+
- ``_oauth.py`` — OAuth 2.0 client (formerly
|
|
12
|
+
``services/google_oauth.py``).
|
|
13
|
+
- ``_auth_helper.py`` — shared credential builder + proactive
|
|
14
|
+
refresh (formerly ``services/handlers/google_auth.py``). Used by
|
|
15
|
+
every Workspace plugin to obtain a refresh-aware ``Credentials``
|
|
16
|
+
object.
|
|
17
|
+
- ``_handlers.py`` — 3 WebSocket handlers
|
|
18
|
+
(``google_oauth_login`` / ``google_oauth_status`` /
|
|
19
|
+
``google_logout``).
|
|
20
|
+
- ``_router.py`` — HTTP OAuth callback (``/api/google/callback``).
|
|
21
|
+
|
|
22
|
+
Two self-registration calls below — the central WS dispatcher and
|
|
23
|
+
the FastAPI app pick up the plugin's surface without ever importing
|
|
24
|
+
this module by name.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from services.event_waiter import register_filter_builder
|
|
28
|
+
from services.status_broadcaster import register_service_refresh
|
|
29
|
+
from services.ws_handler_registry import (
|
|
30
|
+
register_option_loader,
|
|
31
|
+
register_router,
|
|
32
|
+
register_ws_handlers,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
from . import _router
|
|
36
|
+
from ._filters import build_gmail_filter
|
|
37
|
+
from ._handlers import WS_HANDLERS
|
|
38
|
+
from ._option_loaders import (
|
|
39
|
+
load_calendar_list,
|
|
40
|
+
load_drive_folders,
|
|
41
|
+
load_gmail_labels,
|
|
42
|
+
load_tasklists,
|
|
43
|
+
)
|
|
44
|
+
from ._refresh import refresh_google_status
|
|
45
|
+
|
|
46
|
+
register_ws_handlers(WS_HANDLERS)
|
|
47
|
+
register_router(_router.router, name="google")
|
|
48
|
+
register_service_refresh(refresh_google_status)
|
|
49
|
+
register_filter_builder("googleGmailReceive", build_gmail_filter)
|
|
50
|
+
|
|
51
|
+
# loadOptionsMethod loaders (Wave 11.I, milestone M.2).
|
|
52
|
+
register_option_loader("gmailLabels", load_gmail_labels)
|
|
53
|
+
register_option_loader("googleCalendarList", load_calendar_list)
|
|
54
|
+
register_option_loader("googleDriveFolders", load_drive_folders)
|
|
55
|
+
register_option_loader("googleTasklists", load_tasklists)
|
|
@@ -37,7 +37,7 @@ async def get_google_credentials(
|
|
|
37
37
|
Returns:
|
|
38
38
|
google.oauth2.credentials.Credentials ready for API use
|
|
39
39
|
"""
|
|
40
|
-
from
|
|
40
|
+
from services.plugin.deps import get_auth_service, get_database
|
|
41
41
|
|
|
42
42
|
account_mode = parameters.get('account_mode', 'owner')
|
|
43
43
|
customer_id = "owner"
|
|
@@ -47,7 +47,7 @@ async def get_google_credentials(
|
|
|
47
47
|
if not customer_id:
|
|
48
48
|
raise ValueError("customer_id required for customer mode")
|
|
49
49
|
|
|
50
|
-
db =
|
|
50
|
+
db = get_database()
|
|
51
51
|
connection = await db.get_google_connection(customer_id)
|
|
52
52
|
if not connection:
|
|
53
53
|
raise ValueError(f"No Google connection for customer: {customer_id}")
|
|
@@ -61,7 +61,7 @@ async def get_google_credentials(
|
|
|
61
61
|
await db.update_google_last_used(customer_id)
|
|
62
62
|
|
|
63
63
|
else:
|
|
64
|
-
auth_service =
|
|
64
|
+
auth_service = get_auth_service()
|
|
65
65
|
tokens = await auth_service.get_oauth_tokens("google", customer_id="owner")
|
|
66
66
|
|
|
67
67
|
if not tokens or not tokens.get("access_token"):
|
|
@@ -70,9 +70,12 @@ async def get_google_credentials(
|
|
|
70
70
|
)
|
|
71
71
|
|
|
72
72
|
access_token = tokens["access_token"]
|
|
73
|
-
refresh_token
|
|
73
|
+
# refresh_token is read from DB directly (RFC 9700; not cached).
|
|
74
|
+
refresh_token = await auth_service.get_oauth_refresh_token(
|
|
75
|
+
"google", customer_id="owner"
|
|
76
|
+
)
|
|
74
77
|
|
|
75
|
-
auth_service =
|
|
78
|
+
auth_service = get_auth_service()
|
|
76
79
|
client_id = await auth_service.get_api_key("google_client_id") or ""
|
|
77
80
|
client_secret = await auth_service.get_api_key("google_client_secret") or ""
|
|
78
81
|
|
|
@@ -59,12 +59,12 @@ async def track_google_usage(
|
|
|
59
59
|
``google_tasks`` / ``google_contacts``. Google APIs are free at our
|
|
60
60
|
tier — this is analytics bookkeeping, cost is $0.
|
|
61
61
|
"""
|
|
62
|
-
from
|
|
62
|
+
from services.plugin.deps import get_database
|
|
63
63
|
|
|
64
64
|
pricing = get_pricing_service()
|
|
65
65
|
cost_data = pricing.calculate_api_cost(service, action, resource_count)
|
|
66
66
|
|
|
67
|
-
db =
|
|
67
|
+
db = get_database()
|
|
68
68
|
await db.save_api_usage_metric({
|
|
69
69
|
'session_id': context.get('session_id', 'default'),
|
|
70
70
|
'node_id': node_id,
|
|
@@ -7,7 +7,7 @@ to hand to ``googleapiclient.discovery.build``), so :meth:`build_credentials`
|
|
|
7
7
|
returns that object instead of an httpx request.
|
|
8
8
|
|
|
9
9
|
OAuth flow (authorization_url / token_url / scopes) is owned by
|
|
10
|
-
:mod:`
|
|
10
|
+
:mod:`nodes.google._oauth`; this class is the plugin-facing interface
|
|
11
11
|
+ Credentials-modal metadata.
|
|
12
12
|
"""
|
|
13
13
|
|
|
@@ -30,7 +30,7 @@ class GoogleCredential(OAuth2Credential):
|
|
|
30
30
|
docs_url = "https://developers.google.com/workspace"
|
|
31
31
|
|
|
32
32
|
# Scope union across all 6 Google plugins. Single source of truth:
|
|
33
|
-
# :data:`
|
|
33
|
+
# :data:`nodes.google._oauth.GOOGLE_WORKSPACE_SCOPES`, exposed lazily
|
|
34
34
|
# to avoid import-cycle risk during credential auto-discovery.
|
|
35
35
|
scopes: ClassVar[tuple] = ()
|
|
36
36
|
|
|
@@ -38,7 +38,7 @@ class GoogleCredential(OAuth2Credential):
|
|
|
38
38
|
def get_scopes(cls) -> tuple:
|
|
39
39
|
"""Return the live scope list (lazy import)."""
|
|
40
40
|
if not cls.scopes:
|
|
41
|
-
from
|
|
41
|
+
from nodes.google._oauth import GOOGLE_WORKSPACE_SCOPES
|
|
42
42
|
cls.scopes = tuple(GOOGLE_WORKSPACE_SCOPES)
|
|
43
43
|
return cls.scopes
|
|
44
44
|
|
|
@@ -50,12 +50,12 @@ class GoogleCredential(OAuth2Credential):
|
|
|
50
50
|
):
|
|
51
51
|
"""Return a ``google.oauth2.credentials.Credentials`` object.
|
|
52
52
|
|
|
53
|
-
Thin wrapper over :func:`
|
|
53
|
+
Thin wrapper over :func:`nodes.google._auth_helper.get_google_credentials`
|
|
54
54
|
— the existing helper already handles owner-vs-customer token
|
|
55
55
|
sources + proactive refresh. Keeping the implementation there
|
|
56
56
|
(plus this indirection) means the plugin file's import surface
|
|
57
57
|
stays flat and there's a single place to evolve the refresh
|
|
58
58
|
policy.
|
|
59
59
|
"""
|
|
60
|
-
from
|
|
60
|
+
from nodes.google._auth_helper import get_google_credentials
|
|
61
61
|
return await get_google_credentials(parameters, context)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Gmail event-trigger filter builder (Wave 11.I, milestone K).
|
|
2
|
+
|
|
3
|
+
Moved verbatim from ``services/event_waiter.build_gmail_filter``.
|
|
4
|
+
``filter_query`` is applied at the Gmail API level during polling
|
|
5
|
+
(see :mod:`._polling`); this filter only checks labels for events
|
|
6
|
+
already on the bus.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Callable, Dict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_gmail_filter(params: Dict) -> Callable[[Dict], bool]:
|
|
15
|
+
"""Build filter function for Gmail email events."""
|
|
16
|
+
label_filter = params.get('label_filter', 'INBOX')
|
|
17
|
+
|
|
18
|
+
def matches(data: Dict) -> bool:
|
|
19
|
+
if label_filter and label_filter != 'all':
|
|
20
|
+
labels = data.get('labels', [])
|
|
21
|
+
if label_filter not in labels:
|
|
22
|
+
return False
|
|
23
|
+
return True
|
|
24
|
+
|
|
25
|
+
return matches
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Google Workspace WebSocket handlers — factory-built (Wave 11.I, S.2).
|
|
2
|
+
|
|
3
|
+
The 3 handlers (``google_oauth_login`` / ``google_oauth_status`` /
|
|
4
|
+
``google_logout``) come from
|
|
5
|
+
:func:`services.events.oauth_lifecycle.make_oauth_lifecycle_handlers`.
|
|
6
|
+
``legacy_status_broadcast="google_status"`` keeps the pre-S frontend
|
|
7
|
+
listeners happy by emitting the legacy wire-frame alongside the
|
|
8
|
+
unified credential-event broadcast.
|
|
9
|
+
|
|
10
|
+
The factory pulls ``google_client_id`` + ``google_client_secret`` from
|
|
11
|
+
``auth_service`` inside the async :func:`_google_oauth_factory` helper
|
|
12
|
+
and constructs a :class:`GoogleOAuth` per call.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Any, Dict, Optional
|
|
18
|
+
|
|
19
|
+
from services.events.oauth_lifecycle import make_oauth_lifecycle_handlers
|
|
20
|
+
|
|
21
|
+
from ._oauth import GoogleOAuth
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def _google_oauth_factory(
|
|
25
|
+
*, redirect_uri: Optional[str] = None, **_kwargs,
|
|
26
|
+
) -> GoogleOAuth:
|
|
27
|
+
"""Build a :class:`GoogleOAuth` from stored client credentials."""
|
|
28
|
+
from services.plugin.deps import get_auth_service
|
|
29
|
+
|
|
30
|
+
auth_service = get_auth_service()
|
|
31
|
+
client_id = await auth_service.get_api_key("google_client_id") or ""
|
|
32
|
+
client_secret = await auth_service.get_api_key("google_client_secret") or ""
|
|
33
|
+
return GoogleOAuth(
|
|
34
|
+
client_id=client_id,
|
|
35
|
+
client_secret=client_secret,
|
|
36
|
+
redirect_uri=redirect_uri or "",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _user_info_to_email(info: Dict[str, Any]) -> str:
|
|
41
|
+
return info.get("email", "Unknown") or "Unknown"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
WS_HANDLERS = make_oauth_lifecycle_handlers(
|
|
45
|
+
provider="google",
|
|
46
|
+
oauth_factory=_google_oauth_factory,
|
|
47
|
+
user_info_to_subject=_user_info_to_email,
|
|
48
|
+
legacy_status_broadcast="google_status",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Module-level aliases so the contract tests in
|
|
53
|
+
# ``tests/credentials/test_websocket_handlers.py`` can import the
|
|
54
|
+
# handlers by name.
|
|
55
|
+
handle_google_oauth_login = WS_HANDLERS["google_oauth_login"]
|
|
56
|
+
handle_google_oauth_status = WS_HANDLERS["google_oauth_status"]
|
|
57
|
+
handle_google_logout = WS_HANDLERS["google_logout"]
|