{"version":3,"file":"HttpLlmApplicationComposer.mjs","sources":["../../src/composers/HttpLlmApplicationComposer.ts"],"sourcesContent":["import { OpenApi } from \"../OpenApi\";\nimport { IHttpLlmApplication } from \"../structures/IHttpLlmApplication\";\nimport { IHttpLlmFunction } from \"../structures/IHttpLlmFunction\";\nimport { IHttpMigrateApplication } from \"../structures/IHttpMigrateApplication\";\nimport { IHttpMigrateRoute } from \"../structures/IHttpMigrateRoute\";\nimport { ILlmFunction } from \"../structures/ILlmFunction\";\nimport { ILlmSchema } from \"../structures/ILlmSchema\";\nimport { IOpenApiSchemaError } from \"../structures/IOpenApiSchemaError\";\nimport { IResult } from \"../structures/IResult\";\nimport { OpenApiValidator } from \"../utils/OpenApiValidator\";\nimport { LlmSchemaComposer } from \"./LlmSchemaComposer\";\n\nexport namespace HttpLlmComposer {\n  export const application = <Model extends ILlmSchema.Model>(props: {\n    model: Model;\n    migrate: IHttpMigrateApplication;\n    options: IHttpLlmApplication.IOptions<Model>;\n  }): IHttpLlmApplication<Model> => {\n    // COMPOSE FUNCTIONS\n    const errors: IHttpLlmApplication.IError[] = props.migrate.errors\n      .filter((e) => e.operation()[\"x-samchon-human\"] !== true)\n      .map((e) => ({\n        method: e.method,\n        path: e.path,\n        messages: e.messages,\n        operation: () => e.operation(),\n        route: () => undefined,\n      }));\n    const functions: IHttpLlmFunction<Model>[] = props.migrate.routes\n      .filter((e) => e.operation()[\"x-samchon-human\"] !== true)\n      .map((route, i) => {\n        if (route.method === \"head\") {\n          errors.push({\n            method: route.method,\n            path: route.path,\n            messages: [\"HEAD method is not supported in the LLM application.\"],\n            operation: () => route.operation(),\n            route: () => route as any as IHttpMigrateRoute,\n          });\n          return null;\n        } else if (\n          route.body?.type === \"multipart/form-data\" ||\n          route.success?.type === \"multipart/form-data\"\n        ) {\n          errors.push({\n            method: route.method,\n            path: route.path,\n            messages: [\n              `The \"multipart/form-data\" content type is not supported in the LLM application.`,\n            ],\n            operation: () => route.operation(),\n            route: () => route as any as IHttpMigrateRoute,\n          });\n          return null;\n        }\n        const localErrors: string[] = [];\n        const func: IHttpLlmFunction<Model> | null = composeFunction<Model>({\n          model: props.model,\n          config: props.options,\n          components: props.migrate.document().components,\n          route: route,\n          errors: localErrors,\n          index: i,\n        });\n        if (func === null)\n          errors.push({\n            method: route.method,\n            path: route.path,\n            messages: localErrors,\n            operation: () => route.operation(),\n            route: () => route as any as IHttpMigrateRoute,\n          });\n        return func;\n      })\n      .filter((v): v is IHttpLlmFunction<Model> => v !== null);\n\n    const app: IHttpLlmApplication<Model> = {\n      model: props.model,\n      options: props.options,\n      functions,\n      errors,\n    };\n    shorten(app, props.options?.maxLength ?? 64);\n    return app;\n  };\n\n  const composeFunction = <Model extends ILlmSchema.Model>(props: {\n    model: Model;\n    components: OpenApi.IComponents;\n    route: IHttpMigrateRoute;\n    config: IHttpLlmApplication.IOptions<Model>;\n    errors: string[];\n    index: number;\n  }): IHttpLlmFunction<Model> | null => {\n    // METADATA\n    const endpoint: string = `$input.paths[${JSON.stringify(props.route.path)}][${JSON.stringify(props.route.method)}]`;\n    const operation: OpenApi.IOperation = props.route.operation();\n    const description: [string | undefined, number] = (() => {\n      if (!operation.summary?.length || !operation.description?.length)\n        return [\n          operation.summary || operation.description,\n          operation.summary?.length ?? operation.description?.length ?? 0,\n        ];\n      const summary: string = operation.summary.endsWith(\".\")\n        ? operation.summary.slice(0, -1)\n        : operation.summary;\n      const final: string = operation.description.startsWith(summary)\n        ? operation.description\n        : summary + \".\\n\\n\" + operation.description;\n      return [final, final.length];\n    })();\n    if (description[1] > 1_024) {\n      props.errors.push(\n        `The description of the function is too long (must be equal or less than 1,024 characters, but ${description[1].toLocaleString()} length).`,\n      );\n    }\n\n    // FUNCTION NAME\n    const name: string = emend(props.route.accessor.join(\"_\"));\n    const isNameVariable: boolean = /^[a-zA-Z0-9_-]+$/.test(name);\n    const isNameStartsWithNumber: boolean = /^[0-9]/.test(name[0] ?? \"\");\n    if (isNameVariable === false)\n      props.errors.push(\n        `Elements of path (separated by '/') must be composed with alphabets, numbers, underscores, and hyphens`,\n      );\n\n    //----\n    // CONSTRUCT SCHEMAS\n    //----\n    // PARAMETERS\n    const parameters: OpenApi.IJsonSchema.IObject = {\n      type: \"object\",\n      properties: Object.fromEntries([\n        ...props.route.parameters.map(\n          (s) =>\n            [\n              s.key,\n              {\n                ...s.schema,\n                title: s.parameter().title ?? s.schema.title,\n                description: s.parameter().description ?? s.schema.description,\n              },\n            ] as const,\n        ),\n        ...(props.route.query\n          ? [\n              [\n                props.route.query.key,\n                {\n                  ...props.route.query.schema,\n                  title:\n                    props.route.query.title() ?? props.route.query.schema.title,\n                  description:\n                    props.route.query.description() ??\n                    props.route.query.schema.description,\n                },\n              ] as const,\n            ]\n          : []),\n        ...(props.route.body\n          ? [\n              [\n                props.route.body.key,\n                {\n                  ...props.route.body.schema,\n                  description:\n                    props.route.body.description() ??\n                    props.route.body.schema.description,\n                },\n              ] as const,\n            ]\n          : []),\n      ]),\n    };\n    parameters.required = Object.keys(parameters.properties ?? {});\n\n    const llmParameters: IResult<\n      ILlmSchema.IParameters<Model>,\n      IOpenApiSchemaError\n    > = LlmSchemaComposer.parameters(props.model)({\n      config: props.config as any,\n      components: props.components,\n      schema: parameters,\n      accessor: `${endpoint}.parameters`,\n    }) as IResult<ILlmSchema.IParameters<Model>, IOpenApiSchemaError>;\n\n    // RETURN VALUE\n    const output: IResult<ILlmSchema<Model>, IOpenApiSchemaError> | undefined =\n      props.route.success\n        ? (LlmSchemaComposer.schema(props.model)({\n            config: props.config as any,\n            components: props.components,\n            schema: props.route.success.schema,\n            accessor: `${endpoint}.responses[${JSON.stringify(props.route.success.status)}][${JSON.stringify(props.route.success.type)}].schema`,\n            $defs: llmParameters.success\n              ? (llmParameters.value as any).$defs!\n              : {},\n          }) as IResult<ILlmSchema<Model>, IOpenApiSchemaError>)\n        : undefined;\n\n    //----\n    // CONVERSION\n    //----\n    if (\n      output?.success === false ||\n      llmParameters.success === false ||\n      isNameVariable === false ||\n      isNameStartsWithNumber === true ||\n      description[1] > 1_024\n    ) {\n      if (output?.success === false)\n        props.errors.push(\n          ...output.error.reasons.map((r) => `${r.accessor}: ${r.message}`),\n        );\n      if (llmParameters.success === false)\n        props.errors.push(\n          ...llmParameters.error.reasons.map((r) => {\n            const accessor: string = r.accessor.replace(\n              `parameters.properties[\"body\"]`,\n              `requestBody.content[${JSON.stringify(props.route.body?.type ?? \"application/json\")}].schema`,\n            );\n            return `${accessor}: ${r.message}`;\n          }),\n        );\n      return null;\n    }\n    return {\n      method: props.route.method as \"get\",\n      path: props.route.path,\n      name,\n      parameters: llmParameters.value,\n      separated: props.config.separate\n        ? (LlmSchemaComposer.separateParameters(props.model)({\n            predicate: props.config.separate as any,\n            parameters:\n              llmParameters.value satisfies ILlmSchema.ModelParameters[Model] as any,\n          }) as ILlmFunction.ISeparated<Model>)\n        : undefined,\n      output: output?.value,\n      description: description[0],\n      deprecated: operation.deprecated,\n      tags: operation.tags,\n      validate: OpenApiValidator.create({\n        components: props.components,\n        schema: parameters,\n        required: true,\n      }),\n      route: () => props.route as any,\n      operation: () => props.route.operation(),\n    };\n  };\n\n  export const shorten = <Model extends ILlmSchema.Model>(\n    app: IHttpLlmApplication<Model>,\n    limit: number = 64,\n  ): void => {\n    const dictionary: Set<string> = new Set();\n    const longFunctions: IHttpLlmFunction<Model>[] = [];\n    for (const func of app.functions) {\n      dictionary.add(func.name);\n      if (func.name.length > limit) {\n        longFunctions.push(func);\n      }\n    }\n    if (longFunctions.length === 0) return;\n\n    let index: number = 0;\n    for (const func of longFunctions) {\n      let success: boolean = false;\n      let rename = (str: string) => {\n        dictionary.delete(func.name);\n        dictionary.add(str);\n        func.name = str;\n        success = true;\n      };\n      for (let i: number = 1; i < func.route().accessor.length; ++i) {\n        const shortName: string = func.route().accessor.slice(i).join(\"_\");\n        if (shortName.length > limit - 8) continue;\n        else if (dictionary.has(shortName) === false) rename(shortName);\n        else {\n          const newName: string = `_${index}_${shortName}`;\n          if (dictionary.has(newName) === true) continue;\n          rename(newName);\n          ++index;\n        }\n        break;\n      }\n      if (success === false) rename(randomFormatUuid());\n    }\n  };\n}\n\nconst randomFormatUuid = (): string =>\n  \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n    const r = (Math.random() * 16) | 0;\n    const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n    return v.toString(16);\n  });\n\nconst emend = (str: string): string => {\n  for (const ch of FORBIDDEN) str = str.split(ch).join(\"_\");\n  return str;\n};\n\nconst FORBIDDEN = [\"$\", \"%\", \".\"];\n"],"names":["HttpLlmComposer","application","props","errors","migrate","filter","e","operation","map","method","path","messages","route","undefined","functions","routes","i","push","body","type","success","localErrors","func","composeFunction","model","config","options","components","document","v","app","shorten","maxLength","endpoint","JSON","stringify","description","summary","length","endsWith","slice","final","startsWith","toLocaleString","name","emend","accessor","join","isNameVariable","test","isNameStartsWithNumber","parameters","properties","Object","fromEntries","s","key","schema","title","parameter","query","required","keys","llmParameters","LlmSchemaComposer","output","status","$defs","value","error","reasons","r","message","replace","separated","separate","separateParameters","predicate","deprecated","tags","validate","OpenApiValidator","create","limit","dictionary","Set","longFunctions","add","index","rename","str","delete","shortName","has","newName","randomFormatUuid","c","Math","random","toString","ch","FORBIDDEN","split"],"mappings":"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"}