diff --git a/docs.json b/docs.json index c0601197..ee55ad48 100644 --- a/docs.json +++ b/docs.json @@ -309,7 +309,8 @@ "group": "Development Guides", "pages": [ "plugin-dev-en/0432-develop-a-slack-bot-plugin", - "plugin-dev-en/0432-endpoint" + "plugin-dev-en/0432-endpoint", + "plugin-dev-en/0432-develop-flomo-plugin" ] }, { diff --git a/plugin-dev-en/0432-develop-flomo-plugin.mdx b/plugin-dev-en/0432-develop-flomo-plugin.mdx new file mode 100644 index 00000000..0994e812 --- /dev/null +++ b/plugin-dev-en/0432-develop-flomo-plugin.mdx @@ -0,0 +1,334 @@ +--- +title: '10-Minute Guide to Building Dify Plugins' +description: 'Learn how to build a functional Dify plugin that connects with Flomo note-taking service in just 10 minutes' +language: en +standard_title: 10-Minute Guide to Building Dify Plugins +--- + +## What you'll build + +By the end of this guide, you'll have created a Dify plugin that: + +- Connects to the Flomo note-taking API +- Allows users to save notes from AI conversations directly to Flomo +- Handles authentication and error states properly +- Is ready for distribution in the Dify Marketplace + + + + 10 minutes + + + Basic Python knowledge and a Flomo account + + + +## Step 1: Install the Dify CLI and create a project + + + + + + ```bash + brew tap langgenius/dify + brew install dify + ``` + + + Get the latest Dify CLI from the [Dify GitHub releases page](https://github.com/langgenius/dify-plugin-daemon/releases) + + ```bash + # Download appropriate version + chmod +x dify-plugin-linux-amd64 + mv dify-plugin-linux-amd64 dify + sudo mv dify /usr/local/bin/ + ``` + + + + Verify installation: + ```bash + dify version + ``` + + + + Create a new plugin project using: + + ```bash + dify plugin init + ``` + + Follow the prompts to set up your plugin: + - Name it "flomo" + - Select "tool" as the plugin type + - Complete other required fields + + + + ```bash + cd flomo + ``` + + This will create the basic structure for your plugin with all necessary files. + + + +## Step 2: Define your plugin manifest + + +The manifest.yaml file defines your plugin's metadata, permissions, and capabilities. + + +Create a `manifest.yaml` file: + +```yaml +version: 0.0.4 +type: plugin +author: yourname +label: + en_US: Flomo + zh_Hans: Flomo 浮墨笔记 +created_at: "2023-10-01T00:00:00Z" +icon: icon.png + +resource: + memory: 67108864 # 64MB + permission: + storage: + enabled: false + +plugins: + tools: + - flomo.yaml + +meta: + version: 0.0.1 + arch: + - amd64 + - arm64 + runner: + language: python + version: 3.12 + entrypoint: main +``` + +## Step 3: Create the tool definition + +Create a `flomo.yaml` file to define your tool interface: + +```yaml +identity: + author: yourname + name: flomo + label: + en_US: Flomo Note + zh_Hans: Flomo 浮墨笔记 +description: + human: + en_US: Add notes to your Flomo account directly from Dify. + zh_Hans: 直接从Dify添加笔记到您的Flomo账户。 + llm: > + A tool that allows users to save notes to Flomo. Use this tool when users want to save important information from the conversation. The tool accepts a 'content' parameter that contains the text to be saved as a note. +credential_schema: + api_url: + type: string + required: true + label: + en_US: API URL + zh_Hans: API URL + human_description: + en_US: Flomo API URL from your Flomo account settings. + zh_Hans: 从您的Flomo账户设置中获取的API URL。 +tool_schema: + content: + type: string + required: true + label: + en_US: Note Content + zh_Hans: 笔记内容 + human_description: + en_US: Content to save as a note in Flomo. + zh_Hans: 要保存为Flomo笔记的内容。 +``` + +## Step 4: Implement core utility functions + +Create a utility module in `utils/flomo_utils.py` for API interaction: + + +```python utils/flomo_utils.py +import requests + +def send_flomo_note(api_url: str, content: str) -> None: + """ + Send a note to Flomo via the API URL. Raises requests.RequestException on network errors, + and ValueError on invalid status codes or input. + """ + api_url = api_url.strip() + if not api_url: + raise ValueError("API URL is required and cannot be empty.") + if not api_url.startswith('https://flomoapp.com/iwh/'): + raise ValueError( + "API URL should be in the format: https://flomoapp.com/iwh/{token}/{secret}/" + ) + if not content: + raise ValueError("Content cannot be empty.") + + headers = {'Content-Type': 'application/json'} + response = requests.post(api_url, json={"content": content}, headers=headers, timeout=10) + + if response.status_code != 200: + raise ValueError(f"API URL is not valid. Received status code: {response.status_code}") +``` + + +## Step 5: Implement the Tool Provider + +The Tool Provider handles credential validation. Create `provider/flomo.py`: + + +```python provider/flomo.py +from typing import Any +from dify_plugin import ToolProvider +from dify_plugin.errors.tool import ToolProviderCredentialValidationError +import requests +from utils.flomo_utils import send_flomo_note + +class FlomoProvider(ToolProvider): + def _validate_credentials(self, credentials: dict[str, Any]) -> None: + try: + api_url = credentials.get('api_url', '').strip() + # Use utility for validation and sending test note + send_flomo_note(api_url, "Hello, #flomo https://flomoapp.com") + except ValueError as e: + raise ToolProviderCredentialValidationError(str(e)) + except requests.RequestException as e: + raise ToolProviderCredentialValidationError(f"Connection error: {str(e)}") +``` + + +## Step 6: Implement the Tool + +The Tool class handles actual API calls when the user invokes the plugin. Create `tools/flomo.py`: + + +```python tools/flomo.py +from collections.abc import Generator +from typing import Any +from dify_plugin import Tool +from dify_plugin.entities.tool import ToolInvokeMessage +import requests +from utils.flomo_utils import send_flomo_note + +class FlomoTool(Tool): + def _invoke(self, tool_parameters: dict[str, Any]) -> Generator[ToolInvokeMessage]: + content = tool_parameters.get("content", "") + api_url = self.runtime.credentials.get("api_url", "") + + try: + send_flomo_note(api_url, content) + except ValueError as e: + yield self.create_text_message(str(e)) + return + except requests.RequestException as e: + yield self.create_text_message(f"Connection error: {str(e)}") + return + + # Return success message and structured data + yield self.create_text_message( + "Note created successfully! Your content has been sent to Flomo." + ) + yield self.create_json_message({ + "status": "success", + "content": content, + }) +``` + + + +Always handle exceptions gracefully and return user-friendly error messages. Remember that your plugin represents your brand in the Dify ecosystem. + + +## Step 7: Test your plugin + + + + Copy the example environment file: + ```bash + cp .env.example .env + ``` + + Edit the `.env` file with your Dify environment details: + ``` + INSTALL_METHOD=remote + REMOTE_INSTALL_HOST=debug-plugin.dify.dev + REMOTE_INSTALL_PORT=5003 + REMOTE_INSTALL_KEY=your_debug_key + ``` + + You can find your debug key and host in the Dify dashboard: click the "Plugins" icon in the top right corner, then click the debug icon. In the pop-up window, copy the "API Key" and "Host Address". + + + + ```bash + pip install -r requirements.txt + python -m main + ``` + + Your plugin will connect to your Dify instance in debug mode. + + + + In your Dify instance, navigate to plugins and find your debugging plugin (marked as "debugging"). + Add your Flomo API credentials and test sending a note. + + + +## Step 9: Package and distribute + +When you're ready to share your plugin: + +```bash +dify plugin package ./ +``` + +This creates a `plugin.difypkg` file you can upload to the Dify Marketplace. + +## Next steps + + + + Consider adding hashtag support, note search, or other Flomo API features + + + Add more detailed error states and recovery flows + + + Configure GitHub Actions for automated package and PR creation + + + + + + Make sure your `.env` file is properly configured and you're using the correct debug key. + + + + Double-check your Flomo API URL format. It should be in the form: `https://flomoapp.com/iwh/{token}/{secret}/` + + + + Ensure all required files are present and the manifest.yaml structure is valid. + + + +## Summary + +You've built a functioning Dify plugin that connects with an external API service! This same pattern works for integrating with thousands of services - from databases and search engines to productivity tools and custom APIs. + + +Remember to add a privacy policy if you plan to publish your plugin. You can create a simple PRIVACY.md file referencing Flomo's privacy policy. +Remember to write the README.md file in English (en_US) to describe your plugin's functionality, setup instructions, and usage examples. +For other languages, you can create additional README files like `readme/README_zh_Hans.md` for Simplified Chinese. +