Merge pull request #760 from Molecule-AI/refactor/issue-741-extract-medo-plugin
refactor(#741): extract medo.py from builtin_tools to opt-in plugin
This commit is contained in:
commit
7e711a810d
4
.gitignore
vendored
4
.gitignore
vendored
@ -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/
|
||||
|
||||
6
plugins/molecule-medo/plugin.yaml
Normal file
6
plugins/molecule-medo/plugin.yaml
Normal file
@ -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]
|
||||
27
plugins/molecule-medo/skills/medo-tools/SKILL.md
Normal file
27
plugins/molecule-medo/skills/medo-tools/SKILL.md
Normal file
@ -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.
|
||||
@ -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:
|
||||
21
plugins/molecule-medo/tests/conftest.py
Normal file
21
plugins/molecule-medo/tests/conftest.py
Normal file
@ -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()
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user