feat(dashboard): add click-outside dismissal for autocomplete dropdown

Closes bd-3ny. Added mousedown listener that dismisses the dropdown when
clicking outside both the dropdown and textarea. Uses early return to avoid
registering listeners when dropdown is already closed.
This commit is contained in:
teernisse
2026-02-26 16:52:36 -05:00
parent ba16daac2a
commit db3d2a2e31
35 changed files with 5560 additions and 104 deletions

View File

@@ -170,6 +170,8 @@ def main():
existing["last_event"] = f"PreToolUse({tool_name})"
existing["last_event_at"] = now
existing["pending_questions"] = _extract_questions(hook)
# Track when turn paused for duration calculation
existing["turn_paused_at"] = now
_atomic_write(session_file, existing)
_append_event(session_id, {
"event": f"PreToolUse({tool_name})",
@@ -189,6 +191,16 @@ def main():
existing["last_event"] = f"PostToolUse({tool_name})"
existing["last_event_at"] = now
existing.pop("pending_questions", None)
# Accumulate paused time for turn duration calculation
paused_at = existing.pop("turn_paused_at", None)
if paused_at:
try:
paused_start = datetime.fromisoformat(paused_at.replace("Z", "+00:00"))
paused_end = datetime.fromisoformat(now.replace("Z", "+00:00"))
paused_ms = int((paused_end - paused_start).total_seconds() * 1000)
existing["turn_paused_ms"] = existing.get("turn_paused_ms", 0) + paused_ms
except (ValueError, TypeError):
pass
_atomic_write(session_file, existing)
_append_event(session_id, {
"event": f"PostToolUse({tool_name})",
@@ -237,6 +249,20 @@ def main():
"zellij_pane": os.environ.get("ZELLIJ_PANE_ID", ""),
}
# Turn timing: track working time from user prompt to completion
if event == "UserPromptSubmit":
# New turn starting - reset turn timing
state["turn_started_at"] = now
state["turn_paused_ms"] = 0
else:
# Preserve turn timing from existing state
if "turn_started_at" in existing:
state["turn_started_at"] = existing["turn_started_at"]
if "turn_paused_ms" in existing:
state["turn_paused_ms"] = existing["turn_paused_ms"]
if "turn_paused_at" in existing:
state["turn_paused_at"] = existing["turn_paused_at"]
# Store prose question if detected
if prose_question:
state["pending_questions"] = [{

29
bin/amc-server-restart Executable file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Restart the AMC server cleanly
set -e
PORT=7400
# Find and kill existing server
PID=$(lsof -ti :$PORT 2>/dev/null || true)
if [[ -n "$PID" ]]; then
echo "Stopping AMC server (PID $PID)..."
kill "$PID" 2>/dev/null || true
sleep 1
fi
# Start server in background
echo "Starting AMC server on port $PORT..."
cd "$(dirname "$0")/.."
nohup python3 -m amc_server.server > /tmp/amc-server.log 2>&1 &
# Wait for startup
sleep 1
NEW_PID=$(lsof -ti :$PORT 2>/dev/null || true)
if [[ -n "$NEW_PID" ]]; then
echo "AMC server running (PID $NEW_PID)"
else
echo "Failed to start server. Check /tmp/amc-server.log"
exit 1
fi