ai_co_discuss 0.3.20 → 0.3.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1107,11 +1107,11 @@ def advance_queues(connection, room_id):
1107
1107
 
1108
1108
  Asked rows stay, so the speaking order can still show who already answered.
1109
1109
  """
1110
- connection.execute(f"""DELETE FROM free_queue WHERE room_id=? AND NOT {QUEUE_ASKED.format(row="free_queue")}
1111
- AND NOT EXISTS(SELECT 1 FROM room_members m WHERE m.id=free_queue.member_id AND m.status='active')""", (room_id,))
1112
- connection.execute(f"""INSERT OR IGNORE INTO member_requests (room_id,member_id,message_id,chain_id,batch_id,purpose,created_by,created_at)
1113
- SELECT q.room_id,q.member_id,q.message_id,q.message_id,0,'ask','user',? FROM free_queue q
1114
- WHERE q.room_id=? AND q.id=(SELECT MIN(x.id) FROM free_queue x WHERE x.message_id=q.message_id AND NOT {QUEUE_ASKED.format(row="x")})
1110
+ connection.execute("""DELETE FROM free_queue WHERE id IN (SELECT q.id FROM free_queue_waiting q WHERE q.room_id=?
1111
+ AND NOT EXISTS(SELECT 1 FROM room_members m WHERE m.id=q.member_id AND m.status='active'))""", (room_id,))
1112
+ connection.execute("""INSERT OR IGNORE INTO member_requests (room_id,member_id,message_id,chain_id,batch_id,purpose,created_by,created_at)
1113
+ SELECT q.room_id,q.member_id,q.message_id,q.message_id,0,'ask','user',? FROM free_queue_waiting q
1114
+ WHERE q.id IN (SELECT MIN(id) FROM free_queue_waiting WHERE room_id=? GROUP BY message_id)
1115
1115
  AND NOT EXISTS(SELECT 1 FROM member_requests r WHERE r.message_id=q.message_id AND r.status IN ('pending','delivering'))""",
1116
1116
  (int(time.time()), room_id))
1117
1117
 
@@ -1142,8 +1142,11 @@ def speaking_order(connection, room):
1142
1142
  target = session["id"]
1143
1143
  items, later, session_plan_state = discussion.session_speaking_order(connection, session)
1144
1144
  else:
1145
- target = connection.execute("""SELECT MAX(q.message_id) FROM free_queue q LEFT JOIN member_requests r ON r.message_id=q.message_id
1146
- AND r.member_id=q.member_id WHERE q.room_id=? AND (r.id IS NULL OR r.status IN ('pending','delivering'))""", (room["id"],)).fetchone()[0] or 0
1145
+ target = connection.execute("""SELECT MAX(message_id) FROM (
1146
+ SELECT MAX(message_id) AS message_id FROM free_queue_waiting WHERE room_id=?
1147
+ UNION ALL SELECT MAX(r.message_id) FROM member_requests r WHERE r.room_id=? AND r.status IN ('pending','delivering')
1148
+ AND EXISTS(SELECT 1 FROM free_queue q WHERE q.message_id=r.message_id AND q.member_id=r.member_id))""",
1149
+ (room["id"], room["id"])).fetchone()[0] or 0
1147
1150
  if target:
1148
1151
  kind = "queue"
1149
1152
  for row in connection.execute("""SELECT q.member_id,r.status FROM free_queue q LEFT JOIN member_requests r
@@ -1817,8 +1820,8 @@ def interrupt_member(connection, room_id, member_id, token):
1817
1820
 
1818
1821
  def withdrawals(connection, room_id):
1819
1822
  """The room's taken-back messages by id, so the page keeps them in place while AI readers skip them."""
1820
- return [dict(row) for row in connection.execute("""SELECT w.message_id,w.kind FROM message_withdrawals w
1821
- JOIN messages m ON m.id=w.message_id WHERE m.room_id=? ORDER BY w.message_id""", (room_id,))]
1823
+ return [dict(row) for row in connection.execute("""SELECT w.message_id,w.kind FROM message_withdrawal_rooms r
1824
+ JOIN message_withdrawals w ON w.message_id=r.message_id WHERE r.room_id=? ORDER BY r.message_id""", (room_id,))]
1822
1825
 
1823
1826
 
1824
1827
  def owner_message(connection, room_id, message_id):
@@ -20,6 +20,8 @@ from .admin import AdminError
20
20
  from .runtime import begin_write
21
21
 
22
22
  MACHINE_ONLINE_SECONDS = 30
23
+ # Heartbeats refresh seen_at at most this often (well inside the online window) so frequent polls do not each write a row.
24
+ MACHINE_SEEN_REFRESH_SECONDS = 10
23
25
  MACHINE_NAME_MAX = 60
24
26
  PROJECT_NAME_MAX = 80
25
27
  PROJECTS_MAX = 100
@@ -135,11 +137,15 @@ def machine_sync(connection, machine_id, token, payload, now):
135
137
  projects, clients = valid_projects(payload.get("projects")), valid_clients(payload.get("clients"))
136
138
  public_key = valid_public_key(payload["public_key"]) if "public_key" in payload else None
137
139
  begin_write(connection)
138
- connection.execute("UPDATE local_machines SET projects=?, clients=?, seen_at=? WHERE id=?",
139
- (json.dumps(projects, ensure_ascii=False), json.dumps(clients, ensure_ascii=False), now, machine_id))
140
+ # Unchanged heartbeats write nothing until seen_at is due for a refresh.
141
+ connection.execute("UPDATE local_machines SET projects=?1, clients=?2, seen_at=?3 WHERE id=?4 "
142
+ "AND (projects IS NOT ?1 OR clients IS NOT ?2 OR seen_at<?3-?5)",
143
+ (json.dumps(projects, ensure_ascii=False), json.dumps(clients, ensure_ascii=False), now, machine_id,
144
+ MACHINE_SEEN_REFRESH_SECONDS))
140
145
  if public_key:
141
146
  connection.execute("INSERT INTO machine_keys (machine_id,public_key) VALUES (?,?) "
142
- "ON CONFLICT(machine_id) DO UPDATE SET public_key=excluded.public_key", (machine_id, json.dumps(public_key)))
147
+ "ON CONFLICT(machine_id) DO UPDATE SET public_key=excluded.public_key "
148
+ "WHERE machine_keys.public_key IS NOT excluded.public_key", (machine_id, json.dumps(public_key)))
143
149
  rows = connection.execute("SELECT id,request FROM remote_launches WHERE machine_id=? AND status IN ('pending','claimed') ORDER BY created_at",
144
150
  (machine_id,)).fetchall()
145
151
  return {"launches": [{"id": row["id"], "request": json.loads(row["request"])} for row in rows]}
@@ -245,7 +251,7 @@ def claim_machine_commands(connection, machine_id, token, now):
245
251
  require_machine(connection, machine_id, token)
246
252
  begin_write(connection)
247
253
  connection.execute("DELETE FROM machine_commands WHERE machine_id=? AND created_at<?", (machine_id, now - COMMAND_TTL_SECONDS))
248
- connection.execute("UPDATE local_machines SET seen_at=? WHERE id=?", (now, machine_id))
254
+ connection.execute("UPDATE local_machines SET seen_at=? WHERE id=? AND seen_at<?", (now, machine_id, now - MACHINE_SEEN_REFRESH_SECONDS))
249
255
  rows = connection.execute("SELECT id,request FROM machine_commands WHERE machine_id=? AND status='pending' ORDER BY created_at",
250
256
  (machine_id,)).fetchall()
251
257
  for row in rows: