Skip to content

New: add Moyu AI model provider plugin v0.0.1 (FDQ-shrimp/moyu_ai_provider)#2313

Open
FDQ-shrimp wants to merge 14 commits into
langgenius:mainfrom
FDQ-shrimp:main
Open

New: add Moyu AI model provider plugin v0.0.1 (FDQ-shrimp/moyu_ai_provider)#2313
FDQ-shrimp wants to merge 14 commits into
langgenius:mainfrom
FDQ-shrimp:main

Conversation

@FDQ-shrimp
Copy link
Copy Markdown

Plugin Submission Form

1. Metadata

2. Submission Type

  • New plugin submission
  • Version update for existing plugin

3. Description

Moyu AI (moyu.ai) is a third-party LLM aggregation platform that exposes an
OpenAI-compatible chat/completions endpoint. This plugin packages that
platform as a Dify Model Provider so Dify users can plug in a Moyu AI
API key and call the full catalogue of 119 upstream text models
(OpenAI / Anthropic / Google / DeepSeek / Qwen / Kimi / Grok / …) from any
LLM node, chatflow or agent.

Key facts

  • Type: Model Provider plugin (model.llm enabled, OpenAI-compat adapter)
  • Author: community developer — not officially operated by Moyu AI
  • Credentials: a single api_key entered in the Dify UI (secret-input),
    never hard-coded in the package
  • Models: 119 predefined LLM YAMLs, generated directly from Moyu AI's
    /v1/models endpoint so label names match upstream exactly
  • Endpoint: https://api.moyu.ai/v1 (OpenAI-compatible chat/completions)
  • Dependencies: dify_plugin, requests, pyyaml only — openai SDK is
    intentionally not required (the Dify OAI-compat base class is used)
  • Package size: ~213 KB (135 entries, leak-free — scripts/tests/docs/.env
    excluded via .difyignore)

Availability report (transparency)

With the API key used for testing, 76 / 119 models returned 200 OK, and
43 returned errors that come from upstream policy — mostly HTTP 429 (rate
limit on the test key) or HTTP 400 (image / video / TTS models that do not
speak the chat/completions protocol). These 43 YAMLs are intentionally
kept in the plugin because availability depends on the user's own
account tier and quota, not on the plugin code. A human-readable breakdown
lives inside the source repo at docs/MODEL_AVAILABILITY.md.

Relation to Moyu AI

This is a community integration. The plugin talks to Moyu AI's public
OpenAI-compatible API; users must sign up at moyu.ai and supply their own
API key. No Moyu AI credential or debug token is bundled in the package.

4. Checklist

  • I have read and followed the Publish to Dify Marketplace guidelines
  • I have read and comply with the Plugin Developer Agreement
  • I confirm my plugin works properly on both Dify Community Edition and Cloud Version
  • I confirm my plugin has been thoroughly tested for completeness and functionality
  • My plugin brings new value to Dify

5. Documentation Checklist

Please confirm that your plugin README includes all necessary information:

  • Step-by-step setup instructions
  • Detailed usage instructions
  • All required APIs and credentials are clearly listed
  • Connection requirements and configuration details
  • Link to the repository for the plugin source code

6. Privacy Protection Information

Based on Dify Plugin Privacy Protection
Guidelines:

Data Collection

The plugin itself does not collect any personal data. Its only job is
to relay the chat messages that a Dify user explicitly sends to the Moyu
AI API, together with the user's API key taken from Dify's encrypted
credential storage.

However, because the plugin forwards traffic to a third-party service
(Moyu AI), the following data is unavoidably transmitted to that upstream:

  • The API key the user configures in Dify (sent as the Authorization: Bearer … header, per OpenAI convention).
  • The chat messages / prompts that the user sends from a Dify LLM node
    or agent. These may contain whatever content the user decides to put in
    the prompt, including — depending on the user's own use case — personal
    or business data.
  • Standard HTTP metadata (User-Agent, timestamps, IP of the Dify runtime
    that forwards the request).

No analytics, telemetry, third-party trackers, or external logging are
added by the plugin. The plugin does not persist any of the above on its
own side; everything happens in-memory during a single request.

For Moyu AI's own data handling practices, users should consult the Moyu
AI Terms of Service and Privacy Policy directly on their website.

