### Session Management Example Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Example of storing and retrieving user session data using the cache. Handles session expiration or not found scenarios. ```go // Store session sessionKey := fmt.Sprintf("session_info:%s", id) cache.Store(sessionKey, session, time.Minute*30) // Retrieve session session, err := cache.Get[Session](sessionKey) if err == cache.ErrNotFound { // Session expired or not found } ``` -------------------------------- ### Copy Environment File Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Copies the example environment file to .env for configuration. This is a prerequisite for running the daemon. ```bash cp .env.example .env ``` -------------------------------- ### Run Dify Plugin Daemon Server Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Execute the main daemon server process. Ensure Go is installed and the project is set up correctly. ```bash go run cmd/server/main.go ``` -------------------------------- ### Set Up Environment Variables Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Copy the example environment file to .env and configure key variables for database connection, Python interpreter path, and S3 storage. ```bash cp .env.example .env # Key environment variables to configure: # - DB_HOST, DB_NAME, DB_USER, DB_PASS: Database connection # - PYTHON_INTERPRETER_PATH: Python 3.11+ path for plugin SDK # - S3_USE_AWS: Set to false for non-AWS S3 storage ``` -------------------------------- ### Install Dify CLI with Homebrew Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Installs the Dify CLI tool using Homebrew. Ensure you have tapped the Dify CLI repository first. ```bash brew tap langgenius/dify brew install dify ``` -------------------------------- ### Go Function Signature Example Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Illustrates multi-line parameter and return type formatting for Go functions. Ensure parameters are on separate lines if they exceed a single line. ```go func InvokeAgentStrategy( session *session_manager.Session, r *requests.RequestInvokeAgentStrategy, ) (*stream.Stream[agent_entities.AgentStrategyResponseChunk], error) { ``` -------------------------------- ### GET /v1/runner/instances Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Returns information about plugin instances that are ready to run, filtered by a provided filename. ```APIDOC ## GET /v1/runner/instances ### Description Returns information about plugin instances that are ready to run. ### Method GET ### Endpoint /v1/runner/instances ### Parameters #### Query Parameters - **filename** (string) - Required - Name of the uploaded plugin package, in the format: `vendor@plugin@version@hash.difypkg` ### Response #### Success Response (200) - **items** (array) - A list of plugin instances. - **ID** (string) - The unique identifier of the plugin instance. - **Name** (string) - The name of the plugin. - **Endpoint** (string) - The network endpoint for the plugin instance. - **ResourceName** (string) - The name of the underlying resource. ### Response Example ```json { "items": [ { "ID": "string", "Name": "string", "Endpoint": "string", "ResourceName": "string" } ] } ``` ``` -------------------------------- ### Run Dify Plugin Daemon Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Starts the Dify Plugin Daemon using Go. It loads environment variables from the .env file using godotenv. ```bash go run github.com/joho/godotenv/cmd/godotenv@latest -f .env go run cmd/server/main.go ``` -------------------------------- ### GET /ping Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Used by the daemon for connectivity checks during startup. It expects a 'pong' response. ```APIDOC ## GET /ping ### Description Used by the daemon for connectivity checks during startup. ### Method GET ### Endpoint /ping ### Request Example ```http GET /ping Authorization: ``` ### Response #### Success Response (200) - **pong** (string) - Plain text response indicating the service is reachable. ``` -------------------------------- ### Go Struct Field Tags Example Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Shows common struct field tags used for JSON serialization, validation, and HTTP binding. ```go json:"field_name" validate:"required,min=1,max=256" uri:"tenant_id" form:"page" ``` -------------------------------- ### Set Query Parameters Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Appends query parameters to the URL for GET requests or other methods that support them. ```go HttpParams(map[string]string) ``` -------------------------------- ### Get current buffer size Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Returns the current number of items in the stream's buffer. This can be used for monitoring or flow control. ```go s.Size() ``` -------------------------------- ### Type-Safe Cache Operations Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Provides generic methods for cache operations like Get, GetMapField, Subscribe, and AutoGetWithGetter, ensuring type safety for cached data and event types. ```go // Type-safe cache operations cache.Get[models.Plugin](key) cache.GetMapField[node](mapKey, field) cache.Subscribe[EventType](channel) cache.AutoGetWithGetter[plugin_entities.PluginDeclaration](...) ``` -------------------------------- ### Map Operations for Cluster State Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Manage cluster state by setting, getting, and deleting individual fields within a Redis map. Useful for tracking node status. ```go // Set map field cache.SetMapOneField(CLUSTER_STATUS_KEY, nodeId, nodeStatus) // Get single field node, err := cache.GetMapField[node](CLUSTER_STATUS_KEY, nodeId) // Get entire map nodes, err := cache.GetMap[node](CLUSTER_STATUS_KEY) // Delete field cache.DelMapField(CLUSTER_STATUS_KEY, nodeId) ``` -------------------------------- ### POST /v1/launch Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Launches a plugin using a streaming event protocol for real-time daemon parsing of startup status. It accepts multipart/form-data and returns status via Server-Sent Events (SSE). ```APIDOC ## POST /v1/launch ### Description Launches a plugin using a streaming event protocol for real-time daemon parsing of startup status. This API uses `multipart/form-data` for submission and returns status via Server-Sent Events (SSE). ### Method POST ### Endpoint /v1/launch ### Parameters #### Request Body - **context** (file) - Required - Plugin package file in `.difypkg` format. - **verified** (boolean) - Optional - Whether the plugin has been verified by the daemon. ### Response #### Success Response (200) - **SSE Stream** - Returns status updates via Server-Sent Events (SSE). - **Stage** (string) - The current stage of the launch process (`healthz`, `start`, `build`, `run`, `end`). - **State** (string) - The state of the current stage (`running`, `success`, `failed`). - **Obj** (string) - Additional object information related to the stage. - **Message** (string) - A descriptive message about the current status or error. When a message with `Stage=run` and `State=success` is received, the daemon will extract details and register the plugin instance in the format: `endpoint=http://...,name=...,id=...` ### SSE Response Format Example ```json { "Stage": "healthz|start|build|run|end", "State": "running|success|failed", "Obj": "string", "Message": "string" } ``` ### Error Handling - If any stage returns `State = failed`, it is considered a launch failure. The daemon should abort the process and output the `Message` field as the error. ``` -------------------------------- ### Dify Plugin Debugging Configuration Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/cmd/commandline/plugin/templates/python/GUIDE.md Configure your local environment for debugging by copying `.env.example` to `.env` and setting the `INSTALL_METHOD`, `REMOTE_INSTALL_URL`, and `REMOTE_INSTALL_KEY`. ```bash INSTALL_METHOD=remote REMOTE_INSTALL_URL=debug.dify.ai:5003 REMOTE_INSTALL_KEY=your-debug-key ``` -------------------------------- ### Query Plugin Instances Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Retrieve information about available plugin instances that are ready to run. Requires the plugin package filename as a query parameter. ```http GET /v1/runner/instances?filename=vendor@plugin@version@hash.difypkg ``` -------------------------------- ### Initialize Redis Client Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Configure and initialize the Redis client for cache operations. Requires connection details and optional authentication. ```go cache.InitRedisClient( addr, // "localhost:6379" username, // optional password, useSsl, // bool db, // database number ) ``` -------------------------------- ### Launch Plugin with Streaming Events Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Launches a plugin using multipart/form-data for the plugin package and returns status updates via Server-Sent Events (SSE). The `verified` field indicates if the plugin has been pre-verified. ```http POST /v1/launch context, verified multipart payload ``` -------------------------------- ### Configure PostgreSQL/MySQL Database Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/database.md Set database connection details in the .env file. Supports PostgreSQL and MySQL. ```bash DB_TYPE=postgresql # or mysql DB_HOST=localhost DB_DATABASE=dify_plugin DB_USERNAME=postgres DB_PASSWORD=password ``` -------------------------------- ### Configure HTTP Client Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Sets up a custom HTTP client with specified dialer timeouts and idle connection timeouts for efficient connection management. ```go client := &http.Client{ Transport: &http.Transport{ Dial: (&net.Dialer{ Timeout: 5 * time.Second, KeepAlive: 120 * time.Second, }).Dial, IdleConnTimeout: 120 * time.Second, }, } ``` -------------------------------- ### Run Dify Plugin Locally Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/cmd/commandline/plugin/templates/python/GUIDE.md Execute your plugin's main entry point using the Python module command. ```bash python -m main ``` -------------------------------- ### Run Database Migration Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Executes the database migration command for the Dify Plugin Daemon. ```bash go run ./cmd/commandline/ migrate ``` -------------------------------- ### List Available Plugin Instances Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Retrieves a list of available plugin instances based on the provided filename. ```APIDOC ## GET /v1/runner/instances ### Description List available plugin instances. ### Method GET ### Endpoint /v1/runner/instances ### Parameters #### Query Parameters - **filename** (string) - Required - Full plugin package filename (e.g., vendor@plugin@version@hash.difypkg) ### Responses #### Success Response (200) - **items** (array) - List of available plugin instances - **ID** (string) - **Name** (string) - **Endpoint** (string) - **ResourceName** (string) ### Response Example ```json { "items": [ { "ID": "plugin-id-1", "Name": "Example Plugin", "Endpoint": "http://localhost:8080/plugins/example", "ResourceName": "example-resource" } ] } ``` ``` -------------------------------- ### Launch Plugin via SSE Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Launches a plugin using Server-Sent Events (SSE) to stream launch stages. ```APIDOC ## POST /v1/launch ### Description Launch a plugin via SSE. ### Method POST ### Endpoint /v1/launch ### Parameters #### Request Body - **context** (binary) - Required - Plugin package file (.difypkg) - **verified** (boolean) - Optional - Whether the plugin is verified ### Request Example ``` --boundary Content-Disposition: form-data; name="context"; filename="plugin.difypkg" Content-Type: application/octet-stream [binary content of plugin.difypkg] --boundary Content-Disposition: form-data; name="verified" true --boundary-- ``` ### Responses #### Success Response (200) - **Stage** (string) - Enum: healthz, start, build, run, end - The current stage of the plugin launch. - **State** (string) - Enum: running, success, failed - The current state of the plugin launch stage. - **Obj** (string) - Additional object data related to the stage. - **Message** (string) - A descriptive message for the current stage and state. ### Response Example ``` event: launch_update data: {"Stage":"start","State":"running","Message":"Plugin starting..."} event: launch_update data: {"Stage":"build","State":"success","Message":"Plugin built successfully."} ``` ``` -------------------------------- ### Configure Python Compile Arguments Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Use PYTHON_COMPILE_ALL_EXTRA_ARGS to prevent compileall from processing virtual environment files, reducing CPU load during plugin startup. ```shell PYTHON_COMPILE_ALL_EXTRA_ARGS="-x \.venv" ``` -------------------------------- ### Generate Code from Definitions Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Run the code generation tool, typically used for creating service interfaces and other boilerplate code from definitions. ```bash go run cmd/codegen/main.go ``` -------------------------------- ### Create a new stream with buffer size Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Initializes a new stream with a specified buffer size. The buffer size determines the maximum number of items that can be held before blocking. Ensure to close the stream when done. ```go s := stream.NewStream[T](128) defer s.Close() ``` -------------------------------- ### Basic CRUD Operations in Go Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/database.md Perform basic Create, Update, Delete, and DeleteByCondition operations using the GORM database interface. ```go db.Create(&model) ``` ```go db.Update(&model) ``` ```go db.Delete(&model) ``` ```go db.DeleteByCondition(condition) ``` -------------------------------- ### Configure Plugin Ignore UV Lock and PIP Mirror Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/README.md Set PLUGIN_IGNORE_UV_LOCK to true to allow uv to bypass the uv.lock file. Configure PIP_MIRROR_URL to specify a custom PyPI mirror for dependency resolution. ```shell PLUGIN_IGNORE_UV_LOCK=true PIP_MIRROR_URL=https://mirrors.aliyun.com/pypi/simple/ ``` -------------------------------- ### Retrieve Plugin with Remote Declaration in Go Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/database.md Fetch a plugin record and access its remote declaration. Also shows how to retrieve a stored PluginDeclaration record. ```go // Get plugin with remote declaration plugin, _ := db.GetOne[models.Plugin]( db.Equal("plugin_id", pluginID), ) declaration := plugin.RemoteDeclaration ``` ```go // Get stored declaration decl, _ := db.GetOne[models.PluginDeclaration]( db.Equal("plugin_id", pluginID), ) ``` -------------------------------- ### Basic Cache Operations Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Store, retrieve, delete, and check for the existence of keys in the cache. Values are stored with a specified expiration time. ```go // Store and retrieve cache.Store("key", value, time.Minute*30) val, err := cache.Get[Type]("key") cache.Del("key") // Check existence exists, _ := cache.Exist("key") ``` -------------------------------- ### Ping Endpoint for Connectivity Check Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Use this endpoint for the daemon to perform basic connectivity checks with the remote runtime environment during startup. It expects a simple 'pong' response. ```http GET /ping Authorization: ``` -------------------------------- ### Use Length-Prefixed Protocol Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Enables support for length-prefixed protocols, often used in specific RPC or messaging systems. ```go HttpUsingLengthPrefixed(bool) ``` -------------------------------- ### Run Tests for a Specific Package Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Execute tests for a particular package within the internal core plugin daemon directory. Use this command when explicitly requested. ```bash go test ./internal/core/plugin_daemon/... ``` -------------------------------- ### Dify Plugin Manifest Structure Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/cmd/commandline/plugin/templates/python/GUIDE.md Define your plugin's metadata, resources, permissions, and extensions in the `manifest.yaml` file. Ensure it meets the specified restrictions. ```yaml version: 0.1.0 # Required: Plugin version type: plugin # Required: plugin or bundle author: YourOrganization # Required: Organization name label: # Required: Multi-language names en_US: Plugin Name zh_Hans: 插件名称 created_at: 2023-01-01T00:00:00Z # Required: Creation time (RFC3339) icon: assets/icon.png # Required: Icon path # Resources and permissions resource: memory: 268435456 # Max memory (bytes) permission: tool: enabled: true # Tool permission model: enabled: true # Model permission llm: true text_embedding: false # Other model types... # Other permissions... # Extensions definition plugins: tools: - tools/my_tool.yaml # Tool definition files models: - models/my_model.yaml # Model definition files endpoints: - endpoints/my_api.yaml # Endpoint definition files # Runtime metadata meta: version: 0.0.1 # Manifest format version arch: - amd64 - arm64 runner: language: python version: "3.12" entrypoint: main ``` -------------------------------- ### Pub/Sub for Event Notifications Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Publish events to a channel and subscribe to receive them. Channels are prefixed with the configured Redis key prefix. ```go // Publish event cache.Publish(CHANNEL, event) // Subscribe to channel eventChan, cancel := cache.Subscribe[EventType](CHANNEL) def cancel() for event := range eventChan { // Process event } ``` -------------------------------- ### Package Dify Plugin Manually Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/cmd/commandline/plugin/templates/python/GUIDE.md Use the `dify-plugin` CLI tool to package your plugin directory for distribution. ```bash dify-plugin plugin package ./YOUR_PLUGIN_DIR ``` -------------------------------- ### Set Request Headers Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Configures HTTP request headers, typically used for authentication or specifying content types. ```go HttpHeader(map[string]string) ``` -------------------------------- ### Go Constant Naming Convention Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Demonstrates the SCREAMING_SNAKE_CASE convention for constants and enums in Go, often prefixed with a package name. ```go PLUGIN_ACCESS_TYPE_TOOL PLUGIN_RUNTIME_TYPE_LOCAL ``` -------------------------------- ### Run a Single Specific Test Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/CLAUDE.md Execute a single named test case within a specified package. This command should only be used when explicitly requested by the user. ```bash go test -run TestSpecificName ./path/to/package ``` -------------------------------- ### Plugin File Naming Convention Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md Specifies the required naming convention for plugin package files, including vendor, plugin name, version, and a SHA256 hash, all with the `.difypkg` extension. ```text @@@.difypkg ``` ```text langgenius@tavily@0.0.5@7f277f7a63e36b1b3e9ed53e55daab0b281599d14902664bade86215f5374f06.difypkg ``` -------------------------------- ### Set Referer Header Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Sets the 'Referer' header to the request URL, useful for mimicking browser behavior. ```go HttpDirectReferer() ``` -------------------------------- ### Assemble file chunks from a stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Assembles file chunks received from a stream into complete files. It uses a map to store and accumulate chunks based on an ID, processing complete files and cleaning up temporary storage. ```go files := make(map[string]*bytes.Buffer) for response.Next() { chunk, _ := response.Read() if chunk.Type == "blob_chunk" { id := chunk.ID if chunk.End { // Complete file completeFile := files[id].Bytes() processFile(completeFile) delete(files, id) } else { // Accumulate chunks if files[id] == nil { files[id] = bytes.NewBuffer(nil) } files[id].Write(chunk.Data) } } } ``` -------------------------------- ### Type-Safe Queries in Go Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/database.md Execute type-safe database queries for single records, multiple records with pagination and sorting, and record counts. ```go // Get single record plugin, _ := db.GetOne[models.Plugin]( db.Equal("id", pluginID), db.Equal("tenant_id", tenantID), ) ``` ```go // Get multiple records plugins, _ := db.GetAll[models.Plugin]( db.Equal("tenant_id", tenantID), db.Page(1, 20), db.OrderBy("created_at", true), ) ``` ```go // Count records count, _ := db.GetCount[models.Plugin]( db.Equal("tenant_id", tenantID), ) ``` -------------------------------- ### Type-Safe Database Queries with Generics Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Use generic functions like GetOne, GetAll, and GetCount for type-safe database operations. Requires models with defined types. ```go // Type-safe queries plugin, _ := db.GetOne[models.Plugin](...) plugins, _ := db.GetAll[models.Plugin](...) count, _ := db.GetCount[models.Plugin](...) ``` -------------------------------- ### Handle SSE response with a byte stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Sets the SSE content type and streams data from a byte slice stream to the client using Server-Sent Events. Errors are sent as SSE events. ```go func handleSSE(ctx *gin.Context, dataStream *stream.Stream[[]byte]) { ctx.Header("Content-Type", "text/event-stream") for dataStream.Next() { data, err := dataStream.Read() if err != nil { ctx.SSEvent("error", err.Error()) return } ctx.SSEvent("data", string(data)) ctx.Writer.Flush() } } ``` -------------------------------- ### Write data to stream (blocking) Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Writes data to the stream and blocks until space is available in the buffer. Use this when you need to ensure data is written. ```go s.WriteBlocking(data) ``` -------------------------------- ### Generic Plugin Invocation Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Enables type-safe invocation of plugins by specifying request and response types. Requires session, request, and buffer size as parameters. ```go // Generic plugin invocation with request/response types GenericInvokePlugin[RequestType, ResponseType]( session, request, bufferSize, ) // Example usage response, err := GenericInvokePlugin[ requests.RequestInvokeTool, tool_entities.ToolResponseChunk, ](session, request, 128) ``` -------------------------------- ### SSE Response Format for Plugin Launch Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md The Server-Sent Events (SSE) format used to communicate the status of a plugin launch. It includes the current stage, state, an object, and a message. ```json { "Stage": "healthz|start|build|run|end", "State": "running|success|failed", "Obj": "string", "Message": "string" } ``` -------------------------------- ### Handle Stream Responses Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Use this for SSE or chunked responses. It returns a stream that can be iterated over to process chunks as they arrive. ```go stream, err := http_requests.RequestAndParseStream[ChunkType]( client, url, "GET", http_requests.HttpUsingLengthPrefixed(true), ) for stream.Next() { chunk, err := stream.Read() // Process chunk } ``` -------------------------------- ### Send Plain Text Payload Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Sets the request body to a plain text string. ```go HttpPayloadText(string) ``` -------------------------------- ### Perform Typed JSON Request Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Use this for making POST requests with a JSON payload and expecting a typed JSON response. Configure timeouts and headers as needed. ```go resp, err := http_requests.RequestAndParse[ResponseType]( client, "https://api.example.com/endpoint", "POST", http_requests.HttpHeader(map[string]string{ "Authorization": "Bearer token", }), http_requests.HttpPayloadJson(map[string]any{ "key": "value", }), http_requests.HttpWriteTimeout(30), http_requests.HttpReadTimeout(60), ) ``` -------------------------------- ### Register pre-close operations Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Attaches a callback function that will be executed just before the stream is closed. This can be used for final state management. ```go s.BeforeClose(func() { // Finalize state }) ``` -------------------------------- ### Generic HTTP Request and Response Parsing Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Handles HTTP requests with generic parsing for response bodies and streams. Specify the expected ResponseType or ChunkType for type-safe handling. ```go // Generic request/response handling resp, err := http_requests.RequestAndParse[ResponseType]( client, url, method, options... ) // Stream parsing stream, err := http_requests.RequestAndParseStream[ChunkType]( client, url, method, ) ``` -------------------------------- ### Base SSE Handler with Generics Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md A generic base handler for Server-Sent Events (SSE) that accepts a function returning a stream of a specific type T. Used for invoking tools within a session. ```go // Base SSE handler with generics baseSSEWithSession( func(session *Session) (*stream.Stream[T], error) { return plugin_daemon.InvokeTool(session, &r.Data) }, accessType, accessAction, request, context, timeout, ) ``` -------------------------------- ### Stream plugin output to response stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Converts a channel of chunks from a plugin into a stream. It handles writing chunks to the response stream and propagating any errors. The response stream is closed upon completion. ```go func handlePluginResponse(pluginOutput <-chan Chunk) *stream.Stream[Chunk] { response := stream.NewStream[Chunk](128) go func() { defer response.Close() for chunk := range pluginOutput { if err := response.Write(chunk); err != nil { response.WriteError(err) return } } }() return response } ``` -------------------------------- ### Register a cleanup function on stream close Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Attaches a callback function that will be executed when the stream is closed. Useful for releasing resources held by the stream. ```go s.OnClose(func() { // Release resources }) ``` -------------------------------- ### Process and validate data with error propagation Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Creates an output stream that processes data from an input stream, performing validation. Errors encountered during reading or validation are propagated to the output stream. ```go func processWithValidation(input *stream.Stream[Data]) *stream.Stream[Result] { output := stream.NewStream[Result](64) go func() { defer output.Close() for input.Next() { data, err := input.Read() if err != nil { output.WriteError(err) return } result, err := validate(data) if err != nil { output.WriteError(err) return } output.Write(result) } }() return output } ``` -------------------------------- ### Set Write Timeout Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Configures the maximum duration for writing the request body. ```go HttpWriteTimeout(seconds) ``` -------------------------------- ### Write data to stream (non-blocking) Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Writes data to the stream without blocking. Returns an error if the stream's buffer is full. ```go err := s.Write(data) ``` -------------------------------- ### Database Transactions in Go Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/database.md Execute multiple database operations within a transaction to ensure atomicity. Operations will be rolled back if any error occurs. ```go db.WithTransaction(func(tx *gorm.DB) error { if err := db.Create(&plugin, tx); err != nil { return err } return db.Update(&installation, tx) }) ``` -------------------------------- ### Auto-type Cache Operations Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Retrieve values from the cache with an automatic fallback to a provided getter function if the key is not found. Also supports auto-deletion. ```go // Get with automatic getter fallback value := cache.AutoGetWithGetter(key, func() (*Type, error) { return fetchFromDB() }, ttl) // Auto delete cache.AutoDelete[Type](key) ``` -------------------------------- ### Send Multipart Form Payload Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Constructs a multipart/form-data request, typically used for file uploads. ```go HttpPayloadMultipart(files, data) ``` -------------------------------- ### Set Read Timeout Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Configures the maximum duration for reading the response body. ```go HttpReadTimeout(seconds) ``` -------------------------------- ### Process stream items asynchronously Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Processes all items from the stream asynchronously using a provided function. This allows for concurrent processing of stream elements. ```go err := s.Async(func(data T) { processItem(data) }) ``` -------------------------------- ### Health Check Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/runtime/sri.md This endpoint is used by the daemon to verify connectivity with the SRI. ```APIDOC ## GET /ping ### Description Health check endpoint used by the daemon to verify connectivity with the SRI. ### Method GET ### Endpoint /ping ### Responses #### Success Response (200) - **pong** (string) - Returns 'pong' if the service is alive ### Response Example ``` pong ``` ``` -------------------------------- ### Distributed Lock Acquisition Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/cache.md Acquire a distributed lock with a specified duration and timeout. Ensure critical sections are accessed by only one process at a time. ```go // Acquire lock with timeout acquired := cache.Lock(key, duration, timeout) if acquired { defer cache.Unlock(key) // Critical section } ``` -------------------------------- ### Send JSON Payload Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Specifies the request body as JSON. Ensure the data is serializable to JSON. ```go HttpPayloadJson(any) ``` -------------------------------- ### Type-Safe Streaming Operations Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Utilizes generics to create and operate on streams with specific data types, ensuring type safety during data processing. The consumer pattern reads data of the expected type. ```go // Type-safe streaming stream.NewStream[tool_entities.ToolResponseChunk](128) stream.Stream[agent_entities.AgentStrategyResponseChunk] // Consumer pattern for stream.Next() { data, err := stream.Read() // data is correctly typed } ``` -------------------------------- ### Read data from stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Reads data from the stream. This operation blocks until data is available or the stream is closed. Handles `stream.ErrEmpty` specifically. ```go for s.Next() { data, err := s.Read() if err != nil { if err == stream.ErrEmpty { continue } // Handle actual error break } // Process data } ``` -------------------------------- ### Send Payload from Reader Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md Allows sending request bodies from an `io.ReadCloser`, providing flexibility for custom data sources. ```go HttpPayloadReader(io.ReadCloser) ``` -------------------------------- ### Generic Constraints for Comparisons Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/generics.md Defines a generic constraint interface 'genericComparableConstraint' for types that support comparison operations. Used in functions like GreaterThan. ```go // Generic constraints for comparisons type genericComparableConstraint interface { int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 | bool } func GreaterThan[T genericComparableConstraint](field string, value T) ``` -------------------------------- ### Dify Backwards Invocation Request Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/http-requests.md A generic function for making requests to the Dify API, automatically including an inner API key and configured timeouts. It parses the response data into a generic type `T`. ```go func Request[T any](i *RealBackwardsInvocation, method, path string, options ...HttpOptions) (*T, error) { options = append(options, HttpHeader(map[string]string{ "X-Inner-Api-Key": i.difyInnerApiKey, }), HttpWriteTimeout(i.writeTimeout), HttpReadTimeout(i.readTimeout), ) req, err := http_requests.RequestAndParse[BaseResponse[T]]( i.client, i.difyPath(path), method, options..., ) if err != nil { return nil, err } return req.Data, nil } ``` -------------------------------- ### Propagate errors through the stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Writes an error to the stream, signaling a failure condition to consumers. This is crucial for error propagation in asynchronous operations. ```go s.WriteError(err) ``` -------------------------------- ### Signal stream completion Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Closes the stream, signaling that no more data will be sent. Consumers iterating over the stream will stop receiving new data. ```go s.Close() ``` -------------------------------- ### Filter data in the stream Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Adds a filter function to the stream. This function is applied to each data item before it's passed to consumers. It can be used for validation or transformation, returning an error to drop the item. ```go s.Filter(func(data T) error { if !isValid(data) { return errors.New("invalid data") } return nil }) ``` -------------------------------- ### Check if stream is closed Source: https://github.com/langgenius/dify-plugin-daemon/blob/main/docs/claude/stream.md Returns a boolean indicating whether the stream has been closed. Use this to check the stream's state without blocking. ```go s.IsClosed() ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.