Fix sidechat CDP and button selectors\n\n- sidechat_manager._ev: use id=1 and returnByValue to match ev()\n- cmd_sidechat_create: find + button via Side chats header proximity\n- cmd_sidechat_create: use cmd_send for initial message (not DOM hack)\n- Integrate ensure_sidebar with retry

This commit is contained in:
operator-main
2026-10-04 03:19:48 +00:00
parent 7a6e54fed2
commit c57a05963a
2 changed files with 37 additions and 23 deletions
+34 -20
View File
@@ -279,16 +279,40 @@ def cmd_sidechat_create(ws):
if (btn) btn.click();
})()""")
_time.sleep(2)
# The + button sits next to the "Side chats" header (see screenshot 2026-10-04).
# It's not labeled "New side chat" - find it by proximity to the header text.
result = ev(ws, """(() => {
const btn = [...document.querySelectorAll('button')].find(b =>
// Strategy 1: Find button with "+" text near "Side chats"
const header = [...document.querySelectorAll('*')].find(el =>
el.textContent.trim() === 'Side chats' && el.children.length === 0);
if (header) {
// Look for + button in the header's parent or siblings
const parent = header.parentElement;
if (parent) {
const plus = [...parent.querySelectorAll('button')].find(b =>
(b.textContent||'').includes('+') || (b.getAttribute('aria-label')||'').toLowerCase().includes('add'));
if (plus) { plus.click(); return 'CLICKED_VIA_HEADER'; }
}
}
// Strategy 2: Find any button with "+" that's near the top
const plusBtn = [...document.querySelectorAll('button')].find(b => {
const t = (b.textContent||'').trim();
const al = (b.getAttribute('aria-label')||'').toLowerCase();
return t === '+' || al.includes('new side') || al.includes('add chat');
});
if (plusBtn) { plusBtn.click(); return 'CLICKED_VIA_PLUS'; }
// Strategy 3 (fallback): old aria-label exact match
const oldBtn = [...document.querySelectorAll('button')].find(b =>
(b.getAttribute('aria-label')||'') === 'New side chat');
if (!btn) return 'NOT_FOUND';
btn.click();
return 'CLICKED';
if (oldBtn) { oldBtn.click(); return 'CLICKED_VIA_ARIA'; }
return 'NOT_FOUND';
})()""")
if result == 'NOT_FOUND':
print("ERROR: 'New side chat' button not found (sidebar may be closed)", file=sys.stderr)
print("ERROR: New side chat + button not found (sidebar may be closed)", file=sys.stderr)
sys.exit(1)
# Log which strategy worked for debugging
import sys as _sys
print(f"Sidechat create: {result}", file=_sys.stderr)
import time as _time
# Poll for URL to change to a thread URL (up to 15s)
# Fixed 2026-10-04: was sleeping 5s and reading once, often captured
@@ -306,21 +330,11 @@ def cmd_sidechat_create(ws):
# the first message. Send a system message to trigger ID assignment,
# then re-read the URL.
if url.endswith("/thread/new"):
ev(ws, """(() => {
const input = document.querySelector('[contenteditable="true"]');
if (!input) return 'NO_INPUT';
input.focus();
document.execCommand('insertText', false, '[System: Side chat created]');
return 'READY';
})()""")
_time.sleep(1)
# Click send
ev(ws, """(() => {
const btn = [...document.querySelectorAll('button')].find(b =>
(b.getAttribute('aria-label')||'').toLowerCase().includes('send'));
if (btn) { btn.click(); return 'SENT'; }
return 'NO_BTN';
})()""")
# Use proven cmd_send to trigger real thread ID
try:
cmd_send(ws, "[System: Side chat created]")
except Exception as e:
print(f"Warning: initial send failed: {e}", file=sys.stderr)
# Poll for URL to change from /thread/new to /thread/<uuid>
for i in range(15):
_time.sleep(1)
+3 -3
View File
@@ -15,13 +15,13 @@ import json
def _ev(ws, js, await_result=True):
"""Evaluate JS via CDP, return result.
Uses id=1 to match muse-chat-api.py's ev() on shared websocket.
Fixed 2026-10-04: was using id=100, causing response mismatch.
Matches muse-chat-api.py's ev() exactly (id=1, returnByValue).
Fixed 2026-10-04: was using id=100, missing returnByValue.
"""
import json as _json
ws.send(_json.dumps({
"id": 1, "method": "Runtime.evaluate",
"params": {"expression": js, "awaitPromise": True}
"params": {"expression": js, "returnByValue": True, "awaitPromise": await_result}
}))
resp = _json.loads(ws.recv())
result = resp.get("result", {}).get("result", {})