UNPKG

@agentica/core

Version:

Agentic AI Library specialized in LLM Function Calling

180 lines (162 loc) 5.45 kB
import type { ILlmSchema } from "@samchon/openapi"; import type { IAgenticaConfig } from "../../structures/IAgenticaConfig"; import type { IAgenticaController } from "../../structures/IAgenticaController"; import type { IMicroAgenticaConfig } from "../../structures/IMicroAgenticaConfig"; import type { AgenticaOperation } from "../AgenticaOperation"; import type { AgenticaOperationCollection } from "../AgenticaOperationCollection"; import { __map_take } from "../../utils/__map_take"; /** * Compose the agentica operation collection. * * Compose the {@link AgenticaOperationCollection} from the given * controllers and config. * * @internal */ export function compose<Model extends ILlmSchema.Model>(props: { controllers: IAgenticaController<Model>[]; config?: IAgenticaConfig<Model> | IMicroAgenticaConfig<Model> | undefined; }): AgenticaOperationCollection<Model> { const unique: boolean = (props.controllers.length === 1 || (() => { const names = props.controllers.map( controllers => controllers.application.functions.map((func: { name: string }) => func.name), ).flat(); return new Set(names).size === names.length; })()); const array: AgenticaOperation<Model>[] = getOperations({ controllers: props.controllers, naming: (func: string, controllerIndex: number) => unique ? func : `_${controllerIndex}_${func}`, }); const capacity: number | undefined = (props.config as IAgenticaConfig<Model>)?.capacity; const divided: AgenticaOperation<Model>[][] | undefined = capacity !== undefined && array.length > capacity ? divide({ array, capacity, }) : undefined; const flat: Map<string, AgenticaOperation<Model>> = new Map(); const group: Map<string, Map<string, AgenticaOperation<Model>>> = new Map(); for (const item of array) { flat.set(item.name, item); __map_take(group, item.controller.name, () => new Map()).set( item.name, item, ); } return { array, divided, flat, group, }; } /** * @internal */ export function getOperations<Model extends ILlmSchema.Model>(props: { controllers: IAgenticaController<Model>[]; naming: (func: string, controllerIndex: number) => string; }): AgenticaOperation<Model>[] { return props.controllers.flatMap((controller, idx) => { switch (controller.protocol) { case "http":{ return toHttpOperations({ controller, index: idx, naming: props.naming }); } case "class":{ return toClassOperations({ controller, index: idx, naming: props.naming }); } case "mcp": { return toMcpOperations({ controller, index: idx, naming: props.naming }); } default: controller satisfies never; throw new Error(`Unsupported protocol: ${(controller as { protocol: string }).protocol}`); } }); } /** * @internal */ export function toHttpOperations<Model extends ILlmSchema.Model>(props: { controller: IAgenticaController.IHttp<Model>; index: number; naming: (func: string, controllerIndex: number) => string; }): AgenticaOperation<Model>[] { return props.controller.application.functions.map(func => ({ protocol: "http", controller: props.controller, function: func, name: props.naming(func.name, props.index), toJSON: () => ({ protocol: "http", controller: props.controller.name, function: func.name, name: props.naming(func.name, props.index), }), })); } /** * @internal */ export function toClassOperations<Model extends ILlmSchema.Model>(props: { controller: IAgenticaController.IClass<Model>; index: number; naming: (func: string, controllerIndex: number) => string; }): AgenticaOperation<Model>[] { return props.controller.application.functions.map(func => ({ protocol: "class", controller: props.controller, function: func, name: props.naming(func.name, props.index), toJSON: () => ({ protocol: "class", controller: props.controller.name, function: func.name, name: props.naming(func.name, props.index), }), })); } /** * @internal */ export function toMcpOperations<Model extends ILlmSchema.Model>(props: { controller: IAgenticaController.IMcp<Model>; index: number; naming: (func: string, controllerIndex: number) => string; }): AgenticaOperation<Model>[] { return props.controller.application.functions.map(func => ({ protocol: "mcp", controller: props.controller, function: func, name: props.naming(func.name, props.index), toJSON: () => ({ protocol: "mcp", controller: props.controller.name, function: func.name, name: props.naming(func.name, props.index), }), })); } /** * @internal */ export function divide<T>(props: { array: T[]; capacity: number; }): T[][] { if (props.capacity <= 0) { throw new Error("Capacity must be a positive integer"); } if (Number.isNaN(props.capacity)) { throw new TypeError("Capacity must be a positive integer"); } if (props.capacity === Infinity) { throw new Error("Capacity must be a positive integer"); } const size: number = Math.ceil(props.array.length / props.capacity); const capacity: number = Math.ceil(props.array.length / size); const replica: T[] = props.array.slice(); return Array.from({ length: size }, () => replica.splice(0, capacity)); } export const AgenticaOperationComposer = { compose, };