Refactor: decouple task queues, add JS injection support, and simplify stapp rendering
This commit is contained in:
15
agentmain.py
15
agentmain.py
@@ -61,16 +61,15 @@ class GeneraticAgent:
|
|||||||
self.handler.code_stop_signal.append(1)
|
self.handler.code_stop_signal.append(1)
|
||||||
|
|
||||||
def put_task(self, query, source="user"):
|
def put_task(self, query, source="user"):
|
||||||
while self.display_queue.qsize() > 0:
|
display_queue = queue.Queue()
|
||||||
try: self.display_queue.get_nowait()
|
self.task_queue.put({"query": query, "source": source, "output": display_queue})
|
||||||
except queue.Empty: break
|
return display_queue
|
||||||
self.task_queue.put({"query": query, "source": source})
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
task = self.task_queue.get()
|
task = self.task_queue.get()
|
||||||
self.is_running = True
|
self.is_running = True
|
||||||
raw_query, source = task["query"], task["source"]
|
raw_query, source, display_queue = task["query"], task["source"], task["output"]
|
||||||
self.current_source = source
|
self.current_source = source
|
||||||
self.last_active_time = time.time()
|
self.last_active_time = time.time()
|
||||||
|
|
||||||
@@ -90,15 +89,15 @@ class GeneraticAgent:
|
|||||||
if self.stop_sig: break
|
if self.stop_sig: break
|
||||||
full_response += chunk
|
full_response += chunk
|
||||||
if len(full_response) - last_pos > 50:
|
if len(full_response) - last_pos > 50:
|
||||||
self.display_queue.put({'next': f'{full_response}', 'source': source})
|
display_queue.put({'next': f'{full_response}', 'source': source})
|
||||||
last_pos = len(full_response)
|
last_pos = len(full_response)
|
||||||
if '</summary>' in full_response: full_response = full_response.replace('</summary>', '</summary>\n\n')
|
if '</summary>' in full_response: full_response = full_response.replace('</summary>', '</summary>\n\n')
|
||||||
if '</file_content>' in full_response: full_response = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_response, flags=re.DOTALL)
|
if '</file_content>' in full_response: full_response = re.sub(r'<file_content>\s*(.*?)\s*</file_content>', r'\n````\n<file_content>\n\1\n</file_content>\n````', full_response, flags=re.DOTALL)
|
||||||
self.display_queue.put({'done': full_response, 'source': source})
|
display_queue.put({'done': full_response, 'source': source})
|
||||||
self.history = handler.history_info
|
self.history = handler.history_info
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Backend Error: {format_error(e)}")
|
print(f"Backend Error: {format_error(e)}")
|
||||||
self.display_queue.put({'done': full_response + f'\n```\n{format_error(e)}\n```', 'source': source})
|
display_queue.put({'done': full_response + f'\n```\n{format_error(e)}\n```', 'source': source})
|
||||||
finally:
|
finally:
|
||||||
self.is_running = False
|
self.is_running = False
|
||||||
self.stop_sig = False
|
self.stop_sig = False
|
||||||
|
|||||||
19
launch.pyw
19
launch.pyw
@@ -12,12 +12,9 @@ TOP_PADDING = 300 # 离屏幕上边缘的距离
|
|||||||
|
|
||||||
def get_screen_width():
|
def get_screen_width():
|
||||||
try:
|
try:
|
||||||
# GetSystemMetrics(0) 获取主屏幕宽度
|
|
||||||
user32 = ctypes.windll.user32
|
user32 = ctypes.windll.user32
|
||||||
return user32.GetSystemMetrics(0)
|
return user32.GetSystemMetrics(0)
|
||||||
except:
|
except: return 1920
|
||||||
# 如果不是 Windows 或者出错了,返回一个兜底值 (比如 1920)
|
|
||||||
return 1920
|
|
||||||
|
|
||||||
def start_streamlit(port):
|
def start_streamlit(port):
|
||||||
global proc
|
global proc
|
||||||
@@ -30,6 +27,18 @@ def start_streamlit(port):
|
|||||||
proc = subprocess.Popen(cmd)
|
proc = subprocess.Popen(cmd)
|
||||||
atexit.register(proc.kill)
|
atexit.register(proc.kill)
|
||||||
|
|
||||||
|
def inject(text):
|
||||||
|
"""注入输入到 Streamlit"""
|
||||||
|
window.evaluate_js(f"""
|
||||||
|
const input = document.querySelector('input[data-testid="stChatInputTextInput"]');
|
||||||
|
if (input) {{
|
||||||
|
input.value = {repr(text)};
|
||||||
|
input.dispatchEvent(new Event('input', {{bubbles: true}}));
|
||||||
|
input.dispatchEvent(new KeyboardEvent('keydown', {{key: 'Enter', keyCode: 13, bubbles: true}}));
|
||||||
|
}}
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
port = sys.argv[1] if len(sys.argv) > 1 else "8501"
|
port = sys.argv[1] if len(sys.argv) > 1 else "8501"
|
||||||
t = threading.Thread(target=start_streamlit, args=(port,), daemon=True)
|
t = threading.Thread(target=start_streamlit, args=(port,), daemon=True)
|
||||||
@@ -39,7 +48,7 @@ if __name__ == '__main__':
|
|||||||
x_pos = screen_width - WINDOW_WIDTH - RIGHT_PADDING
|
x_pos = screen_width - WINDOW_WIDTH - RIGHT_PADDING
|
||||||
else: x_pos = 100
|
else: x_pos = 100
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
webview.create_window(
|
window = webview.create_window(
|
||||||
title='GenericAgent',
|
title='GenericAgent',
|
||||||
url=f'http://localhost:{port}',
|
url=f'http://localhost:{port}',
|
||||||
width=WINDOW_WIDTH,
|
width=WINDOW_WIDTH,
|
||||||
|
|||||||
36
stapp.py
36
stapp.py
@@ -23,12 +23,6 @@ agent = init()
|
|||||||
|
|
||||||
st.title("🖥️ Cowork")
|
st.title("🖥️ Cowork")
|
||||||
|
|
||||||
if "idle_buf" not in st.session_state: st.session_state.idle_buf = ""
|
|
||||||
if "messages" not in st.session_state: st.session_state.messages = []
|
|
||||||
|
|
||||||
for msg in st.session_state.messages:
|
|
||||||
with st.chat_message(msg["role"]): st.markdown(msg["content"])
|
|
||||||
|
|
||||||
@st.fragment
|
@st.fragment
|
||||||
def render_llm_switcher():
|
def render_llm_switcher():
|
||||||
current_idx = agent.llm_no
|
current_idx = agent.llm_no
|
||||||
@@ -44,36 +38,22 @@ def render_llm_switcher():
|
|||||||
st.toast("下次将重新注入System Prompt")
|
st.toast("下次将重新注入System Prompt")
|
||||||
with st.sidebar: render_llm_switcher()
|
with st.sidebar: render_llm_switcher()
|
||||||
|
|
||||||
@st.fragment(run_every="1s")
|
|
||||||
def global_queue_listener():
|
|
||||||
if agent.current_source == 'auto':
|
|
||||||
while not agent.display_queue.empty():
|
|
||||||
item = agent.display_queue.get()
|
|
||||||
if item.get('source') == 'auto':
|
|
||||||
if 'next' in item: st.session_state.idle_buf = item['next']
|
|
||||||
if 'done' in item:
|
|
||||||
st.session_state.messages.append({"role": "assistant", "content": f"🤖 {item['done']}"})
|
|
||||||
st.session_state.idle_buf = ""; st.rerun()
|
|
||||||
if st.session_state.get("idle_buf"):
|
|
||||||
with st.chat_message("assistant"):
|
|
||||||
st.write(st.session_state.idle_buf + "▌")
|
|
||||||
else:
|
|
||||||
st.caption("🟢 Agent Listener Active", help=f"Last sync: {int(time.time())}")
|
|
||||||
st.session_state.idle_buf = ""
|
|
||||||
|
|
||||||
global_queue_listener()
|
|
||||||
|
|
||||||
def agent_backend_stream(prompt):
|
def agent_backend_stream(prompt):
|
||||||
agent.put_task(prompt, source="user")
|
display_queue = agent.put_task(prompt, source="user")
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
item = agent.display_queue.get()
|
item = display_queue.get()
|
||||||
if 'next' in item: yield item['next']
|
if 'next' in item: yield item['next']
|
||||||
if 'done' in item:
|
if 'done' in item:
|
||||||
yield item['done']; break
|
yield item['done']; break
|
||||||
finally:
|
finally:
|
||||||
agent.abort()
|
agent.abort()
|
||||||
|
|
||||||
|
if "messages" not in st.session_state: st.session_state.messages = []
|
||||||
|
for msg in st.session_state.messages:
|
||||||
|
with st.chat_message(msg["role"]): st.markdown(msg["content"])
|
||||||
|
|
||||||
if prompt := st.chat_input("请输入指令"):
|
if prompt := st.chat_input("请输入指令"):
|
||||||
st.session_state.messages.append({"role": "user", "content": prompt})
|
st.session_state.messages.append({"role": "user", "content": prompt})
|
||||||
with st.chat_message("user"): st.markdown(prompt)
|
with st.chat_message("user"): st.markdown(prompt)
|
||||||
@@ -85,3 +65,7 @@ if prompt := st.chat_input("请输入指令"):
|
|||||||
message_placeholder.markdown(response + "▌")
|
message_placeholder.markdown(response + "▌")
|
||||||
message_placeholder.markdown(response)
|
message_placeholder.markdown(response)
|
||||||
st.session_state.messages.append({"role": "assistant", "content": response})
|
st.session_state.messages.append({"role": "assistant", "content": response})
|
||||||
|
st.session_state.last_reply_time = int(time.time())
|
||||||
|
|
||||||
|
st.markdown(f"""<div id="last-reply-time" style="display:none">{st.session_state.get('last_reply_time', int(time.time()))}</div>""", unsafe_allow_html=True)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user