fix(runtime): improve local service reliability

Close SQLite handles safely on Windows, clean orphaned vectors, normalize Ollama endpoints, and surface model errors without leaking reasoning tags.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-09 17:32:42 -05:00
co-authored by Cursor
parent a6e2ec1136
commit 193e91b234
6 changed files with 414 additions and 21 deletions
+41
View File
@@ -220,6 +220,8 @@ class PersistentMemoryStore:
"DELETE FROM settings WHERE key IN ('anthropic_api_key', 'escalation_model')"
)
self._sweep_orphan_msg_vectors(conn)
conn.commit()
conn.close()
@@ -483,6 +485,10 @@ class PersistentMemoryStore:
conn = self._connect()
try:
cur = conn.cursor()
ids = [r["id"] for r in cur.execute(
"SELECT id FROM messages WHERE conversation_id = ?", (conversation_id,)
).fetchall()]
self._delete_message_vectors(conn, ids)
cur.execute("DELETE FROM messages WHERE conversation_id = ?", (conversation_id,))
cur.execute("DELETE FROM conversations WHERE id = ?", (conversation_id,))
conn.commit()
@@ -671,6 +677,41 @@ class PersistentMemoryStore:
except Exception:
pass
def _delete_message_vectors(self, conn, message_ids) -> None:
"""Drop the cached embeddings of messages that are about to be deleted,
mirroring the removal into the ANN index — the delete-side counterpart of
`_vec_upsert_msg`. Retrieval already ignores orphans (it inner-joins
messages), but `messages.id` is AUTOINCREMENT so a stale vector is never
overwritten either: without this the table and index only ever grow."""
ids = list(message_ids)
if not ids:
return
for i in range(0, len(ids), 500): # stay under SQLite's variable limit
batch = ids[i:i + 500]
conn.execute(
f"DELETE FROM message_vectors WHERE message_id IN ({','.join('?' * len(batch))})",
batch,
)
if self.vec_enabled:
try:
for mid in ids:
conn.execute("DELETE FROM vec_messages WHERE rowid = ?", (mid,))
except Exception:
pass # index absent / extension unavailable — it's only a mirror
def _sweep_orphan_msg_vectors(self, conn) -> None:
"""One-time repair for databases written before delete_conversation
cleaned up after itself: drop vectors whose message is already gone."""
try:
ids = [r["message_id"] for r in conn.execute(
"SELECT v.message_id FROM message_vectors v "
"LEFT JOIN messages m ON m.id = v.message_id WHERE m.id IS NULL"
).fetchall()]
if ids:
self._delete_message_vectors(conn, ids)
except Exception:
pass
def _backfill_vec_msgs(self, conn, dim: int) -> None:
"""Index any message_vectors rows missing from vec_messages."""
try: