n8n
Version:
n8n Workflow Automation Tool
120 lines • 5.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AgentChatHitlResumeHandler = void 0;
const agent_chat_integration_1 = require("./agent-chat-integration");
class AgentChatHitlResumeHandler {
constructor(options) {
this.options = options;
this.activeResumedRuns = new Set();
}
async handleAction(event) {
const { thread } = event;
if (!thread) {
this.options.logger.warn('[AgentChatBridge] Thread is not set for event', {
threadId: event.threadId,
actionId: event.actionId,
});
return;
}
const callbackData = await this.resolveCallbackData(event.actionId, event.value, thread);
if (!callbackData)
return;
const parsed = this.parseActionId(callbackData.actionId, callbackData.value);
if (!parsed)
return;
const platformThreadId = this.options.resolvePlatformThreadId(thread);
const threadId = this.options.toAgentThreadId(platformThreadId);
await this.options.messageContextBridge.updateLatest(threadId.id, event.user.userId, thread, {
messageId: event.messageId,
interactingUserId: event.user.userId,
...this.options.getPlatformAgentContext(),
});
await this.cleanUpBeforeResume(event);
await this.executeResume(thread, parsed.runId, parsed.toolCallId, parsed.resumeData);
}
parseActionId(actionId, value) {
if (actionId.startsWith('ri-sel:')) {
const parts = actionId.split(':');
if (parts.length < 4) {
this.options.logger.warn('[AgentChatBridge] Malformed ri-sel action ID', { actionId });
return null;
}
return {
runId: parts[2],
toolCallId: parts.slice(3).join(':'),
resumeData: { type: 'select', id: parts[1], value },
};
}
if (actionId.startsWith('resume:')) {
const parts = actionId.split(':');
if (parts.length < 4) {
this.options.logger.warn('[AgentChatBridge] Malformed action ID', { actionId });
return null;
}
let resumeData;
try {
resumeData = JSON.parse(value ?? '');
}
catch {
resumeData = { value };
}
return { runId: parts[1], toolCallId: parts.slice(2, -1).join(':'), resumeData };
}
return null;
}
async resolveCallbackData(actionId, value, thread) {
if (!this.options.callbackStore)
return { actionId, value };
const resolved = await this.options.callbackStore.resolve(actionId);
if (!resolved) {
this.options.logger.warn('[AgentChatBridge] Callback key not found or expired', { actionId });
await thread.post('This action is no longer available. The link may have expired or already been used.');
return null;
}
return { actionId: resolved.actionId, value: resolved.value };
}
async cleanUpBeforeResume(event) {
try {
await event.adapter.deleteMessage(event.threadId, event.messageId);
}
catch (deleteError) {
this.options.logger.warn('[AgentChatBridge] Failed to delete card message', {
error: deleteError instanceof Error ? deleteError.message : String(deleteError),
});
}
}
async executeResume(thread, runId, toolCallId, resumeData) {
if (this.activeResumedRuns.has(runId)) {
this.options.logger.warn('[AgentChatBridge] Run is already active', { runId, toolCallId });
await thread.post('This action has already been handled');
return;
}
this.activeResumedRuns.add(runId);
try {
const resumeExecutionContext = await this.options.createResumeExecutionContext(thread);
const statusHandle = (0, agent_chat_integration_1.onceStatusHandle)(resumeExecutionContext.statusHandle);
try {
const stream = this.options.agentService.resumeForChat({
agentId: this.options.agentId,
projectId: this.options.projectId,
runId,
toolCallId,
resumeData,
integrationType: this.options.integration.type,
});
await this.options.streamConsumer.consume(stream, thread, {
...resumeExecutionContext,
statusHandle,
});
}
finally {
await statusHandle?.clearBeforeResponse();
}
}
finally {
this.activeResumedRuns.delete(runId);
}
}
}
exports.AgentChatHitlResumeHandler = AgentChatHitlResumeHandler;
//# sourceMappingURL=agent-chat-hitl-resume-handler.js.map