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,288 @@
|
|
|
1
|
+
"""Process-local queue for learning work after async publish persistence."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import queue
|
|
7
|
+
import threading
|
|
8
|
+
import time
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
|
|
11
|
+
from reflexio.server.cache.reflexio_cache import get_reflexio
|
|
12
|
+
from reflexio.server.env_utils import env_str
|
|
13
|
+
from reflexio.server.operation_limiter import operation_limit, operation_limit_value
|
|
14
|
+
from reflexio.server.services.generation_service import GenerationService
|
|
15
|
+
from reflexio.server.usage_metrics import record_usage_event
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
_DEFAULT_QUEUE_WARN_SIZE = 1000
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _env_int(name: str, default: int, *, minimum: int = 1) -> int:
|
|
23
|
+
raw = env_str(name, str(default))
|
|
24
|
+
try:
|
|
25
|
+
return max(minimum, int(raw))
|
|
26
|
+
except ValueError:
|
|
27
|
+
logger.warning("Invalid %s=%r; using %s", name, raw, default)
|
|
28
|
+
return max(minimum, default)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class PublishLearningJob:
|
|
33
|
+
"""Metadata needed to run post-persist publish learning."""
|
|
34
|
+
|
|
35
|
+
org_id: str
|
|
36
|
+
user_id: str
|
|
37
|
+
request_id: str
|
|
38
|
+
session_id: str | None
|
|
39
|
+
source: str | None
|
|
40
|
+
agent_version: str
|
|
41
|
+
force_extraction: bool
|
|
42
|
+
skip_aggregation: bool
|
|
43
|
+
enqueued_at: float = field(default_factory=time.monotonic)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class PublishLearningWorker:
|
|
47
|
+
"""Process-local worker pool for deferred publish learning."""
|
|
48
|
+
|
|
49
|
+
def __init__(
|
|
50
|
+
self,
|
|
51
|
+
*,
|
|
52
|
+
queue_warn_size: int | None = None,
|
|
53
|
+
worker_count: int | None = None,
|
|
54
|
+
) -> None:
|
|
55
|
+
default_workers = operation_limit_value("publish")
|
|
56
|
+
self.queue_warn_size = (
|
|
57
|
+
queue_warn_size
|
|
58
|
+
if queue_warn_size is not None
|
|
59
|
+
else _env_int(
|
|
60
|
+
"REFLEXIO_PUBLISH_LEARNING_QUEUE_WARN_SIZE",
|
|
61
|
+
_DEFAULT_QUEUE_WARN_SIZE,
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
self.worker_count = (
|
|
65
|
+
worker_count
|
|
66
|
+
if worker_count is not None
|
|
67
|
+
else _env_int("REFLEXIO_PUBLISH_LEARNING_WORKERS", default_workers)
|
|
68
|
+
)
|
|
69
|
+
self._queue: queue.Queue[PublishLearningJob] = queue.Queue()
|
|
70
|
+
self._stop_event = threading.Event()
|
|
71
|
+
self._threads: list[threading.Thread] = []
|
|
72
|
+
self._started = False
|
|
73
|
+
self._start_lock = threading.Lock()
|
|
74
|
+
|
|
75
|
+
def start(self) -> None:
|
|
76
|
+
with self._start_lock:
|
|
77
|
+
if self._started:
|
|
78
|
+
return
|
|
79
|
+
self._stop_event.clear()
|
|
80
|
+
self._threads = [
|
|
81
|
+
threading.Thread(
|
|
82
|
+
target=self._worker_loop,
|
|
83
|
+
name=f"publish-learning-worker-{idx}",
|
|
84
|
+
daemon=True,
|
|
85
|
+
)
|
|
86
|
+
for idx in range(self.worker_count)
|
|
87
|
+
]
|
|
88
|
+
for thread in self._threads:
|
|
89
|
+
thread.start()
|
|
90
|
+
self._started = True
|
|
91
|
+
logger.info(
|
|
92
|
+
"event=publish_learning_worker_started workers=%d queue_warn_size=%d",
|
|
93
|
+
self.worker_count,
|
|
94
|
+
self.queue_warn_size,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def enqueue(self, job: PublishLearningJob) -> bool:
|
|
98
|
+
self.start()
|
|
99
|
+
self._queue.put_nowait(job)
|
|
100
|
+
queue_depth = self._queue.qsize()
|
|
101
|
+
if queue_depth >= self.queue_warn_size:
|
|
102
|
+
record_usage_event(
|
|
103
|
+
org_id=job.org_id,
|
|
104
|
+
user_id=job.user_id,
|
|
105
|
+
request_id=job.request_id,
|
|
106
|
+
session_id=job.session_id,
|
|
107
|
+
source=job.source,
|
|
108
|
+
agent_version=job.agent_version,
|
|
109
|
+
event_name="learning_queue_pressure",
|
|
110
|
+
event_category="publish_learning",
|
|
111
|
+
outcome="queued",
|
|
112
|
+
metadata={
|
|
113
|
+
"queue_depth": queue_depth,
|
|
114
|
+
"queue_warn_size": self.queue_warn_size,
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
logger.warning(
|
|
118
|
+
"event=publish_learning_queue_pressure org_id=%s user_id=%s "
|
|
119
|
+
"request_id=%s queue_depth=%d queue_warn_size=%d",
|
|
120
|
+
job.org_id,
|
|
121
|
+
job.user_id,
|
|
122
|
+
job.request_id,
|
|
123
|
+
queue_depth,
|
|
124
|
+
self.queue_warn_size,
|
|
125
|
+
)
|
|
126
|
+
logger.info(
|
|
127
|
+
"event=publish_learning_enqueued org_id=%s user_id=%s request_id=%s "
|
|
128
|
+
"queue_depth=%d queue_warn_size=%d",
|
|
129
|
+
job.org_id,
|
|
130
|
+
job.user_id,
|
|
131
|
+
job.request_id,
|
|
132
|
+
queue_depth,
|
|
133
|
+
self.queue_warn_size,
|
|
134
|
+
)
|
|
135
|
+
return True
|
|
136
|
+
|
|
137
|
+
def stop(self, timeout: float | None = 5.0) -> None:
|
|
138
|
+
self._stop_event.set()
|
|
139
|
+
deadline = None if timeout is None else time.monotonic() + timeout
|
|
140
|
+
for thread in list(self._threads):
|
|
141
|
+
remaining = (
|
|
142
|
+
None if deadline is None else max(0.0, deadline - time.monotonic())
|
|
143
|
+
)
|
|
144
|
+
thread.join(timeout=remaining)
|
|
145
|
+
if all(not thread.is_alive() for thread in self._threads):
|
|
146
|
+
self._threads = []
|
|
147
|
+
self._started = False
|
|
148
|
+
logger.info("event=publish_learning_worker_stopped")
|
|
149
|
+
|
|
150
|
+
def _worker_loop(self) -> None:
|
|
151
|
+
while not self._stop_event.is_set() or not self._queue.empty():
|
|
152
|
+
try:
|
|
153
|
+
job = self._queue.get(timeout=0.25)
|
|
154
|
+
except queue.Empty:
|
|
155
|
+
continue
|
|
156
|
+
try:
|
|
157
|
+
self._process_job(job)
|
|
158
|
+
finally:
|
|
159
|
+
self._queue.task_done()
|
|
160
|
+
|
|
161
|
+
def _process_job(self, job: PublishLearningJob) -> None:
|
|
162
|
+
try:
|
|
163
|
+
with operation_limit(
|
|
164
|
+
job.org_id,
|
|
165
|
+
"publish",
|
|
166
|
+
wait_forever=False,
|
|
167
|
+
log_timeout=False,
|
|
168
|
+
):
|
|
169
|
+
reflexio = get_reflexio(org_id=job.org_id)
|
|
170
|
+
GenerationService(
|
|
171
|
+
llm_client=reflexio.llm_client,
|
|
172
|
+
request_context=reflexio.request_context,
|
|
173
|
+
).run_deferred_learning(
|
|
174
|
+
user_id=job.user_id,
|
|
175
|
+
request_id=job.request_id,
|
|
176
|
+
session_id=job.session_id,
|
|
177
|
+
source=job.source,
|
|
178
|
+
agent_version=job.agent_version,
|
|
179
|
+
force_extraction=job.force_extraction,
|
|
180
|
+
skip_aggregation=job.skip_aggregation,
|
|
181
|
+
)
|
|
182
|
+
except TimeoutError:
|
|
183
|
+
self._requeue_after_limiter_timeout(job)
|
|
184
|
+
return
|
|
185
|
+
except Exception as exc:
|
|
186
|
+
record_usage_event(
|
|
187
|
+
org_id=job.org_id,
|
|
188
|
+
user_id=job.user_id,
|
|
189
|
+
request_id=job.request_id,
|
|
190
|
+
session_id=job.session_id,
|
|
191
|
+
source=job.source,
|
|
192
|
+
agent_version=job.agent_version,
|
|
193
|
+
event_name="learning_failed",
|
|
194
|
+
event_category="publish_learning",
|
|
195
|
+
outcome="failed",
|
|
196
|
+
error_kind=type(exc).__name__,
|
|
197
|
+
)
|
|
198
|
+
logger.exception(
|
|
199
|
+
"event=publish_learning_failed org_id=%s user_id=%s request_id=%s",
|
|
200
|
+
job.org_id,
|
|
201
|
+
job.user_id,
|
|
202
|
+
job.request_id,
|
|
203
|
+
)
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
record_usage_event(
|
|
207
|
+
org_id=job.org_id,
|
|
208
|
+
user_id=job.user_id,
|
|
209
|
+
request_id=job.request_id,
|
|
210
|
+
session_id=job.session_id,
|
|
211
|
+
source=job.source,
|
|
212
|
+
agent_version=job.agent_version,
|
|
213
|
+
event_name="learning_succeeded",
|
|
214
|
+
event_category="publish_learning",
|
|
215
|
+
outcome="success",
|
|
216
|
+
)
|
|
217
|
+
logger.info(
|
|
218
|
+
"event=publish_learning_done org_id=%s user_id=%s request_id=%s "
|
|
219
|
+
"queue_depth=%d",
|
|
220
|
+
job.org_id,
|
|
221
|
+
job.user_id,
|
|
222
|
+
job.request_id,
|
|
223
|
+
self._queue.qsize(),
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def _requeue_after_limiter_timeout(self, job: PublishLearningJob) -> None:
|
|
227
|
+
self._queue.put_nowait(job)
|
|
228
|
+
|
|
229
|
+
record_usage_event(
|
|
230
|
+
org_id=job.org_id,
|
|
231
|
+
user_id=job.user_id,
|
|
232
|
+
request_id=job.request_id,
|
|
233
|
+
session_id=job.session_id,
|
|
234
|
+
source=job.source,
|
|
235
|
+
agent_version=job.agent_version,
|
|
236
|
+
event_name="learning_requeued_limiter_busy",
|
|
237
|
+
event_category="publish_learning",
|
|
238
|
+
outcome="requeued",
|
|
239
|
+
metadata={
|
|
240
|
+
"age_seconds": self._job_age_seconds(job),
|
|
241
|
+
"queue_depth": self._queue.qsize(),
|
|
242
|
+
},
|
|
243
|
+
)
|
|
244
|
+
logger.info(
|
|
245
|
+
"event=publish_learning_requeued_limiter_busy org_id=%s user_id=%s "
|
|
246
|
+
"request_id=%s queue_depth=%d age_seconds=%.3f",
|
|
247
|
+
job.org_id,
|
|
248
|
+
job.user_id,
|
|
249
|
+
job.request_id,
|
|
250
|
+
self._queue.qsize(),
|
|
251
|
+
self._job_age_seconds(job),
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
@staticmethod
|
|
255
|
+
def _job_age_seconds(job: PublishLearningJob) -> float:
|
|
256
|
+
return time.monotonic() - job.enqueued_at
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
_worker: PublishLearningWorker | None = None
|
|
260
|
+
_worker_lock = threading.Lock()
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def get_publish_learning_worker() -> PublishLearningWorker:
|
|
264
|
+
global _worker # noqa: PLW0603
|
|
265
|
+
if _worker is None:
|
|
266
|
+
with _worker_lock:
|
|
267
|
+
if _worker is None:
|
|
268
|
+
_worker = PublishLearningWorker()
|
|
269
|
+
return _worker
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def enqueue_publish_learning(job: PublishLearningJob) -> bool:
|
|
273
|
+
return get_publish_learning_worker().enqueue(job)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def stop_publish_learning_worker(timeout: float | None = 5.0) -> None:
|
|
277
|
+
global _worker # noqa: PLW0603
|
|
278
|
+
worker = _worker
|
|
279
|
+
if worker is not None:
|
|
280
|
+
worker.stop(timeout=timeout)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def reset_publish_learning_worker_for_tests() -> None:
|
|
284
|
+
global _worker # noqa: PLW0603
|
|
285
|
+
worker = _worker
|
|
286
|
+
if worker is not None:
|
|
287
|
+
worker.stop(timeout=0.1)
|
|
288
|
+
_worker = None
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from ._agent_run import SQLiteAgentRunMixin
|
|
2
1
|
from ._base import (
|
|
3
2
|
SQLiteStorageBase,
|
|
4
3
|
_cosine_similarity,
|
|
@@ -6,12 +5,12 @@ from ._base import (
|
|
|
6
5
|
_sanitize_fts_query,
|
|
7
6
|
_true_rrf_merge,
|
|
8
7
|
_vector_rank_rows,
|
|
8
|
+
parse_status,
|
|
9
9
|
)
|
|
10
10
|
from ._extras import ExtrasMixin
|
|
11
11
|
from ._governance import SQLiteGovernanceMixin
|
|
12
12
|
from ._lineage import SQLiteLineageMixin
|
|
13
13
|
from ._operations import OperationMixin
|
|
14
|
-
from ._profiles import ProfileMixin
|
|
15
14
|
from ._requests import RequestMixin
|
|
16
15
|
from ._shadow_verdicts import ShadowVerdictsMixin as SQLiteShadowVerdictsMixin
|
|
17
16
|
from ._share_links import SQLiteShareLinkMixin
|
|
@@ -25,6 +24,19 @@ from ._stall_state import (
|
|
|
25
24
|
mark_stall_notified,
|
|
26
25
|
upsert_stall_state,
|
|
27
26
|
)
|
|
27
|
+
from .agent_run import (
|
|
28
|
+
SQLiteAgentRunStoreMixin,
|
|
29
|
+
SQLitePendingToolCallStoreMixin,
|
|
30
|
+
SQLiteRunToolDependencyStoreMixin,
|
|
31
|
+
)
|
|
32
|
+
from .base import SQLiteDeletionMixin, SQLiteFtsVecMixin
|
|
33
|
+
from .governance import (
|
|
34
|
+
AuditEventStoreMixin,
|
|
35
|
+
GovernanceEraseExecutionMixin,
|
|
36
|
+
PurgeOperationStoreMixin,
|
|
37
|
+
RebuildHideMixin,
|
|
38
|
+
SubjectBarrierMixin,
|
|
39
|
+
)
|
|
28
40
|
from .playbook import (
|
|
29
41
|
AgentEvaluationResultStoreMixin,
|
|
30
42
|
AgentPlaybookStoreMixin,
|
|
@@ -32,17 +44,27 @@ from .playbook import (
|
|
|
32
44
|
PlaybookSourceLinkageMixin,
|
|
33
45
|
UserPlaybookStoreMixin,
|
|
34
46
|
)
|
|
47
|
+
from .profiles import InteractionStoreMixin, ProfileSearchMixin, ProfileStoreMixin
|
|
35
48
|
|
|
36
49
|
|
|
37
50
|
class SQLiteStorage(
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
SQLiteAgentRunStoreMixin,
|
|
52
|
+
SQLitePendingToolCallStoreMixin,
|
|
53
|
+
SQLiteRunToolDependencyStoreMixin,
|
|
54
|
+
ProfileStoreMixin,
|
|
55
|
+
InteractionStoreMixin,
|
|
56
|
+
ProfileSearchMixin,
|
|
40
57
|
RequestMixin,
|
|
41
58
|
AgentPlaybookStoreMixin,
|
|
42
59
|
UserPlaybookStoreMixin,
|
|
43
60
|
PlaybookSourceLinkageMixin,
|
|
44
61
|
OptimizationJobStoreMixin,
|
|
45
62
|
AgentEvaluationResultStoreMixin,
|
|
63
|
+
AuditEventStoreMixin,
|
|
64
|
+
PurgeOperationStoreMixin,
|
|
65
|
+
SubjectBarrierMixin,
|
|
66
|
+
GovernanceEraseExecutionMixin,
|
|
67
|
+
RebuildHideMixin,
|
|
46
68
|
SQLiteGovernanceMixin,
|
|
47
69
|
SQLiteLineageMixin,
|
|
48
70
|
OperationMixin,
|
|
@@ -50,6 +72,8 @@ class SQLiteStorage(
|
|
|
50
72
|
SQLiteShareLinkMixin,
|
|
51
73
|
SQLiteStallStateMixin,
|
|
52
74
|
SQLiteShadowVerdictsMixin,
|
|
75
|
+
SQLiteDeletionMixin,
|
|
76
|
+
SQLiteFtsVecMixin,
|
|
53
77
|
SQLiteStorageBase,
|
|
54
78
|
):
|
|
55
79
|
"""SQLite-based storage with FTS5 and hybrid search."""
|
|
@@ -64,6 +88,7 @@ __all__ = [
|
|
|
64
88
|
"_sanitize_fts_query",
|
|
65
89
|
"_true_rrf_merge",
|
|
66
90
|
"_vector_rank_rows",
|
|
91
|
+
"parse_status",
|
|
67
92
|
"StallReason",
|
|
68
93
|
"StallState",
|
|
69
94
|
"clear_stall_state",
|