donobu
Version:
Create browser automations with an LLM agent and replay them as Playwright scripts.
155 lines • 6.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FlowCatalog = void 0;
const FlowNotFoundException_1 = require("../exceptions/FlowNotFoundException");
const FederatedPagination_1 = require("./FederatedPagination");
/**
* Centralized access layer for flow metadata, tool calls, and browser state.
*
* Responsibilities:
* - Prefer in-memory runtime state when running locally (so callers see live mutations)
* - Federate reads across all configured persistence layers with simple pagination merge
* - Provide a single surface for flow metadata, tool call history, browser state, and deletes
*/
class FlowCatalog {
constructor(flowsPersistenceRegistry, flowRuntime, deploymentEnvironment) {
this.flowsPersistenceRegistry = flowsPersistenceRegistry;
this.flowRuntime = flowRuntime;
this.deploymentEnvironment = deploymentEnvironment;
}
async getFlowById(flowId) {
if (this.isLocal()) {
const activeMetadata = this.flowRuntime.metadataFor(flowId);
if (activeMetadata) {
return activeMetadata;
}
}
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
try {
return await persistence.getFlowMetadataById(flowId);
}
catch (error) {
if (!(error instanceof FlowNotFoundException_1.FlowNotFoundException)) {
throw error;
}
}
}
throw FlowNotFoundException_1.FlowNotFoundException.forId(flowId);
}
async getFlowByName(flowName) {
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
try {
return await persistence.getFlowMetadataByName(flowName);
}
catch (error) {
if (!(error instanceof FlowNotFoundException_1.FlowNotFoundException)) {
throw error;
}
}
}
throw FlowNotFoundException_1.FlowNotFoundException.forName(flowName);
}
async getToolCalls(flowId) {
if (this.isLocal()) {
const activeHandle = this.flowRuntime.get(flowId);
if (activeHandle) {
const { invokedToolCalls, inProgressToolCall } = activeHandle.donobuFlow;
const all = inProgressToolCall
? [...invokedToolCalls, inProgressToolCall]
: [...invokedToolCalls];
return all.sort((a, b) => new Date(a.startedAt).getTime() - new Date(b.startedAt).getTime());
}
}
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
try {
return await persistence.getToolCalls(flowId);
}
catch (error) {
if (!(error instanceof FlowNotFoundException_1.FlowNotFoundException)) {
throw error;
}
}
}
throw FlowNotFoundException_1.FlowNotFoundException.forId(flowId);
}
async getAiQueries(flowId) {
if (this.isLocal()) {
const activeHandle = this.flowRuntime.get(flowId);
if (activeHandle) {
return [...activeHandle.donobuFlow.aiQueries].sort((a, b) => a.startedAt - b.startedAt);
}
}
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
try {
return await persistence.getAiQueries(flowId);
}
catch (error) {
if (!(error instanceof FlowNotFoundException_1.FlowNotFoundException)) {
throw error;
}
}
}
throw FlowNotFoundException_1.FlowNotFoundException.forId(flowId);
}
async deleteFlow(flowId) {
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
await persistence.deleteFlow(flowId);
}
}
async getBrowserState(flowId) {
for (const persistence of await this.flowsPersistenceRegistry.getAll()) {
try {
const browserState = await persistence.getBrowserState(flowId);
if (browserState) {
return browserState;
}
}
catch (error) {
if (!(error instanceof FlowNotFoundException_1.FlowNotFoundException)) {
throw error;
}
}
}
return null;
}
async getFlows(query) {
const layers = (await this.flowsPersistenceRegistry.getAll()).map((persistence) => ({
getItems: (q) => persistence.getFlowsMetadata(q),
}));
const sortBy = query.sortBy ?? 'created_at';
const desc = (query.sortOrder ?? 'desc') === 'desc';
// For `created_at` we don't have a real field on FlowMetadata; use
// `startedAt` as a close-enough proxy, falling back to "now" when
// null so unstarted flows sort to the most-recent end.
const fieldFor = (flow) => {
switch (sortBy) {
case 'created_at':
return flow.startedAt ?? Date.now();
case 'name':
return flow.name ?? '';
case 'run_mode':
return flow.runMode;
case 'state':
return flow.state;
default:
return '';
}
};
return (0, FederatedPagination_1.federatedList)(layers, query, (a, b) => {
const aKey = fieldFor(a);
const bKey = fieldFor(b);
if (aKey < bKey) {
return desc ? 1 : -1;
}
if (aKey > bKey) {
return desc ? -1 : 1;
}
return 0;
});
}
isLocal() {
return this.deploymentEnvironment === 'LOCAL';
}
}
exports.FlowCatalog = FlowCatalog;
//# sourceMappingURL=FlowCatalog.js.map