molecule-core/workspace-template/plugins_registry/raw_drop.py
Hongming Wang 24fec62d7f initial commit — Molecule AI platform
Forked clean from public hackathon repo (Starfire-AgentTeam, BSL 1.1)
with full rebrand to Molecule AI under github.com/Molecule-AI/molecule-monorepo.

Brand: Starfire → Molecule AI.
Slug: starfire / agent-molecule → molecule.
Env vars: STARFIRE_* → MOLECULE_*.
Go module: github.com/agent-molecule/platform → github.com/Molecule-AI/molecule-monorepo/platform.
Python packages: starfire_plugin → molecule_plugin, starfire_agent → molecule_agent.
DB: agentmolecule → molecule.

History truncated; see public repo for prior commits and contributor
attribution. Verified green: go test -race ./... (platform), pytest
(workspace-template 1129 + sdk 132), vitest (canvas 352), build (mcp).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:55:37 -07:00

72 lines
2.5 KiB
Python

"""Fallback adaptor used when no per-runtime adaptor is found.
Behaviour: copy the plugin's content into ``/configs/plugins/<name>/`` so a
user can still inspect or hand-wire it, then surface a warning that no tools
or sub-agents were registered.
This preserves the "power users can drop raw files" escape hatch without
silently breaking — the warning is propagated up via :class:`InstallResult`
so the API can surface it to the user.
"""
from __future__ import annotations
import shutil
from .protocol import InstallContext, InstallResult, PluginAdaptor
class RawDropAdaptor:
"""Filesystem-only fallback. Implements :class:`PluginAdaptor`."""
def __init__(self, plugin_name: str, runtime: str) -> None:
self.plugin_name = plugin_name
self.runtime = runtime
async def install(self, ctx: InstallContext) -> InstallResult:
dst = ctx.configs_dir / "plugins" / self.plugin_name
files_written: list[str] = []
if ctx.plugin_root.exists() and ctx.plugin_root.is_dir():
dst.parent.mkdir(parents=True, exist_ok=True)
if dst.exists():
# Idempotent — leave existing copy alone.
ctx.logger.info(
"raw_drop: %s already present at %s, skipping copy",
self.plugin_name, dst,
)
else:
shutil.copytree(ctx.plugin_root, dst)
for p in dst.rglob("*"):
if p.is_file():
files_written.append(str(p.relative_to(ctx.configs_dir)))
ctx.logger.info(
"raw_drop: copied %s%s (%d files)",
self.plugin_name, dst, len(files_written),
)
warning = (
f"plugin '{self.plugin_name}' has no adaptor for runtime "
f"'{self.runtime}' — files dropped at /configs/plugins/{self.plugin_name} "
f"but no tools/sub-agents were wired in"
)
ctx.logger.warning(warning)
return InstallResult(
plugin_name=self.plugin_name,
runtime=self.runtime,
source="raw_drop",
files_written=files_written,
warnings=[warning],
)
async def uninstall(self, ctx: InstallContext) -> None:
dst = ctx.configs_dir / "plugins" / self.plugin_name
if dst.exists():
shutil.rmtree(dst)
ctx.logger.info("raw_drop: removed %s", dst)
# Static check: RawDropAdaptor satisfies PluginAdaptor.
_: PluginAdaptor = RawDropAdaptor("_", "_")