npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ifzai/connect2dify

v1.0.8

Published

A comprehensive TypeScript client for the Dify API, providing a clean and modular interface for chat, workflow, file management, and application interactions.

Readme

@ifzai/connect2dify

A comprehensive TypeScript client for the Dify API, providing a clean and modular interface for chat, workflow, file management, and application interactions.

Features

  • 🚀 Modular Architecture: Organized into focused API modules (Chat, Conversation, Workflow, File, App)
  • 🔄 Streaming Support: Built-in support for real-time streaming responses
  • 💪 TypeScript: Full type safety with comprehensive type definitions
  • 🌐 Universal: Works in both browser and Node.js environments
  • 📦 Tree Shakable: Import only the modules you need
  • 🔧 Configurable: Flexible configuration options
  • 🔄 Backward Compatible: Deprecated methods maintain compatibility

Installation

npm install @ifzai/connect2dify
# or
pnpm add @ifzai/connect2dify
# or
yarn add @ifzai/connect2dify

Quick Start

Basic Usage

import { DifyClient } from '@ifzai/connect2dify';

const client = new DifyClient({
  baseUrl: 'https://api.dify.ai',
  apiKey: 'your-api-key',
});

// Send a chat message (agent-chat apps only support streaming)
const response = await client.chat.sendMessage({
  user: 'user-123',
  query: 'Hello, how can you help me?',
  response_mode: 'streaming',
  inputs: {}, // Required for agent-chat applications
});

console.log(response.answer);

Streaming Responses

// Chat streaming example
const streamParams = {
  user: 'user-123',
  query: 'Tell me a story',
  response_mode: 'streaming' as const,
};

const result = await client.chat.sendMessage(streamParams);
if (Array.isArray(result)) {
  // Handle streaming chunks
  for (const chunk of result) {
    console.log(chunk.answer);
  }
}

Workflow Execution

// Execute a workflow in blocking mode
const workflowResponse = await client.workflow.runWorkflow({
  inputs: {
    query: 'What is artificial intelligence?',
  },
  user: 'user-123',
  response_mode: 'blocking',
});

console.log('Workflow result:', workflowResponse.data.outputs);

// Execute a workflow with streaming for real-time output
const streamingWorkflow = await client.workflow.runWorkflow({
  inputs: {
    query: 'Tell me a short story',
  },
  user: 'user-123',
  response_mode: 'streaming',
  chunkCompletionCallback: (chunk) => {
    if (chunk.event === 'text_chunk' && chunk.data?.text) {
      process.stdout.write(chunk.data.text); // Real-time text streaming
    }
  },
});

Using Individual API Modules

import { ChatAPI, WorkflowAPI } from '@ifzai/connect2dify';

const config = {
  baseUrl: 'https://api.dify.ai',
  apiKey: 'your-api-key',
};

const chatAPI = new ChatAPI(config);
const workflowAPI = new WorkflowAPI(config);

// Use APIs independently
const chatResponse = await chatAPI.sendMessage({
  user: 'user-123',
  query: 'Hello!',
});

const workflowResponse = await workflowAPI.runWorkflow({
  user: 'user-123',
  inputs: { text: 'Process this' },
});

Workflow Examples

Basic Workflow Execution

import { DifyClient } from '@ifzai/connect2dify';

const client = new DifyClient({
  baseUrl: 'https://api.dify.ai/v1',
  apiKey: 'your-workflow-api-key',
});

// Execute workflow in blocking mode
const response = await client.workflow.runWorkflow({
  inputs: {
    query: 'What is the weather like today?',
  },
  user: 'user-123',
  response_mode: 'blocking',
});

console.log('Workflow result:', response.data.outputs);

Streaming Workflow with Real-time Output

// Execute workflow with real-time streaming
const streamingResponse = await client.workflow.runWorkflow({
  inputs: {
    query: 'Tell me a short story about a robot.',
  },
  user: 'user-123',
  response_mode: 'streaming',
  chunkCompletionCallback: (chunk) => {
    // Handle different event types
    if (chunk.event === 'workflow_started') {
      console.log('🎬 Workflow started...');
    } else if (chunk.event === 'node_started') {
      console.log(`🔧 Node started: ${chunk.data?.title || 'Unknown'}`);
    } else if (chunk.event === 'text_chunk' && chunk.data?.text) {
      // This is the actual streaming text - display it word by word
      process.stdout.write(chunk.data.text);
    } else if (chunk.event === 'node_finished') {
      console.log(`✅ Node finished: ${chunk.data?.title || 'Unknown'}`);
    } else if (chunk.event === 'workflow_finished') {
      console.log('\n🏁 Workflow finished!');
    }
  },
});

console.log('Streaming completed!');

Workflow with Custom Inputs

// Execute workflow with custom parameters
const customResponse = await client.workflow.runWorkflow({
  inputs: {
    query: 'How do I cook pasta step by step?',
    language: 'en',
    detail_level: 'comprehensive',
    // Add any custom inputs your workflow expects
  },
  user: 'user-123',
  response_mode: 'blocking',
});

console.log('Custom workflow result:', customResponse.data.outputs);

Retrieving Workflow Information

// First execute a workflow to get a workflow_run_id
const runResponse = await client.workflow.runWorkflow({
  inputs: { query: 'Hello, this is a test.' },
  user: 'user-123',
  response_mode: 'blocking',
});

// Then get detailed information about the workflow run
if (runResponse.workflow_run_id) {
  const workflowInfo = await client.workflow.getWorkflow({
    workflow_run_id: runResponse.workflow_run_id,
  });

  console.log('Workflow Details:');
  console.log(`- Status: ${workflowInfo.status}`);
  console.log(`- Total Steps: ${workflowInfo.total_steps}`);
  console.log(`- Total Tokens: ${workflowInfo.total_tokens}`);
  console.log(`- Execution Time: ${workflowInfo.elapsed_time}s`);
}

File Upload with Workflow

// Upload a file first
const fileResponse = await client.file.uploadFile({
  file: fileBuffer, // or File object in browser
  user: 'user-123',
});

// Use the uploaded file in a workflow
const workflowResponse = await client.workflow.runWorkflow({
  inputs: {
    query: 'Analyze this document',
  },
  user: 'user-123',
  response_mode: 'blocking',
  files: [
    {
      type: 'document',
      transfer_method: 'local_file',
      upload_file_id: fileResponse.id,
    },
  ],
});

API Reference

DifyClient

The main client class that provides access to all API modules:

const client = new DifyClient({
  baseUrl: 'https://api.dify.ai/v1', // Required: Your Dify API base URL
  apiKey: 'your-api-key', // Required: Your API key
  defaultResponseMode: 'blocking', // Optional: 'blocking' | 'streaming'
  defaultUser: 'default-user', // Optional: Default user ID for requests
  requestOptions: {
    // Optional: Additional request configuration
    extraHeaders: {
      'Custom-Header': 'value',
      'X-Source': 'my-app',
    },
    timeout: 30000, // Request timeout in milliseconds
  },
});

Configuration Options

