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-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-09-16 11:41:59 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
directory = os.path.dirname(__file__)
|
|
|
|
|
sys.path.append(directory + '/../../')
|
2023-09-16 11:41:59 -07:00
|
|
|
from aios_kernel import Workflow,AIAgent,AgentMsg,AgentMsgStatus,ComputeKernel,OpenAI_ComputeNode,AIBus,AIChatSession,AgentTunnel,TelegramTunnel,CalenderEnvironment,Environment,EmailTunnel
|
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-16 11:41:59 -07:00
|
|
|
shell_style = Style.from_dict({
|
|
|
|
|
'title': '#87d7ff bold', #RGB
|
|
|
|
|
'content': '#007f00 bold',
|
|
|
|
|
'prompt': '#00FF00',
|
|
|
|
|
})
|
|
|
|
|
|
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-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-10 20:50:37 -07:00
|
|
|
agent.owner_env = Environment.get_env_by_id("calender")
|
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-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
|
|
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
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-04 22:36:59 -07:00
|
|
|
cal_env = CalenderEnvironment("calender")
|
|
|
|
|
cal_env.start()
|
|
|
|
|
Environment.set_env_by_id("calender",cal_env)
|
|
|
|
|
|
2023-09-16 11:41:59 -07:00
|
|
|
AgentManager.get_instance().initial(os.path.abspath(directory + "/../../../rootfs/"))
|
|
|
|
|
WorkflowManager.get_instance().initial(os.path.abspath(directory + "/../../../rootfs/workflows/"))
|
|
|
|
|
open_ai_node = OpenAI_ComputeNode.get_instance()
|
2023-08-27 18:07:33 -07:00
|
|
|
open_ai_node.start()
|
2023-09-16 11:41:59 -07:00
|
|
|
ComputeKernel.get_instance().add_compute_node(open_ai_node)
|
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-15 17:35:12 -07:00
|
|
|
|
|
|
|
|
TelegramTunnel.register_to_loader()
|
2023-09-16 11:41:59 -07:00
|
|
|
EmailTunnel.register_to_loader()
|
2023-09-15 17:35:12 -07:00
|
|
|
|
|
|
|
|
tunnels_config_path = os.path.abspath(directory + "/../../../rootfs/tunnels.cfg.toml")
|
|
|
|
|
tunnel_config = toml.load(tunnels_config_path)
|
|
|
|
|
await AgentTunnel.load_all_tunnels_from_config(tunnel_config["tunnels"])
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_version(self) -> str:
|
|
|
|
|
return "0.0.1"
|
|
|
|
|
|
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:
|
|
|
|
|
return resp.body
|
|
|
|
|
else:
|
|
|
|
|
return "error!"
|
2023-08-27 18:07:33 -07:00
|
|
|
|
|
|
|
|
async def install_workflow(self,workflow_id:Workflow) -> None:
|
|
|
|
|
pass
|
2023-09-14 01:50:18 -07:00
|
|
|
|
|
|
|
|
async def _user_process_msg(self,msg:AgentMsg) -> AgentMsg:
|
|
|
|
|
pass
|
2023-08-27 18:07:33 -07:00
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
async def call_func(self,func_name, args):
|
|
|
|
|
match func_name:
|
|
|
|
|
case 'send':
|
|
|
|
|
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)])
|
|
|
|
|
return show_text
|
|
|
|
|
case 'open':
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
target_id = args[0]
|
|
|
|
|
if len(args) >= 2:
|
|
|
|
|
topic = args[1]
|
|
|
|
|
|
|
|
|
|
self.current_target = target_id
|
|
|
|
|
self.current_topic = topic
|
|
|
|
|
show_text = FormattedText([("class:title", f"current session switch to {topic}@{target_id}")])
|
|
|
|
|
return show_text
|
2023-09-01 12:05:03 -07:00
|
|
|
case 'login':
|
|
|
|
|
if len(args) >= 1:
|
|
|
|
|
self.username = args[0]
|
2023-09-14 01:50:18 -07:00
|
|
|
AIBus().get_default_bus().register_message_handler(self.username,self._user_process_msg)
|
2023-09-01 12:05:03 -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-08-30 23:01:44 -07:00
|
|
|
#######################################################################################
|
2023-08-30 12:30:41 -07:00
|
|
|
history = FileHistory('history.txt')
|
|
|
|
|
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):
|
|
|
|
|
match = re.search(r'\s*(\w+)\s*\(\s*(.*)\s*\)\s*', func_string)
|
|
|
|
|
if not match:
|
2023-08-30 23:01:44 -07:00
|
|
|
return None
|
2023-09-01 00:39:36 -07:00
|
|
|
|
|
|
|
|
func_name = match.group(1)
|
|
|
|
|
params_string = match.group(2).strip()
|
|
|
|
|
params = re.split(r'\s*,\s*(?=(?:[^"]*"[^"]*")*[^"]*$)', params_string)
|
|
|
|
|
params = [param.strip('"') for param in params]
|
|
|
|
|
if len(params[0]) == 0:
|
|
|
|
|
params = None
|
|
|
|
|
|
|
|
|
|
return func_name, params
|
2023-08-30 23:01:44 -07:00
|
|
|
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
async def main():
|
|
|
|
|
print("aios shell prepareing...")
|
2023-09-01 12:05:03 -07:00
|
|
|
logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8',force=True,
|
2023-09-01 00:39:36 -07:00
|
|
|
level=logging.INFO,
|
|
|
|
|
format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s')
|
2023-08-27 18:07:33 -07:00
|
|
|
shell = AIOS_Shell("user")
|
|
|
|
|
await shell.initial()
|
2023-09-14 01:50:18 -07:00
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
print(f"aios shell {shell.get_version()} ready.")
|
|
|
|
|
|
2023-08-30 23:01:44 -07:00
|
|
|
completer = WordCompleter(['send($target,$msg,$topic)',
|
|
|
|
|
'open($target,$topic)',
|
|
|
|
|
'history($num,$offset)',
|
2023-09-01 12:05:03 -07:00
|
|
|
'login($username)'
|
2023-08-30 23:01:44 -07:00
|
|
|
'show()',
|
|
|
|
|
'exit()',
|
|
|
|
|
'help()'], ignore_case=True)
|
|
|
|
|
|
2023-08-27 18:07:33 -07:00
|
|
|
while True:
|
2023-08-30 23:01:44 -07:00
|
|
|
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:
|
|
|
|
|
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-08-27 18:07:33 -07:00
|
|
|
|
2023-08-30 12:30:41 -07:00
|
|
|
if __name__ == "__main__":
|
2023-08-27 18:07:33 -07:00
|
|
|
asyncio.run(main())
|
|
|
|
|
|