claude-smart 0.2.47 → 0.2.48
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.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/dashboard/app/sessions/[sessionId]/page.tsx +36 -2
- package/plugin/dashboard/package-lock.json +61 -390
- package/plugin/dashboard/package.json +2 -2
- package/plugin/pyproject.toml +1 -1
- package/plugin/uv.lock +1 -1
- package/plugin/vendor/reflexio/.env.example +7 -0
- package/plugin/vendor/reflexio/pyproject.toml +2 -1
- package/plugin/vendor/reflexio/reflexio/README.md +8 -5
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +23 -18
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +16 -1
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +15 -11
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +1 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +24 -3
- package/plugin/vendor/reflexio/reflexio/server/README.md +25 -8
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +21 -2
- package/plugin/vendor/reflexio/reflexio/server/api.py +133 -3273
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +4 -3
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +16 -1
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +62 -36
- package/plugin/vendor/reflexio/reflexio/server/deployment_profile.py +69 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_embedding.py +424 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_json_extraction.py +249 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_structured_output.py +195 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_subprocess.py +152 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_text_generation.py +980 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_types.py +110 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +73 -1819
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +56 -4
- package/plugin/vendor/reflexio/reflexio/server/middleware.py +244 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +9 -1
- package/plugin/vendor/reflexio/reflexio/server/rate_limit.py +79 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/_common.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/_metering.py +98 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/braintrust.py +129 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/config.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/evaluation.py +549 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/interactions.py +259 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/playbooks.py +578 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/profiles.py +423 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/provenance.py +345 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/search.py +349 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/system.py +261 -0
- package/plugin/vendor/reflexio/reflexio/server/scheduling.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +3 -2
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/__init__.py +38 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_batch_progress.py +298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_config_filter.py +152 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_extraction_lifecycle.py +243 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_should_run.py +299 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_status_change.py +273 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_usage_billing.py +258 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +17 -1183
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +8 -1
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +26 -41
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +232 -123
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +362 -81
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator.py +68 -490
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_clustering.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_postprocessing.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_prompt_formatting.py +212 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/consolidator.py +258 -69
- package/plugin/vendor/reflexio/reflexio/server/services/publish_learning_worker.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +29 -4
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +10 -1167
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +56 -351
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +0 -1513
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +6 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +7 -1281
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_agent_run_store.py +506 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_pending_tool_call_store.py +704 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_run_tool_dependency_store.py +123 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/_deletion.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/_fts_vec.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_audit.py +122 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_erase_execution.py +465 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_purge.py +387 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_rebuild_hide.py +332 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_subject_barrier.py +511 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +6 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +13 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_interaction_store.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_profile_store.py +896 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_search.py +270 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +33 -8
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +64 -370
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +20 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_agent_run_store.py +86 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_models.py +195 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_pending_tool_call_store.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_run_tool_dependency_store.py +38 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_audit.py +29 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_erase_execution.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_purge.py +74 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_rebuild_hide.py +32 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_subject_barrier.py +49 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_interaction_store.py +73 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/{_profiles.py → profiles/_profile_store.py} +44 -86
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_search.py +32 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_governance.py +0 -148
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
"""Interaction store CRUD methods for SQLite storage.
|
|
2
|
+
|
|
3
|
+
Extracted verbatim from ``_profiles.py`` (the InteractionStore bucket). Profile
|
|
4
|
+
CRUD lives in ``profiles._profile_store`` (``ProfileStoreMixin``); search methods
|
|
5
|
+
live in ``profiles._search`` (``ProfileSearchMixin``).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import sqlite3
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from reflexio.models.api_schema.service_schemas import (
|
|
13
|
+
DeleteUserInteractionRequest,
|
|
14
|
+
Interaction,
|
|
15
|
+
)
|
|
16
|
+
from reflexio.server.llm.providers.embedding_service_provider import (
|
|
17
|
+
EmbeddingUnavailableError,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
from .._base import (
|
|
21
|
+
SQLiteStorageBase,
|
|
22
|
+
_epoch_to_iso,
|
|
23
|
+
_json_dumps,
|
|
24
|
+
_row_to_interaction,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class InteractionStoreMixin:
|
|
31
|
+
"""Mixin providing interaction-store CRUD for SQLite storage."""
|
|
32
|
+
|
|
33
|
+
# Type hints for instance attributes/methods provided by SQLiteStorageBase via MRO
|
|
34
|
+
_lock: Any
|
|
35
|
+
conn: sqlite3.Connection
|
|
36
|
+
_fetchone: Any
|
|
37
|
+
_fetchall: Any
|
|
38
|
+
_get_embedding: Any
|
|
39
|
+
_fts_upsert: Any
|
|
40
|
+
_vec_upsert: Any
|
|
41
|
+
_delete_in_chunks: Any
|
|
42
|
+
_has_sqlite_vec: bool
|
|
43
|
+
llm_client: Any
|
|
44
|
+
embedding_model_name: str
|
|
45
|
+
embedding_dimensions: int
|
|
46
|
+
_subject_ref_for_user_id: Any
|
|
47
|
+
_assert_subject_writable_locked: Any
|
|
48
|
+
|
|
49
|
+
# ------------------------------------------------------------------
|
|
50
|
+
# CRUD — Interactions
|
|
51
|
+
# ------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
@SQLiteStorageBase.handle_exceptions
|
|
54
|
+
def get_all_interactions(self, limit: int = 100) -> list[Interaction]:
|
|
55
|
+
rows = self._fetchall(
|
|
56
|
+
"SELECT * FROM interactions ORDER BY created_at DESC LIMIT ?", (limit,)
|
|
57
|
+
)
|
|
58
|
+
return [_row_to_interaction(r) for r in rows]
|
|
59
|
+
|
|
60
|
+
@SQLiteStorageBase.handle_exceptions
|
|
61
|
+
def get_user_interaction(self, user_id: str) -> list[Interaction]:
|
|
62
|
+
rows = self._fetchall(
|
|
63
|
+
"SELECT * FROM interactions WHERE user_id = ?", (user_id,)
|
|
64
|
+
)
|
|
65
|
+
return [_row_to_interaction(r) for r in rows]
|
|
66
|
+
|
|
67
|
+
@SQLiteStorageBase.handle_exceptions
|
|
68
|
+
def get_all_user_ids(self) -> list[str]:
|
|
69
|
+
rows = self._fetchall("SELECT DISTINCT user_id FROM interactions")
|
|
70
|
+
return sorted(r["user_id"] for r in rows)
|
|
71
|
+
|
|
72
|
+
@SQLiteStorageBase.handle_exceptions
|
|
73
|
+
def add_user_interaction(self, user_id: str, interaction: Interaction) -> None: # noqa: ARG002
|
|
74
|
+
embedding = self._get_embedding(
|
|
75
|
+
f"{interaction.content}\n{interaction.user_action_description}"
|
|
76
|
+
)
|
|
77
|
+
interaction.embedding = embedding
|
|
78
|
+
self._insert_interaction(interaction)
|
|
79
|
+
|
|
80
|
+
def _insert_interaction(self, interaction: Interaction) -> int:
|
|
81
|
+
created_at_iso = _epoch_to_iso(interaction.created_at)
|
|
82
|
+
subject_ref = self._subject_ref_for_user_id(interaction.user_id)
|
|
83
|
+
with self._lock:
|
|
84
|
+
try:
|
|
85
|
+
self.conn.execute("BEGIN IMMEDIATE")
|
|
86
|
+
self._assert_subject_writable_locked(subject_ref)
|
|
87
|
+
if interaction.interaction_id:
|
|
88
|
+
self.conn.execute(
|
|
89
|
+
"""INSERT OR REPLACE INTO interactions
|
|
90
|
+
(interaction_id, user_id, content, request_id, created_at,
|
|
91
|
+
role, user_action, user_action_description,
|
|
92
|
+
interacted_image_url, image_encoding, shadow_content,
|
|
93
|
+
expert_content, tools_used, citations, embedding, governance_subject_ref)
|
|
94
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
|
95
|
+
(
|
|
96
|
+
interaction.interaction_id,
|
|
97
|
+
interaction.user_id,
|
|
98
|
+
interaction.content,
|
|
99
|
+
interaction.request_id,
|
|
100
|
+
created_at_iso,
|
|
101
|
+
interaction.role,
|
|
102
|
+
interaction.user_action.value,
|
|
103
|
+
interaction.user_action_description,
|
|
104
|
+
interaction.interacted_image_url,
|
|
105
|
+
interaction.image_encoding,
|
|
106
|
+
interaction.shadow_content,
|
|
107
|
+
interaction.expert_content,
|
|
108
|
+
_json_dumps(
|
|
109
|
+
[t.model_dump() for t in interaction.tools_used]
|
|
110
|
+
),
|
|
111
|
+
_json_dumps(
|
|
112
|
+
[c.model_dump() for c in interaction.citations]
|
|
113
|
+
),
|
|
114
|
+
_json_dumps(interaction.embedding),
|
|
115
|
+
subject_ref,
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
iid = interaction.interaction_id
|
|
119
|
+
else:
|
|
120
|
+
cur = self.conn.execute(
|
|
121
|
+
"""INSERT INTO interactions
|
|
122
|
+
(user_id, content, request_id, created_at,
|
|
123
|
+
role, user_action, user_action_description,
|
|
124
|
+
interacted_image_url, image_encoding, shadow_content,
|
|
125
|
+
expert_content, tools_used, citations, embedding, governance_subject_ref)
|
|
126
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
|
127
|
+
(
|
|
128
|
+
interaction.user_id,
|
|
129
|
+
interaction.content,
|
|
130
|
+
interaction.request_id,
|
|
131
|
+
created_at_iso,
|
|
132
|
+
interaction.role,
|
|
133
|
+
interaction.user_action.value,
|
|
134
|
+
interaction.user_action_description,
|
|
135
|
+
interaction.interacted_image_url,
|
|
136
|
+
interaction.image_encoding,
|
|
137
|
+
interaction.shadow_content,
|
|
138
|
+
interaction.expert_content,
|
|
139
|
+
_json_dumps(
|
|
140
|
+
[t.model_dump() for t in interaction.tools_used]
|
|
141
|
+
),
|
|
142
|
+
_json_dumps(
|
|
143
|
+
[c.model_dump() for c in interaction.citations]
|
|
144
|
+
),
|
|
145
|
+
_json_dumps(interaction.embedding),
|
|
146
|
+
subject_ref,
|
|
147
|
+
),
|
|
148
|
+
)
|
|
149
|
+
iid = cur.lastrowid or 0
|
|
150
|
+
interaction.interaction_id = iid
|
|
151
|
+
self.conn.commit()
|
|
152
|
+
except Exception:
|
|
153
|
+
self.conn.rollback()
|
|
154
|
+
raise
|
|
155
|
+
# Update FTS and vec
|
|
156
|
+
self._fts_upsert(
|
|
157
|
+
"interactions_fts",
|
|
158
|
+
iid,
|
|
159
|
+
content=interaction.content,
|
|
160
|
+
user_action_description=interaction.user_action_description,
|
|
161
|
+
)
|
|
162
|
+
if interaction.embedding:
|
|
163
|
+
self._vec_upsert("interactions_vec", iid, interaction.embedding)
|
|
164
|
+
return iid
|
|
165
|
+
|
|
166
|
+
@SQLiteStorageBase.handle_exceptions
|
|
167
|
+
def add_user_interactions_bulk(
|
|
168
|
+
self,
|
|
169
|
+
user_id: str, # noqa: ARG002
|
|
170
|
+
interactions: list[Interaction],
|
|
171
|
+
) -> None:
|
|
172
|
+
if not interactions:
|
|
173
|
+
return
|
|
174
|
+
texts = [
|
|
175
|
+
"\n".join([i.content or "", i.user_action_description or ""])
|
|
176
|
+
for i in interactions
|
|
177
|
+
]
|
|
178
|
+
try:
|
|
179
|
+
embeddings = self.llm_client.get_embeddings(
|
|
180
|
+
texts, self.embedding_model_name, self.embedding_dimensions
|
|
181
|
+
)
|
|
182
|
+
except EmbeddingUnavailableError as exc:
|
|
183
|
+
logger.warning(
|
|
184
|
+
"Embedding unavailable for interaction bulk insert; "
|
|
185
|
+
"continuing without vectors: %s",
|
|
186
|
+
exc,
|
|
187
|
+
)
|
|
188
|
+
embeddings = [[] for _ in texts]
|
|
189
|
+
for interaction, embedding in zip(interactions, embeddings, strict=False):
|
|
190
|
+
interaction.embedding = embedding
|
|
191
|
+
self._insert_interaction(interaction)
|
|
192
|
+
|
|
193
|
+
@SQLiteStorageBase.handle_exceptions
|
|
194
|
+
def delete_user_interaction(self, request: DeleteUserInteractionRequest) -> None:
|
|
195
|
+
with self._lock:
|
|
196
|
+
row = self.conn.execute(
|
|
197
|
+
"SELECT interaction_id FROM interactions WHERE user_id = ? AND interaction_id = ?",
|
|
198
|
+
(request.user_id, request.interaction_id),
|
|
199
|
+
).fetchone()
|
|
200
|
+
if row is None:
|
|
201
|
+
return
|
|
202
|
+
self.conn.execute(
|
|
203
|
+
"DELETE FROM interactions_fts WHERE rowid = ?",
|
|
204
|
+
(request.interaction_id,),
|
|
205
|
+
)
|
|
206
|
+
if self._has_sqlite_vec:
|
|
207
|
+
self.conn.execute(
|
|
208
|
+
"DELETE FROM interactions_vec WHERE rowid = ?",
|
|
209
|
+
(request.interaction_id,),
|
|
210
|
+
)
|
|
211
|
+
self.conn.execute(
|
|
212
|
+
"DELETE FROM interactions WHERE user_id = ? AND interaction_id = ?",
|
|
213
|
+
(request.user_id, request.interaction_id),
|
|
214
|
+
)
|
|
215
|
+
self.conn.commit()
|
|
216
|
+
|
|
217
|
+
@SQLiteStorageBase.handle_exceptions
|
|
218
|
+
def delete_all_interactions_for_user(self, user_id: str) -> None:
|
|
219
|
+
with self._lock:
|
|
220
|
+
rows = self.conn.execute(
|
|
221
|
+
"SELECT interaction_id FROM interactions WHERE user_id = ?", (user_id,)
|
|
222
|
+
).fetchall()
|
|
223
|
+
if not rows:
|
|
224
|
+
return
|
|
225
|
+
ids = [r["interaction_id"] for r in rows]
|
|
226
|
+
self._delete_in_chunks("interactions_fts", "rowid", ids)
|
|
227
|
+
if self._has_sqlite_vec:
|
|
228
|
+
self._delete_in_chunks("interactions_vec", "rowid", ids)
|
|
229
|
+
self.conn.execute("DELETE FROM interactions WHERE user_id = ?", (user_id,))
|
|
230
|
+
self.conn.commit()
|
|
231
|
+
|
|
232
|
+
@SQLiteStorageBase.handle_exceptions
|
|
233
|
+
def delete_all_interactions(self) -> None:
|
|
234
|
+
with self._lock:
|
|
235
|
+
self.conn.execute("DELETE FROM interactions_fts")
|
|
236
|
+
if self._has_sqlite_vec:
|
|
237
|
+
self.conn.execute("DELETE FROM interactions_vec")
|
|
238
|
+
self.conn.execute("DELETE FROM interactions")
|
|
239
|
+
self.conn.commit()
|
|
240
|
+
|
|
241
|
+
@SQLiteStorageBase.handle_exceptions
|
|
242
|
+
def count_all_interactions(self) -> int:
|
|
243
|
+
row = self._fetchone("SELECT COUNT(*) as cnt FROM interactions")
|
|
244
|
+
return row["cnt"] if row else 0
|
|
245
|
+
|
|
246
|
+
@SQLiteStorageBase.handle_exceptions
|
|
247
|
+
def delete_oldest_interactions(self, count: int) -> int:
|
|
248
|
+
if count <= 0:
|
|
249
|
+
return 0
|
|
250
|
+
with self._lock:
|
|
251
|
+
rows = self.conn.execute(
|
|
252
|
+
"SELECT interaction_id FROM interactions ORDER BY created_at ASC LIMIT ?",
|
|
253
|
+
(count,),
|
|
254
|
+
).fetchall()
|
|
255
|
+
if not rows:
|
|
256
|
+
return 0
|
|
257
|
+
ids = [r["interaction_id"] for r in rows]
|
|
258
|
+
self._delete_in_chunks("interactions_fts", "rowid", ids)
|
|
259
|
+
if self._has_sqlite_vec:
|
|
260
|
+
self._delete_in_chunks("interactions_vec", "rowid", ids)
|
|
261
|
+
self._delete_in_chunks("interactions", "interaction_id", ids)
|
|
262
|
+
self.conn.commit()
|
|
263
|
+
return len(ids)
|