| Option | Type | Required | Default | Description | | ----------------------------- | --------------------------- | -------- | ------------ | ------------------------------------------------------- | | baseUrl | string | ✅ | - | Your Dify API base URL (e.g., https://api.dify.ai/v1) | | apiKey | string | ✅ | - | Your application API key from Dify dashboard | | defaultResponseMode | 'blocking' \| 'streaming' | ❌ | 'blocking' | Default response mode for API calls | | defaultUser | string | ❌ | - | Default user ID to use when not specified in requests | | requestOptions.extraHeaders | Record<string, string> | ❌ | {} | Additional HTTP headers to include in requests | | requestOptions.timeout | number | ❌ | 60000 | Request timeout in milliseconds |

Environment Variables

You can also configure the client using environment variables:

# .env file
DIFY_API_BASE_URL=https://api.dify.ai/v1
DIFY_API_KEY=your-api-key-here
DIFY_DEFAULT_USER=default-user-id
// Use environment variables
const client = new DifyClient({
  baseUrl: process.env.DIFY_API_BASE_URL || 'https://api.dify.ai/v1',
  apiKey: process.env.DIFY_API_KEY,
  defaultUser: process.env.DIFY_DEFAULT_USER,
});

Chat API (client.chat)

  • sendMessage(params) - Send a chat message (agent-chat apps only support streaming mode)
  • getMessages(params) - Get conversation messages
  • createMessageFeedback(params) - Provide feedback on a message
  • getMessageSuggests(params) - Get suggested questions
  • stopMessageResponse(params) - Stop a message response

Conversation API (client.conversation)

  • getConversations(params) - List conversations
  • deleteConversation(params) - Delete a conversation
  • renameConversation(params) - Rename a conversation

Workflow API (client.workflow)

  • runWorkflow(params) - Execute a workflow (supports both blocking and streaming)
  • getWorkflow(params) - Get workflow details
  • stopWorkflowTask(params) - Stop a workflow task
  • getWorkflowLogs(params) - Get workflow execution logs

File API (client.file)

  • uploadFile(params) - Upload a file
  • audioToText(params) - Convert audio to text

App API (client.app)

  • getParameters() - Get application parameters
  • getInfo() - Get application information
  • getMeta() - Get application metadata
  • sendCompletionMessage(params) - Send completion message (supports both blocking and streaming)
  • stopCompletionMessage(params) - Stop completion message

Environment Support

This package works in both browser and Node.js environments using modern web APIs:

  • ✅ Node.js 18+ (native fetch and ReadableStream support)
  • ✅ Modern browsers (Chrome 66+, Firefox 65+, Safari 12+)
  • ✅ Edge runtime environments (Vercel Edge, Cloudflare Workers)
  • ❌ Node.js < 18 (requires fetch polyfill)

Error Handling

Basic Error Handling

try {
  const response = await client.chat.sendMessage({
    user: 'user-123',
    query: 'Hello!',
  });
  console.log('Success:', response.answer);
} catch (error) {
  console.error('API Error:', error.message);

  // Handle specific error types
  if (error.message.includes('unauthorized')) {
    console.error('Check your API key');
  } else if (error.message.includes('quota')) {
    console.error('API quota exceeded');
  }
}

Workflow Error Handling

try {
  const response = await client.workflow.runWorkflow({
    inputs: { query: 'Process this data' },
    user: 'user-123',
    response_mode: 'blocking',
  });

  // Check workflow execution status
  if (response.data.status === 'failed') {
    console.error('Workflow failed:', response.data.error);
    return;
  }

  console.log('Workflow succeeded:', response.data.outputs);
} catch (error) {
  console.error('Workflow execution error:', error.message);

  // Handle specific workflow errors
  if (error.message.includes('workflow not found')) {
    console.error('Check your workflow ID and permissions');
  } else if (error.message.includes('invalid inputs')) {
    console.error('Check your input parameters match workflow requirements');
  }
}

Streaming Error Handling

try {
  const result = await client.workflow.runWorkflow({
    inputs: { query: 'Tell me a story' },
    user: 'user-123',
    response_mode: 'streaming',
    chunkCompletionCallback: (chunk) => {
      // Handle streaming errors
      if (chunk.event === 'error') {
        console.error('Streaming error:', chunk.data?.error);
        return;
      }

      // Process successful chunks
      if (chunk.event === 'text_chunk' && chunk.data?.text) {
        process.stdout.write(chunk.data.text);
      }
    },
  });
} catch (error) {
  if (error.message.includes('Streaming is not supported')) {
    // Fallback to blocking mode
    console.log('Falling back to blocking mode...');
    const response = await client.workflow.runWorkflow({
      inputs: { query: 'Tell me a story' },
      user: 'user-123',
      response_mode: 'blocking',
    });
    console.log(response.data.outputs);
  } else {
    console.error('Streaming workflow failed:', error.message);
  }
}

Migration from Previous Versions

The new modular structure provides a cleaner API while maintaining backward compatibility:

// Old way (still works, but deprecated)
const response = await client.sendMessage(params);
const workflowResult = await client.runWorkflow(params);

// New way (recommended)
const response = await client.chat.sendMessage(params);
const workflowResult = await client.workflow.runWorkflow(params);

Running Examples

This package includes comprehensive examples demonstrating real-world usage patterns. All examples use actual Dify API endpoints and showcase different functionality.

Prerequisites

Before running examples, ensure you have:

  1. Node.js 18+ installed
  2. Valid Dify API credentials (API key and base URL)
  3. Dependencies installed: pnpm install

Available Examples

1. Comprehensive Workflow Demo

Location: examples/comprehensive-workflow-demo.ts

Run Command:

npm run example:workflow

What it demonstrates:

  • ✅ Blocking workflow execution with timing
  • 🔄 Streaming workflow execution with real-time text output
  • ⚙️ Custom input parameters
  • 📊 Workflow run information retrieval
  • ✅ Parameter validation
  • 🎬 Event handling for different workflow stages

Sample Output:

🎯 Comprehensive Dify Workflow Demo
===================================

📋 Test 1: Blocking Workflow Execution
--------------------------------------
✅ Blocking execution completed in 6.852s
Response structure:
- Task ID: 95cc6b94-22ea-468d-94f8-8ecd46601fc1
- Status: succeeded
- Total Tokens: 268

🔄 Test 2: Streaming Workflow Execution
---------------------------------------
🚀 Starting streaming workflow...
📝 Streaming output (word by word):
---
Here's a short story about a curious robot... [streaming text appears here]
✅ Streaming execution completed in 13.708s
- Total chunks received: 428
- Event type distribution: { text_chunk: 420, workflow_started: 1, ... }

2. API Debugging Tool

Location: examples/debug-api.ts

Run Command:

npm run debug:api

What it demonstrates:

  • 🔍 App info and parameters retrieval
  • 💬 Chat completion API usage
  • 🔧 Workflow API with detailed logging
  • 🐛 Error analysis and troubleshooting

3. Raw API Testing

Location: examples/raw-api-test.js

Run Command:

npm run test:raw

What it demonstrates:

  • 🧪 Low-level API testing with raw fetch calls
  • 📡 Direct HTTP request/response analysis
  • 🔧 API connectivity troubleshooting
  • ⚡ Bypasses client library for pure API testing

Configuring Examples

Most examples include API credentials that you'll need to update:

// Update these values in the example files
const client = new DifyClient({
  baseUrl: 'https://api.dify.ai/v1', // Your Dify instance URL
  apiKey: 'your-api-key-here', // Your workflow/app API key
});

const userId = 'your-user-id'; // Your user identifier

Example Output Features

The examples showcase:

  • Real-time Streaming: Watch AI responses generate word-by-word
  • Performance Metrics: Execution time, token usage, chunk counts
  • Event Tracking: Workflow progression through different stages
  • Error Handling: Robust error catching and user-friendly messages
  • Type Safety: Full TypeScript integration with proper typing

Creating Custom Examples

You can create your own examples by following this pattern:

import { DifyClient } from '../src/index.js';

async function myCustomExample() {
  const client = new DifyClient({
    baseUrl: 'https://api.dify.ai/v1',
    apiKey: 'your-api-key',
  });

  try {
    const response = await client.workflow.runWorkflow({
      inputs: { query: 'Your custom input' },
      user: 'your-user-id',
      response_mode: 'streaming',
      chunkCompletionCallback: (chunk) => {
        // Handle streaming chunks
        console.log('Received chunk:', chunk.event);
      },
    });

    console.log('Success:', response);
  } catch (error) {
    console.error('Error:', error.message);
  }
}

myCustomExample().catch(console.error);

Troubleshooting Examples

If examples fail to run:

  1. Check API credentials - Ensure your API key and base URL are correct
  2. Verify network connectivity - Test if you can reach the Dify API
  3. Review console output - Examples provide detailed error messages
  4. Check API quotas - Ensure you have sufficient API credits
  5. Validate workflow configuration - Make sure your workflow accepts the input parameters

Setup

Install the dependencies:

pnpm install

Get started

Build the library:

pnpm build

Build the library in watch mode:

pnpm dev

Commit Convention

This project follows Conventional Commits specification. All commit messages must be formatted as:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
  • refactor: A code change that neither fixes a bug nor adds a feature
  • perf: A code change that improves performance
  • test: Adding missing tests or correcting existing tests
  • build: Changes that affect the build system or external dependencies
  • ci: Changes to our CI configuration files and scripts
  • chore: Other changes that don't modify src or test files
  • revert: Reverts a previous commit

Examples

feat: add user authentication
fix: resolve memory leak in data processing
docs: update API documentation
style: format code with prettier
refactor: extract utility functions
perf: optimize database queries
test: add unit tests for user service
build: update dependencies
ci: add automated testing workflow
chore: update .gitignore

Git Hooks

This project uses Husky to run git hooks:

  • pre-commit: Runs code formatting and tests
  • commit-msg: Validates commit message format

The hooks will automatically run when you commit. If they fail, the commit will be rejected.