From 711e347346c46783bd0c5469aad4e5eb3beb2cc7 Mon Sep 17 00:00:00 2001 From: mbruzon Date: Sat, 13 Jun 2026 09:50:59 +0200 Subject: [PATCH] #wip: Building the projects builder. --- JSON/AnP.settings.json | 23 ++--- MD/PseudoLoRAs/AnP.inputs.md | 2 + MD/PseudoLoRAs/AnP.md | 4 +- .../ecma/Components/AIChatComponent.ecma.js | 2 +- Python/Abstracts/FilesAbstract.py | 95 ++++++++++++++++++ Python/Application/AnP.py | 3 + Python/Drivers/FilesDriver.py | 97 +++++++++++++++++++ .../Abstracts/FilesAbstractInterface.py | 46 +++++++++ Python/Interfaces/Application/AnPInterface.py | 2 + Python/Managers/AIInterpretersManager.py | 2 +- Python/Managers/ControllersManager.py | 2 +- Python/Managers/DispatchesManager.py | 2 +- Python/Managers/HTTPServersManager.py | 2 +- Python/Managers/I18NManager.py | 2 +- Python/Managers/ModelsManager.py | 2 +- Python/Managers/PrintTypesManager.py | 2 +- Python/Managers/PseudoLoRAsManager.py | 11 +-- Python/Managers/QueusManager.py | 2 +- Python/Managers/RoutesManager.py | 8 +- Python/Managers/SettingsManager.py | 4 +- Python/Managers/WebSocketServersManager.py | 2 +- Python/Utils/Patterns.py | 3 +- Python/run.py | 4 +- 23 files changed, 285 insertions(+), 37 deletions(-) create mode 100644 MD/PseudoLoRAs/AnP.inputs.md create mode 100644 Python/Abstracts/FilesAbstract.py create mode 100644 Python/Drivers/FilesDriver.py create mode 100644 Python/Interfaces/Abstracts/FilesAbstractInterface.py diff --git a/JSON/AnP.settings.json b/JSON/AnP.settings.json index 2b85af6..c3cb480 100644 --- a/JSON/AnP.settings.json +++ b/JSON/AnP.settings.json @@ -97,26 +97,27 @@ "type" : "OllamaDriver", "url" : "http://localhost:11434/api/generate/", "model" : "gemma3:1b", - "pool" : "anp", - "stream" : false, + "pool" : "anp", "format" : { - "type" : "array", - "items" : { - "type" : "string" + "type": "array", + "items": { + "type": "boolean" } }, - "orders" : [ - "En base al mensaje del usuario y los Tokens que tengas de la conversación, selecciona posibles títulos que tengan que ver con ello.", - "Devuelve una lista con los títulos seleccionados, sin ningún otro texto.", - "Si el mensaje del usuario no tiene relación con ningún título, devuelve una lista vacía." - ] + "stream" : false, + "think" : false, + "temperature" : 0.0, + "allow_contexts" : true }, "anp_responses" : { "type" : "OllamaDriver", "url" : "http://localhost:11434/api/generate/", "model" : "gemma4:e4b", + "stream" : true, "pool" : "anp", - "stream" : true + "think" : false, + "temperature" : 0.7, + "allow_contexts" : true } }, "AnP_AIInterpretersManager_end" : null, diff --git a/MD/PseudoLoRAs/AnP.inputs.md b/MD/PseudoLoRAs/AnP.inputs.md new file mode 100644 index 0000000..e145628 --- /dev/null +++ b/MD/PseudoLoRAs/AnP.inputs.md @@ -0,0 +1,2 @@ +- **end_print_types**: `array[string]`. Opcional. Por defecto `["UNKN", "EXCE", "ERRO"]`. Determina qué mensajes de consola tienen valor `end`, el cual es un valor para mostrar trazas, listas como los errores, etc. +- **root_projects_paths**: `array[string]`. Opcional. Por defecto `[]`. \ No newline at end of file diff --git a/MD/PseudoLoRAs/AnP.md b/MD/PseudoLoRAs/AnP.md index 59cfcf3..ea2eb82 100644 --- a/MD/PseudoLoRAs/AnP.md +++ b/MD/PseudoLoRAs/AnP.md @@ -2,6 +2,6 @@ AnP, de Attach & Play en inglés, es un Framework basado en Gestores y su consum Está desarrollado en Python para el servidor; y JavaScript para el entorno cliente Web. -Para crear un objecto AnP simplemente hemos de crearlo sin ningún argumento si queremos dejar todo por defecto o si queremos personalizar algo, podemos hacer uso del argumento `inputs`. +Para crear un objecto AnP simplemente hemos de crearlo sin ningún argumento si queremos dejar todo por defecto o si queremos personalizar algo, podemos hacer uso del primer argumento llamado `inputs`, el cual tiene los siguientes parámetros: -> Para saber qué puede contener el argumento `inputs` mirar la configuración. \ No newline at end of file +[[!include /MD/PseudoLoRAs/AnP.inputs.md]] \ No newline at end of file diff --git a/Public/ecma/Components/AIChatComponent.ecma.js b/Public/ecma/Components/AIChatComponent.ecma.js index a060ed1..7a929c2 100644 --- a/Public/ecma/Components/AIChatComponent.ecma.js +++ b/Public/ecma/Components/AIChatComponent.ecma.js @@ -182,7 +182,7 @@ export const AIChatComponent = (function(){ }; const set_status = (conversation, message, status) => { - console.log([conversation, message, status]); + // console.log([conversation, message, status]); const box = document.querySelector(".aichat [data-conversation='" + conversation + "']>[data-type=bot][data-id='" + message + "']"), status_box = box.querySelector("[data-name=status]"), diff --git a/Python/Abstracts/FilesAbstract.py b/Python/Abstracts/FilesAbstract.py new file mode 100644 index 0000000..f6e2681 --- /dev/null +++ b/Python/Abstracts/FilesAbstract.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from typing import Any, Optional, Self, Sequence +from abc import ABC, abstractmethod +from os.path import dirname as directory_name, abspath as absolute_path +from Interfaces.Application.AnPInterface import AnPInterface +from Utils.Common import Common +from Utils.Checks import Check +from Utils.Patterns import RE + +class FilesAbstract(ABC): + + def __init__(self:Self, anp:AnPInterface, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: + self.anp:AnPInterface = anp + root_path:str = directory_name(absolute_path(__file__)) + self._slash:str = Common.get_value("slash", inputs, "/" if "/" in root_path else "\\\\") + self._root_paths:list[str] = Common.get_value( + "root_paths", + inputs, + [""] + self.get_parents(root_path, 4) + ) + + def set_root_paths(self:Self, paths:str|Sequence[str]) -> None: + + path:str + + for path in Common.get_array(paths): + if path not in self._root_paths: + self._root_paths.append(path) + + def set_slash(self:Self, slash:str) -> None: + self._slash = slash + + def fix_path(self:Self, path:str) -> str: + return RE.SLASHES.sub(self._slash, path) + + def get_parent(self:Self, path:str) -> str: + return RE.PARENT_PATH.sub(r'\1', self.fix_path(path)) + + def get_parents(self:Self, path:str, levels:int = 1) -> list[str]: + + parents:list[str] = [self.fix_path(path)] + + while len(parents[-1]) > 2 and len(parents) < levels: + parents.append(RE.PARENT_PATH.sub(r'\1', parents[-1])) + + return parents + + @abstractmethod + def get_absolute_path(self:Self, path:str) -> str|None:pass + + @abstractmethod + def exists(self:Self, path:str) -> bool:pass + + @abstractmethod + def is_file(self:Self, path:str) -> bool:pass + + @abstractmethod + def is_directory(self:Self, path:str) -> bool:pass + + @abstractmethod + def load(self:Self, path:str, mode:str = "r") -> str|bytes|None:pass + + @abstractmethod + def make_directory(self:Self, path:str) -> bool:pass + + @abstractmethod + def save(self:Self, path:str, content:str|bytes) -> bool:pass + + @abstractmethod + def delete(self:Self, path:str) -> bool:pass + + def load_json(self:Self, inputs:Any|None, only_dictionaries:bool = True) -> list[dict[str, Any|None]|Sequence[Any|None]]: + + results:list[dict[str, Any|None]|Sequence[Any|None]] = [] + + if Check.is_dictionary(inputs): + results.append(inputs) + elif Check.is_array(inputs): + if only_dictionaries: + for item in inputs: + results.extend(self.load_json(item, only_dictionaries)) + else: + results.append(inputs) + elif Check.is_string(inputs): + + json:dict[str, Any|None]|Sequence[Any|None]|None = Common.json_decode(inputs) + + if json is None: + results.extend(self.load_json(self.load(inputs), only_dictionaries)) + else: + results.extend(self.load_json(json, only_dictionaries)) + + return results \ No newline at end of file diff --git a/Python/Application/AnP.py b/Python/Application/AnP.py index 4dbd5df..ddff67e 100644 --- a/Python/Application/AnP.py +++ b/Python/Application/AnP.py @@ -6,6 +6,8 @@ import datetime from re import Match as REMatch from traceback import extract_tb as extract_traceback, format_stack as trace_format_stack from time import time as timestamp, sleep +from Abstracts.FilesAbstract import FilesAbstract +from Drivers.FilesDriver import FilesDriver from Managers.I18NManager import I18NManager from Managers.SettingsManager import SettingsManager from Managers.PrintTypesManager import PrintTypesManager @@ -38,6 +40,7 @@ class AnP: def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: self.__working:bool = True + self.files:FilesAbstract = FilesDriver(self) self.settings:SettingsManager = SettingsManager(self, inputs) self.i18n:I18NManager = I18NManager(self) self.print_types:PrintTypesManager = PrintTypesManager(self) diff --git a/Python/Drivers/FilesDriver.py b/Python/Drivers/FilesDriver.py new file mode 100644 index 0000000..1484dc6 --- /dev/null +++ b/Python/Drivers/FilesDriver.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from typing import Self +from os.path import isfile as is_file, isdir as is_directory, exists as path_exists +from os import unlink as delete_path, mkdir as make_directory +from Abstracts.FilesAbstract import FilesAbstract +from Abstracts.ModelAbstract import ModelAbstract +from Utils.Checks import Check + +class FilesDriver(FilesAbstract, ModelAbstract): + + def get_absolute_path(self:Self, path:str) -> str|None: + + root_path:str + + for root_path in self._root_paths: + + absolute_path:str = self.fix_path((root_path + self._slash + path) if root_path else path) + + if path_exists(absolute_path): + return absolute_path + return None + + def exists(self:Self, path:str) -> bool: + return self.get_absolute_path(path) is not None + + def is_file(self:Self, path:str) -> bool: + + absolute_path:str|None = self.get_absolute_path(path) + + return is_file(absolute_path) if absolute_path else False + + def is_directory(self:Self, path:str) -> bool: + + absolute_path:str|None = self.get_absolute_path(path) + + return is_directory(absolute_path) if absolute_path else False + + def load(self:Self, path:str, mode:str = "r") -> str|bytes|None: + + absolute_path:str|None = self.get_absolute_path(path) + + if absolute_path: + try: + with open(absolute_path, mode) as file: + return file.read() + except Exception as exception: + self.anp.exception(exception, "anp_files_driver_load_exception", { + "path" : path, + "absolute_path" : absolute_path, + "mode" : mode + }) + return None + + def make_directory(self:Self, path:str) -> bool: + try: + make_directory(path) + return True + except Exception as exception: + self.anp.exception(exception, "anp_files_driver_make_directory_exception", { + "path" : path + }) + return False + + def save(self:Self, path:str, content:str|bytes) -> bool: + + directory:str = self.get_parent(path) + + if self.exists(directory) or self.make_directory(directory): + try: + with open(self.fix_path(path), ( + "wb" if Check.is_binary(content) else + "w")) as file: + file.write(content) + return True + except Exception as exception: + self.anp.exception(exception, "anp_files_driver_save_exception", { + "path" : path, + "mode" : "wb" if Check.is_binary(content) else "w" + }) + return False + + def delete(self:Self, path:str) -> bool: + + absolute_path:str|None = self.get_absolute_path(path) + + if absolute_path: + try: + delete_path(absolute_path) + return True + except Exception as exception: + self.anp.exception(exception, "anp_files_driver_delete_exception", { + "path" : path, + "absolute_path" : absolute_path + }) + return False \ No newline at end of file diff --git a/Python/Interfaces/Abstracts/FilesAbstractInterface.py b/Python/Interfaces/Abstracts/FilesAbstractInterface.py new file mode 100644 index 0000000..30ab2b2 --- /dev/null +++ b/Python/Interfaces/Abstracts/FilesAbstractInterface.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from typing import Self, Sequence +from abc import ABC, abstractmethod + +class FilesAbstractInterface(ABC): + + @abstractmethod + def get_parents(path:str, levels:int = 1) -> list[str]:pass + + @abstractmethod + def set_root_paths(self:Self, paths:str|Sequence[str]) -> None:pass + + @abstractmethod + def set_slash(self:Self, slash:str) -> None:pass + + @abstractmethod + def fix_path(self:Self, path:str) -> str:pass + + @abstractmethod + def get_parent(self:Self, path:str) -> str:pass + + @abstractmethod + def get_absolute_path(self:Self, path:str) -> str|None:pass + + @abstractmethod + def exists(self:Self, path:str) -> bool:pass + + @abstractmethod + def is_file(self:Self, path:str) -> bool:pass + + @abstractmethod + def is_directory(self:Self, path:str) -> bool:pass + + @abstractmethod + def load(self:Self, path:str, mode:str = "r") -> str|bytes|None:pass + + @abstractmethod + def make_directory(self:Self, path:str) -> bool:pass + + @abstractmethod + def save(self:Self, path:str, content:str|bytes) -> bool:pass + + @abstractmethod + def delete(self:Self, path:str) -> bool:pass \ No newline at end of file diff --git a/Python/Interfaces/Application/AnPInterface.py b/Python/Interfaces/Application/AnPInterface.py index 5b7c4a3..24ae6df 100644 --- a/Python/Interfaces/Application/AnPInterface.py +++ b/Python/Interfaces/Application/AnPInterface.py @@ -7,6 +7,7 @@ from Interfaces.Managers.SettingsManagerInterface import SettingsManagerInterfac from Interfaces.Managers.I18NManagerInterface import I18NManagerInterface from Interfaces.Managers.PrintTypesManagerInterface import PrintTypesManagerInterface from Interfaces.Managers.TerminalManagerInterface import TerminalManagerInterface +from Interfaces.Abstracts.FilesAbstractInterface import FilesAbstractInterface from Interfaces.Managers.ModelsManagerInterface import ModelsManagerInterface from Interfaces.Managers.UniqueKeysManagerInterface import UniqueKeysManagerInterface from Interfaces.Managers.QueusManagerInterface import QueusManagerInterface @@ -23,6 +24,7 @@ from Interfaces.Managers.AIInterpretersManagerInterface import AIInterpretersMan class AnPInterface(ABC): def __init__(self:Self, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None: + self.files:FilesAbstractInterface = None self.settings:SettingsManagerInterface = None self.i18n:I18NManagerInterface = None self.print_types:PrintTypesManagerInterface = None diff --git a/Python/Managers/AIInterpretersManager.py b/Python/Managers/AIInterpretersManager.py index d64acc4..27081e0 100644 --- a/Python/Managers/AIInterpretersManager.py +++ b/Python/Managers/AIInterpretersManager.py @@ -38,7 +38,7 @@ class AIInterpretersManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str value:Any|None diff --git a/Python/Managers/ControllersManager.py b/Python/Managers/ControllersManager.py index f07cd34..adec076 100644 --- a/Python/Managers/ControllersManager.py +++ b/Python/Managers/ControllersManager.py @@ -34,7 +34,7 @@ class ControllersManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): for key, controller in subinputs.items(): if Common.is_mark_key(key) and controller is None: continue diff --git a/Python/Managers/DispatchesManager.py b/Python/Managers/DispatchesManager.py index 065311d..78fad7f 100644 --- a/Python/Managers/DispatchesManager.py +++ b/Python/Managers/DispatchesManager.py @@ -33,7 +33,7 @@ class DispatchesManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): for key, dispatch in subinputs.items(): if Common.is_mark_key(key) and dispatch is None: continue diff --git a/Python/Managers/HTTPServersManager.py b/Python/Managers/HTTPServersManager.py index 58d0b68..a56cc4b 100644 --- a/Python/Managers/HTTPServersManager.py +++ b/Python/Managers/HTTPServersManager.py @@ -40,7 +40,7 @@ class HTTPServersManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str value:Any|None diff --git a/Python/Managers/I18NManager.py b/Python/Managers/I18NManager.py index 53d1a2a..09a7003 100644 --- a/Python/Managers/I18NManager.py +++ b/Python/Managers/I18NManager.py @@ -80,7 +80,7 @@ class I18NManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): language:str sentences:dict[str, str|list[str]] diff --git a/Python/Managers/ModelsManager.py b/Python/Managers/ModelsManager.py index 8157149..5d9c954 100644 --- a/Python/Managers/ModelsManager.py +++ b/Python/Managers/ModelsManager.py @@ -46,7 +46,7 @@ class ModelsManager: subinputs:dict[str, ModelAbstract] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): for key, model in subinputs.items(): if Common.is_mark_key(key) and model is None: continue diff --git a/Python/Managers/PrintTypesManager.py b/Python/Managers/PrintTypesManager.py index 587a1d6..8733d93 100644 --- a/Python/Managers/PrintTypesManager.py +++ b/Python/Managers/PrintTypesManager.py @@ -75,4 +75,4 @@ class PrintTypesManager: subinputs:Any|None for subinputs in item: - self.add(Common.load_json(subinputs)) + self.add(self.anp.files.load_json(subinputs)) diff --git a/Python/Managers/PseudoLoRAsManager.py b/Python/Managers/PseudoLoRAsManager.py index 7dcb1ce..cac30c1 100644 --- a/Python/Managers/PseudoLoRAsManager.py +++ b/Python/Managers/PseudoLoRAsManager.py @@ -4,7 +4,6 @@ from typing import Self, Any, Sequence, Callable, Optional from Interfaces.Application.AnPInterface import AnPInterface from Models.PseudoLoRAModel import PseudoLoRAModel -from Utils.Common import Common from Utils.Checks import Check class PseudoLoRAsManager: @@ -35,7 +34,7 @@ class PseudoLoRAsManager: def __try_load_file(self:Self, path:str) -> bool: - data:list[dict[str, Any|None]|Sequence[Any|None]] = Common.load_json(path) + data:list[dict[str, Any|None]|Sequence[Any|None]] = self.anp.files.load_json(path) if len(data): self.add(data) @@ -49,7 +48,7 @@ class PseudoLoRAsManager: subinputs:dict[str, Any|None]|Sequence[Any|None] - for subinputs in Common.load_json(inputs, False): + for subinputs in self.anp.files.load_json(inputs, False): if Check.is_string(subinputs): self.__try_load_file(subinputs) elif Check.is_array(subinputs): @@ -113,14 +112,14 @@ class PseudoLoRAsManager: lora:PseudoLoRAModel = loras[i] if lora.path is not None: - results.append((lora.title, Common.load_file(lora.path, "r"))) + results.append((lora.title, self.anp.files.load(lora.path, "r"))) # data:str|None # if lora.cacheable: # if not lora.cache: - # lora.cache = Common.load_file(lora.path, "r") + # lora.cache = self.anp.files.load(lora.path, "r") # lora.memory = len(lora.cache) # self.__memory_cached += lora.memory @@ -139,7 +138,7 @@ class PseudoLoRAsManager: # lora.clean_cache() # del self.__cache[i] - # if (data := lora.cache or Common.load_file(lora.path, "r")): + # if (data := lora.cache or self.anp.files.load(lora.path, "r")): # results.append((lora.title, lora.path)) else: diff --git a/Python/Managers/QueusManager.py b/Python/Managers/QueusManager.py index d00cfc9..8bfa2a9 100644 --- a/Python/Managers/QueusManager.py +++ b/Python/Managers/QueusManager.py @@ -31,7 +31,7 @@ class QueuesManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str queue:Any|None diff --git a/Python/Managers/RoutesManager.py b/Python/Managers/RoutesManager.py index 67d03fe..e576962 100644 --- a/Python/Managers/RoutesManager.py +++ b/Python/Managers/RoutesManager.py @@ -49,10 +49,10 @@ class RoutesManager: for index in [""] + self.anp.indexes.get(): - path_indexed:str|None = Common.get_absolute_path(route.path + "/" + path + ("/" + index if index else "")) + path_indexed:str|None = self.anp.files.get_absolute_path(route.path + "/" + path + ("/" + index if index else "")) - if path_indexed is not None and Common.is_file(path_indexed): - request.set_response(Common.load_file(path_indexed, "rb")) + if path_indexed is not None and self.anp.files.is_file(path_indexed): + request.set_response(self.anp.files.load(path_indexed, "rb")) request.response_mime = Common.get_mime_from_path(path_indexed) return request.set_response({ @@ -101,7 +101,7 @@ class RoutesManager: subinputs:Any|None - for subinputs in Common.load_json(inputs, False): + for subinputs in self.anp.files.load_json(inputs, False): if isinstance(subinputs, RouteModel): self.__add_new_route(subinputs, overwrite) elif ( diff --git a/Python/Managers/SettingsManager.py b/Python/Managers/SettingsManager.py index 0c259e0..8e07215 100644 --- a/Python/Managers/SettingsManager.py +++ b/Python/Managers/SettingsManager.py @@ -52,7 +52,7 @@ class SettingsManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str value:Any|None @@ -67,7 +67,7 @@ class SettingsManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str value:Any|None diff --git a/Python/Managers/WebSocketServersManager.py b/Python/Managers/WebSocketServersManager.py index 8236f6c..03c402f 100644 --- a/Python/Managers/WebSocketServersManager.py +++ b/Python/Managers/WebSocketServersManager.py @@ -58,7 +58,7 @@ class WebSocketServersManager: subinputs:dict[str, Any|None] - for subinputs in Common.load_json(inputs, True): + for subinputs in self.anp.files.load_json(inputs, True): key:str value:Any|None diff --git a/Python/Utils/Patterns.py b/Python/Utils/Patterns.py index ded5760..03d9e36 100644 --- a/Python/Utils/Patterns.py +++ b/Python/Utils/Patterns.py @@ -14,4 +14,5 @@ class RE: ROUTE_KEY:REPattern = re_compile(r'\\\{([a-z_][a-z0-9_]*)\\\}', RE_IGNORECASE) EXCEPTION:REPattern = re_compile(r'^\s*File "([^"]+)", line ([0-9]+), in ([^\n]+)(.*|[\r\n]*)*$') NEW_LINE:REPattern = re_compile(r'\r\n|[\r\n]') - HTTP_VARIABLE:REPattern = re_compile(r'([^=&]+)=([^&]*)') \ No newline at end of file + HTTP_VARIABLE:REPattern = re_compile(r'([^=&]+)=([^&]*)') + PARENT_PATH:REPattern = re_compile(r'^(.*)[\/\\][^\/\\]+[\/\\]?$') \ No newline at end of file diff --git a/Python/run.py b/Python/run.py index 9ac71f1..1414507 100644 --- a/Python/run.py +++ b/Python/run.py @@ -7,13 +7,15 @@ from Controllers.AIController import AIController from Drivers.WebSocketServerDriver import WebSocketServerDriver from Drivers.HTTPDriver import HTTPDriver from Drivers.OllamaDriver import OllamaDriver +from Drivers.FilesDriver import FilesDriver inputs:dict[str, dict[str, Any|None]] = { "default_models" : { "AIController" : AIController, "WebSocketServerDriver" : WebSocketServerDriver, "HTTPDriver" : HTTPDriver, - "OllamaDriver" : OllamaDriver + "OllamaDriver" : OllamaDriver, + "FilesDriver" : FilesDriver } }