2023-09-17 18:18:54 -07:00
|
|
|
from typing import Any
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import os
|
|
|
|
|
import logging
|
|
|
|
|
import toml
|
|
|
|
|
import aiofiles
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
_file_dir = os.path.dirname(__file__)
|
|
|
|
|
|
|
|
|
|
class ResourceLocation:
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-09-25 20:57:10 -07:00
|
|
|
class FeatureItem:
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
pass
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
class UserConfigItem:
|
2023-09-19 15:43:17 -07:00
|
|
|
def __init__(self,desc:str=None) -> None:
|
2023-09-17 18:18:54 -07:00
|
|
|
self.default_value = None
|
|
|
|
|
self.is_optional = False
|
|
|
|
|
self.item_type = "str"
|
2023-09-19 15:43:17 -07:00
|
|
|
self.desc = desc
|
2023-09-17 18:18:54 -07:00
|
|
|
self.value = None
|
|
|
|
|
self.user_set = False
|
2023-09-19 08:29:55 +00:00
|
|
|
|
|
|
|
|
def clone(self):
|
|
|
|
|
new_config_item = UserConfigItem()
|
|
|
|
|
new_config_item.default_value = self.default_value
|
|
|
|
|
new_config_item.is_optional = self.is_optional
|
|
|
|
|
new_config_item.desc = self.desc
|
|
|
|
|
new_config_item.item_type = self.item_type
|
|
|
|
|
new_config_item.value = self.value
|
|
|
|
|
return new_config_item
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
class UserConfig:
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
self.config_table = {}
|
|
|
|
|
self.user_config_path:str = None
|
|
|
|
|
|
2023-11-13 16:07:33 -08:00
|
|
|
self._init_default_value("llm_model_name","gpt-4-1106-preview")
|
|
|
|
|
|
|
|
|
|
def _init_default_value(self,key:str,value:Any) -> None:
|
|
|
|
|
if self.config_table.get(key) is not None:
|
|
|
|
|
logger.warning("user config key %s already exist, will be overrided",key)
|
|
|
|
|
|
|
|
|
|
new_config_item = UserConfigItem()
|
|
|
|
|
new_config_item.default_value = value
|
|
|
|
|
new_config_item.is_optional = True
|
|
|
|
|
self.config_table[key] = new_config_item
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
def add_user_config(self,key:str,desc:str,is_optional:bool,default_value:Any=None,item_type="str") -> None:
|
|
|
|
|
if self.config_table.get(key) is not None:
|
|
|
|
|
logger.warning("user config key %s already exist, will be overrided",key)
|
|
|
|
|
|
|
|
|
|
new_config_item = UserConfigItem()
|
|
|
|
|
new_config_item.default_value = default_value
|
|
|
|
|
new_config_item.is_optional = is_optional
|
|
|
|
|
new_config_item.desc = desc
|
|
|
|
|
new_config_item.item_type = item_type
|
|
|
|
|
self.config_table[key] = new_config_item
|
|
|
|
|
|
|
|
|
|
async def load_value_from_file(self,file_path:str,is_user_config = False) -> None:
|
|
|
|
|
try:
|
|
|
|
|
all_config = toml.load(file_path)
|
|
|
|
|
if all_config is not None:
|
|
|
|
|
for key,value in all_config.items():
|
|
|
|
|
config_item = self.config_table.get(key)
|
|
|
|
|
if config_item is None:
|
|
|
|
|
logger.warning("user config key %s not exist",key)
|
|
|
|
|
continue
|
|
|
|
|
config_item.value = value
|
|
|
|
|
config_item.user_set = is_user_config
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.warn(f"load user config from {file_path} failed!")
|
|
|
|
|
|
2023-09-20 22:47:52 -07:00
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
async def save_to_user_config(self) -> None:
|
2023-09-17 18:18:54 -07:00
|
|
|
will_save_config = {}
|
|
|
|
|
for key,value in self.config_table.items():
|
|
|
|
|
if value.user_set:
|
|
|
|
|
will_save_config[key] = value.value
|
|
|
|
|
|
|
|
|
|
if len(will_save_config) > 0:
|
|
|
|
|
try:
|
|
|
|
|
directory = os.path.dirname(self.user_config_path)
|
|
|
|
|
if not os.path.exists(directory):
|
|
|
|
|
os.makedirs(directory)
|
|
|
|
|
|
|
|
|
|
async with aiofiles.open(self.user_config_path,"w") as f:
|
|
|
|
|
toml_str = toml.dumps(will_save_config)
|
|
|
|
|
await f.write(toml_str)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"save user config to {self.user_config_path} failed!")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
def get_config_item(self,key:str) -> Any:
|
|
|
|
|
config_item = self.config_table.get(key)
|
|
|
|
|
if config_item is None:
|
2023-09-26 18:46:26 -07:00
|
|
|
logger.warning(f"user config key {key} not exist")
|
|
|
|
|
return None
|
2023-09-19 00:53:13 -07:00
|
|
|
|
|
|
|
|
return config_item
|
|
|
|
|
|
|
|
|
|
def get_value(self,key:str)->Any:
|
2023-09-17 18:18:54 -07:00
|
|
|
config_item = self.config_table.get(key)
|
|
|
|
|
if config_item is None:
|
2023-09-26 18:46:26 -07:00
|
|
|
logger.warning(f"user config key {key} not exist")
|
|
|
|
|
return None
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
if config_item.value is None:
|
2023-09-20 08:45:53 +00:00
|
|
|
return config_item.default_value
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
return config_item.value
|
|
|
|
|
|
|
|
|
|
def set_value(self,key:str,value:Any) -> None:
|
2023-09-17 18:18:54 -07:00
|
|
|
config_item = self.config_table.get(key)
|
|
|
|
|
if config_item is None:
|
|
|
|
|
logger.warning("user config key %s not exist",key)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
config_item.value = value
|
|
|
|
|
config_item.user_set = True
|
|
|
|
|
#TODO: save to file?
|
|
|
|
|
|
|
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
def check_config(self) -> None:
|
2023-09-17 18:18:54 -07:00
|
|
|
check_result = {}
|
|
|
|
|
for key,config_item in self.config_table.items():
|
|
|
|
|
if config_item.value is None and not config_item.is_optional:
|
|
|
|
|
check_result[key] = config_item
|
|
|
|
|
|
|
|
|
|
if len(check_result) > 0:
|
|
|
|
|
return check_result
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
# storage sytem for current user
|
|
|
|
|
class AIStorage:
|
|
|
|
|
_instance = None
|
|
|
|
|
@classmethod
|
|
|
|
|
def get_instance(cls):
|
|
|
|
|
if cls._instance is None:
|
|
|
|
|
cls._instance = AIStorage()
|
|
|
|
|
return cls._instance
|
|
|
|
|
|
|
|
|
|
def __init__(self) -> None:
|
|
|
|
|
self.is_dev_mode = False
|
|
|
|
|
self.user_config = UserConfig()
|
2023-09-26 01:19:33 -07:00
|
|
|
self.feature_init_results = {}
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
async def initial(self)->bool:
|
|
|
|
|
self.user_config.user_config_path = str(self.get_myai_dir() / "etc/system.cfg.toml")
|
|
|
|
|
await self.user_config.load_value_from_file(self.get_system_dir() + "/system.cfg.toml")
|
|
|
|
|
await self.user_config.load_value_from_file(self.user_config.user_config_path,True)
|
|
|
|
|
|
2023-09-25 20:57:10 -07:00
|
|
|
async def enable_feature(self,feature_name:str) -> None:
|
2023-09-26 01:19:33 -07:00
|
|
|
self.user_config.set_value(f"feature.{feature_name}","True")
|
|
|
|
|
await self.user_config.save_to_user_config()
|
|
|
|
|
|
2023-09-25 20:57:10 -07:00
|
|
|
|
|
|
|
|
async def disable_feature(self,feature_name:str) -> None:
|
2023-09-26 01:19:33 -07:00
|
|
|
self.user_config.set_value(f"feature.{feature_name}","False")
|
|
|
|
|
await self.user_config.save_to_user_config()
|
2023-09-25 20:57:10 -07:00
|
|
|
|
|
|
|
|
async def set_feature_init_result(self,feature_name:str,result:bool) -> None:
|
2023-09-26 01:19:33 -07:00
|
|
|
self.feature_init_results[feature_name] = result
|
2023-09-25 20:57:10 -07:00
|
|
|
|
|
|
|
|
async def is_feature_enable(self,feature_name:str) -> bool:
|
2023-09-26 01:19:33 -07:00
|
|
|
is_enable = self.user_config.get_value(f"feature.{feature_name}")
|
|
|
|
|
if is_enable is None:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
init_result = self.feature_init_results.get(feature_name)
|
|
|
|
|
if init_result:
|
|
|
|
|
if init_result is False:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if is_enable == "True":
|
|
|
|
|
return True
|
|
|
|
|
return False
|
2023-09-25 20:57:10 -07:00
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
def get_user_config(self) -> UserConfig:
|
|
|
|
|
return self.user_config
|
|
|
|
|
|
|
|
|
|
def get_system_dir(self) -> str:
|
|
|
|
|
"""
|
|
|
|
|
system dir is dir for aios system
|
|
|
|
|
/opt/aios
|
|
|
|
|
"""
|
|
|
|
|
if self.is_dev_mode:
|
2023-11-30 21:04:19 -08:00
|
|
|
return os.path.abspath(_file_dir + "/../../")
|
2023-09-17 18:18:54 -07:00
|
|
|
else:
|
|
|
|
|
return "/opt/aios/"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_system_app_dir(self)->str:
|
|
|
|
|
"""
|
|
|
|
|
system app dir is the dir for aios build-in app
|
|
|
|
|
/opt/aios/app
|
|
|
|
|
"""
|
|
|
|
|
if self.is_dev_mode:
|
2023-11-30 21:04:19 -08:00
|
|
|
return os.path.abspath(_file_dir + "/../../../rootfs/")
|
2023-09-17 18:18:54 -07:00
|
|
|
else:
|
|
|
|
|
return "/opt/aios/app/"
|
|
|
|
|
|
|
|
|
|
def get_myai_dir(self) -> str:
|
|
|
|
|
"""
|
|
|
|
|
my ai dir is the dir for user to store their ai app and data
|
|
|
|
|
~/myai/
|
|
|
|
|
"""
|
|
|
|
|
return Path.home() / "myai"
|
2023-12-01 09:26:55 +00:00
|
|
|
|
|
|
|
|
def get_download_dir(self) -> str:
|
|
|
|
|
"""
|
|
|
|
|
download dir is the dir for user to store the files downloaded with the system.
|
|
|
|
|
~/myai/download
|
|
|
|
|
"""
|
|
|
|
|
return f"{self.get_myai_dir()}/download"
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
def get_db(self,app_name:str)->ResourceLocation:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def open_file(self,file_path:str,options:dict):
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def get_named_object(self,name:str) -> Any:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def put_named_object(self,name:str,obj:Any) -> None:
|
|
|
|
|
pass
|
2023-09-20 22:47:52 -07:00
|
|
|
|
|
|
|
|
async def try_create_file_with_default_value(self,path:str,default_value:str):
|
|
|
|
|
if os.path.exists(path):
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
directory = os.path.dirname(path)
|
|
|
|
|
if not os.path.exists(directory):
|
|
|
|
|
os.makedirs(directory)
|
|
|
|
|
async with aiofiles.open(path,"w") as f:
|
|
|
|
|
await f.write(default_value)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"open or create file {path} failed! {str(e)}")
|