UNPKG

donobu

Version:

Create browser automations with an LLM agent and replay them as Playwright scripts.

149 lines 5.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlowsPersistenceVolatile = void 0; const FlowNotFoundException_1 = require("../exceptions/FlowNotFoundException"); /** * A volatile (in-memory) implementation of FlowsPersistence. */ class FlowsPersistenceVolatile { constructor() { this.flows = new Map(); this.screenshots = new Map(); this.toolCalls = new Map(); this.videos = new Map(); this.files = new Map(); this.browserStates = new Map(); } async saveMetadata(flowMetadata) { this.flows.set(flowMetadata.id, { ...flowMetadata }); } async getMetadataByFlowId(flowId) { const metadata = this.flows.get(flowId); if (!metadata) { throw FlowNotFoundException_1.FlowNotFoundException.forId(flowId); } return { ...metadata }; } async getMetadataByFlowName(flowName) { const flows = Array.from(this.flows.values()).filter((flow) => flow.name === flowName); if (flows.length > 0) { return { ...flows[0] }; } throw FlowNotFoundException_1.FlowNotFoundException.forName(flowName); } async savePngScreenShot(flowId, bytes) { if (!this.screenshots.has(flowId)) { this.screenshots.set(flowId, new Map()); } const filename = `${new Date().toISOString()}.screenshot.png`; this.screenshots.get(flowId).set(filename, Buffer.from(bytes)); return filename; } async getPngScreenShot(flowId, screenShotId) { return this.getFlowFile(flowId, screenShotId); } async saveToolCall(flowId, toolCall) { if (!this.toolCalls.has(flowId)) { this.toolCalls.set(flowId, []); } this.toolCalls.get(flowId).push({ ...toolCall }); } async getToolCalls(flowId) { if (!this.flows.has(flowId)) { throw FlowNotFoundException_1.FlowNotFoundException.forId(flowId); } const calls = this.toolCalls.get(flowId) || []; return [...calls].sort((a, b) => (a.startedAt || 0) - (b.startedAt || 0)); } /** * Get flows with pagination and filtering from in-memory storage. */ async getFlows(query) { const { limit = 20, pageToken, name, runMode, state, startedAfter, startedBefore, } = query || {}; // Validate inputs. const validLimit = Math.min(Math.max(1, limit), 100); // Get all flows let filteredFlows = Array.from(this.flows.values()); // Apply filters if (name) { filteredFlows = filteredFlows.filter((flow) => flow.name === name); } if (runMode) { filteredFlows = filteredFlows.filter((flow) => flow.runMode === runMode); } if (state) { filteredFlows = filteredFlows.filter((flow) => flow.state === state); } // Apply startedAfter filter if (startedAfter !== undefined) { filteredFlows = filteredFlows.filter((flow) => (flow.startedAt || 0) >= startedAfter); } // Apply startedBefore filter if (startedBefore !== undefined) { filteredFlows = filteredFlows.filter((flow) => (flow.startedAt || 0) <= startedBefore); } // Sort by startedAt (newest first). filteredFlows.sort((a, b) => (b.startedAt || 0) - (a.startedAt || 0)); // Parse page token to get the offset. const offset = pageToken ? parseInt(pageToken, 10) : 0; // Slice the array to get paginated results. const paginatedFlows = filteredFlows.slice(offset, offset + validLimit); // Check if there are more results. const hasMore = offset + validLimit < filteredFlows.length; // Calculate next page token. const nextPageToken = hasMore ? (offset + validLimit).toString() : undefined; return { items: paginatedFlows.map((flow) => ({ ...flow })), // Return copies to prevent modification nextPageToken, }; } async setVideo(flowId, bytes) { this.videos.set(flowId, Buffer.from(bytes)); } async getVideoSegment(flowId, startOffset, length) { const video = this.videos.get(flowId); if (!video) { return null; } const totalLength = video.length; const adjustedLength = Math.min(length, totalLength - startOffset); return { bytes: video.slice(startOffset, startOffset + adjustedLength), totalLength, startOffset, }; } async getFlowFile(flowId, fileId) { const flowFiles = this.files.get(flowId); if (!flowFiles) { return null; } const file = flowFiles.get(fileId); return file ? Buffer.from(file) : null; } async setFlowFile(flowId, fileId, fileBytes) { if (!this.files.has(flowId)) { this.files.set(flowId, new Map()); } this.files.get(flowId).set(fileId, Buffer.from(fileBytes)); } async setBrowserState(flowId, browserState) { this.browserStates.set(flowId, { ...browserState }); } async getBrowserState(flowId) { const state = this.browserStates.get(flowId); return state ? { ...state } : null; } async deleteFlow(flowId) { this.flows.delete(flowId); this.screenshots.delete(flowId); this.toolCalls.delete(flowId); this.videos.delete(flowId); this.files.delete(flowId); this.browserStates.delete(flowId); } } exports.FlowsPersistenceVolatile = FlowsPersistenceVolatile; //# sourceMappingURL=FlowsPersistenceVolatile.js.map