ai-ip-plugin
Version:
AI-IP Plugin for MCP Workflow Management with SSE streaming and event handling
354 lines • 11 kB
JavaScript
"use strict";
/**
* MCP Manager - Core class for managing MCP workflows
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.MCPPlugin = exports.MCPManager = void 0;
const api_1 = require("../services/api");
const EventHandler_1 = require("./EventHandler");
const StreamProcessor_1 = require("./StreamProcessor");
const DataManager_1 = require("./DataManager");
const utils_1 = require("../utils");
class MCPManager {
constructor(config) {
this.streamController = null;
this.config = config;
this.apiService = new api_1.APIService(config);
this.eventHandler = new EventHandler_1.EventHandler();
this.streamProcessor = new StreamProcessor_1.StreamProcessor();
this.dataManager = new DataManager_1.DataManager();
this.state = {
taskId: null,
isLoading: false,
error: null,
currentStep: null,
};
this.setupEventHandlers();
}
/**
* Setup event handlers
*/
setupEventHandlers() {
this.eventHandler.on("workflow_created", (data) => {
this.updateState({ taskId: data.task_id, isLoading: true });
this.handleWorkflowCreated(data);
});
this.eventHandler.on("workflow_restarted", (data) => {
this.updateState({ taskId: data.thread_id, isLoading: true });
this.handleWorkflowRestarted(data);
});
this.eventHandler.on("start_of_agent", (data) => {
this.updateState({ currentStep: data.agent_name });
this.handleStartOfAgent(data);
});
this.eventHandler.on("end_of_agent", (data) => {
this.handleEndOfAgent(data);
});
this.eventHandler.on("message", (data) => {
this.handleMessage(data);
});
this.eventHandler.on("tool_call", (data) => {
this.handleToolCall(data);
});
this.eventHandler.on("tool_call_result", (data) => {
this.handleToolCallResult(data);
});
this.eventHandler.on("workflow_interrupted", (data) => {
this.updateState({ isLoading: false });
this.handleWorkflowInterrupted(data);
});
this.eventHandler.on("end_of_workflow", () => {
this.updateState({ isLoading: false, currentStep: null });
});
this.eventHandler.on("error", (data) => {
this.updateState({
isLoading: false,
error: data.message || "Unknown error",
});
this.handleError(data);
});
}
/**
* Update manager state
*/
updateState(updates) {
this.state = { ...this.state, ...updates };
this.config.onStateChange?.(this.state);
}
/**
* Start workflow
*/
async startWorkflow(params) {
try {
this.updateState({ isLoading: true, error: null });
const { responseData, controller } = await this.apiService.startWorkflow(params);
if (!responseData.ok || !responseData.body) {
throw new Error("Failed to start workflow");
}
this.streamController = {
controller,
reader: responseData.body.getReader(),
};
const handlers = this.createSSEHandlers();
if (this.streamController.reader) {
await this.streamProcessor.processStream(this.streamController.reader, handlers);
}
}
catch (error) {
this.updateState({ isLoading: false, error: error.message });
this.config.onError?.(error);
}
}
/**
* Continue workflow
*/
async continueWorkflow(params) {
try {
this.updateState({ isLoading: true, error: null });
const { responseData, controller } = await this.apiService.continueWorkflow(params);
if (!responseData.ok || !responseData.body) {
throw new Error("Failed to continue workflow");
}
this.streamController = {
controller,
reader: responseData.body.getReader(),
};
const handlers = this.createSSEHandlers();
if (this.streamController.reader) {
await this.streamProcessor.processStream(this.streamController.reader, handlers);
}
}
catch (error) {
this.updateState({ isLoading: false, error: error.message });
this.config.onError?.(error);
}
}
/**
* Resume workflow
*/
async resumeWorkflow(params) {
try {
this.updateState({ isLoading: true, error: null });
const { responseData, controller } = await this.apiService.resumeWorkflow(params);
if (!responseData.ok || !responseData.body) {
throw new Error("Failed to resume workflow");
}
this.streamController = {
controller,
reader: responseData.body.getReader(),
};
const handlers = this.createSSEHandlers();
if (this.streamController.reader) {
await this.streamProcessor.processStream(this.streamController.reader, handlers);
}
}
catch (error) {
this.updateState({ isLoading: false, error: error.message });
this.config.onError?.(error);
}
}
/**
* Stop workflow
*/
async stopWorkflow(params) {
try {
await this.apiService.stopWorkflow(params);
this.abortCurrentStream();
this.updateState({ isLoading: false });
}
catch (error) {
this.config.onError?.(error);
}
}
/**
* Get workflow history
*/
async getWorkflowHistory(taskId) {
try {
const response = await this.apiService.getWorkflowHistory(taskId);
if (!response.ok) {
throw new Error("Failed to get workflow history");
}
const result = await response.json();
return result.data?.history || [];
}
catch (error) {
this.config.onError?.(error);
return [];
}
}
/**
* Get workflow state data
*/
async getWorkflowStateData(taskId) {
try {
const result = await this.apiService.getWorkflowStateData(taskId);
if (result.code === 200) {
return {
success: true,
oralText: result.data.polisher_content || result.data.writer_content || "",
};
}
return { success: false, oralText: "" };
}
catch (error) {
this.config.onError?.(error);
return { success: false, oralText: "" };
}
}
/**
* Create SSE handlers
*/
createSSEHandlers() {
return {
onopen: () => {
console.log("SSE connection established");
},
onerror: (error) => {
console.error("SSE error:", error);
this.updateState({ isLoading: false, error: "Connection error" });
},
onmessage: ({ event, data }) => {
this.eventHandler.emit(event, data);
},
};
}
/**
* Abort current stream
*/
abortCurrentStream() {
if (this.streamController &&
!this.streamController.controller.signal.aborted) {
this.streamController.controller.abort();
this.streamController = null;
}
}
/**
* Get current state
*/
getState() {
return { ...this.state };
}
/**
* Get workflow data
*/
getWorkflowData() {
return this.dataManager.getWorkflowData();
}
/**
* Handle workflow created event
*/
handleWorkflowCreated(data) {
const uuid = (0, utils_1.generateUUID)();
const messageItem = {
content: data.user_input,
additional_kwargs: {},
response_metadata: {},
type: "human",
agent_type: "user",
name: "",
id: uuid,
example: false,
uuid: uuid,
event: "workflow_created",
task_id: data.task_id,
finished: true,
session_id: uuid,
tool_calls: [],
invalid_tool_calls: [],
};
this.dataManager.addWorkflowItem(uuid, messageItem);
this.notifyDataUpdate();
}
/**
* Handle workflow restarted event
*/
handleWorkflowRestarted(data) {
const uuid = (0, utils_1.generateUUID)();
const messageItem = {
content: data.user_input,
additional_kwargs: {},
response_metadata: {},
type: "human",
agent_type: "user",
name: "",
id: uuid,
example: false,
uuid: uuid,
event: "workflow_restarted",
task_id: data.thread_id,
finished: true,
session_id: uuid,
tool_calls: [],
invalid_tool_calls: [],
};
this.dataManager.addWorkflowItem(uuid, messageItem);
this.notifyDataUpdate();
}
/**
* Handle start of agent event
*/
handleStartOfAgent(data) {
this.dataManager.handleStartOfAgent(data);
this.notifyDataUpdate();
}
/**
* Handle end of agent event
*/
handleEndOfAgent(data) {
this.dataManager.handleEndOfAgent(data);
this.notifyDataUpdate();
}
/**
* Handle message event
*/
handleMessage(data) {
this.dataManager.handleMessage(data);
this.notifyDataUpdate();
}
/**
* Handle tool call event
*/
handleToolCall(data) {
this.dataManager.handleToolCall(data);
this.notifyDataUpdate();
}
/**
* Handle tool call result event
*/
handleToolCallResult(data) {
this.dataManager.handleToolCallResult(data);
this.notifyDataUpdate();
}
/**
* Handle workflow interrupted event
*/
handleWorkflowInterrupted(data) {
this.dataManager.handleWorkflowInterrupted(data);
this.notifyDataUpdate();
}
/**
* Handle error event
*/
handleError(data) {
this.dataManager.handleError(data);
this.notifyDataUpdate();
}
/**
* Notify data update
*/
notifyDataUpdate() {
this.config.onDataUpdate?.(this.dataManager.getWorkflowData());
}
/**
* Cleanup resources
*/
destroy() {
this.abortCurrentStream();
this.eventHandler.removeAllListeners();
this.dataManager.clear();
}
}
exports.MCPManager = MCPManager;
exports.MCPPlugin = MCPManager;
//# sourceMappingURL=MCPManager.js.map