story maker
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
instance_id = "fairy_tale_writer"
|
||||||
|
fullname = "tracy wang"
|
||||||
|
llm_model_name = "gpt-3.5-turbo-16k-0613"
|
||||||
|
|
||||||
|
[[prompt]]
|
||||||
|
role = "system"
|
||||||
|
content = "你是一个童话做作家,能够写出各种有趣的童话。"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
instance_id = "studio_director"
|
||||||
|
fullname = "tracy wang"
|
||||||
|
llm_model_name = "gpt-3.5-turbo-16k-0613"
|
||||||
|
|
||||||
|
[[prompt]]
|
||||||
|
role = "system"
|
||||||
|
content = "你是一个演播导演,请将下面故事改编成朗读剧本,提取旁白和角色台词,每个角色需要有性别、年龄、以及每句台词的语气。并调用text_to_speech function生成音频数据。"
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
name = "story_maker"
|
||||||
|
|
||||||
|
|
||||||
|
[filter]
|
||||||
|
"*" = "manager"
|
||||||
|
|
||||||
|
[roles.manager]
|
||||||
|
name = "manager"
|
||||||
|
fullname = "总导演"
|
||||||
|
agent="manager"
|
||||||
|
[[roles.manager.prompt]]
|
||||||
|
role="system"
|
||||||
|
content="""
|
||||||
|
你是一个语音故事制作总导演,与客户对接并向团队下达指令。你的团队分为下面几个成员:writer,studio_director。一个故事制作分成两个阶段:让writer写出故事,再交由studio_director演播故事。你的基本工作模式是:
|
||||||
|
1. 收到客户的明确的指令后,让writer写出故事
|
||||||
|
2. 将writer写出的故事交给studio_director演播
|
||||||
|
3. 当你决定要和成员通信时,请使用下面形式输出需要通信的消息
|
||||||
|
```
|
||||||
|
##/send_msg 成员名称
|
||||||
|
内容
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
|
||||||
|
[roles.writer]
|
||||||
|
name = "writer"
|
||||||
|
agent = "fairy_tale_writer"
|
||||||
|
fullname = "作家"
|
||||||
|
[[roles.writer.prompt]]
|
||||||
|
role="system"
|
||||||
|
content=""
|
||||||
|
|
||||||
|
[roles.studio_director]
|
||||||
|
name = "studio_director"
|
||||||
|
agent = "studio_director"
|
||||||
|
[[roles.studio_director.prompt]]
|
||||||
|
role="system"
|
||||||
|
content=""
|
||||||
@@ -19,6 +19,7 @@ from .tg_tunnel import TelegramTunnel
|
|||||||
from .email_tunnel import EmailTunnel
|
from .email_tunnel import EmailTunnel
|
||||||
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
|
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
|
||||||
from .contact_manager import ContactManager,Contact,FamilyMember
|
from .contact_manager import ContactManager,Contact,FamilyMember
|
||||||
|
from .text_to_speech_function import TextToSpeechFunction
|
||||||
|
|
||||||
AIOS_Version = "0.5.1, build 2023-9-17"
|
AIOS_Version = "0.5.1, build 2023-9-17"
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ class ChatSessionDB:
|
|||||||
self._create_table(conn)
|
self._create_table(conn)
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not hasattr(self.local, 'conn'):
|
if not hasattr(self.local, 'conn'):
|
||||||
return
|
return
|
||||||
self.local.conn.close()
|
self.local.conn.close()
|
||||||
|
|
||||||
def _create_table(self, conn):
|
def _create_table(self, conn):
|
||||||
@@ -56,7 +56,7 @@ class ChatSessionDB:
|
|||||||
|
|
||||||
# create messages table
|
# create messages table
|
||||||
# reciver_id could be None
|
# reciver_id could be None
|
||||||
|
|
||||||
conn.execute("""
|
conn.execute("""
|
||||||
CREATE TABLE IF NOT EXISTS Messages (
|
CREATE TABLE IF NOT EXISTS Messages (
|
||||||
MessageID TEXT PRIMARY KEY,
|
MessageID TEXT PRIMARY KEY,
|
||||||
@@ -142,7 +142,7 @@ class ChatSessionDB:
|
|||||||
except Error as e:
|
except Error as e:
|
||||||
logging.error("Error occurred while inserting message: %s", e)
|
logging.error("Error occurred while inserting message: %s", e)
|
||||||
return -1 # return -1 if an error occurs
|
return -1 # return -1 if an error occurs
|
||||||
|
|
||||||
def get_chatsession_by_id(self, session_id):
|
def get_chatsession_by_id(self, session_id):
|
||||||
"""Get a message by its ID"""
|
"""Get a message by its ID"""
|
||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
@@ -150,7 +150,7 @@ class ChatSessionDB:
|
|||||||
c.execute("SELECT * FROM ChatSessions WHERE SessionID = ?", (session_id,))
|
c.execute("SELECT * FROM ChatSessions WHERE SessionID = ?", (session_id,))
|
||||||
chatsession = c.fetchone()
|
chatsession = c.fetchone()
|
||||||
return chatsession
|
return chatsession
|
||||||
|
|
||||||
def get_chatsession_by_owner_topic(self, owner_id, topic):
|
def get_chatsession_by_owner_topic(self, owner_id, topic):
|
||||||
"""Get a chatsession by its owner and topic"""
|
"""Get a chatsession by its owner and topic"""
|
||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
@@ -175,7 +175,7 @@ class ChatSessionDB:
|
|||||||
except Error as e:
|
except Error as e:
|
||||||
logging.error("Error occurred while getting sessions: %s", e)
|
logging.error("Error occurred while getting sessions: %s", e)
|
||||||
return -1, None # return -1 and None if an error occurs
|
return -1, None # return -1 and None if an error occurs
|
||||||
|
|
||||||
def get_message_by_id(self, message_id):
|
def get_message_by_id(self, message_id):
|
||||||
"""Get a message by its ID"""
|
"""Get a message by its ID"""
|
||||||
conn =self._get_conn()
|
conn =self._get_conn()
|
||||||
@@ -216,7 +216,7 @@ class ChatSessionDB:
|
|||||||
except Error as e:
|
except Error as e:
|
||||||
logging.error("Error occurred while updating message status: %s", e)
|
logging.error("Error occurred while updating message status: %s", e)
|
||||||
return -1 # return -1 if an error occurs
|
return -1 # return -1 if an error occurs
|
||||||
|
|
||||||
|
|
||||||
# chat session store the chat history between owner and agent
|
# chat session store the chat history between owner and agent
|
||||||
# chat session might be large, so can read / write at stream mode.
|
# chat session might be large, so can read / write at stream mode.
|
||||||
@@ -230,7 +230,7 @@ class AIChatSession:
|
|||||||
# cls._dbs[db_path] = db
|
# cls._dbs[db_path] = db
|
||||||
# db.get_chatsession_by_id(session_id)
|
# db.get_chatsession_by_id(session_id)
|
||||||
# #result = AIChatSession()
|
# #result = AIChatSession()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_session(cls,owner_id:str,session_topic:str,db_path:str,auto_create = True) -> str:
|
def get_session(cls,owner_id:str,session_topic:str,db_path:str,auto_create = True) -> str:
|
||||||
db = cls._dbs.get(db_path)
|
db = cls._dbs.get(db_path)
|
||||||
@@ -249,21 +249,22 @@ class AIChatSession:
|
|||||||
result = AIChatSession(owner_id,session[0],db)
|
result = AIChatSession(owner_id,session[0],db)
|
||||||
result.topic = session_topic
|
result.topic = session_topic
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def __init__(self,owner_id:str, session_id:str, db:ChatSessionDB) -> None:
|
def __init__(self,owner_id:str, session_id:str, db:ChatSessionDB) -> None:
|
||||||
self.owner_id :str = owner_id
|
self.owner_id :str = owner_id
|
||||||
self.session_id : str = session_id
|
self.session_id : str = session_id
|
||||||
self.db : ChatSessionDB = db
|
self.db : ChatSessionDB = db
|
||||||
|
|
||||||
self.topic : str = None
|
self.topic : str = None
|
||||||
self.start_time : str = None
|
self.start_time : str = None
|
||||||
|
|
||||||
def get_owner_id(self) -> str:
|
def get_owner_id(self) -> str:
|
||||||
return self.owner_id
|
return self.owner_id
|
||||||
|
|
||||||
def read_history(self, number:int=10,offset=0) -> [AgentMsg]:
|
def read_history(self, number:int=10,offset=0) -> [AgentMsg]:
|
||||||
|
return []
|
||||||
msgs = self.db.get_messages(self.session_id, number, offset)
|
msgs = self.db.get_messages(self.session_id, number, offset)
|
||||||
result = []
|
result = []
|
||||||
for msg in msgs:
|
for msg in msgs:
|
||||||
@@ -298,4 +299,4 @@ class AIChatSession:
|
|||||||
# """chat session changed event handler"""
|
# """chat session changed event handler"""
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
#TODO : add iterator interface for read chat history
|
#TODO : add iterator interface for read chat history
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from asyncio import Queue
|
|||||||
|
|
||||||
from .agent import AgentPrompt
|
from .agent import AgentPrompt
|
||||||
from .compute_node import ComputeNode
|
from .compute_node import ComputeNode
|
||||||
from .compute_task import ComputeTask, ComputeTaskState, ComputeTaskResult
|
from .compute_task import ComputeTask, ComputeTaskState, ComputeTaskResult, ComputeTaskType
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class ComputeKernel:
|
|||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = ComputeKernel()
|
cls._instance = ComputeKernel()
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.is_start = False
|
self.is_start = False
|
||||||
self.task_queue = Queue()
|
self.task_queue = Queue()
|
||||||
@@ -73,7 +73,7 @@ class ComputeKernel:
|
|||||||
hit_pos = random.randint(0, total_weights - 1)
|
hit_pos = random.randint(0, total_weights - 1)
|
||||||
for i in range(min(len(support_nodes) - 1, hit_pos), -1, -1):
|
for i in range(min(len(support_nodes) - 1, hit_pos), -1, -1):
|
||||||
if support_nodes[i]["pos"] <= hit_pos:
|
if support_nodes[i]["pos"] <= hit_pos:
|
||||||
return node
|
return support_nodes[i]["node"]
|
||||||
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"task {task.display()} is not support by any compute node")
|
f"task {task.display()} is not support by any compute node")
|
||||||
@@ -137,7 +137,7 @@ class ComputeKernel:
|
|||||||
task_req.set_text_embedding_params(input,model_name)
|
task_req.set_text_embedding_params(input,model_name)
|
||||||
self.run(task_req)
|
self.run(task_req)
|
||||||
return task_req
|
return task_req
|
||||||
|
|
||||||
async def do_text_embedding(self,input:str,model_name:Optional[str] = None) -> [float]:
|
async def do_text_embedding(self,input:str,model_name:Optional[str] = None) -> [float]:
|
||||||
task_req = self.text_embedding(input,model_name)
|
task_req = self.text_embedding(input,model_name)
|
||||||
async def check_timer():
|
async def check_timer():
|
||||||
@@ -155,11 +155,45 @@ class ComputeKernel:
|
|||||||
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
check_times += 1
|
check_times += 1
|
||||||
|
|
||||||
await asyncio.create_task(check_timer())
|
await asyncio.create_task(check_timer())
|
||||||
if task_req.state == ComputeTaskState.DONE:
|
if task_req.state == ComputeTaskState.DONE:
|
||||||
return task_req.result.result
|
return task_req.result.result
|
||||||
|
|
||||||
return "error!"
|
return "error!"
|
||||||
|
|
||||||
|
async def do_text_to_speech(self,
|
||||||
|
input:str,
|
||||||
|
language_code:Optional[str] = None,
|
||||||
|
gender: Optional[str] = None,
|
||||||
|
age: Optional[str] = None,
|
||||||
|
voice_name: Optional[str] = None,
|
||||||
|
tone: Optional[str] = None):
|
||||||
|
task_req = ComputeTask()
|
||||||
|
task_req.params["text"] = input
|
||||||
|
task_req.params["language_code"] = language_code
|
||||||
|
task_req.params["gender"] = gender
|
||||||
|
task_req.params["age"] = age
|
||||||
|
task_req.params["voice_name"] = voice_name
|
||||||
|
task_req.params["tone"] = tone
|
||||||
|
task_req.task_type = ComputeTaskType.TEXT_2_VOICE
|
||||||
|
self.run(task_req)
|
||||||
|
|
||||||
|
check_times = 0
|
||||||
|
while True:
|
||||||
|
if task_req.state == ComputeTaskState.DONE:
|
||||||
|
break
|
||||||
|
if task_req.state == ComputeTaskState.ERROR:
|
||||||
|
break
|
||||||
|
if check_times >= 60:
|
||||||
|
task_req.state = ComputeTaskState.ERROR
|
||||||
|
break
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
check_times += 1
|
||||||
|
|
||||||
|
if task_req.state == ComputeTaskState.DONE:
|
||||||
|
return task_req.result.result
|
||||||
|
else:
|
||||||
|
raise Exception("do_text_to_speech failed!")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,24 +21,69 @@ see:https://cloud.google.com/text-to-speech/docs/before-you-begin
|
|||||||
class GoogleTextToSpeechNode(ComputeNode):
|
class GoogleTextToSpeechNode(ComputeNode):
|
||||||
_instance = None
|
_instance = None
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
@classmethod
|
||||||
|
def get_instance(cls):
|
||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = super(GoogleTextToSpeechNode, cls).__new__(cls)
|
cls._instance = cls()
|
||||||
cls._instance.is_start = False
|
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
if self.is_start is True:
|
|
||||||
logger.warn("GoogleTextToSpeechNode is already start")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.is_start = True
|
|
||||||
self.node_id = "google_text_to_speech_node"
|
self.node_id = "google_text_to_speech_node"
|
||||||
self.task_queue = Queue()
|
self.task_queue = Queue()
|
||||||
|
|
||||||
self.client = texttospeech.TextToSpeechClient()
|
self.client = texttospeech.TextToSpeechClient()
|
||||||
|
|
||||||
|
self.language_list = {
|
||||||
|
"cnm-CN": {
|
||||||
|
"female": ["cmn-CN-Standard-A",
|
||||||
|
"cmn-CN-Standard-D",
|
||||||
|
"cmn-CN-Wavenet-A",
|
||||||
|
"cmn-CN-Wavenet-D",
|
||||||
|
"cmn-TW-Standard-A",
|
||||||
|
"cmn-TW-Wavenet-A"],
|
||||||
|
"man": ["cmn-CN-Standard-B",
|
||||||
|
"cmn-CN-Standard-C",
|
||||||
|
"cmn-CN-Wavenet-B",
|
||||||
|
"cmn-CN-Wavenet-C",
|
||||||
|
"cmn-TW-Standard-B",
|
||||||
|
"cmn-TW-Standard-C",
|
||||||
|
"cmn-TW-Wavenet-B",
|
||||||
|
"cmn-TW-Wavenet-C"]
|
||||||
|
},
|
||||||
|
"en-US": {
|
||||||
|
"female": ["en-US-Neural2-C",
|
||||||
|
"en-US-Neural2-E",
|
||||||
|
"en-US-Neural2-F",
|
||||||
|
"en-US-Neural2-G",
|
||||||
|
"en-US-Neural2-H",
|
||||||
|
"en-US-News-K",
|
||||||
|
"en-US-News-L",
|
||||||
|
"en-US-Standard-C",
|
||||||
|
"en-US-Standard-E",
|
||||||
|
"en-US-Standard-F",
|
||||||
|
"en-US-Standard-G",
|
||||||
|
"en-US-Standard-H",
|
||||||
|
"en-US-Studio-O",
|
||||||
|
"en-US-Wavenet-C",
|
||||||
|
"en-US-Wavenet-E",
|
||||||
|
"en-US-Wavenet-F",
|
||||||
|
"en-US-Wavenet-G",
|
||||||
|
"en-US-Wavenet-H"],
|
||||||
|
"man": ["en-US-Polyglot-1",
|
||||||
|
"en-US-Standard-A",
|
||||||
|
"en-US-Standard-B",
|
||||||
|
"en-US-Standard-D",
|
||||||
|
"en-US-Standard-I",
|
||||||
|
"en-US-Standard-J",
|
||||||
|
"en-US-Studio-M",
|
||||||
|
"en-US-Wavenet-A",
|
||||||
|
"en-US-Wavenet-B",
|
||||||
|
"en-US-Wavenet-D",
|
||||||
|
"en-US-Wavenet-I",
|
||||||
|
"en-US-Wavenet-J"]
|
||||||
|
}
|
||||||
|
}
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@@ -64,10 +109,24 @@ class GoogleTextToSpeechNode(ComputeNode):
|
|||||||
task.state = ComputeTaskState.RUNNING
|
task.state = ComputeTaskState.RUNNING
|
||||||
language_code = task.params["language_code"]
|
language_code = task.params["language_code"]
|
||||||
text = task.params["text"]
|
text = task.params["text"]
|
||||||
|
voice_name = task.params["voice_name"]
|
||||||
|
gender = task.params["gender"]
|
||||||
|
age = task.params["age"]
|
||||||
|
|
||||||
|
if language_code == "zh":
|
||||||
|
language_code = "cnm-CN"
|
||||||
|
elif language_code == "en":
|
||||||
|
language_code = "en-US"
|
||||||
|
else:
|
||||||
|
raise Exception(f"language_code {language_code} not support")
|
||||||
|
|
||||||
|
lang_list = self.language_list[language_code][gender]
|
||||||
|
voice = lang_list[hash(voice_name) % len(lang_list)]
|
||||||
|
|
||||||
synthesis_input = texttospeech.SynthesisInput(text=text)
|
synthesis_input = texttospeech.SynthesisInput(text=text)
|
||||||
voice = texttospeech.VoiceSelectionParams(language_code=language_code,
|
voice = texttospeech.VoiceSelectionParams(language_code=language_code,
|
||||||
ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL)
|
ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL,
|
||||||
|
name=voice)
|
||||||
|
|
||||||
audio_config = texttospeech.AudioConfig(audio_encoding=texttospeech.AudioEncoding.MP3)
|
audio_config = texttospeech.AudioConfig(audio_encoding=texttospeech.AudioEncoding.MP3)
|
||||||
|
|
||||||
@@ -95,8 +154,8 @@ class GoogleTextToSpeechNode(ComputeNode):
|
|||||||
def get_capacity(self):
|
def get_capacity(self):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def is_support(self, task_type: ComputeTaskType) -> bool:
|
def is_support(self, task: ComputeTask) -> bool:
|
||||||
if task_type == ComputeTaskType.TEXT_2_VOICE:
|
if task.task_type == ComputeTaskType.TEXT_2_VOICE:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import io
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from aios_kernel import ComputeKernel
|
||||||
|
from aios_kernel.ai_function import AIFunction
|
||||||
|
|
||||||
|
from pydub import AudioSegment
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class TextToSpeechFunction(AIFunction):
|
||||||
|
def __init__(self):
|
||||||
|
self.func_id = "text_to_speech"
|
||||||
|
self.description = "根据输入的剧本生成音频数据"
|
||||||
|
|
||||||
|
def get_name(self) -> str:
|
||||||
|
return self.func_id
|
||||||
|
|
||||||
|
def get_description(self) -> str:
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def get_parameters(self) -> Dict:
|
||||||
|
return {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"language": {"type": "string", "description": "演播语言", "enum": ["zh", "en"]},
|
||||||
|
"roles": {"type": "array", "items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {"type": "string", "description": "角色名字"},
|
||||||
|
"gender": {"type": "string", "description": "角色性别", "enum": ["man", "female"]},
|
||||||
|
"age": {"type": "string", "description": "年龄", "enum": ["child", "adult"]},
|
||||||
|
}}},
|
||||||
|
"lines": {"type": "array", "items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {"type": "string", "description": "角色名字"},
|
||||||
|
"tone": {"type": "string", "description": "演播情感",
|
||||||
|
"enum": ["happy", "sad", "angry", "fear", "disgust", "surprise", "neutral"]},
|
||||||
|
"text": {"type": "string", "description": "台词"},
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async def execute(self, **kwargs) -> str:
|
||||||
|
logger.info(f"execute text_to_speech function: {kwargs}")
|
||||||
|
|
||||||
|
language = kwargs.get("language")
|
||||||
|
if language is None:
|
||||||
|
language = "zh"
|
||||||
|
roles = kwargs.get("roles")
|
||||||
|
lines = kwargs.get("lines")
|
||||||
|
|
||||||
|
audio = None
|
||||||
|
for line in lines:
|
||||||
|
name = line.get("name")
|
||||||
|
tone = line.get("tone")
|
||||||
|
text = line.get("text")
|
||||||
|
gender = None
|
||||||
|
age = None
|
||||||
|
for role in roles:
|
||||||
|
role_name = role.get("name")
|
||||||
|
if role_name == name:
|
||||||
|
gender = role.get("gender")
|
||||||
|
age = role.get("age")
|
||||||
|
break
|
||||||
|
i = 0
|
||||||
|
while i < 3:
|
||||||
|
try:
|
||||||
|
data = await ComputeKernel.get_instance().do_text_to_speech(text, language, gender, age, name, tone)
|
||||||
|
if audio is None:
|
||||||
|
audio = AudioSegment.from_mp3(io.BytesIO(data))
|
||||||
|
else:
|
||||||
|
audio = audio + AudioSegment.from_mp3(io.BytesIO(data))
|
||||||
|
break
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"do_text_to_speech failed: {e}")
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if audio is not None:
|
||||||
|
path = os.path.join(os.curdir, "{}.mp3".format(random.sample('zyxwvutsrqponmlkjihgfedcba', 10)))
|
||||||
|
audio.export(path, format="mp3")
|
||||||
|
return "complete.file path:{}".format(path)
|
||||||
|
else:
|
||||||
|
return "failed"
|
||||||
|
|
||||||
|
def is_local(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_in_zone(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def is_ready_only(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -7,6 +7,8 @@ from sqlite3 import Error
|
|||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from .text_to_speech_function import TextToSpeechFunction
|
||||||
from .environment import Environment,EnvironmentEvent
|
from .environment import Environment,EnvironmentEvent
|
||||||
from .ai_function import SimpleAIFunction
|
from .ai_function import SimpleAIFunction
|
||||||
from .storage import AIStorage
|
from .storage import AIStorage
|
||||||
@@ -23,8 +25,8 @@ class CalenderEvent(EnvironmentEvent):
|
|||||||
self.data = data
|
self.data = data
|
||||||
|
|
||||||
def display(self) -> str:
|
def display(self) -> str:
|
||||||
return f"#event timer:{self.data}"
|
return f"#event timer:{self.data}"
|
||||||
|
|
||||||
# AI Calender GOAL: Let user use "create notify after 2 days" to create a timer event
|
# AI Calender GOAL: Let user use "create notify after 2 days" to create a timer event
|
||||||
class CalenderEnvironment(Environment):
|
class CalenderEnvironment(Environment):
|
||||||
def __init__(self, env_id: str) -> None:
|
def __init__(self, env_id: str) -> None:
|
||||||
@@ -39,7 +41,7 @@ class CalenderEnvironment(Environment):
|
|||||||
#self.add_ai_function(SimpleAIFunction("serach_events",
|
#self.add_ai_function(SimpleAIFunction("serach_events",
|
||||||
# "search events in calender",
|
# "search events in calender",
|
||||||
# self._search_events))
|
# self._search_events))
|
||||||
|
|
||||||
get_param = {
|
get_param = {
|
||||||
"start_time": "start time (UTC) of event",
|
"start_time": "start time (UTC) of event",
|
||||||
"end_time": "end time (UTC) of event"
|
"end_time": "end time (UTC) of event"
|
||||||
@@ -59,14 +61,14 @@ class CalenderEnvironment(Environment):
|
|||||||
self.add_ai_function(SimpleAIFunction("add_event",
|
self.add_ai_function(SimpleAIFunction("add_event",
|
||||||
"add event to calender",
|
"add event to calender",
|
||||||
self._add_event,add_param))
|
self._add_event,add_param))
|
||||||
|
|
||||||
delete_param = {
|
delete_param = {
|
||||||
"event_id": "id of event"
|
"event_id": "id of event"
|
||||||
}
|
}
|
||||||
self.add_ai_function(SimpleAIFunction("delete_event",
|
self.add_ai_function(SimpleAIFunction("delete_event",
|
||||||
"delete event from calender",
|
"delete event from calender",
|
||||||
self._delete_event,delete_param))
|
self._delete_event,delete_param))
|
||||||
|
|
||||||
update_param = {
|
update_param = {
|
||||||
"event_id": "id of event",
|
"event_id": "id of event",
|
||||||
"new_title": "new title of event",
|
"new_title": "new title of event",
|
||||||
@@ -79,7 +81,7 @@ class CalenderEnvironment(Environment):
|
|||||||
self.add_ai_function(SimpleAIFunction("update_event",
|
self.add_ai_function(SimpleAIFunction("update_event",
|
||||||
"update event in calender",
|
"update event in calender",
|
||||||
self._update_event,update_param))
|
self._update_event,update_param))
|
||||||
|
|
||||||
#self.add_ai_function(SimpleAIFunction("user_confirm",
|
#self.add_ai_function(SimpleAIFunction("user_confirm",
|
||||||
# "user confirm",
|
# "user confirm",
|
||||||
# self._user_confirm))
|
# self._user_confirm))
|
||||||
@@ -98,7 +100,7 @@ class CalenderEnvironment(Environment):
|
|||||||
);
|
);
|
||||||
""")
|
""")
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
async def _add_event(self,title, start_time, end_time, participants=None, location=None, details=None):
|
async def _add_event(self,title, start_time, end_time, participants=None, location=None, details=None):
|
||||||
async with aiosqlite.connect(self.db_file) as db:
|
async with aiosqlite.connect(self.db_file) as db:
|
||||||
await db.execute("""
|
await db.execute("""
|
||||||
@@ -127,7 +129,7 @@ class CalenderEnvironment(Environment):
|
|||||||
_event["details"] = row[6]
|
_event["details"] = row[6]
|
||||||
result[row[0]] = _event
|
result[row[0]] = _event
|
||||||
return json.dumps(result, indent=4, sort_keys=True)
|
return json.dumps(result, indent=4, sort_keys=True)
|
||||||
|
|
||||||
async def _get_events_by_time_range(self,start_time, end_time):
|
async def _get_events_by_time_range(self,start_time, end_time):
|
||||||
async with aiosqlite.connect(self.db_file) as db:
|
async with aiosqlite.connect(self.db_file) as db:
|
||||||
cursor = await db.execute("""
|
cursor = await db.execute("""
|
||||||
@@ -153,7 +155,7 @@ class CalenderEnvironment(Environment):
|
|||||||
return "No event."
|
return "No event."
|
||||||
|
|
||||||
return json.dumps(result, indent=4, sort_keys=True)
|
return json.dumps(result, indent=4, sort_keys=True)
|
||||||
|
|
||||||
async def _update_event(self,event_id, new_title=None, new_participants=None, new_location=None, new_details=None ,start_time=None, end_time=None):
|
async def _update_event(self,event_id, new_title=None, new_participants=None, new_location=None, new_details=None ,start_time=None, end_time=None):
|
||||||
fields_to_update = []
|
fields_to_update = []
|
||||||
values = []
|
values = []
|
||||||
@@ -191,8 +193,8 @@ class CalenderEnvironment(Environment):
|
|||||||
WHERE id = ?;
|
WHERE id = ?;
|
||||||
"""
|
"""
|
||||||
|
|
||||||
values.append(event_id)
|
values.append(event_id)
|
||||||
|
|
||||||
async with aiosqlite.connect(self.db_file) as db:
|
async with aiosqlite.connect(self.db_file) as db:
|
||||||
await db.execute(sql_update_query, values)
|
await db.execute(sql_update_query, values)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
@@ -212,16 +214,16 @@ class CalenderEnvironment(Environment):
|
|||||||
|
|
||||||
async def start(self) -> None:
|
async def start(self) -> None:
|
||||||
if self.is_run:
|
if self.is_run:
|
||||||
return
|
return
|
||||||
self.is_run = True
|
self.is_run = True
|
||||||
await self.init_db()
|
await self.init_db()
|
||||||
|
|
||||||
self.register_get_handler("now",self.get_now)
|
self.register_get_handler("now",self.get_now)
|
||||||
async def timer_loop():
|
async def timer_loop():
|
||||||
while True:
|
while True:
|
||||||
if self.is_run == False:
|
if self.is_run == False:
|
||||||
break
|
break
|
||||||
|
|
||||||
await asyncio.sleep(1.0)
|
await asyncio.sleep(1.0)
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
@@ -238,13 +240,13 @@ class CalenderEnvironment(Environment):
|
|||||||
def get_now(self)->str:
|
def get_now(self)->str:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
return formatted_time
|
return formatted_time
|
||||||
|
|
||||||
async def _get_now(self) -> str:
|
async def _get_now(self) -> str:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
return formatted_time
|
return formatted_time
|
||||||
|
|
||||||
# Default Workflow Environment(Context)
|
# Default Workflow Environment(Context)
|
||||||
class WorkflowEnvironment(Environment):
|
class WorkflowEnvironment(Environment):
|
||||||
def __init__(self, env_id: str,db_file:str) -> None:
|
def __init__(self, env_id: str,db_file:str) -> None:
|
||||||
@@ -252,6 +254,7 @@ class WorkflowEnvironment(Environment):
|
|||||||
self.db_file = db_file
|
self.db_file = db_file
|
||||||
self.local = threading.local()
|
self.local = threading.local()
|
||||||
self.table_name = "WorkflowEnv_" + env_id
|
self.table_name = "WorkflowEnv_" + env_id
|
||||||
|
self.add_ai_function(TextToSpeechFunction())
|
||||||
|
|
||||||
|
|
||||||
def _get_conn(self):
|
def _get_conn(self):
|
||||||
@@ -259,7 +262,7 @@ class WorkflowEnvironment(Environment):
|
|||||||
if not hasattr(self.local, 'conn'):
|
if not hasattr(self.local, 'conn'):
|
||||||
self.local.conn = self._create_connection()
|
self.local.conn = self._create_connection()
|
||||||
return self.local.conn
|
return self.local.conn
|
||||||
|
|
||||||
def _create_connection(self):
|
def _create_connection(self):
|
||||||
""" create a database connection to a SQLite database """
|
""" create a database connection to a SQLite database """
|
||||||
conn = None
|
conn = None
|
||||||
@@ -273,10 +276,10 @@ class WorkflowEnvironment(Environment):
|
|||||||
self._create_table(conn)
|
self._create_table(conn)
|
||||||
|
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if not hasattr(self.local, 'conn'):
|
if not hasattr(self.local, 'conn'):
|
||||||
return
|
return
|
||||||
self.local.conn.close()
|
self.local.conn.close()
|
||||||
|
|
||||||
def _create_table(self, conn):
|
def _create_table(self, conn):
|
||||||
@@ -293,7 +296,7 @@ class WorkflowEnvironment(Environment):
|
|||||||
conn.commit()
|
conn.commit()
|
||||||
except Error as e:
|
except Error as e:
|
||||||
logging.error("Error occurred while creating tables: %s", e)
|
logging.error("Error occurred while creating tables: %s", e)
|
||||||
|
|
||||||
def _do_get_value(self, key: str) -> str | None:
|
def _do_get_value(self, key: str) -> str | None:
|
||||||
try:
|
try:
|
||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
@@ -311,7 +314,7 @@ class WorkflowEnvironment(Environment):
|
|||||||
super().set_value(key,str_value)
|
super().set_value(key,str_value)
|
||||||
if is_storage is False:
|
if is_storage is False:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn = self._get_conn()
|
conn = self._get_conn()
|
||||||
conn.execute("""
|
conn.execute("""
|
||||||
|
|||||||
@@ -64,17 +64,17 @@ class AIOS_Shell:
|
|||||||
target_id = msg.target.split(".")[0]
|
target_id = msg.target.split(".")[0]
|
||||||
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
||||||
if agent is not None:
|
if agent is not None:
|
||||||
agent.owner_env = Environment.get_env_by_id("calender")
|
agent.owner_env = Environment.get_env_by_id("calender")
|
||||||
bus.register_message_handler(target_id,agent._process_msg)
|
bus.register_message_handler(target_id,agent._process_msg)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
a_workflow = await WorkflowManager.get_instance().get_workflow(target_id)
|
a_workflow = await WorkflowManager.get_instance().get_workflow(target_id)
|
||||||
if a_workflow is not None:
|
if a_workflow is not None:
|
||||||
bus.register_message_handler(target_id,a_workflow._process_msg)
|
bus.register_message_handler(target_id,a_workflow._process_msg)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def is_agent(self,target_id:str) -> bool:
|
async def is_agent(self,target_id:str) -> bool:
|
||||||
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
||||||
if agent is not None:
|
if agent is not None:
|
||||||
@@ -96,7 +96,10 @@ class AIOS_Shell:
|
|||||||
logger.error("openai node initial failed!")
|
logger.error("openai node initial failed!")
|
||||||
return False
|
return False
|
||||||
ComputeKernel.get_instance().add_compute_node(open_ai_node)
|
ComputeKernel.get_instance().add_compute_node(open_ai_node)
|
||||||
|
|
||||||
|
google_text_to_speech_node = GoogleTextToSpeechNode.get_instance()
|
||||||
|
ComputeKernel.get_instance().add_compute_node(google_text_to_speech_node)
|
||||||
|
|
||||||
llama_ai_node = LocalLlama_ComputeNode()
|
llama_ai_node = LocalLlama_ComputeNode()
|
||||||
await llama_ai_node.start()
|
await llama_ai_node.start()
|
||||||
# ComputeKernel.get_instance().add_compute_node(llama_ai_node)
|
# ComputeKernel.get_instance().add_compute_node(llama_ai_node)
|
||||||
@@ -116,7 +119,7 @@ class AIOS_Shell:
|
|||||||
|
|
||||||
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
||||||
tunnel_config = None
|
tunnel_config = None
|
||||||
try:
|
try:
|
||||||
tunnel_config = toml.load(tunnels_config_path)
|
tunnel_config = toml.load(tunnels_config_path)
|
||||||
if tunnel_config is not None:
|
if tunnel_config is not None:
|
||||||
await AgentTunnel.load_all_tunnels_from_config(tunnel_config)
|
await AgentTunnel.load_all_tunnels_from_config(tunnel_config)
|
||||||
@@ -156,11 +159,11 @@ class AIOS_Shell:
|
|||||||
case "email":
|
case "email":
|
||||||
tunnel_config["type"] = "EmailTunnel"
|
tunnel_config["type"] = "EmailTunnel"
|
||||||
case _:
|
case _:
|
||||||
error_text = FormattedText([("class:error", f"tunnel type {tunnel_type}not support!")])
|
error_text = FormattedText([("class:error", f"tunnel type {tunnel_type}not support!")])
|
||||||
print_formatted_text(error_text,style=shell_style)
|
print_formatted_text(error_text,style=shell_style)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
intro_text = FormattedText([("class:prompt", tunnel_introduce)])
|
intro_text = FormattedText([("class:prompt", tunnel_introduce)])
|
||||||
print_formatted_text(intro_text,style=shell_style)
|
print_formatted_text(intro_text,style=shell_style)
|
||||||
for key,item in intpu_table.items():
|
for key,item in intpu_table.items():
|
||||||
user_input = await try_get_input(f"{key} : {item.desc}")
|
user_input = await try_get_input(f"{key} : {item.desc}")
|
||||||
@@ -174,7 +177,7 @@ class AIOS_Shell:
|
|||||||
async def append_tunnel_config(self,tunnel_config):
|
async def append_tunnel_config(self,tunnel_config):
|
||||||
user_data_dir = AIStorage.get_instance().get_myai_dir()
|
user_data_dir = AIStorage.get_instance().get_myai_dir()
|
||||||
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
||||||
try:
|
try:
|
||||||
all_tunnels = toml.load(tunnels_config_path)
|
all_tunnels = toml.load(tunnels_config_path)
|
||||||
if all_tunnels is not None:
|
if all_tunnels is not None:
|
||||||
all_tunnels[tunnel_config["tunnel_id"]] = tunnel_config
|
all_tunnels[tunnel_config["tunnel_id"]] = tunnel_config
|
||||||
@@ -255,7 +258,7 @@ class AIOS_Shell:
|
|||||||
AIStorage.get_instance().get_user_config().set_value(key,value)
|
AIStorage.get_instance().get_user_config().set_value(key,value)
|
||||||
await AIStorage.get_instance().get_user_config().save_to_user_config()
|
await AIStorage.get_instance().get_user_config().save_to_user_config()
|
||||||
show_text = FormattedText([("class:title", f"set {key} to {value} success!")])
|
show_text = FormattedText([("class:title", f"set {key} to {value} success!")])
|
||||||
|
|
||||||
return show_text
|
return show_text
|
||||||
case 'connect':
|
case 'connect':
|
||||||
show_text = FormattedText([("class:title", "args error, /connect $target telegram | email")])
|
show_text = FormattedText([("class:title", "args error, /connect $target telegram | email")])
|
||||||
@@ -293,8 +296,8 @@ class AIOS_Shell:
|
|||||||
if len(args) >= 1:
|
if len(args) >= 1:
|
||||||
self.username = args[0]
|
self.username = args[0]
|
||||||
AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
||||||
|
|
||||||
return self.username + " login success!"
|
return self.username + " login success!"
|
||||||
case 'history':
|
case 'history':
|
||||||
num = 10
|
num = 10
|
||||||
offset = 0
|
offset = 0
|
||||||
@@ -324,9 +327,9 @@ class AIOS_Shell:
|
|||||||
return FormattedText([("class:title", f"help~~~")])
|
return FormattedText([("class:title", f"help~~~")])
|
||||||
|
|
||||||
|
|
||||||
##########################################################################################################################
|
##########################################################################################################################
|
||||||
history = FileHistory('aios_shell_history.txt')
|
history = FileHistory('aios_shell_history.txt')
|
||||||
session = PromptSession(history=history)
|
session = PromptSession(history=history)
|
||||||
|
|
||||||
def parse_function_call(func_string):
|
def parse_function_call(func_string):
|
||||||
if len(func_string) > 2:
|
if len(func_string) > 2:
|
||||||
@@ -337,7 +340,7 @@ def parse_function_call(func_string):
|
|||||||
return func_name, params
|
return func_name, params
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def try_get_input(desc:str,check_func:callable = None) -> str:
|
async def try_get_input(desc:str,check_func:callable = None) -> str:
|
||||||
user_input = await session.prompt_async(f"{desc} \nType /exit to abort. \nPlease input:",style=shell_style)
|
user_input = await session.prompt_async(f"{desc} \nType /exit to abort. \nPlease input:",style=shell_style)
|
||||||
err_str = ""
|
err_str = ""
|
||||||
@@ -347,13 +350,13 @@ async def try_get_input(desc:str,check_func:callable = None) -> str:
|
|||||||
return user_input
|
return user_input
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
is_ok,err_str = check_func(user_input)
|
is_ok,err_str = check_func(user_input)
|
||||||
if is_ok:
|
if is_ok:
|
||||||
return user_input
|
return user_input
|
||||||
|
|
||||||
error_text = FormattedText([("class:error", err_str)])
|
error_text = FormattedText([("class:error", err_str)])
|
||||||
print_formatted_text(error_text,style=shell_style)
|
print_formatted_text(error_text,style=shell_style)
|
||||||
return await try_get_input(desc,check_func)
|
return await try_get_input(desc,check_func)
|
||||||
|
|
||||||
@@ -373,7 +376,7 @@ async def main_daemon_loop(shell:AIOS_Shell):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def print_welcome_screen():
|
def print_welcome_screen():
|
||||||
print("\033[1;31m")
|
print("\033[1;31m")
|
||||||
logo = """
|
logo = """
|
||||||
\t _______ ____________________ __
|
\t _______ ____________________ __
|
||||||
\t __ __ \______________________ __ \__ |__ | / /
|
\t __ __ \______________________ __ \__ |__ | / /
|
||||||
@@ -384,9 +387,9 @@ def print_welcome_screen():
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
print(logo)
|
print(logo)
|
||||||
print("\033[0m")
|
print("\033[0m")
|
||||||
|
|
||||||
print("\033[1;32m \t\tWelcome to OpenDAN - Your Personal AI OS\033[0m\n")
|
print("\033[1;32m \t\tWelcome to OpenDAN - Your Personal AI OS\033[0m\n")
|
||||||
|
|
||||||
introduce = """
|
introduce = """
|
||||||
\tThe core goal of version 0.5.1 is to turn the concept of AIOS into code and get it up and running as quickly as possible.
|
\tThe core goal of version 0.5.1 is to turn the concept of AIOS into code and get it up and running as quickly as possible.
|
||||||
@@ -396,12 +399,12 @@ def print_welcome_screen():
|
|||||||
\twe intend to strengthen some components. This document will explain these changes and provide an update
|
\twe intend to strengthen some components. This document will explain these changes and provide an update
|
||||||
\ton the current development progress of MVP(0.5.1,0.5.2)
|
\ton the current development progress of MVP(0.5.1,0.5.2)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
print(introduce)
|
print(introduce)
|
||||||
|
|
||||||
print(f"\033[1;34m \t\tVersion: {AIOS_Version}\n\033")
|
print(f"\033[1;34m \t\tVersion: {AIOS_Version}\n\033")
|
||||||
print("\033[1;33m \tOpenDAN is an open-source project, let's define the future of Humans and AI together.\033[0m")
|
print("\033[1;33m \tOpenDAN is an open-source project, let's define the future of Humans and AI together.\033[0m")
|
||||||
print("\033[1;33m \tGithub\t: https://github.com/fiatrete/OpenDAN-Personal-AI-OS\033[0m")
|
print("\033[1;33m \tGithub\t: https://github.com/fiatrete/OpenDAN-Personal-AI-OS\033[0m")
|
||||||
print("\033[1;33m \tWebsite\t: https://www.opendan.ai\033[0m")
|
print("\033[1;33m \tWebsite\t: https://www.opendan.ai\033[0m")
|
||||||
print("\n\n")
|
print("\n\n")
|
||||||
|
|
||||||
@@ -412,19 +415,19 @@ async def main():
|
|||||||
logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8',force=True,
|
logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8',force=True,
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s')
|
format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s')
|
||||||
|
|
||||||
if os.path.isdir(f"{directory}/../../../rootfs"):
|
if os.path.isdir(f"{directory}/../../../rootfs"):
|
||||||
AIStorage.get_instance().is_dev_mode = True
|
AIStorage.get_instance().is_dev_mode = True
|
||||||
else:
|
else:
|
||||||
AIStorage.get_instance().is_dev_mode = False
|
AIStorage.get_instance().is_dev_mode = False
|
||||||
|
|
||||||
is_daemon = False
|
is_daemon = False
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
if os.getppid() == 1:
|
if os.getppid() == 1:
|
||||||
is_daemon = True
|
is_daemon = True
|
||||||
|
|
||||||
shell = AIOS_Shell("user")
|
shell = AIOS_Shell("user")
|
||||||
shell.declare_all_user_config()
|
shell.declare_all_user_config()
|
||||||
await AIStorage.get_instance().initial()
|
await AIStorage.get_instance().initial()
|
||||||
check_result = AIStorage.get_instance().get_user_config().check_config()
|
check_result = AIStorage.get_instance().get_user_config().check_config()
|
||||||
if check_result is not None:
|
if check_result is not None:
|
||||||
@@ -435,7 +438,7 @@ async def main():
|
|||||||
#Remind users to enter necessary configurations.
|
#Remind users to enter necessary configurations.
|
||||||
if await get_user_config_from_input(check_result) is False:
|
if await get_user_config_from_input(check_result) is False:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
init_result = await shell.initial()
|
init_result = await shell.initial()
|
||||||
if init_result is False:
|
if init_result is False:
|
||||||
if is_daemon:
|
if is_daemon:
|
||||||
@@ -451,8 +454,8 @@ async def main():
|
|||||||
proxy.apply_storage()
|
proxy.apply_storage()
|
||||||
|
|
||||||
#TODO: read last input config
|
#TODO: read last input config
|
||||||
completer = WordCompleter(['/send $target $msg $topic',
|
completer = WordCompleter(['/send $target $msg $topic',
|
||||||
'/open $target $topic',
|
'/open $target $topic',
|
||||||
'/history $num $offset',
|
'/history $num $offset',
|
||||||
'/login $username',
|
'/login $username',
|
||||||
'/connect $target',
|
'/connect $target',
|
||||||
@@ -462,7 +465,7 @@ async def main():
|
|||||||
'/set_config $key',
|
'/set_config $key',
|
||||||
'/list_config',
|
'/list_config',
|
||||||
'/show',
|
'/show',
|
||||||
'/exit',
|
'/exit',
|
||||||
'/help'], ignore_case=True)
|
'/help'], ignore_case=True)
|
||||||
|
|
||||||
current = AIStorage.get_instance().get_user_config().get_value("shell.current")
|
current = AIStorage.get_instance().get_user_config().get_value("shell.current")
|
||||||
@@ -470,7 +473,7 @@ async def main():
|
|||||||
shell.current_target = current[1]
|
shell.current_target = current[1]
|
||||||
shell.current_topic = current[0]
|
shell.current_topic = current[0]
|
||||||
|
|
||||||
await asyncio.sleep(0.2)
|
await asyncio.sleep(0.2)
|
||||||
while True:
|
while True:
|
||||||
user_input = await session.prompt_async(f"{shell.username}<->{shell.current_topic}@{shell.current_target}$ ",completer=completer,style=shell_style)
|
user_input = await session.prompt_async(f"{shell.username}<->{shell.current_topic}@{shell.current_target}$ ",completer=completer,style=shell_style)
|
||||||
if len(user_input) <= 1:
|
if len(user_input) <= 1:
|
||||||
@@ -491,6 +494,6 @@ async def main():
|
|||||||
#print_formatted_text(f"{shell.username}<->{shell.current_topic}@{shell.current_target} >>> {resp}",style=shell_style)
|
#print_formatted_text(f"{shell.username}<->{shell.current_topic}@{shell.current_target} >>> {resp}",style=shell_style)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user