2023-08-27 18:07:33 -07:00
|
|
|
# aiso shell like bash for linux
|
|
|
|
|
import asyncio
|
|
|
|
|
import sys
|
|
|
|
|
import os
|
|
|
|
|
import logging
|
2023-08-30 23:01:44 -07:00
|
|
|
import re
|
2023-09-15 17:35:12 -07:00
|
|
|
import toml
|
2023-09-18 00:40:37 -07:00
|
|
|
import shlex
|
2023-09-26 01:19:33 -07:00
|
|
|
from logging.handlers import RotatingFileHandler
|
2023-08-27 18:07:33 -07:00
|
|
|
|
|
|
|
|
from typing import Any, Optional, TypeVar, Tuple, Sequence
|
|
|
|
|
import argparse
|
|
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
|
|
|
|
|
from prompt_toolkit import HTML, PromptSession, prompt,print_formatted_text
|
|
|
|
|
from prompt_toolkit.formatted_text import FormattedText
|
2023-08-27 18:07:33 -07:00
|
|
|
from prompt_toolkit.selection import SelectionState
|
|
|
|
|
from prompt_toolkit.history import FileHistory
|
|
|
|
|
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
|
|
|
from prompt_toolkit.completion import WordCompleter
|
2023-08-30 23:01:44 -07:00
|
|
|
from prompt_toolkit.styles import Style
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
directory = os.path.dirname(__file__)
|
|
|
|
|
sys.path.append(directory + '/../../')
|
2023-09-17 18:30:26 -07:00
|
|
|
|
2023-09-27 20:32:37 -07:00
|
|
|
|
|
|
|
|
|
2023-09-19 08:29:55 +00:00
|
|
|
import proxy
|
2023-09-21 18:32:17 +08:00
|
|
|
from aios_kernel import *
|
2023-09-27 20:32:37 -07:00
|
|
|
|
2023-09-21 18:32:17 +08:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
sys.path.append(directory + '/../../component/')
|
|
|
|
|
from agent_manager import AgentManager
|
|
|
|
|
from workflow_manager import WorkflowManager
|
2023-09-15 17:35:12 -07:00
|
|
|
|
2023-08-30 12:30:41 -07:00
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2023-09-16 11:41:59 -07:00
|
|
|
shell_style = Style.from_dict({
|
|
|
|
|
'title': '#87d7ff bold', #RGB
|
2023-09-19 15:43:17 -07:00
|
|
|
'content': '#007f00', # resp content
|
2023-09-16 11:41:59 -07:00
|
|
|
'prompt': '#00FF00',
|
2023-09-19 15:43:17 -07:00
|
|
|
'error': '#8F0000 bold'
|
2023-09-16 11:41:59 -07:00
|
|
|
})
|
2023-08-30 12:30:41 -07:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
class AIOS_Shell:
|
|
|
|
|
def __init__(self,username:str) -> None:
|
|
|
|
|
self.username = username
|
2023-08-30 23:01:44 -07:00
|
|
|
self.current_target = "_"
|
|
|
|
|
self.current_topic = "default"
|
2023-09-17 18:18:54 -07:00
|
|
|
self.is_working = True
|
|
|
|
|
|
|
|
|
|
def declare_all_user_config(self):
|
2023-09-26 01:19:33 -07:00
|
|
|
user_data_dir = AIStorage.get_instance().get_myai_dir()
|
|
|
|
|
contact_config_path =os.path.abspath(f"{user_data_dir}/contacts.toml")
|
|
|
|
|
cm = ContactManager.get_instance(contact_config_path)
|
2023-09-25 20:57:10 -07:00
|
|
|
cm.load_data()
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
user_config = AIStorage.get_instance().get_user_config()
|
2023-09-25 20:57:10 -07:00
|
|
|
user_config.add_user_config("username","username is your full name when using AIOS",False,None)
|
|
|
|
|
user_config.add_user_config("telegram","Your telgram username",False,None)
|
|
|
|
|
user_config.add_user_config("email","Your email",False,None)
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
user_config.add_user_config("feature.llama","enable Local-llama feature",True,"False")
|
|
|
|
|
user_config.add_user_config("feature.aigc","enable AIGC feature",True,"False")
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
openai_node = OpenAI_ComputeNode.get_instance()
|
|
|
|
|
openai_node.declare_user_config()
|
|
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
user_config.add_user_config("shell.current","last opened target and topic",True,"default@Jarvis")
|
2023-09-19 08:29:55 +00:00
|
|
|
proxy.declare_user_config()
|
2023-09-19 00:53:13 -07:00
|
|
|
|
2023-09-22 13:38:44 +08:00
|
|
|
google_text_to_speech = GoogleTextToSpeechNode.get_instance()
|
|
|
|
|
google_text_to_speech.declare_user_config()
|
|
|
|
|
|
2023-09-23 13:19:18 +08:00
|
|
|
Local_Stability_ComputeNode.declare_user_config()
|
|
|
|
|
|
2023-09-26 16:40:52 +08:00
|
|
|
#Stability_ComputeNode.declare_user_config()
|
2023-09-26 01:19:33 -07:00
|
|
|
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-08-30 12:30:41 -07:00
|
|
|
async def _handle_no_target_msg(self,bus:AIBus,msg:AgentMsg) -> bool:
|
2023-09-01 00:39:36 -07:00
|
|
|
target_id = msg.target.split(".")[0]
|
2023-09-16 11:41:59 -07:00
|
|
|
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
2023-08-30 12:30:41 -07:00
|
|
|
if agent is not None:
|
2023-09-01 00:39:36 -07:00
|
|
|
bus.register_message_handler(target_id,agent._process_msg)
|
2023-08-30 12:30:41 -07:00
|
|
|
return True
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-16 11:41:59 -07:00
|
|
|
a_workflow = await WorkflowManager.get_instance().get_workflow(target_id)
|
2023-08-30 12:30:41 -07:00
|
|
|
if a_workflow is not None:
|
2023-09-01 00:39:36 -07:00
|
|
|
bus.register_message_handler(target_id,a_workflow._process_msg)
|
2023-08-30 12:30:41 -07:00
|
|
|
return True
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-08-30 12:30:41 -07:00
|
|
|
return False
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
async def is_agent(self,target_id:str) -> bool:
|
2023-09-16 11:41:59 -07:00
|
|
|
agent : AIAgent = await AgentManager.get_instance().get(target_id)
|
2023-08-30 23:01:44 -07:00
|
|
|
if agent is not None:
|
|
|
|
|
return True
|
|
|
|
|
else:
|
|
|
|
|
return False
|
2023-08-30 12:30:41 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
async def initial(self) -> bool:
|
2023-09-25 20:57:10 -07:00
|
|
|
cm = ContactManager.get_instance()
|
|
|
|
|
owenr = cm.find_contact_by_name(self.username)
|
|
|
|
|
if owenr is None:
|
|
|
|
|
owenr = Contact(self.username)
|
|
|
|
|
owenr.added_by = self.username
|
|
|
|
|
owenr.is_family_member = True
|
|
|
|
|
owenr.email = AIStorage.get_instance().get_user_config().get_value("email")
|
|
|
|
|
owenr.telegram = AIStorage.get_instance().get_user_config().get_value("telegram")
|
|
|
|
|
|
2023-09-27 10:09:31 -07:00
|
|
|
cm.add_family_member(self.username,owenr)
|
2023-09-25 20:57:10 -07:00
|
|
|
|
2023-09-27 15:52:17 +08:00
|
|
|
knowledge_env = KnowledgeEnvironment("knowledge")
|
|
|
|
|
Environment.set_env_by_id("knowledge",knowledge_env)
|
|
|
|
|
|
2023-09-04 22:36:59 -07:00
|
|
|
cal_env = CalenderEnvironment("calender")
|
2023-09-20 01:33:00 -07:00
|
|
|
await cal_env.start()
|
2023-09-04 22:36:59 -07:00
|
|
|
Environment.set_env_by_id("calender",cal_env)
|
2023-09-21 20:51:21 -07:00
|
|
|
|
2023-09-21 23:18:52 -07:00
|
|
|
workspace_env = WorkspaceEnvironment("bash")
|
|
|
|
|
Environment.set_env_by_id("bash",workspace_env)
|
|
|
|
|
|
2023-09-26 16:40:52 +08:00
|
|
|
paint_env = PaintEnvironment("paint")
|
|
|
|
|
Environment.set_env_by_id("paint",paint_env)
|
|
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
if await AgentManager.get_instance().initial() is not True:
|
|
|
|
|
logger.error("agent manager initial failed!")
|
|
|
|
|
return False
|
|
|
|
|
if await WorkflowManager.get_instance().initial() is not True:
|
|
|
|
|
logger.error("workflow manager initial failed!")
|
|
|
|
|
return False
|
2023-09-21 20:51:21 -07:00
|
|
|
|
2023-09-16 11:41:59 -07:00
|
|
|
open_ai_node = OpenAI_ComputeNode.get_instance()
|
2023-09-17 18:18:54 -07:00
|
|
|
if await open_ai_node.initial() is not True:
|
|
|
|
|
logger.error("openai node initial failed!")
|
|
|
|
|
return False
|
2023-09-16 11:41:59 -07:00
|
|
|
ComputeKernel.get_instance().add_compute_node(open_ai_node)
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
if await AIStorage.get_instance().is_feature_enable("llama"):
|
|
|
|
|
llama_ai_node = LocalLlama_ComputeNode()
|
|
|
|
|
if await llama_ai_node.initial() is True:
|
2023-09-27 20:32:37 -07:00
|
|
|
await llama_ai_node.start()
|
2023-09-26 01:19:33 -07:00
|
|
|
ComputeKernel.get_instance().add_compute_node(llama_ai_node)
|
|
|
|
|
else:
|
|
|
|
|
logger.error("llama node initial failed!")
|
|
|
|
|
await AIStorage.get_instance().set_feature_init_result("llama",False)
|
|
|
|
|
|
2023-09-26 20:25:02 +08:00
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
if await AIStorage.get_instance().is_feature_enable("aigc"):
|
|
|
|
|
try:
|
|
|
|
|
google_text_to_speech_node = GoogleTextToSpeechNode.get_instance()
|
|
|
|
|
google_text_to_speech_node.init()
|
|
|
|
|
ComputeKernel.get_instance().add_compute_node(google_text_to_speech_node)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"google text to speech node initial failed! {e}")
|
|
|
|
|
await AIStorage.get_instance.set_feature_init_result("aigc",False)
|
|
|
|
|
|
2023-09-26 16:40:52 +08:00
|
|
|
# stability_api_node = Stability_ComputeNode()
|
|
|
|
|
# if await stability_api_node.initial() is not True:
|
|
|
|
|
# logger.error("stability api node initial failed!")
|
|
|
|
|
# ComputeKernel.get_instance().add_compute_node(stability_api_node)
|
2023-09-27 20:32:37 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-09-26 20:25:02 +08:00
|
|
|
local_st_text_compute_node = LocalSentenceTransformer_Text_ComputeNode()
|
|
|
|
|
if local_st_text_compute_node.initial() is not True:
|
|
|
|
|
logger.error("local sentence transformer text embedding node initial failed!")
|
2023-09-25 17:26:06 +08:00
|
|
|
else:
|
2023-09-26 20:25:02 +08:00
|
|
|
ComputeKernel.get_instance().add_compute_node(local_st_text_compute_node)
|
|
|
|
|
|
|
|
|
|
local_st_image_compute_node = LocalSentenceTransformer_Image_ComputeNode()
|
|
|
|
|
if local_st_image_compute_node.initial() is not True:
|
|
|
|
|
logger.error("local sentence transformer image embedding node initial failed!")
|
2023-09-25 17:26:06 +08:00
|
|
|
else:
|
2023-09-26 20:25:02 +08:00
|
|
|
ComputeKernel.get_instance().add_compute_node(local_st_image_compute_node)
|
|
|
|
|
|
2023-09-27 20:32:37 -07:00
|
|
|
|
2023-09-18 23:25:44 -07:00
|
|
|
await ComputeKernel.get_instance().start()
|
2023-09-17 13:16:21 +00:00
|
|
|
|
2023-08-30 12:30:41 -07:00
|
|
|
AIBus().get_default_bus().register_unhandle_message_handler(self._handle_no_target_msg)
|
2023-09-14 01:50:18 -07:00
|
|
|
AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
2023-09-26 01:19:33 -07:00
|
|
|
KnowledgePipline.get_instance().initial()
|
2023-09-15 17:35:12 -07:00
|
|
|
|
|
|
|
|
TelegramTunnel.register_to_loader()
|
2023-09-16 11:41:59 -07:00
|
|
|
EmailTunnel.register_to_loader()
|
2023-09-26 01:19:33 -07:00
|
|
|
user_data_dir = str(AIStorage.get_instance().get_myai_dir())
|
2023-09-18 11:41:16 -07:00
|
|
|
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
2023-09-17 18:18:54 -07:00
|
|
|
tunnel_config = None
|
2023-09-21 15:52:56 +08:00
|
|
|
try:
|
2023-09-17 18:18:54 -07:00
|
|
|
tunnel_config = toml.load(tunnels_config_path)
|
|
|
|
|
if tunnel_config is not None:
|
2023-09-19 15:43:17 -07:00
|
|
|
await AgentTunnel.load_all_tunnels_from_config(tunnel_config)
|
2023-09-17 18:18:54 -07:00
|
|
|
except Exception as e:
|
|
|
|
|
logger.warning(f"load tunnels config from {tunnels_config_path} failed!")
|
2023-09-22 13:38:44 +08:00
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
|
2023-09-22 13:38:44 +08:00
|
|
|
return True
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
|
|
|
|
|
def get_version(self) -> str:
|
2023-09-17 18:18:54 -07:00
|
|
|
return "0.5.1"
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
async def send_msg(self,msg:str,target_id:str,topic:str,sender:str = None) -> str:
|
2023-08-27 18:07:33 -07:00
|
|
|
agent_msg = AgentMsg()
|
|
|
|
|
agent_msg.set(sender,target_id,msg)
|
2023-08-30 23:01:44 -07:00
|
|
|
agent_msg.topic = topic
|
2023-09-14 01:50:18 -07:00
|
|
|
resp = await AIBus.get_default_bus().send_message(agent_msg)
|
2023-08-30 12:30:41 -07:00
|
|
|
if resp is not None:
|
2023-09-26 18:46:26 -07:00
|
|
|
if resp.msg_type != AgentMsgType.TYPE_SYSTEM:
|
|
|
|
|
return resp.body
|
|
|
|
|
else:
|
|
|
|
|
return f"Process Message Error: {resp.body} Please check logs/aios.log for more details!"
|
2023-08-30 12:30:41 -07:00
|
|
|
else:
|
2023-09-26 18:46:26 -07:00
|
|
|
return "System Error: Timeout, no resopnse! Please check logs/aios.log for more details!"
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-09-14 01:50:18 -07:00
|
|
|
async def _user_process_msg(self,msg:AgentMsg) -> AgentMsg:
|
2023-08-27 18:07:33 -07:00
|
|
|
pass
|
2023-09-25 20:57:10 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-09-19 15:43:17 -07:00
|
|
|
async def get_tunnel_config_from_input(self,tunnel_target,tunnel_type):
|
|
|
|
|
tunnel_config = {}
|
|
|
|
|
tunnel_config["tunnel_id"] = f"{tunnel_type}_2_{tunnel_target}"
|
|
|
|
|
tunnel_config["target"] = tunnel_target
|
2023-09-26 18:46:26 -07:00
|
|
|
input_table = {}
|
2023-09-19 15:43:17 -07:00
|
|
|
tunnel_introduce : str = ""
|
|
|
|
|
match tunnel_type:
|
|
|
|
|
case "telegram":
|
|
|
|
|
tunnel_config["type"] = "TelegramTunnel"
|
2023-09-26 18:46:26 -07:00
|
|
|
input_table["token"] = UserConfigItem("telegram bot token")
|
|
|
|
|
input_table["allow"] = UserConfigItem("allow group (default is member,you can choose contact or guest)")
|
2023-09-19 15:43:17 -07:00
|
|
|
case "email":
|
|
|
|
|
tunnel_config["type"] = "EmailTunnel"
|
|
|
|
|
case _:
|
2023-09-21 15:52:56 +08:00
|
|
|
error_text = FormattedText([("class:error", f"tunnel type {tunnel_type}not support!")])
|
2023-09-19 15:43:17 -07:00
|
|
|
print_formatted_text(error_text,style=shell_style)
|
|
|
|
|
return None
|
|
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
intro_text = FormattedText([("class:prompt", tunnel_introduce)])
|
2023-09-19 15:43:17 -07:00
|
|
|
print_formatted_text(intro_text,style=shell_style)
|
2023-09-26 18:46:26 -07:00
|
|
|
for key,item in input_table.items():
|
2023-09-19 15:43:17 -07:00
|
|
|
user_input = await try_get_input(f"{key} : {item.desc}")
|
|
|
|
|
if user_input is None:
|
|
|
|
|
return None
|
|
|
|
|
|
2023-09-22 13:38:44 +08:00
|
|
|
tunnel_config[key] = user_input
|
|
|
|
|
|
|
|
|
|
return tunnel_config
|
2023-09-19 15:43:17 -07:00
|
|
|
|
|
|
|
|
async def append_tunnel_config(self,tunnel_config):
|
|
|
|
|
user_data_dir = AIStorage.get_instance().get_myai_dir()
|
|
|
|
|
tunnels_config_path = os.path.abspath(f"{user_data_dir}/etc/tunnels.cfg.toml")
|
2023-09-21 15:52:56 +08:00
|
|
|
try:
|
2023-09-19 15:43:17 -07:00
|
|
|
all_tunnels = toml.load(tunnels_config_path)
|
|
|
|
|
if all_tunnels is not None:
|
|
|
|
|
all_tunnels[tunnel_config["tunnel_id"]] = tunnel_config
|
|
|
|
|
f = open(tunnels_config_path,"w")
|
|
|
|
|
if f:
|
|
|
|
|
toml.dump(all_tunnels,f)
|
|
|
|
|
except Exception as e:
|
2023-09-26 18:46:26 -07:00
|
|
|
logger.warning(f"load tunnels config from {tunnels_config_path} failed! {e}")
|
2023-09-19 15:43:17 -07:00
|
|
|
|
2023-09-25 20:57:10 -07:00
|
|
|
async def handle_contact_commands(self,args):
|
|
|
|
|
cm = ContactManager.get_instance()
|
|
|
|
|
if len(args) < 1:
|
|
|
|
|
return FormattedText([("class:error", f'/contact $contact_name, Like /contact "Jim Green"')])
|
|
|
|
|
contact_name = args[0]
|
|
|
|
|
contact = cm.find_contact_by_name(contact_name)
|
|
|
|
|
is_update = False
|
|
|
|
|
if contact is not None:
|
|
|
|
|
#show old info and ask user to update or remove
|
|
|
|
|
is_update = True
|
|
|
|
|
op_str = await try_get_input(f"Contact {contact_name} already exist, update or remove? (u/r)")
|
|
|
|
|
if op_str is None:
|
|
|
|
|
return None
|
|
|
|
|
if op_str == "r":
|
|
|
|
|
cm.remove_contact(contact_name)
|
|
|
|
|
return FormattedText([("class:title", f"remove {contact_name} success!")])
|
|
|
|
|
else:
|
|
|
|
|
print(f"old info: {contact}")
|
|
|
|
|
else:
|
|
|
|
|
contact = Contact(contact_name)
|
|
|
|
|
|
|
|
|
|
contact.is_family_member = False
|
|
|
|
|
is_family_member = await try_get_input(f"Is {contact_name} your family member? (y/n)")
|
|
|
|
|
if is_family_member is not None:
|
|
|
|
|
if is_family_member == "y" or is_family_member == "Y":
|
|
|
|
|
contact.is_family_member = True
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
contact_telegram = await try_get_input(f"Input {contact_name}'s telegram username:")
|
|
|
|
|
if contact_telegram is None:
|
|
|
|
|
return None
|
|
|
|
|
contact.telegram = contact_telegram
|
|
|
|
|
|
|
|
|
|
contact_email = await try_get_input(f"Input {contact_name}'s email:")
|
|
|
|
|
if contact_email is None:
|
|
|
|
|
return None
|
|
|
|
|
contact.email = contact_email
|
|
|
|
|
|
|
|
|
|
contact_phone = await try_get_input(f"Input {contact_name}'s phone (optional):")
|
|
|
|
|
if contact_phone is not None:
|
|
|
|
|
contact.phone = contact_phone
|
|
|
|
|
|
|
|
|
|
contact_note = await try_get_input(f"Input {contact_name}'s note (optional):")
|
|
|
|
|
if contact_note is not None:
|
|
|
|
|
contact.note = contact_note
|
|
|
|
|
|
|
|
|
|
contact.added_by = self.username
|
|
|
|
|
if is_update:
|
|
|
|
|
cm.set_contact(contact_name,contact)
|
|
|
|
|
else:
|
|
|
|
|
cm.add_contact(contact_name,contact)
|
|
|
|
|
|
2023-09-21 18:32:17 +08:00
|
|
|
async def handle_knowledge_commands(self, args):
|
|
|
|
|
show_text = FormattedText([("class:title", "sub command not support!\n"
|
2023-09-27 20:32:37 -07:00
|
|
|
"/knowledge add email | dir\n"
|
2023-09-28 11:05:24 +08:00
|
|
|
"/knowledge journal [$topn]\n")])
|
2023-09-21 18:32:17 +08:00
|
|
|
if len(args) < 1:
|
|
|
|
|
return show_text
|
|
|
|
|
sub_cmd = args[0]
|
|
|
|
|
if sub_cmd == "add":
|
|
|
|
|
if len(args) < 2:
|
|
|
|
|
return show_text
|
|
|
|
|
if args[1] == "email":
|
|
|
|
|
config = dict()
|
|
|
|
|
for key, item in KnowledgeEmailSource.user_config_items():
|
|
|
|
|
user_input = await try_get_input(f"{key} : {item}")
|
|
|
|
|
if user_input is None:
|
|
|
|
|
return show_text
|
|
|
|
|
config[key] = user_input
|
|
|
|
|
error = KnowledgePipline.get_instance().add_email_source(KnowledgeEmailSource(config))
|
|
|
|
|
if error is not None:
|
|
|
|
|
return FormattedText([("class:title", f"/knowledge add email failed {error}\n")])
|
|
|
|
|
else:
|
2023-09-25 20:57:10 -07:00
|
|
|
KnowledgePipline.get_instance().save_cosnfig()
|
2023-09-21 18:32:17 +08:00
|
|
|
if args[1] == "dir":
|
|
|
|
|
config = dict()
|
|
|
|
|
for key, item in KnowledgeDirSource.user_config_items():
|
|
|
|
|
user_input = await try_get_input(f"{key} : {item}")
|
|
|
|
|
if user_input is None:
|
|
|
|
|
return show_text
|
|
|
|
|
config[key] = user_input
|
|
|
|
|
error = KnowledgePipline.get_instance().add_dir_source(KnowledgeDirSource(config))
|
|
|
|
|
if error is not None:
|
|
|
|
|
return FormattedText([("class:title", f"/knowledge add dir failed {error}\n")])
|
|
|
|
|
else:
|
|
|
|
|
KnowledgePipline.get_instance().save_config()
|
|
|
|
|
else:
|
|
|
|
|
return show_text
|
|
|
|
|
if sub_cmd == "journal":
|
|
|
|
|
topn = 10 if len(args) == 1 else int(args[1])
|
|
|
|
|
journals = [str(journal) for journal in KnowledgePipline.get_instance().get_latest_journals(topn)]
|
|
|
|
|
print_formatted_text("\r\n".join(journals))
|
2023-09-22 13:38:44 +08:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
async def call_func(self,func_name, args):
|
|
|
|
|
match func_name:
|
|
|
|
|
case 'send':
|
2023-09-26 18:46:26 -07:00
|
|
|
show_text = FormattedText([("class:error", f'send args error,/send Tracy "Hello! It is a good day!" default')])
|
|
|
|
|
if len(args) == 3:
|
|
|
|
|
target_id = args[0]
|
|
|
|
|
msg_content = args[1]
|
|
|
|
|
topic = args[2]
|
|
|
|
|
resp = await self.send_msg(msg_content,target_id,topic,self.username)
|
|
|
|
|
show_text = FormattedText([("class:title", f"{self.current_topic}@{self.current_target} >>> "),
|
|
|
|
|
("class:content", resp)])
|
2023-08-30 23:01:44 -07:00
|
|
|
return show_text
|
2023-09-18 00:40:37 -07:00
|
|
|
case 'set_config':
|
2023-09-26 18:46:26 -07:00
|
|
|
show_text = FormattedText([("class:error", f"set config args error,/set_config $config_item! ")])
|
2023-09-18 00:40:37 -07:00
|
|
|
if len(args) == 1:
|
|
|
|
|
key = args[0]
|
2023-09-20 16:17:06 +08:00
|
|
|
config_item = AIStorage.get_instance().get_user_config().get_config_item(key)
|
2023-09-20 08:45:53 +00:00
|
|
|
old_value = AIStorage.get_instance().get_user_config().get_value(key)
|
2023-09-22 13:38:44 +08:00
|
|
|
|
2023-09-18 00:40:37 -07:00
|
|
|
if config_item is not None:
|
2023-09-20 08:45:53 +00:00
|
|
|
value = await session.prompt_async(f"{key} : {config_item.desc} \nCurrent : {old_value}\nPlease input new value:",style=shell_style)
|
|
|
|
|
AIStorage.get_instance().get_user_config().set_value(key,value)
|
|
|
|
|
await AIStorage.get_instance().get_user_config().save_to_user_config()
|
|
|
|
|
show_text = FormattedText([("class:title", f"set {key} to {value} success!")])
|
2023-09-26 18:46:26 -07:00
|
|
|
else:
|
|
|
|
|
show_text = FormattedText([("class:error", f"set config failed! config item {key} not found!")])
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-18 00:40:37 -07:00
|
|
|
return show_text
|
2023-09-19 15:43:17 -07:00
|
|
|
case 'connect':
|
2023-09-26 18:46:26 -07:00
|
|
|
show_text = FormattedText([("class:error", "args error, /connect $target")])
|
2023-09-19 15:43:17 -07:00
|
|
|
if len(args) < 1:
|
|
|
|
|
return show_text
|
|
|
|
|
tunnel_target = args[0]
|
|
|
|
|
if len(args) < 2:
|
|
|
|
|
tunnel_type = "telegram"
|
|
|
|
|
else:
|
|
|
|
|
tunnel_type = args[1]
|
2023-09-18 00:40:37 -07:00
|
|
|
|
2023-09-19 15:43:17 -07:00
|
|
|
tunnel_config = await self.get_tunnel_config_from_input(tunnel_target,tunnel_type)
|
|
|
|
|
if tunnel_config:
|
|
|
|
|
if await AgentTunnel.load_tunnel_from_config(tunnel_config):
|
|
|
|
|
# append
|
|
|
|
|
await self.append_tunnel_config(tunnel_config)
|
|
|
|
|
show_text = FormattedText([("class:title", f"connect to {tunnel_target} success!")])
|
2023-09-18 00:40:37 -07:00
|
|
|
|
2023-09-19 15:43:17 -07:00
|
|
|
return show_text
|
2023-09-21 18:32:17 +08:00
|
|
|
case 'knowledge':
|
|
|
|
|
return await self.handle_knowledge_commands(args)
|
2023-09-25 20:57:10 -07:00
|
|
|
case 'contact':
|
|
|
|
|
return await self.handle_contact_commands(args)
|
2023-08-30 23:01:44 -07:00
|
|
|
case 'open':
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
target_id = args[0]
|
2023-09-25 20:57:10 -07:00
|
|
|
else:
|
|
|
|
|
show_text = FormattedText([("class:error", "/open Need Target Agent/Workflow ID! like /open Jarvis default")])
|
|
|
|
|
return show_text
|
|
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
if len(args) >= 2:
|
|
|
|
|
topic = args[1]
|
2023-09-25 20:57:10 -07:00
|
|
|
else:
|
|
|
|
|
topic = "default"
|
2023-08-30 23:01:44 -07:00
|
|
|
|
|
|
|
|
self.current_target = target_id
|
|
|
|
|
self.current_topic = topic
|
|
|
|
|
show_text = FormattedText([("class:title", f"current session switch to {topic}@{target_id}")])
|
2023-09-19 00:53:13 -07:00
|
|
|
AIStorage.get_instance().get_user_config().set_value("shell.current",f"{self.current_topic}@{self.current_target}")
|
|
|
|
|
await AIStorage.get_instance().get_user_config().save_to_user_config()
|
2023-08-30 23:01:44 -07:00
|
|
|
return show_text
|
2023-09-26 01:19:33 -07:00
|
|
|
case 'enable':
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
feature = args[0]
|
|
|
|
|
else:
|
|
|
|
|
show_text = FormattedText([("class:error", "/enable Need Feature Name! like /enable llama")])
|
|
|
|
|
return show_text
|
|
|
|
|
|
|
|
|
|
if await AIStorage.get_instance().is_feature_enable(feature):
|
|
|
|
|
show_text = FormattedText([("class:title", f"Feature {feature} already enabled!")])
|
|
|
|
|
return show_text
|
|
|
|
|
|
|
|
|
|
AIStorage.get_instance().enable_feature(feature)
|
|
|
|
|
show_text = FormattedText([("class:title", f"Feature {feature} enabled!")])
|
|
|
|
|
return show_text
|
|
|
|
|
case 'disable':
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
feature = args[0]
|
|
|
|
|
else:
|
|
|
|
|
show_text = FormattedText([("class:error", "/disable Need Feature Name! like /disable llama")])
|
|
|
|
|
return show_text
|
|
|
|
|
|
|
|
|
|
if not await AIStorage.get_instance().is_feature_enable(feature):
|
|
|
|
|
show_text = FormattedText([("class:title", f"Feature {feature} already disabled!")])
|
|
|
|
|
return show_text
|
|
|
|
|
|
|
|
|
|
AIStorage.get_instance().disable_feature(feature)
|
|
|
|
|
show_text = FormattedText([("class:title", f"Feature {feature} disabled!")])
|
|
|
|
|
return show_text
|
2023-09-26 18:46:26 -07:00
|
|
|
#case 'login':
|
|
|
|
|
# if len(args) >= 1:
|
|
|
|
|
# self.username = args[0]
|
|
|
|
|
# AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-26 18:46:26 -07:00
|
|
|
# return self.username + " login success!"
|
2023-08-30 23:01:44 -07:00
|
|
|
case 'history':
|
|
|
|
|
num = 10
|
|
|
|
|
offset = 0
|
2023-09-01 00:39:36 -07:00
|
|
|
if args is not None:
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
num = args[0]
|
|
|
|
|
if len(args) >= 2:
|
|
|
|
|
offset = args[1]
|
2023-08-30 23:01:44 -07:00
|
|
|
|
|
|
|
|
db_path = ""
|
|
|
|
|
if await self.is_agent(self.current_target):
|
2023-09-16 11:41:59 -07:00
|
|
|
db_path = AgentManager.get_instance().db_path
|
2023-08-30 23:01:44 -07:00
|
|
|
else:
|
2023-09-16 11:41:59 -07:00
|
|
|
db_path = WorkflowManager.get_instance().db_file
|
2023-08-30 23:01:44 -07:00
|
|
|
chatsession:AIChatSession = AIChatSession.get_session(self.current_target,f"{self.username}#{self.current_topic}",db_path,False)
|
|
|
|
|
if chatsession is not None:
|
|
|
|
|
msgs = chatsession.read_history(num,offset)
|
|
|
|
|
format_texts = []
|
2023-09-14 01:50:18 -07:00
|
|
|
for msg in msgs:
|
2023-08-30 23:01:44 -07:00
|
|
|
format_texts.append(("class:content",f"{msg.sender} >>> {msg.body}"))
|
|
|
|
|
format_texts.append(("",f"\n-------------------\n"))
|
|
|
|
|
return FormattedText(format_texts)
|
|
|
|
|
return FormattedText([("class:title", f"chatsession not found")])
|
|
|
|
|
case 'exit':
|
|
|
|
|
os._exit(0)
|
|
|
|
|
case 'help':
|
|
|
|
|
return FormattedText([("class:title", f"help~~~")])
|
2023-08-27 18:07:33 -07:00
|
|
|
|
|
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
##########################################################################################################################
|
2023-09-17 18:18:54 -07:00
|
|
|
history = FileHistory('aios_shell_history.txt')
|
2023-09-21 15:52:56 +08:00
|
|
|
session = PromptSession(history=history)
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-09-01 00:39:36 -07:00
|
|
|
def parse_function_call(func_string):
|
2023-09-18 00:40:37 -07:00
|
|
|
if len(func_string) > 2:
|
|
|
|
|
if func_string[0] == '/' and func_string[1] != '/':
|
|
|
|
|
str_list = shlex.split(func_string[1:])
|
|
|
|
|
func_name = str_list[0]
|
|
|
|
|
params = str_list[1:]
|
|
|
|
|
return func_name, params
|
|
|
|
|
else:
|
2023-08-30 23:01:44 -07:00
|
|
|
return None
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-26 18:46:26 -07:00
|
|
|
async def try_get_input(desc:str,mutil_line:bool = False,check_func:callable = None) -> str:
|
2023-09-19 15:43:17 -07:00
|
|
|
user_input = await session.prompt_async(f"{desc} \nType /exit to abort. \nPlease input:",style=shell_style)
|
|
|
|
|
err_str = ""
|
|
|
|
|
if check_func is None:
|
|
|
|
|
if len(user_input) > 0:
|
|
|
|
|
if user_input != "/exit":
|
2023-09-26 18:46:26 -07:00
|
|
|
if mutil_line is False:
|
|
|
|
|
user_input = user_input.strip()
|
2023-09-19 15:43:17 -07:00
|
|
|
return user_input
|
|
|
|
|
else:
|
|
|
|
|
return None
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-19 15:43:17 -07:00
|
|
|
else:
|
|
|
|
|
is_ok,err_str = check_func(user_input)
|
|
|
|
|
if is_ok:
|
|
|
|
|
return user_input
|
2023-09-21 15:52:56 +08:00
|
|
|
|
|
|
|
|
error_text = FormattedText([("class:error", err_str)])
|
2023-09-19 15:43:17 -07:00
|
|
|
print_formatted_text(error_text,style=shell_style)
|
|
|
|
|
return await try_get_input(desc,check_func)
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
async def get_user_config_from_input(check_result:dict) -> bool:
|
|
|
|
|
for key,item in check_result.items():
|
2023-09-19 15:43:17 -07:00
|
|
|
user_input = await try_get_input(f"System config {key} ({item.desc}) not define!")
|
2023-09-25 20:57:10 -07:00
|
|
|
if user_input is None:
|
|
|
|
|
if item.is_optional:
|
|
|
|
|
continue
|
|
|
|
|
else:
|
|
|
|
|
True
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
if len(user_input) > 0:
|
2023-09-19 00:53:13 -07:00
|
|
|
AIStorage.get_instance().get_user_config().set_value(key,user_input)
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-19 00:53:13 -07:00
|
|
|
await AIStorage.get_instance().get_user_config().save_to_user_config()
|
2023-09-17 18:18:54 -07:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
async def main_daemon_loop(shell:AIOS_Shell):
|
|
|
|
|
while shell.is_working:
|
|
|
|
|
await asyncio.sleep(1)
|
|
|
|
|
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def print_welcome_screen():
|
2023-09-21 15:52:56 +08:00
|
|
|
print("\033[1;31m")
|
2023-09-17 18:18:54 -07:00
|
|
|
logo = """
|
2023-09-19 15:43:17 -07:00
|
|
|
\t _______ ____________________ __
|
|
|
|
|
\t __ __ \______________________ __ \__ |__ | / /
|
|
|
|
|
\t _ / / /__ __ \ _ \_ __ \_ / / /_ /| |_ |/ /
|
|
|
|
|
\t / /_/ /__ /_/ / __/ / / / /_/ /_ ___ | /| /
|
|
|
|
|
\t \____/ _ .___/\___//_/ /_//_____/ /_/ |_/_/ |_/
|
|
|
|
|
\t /_/
|
2023-09-17 18:18:54 -07:00
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
print(logo)
|
2023-09-21 15:52:56 +08:00
|
|
|
print("\033[0m")
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
print("\033[1;32m \t\tWelcome to OpenDAN - Your Personal AI OS\033[0m\n")
|
2023-09-18 00:40:37 -07:00
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
introduce = """
|
2023-09-27 11:40:46 -07:00
|
|
|
\tOpenDAN (Open and Do Anything Now with AI) is revolutionizing the
|
|
|
|
|
\tAI landscape with its Personal AI Operating System. Designed for
|
|
|
|
|
\tseamless integration of diverse AI modules, it ensures unmatched
|
|
|
|
|
\tinteroperability. OpenDAN empowers users to craft powerful AI agents:
|
|
|
|
|
\tfrom butlers and assistants to personal tutors and digital companions.
|
|
|
|
|
\tAll while retaining control. These agents can team up to tackle complex
|
|
|
|
|
\tchallenges, integrate with existing services, and command IoT devices.
|
|
|
|
|
\t
|
|
|
|
|
\tWith OpenDAN, we're putting AI in your hands, making life simpler and smarter.
|
|
|
|
|
\t
|
|
|
|
|
\t================ AIOS Shell Handbook ================
|
|
|
|
|
|
|
|
|
|
\033[1;94m\tUnderstand the Shell Prompt :\033[0m [current_username]<->[current_topic]@[current_target]$
|
|
|
|
|
\033[1;94m\tTalk with Agent/Workflow :\033[0m Directly input and wait.
|
|
|
|
|
\033[1;94m\tTalk with another Agent/Workflow :\033[0m /open $target_name [$topic_name]
|
|
|
|
|
\033[1;94m\tInstall new Agent/Workflow :\033[0m /install $agent_name (Not support at 0.5.1)
|
|
|
|
|
\t\t(For Developer) Download and unzip Agent to ~/myai/agents or ~/myai/workflows
|
|
|
|
|
\033[1;94m\tView chat History :\033[0m /history
|
|
|
|
|
\033[1;94m\tChange AIOS Owner's telegram username :\033[0m /set_config telegram
|
|
|
|
|
\033[1;94m\tChange OpenAI API Token :\033[0m /set_config $openai_api_key
|
|
|
|
|
\033[1;94m\tGive your Agent a Telegram account :\033[0m /connect $agent_name
|
|
|
|
|
\033[1;94m\tAdd personal files to the AI Knowledge Base. \033[0m
|
|
|
|
|
\t\t1) Copy your file to ~/myai/data
|
2023-09-27 20:32:37 -07:00
|
|
|
\t\t2) /knowlege add $dir
|
2023-09-27 11:40:46 -07:00
|
|
|
\033[1;94m\tSearch your knowledge base :\033[0m /open Mia
|
|
|
|
|
\033[1;94m\tCheck the progress of AI reading personal data :\033[0m /knowledge journal
|
|
|
|
|
\033[1;94m\tOpen AI Bash (For Developer Only):\033[0m /open ai_bash
|
|
|
|
|
\033[1;94m\tEnable AIGC Feature :\033[0m /enable aigc
|
|
|
|
|
\033[1;94m\tEnable llama (Local LLM Kernel) :\033[0m /enable llama
|
2023-09-21 15:52:56 +08:00
|
|
|
"""
|
2023-09-17 18:18:54 -07:00
|
|
|
print(introduce)
|
|
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
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 \tGithub\t: https://github.com/fiatrete/OpenDAN-Personal-AI-OS\033[0m")
|
2023-09-17 18:18:54 -07:00
|
|
|
print("\033[1;33m \tWebsite\t: https://www.opendan.ai\033[0m")
|
|
|
|
|
print("\n\n")
|
|
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
async def main():
|
2023-09-17 18:18:54 -07:00
|
|
|
print_welcome_screen()
|
2023-09-18 00:40:37 -07:00
|
|
|
print("Booting...")
|
2023-09-21 15:52:56 +08:00
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
if os.path.isdir(f"{directory}/../../../rootfs"):
|
|
|
|
|
AIStorage.get_instance().is_dev_mode = True
|
|
|
|
|
else:
|
2023-09-21 15:52:56 +08:00
|
|
|
AIStorage.get_instance().is_dev_mode = False
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-26 01:19:33 -07:00
|
|
|
|
|
|
|
|
if AIStorage.get_instance().is_dev_mode:
|
|
|
|
|
logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8',force=True,
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s')
|
|
|
|
|
else:
|
2023-09-26 18:46:26 -07:00
|
|
|
dir_path = f"{AIStorage.get_instance().get_myai_dir()}/logs"
|
|
|
|
|
if not os.path.exists(dir_path):
|
|
|
|
|
os.makedirs(dir_path)
|
|
|
|
|
log_file = f"{AIStorage.get_instance().get_myai_dir()}/logs/aios.log"
|
2023-09-26 01:19:33 -07:00
|
|
|
handler = RotatingFileHandler(log_file, maxBytes=50*1024*1024, backupCount=100)
|
|
|
|
|
|
|
|
|
|
logging.basicConfig(handlers=[handler],
|
|
|
|
|
level=logging.INFO,
|
|
|
|
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
is_daemon = False
|
2023-09-26 22:50:50 -07:00
|
|
|
logger.info(f"Check Host OS :{os.name}")
|
2023-09-17 18:18:54 -07:00
|
|
|
if os.name != 'nt':
|
2023-09-26 22:50:50 -07:00
|
|
|
is_daemon = os.fstat(0) != os.fstat(1) or os.fstat(0) != os.fstat(2)
|
2023-09-17 18:18:54 -07:00
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
shell = AIOS_Shell("user")
|
|
|
|
|
shell.declare_all_user_config()
|
2023-09-17 18:18:54 -07:00
|
|
|
await AIStorage.get_instance().initial()
|
2023-09-19 00:53:13 -07:00
|
|
|
check_result = AIStorage.get_instance().get_user_config().check_config()
|
2023-09-17 18:18:54 -07:00
|
|
|
if check_result is not None:
|
|
|
|
|
if is_daemon:
|
|
|
|
|
logger.error(check_result)
|
|
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
#Remind users to enter necessary configurations.
|
|
|
|
|
if await get_user_config_from_input(check_result) is False:
|
|
|
|
|
return 1
|
2023-09-26 18:46:26 -07:00
|
|
|
shell.username = AIStorage.get_instance().get_user_config().get_value("username")
|
2023-09-17 18:18:54 -07:00
|
|
|
init_result = await shell.initial()
|
2023-09-26 18:46:26 -07:00
|
|
|
proxy.apply_storage()
|
|
|
|
|
|
2023-09-17 18:18:54 -07:00
|
|
|
if init_result is False:
|
|
|
|
|
if is_daemon:
|
|
|
|
|
logger.error("aios shell initial failed!")
|
|
|
|
|
return 1
|
|
|
|
|
else:
|
|
|
|
|
print("aios shell initial failed!")
|
2023-09-26 01:19:33 -07:00
|
|
|
return 1
|
2023-09-14 01:50:18 -07:00
|
|
|
|
2023-09-26 18:46:26 -07:00
|
|
|
print(f"aios shell {shell.get_version()} ready. Daemon:{is_daemon}")
|
|
|
|
|
logger.info(f"aios shell {shell.get_version()} ready. Daemon:{is_daemon}")
|
2023-09-17 18:18:54 -07:00
|
|
|
if is_daemon:
|
|
|
|
|
return await main_daemon_loop(shell)
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
completer = WordCompleter(['/send $target $msg $topic',
|
|
|
|
|
'/open $target $topic',
|
2023-09-18 00:40:37 -07:00
|
|
|
'/history $num $offset',
|
|
|
|
|
'/connect $target',
|
2023-09-25 20:57:10 -07:00
|
|
|
'/contact $name',
|
2023-09-27 20:32:37 -07:00
|
|
|
'/knowledge add email | dir',
|
2023-09-28 11:05:24 +08:00
|
|
|
'/knowledge journal [$topn]',
|
2023-09-18 00:40:37 -07:00
|
|
|
'/set_config $key',
|
2023-09-26 01:19:33 -07:00
|
|
|
'/enable $feature',
|
|
|
|
|
'/disable $feature',
|
2023-09-18 00:40:37 -07:00
|
|
|
'/list_config',
|
|
|
|
|
'/show',
|
2023-09-21 15:52:56 +08:00
|
|
|
'/exit',
|
2023-09-18 00:40:37 -07:00
|
|
|
'/help'], ignore_case=True)
|
2023-09-19 00:53:13 -07:00
|
|
|
|
|
|
|
|
current = AIStorage.get_instance().get_user_config().get_value("shell.current")
|
|
|
|
|
current = current.split("@")
|
|
|
|
|
shell.current_target = current[1]
|
|
|
|
|
shell.current_topic = current[0]
|
|
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
await asyncio.sleep(0.2)
|
2023-08-27 18:07:33 -07:00
|
|
|
while True:
|
2023-09-20 02:23:46 -07:00
|
|
|
user_input = await session.prompt_async(f"{shell.username}<->{shell.current_topic}@{shell.current_target}$ ",completer=completer,style=shell_style)
|
2023-08-30 23:01:44 -07:00
|
|
|
if len(user_input) <= 1:
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
func_call = parse_function_call(user_input)
|
|
|
|
|
show_text = None
|
|
|
|
|
if func_call:
|
|
|
|
|
show_text = await shell.call_func(func_call[0], func_call[1])
|
|
|
|
|
else:
|
|
|
|
|
resp = await shell.send_msg(user_input,shell.current_target,shell.current_topic,shell.username)
|
|
|
|
|
show_text = FormattedText([
|
|
|
|
|
("class:title", f"{shell.current_topic}@{shell.current_target} >>> "),
|
|
|
|
|
("class:content", resp)
|
|
|
|
|
])
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
print_formatted_text(show_text,style=shell_style)
|
|
|
|
|
#print_formatted_text(f"{shell.username}<->{shell.current_topic}@{shell.current_target} >>> {resp}",style=shell_style)
|
|
|
|
|
|
2023-09-19 18:25:25 -07:00
|
|
|
|
2023-09-21 15:52:56 +08:00
|
|
|
if __name__ == "__main__":
|
2023-08-27 18:07:33 -07:00
|
|
|
asyncio.run(main())
|
|
|
|
|
|