diff --git a/.gitignore b/.gitignore index a3a4a2a1..a5374468 100644 --- a/.gitignore +++ b/.gitignore @@ -125,5 +125,7 @@ org-templates/**/.auth-token # Cloned-via-manifest dirs — populated locally by scripts/clone-manifest.sh, # tracked in their own standalone repos. Never commit to core. /org-templates/ -/plugins/ +/plugins/* +# Exception: molecule-medo lives here until it gets its own standalone repo. +!/plugins/molecule-medo/ /workspace-configs-templates/ diff --git a/plugins/molecule-medo/plugin.yaml b/plugins/molecule-medo/plugin.yaml new file mode 100644 index 00000000..74adce13 --- /dev/null +++ b/plugins/molecule-medo/plugin.yaml @@ -0,0 +1,6 @@ +name: molecule-medo +version: 0.1.0 +description: Baidu MeDo no-code AI platform integration (hackathon / China-region) +author: Molecule AI +tags: [hackathon, baidu, medo, china] +runtimes: [claude_code, deepagents, langgraph] diff --git a/plugins/molecule-medo/skills/medo-tools/SKILL.md b/plugins/molecule-medo/skills/medo-tools/SKILL.md new file mode 100644 index 00000000..a8fdd8c8 --- /dev/null +++ b/plugins/molecule-medo/skills/medo-tools/SKILL.md @@ -0,0 +1,27 @@ +--- +name: MeDo Tools +description: > + Create, update, and publish applications on Baidu MeDo (摩搭), a no-code AI + application builder. Used in the Molecule AI hackathon integration (May 2026). +tags: [hackathon, baidu, medo, china, no-code] +examples: + - "Create a chatbot app on MeDo called 'Customer Support'" + - "Update the content of my MeDo app abc123" + - "Publish my MeDo app to production" +--- + +# MeDo Tools + +Provides three tools for interacting with the Baidu MeDo no-code platform: + +- **create_medo_app** — Scaffold a new application from a template (blank, chatbot, form, dashboard). +- **update_medo_app** — Push content or configuration changes to an existing application. +- **publish_medo_app** — Publish a draft application to production or staging. + +## Setup + +Set `MEDO_API_KEY` as a workspace secret. Optionally override the base URL via `MEDO_BASE_URL` +(default: `https://api.moda.baidu.com/v1`). + +When `MEDO_API_KEY` is absent the tools run in mock mode and return stub responses — safe for +local development and testing. diff --git a/workspace-template/builtin_tools/medo.py b/plugins/molecule-medo/skills/medo-tools/scripts/medo.py similarity index 98% rename from workspace-template/builtin_tools/medo.py rename to plugins/molecule-medo/skills/medo-tools/scripts/medo.py index 0c824f91..ddf53271 100644 --- a/workspace-template/builtin_tools/medo.py +++ b/plugins/molecule-medo/skills/medo-tools/scripts/medo.py @@ -1,4 +1,4 @@ -"""MeDo builtin tools — Baidu MeDo no-code AI platform integration. +"""MeDo tools — Baidu MeDo no-code AI platform integration. MeDo (摩搭, moda.baidu.com) is Baidu's no-code AI application builder used in the Molecule AI hackathon integration (May 2026). Three core operations: diff --git a/plugins/molecule-medo/tests/conftest.py b/plugins/molecule-medo/tests/conftest.py new file mode 100644 index 00000000..413c2298 --- /dev/null +++ b/plugins/molecule-medo/tests/conftest.py @@ -0,0 +1,21 @@ +"""Minimal conftest for molecule-medo plugin tests. + +langchain_core is a declared dependency of workspace-template (>=0.3.0) and +is expected to be present in the test environment. If it is absent, mock it +so the @tool decorator in medo.py is a no-op and the tests can still run. +""" + +import sys +from types import ModuleType + + +def _mock_langchain_if_missing(): + if "langchain_core" not in sys.modules: + lc_mod = ModuleType("langchain_core") + lc_tools_mod = ModuleType("langchain_core.tools") + lc_tools_mod.tool = lambda f: f # @tool becomes identity decorator + sys.modules["langchain_core"] = lc_mod + sys.modules["langchain_core.tools"] = lc_tools_mod + + +_mock_langchain_if_missing() diff --git a/workspace-template/tests/test_medo.py b/plugins/molecule-medo/tests/test_medo.py similarity index 73% rename from workspace-template/tests/test_medo.py rename to plugins/molecule-medo/tests/test_medo.py index 1dfe09b1..301e8d7b 100644 --- a/workspace-template/tests/test_medo.py +++ b/plugins/molecule-medo/tests/test_medo.py @@ -1,16 +1,11 @@ -"""Tests for workspace-template/builtin_tools/medo.py. +"""Tests for plugins/molecule-medo/skills/medo-tools/scripts/medo.py. All tests exercise the mock backend (no MEDO_API_KEY required). -NOTE: conftest.py mocks builtin_tools with __path__=[] and mocks -langchain_core.tools.tool as a no-op (lambda f: f) so adapters can be -imported without heavy deps. Consequence: direct package import of -builtin_tools.medo is blocked (empty __path__ prevents filesystem -lookup), and @tool returns the raw async function rather than a LangChain -StructuredTool — so .ainvoke() is unavailable. - -Fix: load medo.py via importlib (bypasses the mock package root) and -call functions directly, not via .ainvoke(). +NOTE: @tool is a LangChain decorator that returns a StructuredTool rather than +the raw async function. conftest.py mocks langchain_core.tools.tool as an +identity decorator so that calling the functions directly (without .ainvoke()) +works in tests — matching the original test approach. """ import importlib.util @@ -19,14 +14,15 @@ from pathlib import Path import pytest -ROOT = Path(__file__).resolve().parents[1] -_MEDO_PATH = ROOT / "builtin_tools" / "medo.py" +# plugin root: plugins/molecule-medo/ +_PLUGIN_ROOT = Path(__file__).resolve().parents[1] +_MEDO_PATH = _PLUGIN_ROOT / "skills" / "medo-tools" / "scripts" / "medo.py" def _load_medo(): - spec = importlib.util.spec_from_file_location("builtin_tools.medo", _MEDO_PATH) + spec = importlib.util.spec_from_file_location("medo_plugin_tools", _MEDO_PATH) mod = importlib.util.module_from_spec(spec) - sys.modules["builtin_tools.medo"] = mod # register before exec to handle self-refs + sys.modules["medo_plugin_tools"] = mod # register before exec to handle self-refs spec.loader.exec_module(mod) return mod