338 lines
10 KiB
JavaScript
338 lines
10 KiB
JavaScript
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
|