diff --git a/frontends/conductor.html b/frontends/conductor.html index 5380d5c8..a8155f60 100644 --- a/frontends/conductor.html +++ b/frontends/conductor.html @@ -76,6 +76,7 @@ } .title { font-size: 17px; letter-spacing: .2px; font-weight: 700; } .hint { color: var(--muted); font-size: 12px; } + #llm { max-width: 42vw; margin-left: 10px; padding: 4px 6px; border: 1px solid #dfe5ee; border-radius: 6px; background: #fff; font: 600 12px inherit; } .cards { flex: 1; @@ -312,7 +313,7 @@
-
Conversation
+
Conversation
connecting...
@@ -331,6 +332,7 @@ const messagesEl = document.getElementById('messages'); const inputEl = document.getElementById('input'); const sendBtn = document.getElementById('send'); + const llmEl = document.getElementById('llm'); const wsStatus = document.getElementById('wsStatus'); const apprEl = document.getElementById('approvals'); const apprBody = document.getElementById('approvalsBody'); @@ -452,6 +454,7 @@ renderCards(data.subagents||[]); messagesEl.innerHTML=''; (data.chat||[]).forEach(addMsg); renderLog(data.log||[]); + llmEl.innerHTML=(data.llms||[]).map(x=>``).join(''); llmEl.value=data.llm; llmEl.disabled=!llmEl.options.length; } else if(data.type==='subagents'){ renderCards(data.items||[]); } else if(data.type==='chat'){ addMsg(data.item); } else if(data.type==='chat_read'){ markAllRead(); } @@ -465,6 +468,7 @@ ws.send(JSON.stringify({msg})); inputEl.value=''; inputEl.focus(); } sendBtn.addEventListener('click', send); + llmEl.addEventListener('change', ()=>{ if(ws?.readyState===1) ws.send(JSON.stringify({llm:+llmEl.value})); }); inputEl.addEventListener('keydown', e=>{ if(e.key==='Enter' && !e.shiftKey && !e.isComposing && e.keyCode!==229){ e.preventDefault(); send(); } }); // Input length limit (10000 chars) diff --git a/frontends/conductor.py b/frontends/conductor.py index 4086d918..cce8a8af 100644 --- a/frontends/conductor.py +++ b/frontends/conductor.py @@ -414,7 +414,6 @@ API: {base};requests,GET /readme查用法,GET /chat读未读对话,GET / return def _run(self): - self.agent = GenericAgent() self.agent.inc_out = True start_agent_runner(self.agent, "conductor-agent") self.started = True @@ -431,18 +430,19 @@ API: {base};requests,GET /readme查用法,GET /chat读未读对话,GET / self.inbox.task_done() except Exception: break + kind = first.get("type"); others = [e for e in events if e.get("type") != kind]; events = [e for e in events if e.get("type") == kind] or [first] + for e in others: self.inbox.put(e) try: prompt = self._build_prompt(events) - # Follow the desktop-selected model live: re-read before each task - # so switching models in the UI takes effect without restarting. - _apply_desktop_model(self.agent) dq = self.agent.put_task(prompt, source="conductor") self._drain(dq, events) except Exception as e: print(f"Conductor error: {e}") add_chat(f"⚠ 回复失败:{e}", role="error") - def start(self): threading.Thread(target=self._run, name="conductor-loop", daemon=True).start() + def start(self): + self.agent = GenericAgent(); _apply_desktop_model(self.agent) + threading.Thread(target=self._run, name="conductor-loop", daemon=True).start() conductor = Conductor() @@ -573,9 +573,12 @@ async def websocket(ws: WebSocket): ws_clients.add(ws) try: running = any(s.status == "running" for s in pool.subagents.values()) - await ws.send_json({"type": "hello", "subagents": pool.snapshot(), "chat": chat_messages, "log": conductor.log, "running": running}) + await ws.send_json({"type": "hello", "subagents": pool.snapshot(), "chat": chat_messages, "log": conductor.log, "running": running, "llms": conductor.agent.list_llms(), "llm": conductor.agent.llm_no}) while True: data = await ws.receive_json() + if "llm" in data: + if type(n := data["llm"]) is int and 0 <= n < len(conductor.agent.list_llms()): conductor.agent.next_llm(n) + continue msg = (data.get("msg") or "").strip() if not msg: continue add_chat(msg, role="user", files=data.get("files") or [], images=data.get("images") or []) diff --git a/frontends/desktop/static/app.js b/frontends/desktop/static/app.js index 23eb4f07..f3b674e0 100644 --- a/frontends/desktop/static/app.js +++ b/frontends/desktop/static/app.js @@ -775,7 +775,17 @@ if (pqEl) pqEl.addEventListener('click', (e) => { const btn = e.target.closest('.pq-btn[data-provider]'); if (!btn) return; e.preventDefault(); e.stopPropagation(); - if (btn.dataset.provider === 'ga-token') { bridgeFetch('/subscription-portal', { method: 'POST', body: {} }); return; } + if (btn.dataset.provider === 'ga-token') { + window.ga.getMykeyContent().then(r => { + const base = r?.content || '', t0 = Date.now(); + bridgeFetch('/subscription-portal', { method: 'POST', body: {} }); + const timer = setInterval(async () => { + const cur = (await window.ga.getMykeyContent().catch(() => null))?.content; + if ((cur != null && cur !== base) || Date.now() - t0 > 3e5) { clearInterval(timer); if (cur !== base) await loadModelProfiles(); } + }, 3000); + }); + return; + } openAddModelFormForProvider(btn.dataset.provider); }); // 「快速接入」卡片折叠/展开(向下箭头),状态记忆到 localStorage diff --git a/frontends/desktop/static/index.html b/frontends/desktop/static/index.html index bfc98436..385a116b 100644 --- a/frontends/desktop/static/index.html +++ b/frontends/desktop/static/index.html @@ -696,6 +696,6 @@ - + diff --git a/ga.py b/ga.py index 3662cfb2..dc38f9a4 100644 --- a/ga.py +++ b/ga.py @@ -565,7 +565,7 @@ class GenericAgentHandler(BaseHandler): prompt = f"\n### [WORKING MEMORY]\n{earlier}{history}" prompt += f"\nCurrent turn: {self.current_turn}\n" if self.working.get('key_info'): prompt += f"\n{self.working.get('key_info')}" - if self.working.get('related_sop'): prompt += f"\n有不清晰的地方请再次读取{self.working.get('related_sop')}" + #if self.working.get('related_sop'): prompt += f"\n有不清晰的地方请再次读取{self.working.get('related_sop')}" if getattr(self.parent, 'verbose', False): self.print(prompt) return prompt