The full privacy statement (including what is collected, how it is used,
and what is not collected) is included in the plugin package as
privacy.md.

Privacy Policy

  • I confirm that I have prepared and included a privacy policy in my plugin package based on the Plugin Privacy Protection Guidelines

@FDQ-shrimp
Copy link
Copy Markdown
Author

Follow-up: rebuilt v0.0.1 with lowercase author: fdq-shrimp in manifest.yaml so the plugin_unique_identifier passes Dify Plugin Daemon validation (uppercase letters in the identifier were rejected with PluginDaemonBadRequestError).

Folder renamed accordingly: FDQ-shrimp/fdq-shrimp/. Verified the new package installs cleanly in a self-hosted Dify, Moyu AI provider appears, and a live LLM call against GPT-4o returns SUCCESS (3.47s, 21 tokens). Source repo also updated: https://github.com/FDQ-shrimp/moyu_ai_provider (commit on main).

Package SHA changed; PR diff now contains fdq-shrimp/moyu_ai_provider/moyu_ai_provider-0.0.1.difypkg.

@FDQ-shrimp
Copy link
Copy Markdown
Author

Update: lowercase author fix (v0.0.1 rebuilt)

Rebuilt v0.0.1 to satisfy Dify Plugin Daemon's plugin_unique_identifier format (uppercase letters were rejected with PluginDaemonBadRequestError). Changes:

  • manifest.yaml: author: FDQ-shrimpauthor: fdq-shrimp
  • PR folder: FDQ-shrimp/moyu_ai_provider/fdq-shrimp/moyu_ai_provider/
  • Source repo (https://github.com/FDQ-shrimp/moyu_ai_provider) updated accordingly
  • Net diff remains 2 files (.gitkeep + moyu_ai_provider-0.0.1.difypkg, ~209 KB)

Verified locally

Installed the rebuilt .difypkg on self-hosted Dify:

  • Provider card "魔芋AI 0.0.1" appears in Model Provider list
  • API key saved via the UI (secret-input only; no hard-coded credentials in the package)
  • All 119 predefined models listed
  • LLM node test on GPT-4o: SUCCESS (3.47s, 21 tokens, Pong! response)
  • model_provider in runtime = fdq-shrimp/moyu_ai_provider/moyu

@FDQ-shrimp
Copy link
Copy Markdown
Author

Update: removed .gitkeep, so the PR now changes exactly one file: fdq-shrimp/moyu_ai_provider/moyu_ai_provider-0.0.1.difypkg.

The package is the rebuilt v0.0.1 with lowercase author: fdq-shrimp, verified locally in Dify.

Copy link
Copy Markdown
Member

@crazywoola crazywoola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Results

Check Status Required Action
single_difypkg ✅ pass None
pr_language ✅ pass None
checkout_pr ✅ pass None
manifest ✅ pass None
icon ✅ pass None
version_exists ✅ pass None
readme_language ❌ no pass Use English README or follow multilingual README guidance.
dify_plugin_version ✅ pass None

Next steps

Please address the failing checks and push fixes.

For README language guidelines: https://docs.dify.ai/en/develop-plugin/features-and-specs/plugin-types/multilingual-readme#multilingual-readme

…rified models

Fix readme_language CI failure by removing all Chinese characters from README.md.
Rebuild package with only 81 probe-verified models (removed 42 unavailable, added 4 newly confirmed).
Package contents are unchanged: 81 probe-verified model YAMLs and English README. Rebuilt the difypkg to trigger a fresh pull_request synchronize check after the previous manual rerun failed before detecting PLUGIN_PATH.

Made-with: Cursor
@FDQ-shrimp
Copy link
Copy Markdown
Author

Hi maintainers, I have pushed a rebuilt package for moyu_ai_provider v0.0.1. The workflow is currently awaiting maintainer approval. Could you please approve and rerun the pre-check when convenient? Thank you!

Copy link
Copy Markdown
Member

@crazywoola crazywoola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Request Changes

Decision: Request changes

Failed Checks

Check Status Detail
Install test ❌ Fail Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6…

Full Check Results

Check Status Detail
PR content language ✅ Pass PR title/body CJK ratio=0.0% (zh=0, en=3938, ignored_zh=0, allowed_zh<=0)
Project structure ✅ Pass All expected files present: manifest.yaml, README.md, PRIVACY.md. _assets/: yes.
Manifest author ✅ Pass author is valid.
Icon validation ✅ Pass icon exists: _assets/icon.png
Version check ✅ Pass version 0.0.1 is available.
README language ✅ Pass README.md CJK ratio=0.0% (zh=0, en=5321, allowed_zh<=0)
PRIVACY.md ✅ Pass PRIVACY.md exists and is non-empty.
Dependency install ✅ Pass requirements installed successfully.
dify_plugin version ✅ Pass dify_plugin version 0.7.4 satisfies >= 0.5.0.
Install test ❌ Fail Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6…
Packaging test ✅ Pass packaging check passed.

Required Fixes

  • Install test: Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-sv1obnsf/unpacked_plugin
    ERROR:root:code for hash blake2b was not found.
    Traceback (most recent call last):
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 245, in
    globals()[__func_name] = __get_hash(__func_name)
    ^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 129, in __get_openssl_constructor
    return __get_builtin_constructor(name)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 123, in __get_builtin_constructor
    raise ValueError('unsupported hash type ' + name)
    ValueError: unsupported hash type blake2b
    ERROR:root:code for hash blake2s was not found.
    Traceback (most recent call last):
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 245, in
    globals()[__func_name] = __get_hash(__func_name)
    ^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 129, in __get_openssl_constructor
    return __get_builtin_constructor(name)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py", line 123, in __get_builtin_constructor
    raise ValueError('unsupported hash type ' + name)
    ValueError: unsupported hash type blake2s

Please address these issues and push an update.

Copy link
Copy Markdown
Member

@crazywoola crazywoola left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Request Changes

Decision: Request changes

Failed Checks

Check Status Detail
Install test ❌ Fail Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6…

Full Check Results

Check Status Detail
PR content language ✅ Pass PR title/body CJK ratio=0.0% (zh=0, en=3938, ignored_zh=0, allowed_zh<=0)
Project structure ✅ Pass All expected files present: manifest.yaml, README.md, PRIVACY.md. _assets/: yes.
Manifest author ✅ Pass author is valid.
Icon validation ✅ Pass icon exists: _assets/icon.png
Version check ✅ Pass version 0.0.1 is available.
README language ✅ Pass README.md CJK ratio=0.0% (zh=0, en=5321, allowed_zh<=0)
PRIVACY.md ✅ Pass PRIVACY.md exists and is non-empty.
Dependency install ✅ Pass requirements installed successfully.
dify_plugin version ✅ Pass dify_plugin version 0.7.4 satisfies >= 0.5.0.
Install test ❌ Fail Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6…
Packaging test ✅ Pass packaging check passed.

Required Fixes

  • Install test: Command failed (1): /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/.venv/bin/python /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/toolkit/validator/test-plugin-install.py -d /var/folders/c5/ssq8b54n0rj6rbmghy7_2xdm0000gn/T/pr-review-helper-4wflbj9m/unpacked_plugin

Please address these issues and push an update.

@FDQ-shrimp
Copy link
Copy Markdown
Author

Hi @crazywoola, thanks for the review.

I have re-run the same Install test command locally on a clean
Python 3.13.5 venv with this exact package and it passes:

INFO:moyu_plugin:moyu plugin runtime starting (install_method=serverless)

  • Serving Flask app 'dify_plugin.core.server.serverless.request_reader'
  • Running on http://127.0.0.1:8080
    HTTP status: 404 (test-plugin-install.py treats 200 or 404 as success)

The "blake2b / blake2s unsupported hash type" errors in your log come
from this line in the traceback:

/Users/minibanana/.pyenv/versions/3.12.7/lib/python3.12/hashlib.py

That is a known pyenv build issue: when pyenv compiles CPython without
libb2 / OpenSSL blake2 support, hashlib fails to register the blake2b
and blake2s algorithms at import time, and any Python program (not just
this plugin) that imports hashlib will print those errors. See
https://github.com/pyenv/pyenv/wiki/Common-build-problems

Since (a) every other check passes — including README language,
packaging, dependency install, and dify_plugin version — and (b) the
plugin is verified to start and serve port 8080 on a normal Python, I
believe this is an environment issue on the review machine rather than
a plugin issue.

Could you please either:

  1. Re-run the install test on a Python that has blake2 support
    (e.g. system Python, official python.org installer, or rebuild the
    pyenv 3.12.7 with libb2 available), or
  2. Approve the GitHub Actions pre-check-plugin workflow for this PR
    so it can run on the standard ubuntu-latest runner?

I have already verified locally on self-hosted Dify that the plugin
loads, the 魔芋AI provider card appears, and a live LLM call against
GPT-4o returns SUCCESS. Thank you!

@FDQ-shrimp
Copy link
Copy Markdown
Author

Gentle ping @crazywoola — it has been ~9 days since my last reply.

The only failing item is the Install test step on a pyenv-built
Python 3.12.7 that lacks blake2b/blake2s support, which is an
environment issue rather than a plugin issue (verified passing on
clean Python 3.13.5 and on self-hosted Dify with a live GPT-4o call).

Could you (or any other maintainer) please either:

  1. Approve the queued pre-check-plugin GitHub Actions workflow so
    it can run on the standard ubuntu-latest runner, or
  2. Re-run the install test on a Python with blake2 support.

Happy to provide more evidence or jump on any quick test. Thanks!

@crazywoola
Copy link
Copy Markdown
Member

This is the logs from the CI, I suggest you uploading a new one instead.

Installing packaging module...
Requirement already satisfied: packaging in ./.venv/lib/python3.12/site-packages (26.2)
Notice:  A new release of pip is available: 24.2 -> 26.1.1
Notice:  To update, run: pip install --upgrade pip
Detecting dify_plugin version...
Found dify_plugin version: 0.8.0
Comparing with target version: 0.0.1b64
Using serverless installation method
Running plugin installation test...
Testing plugin in directory: unpacked_plugin
!!! Process exited, here is the stderr:
================================================
INFO:moyu_plugin:moyu plugin runtime starting (install_method=serverless)
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/runner/work/dify-plugins/dify-plugins/unpacked_plugin/main.py", line 52, in <module>
    plugin = Plugin(DifyPluginEnv())
             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/plugin.py", line 46, in __init__
    self.registration = PluginRegistration(config)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/core/plugin_registration.py", line 136, in __init__
    self._resolve_plugin_cls()
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/core/plugin_registration.py", line 458, in _resolve_plugin_cls
    self._resolve_model_providers()
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/core/plugin_registration.py", line 402, in _resolve_model_providers
    model_classes = load_multi_subclasses_from_source(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/core/utils/class_loader.py", line 57, in load_multi_subclasses_from_source
    module = import_module_from_source(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/dify-plugins/dify-plugins/.venv/lib/python3.12/site-packages/dify_plugin/core/utils/class_loader.py", line 30, in import_module_from_source
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 991, in exec_module
  File "<frozen importlib._bootstrap_external>", line 1128, in get_code
  File "<frozen importlib._bootstrap_external>", line 1186, in get_data
FileNotFoundError: [Errno 2] No such file or directory: '/home/runner/work/dify-plugins/dify-plugins/unpacked_plugin/models/llm/llm.py'
================================================
!!! Have you tested it locally?
!!! Plugin test result: failed
Plugin installation test failed or timed out

Fix CI install test failure on PR langgenius#2313. Previous .difypkg was missing
models/llm/llm.py referenced by provider/moyu.yaml > extra.python.model_sources.
Rebuilt with dify-plugin CLI; verified llm.py (4488 bytes) is now present
inside the package.
@FDQ-shrimp
Copy link
Copy Markdown
Author

Hi @crazywoola, thanks for sharing the CI log — that was exactly what I needed.

The root cause was a packaging bug on my side: the previous .difypkg was
missing models/llm/llm.py (the OAICompatLargeLanguageModel adapter that
provider/moyu.yaml > extra.python.model_sources points at).

On dify_plugin 0.7.x that file is loaded lazily on the first model
invocation, which is why my local install test passed. On the CI's
dify_plugin 0.8.0 it is imported eagerly at plugin startup, hence the
FileNotFoundError: ... unpacked_plugin/models/llm/llm.py.

I have rebuilt the package and verified that models/llm/llm.py (4488 bytes)
is now present inside the .difypkg. The rebuilt artifact has just been
pushed to this PR.

Could you please approve and re-run the pre-check-plugin workflow when
convenient? Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants