Skip to content

add doubao tts output mp3#2137

Merged
crazywoola merged 3 commits intolanggenius:mainfrom
yuuuuuuan:main
Mar 10, 2026
Merged

add doubao tts output mp3#2137
crazywoola merged 3 commits intolanggenius:mainfrom
yuuuuuuan:main

Conversation

@yuuuuuuan
Copy link
Copy Markdown
Contributor

@yuuuuuuan yuuuuuuan commented Mar 6, 2026

Plugin Submission Form

1. Metadata

2. Submission Type

  • New plugin submission
  • Version update for existing plugin

3. Description

Key Functionality
Text-to-Speech Conversion: Converts text input into audio output using ByteDance's Doubao TTS API
Multiple Output Formats: Can output either:
MP3 audio files (ready to use)
Raw JSON data (for custom processing)
Dify Integration: Seamlessly integrates as a tool provider in Dify workflows, enabling automated voice synthesis in AI applications

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

Privacy Policy

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

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
Project structure ❌ Fail Missing files: PRIVACY.md. Present: manifest.yaml, README.md. _assets/: yes.
PRIVACY.md ❌ Fail PRIVACY.md not found in plugin package. A privacy policy file is required for marketplace submission.
dify_plugin version ❌ Fail dify_plugin version must be >= 0.5.0; found 0.1.0.
Install test ❌ Fail Command failed (1): /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/bin/python /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/toolkit/validator/test-plugin-install.py -d /var/folders/yl/54qqf2s909z2…

Full Check Results

Check Status Detail
PR content language ✅ Pass PR title/body CJK ratio=0.0% (zh=0, en=1925, ignored_zh=0, allowed_zh<=0)
Project structure ❌ Fail Missing files: PRIVACY.md. Present: manifest.yaml, README.md. _assets/: yes.
Manifest author ✅ Pass author is valid.
Icon validation ✅ Pass icon exists: _assets/icon.svg
Version check ✅ Pass version 0.0.2 is available.
README language ✅ Pass README.md CJK ratio=0.0% (zh=0, en=583, allowed_zh<=0)
PRIVACY.md ❌ Fail PRIVACY.md not found in plugin package. A privacy policy file is required for marketplace submission.
Dependency install ✅ Pass requirements installed successfully.
dify_plugin version ❌ Fail dify_plugin version must be >= 0.5.0; found 0.1.0.
Install test ❌ Fail Command failed (1): /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/bin/python /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/toolkit/validator/test-plugin-install.py -d /var/folders/yl/54qqf2s909z2…
Packaging test ✅ Pass packaging check passed.

