Dify Plugin Daemon

repository·main·Indexed 19 days ago

https://github.com/langgenius/dify-plugin-daemon

A service that manages the lifecycle and execution of plugins across Local, Debug, and Serverless runtime environments. It includes a CLI for local plugin development, bundle management (initialization, dependency analysis, and packaging), and tools for configuring Python runtimes and Redis namespacing.

Tokens
49K
Snippets
163
Records
214
Agent score
61%

What's inside dify-plugin-daemon

  1. Understand Redis key naming and prefixing behavior

    main

    The cache system manages namespaces using a prefix system:

    • Default Prefix: plugin_daemon.
    • Override: Use the REDIS_KEY_PREFIX environment variable to change the prefix.
    • Scope: The prefix applies to both standard keys and Pub/Sub channels.
    • Namespace Switching: Changing the prefix switches the active namespace; it does not migrate existing data to the new prefix.
    • Cluster Hash Tags: Logical keys containing Redis Cluster hash tags (e.g., {remote:key:manager}) will keep those tags intact because the prefix is prepended to the full logical key.
  2. How the Stream[T] type works

    main

    The Stream[T] type provides a thread-safe, generic, and buffered communication channel between goroutines, specifically designed for asynchronous producer-consumer patterns. It implements backpressure control using a configurable buffer size, which determines the maximum number of items that can be held before producers are blocked or encounter errors. It is built using a deque for efficient FIFO operations and uses mutexes, atomic operations, and condition variables to ensure thread safety and manage blocking states.

    // Create with buffer size (max items before blocking)
    s := stream.NewStream[T](128)
    defer s.Close()
  3. How Dify Plugin Daemon runtimes work

    main

    The Dify Plugin Daemon manages three distinct runtime types to execute plugins, forwarding HTTP requests from the Dify API server based on the selected runtime:

    1. Local runtime: Runs on the same machine as the Dify server. The daemon starts the plugin as a subprocess and communicates via STDIN/STDOUT.
    2. Debug runtime: Used for local development. The daemon waits for a plugin to connect via a TCP-based, full-duplex connection.
    3. Serverless runtime: Runs on platforms like AWS Lambda. The plugin is packaged as a third-party service and invoked by the daemon via HTTP.

    For detailed information on the Serverless Runtime Interface, refer to the SRI Docs.

  4. How request batching works for large payloads

    main

    To prevent failures due to platform payload limits (e.g., the 6 MB limit on AWS Lambda Function URLs), the daemon implements automatic batching for requests like text embedding and token counting that exceed MAX_SERVERLESS_REQUEST_BYTES.

    • Transparent Processing: The daemon automatically splits large requests into batches and merges the results; plugin developers do not need to handle this.
    • Sequential Execution: Batches are processed in order to ensure consistent results.
    • Error Handling: If a single item within a request is itself larger than the limit, the daemon returns a ServerlessPayloadTooLargeError.
  5. Understand Dify Plugin Types

    main

    Dify plugins extend three main capabilities. Depending on your goal, you will implement one of the following types:

    • Tool: Performs specific tasks (e.g., Google Search, Stable Diffusion). Can be a tool provider with optional endpoints.
    • Model: Provides AI model integrations (e.g., OpenAI, Anthropic). These are model providers only.
    • Endpoint: Provides HTTP services (e.g., Custom APIs, integrations). Also referred to as an Extension.

    Important Restrictions:

    • You cannot extend both tools and models in the same plugin.
    • You cannot extend both models and endpoints in the same plugin.
    • A plugin must have at least one extension.
    • You are limited to one supplier per extension type.
  6. How request batching works in SRI

    main

    To prevent exceeding platform-specific payload limits (such as the 6 MB limit for AWS Lambda Function URLs), the Dify Plugin Daemon implements automatic batching for large requests.

    Key Behaviors:

    • Transparent batching: The daemon automatically splits and merges text embedding and token counting requests. Plugin developers do not need to implement custom logic for this.
    • Serial processing: Batches are processed one after another to ensure consistent results.
    • Automatic merging: Results from all batches are merged into a single response for the user.
    • Error handling: If a single text item is so large that it exceeds MAX_SERVERLESS_REQUEST_BYTES even when alone, the request will fail with a ServerlessPayloadTooLargeError.
  7. Configure an HTTP client

    main

    When setting up the http.Client for use with the http_requests utilities, it is recommended to configure a custom Transport with specific Dial timeouts and IdleConnTimeout to manage connection lifecycles effectively.

    client := &http.Client{
        Transport: &http.Transport{
            Dial: (&net.Dialer{
                Timeout:   5 * time.Second,
                KeepAlive: 120 * time.Second,
            }).Dial,
            IdleConnTimeout: 120 * time.Second,
        },
    }
  8. Prepare a PRIVACY.md for plugin publication

    main

    When developing a plugin for the Dify Marketplace, you must provide a valid PRIVACY.md file. Using a placeholder or empty template will result in your Marketplace submission being rejected. Your privacy policy must explicitly detail how your plugin handles user data to comply with the Plugin Privacy Protection Guidelines.

    Your PRIVACY.md should include the following sections:

    1. Data Collection: Specify if personal data (name, email, etc.) is collected, how credentials or API keys are stored, and what user content is processed.
    2. Data Usage: Explain how collected data is used and list any third-party services involved, including links to their respective privacy policies.
    3. Data Retention: State how long data is kept and the process for users to request data deletion.
    4. Contact: Provide a way for users to reach you regarding privacy concerns.
  9. Create and use a Stream[T]

    main

    To use a stream, initialize it with a specific buffer size using stream.NewStream[T](size). The size represents the maximum number of items allowed in the buffer before the producer is affected by backpressure.

    Producer Operations

    • Write(data): Non-blocking write. Returns an error if the buffer is full.
    • WriteBlocking(data): Blocking write. Waits until space becomes available in the buffer.
    • WriteError(err): Propagates an error into the stream.
    • Close(): Signals completion and closes the stream.

    Consumer Operations

    Use the Next() and Read() pattern to iterate through data:

    • Next(): Blocks until new data is available or the stream is closed.
    • Read(): Returns the next item and an error. If the error is stream.ErrEmpty, the consumer should continue waiting.
    // Create with buffer size (max items before blocking)
    s := stream.NewStream[T](128)
    defer s.Close()
    
    // Producer side
    err := s.Write(data)
    
    // Consumer side
    for s.Next() {
        data, err := s.Read()
        if err != nil {
            if err == stream.ErrEmpty {
                continue
            }
            // Handle actual error
            break
        }
        // Process data
    }
  10. Configure the Serverless Runtime Interface (SRI)

    main

    The Dify Plugin Daemon connects to remote serverless environments (like AWS Lambda) using the Serverless Runtime Interface (SRI). This connection is configured via the following environment variables:

    VariableDescription
    DIFY_PLUGIN_SERVERLESS_CONNECTOR_URLBase URL of the remote runtime environment (e.g., https://example.com)
    DIFY_PLUGIN_SERVERLESS_CONNECTOR_API_KEYAuthentication token passed in the Authorization request header
    MAX_SERVERLESS_REQUEST_BYTESMaximum serialized request payload size in bytes. Default is 5242880 (5 MB). This is set to allow a safety margin below the 6 MB limit of AWS Lambda Function URLs.

    Note: The SRI is currently in Alpha. Stability and backward compatibility are not guaranteed.

  11. Structure of a Dify Plugin README template

    main

    When developing a plugin for the Dify Marketplace, use the provided template to ensure your documentation meets review standards. The template includes placeholders for metadata, description, setup instructions, and usage examples.

    Important Requirements:

    • Language: The README.md must be in English only. If you need to provide translations, use localized files like README_zh_Hans.md instead of mixing languages in the main file.
    • Content Quality: Replace all {{ .Placeholder }} sections with real, actionable content before publishing.
    • Setup Section: Must detail required credentials, API keys, prerequisites, and how to obtain them.
    • Usage Section: Should explain how to use the plugin within the Dify interface, ideally with concrete examples.
    ## {{ .PluginName }}
    
    **Author:** {{ .Author }}
    **Version:** {{ .Version }}
    **Type:** {{ .Category }}
    
    ### Description
    
    {{ .PluginDescription }}
    
    ### Setup
    
    Describe how to configure the plugin: required credentials or API keys, where to obtain them, and any prerequisites.
    
    ### Usage
    
    Describe how to use the plugin in Dify, with examples if possible.