UNPKG

@autobe/agent

Version:

AI backend server code generator

409 lines (405 loc) 19.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAutoBeContext = void 0; const core_1 = require("@agentica/core"); const utils_1 = require("@autobe/utils"); const tstl_1 = require("tstl"); const typia_1 = __importDefault(require("typia")); const uuid_1 = require("uuid"); const AutoBeTokenUsageComponent_1 = require("../context/AutoBeTokenUsageComponent"); const AutoBeTimeoutError_1 = require("../utils/AutoBeTimeoutError"); const TimedConversation_1 = require("../utils/TimedConversation"); const consentFunctionCall_1 = require("./consentFunctionCall"); const getCommonPrompt_1 = require("./getCommonPrompt"); const getCriticalCompiler_1 = require("./getCriticalCompiler"); const supportMistral_1 = require("./supportMistral"); const createAutoBeContext = (props) => { var _a, _b, _c; const config = { retry: (_a = props.config.retry) !== null && _a !== void 0 ? _a : 4 /* AutoBeConfigConstant.RETRY */, locale: (_b = props.config.locale) !== null && _b !== void 0 ? _b : "en-US", timeout: (_c = props.config.timeout) !== null && _c !== void 0 ? _c : null, }; const critical = new tstl_1.Semaphore(2); return { model: props.model, vendor: props.vendor, retry: config.retry, locale: config.locale, aggregates: props.aggregates, compilerListener: props.compilerListener, compiler: () => __awaiter(void 0, void 0, void 0, function* () { const compiler = yield props.compiler(); return (0, getCriticalCompiler_1.getCriticalCompiler)(critical, compiler); }), files: props.files, histories: props.histories, state: props.state, usage: props.usage, dispatch: createDispatch(props), assistantMessage: (message) => { props.histories().push(message); setTimeout(() => { void props.dispatch(message).catch(() => { }); }); return message; }, conversate: (next, closure) => __awaiter(void 0, void 0, void 0, function* () { const aggregate = utils_1.AutoBeProcessAggregateFactory.createAggregate(); const metric = (key) => { const accumulate = (collection) => { var _a; var _b; ++collection.total.metric[key]; (_a = collection[_b = next.source]) !== null && _a !== void 0 ? _a : (collection[_b] = utils_1.AutoBeProcessAggregateFactory.createAggregate()); ++collection[next.source].metric[key]; }; ++aggregate.metric[key]; accumulate(props.aggregates); }; const consume = (tokenUsage) => { var _a; const accumulate = (collection) => { var _a; var _b; utils_1.TokenUsageComputer.increment(collection.total.tokenUsage, tokenUsage); (_a = collection[_b = next.source]) !== null && _a !== void 0 ? _a : (collection[_b] = utils_1.AutoBeProcessAggregateFactory.createAggregate()); utils_1.TokenUsageComputer.increment(collection[next.source].tokenUsage, tokenUsage); }; utils_1.TokenUsageComputer.increment(aggregate.tokenUsage, tokenUsage); accumulate(props.aggregates); props .usage() .record(tokenUsage, [ (_a = STAGES.find((stage) => next.source.startsWith(stage))) !== null && _a !== void 0 ? _a : "analyze", ]); }; const progress = { request: 0, response: 0, timeout: 0, }; const execute = () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d; // CREATE AGENT const agent = new core_1.MicroAgentica({ model: props.model, vendor: props.vendor, config: Object.assign(Object.assign({}, ((_a = props.config) !== null && _a !== void 0 ? _a : {})), { retry: (_c = (_b = props.config) === null || _b === void 0 ? void 0 : _b.retry) !== null && _c !== void 0 ? _c : 4 /* AutoBeConfigConstant.RETRY */, executor: { describe: null, }, systemPrompt: { common: () => (0, getCommonPrompt_1.getCommonPrompt)(props.config), } }), histories: next.histories, controllers: [next.controller], }); (0, supportMistral_1.supportMistral)(agent, props.vendor); // ADD EVENT LISTENERS agent.on("request", (event) => __awaiter(void 0, void 0, void 0, function* () { if (next.enforceFunctionCall === true && event.body.tools) event.body.tool_choice = "required"; if (event.body.parallel_tool_calls !== undefined) delete event.body.parallel_tool_calls; if (next.promptCacheKey) event.body.prompt_cache_key = next.promptCacheKey; yield props.dispatch(Object.assign(Object.assign({}, event), { type: "vendorRequest", source: next.source, retry: progress.request++ })); })); agent.on("response", (event) => __awaiter(void 0, void 0, void 0, function* () { void props .dispatch(Object.assign(Object.assign({}, event), { type: "vendorResponse", source: next.source, retry: progress.response++ })) .catch(() => { }); })); agent.on("call", () => { metric("attempt"); }); agent.on("jsonParseError", (event) => { metric("invalidJson"); void props .dispatch(Object.assign(Object.assign({}, event), { function: event.operation.function.name, source: next.source })) .catch(() => { }); }); agent.on("validate", (event) => { metric("validationFailure"); void props .dispatch({ type: "jsonValidateError", id: (0, uuid_1.v7)(), source: next.source, function: event.operation.function.name, result: event.result, life: event.life, created_at: event.created_at, }) .catch(() => { }); }); if (closure) closure(agent); // DO CONVERSATE const message = next.enforceFunctionCall === true ? utils_1.StringUtil.trim ` ${next.userMessage} > You have to call function(s) of below to accomplish my request. > > Never hesitate the function calling. Never ask for me permission > to execute the function. Never explain me your plan with waiting > for my approval. > > I gave you every information for the function calling, so just > call it. I repeat that, never hesitate the function calling. > Just do it without any explanation. > ${next.controller.application.functions .map((f) => `> - ${f.name}`) .join("\n")} ` : next.userMessage; const result = yield TimedConversation_1.TimedConversation.process({ timeout: config.timeout, agent, message, }); const tokenUsage = agent .getTokenUsage() .toJSON().aggregate; props .usage() .record(tokenUsage, [ (_d = STAGES.find((stage) => next.source.startsWith(stage))) !== null && _d !== void 0 ? _d : "analyze", ]); consume(tokenUsage); const success = (histories) => { metric("success"); return { histories, tokenUsage: aggregate.tokenUsage, metric: aggregate.metric, __agent: agent, }; }; if (result.type === "error") throw result.error; else if (result.type === "timeout") { void props .dispatch({ type: "vendorTimeout", id: (0, uuid_1.v7)(), source: next.source, timeout: config.timeout, retry: progress.timeout++, created_at: new Date().toISOString(), }) .catch(() => { }); throw result.error; } else if (true === next.enforceFunctionCall && false === result.histories.some((h) => h.type === "execute" && h.success === true)) { const failure = () => { throw new Error(utils_1.StringUtil.trim ` Failed to function calling in the ${next.source} step. Here is the list of history types that occurred during the conversation: ${result.histories.map((h) => `- ${h.type}`).join("\n")} ${JSON.stringify(result.histories)} `); }; const last = result.histories.at(-1); if ((last === null || last === void 0 ? void 0 : last.type) === "assistantMessage" && last.text.trim().length !== 0) { metric("consent"); const consent = yield (0, consentFunctionCall_1.consentFunctionCall)({ source: next.source, dispatch: (e) => { props.dispatch(e).catch(() => { }); }, config: props.config, vendor: props.vendor, assistantMessage: last.text, }); if (consent !== null) { const newHistories = yield agent.conversate(consent); const newTokenUsage = AutoBeTokenUsageComponent_1.AutoBeTokenUsageComponent.minus(new AutoBeTokenUsageComponent_1.AutoBeTokenUsageComponent(agent.getTokenUsage().toJSON().aggregate), new AutoBeTokenUsageComponent_1.AutoBeTokenUsageComponent(tokenUsage)); consume(newTokenUsage); if (newHistories.some((h) => h.type === "execute" && h.success)) return success(newHistories); } } failure(); } return success(result.histories); }); if (next.enforceFunctionCall === true) return yield forceRetry(execute, config.retry); else return yield execute(); }), getCurrentAggregates: (phase) => { const previous = utils_1.AutoBeProcessAggregateFactory.reduce(props .histories() .filter((h) => h.type === "analyze" || h.type === "prisma" || h.type === "interface" || h.type === "test" || h.type === "realize") .map((h) => h.aggregates)); return utils_1.AutoBeProcessAggregateFactory.filterPhase(utils_1.AutoBeProcessAggregateFactory.minus(props.aggregates, previous), phase); }, }; }; exports.createAutoBeContext = createAutoBeContext; const createDispatch = (props) => { let analyzeStart = null; let prismaStart = null; let interfaceStart = null; let testStart = null; let realizeStart = null; return (event) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j; // starts if (event.type === "analyzeStart") analyzeStart = event; else if (event.type === "prismaStart") prismaStart = event; else if (event.type === "interfaceStart") interfaceStart = event; else if (event.type === "testStart") testStart = event; else if (event.type === "realizeStart") realizeStart = event; // completes else if (event.type === "analyzeComplete") return transformAndDispatch({ dispatch: props.dispatch, histories: props.histories, state: props.state, event, history: { type: "analyze", id: (0, uuid_1.v7)(), prefix: event.prefix, actors: event.actors, files: event.files, aggregates: event.aggregates, step: event.step, created_at: (_a = analyzeStart === null || analyzeStart === void 0 ? void 0 : analyzeStart.created_at) !== null && _a !== void 0 ? _a : new Date().toISOString(), completed_at: event.created_at, }, }); else if (event.type === "prismaComplete") return transformAndDispatch({ dispatch: props.dispatch, histories: props.histories, state: props.state, event, history: { type: "prisma", id: (0, uuid_1.v7)(), instruction: (_b = prismaStart === null || prismaStart === void 0 ? void 0 : prismaStart.reason) !== null && _b !== void 0 ? _b : "", schemas: event.schemas, result: event.result, compiled: event.compiled, aggregates: event.aggregates, step: event.step, created_at: (_c = prismaStart === null || prismaStart === void 0 ? void 0 : prismaStart.created_at) !== null && _c !== void 0 ? _c : new Date().toISOString(), completed_at: event.created_at, }, }); else if (event.type === "interfaceComplete") return transformAndDispatch({ dispatch: props.dispatch, histories: props.histories, state: props.state, event, history: { type: "interface", id: (0, uuid_1.v7)(), instruction: (_d = interfaceStart === null || interfaceStart === void 0 ? void 0 : interfaceStart.reason) !== null && _d !== void 0 ? _d : "", authorizations: event.authorizations, document: event.document, missed: event.missed, aggregates: event.aggregates, step: event.step, created_at: (_e = interfaceStart === null || interfaceStart === void 0 ? void 0 : interfaceStart.created_at) !== null && _e !== void 0 ? _e : new Date().toISOString(), completed_at: new Date().toISOString(), }, }); else if (event.type === "testComplete") return transformAndDispatch({ dispatch: props.dispatch, histories: props.histories, state: props.state, event, history: { type: "test", id: (0, uuid_1.v7)(), instruction: (_f = testStart === null || testStart === void 0 ? void 0 : testStart.reason) !== null && _f !== void 0 ? _f : "", files: event.files, compiled: event.compiled, aggregates: event.aggregates, step: event.step, created_at: (_g = testStart === null || testStart === void 0 ? void 0 : testStart.created_at) !== null && _g !== void 0 ? _g : new Date().toISOString(), completed_at: new Date().toISOString(), }, }); else if (event.type === "realizeComplete") return transformAndDispatch({ dispatch: props.dispatch, histories: props.histories, state: props.state, event, history: { type: "realize", id: (0, uuid_1.v7)(), instruction: (_h = realizeStart === null || realizeStart === void 0 ? void 0 : realizeStart.reason) !== null && _h !== void 0 ? _h : "", authorizations: event.authorizations, functions: event.functions, controllers: event.controllers, compiled: event.compiled, aggregates: event.aggregates, step: event.step, created_at: (_j = realizeStart === null || realizeStart === void 0 ? void 0 : realizeStart.created_at) !== null && _j !== void 0 ? _j : new Date().toISOString(), completed_at: new Date().toISOString(), }, }); void props.dispatch(event).catch(() => { }); return null; }; }; const transformAndDispatch = (props) => { props.histories().push(props.history); props.state()[props.history.type] = props.history; void props.dispatch(props.event).catch(() => { }); return props.history; }; const forceRetry = (task, count) => __awaiter(void 0, void 0, void 0, function* () { let error = undefined; for (let i = 0; i < count; ++i) try { return yield task(); } catch (e) { if (e instanceof AutoBeTimeoutError_1.AutoBeTimeoutError) throw e; error = e; } throw error; }); const STAGES = [ "analyze", "prisma", "interface", "test", "realize" ]; //# sourceMappingURL=createAutoBeContext.js.map