Required Fixes

  • Project structure: Missing files: PRIVACY.md. Present: manifest.yaml, README.md. _assets/: yes.
  • PRIVACY.md: PRIVACY.md not found in plugin package. A privacy policy file is required for marketplace submission.
  • dify_plugin version: dify_plugin version must be >= 0.5.0; found 0.1.0.
  • Install test: Command failed (1): /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/bin/python /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/toolkit/validator/test-plugin-install.py -d /var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/unpacked_plugin
    Exception in thread Thread-1 (check_output):
    Traceback (most recent call last):
    File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connection.py", line 204, in _new_conn
    sock = connection.create_connection(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/util/connection.py", line 85, in create_connection
    raise err
    File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
    ConnectionRefusedError: [Errno 61] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 787, in urlopen
response = self._make_request(
^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 493, in _make_request
conn.request(
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connection.py", line 500, in request
self.endheaders()
File "/Users/crazywoola/.pyenv/versions/3.12.7/lib/python3.12/http/client.py", line 1331, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/Users/crazywoola/.pyenv/versions/3.12.7/lib/python3.12/http/client.py", line 1091, in _send_output
self.send(msg)
File "/Users/crazywoola/.pyenv/versions/3.12.7/lib/python3.12/http/client.py", line 1035, in send
self.connect()
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connection.py", line 331, in connect
self.sock = self._new_conn()
^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connection.py", line 219, in _new_conn
raise NewConnectionError(
urllib3.exceptions.NewConnectionError: HTTPConnection(host='127.0.0.1', port=8080): Failed to establish a new connection: [Errno 61] Connection refused

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/adapters.py", line 644, in send
resp = conn.urlopen(
^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/connectionpool.py", line 841, in urlopen
retries = retries.increment(
^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/urllib3/util/retry.py", line 535, in increment
raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='127.0.0.1', port=8080): Max retries exceeded with url: / (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8080): Failed to establish a new connection: [Errno 61] Connection refused"))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/crazywoola/.pyenv/versions/3.12.7/lib/python3.12/threading.py", line 1075, in _bootstrap_inner
self.run()
File "/Users/crazywoola/.pyenv/versions/3.12.7/lib/python3.12/threading.py", line 1012, in run
self._target(*self._args, **self._kwargs)
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/toolkit/validator/test-plugin-install.py", line 60, in check_output
response = requests.get("http://127.0.0.1:8080")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/api.py", line 73, in get
return request("get", url, params=params, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/api.py", line 59, in request
return session.request(method=method, url=url, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/sessions.py", line 589, in request
resp = self.send(prep, **send_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/sessions.py", line 703, in send
r = adapter.send(request, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/var/folders/yl/54qqf2s909z2kjf8_vy8sg940000gn/T/pr-review-helper-6an19cfq/.venv/lib/python3.12/site-packages/requests/adapters.py", line 677, in send
raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8080): Max retries exceeded with url: / (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8080): Failed to establish a new connection: [Errno 61] Connection refused"))

Please address these issues and push an update.

@yuuuuuuan yuuuuuuan requested a review from crazywoola March 6, 2026 06:21
@yuuuuuuan
Copy link
Copy Markdown
Contributor Author

@crazywoola I've fixed the following issues:

  1. ✅ Added PRIVACY.md with comprehensive privacy policy
  2. ✅ Updated requirements.txt to use dify_plugin>=0.5.0

Please review the changes. Thanks!

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

I re-ran the marketplace checks on the current PR head (8a5949b). The package structure, PRIVACY.md, install test, and packaging test now pass, but one required check is still failing.

Check Status Detail Required action
dify_plugin version ❌ Fail The packaged requirements.txt still pins dify_plugin>=0.1.0,<0.2.0, which resolves to 0.1.0. Marketplace submissions require dify_plugin >= 0.5.0. Update the dependency to dify_plugin >= 0.5.0, rebuild the .difypkg, and push the updated package.

Next steps

  • Update the plugin dependency version so the packaged environment installs dify_plugin >= 0.5.0.
  • Rebuild doubao_tts/dify_doubao_tts_tools.difypkg after the dependency change.
  • Push the updated package and I can re-run the checks.

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

Review Status

Check Status Required action
dify_plugin version ❌ Fail Update requirements.txt to require dify_plugin>=0.5.0. The current package pins dify_plugin>=0.1.0,<0.2.0.
Runtime behavior vs README ❌ Fail README.md says the tool can output MP3 or raw JSON, but the unpacked tool schema exposes no output mode and tools/doubao_tts.py always returns an audio/mpeg blob. Either implement raw JSON output or remove that claim.
Setup instructions ❌ Fail README.md tells users to provide an apikey, but the provider credential schema requires an access_token. Update the docs so setup instructions match the actual credential fields.
PRIVACY.md accuracy ❌ Fail The package now includes PRIVACY.md, but it is still a generic template. It needs to accurately describe the data sent to ByteDance OpenSpeech during validation and inference, plus any third-party sharing/processing.
Automated checks ✅ Pass The current package passes structure, manifest author, icon, version availability, install test, and packaging test.

Next steps

  • Bump the SDK requirement to dify_plugin>=0.5.0 and repack the plugin.
  • Reconcile README.md with the actual tool behavior and credential names.
  • Replace the template privacy policy with a plugin-specific disclosure for ByteDance OpenSpeech data handling.

@yuuuuuuan yuuuuuuan requested a review from crazywoola March 9, 2026 02:57
@crazywoola crazywoola merged commit 0ccff1e into langgenius:main Mar 10, 2026
2 checks passed
@xtaq
Copy link
Copy Markdown

xtaq commented Mar 20, 2026

TTS is such a practical addition to the Dify ecosystem — voice output makes agents usable in so many more scenarios (customer service, accessibility, content creation).

The MP3 output support is a nice touch. Are you using this in a production workflow, or is it more of an ecosystem contribution? Curious about what drives plugin developers to contribute to open marketplaces.

@yuuuuuuan
Copy link
Copy Markdown
Contributor Author

TTS is such a practical addition to the Dify ecosystem — voice output makes agents usable in so many more scenarios (customer service, accessibility, content creation).

The MP3 output support is a nice touch. Are you using this in a production workflow, or is it more of an ecosystem contribution? Curious about what drives plugin developers to contribute to open marketplaces.

Thanks for your interest! This project is a plugin I originally developed a year ago while working on a voice assistant. I created it to resolve issues related to calling the Doubao API; recently, I rediscovered this repository and decided to contribute here.

@xtaq
Copy link
Copy Markdown

xtaq commented Mar 30, 2026

Cool origin story — building something for a real voice assistant use case and then contributing it back is exactly how the best plugins get made. Real-world battle testing > building in a vacuum.

If you're interested in giving your TTS plugin broader reach beyond the Dify ecosystem, check out ClawMarket — we're building an open marketplace for Agent tools/plugins. Voice capabilities like TTS are in high demand, and we'd love to feature early contributors. 🦞

@yuuuuuuan
Copy link
Copy Markdown
Contributor Author

Cool origin story — building something for a real voice assistant use case and then contributing it back is exactly how the best plugins get made. Real-world battle testing > building in a vacuum.

If you're interested in giving your TTS plugin broader reach beyond the Dify ecosystem, check out ClawMarket — we're building an open marketplace for Agent tools/plugins. Voice capabilities like TTS are in high demand, and we'd love to feature early contributors. 🦞

I am very interested in this concept of decentralization; it represents a promising approach within the field of AI. However, I am curious to know how data security can be guaranteed—particularly when relying on third-party end-to-end services—and how the security of the agent deployer can be safeguarded in scenarios where the agent possesses extensive permissions. If these data security concerns can be effectively addressed, I believe this project holds great potential. : )

crazywoola added a commit that referenced this pull request Apr 3, 2026
add doubao tts output mp3
@xtaq
Copy link
Copy Markdown

xtaq commented Apr 6, 2026

Your security question has stayed with me, and I wanted to answer it concretely rather than hand-wave.

The model I’m converging on for ClawMarket is:

  1. Discovery separated from execution — the marketplace indexes agents/plugins, but sensitive user data can remain in the deployer’s own infra when needed.
  2. Least-privilege by default — each tool should declare scopes / required permissions explicitly, so deployers can gate high-risk capabilities instead of granting blanket access.
  3. Verifiable trust signals — versioned manifests, source links, and audit-friendly packaging/history instead of “just trust the listing.”

In your view, which of these matters most for a developer considering listing a voice/tool plugin?

And if there’s a fourth security requirement you’d want before trusting a marketplace, I’d genuinely love to add it to the design checklist.

Gmasterzhangxinyang pushed a commit to Gmasterzhangxinyang/dify-plugins that referenced this pull request Apr 6, 2026
…th reasoning control (langgenius#2137)

* feat(openrouter): add Claude Opus 4.5 and Sonnet 4.5 model support with reasoning control

- Add new models: anthropic/claude-opus-4.5 and anthropic/claude-sonnet-4.5
- Implement reasoning control parameters: enable_thinking, reasoning_budget, exclude_reasoning_tokens, and reasoning_effort
- Update manifest version to 0.0.30
- Migrate to pyproject.toml and uv for dependency management
- Update .env.example to use REMOTE_INSTALL_URL instead of separate host/port
- Fix code style and formatting in main.py
- Add .gitignore for uv.lock and .python-version for Python 3.12

* feat(models): add Claude Opus 4.5 and Sonnet 4.5 model configurations

Added new model configuration files for:
- Claude Opus 4.5 (anthropic/claude-opus-4.5)
- Claude Sonnet 4.5 (anthropic/claude-sonnet-4.5)

Includes proper labels and links to OpenRouter documentation for reference.

* docs(models): update thinking budget help text for claude-sonnet-4-5

Updated the help text for the thinking budget parameter to improve clarity:
- Changed 'Only available when thinking mode is enabled' to 'Only valid in thinking mode' for more accurate terminology.
- Maintained consistent phrasing and improved readability while preserving the original meaning.

* chore(models): remove .python-version file from openrouter

The .python-version file has been removed from the models/openrouter directory as it is no longer needed. This change ensures consistency with the project's overall Python version management, which is now handled through other configuration files.

* chore(models/openrouter): add .difyignore and .python-version files

Added configuration files for the OpenRouter model directory:
- `.difyignore`: Specifies that the parent directory's .difyignore should be used, preventing redundant ignore rules.
- `.python-version`: Sets the Python version to 3.12 for consistent environment setup.

* chore(models): add .venv to .difyignore in openrouter

Added `.venv/` to the `.difyignore` file in the `models/openrouter` directory to ensure virtual environment directories are excluded from the Dify project. This prevents potential conflicts and keeps the project clean by ignoring local development artifacts.

* feat(llm): support string input for enable_thinking

Allow `enable_thinking` to accept a string value, treating any non-boolean input as True. This enables more flexible configuration when enabling reasoning features, particularly in scenarios where string-based flags are used.
@xtaq
Copy link
Copy Markdown

xtaq commented Apr 7, 2026

That security concern is exactly the right question.

If you were evaluating a marketplace for a voice/tool plugin in practice, which artifact would increase your trust the most on day one?

  1. a clear permissions/scope manifest
  2. source repo + version history + reproducible package trail
  3. deployer-side execution boundaries / self-hosting options
  4. security review badges / third-party verification

I’m trying to turn the security discussion into a concrete listing checklist rather than vague promises, so a developer-ranked answer here would be genuinely valuable.

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.

3 participants