UNPKG

@ifzai/connect2dify

Version:

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

673 lines (672 loc) 23.8 kB
"use strict"; var __webpack_require__ = {}; (()=>{ __webpack_require__.d = (exports1, definition)=>{ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, { enumerable: true, get: definition[key] }); }; })(); (()=>{ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop); })(); (()=>{ __webpack_require__.r = (exports1)=>{ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, { value: 'Module' }); Object.defineProperty(exports1, '__esModule', { value: true }); }; })(); var __webpack_exports__ = {}; __webpack_require__.r(__webpack_exports__); __webpack_require__.d(__webpack_exports__, { DifyClient: ()=>DifyClient, MIME_MAP: ()=>MIME_MAP, buildURL: ()=>buildURL, AppAPI: ()=>AppAPI, FileAPI: ()=>FileAPI, createHeaders: ()=>createHeaders, handleResponse: ()=>handleResponse, ConversationAPI: ()=>ConversationAPI, handleStreamResponse: ()=>handleStreamResponse, Client: ()=>Client, WorkflowAPI: ()=>WorkflowAPI, parseSSEChunk: ()=>parseSSEChunk, ChatAPI: ()=>ChatAPI }); function createHeaders(apiKey, extraHeaders = {}, includeContentType = true) { const headers = { Authorization: `Bearer ${apiKey}`, ...extraHeaders }; if (includeContentType) headers['Content-Type'] = 'application/json'; return headers; } async function handleResponse(response) { if (!response.ok) throw new Error(`Request failed: ${response.status} ${response.statusText}`); return response.json(); } function parseSSEChunk(chunkData) { if (!chunkData.trim().startsWith('data:')) return null; try { return JSON.parse(chunkData.replace(/^data: /, '')); } catch (error) { console.error('Failed to parse chunk:', chunkData); throw new Error(`Invalid chunk format: ${chunkData}`); } } function processSSEBuffer(buffer, chunks, onChunk) { const splitMark = '\n\n'; let remainingBuffer = buffer; while(true){ const chunkEnd = remainingBuffer.indexOf(splitMark); if (-1 === chunkEnd) break; const chunkData = remainingBuffer.slice(0, chunkEnd + splitMark.length); remainingBuffer = remainingBuffer.slice(chunkEnd + splitMark.length); const chunk = parseSSEChunk(chunkData); if (chunk) { chunks.push(chunk); onChunk?.(chunk); } } return remainingBuffer; } async function handleStreamResponse(response, onChunk) { if (!response.body) throw new Error('Response body is empty'); const reader = response.body.getReader(); const chunks = []; let buffer = ''; try { while(true){ const { done, value } = await reader.read(); if (value) { buffer += new TextDecoder().decode(value, { stream: true }); buffer = processSSEBuffer(buffer, chunks, onChunk); } if (done) { processSSEBuffer(buffer, chunks, onChunk); break; } } } finally{ reader.releaseLock(); } return chunks; } function isStreamingSupported() { try { return 'undefined' != typeof ReadableStream && new Response(new ReadableStream()).body?.getReader() !== void 0; } catch { return false; } } function createFormData(params) { const formData = new FormData(); formData.append('file', params.file); formData.append('user', params.user); return formData; } function buildURL(baseUrl, path, params = {}) { let fullUrl; if (path.startsWith('/')) fullUrl = `${baseUrl}${path}`; else { const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`; fullUrl = `${normalizedBaseUrl}${path}`; } if (Object.keys(params).length > 0) { const queryParams = new URLSearchParams(); for (const [key, value] of Object.entries(params))if (null != value) queryParams.set(key, value); const queryString = queryParams.toString(); if (queryString) fullUrl += `?${queryString}`; } return fullUrl; } class AppAPI { config; constructor(config){ this.config = config; } async getParameters() { const url = buildURL(this.config.baseUrl, 'parameters'); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false) }); return handleResponse(response); } async getInfo() { const url = buildURL(this.config.baseUrl, 'info'); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false) }); return handleResponse(response); } async getMeta() { const url = buildURL(this.config.baseUrl, 'meta'); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false) }); return handleResponse(response); } async sendCompletionMessage(params) { const url = buildURL(this.config.baseUrl, 'completion-messages'); const body = { inputs: params.inputs || {}, response_mode: params.response_mode, user: params.user, files: params.files }; if ('blocking' === params.response_mode) { const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(body) }); return handleResponse(response); } const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(body) }); if (!response.ok) throw new Error(`Request failed: ${response.status} ${response.statusText}`); return handleStreamResponse(response, params.chunkCompletionCallback); } async stopCompletionMessage(params) { const url = buildURL(this.config.baseUrl, `completion-messages/${params.task_id}/stop`); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ user: params.user }) }); return handleResponse(response); } } class ChatAPI { config; constructor(config){ this.config = config; } async sendMessage(params) { const url = buildURL(this.config.baseUrl, 'chat-messages'); const body = { inputs: {}, ...params }; if ('streaming' === params.response_mode) return this.handleChatStream(url, body, params); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(body) }); return handleResponse(response); } async getMessages(params) { const queryParams = { conversation_id: params.conversation_id, user: params.user }; if (params.first_id) queryParams.first_id = params.first_id; if (params.limit) queryParams.limit = String(params.limit); const url = buildURL(this.config.baseUrl, 'messages', queryParams); const response = await fetch(url, { headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false), method: 'GET' }); return handleResponse(response); } async createMessageFeedback(params) { const url = buildURL(this.config.baseUrl, `messages/${params.message_id}/feedbacks`); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ rating: params.rating, user: params.user, content: params.content }) }); return handleResponse(response); } async getMessageSuggests(params) { const queryParams = { user: params.user }; const url = buildURL(this.config.baseUrl, `messages/${params.message_id}/suggested`, queryParams); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders) }); return handleResponse(response); } async stopMessageResponse(params) { const url = buildURL(this.config.baseUrl, `chat-messages/${params.task_id}/stop`); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ user: params.user }) }); return handleResponse(response); } async handleChatStream(url, body, params) { const extraHeaders = this.config.requestOptions?.extraHeaders || {}; if (!isStreamingSupported()) throw new Error('Streaming is not supported in this environment. Please use blocking mode instead.'); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, extraHeaders), body: JSON.stringify(body) }); if (!response.ok) throw new Error(`Request failed: ${response.status} ${response.statusText}`); return handleStreamResponse(response, params.chunkCompletionCallback); } } class ConversationAPI { config; constructor(config){ this.config = config; } async getConversations(params) { const queryParams = { user: params.user }; if (params.last_id) queryParams.last_id = params.last_id; if (params.limit) queryParams.limit = String(params.limit); if (params.sort_by) queryParams.sort_by = params.sort_by; const url = buildURL(this.config.baseUrl, 'conversations', queryParams); const response = await fetch(url, { headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false), method: 'GET' }); return handleResponse(response); } async deleteConversation(params) { const url = buildURL(this.config.baseUrl, `conversations/${params.conversation_id}`); const response = await fetch(url, { method: 'DELETE', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ user: params.user }) }); return handleResponse(response); } async renameConversation(params) { const url = buildURL(this.config.baseUrl, `conversations/${params.conversation_id}/name`); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ name: params.name, auto_generate: params.auto_generate, user: params.user }) }); return handleResponse(response); } } class FileAPI { config; constructor(config){ this.config = config; } async uploadFile(params) { const url = buildURL(this.config.baseUrl, 'files/upload'); const formData = createFormData(params); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false), body: formData }); return handleResponse(response); } async audioToText(params) { const url = buildURL(this.config.baseUrl, 'audio-to-text'); const formData = createFormData(params); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders, false), body: formData }); return handleResponse(response); } async textToAudio(params) { const url = buildURL(this.config.baseUrl, 'text-to-audio'); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(params) }); if (!response.ok) throw new Error(`Request failed: ${response.status} ${response.statusText}`); return response.blob(); } } class WorkflowAPI { config; constructor(config){ this.config = config; } async runWorkflow(params) { const url = buildURL(this.config.baseUrl, 'workflows/run'); const isStreaming = 'streaming' === params.response_mode; if (isStreaming) return this.handleWorkflowStream(params, url); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(params) }); return handleResponse(response); } async getWorkflow(params) { const url = buildURL(this.config.baseUrl, `workflows/run/${params.workflow_run_id}`); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders) }); return handleResponse(response); } async stopWorkflowTask(params) { const url = buildURL(this.config.baseUrl, `workflows/tasks/${params.task_id}/stop`); const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify({ user: params.user }) }); return handleResponse(response); } async getWorkflowLogs(params) { const queryParams = {}; if (params.keyword) queryParams.keyword = params.keyword; if (params.status) queryParams.status = params.status; if (params.page) queryParams.page = String(params.page); if (params.limit) queryParams.limit = String(params.limit); const url = buildURL(this.config.baseUrl, 'workflows/logs', queryParams); const response = await fetch(url, { method: 'GET', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders) }); return handleResponse(response); } async handleWorkflowStream(params, url) { const response = await fetch(url, { method: 'POST', headers: createHeaders(this.config.apiKey, this.config.requestOptions?.extraHeaders), body: JSON.stringify(params) }); if (!response.ok) { const errorText = await response.text(); throw new Error(`Workflow failed: ${response.status} ${response.statusText} - ${errorText}`); } if (!response.body) throw new Error(`Workflow failed: ${response.status} ${response.statusText}`); return handleStreamResponse(response, params.chunkCompletionCallback); } } class DifyClient { config; chat; conversation; workflow; file; app; constructor(config){ this.config = { baseUrl: config.baseUrl, apiKey: config.apiKey, defaultResponseMode: config.defaultResponseMode || 'blocking', defaultUser: config.defaultUser, requestOptions: config.requestOptions }; this.chat = new ChatAPI(this.config); this.conversation = new ConversationAPI(this.config); this.workflow = new WorkflowAPI(this.config); this.file = new FileAPI(this.config); this.app = new AppAPI(this.config); } updateConfig(newConfig) { this.config = { ...this.config, ...newConfig }; Object.assign(this.chat, new ChatAPI(this.config)); Object.assign(this.conversation, new ConversationAPI(this.config)); Object.assign(this.workflow, new WorkflowAPI(this.config)); Object.assign(this.file, new FileAPI(this.config)); Object.assign(this.app, new AppAPI(this.config)); } getConfig() { return { ...this.config }; } async sendMessage(params) { const result = await this.chat.sendMessage(params); if (Array.isArray(result)) throw new Error('Use sendMessageStream for streaming responses'); return result; } async sendMessageStream(params) { const streamParams = { ...params, response_mode: 'streaming' }; const result = await this.chat.sendMessage(streamParams); if (!Array.isArray(result)) throw new Error('Expected streaming response'); return async function*() { for (const chunk of result)yield chunk; }(); } async stopMessage(params) { return this.chat.stopMessageResponse(params); } async createMessageFeedback(params) { return this.chat.createMessageFeedback(params); } async getMessageSuggests(params) { return this.chat.getMessageSuggests(params); } async getConversations(params) { return this.conversation.getConversations(params); } async deleteConversation(params) { return this.conversation.deleteConversation(params); } async renameConversation(params) { return this.conversation.renameConversation(params); } async getMessages(params) { return this.chat.getMessages(params); } async runWorkflow(params) { const result = await this.workflow.runWorkflow(params); if (Array.isArray(result)) throw new Error('Use runWorkflowStream for streaming responses'); return result; } async runWorkflowStream(params) { const streamParams = { ...params, response_mode: 'streaming' }; const result = await this.workflow.runWorkflow(streamParams); if (!Array.isArray(result)) throw new Error('Expected streaming response'); return async function*() { for (const chunk of result)yield chunk; }(); } async getWorkflow(params) { return this.workflow.getWorkflow(params); } async stopWorkflowTask(params) { return this.workflow.stopWorkflowTask(params); } async getWorkflowLogs(params) { return this.workflow.getWorkflowLogs(params); } async uploadFile(params) { return this.file.uploadFile(params); } async audioToText(params) { return this.file.audioToText(params); } async getAppParameters(params) { return this.app.getParameters(); } async getAppInfo(params) { return this.app.getInfo(); } async getAppMeta(params) { return this.app.getMeta(); } async sendCompletionMessage(params) { const result = await this.app.sendCompletionMessage(params); if (Array.isArray(result)) throw new Error('Use sendCompletionMessageStream for streaming responses'); return result; } async sendCompletionMessageStream(params) { const streamParams = { ...params, response_mode: 'streaming' }; const result = await this.app.sendCompletionMessage(streamParams); if (!Array.isArray(result)) throw new Error('Expected streaming response'); return async function*() { for (const chunk of result)yield chunk; }(); } async stopCompletionMessage(params) { return this.app.stopCompletionMessage(params); } } const Client = DifyClient; const MIME_MAP = { document: { mimeTypes: [ 'text/plain', 'text/markdown', 'text/html', 'application/pdf', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/msword', 'text/csv', 'message/rfc822', 'application/vnd.ms-outlook', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.ms-powerpoint', 'application/xml', 'text/xml', 'application/epub+zip' ], extensions: [ '.txt', '.md', '.mdx', '.html', '.htm', '.pdf', '.xlsx', '.xls', '.docx', '.doc', '.csv', '.eml', '.msg', '.pptx', '.ppt', '.xml', '.epub' ] }, image: { mimeTypes: [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml' ], extensions: [ '.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg' ] }, audio: { mimeTypes: [ 'audio/mpeg', 'audio/mp4', 'audio/wav', 'audio/webm', 'audio/amr' ], extensions: [ '.mp3', '.mpga', '.m4a', '.wav', '.webm', '.amr' ] }, video: { mimeTypes: [ 'video/mp4', 'video/quicktime', 'video/mpeg', 'audio/mpeg' ], extensions: [ '.mp4', '.mov', '.mpeg', '.mpg', '.mpe' ] } }; exports.AppAPI = __webpack_exports__.AppAPI; exports.ChatAPI = __webpack_exports__.ChatAPI; exports.Client = __webpack_exports__.Client; exports.ConversationAPI = __webpack_exports__.ConversationAPI; exports.DifyClient = __webpack_exports__.DifyClient; exports.FileAPI = __webpack_exports__.FileAPI; exports.MIME_MAP = __webpack_exports__.MIME_MAP; exports.WorkflowAPI = __webpack_exports__.WorkflowAPI; exports.buildURL = __webpack_exports__.buildURL; exports.createHeaders = __webpack_exports__.createHeaders; exports.handleResponse = __webpack_exports__.handleResponse; exports.handleStreamResponse = __webpack_exports__.handleStreamResponse; exports.parseSSEChunk = __webpack_exports__.parseSSEChunk; for(var __webpack_i__ in __webpack_exports__)if (-1 === [ "AppAPI", "ChatAPI", "Client", "ConversationAPI", "DifyClient", "FileAPI", "MIME_MAP", "WorkflowAPI", "buildURL", "createHeaders", "handleResponse", "handleStreamResponse", "parseSSEChunk" ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__]; Object.defineProperty(exports, '__esModule', { value: true });