Nail sidechat create: direct send, no ID lookup\n\n- cmd_sidechat_create: simplified, just create and return\n- job-dispatch: after create, send via direct API to current chat\n- No thread ID parsing needed; thread lookup via URL for later ops
This commit is contained in:
+65
-36
@@ -96,25 +96,46 @@ def send_dm(agent, target, message, dry_run=False):
|
|||||||
|
|
||||||
def create_sidechat(sender_agent, dry_run=False):
|
def create_sidechat(sender_agent, dry_run=False):
|
||||||
"""Create a sidechat via muse-chat-api.py in sender's context.
|
"""Create a sidechat via muse-chat-api.py in sender's context.
|
||||||
Returns the thread URL or None on failure."""
|
Returns True on success (browser now on new sidechat), False on failure."""
|
||||||
if dry_run:
|
if dry_run:
|
||||||
print(f"[DRY RUN] Would create sidechat for {sender_agent}")
|
print(f"[DRY RUN] Would create sidechat for {sender_agent}")
|
||||||
return "https://muse.ai/thread/dry-run-uuid"
|
return True
|
||||||
|
|
||||||
cmd = [NETVM_EXEC, sender_agent, "--", "python3", str(CHAT_API),
|
cmd = [NETVM_EXEC, sender_agent, "--", "python3", str(CHAT_API),
|
||||||
"--account", sender_agent, "sidechat", "create"]
|
"--account", sender_agent, "sidechat", "create"]
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=90)
|
||||||
output = result.stdout.strip() + result.stderr.strip()
|
output = result.stdout.strip()
|
||||||
# Look for "Created: <url>"
|
# Success if we see "Created:" (URL may be /thread/new placeholder)
|
||||||
for line in output.split("\n"):
|
if "Created:" in output:
|
||||||
if "Created:" in line:
|
print(f"Sidechat created", file=sys.stderr)
|
||||||
url = line.split("Created:")[1].strip()
|
return True
|
||||||
return url
|
print(f"Sidechat create failed: {output[:200]}", file=sys.stderr)
|
||||||
print(f"Sidechat create output: {output[:200]}", file=sys.stderr)
|
return False
|
||||||
return None
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Sidechat creation failed: {e}", file=sys.stderr)
|
print(f"Sidechat creation failed: {e}", file=sys.stderr)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_to_current_chat(sender_agent, message, dry_run=False):
|
||||||
|
"""Send message to current chat via muse-chat-api.py (no navigation).
|
||||||
|
Used after sidechat create - browser is already on the new chat."""
|
||||||
|
if dry_run:
|
||||||
|
print(f"[DRY RUN] Would send to current chat: {message[:100]}...")
|
||||||
|
return "dry-run-id"
|
||||||
|
|
||||||
|
if HAS_RATE_LIMITER:
|
||||||
|
rate_limit_wait(sender_agent)
|
||||||
|
|
||||||
|
cmd = [NETVM_EXEC, sender_agent, "--", "python3", str(CHAT_API),
|
||||||
|
"--account", sender_agent, "send", message]
|
||||||
|
try:
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
|
||||||
|
if result.returncode == 0:
|
||||||
|
return "sent-to-sidechat"
|
||||||
|
print(f"Send failed: {result.stderr[:200]}", file=sys.stderr)
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Send failed: {e}", file=sys.stderr)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -155,30 +176,24 @@ def main():
|
|||||||
sidechat_cfg = job.get("sidechat", {})
|
sidechat_cfg = job.get("sidechat", {})
|
||||||
sidechat_url = None
|
sidechat_url = None
|
||||||
|
|
||||||
if sidechat_cfg.get("create", False):
|
use_sidechat = sidechat_cfg.get("create", False)
|
||||||
# Create sidechat in sender's (opm's) context
|
sidechat_created = False
|
||||||
# Then send the job DM DIRECTLY to the sidechat, not main.
|
|
||||||
# This keeps main chat clean; the sidechat IS the job workspace.
|
if use_sidechat:
|
||||||
|
# Create sidechat in sender's (opm's) context.
|
||||||
|
# Browser will be on the new sidechat; we send directly to it.
|
||||||
|
# No thread ID lookup needed - send_to_current_chat uses current page.
|
||||||
print(f"Creating sidechat for job {job_id}...", file=sys.stderr)
|
print(f"Creating sidechat for job {job_id}...", file=sys.stderr)
|
||||||
sidechat_url = create_sidechat("opm", dry_run=dry_run)
|
sidechat_created = create_sidechat("opm", dry_run=dry_run)
|
||||||
if sidechat_url:
|
if sidechat_created:
|
||||||
# Extract thread ID from URL (https://muse.ai/thread/<uuid>)
|
name_tmpl = sidechat_cfg.get("name_template", "job-{job_name}-{date}")
|
||||||
m = re.search(r"/thread/([a-f0-9-]+)", sidechat_url)
|
sc_name = render_prompt(name_tmpl, variables)
|
||||||
if m:
|
log_event("job_sidechat_created", {
|
||||||
thread_id = m.group(1)
|
"job_id": job_id,
|
||||||
target = thread_id # DM goes directly to sidechat
|
"sidechat_name": sc_name,
|
||||||
name_tmpl = sidechat_cfg.get("name_template", "job-{job_name}-{date}")
|
})
|
||||||
sc_name = render_prompt(name_tmpl, variables)
|
print(f"Sidechat created: {sc_name}", file=sys.stderr)
|
||||||
log_event("job_sidechat_created", {
|
target = "sidechat" # marker, not used for dm.py
|
||||||
"job_id": job_id,
|
|
||||||
"sidechat_url": sidechat_url,
|
|
||||||
"sidechat_name": sc_name,
|
|
||||||
"thread_id": thread_id,
|
|
||||||
})
|
|
||||||
print(f"Sidechat created: {sc_name} ({thread_id})", file=sys.stderr)
|
|
||||||
else:
|
|
||||||
print(f"Warning: Could not parse thread ID from {sidechat_url}", file=sys.stderr)
|
|
||||||
target = "main"
|
|
||||||
else:
|
else:
|
||||||
print(f"Warning: Failed to create sidechat, falling back to main", file=sys.stderr)
|
print(f"Warning: Failed to create sidechat, falling back to main", file=sys.stderr)
|
||||||
target = "main"
|
target = "main"
|
||||||
@@ -194,8 +209,22 @@ def main():
|
|||||||
"dry_run": dry_run,
|
"dry_run": dry_run,
|
||||||
})
|
})
|
||||||
|
|
||||||
# Send DM
|
# Send DM: to sidechat via direct API, or to main via dm.py
|
||||||
msg_id = send_dm(agent, target, dm_message, dry_run=dry_run)
|
if use_sidechat and sidechat_created:
|
||||||
|
msg_id = send_to_current_chat("opm", dm_message, dry_run=dry_run)
|
||||||
|
# Log as dispatched (no dm.py ID, but sent)
|
||||||
|
if msg_id and not dry_run:
|
||||||
|
print(f"Dispatched job {job_id} to sidechat (direct send)")
|
||||||
|
log_event("job_dispatched", {
|
||||||
|
"job_id": job_id,
|
||||||
|
"target": "sidechat",
|
||||||
|
"method": "direct",
|
||||||
|
})
|
||||||
|
# Skip the dm.py dispatch block below
|
||||||
|
import sys as _sys2
|
||||||
|
_sys2.exit(0)
|
||||||
|
else:
|
||||||
|
msg_id = send_dm(agent, target, dm_message, dry_run=dry_run)
|
||||||
|
|
||||||
if msg_id and not dry_run:
|
if msg_id and not dry_run:
|
||||||
print(f"Dispatched job {job_id} to {agent} (DM: {msg_id})")
|
print(f"Dispatched job {job_id} to {agent} (DM: {msg_id})")
|
||||||
|
|||||||
+4
-18
@@ -326,24 +326,10 @@ def cmd_sidechat_create(ws):
|
|||||||
if not url or "/thread/" not in url:
|
if not url or "/thread/" not in url:
|
||||||
print(f"ERROR: Sidechat creation did not navigate to thread URL (got: {url})", file=sys.stderr)
|
print(f"ERROR: Sidechat creation did not navigate to thread URL (got: {url})", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
# If we got /thread/new (placeholder), the real ID is assigned after
|
# Return the URL (may be /thread/new placeholder).
|
||||||
# the first message. Send a system message to trigger ID assignment,
|
# The caller sends directly to current chat via cmd_send (no ID needed).
|
||||||
# then re-read the URL.
|
# Thread ID can be looked up later via URL polling if needed.
|
||||||
if url.endswith("/thread/new"):
|
# Fixed 2026-10-04: don't chase real ID at create time, just create.
|
||||||
# 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)
|
|
||||||
url = ev(ws, "window.location.href")
|
|
||||||
if url and "/thread/" in url and not url.endswith("/thread/new"):
|
|
||||||
break
|
|
||||||
if not url or "/thread/" not in url or url.endswith("/thread/new"):
|
|
||||||
print(f"ERROR: Could not get real thread ID (got: {url})", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
print(f"Created: {url}")
|
print(f"Created: {url}")
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user