Files
2026-01-12 09:12:41 +00:00

338 lines
10 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
EventType,
W,
from
} from "./chunk-IILPD2DB.js";
import "./chunk-A6PGQRKG.js";
import {
__publicField
} from "./chunk-EWTE5DHJ.js";
// node_modules/@shangzy/ag-ui-dify/dist/index.mjs
function difyMessagesToAgui(messages) {
return messages.map((msg) => ({
role: msg.role,
content: msg.content
}));
}
function aguiMessagesToDify(messages) {
return messages.map((msg) => ({
role: msg.role,
content: msg.content
}));
}
var DifyClient = class {
constructor(config) {
__publicField(this, "apiKey");
__publicField(this, "baseUrl");
this.apiKey = config.apiKey || "";
this.baseUrl = config.baseUrl || "";
}
async *streamChat(params) {
var _a;
const url = `${this.baseUrl}/chat-messages`;
const lastUserMessage = [...params.messages].reverse().find((msg) => msg.role === "user");
let body = {};
try {
body = JSON.parse(lastUserMessage == null ? void 0 : lastUserMessage.content);
} catch (error) {
body = {
inputs: {},
query: (lastUserMessage == null ? void 0 : lastUserMessage.content) || "",
response_mode: "streaming",
auto_generate_name: "true",
conversation_id: "",
// 如果需要保持对话上下文,这里需要传入
user: "ag-ui"
// 可以自定义用户标识
};
}
if (typeof body !== "object") {
body = {
inputs: {},
query: (lastUserMessage == null ? void 0 : lastUserMessage.content) || "",
response_mode: "streaming",
auto_generate_name: "true",
conversation_id: "",
// 如果需要保持对话上下文,这里需要传入
user: "ag-ui"
// 可以自定义用户标识
};
}
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${body.appKey || this.apiKey}`
},
body: JSON.stringify(
Object.assign(body, {
response_mode: "streaming",
auto_generate_name: "true"
})
)
});
if (!response.ok) {
console.error("Dify API 错误响应:", {
status: response.status,
statusText: response.statusText,
url: response.url
});
throw new Error(`Dify API error: ${response.statusText}`);
}
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
if (!reader) {
throw new Error("Failed to get response reader");
}
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const line of lines) {
if (line.trim() === "") continue;
if (!line.startsWith("data: ")) continue;
try {
const data = JSON.parse(line.slice(6));
yield data;
} catch (e) {
console.error("Failed to parse Dify stream data:", e);
}
}
}
}
};
var DifyAgent = class extends W {
constructor(config) {
super();
__publicField(this, "difyClient");
__publicField(this, "showMetadata");
__publicField(this, "showAgentLog");
this.showMetadata = config.showMetadata || false;
this.showAgentLog = config.showAgentLog || false;
this.difyClient = new DifyClient(config);
}
run(input) {
return from(this.stream(input));
}
async *stream(input) {
var _a, _b, _c;
const difyMessages = aguiMessagesToDify(input.messages);
const difyTools = (_a = input.tools) == null ? void 0 : _a.map((tool) => ({
name: tool.name,
description: tool.description,
parameters: tool.parameters
}));
const difyStream = await this.difyClient.streamChat({
messages: difyMessages,
tools: difyTools
});
yield {
type: EventType.RUN_STARTED,
timestamp: (/* @__PURE__ */ new Date()).getTime(),
threadId: input.threadId,
runId: input.runId
};
let conversationId = "";
let message = true;
let logContent = "";
let roundCount = 1;
let isMessageStart = false;
for await (const chunk of difyStream) {
switch (chunk.event) {
case "agent_message":
// 文本消息
case "message":
if (!conversationId) {
conversationId = `${chunk.conversation_id}_${chunk.message_id}`;
if (!isMessageStart) {
yield {
type: EventType.TEXT_MESSAGE_START,
messageId: conversationId,
role: "assistant",
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
isMessageStart = true;
}
}
if (chunk.answer) {
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: chunk.answer,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
break;
case "agent_log":
if (!this.showAgentLog) break;
if (!((_b = chunk.data) == null ? void 0 : _b.data)) break;
if (!conversationId) {
conversationId = `${chunk.conversation_id}_${chunk.message_id}`;
if (!isMessageStart) {
yield {
type: EventType.TEXT_MESSAGE_START,
messageId: conversationId,
role: "assistant",
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
isMessageStart = true;
}
}
try {
const logData = chunk.data.data || {};
const label = chunk.data.label;
const status = chunk.data.status;
if (label.includes("Thought") && status === "success" && logData.action) {
let thoughtContent = logData.thought || "";
if (thoughtContent.startsWith("<think>") && thoughtContent.endsWith("</think>") && thoughtContent.slice(7, -8).includes("<think>")) {
thoughtContent = thoughtContent.replace(/<\/think>\s*。\s*<\/think>/g, "</think></think>");
thoughtContent = thoughtContent.slice(7, -8).trim();
}
if (thoughtContent) {
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: `
**AI思考过程**
${thoughtContent}
`,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
} else if (label.includes("CALL") && status === "success" && logData.output) {
if ((_c = logData.tool_call_args) == null ? void 0 : _c.code) {
const language = logData.tool_call_args.language || "python";
logContent = `
\`\`\`${language}
${logData.tool_call_args.code.trim()}
\`\`\`
`;
}
try {
const output = JSON.parse(logData.output);
if (output.run_result) {
if (output.run_result.execution_time) {
logContent += `> 耗时:${output.run_result.execution_time.toFixed(2)}s
`;
}
if (output.run_result.stdout) {
logContent += `
输出:
\`\`\`plaintext
${output.run_result.stdout.trim()}
\`\`\`
`;
}
if (output.run_result.stderr) {
logContent += `
❌ 错误:
\`\`\`error
${output.run_result.stderr.trim()}
\`\`\`
`;
}
}
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: logContent,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
} catch (error) {
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: `
❌ **解析失败:** ${error.message}
`,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
} else if (label.includes("ROUND") && status === "start") {
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: `
<round data-id="round-${roundCount}">
### 第 ${roundCount} 轮思考
`,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
roundCount += 1;
} else if (label.includes("ROUND") && status === "success") {
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: `
</round>
`,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
} catch (error) {
console.error("处理Agent日志失败:", error);
yield {
type: EventType.TEXT_MESSAGE_CONTENT,
messageId: conversationId,
delta: `
❌ 处理执行日志失败: ${error.message}
`,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
break;
case "workflow_finished":
if (isMessageStart) {
message = false;
yield {
type: EventType.TEXT_MESSAGE_END,
messageId: conversationId,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
break;
case "message_end":
if (this.showMetadata) {
yield {
type: EventType.STATE_SNAPSHOT,
timestamp: (/* @__PURE__ */ new Date()).getTime(),
snapshot: {
name: "on_metadata",
metadata: chunk.metadata
}
};
}
if (message) {
if (isMessageStart) {
yield {
type: EventType.TEXT_MESSAGE_END,
messageId: conversationId,
timestamp: (/* @__PURE__ */ new Date()).getTime()
};
}
}
yield {
type: EventType.RUN_FINISHED,
timestamp: (/* @__PURE__ */ new Date()).getTime(),
threadId: input.threadId,
runId: input.runId
};
break;
}
}
}
};
export {
DifyAgent,
aguiMessagesToDify,
difyMessagesToAgui
};
//# sourceMappingURL=@shangzy_ag-ui-dify.js.map