#!/usr/bin/env python3 """Create a reviewed command-extension skeleton without runtime privileges.""" from __future__ import annotations import argparse import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] sys.path[:0] = [ str(ROOT / "packages" / "jwebot-sdk" / "src"), str(ROOT / "packages" / "jwebot-kernel" / "src"), ] from jwebot_kernel import ManifestError, parse_manifest # noqa: E402 def module_name(plugin_id: str) -> str: return plugin_id.replace("-", "_") def manifest_text( plugin_id: str, command: str, author: str, description: str, help_entry: str, ) -> str: module = module_name(plugin_id) return f"""id = "{plugin_id}" author = "{author}" description = {json.dumps(description, ensure_ascii=False)} help = [{json.dumps(help_entry, ensure_ascii=False)}] version = "1.0.0" api_version = "1" entrypoint = "{module}:plugin" type = "command" [capabilities] commands = ["{command}"] storage = false network_profiles = [] service_profiles = [] """ def module_text(plugin_id: str, command: str) -> str: return f'''"""Command extension: {plugin_id}.""" from jwebot_sdk import Event, ExtensionResult, ReplyPlan, SingleGroupContext def handle(event: Event, arguments: str) -> ExtensionResult: del event, arguments return ExtensionResult(reply=ReplyPlan.text("TODO")) def plugin(context: SingleGroupContext) -> None: context.commands.register("{command}", handle) ''' def test_text(plugin_id: str) -> str: module = module_name(plugin_id) return f'''import sys import unittest from pathlib import Path SOURCE = Path(__file__).resolve().parents[1] / "src" sys.path.insert(0, str(SOURCE)) from jwebot_sdk import Event, PlanKind from {module} import handle class PluginTests(unittest.TestCase): def test_command_returns_a_structured_reply(self): event = Event( event_id="event-1", observed_at="2026-01-01T00:00:00+08:00", sender="tester", text="@JWeBot test", group_fingerprint="group-test", mention_bot=True, ) result = handle(event, "") self.assertEqual(result.reply.kind, PlanKind.TEXT) if __name__ == "__main__": unittest.main() ''' def readme_text( plugin_id: str, command: str, author: str, description: str, help_entry: str, ) -> str: return f"""# {plugin_id} Author: `{author}` {description} Command: `{command}` Help: `{help_entry}` This extension may return structured JWeBot SDK results only. It must not use GUI automation, raw storage, environment variables, subprocesses, SSH, Docker, or unrestricted network access. """ def validate_inputs( plugin_id: str, command: str, author: str, description: str, help_entry: str, ) -> None: parse_manifest( { "id": plugin_id, "author": author, "description": description, "help": [help_entry], "version": "1.0.0", "api_version": "1", "entrypoint": f"{module_name(plugin_id)}:plugin", "type": "command", "capabilities": { "commands": [command], "storage": False, "network_profiles": [], }, } ) def create_plugin( output: Path, plugin_id: str, command: str, author: str, description: str, help_entry: str | None = None, ) -> Path: help_entry = help_entry or command validate_inputs( plugin_id, command, author, description, help_entry, ) destination = output / plugin_id if destination.exists(): raise FileExistsError(f"destination already exists: {destination}") source = destination / "src" tests = destination / "tests" source.mkdir(parents=True) tests.mkdir() module = module_name(plugin_id) (destination / "plugin.toml").write_text( manifest_text( plugin_id, command, author, description, help_entry, ), encoding="utf-8", ) (source / f"{module}.py").write_text( module_text(plugin_id, command), encoding="utf-8", ) (tests / "test_plugin.py").write_text( test_text(plugin_id), encoding="utf-8", ) (destination / "README.md").write_text( readme_text( plugin_id, command, author, description, help_entry, ), encoding="utf-8", ) return destination def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("plugin_id") parser.add_argument("command") parser.add_argument("--author", required=True) parser.add_argument("--description", required=True) parser.add_argument("--help-entry") parser.add_argument( "--output", type=Path, default=ROOT / "extensions" / "friends", ) args = parser.parse_args() try: destination = create_plugin( args.output, args.plugin_id, args.command, args.author, args.description, args.help_entry, ) except (ManifestError, FileExistsError) as error: parser.error(str(error)) print(destination) return 0 if __name__ == "__main__": raise SystemExit(main())