claude-smart 0.2.46 → 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 +19 -11
- package/bin/claude-smart.js +290 -68
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +11 -10
- package/plugin/dashboard/app/layout.tsx +20 -0
- 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/opencode/dist/server.mjs +76 -2
- package/plugin/opencode/server.mts +79 -2
- package/plugin/pyproject.toml +6 -2
- package/plugin/scripts/smart-install.sh +7 -1
- package/plugin/src/claude_smart/cli.py +210 -22
- package/plugin/src/claude_smart/context_format.py +9 -9
- package/plugin/src/claude_smart/cs_cite.py +66 -19
- package/plugin/uv.lock +5 -5
- package/plugin/vendor/reflexio/.env.example +7 -0
- package/plugin/vendor/reflexio/README.md +3 -3
- package/plugin/vendor/reflexio/pyproject.toml +2 -1
- package/plugin/vendor/reflexio/reflexio/README.md +11 -6
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +1 -1
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +2 -2
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +44 -1
- package/plugin/vendor/reflexio/reflexio/client/client.py +97 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +8 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +15 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +23 -18
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +9 -8
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +16 -1
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +27 -16
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +27 -5
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +1 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/governance.py +117 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +45 -3
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +37 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +38 -9
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +21 -2
- package/plugin/vendor/reflexio/reflexio/server/api.py +274 -3267
- 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/api_endpoints/request_context.py +1 -1
- package/plugin/vendor/reflexio/reflexio/server/{_auth.py → auth.py} +2 -0
- 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/extensions.py +213 -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/model_defaults.py +4 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +57 -5
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +12 -1
- 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/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +14 -2
- 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 +5 -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/extraction/resume_worker.py +8 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +232 -123
- package/plugin/vendor/reflexio/reflexio/server/services/governance/config.py +52 -0
- package/plugin/vendor/reflexio/reflexio/server/services/governance/service.py +378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/governance/subject_refs.py +34 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +385 -78
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +9 -1
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/aggregation_prompt_processing.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator.py +121 -525
- 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/playbook/service.py +9 -9
- package/plugin/vendor/reflexio/reflexio/server/services/profile/components/extractor.py +3 -2
- package/plugin/vendor/reflexio/reflexio/server/services/publish_learning_worker.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/recency.py +211 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +29 -13
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +4 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/governance_validation.py +681 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +43 -6
- 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 +58 -351
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +49 -19
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +452 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +11 -4
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1 -2133
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +7 -1126
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +73 -33
- 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/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +955 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_eval_results.py +189 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_optimization.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +145 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +844 -0
- 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 +50 -9
- 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/_extras.py +4 -4
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +0 -909
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +2 -0
- 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/playbook/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_agent.py +365 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_eval_results.py +124 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_optimization.py +85 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_source_linkage.py +47 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_user.py +333 -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} +57 -86
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_search.py +32 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +153 -12
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/user_detail_stripping.py +0 -84
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Abstract agent playbook source-linkage declarations."""
|
|
2
|
+
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
|
|
6
|
+
from reflexio.models.api_schema.domain import AgentPlaybookSourceWindow
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PlaybookSourceLinkageMixin:
|
|
10
|
+
"""Abstract agent playbook source-linkage methods."""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def set_source_user_playbook_ids_for_agent_playbook(
|
|
14
|
+
self, agent_playbook_id: int, user_playbook_ids: list[int]
|
|
15
|
+
) -> None:
|
|
16
|
+
"""Persist the source user playbook ids that produced an agent playbook."""
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def get_source_user_playbook_ids_for_agent_playbook(
|
|
21
|
+
self, agent_playbook_id: int
|
|
22
|
+
) -> list[int]:
|
|
23
|
+
"""Return source user playbook ids for an agent playbook."""
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def get_source_user_playbook_ids_for_agent_playbooks(
|
|
28
|
+
self, agent_playbook_ids: Sequence[int]
|
|
29
|
+
) -> dict[int, list[int]]:
|
|
30
|
+
"""Return source user playbook ids keyed by agent playbook id."""
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def set_source_windows_for_agent_playbook(
|
|
35
|
+
self,
|
|
36
|
+
agent_playbook_id: int,
|
|
37
|
+
source_windows: list[AgentPlaybookSourceWindow],
|
|
38
|
+
) -> None:
|
|
39
|
+
"""Persist replayable source windows that produced an agent playbook."""
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def get_source_windows_for_agent_playbook(
|
|
44
|
+
self, agent_playbook_id: int
|
|
45
|
+
) -> list[AgentPlaybookSourceWindow]:
|
|
46
|
+
"""Return replayable source windows for an agent playbook."""
|
|
47
|
+
raise NotImplementedError
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_user.py
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"""Abstract user playbook CRUD + search declarations."""
|
|
2
|
+
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
|
|
5
|
+
from reflexio.models.api_schema.common import BlockingIssue
|
|
6
|
+
from reflexio.models.api_schema.domain import Status, UserPlaybook
|
|
7
|
+
from reflexio.models.api_schema.retriever_schema import SearchUserPlaybookRequest
|
|
8
|
+
from reflexio.models.config_schema import SearchOptions
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UserPlaybookStoreMixin:
|
|
12
|
+
"""Abstract user playbook CRUD + search methods."""
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def save_user_playbooks(self, user_playbooks: list[UserPlaybook]) -> None:
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def get_user_playbooks(
|
|
20
|
+
self,
|
|
21
|
+
limit: int = 100,
|
|
22
|
+
user_id: str | None = None,
|
|
23
|
+
playbook_name: str | None = None,
|
|
24
|
+
agent_version: str | None = None,
|
|
25
|
+
status_filter: list[Status | None] | None = None,
|
|
26
|
+
start_time: int | None = None,
|
|
27
|
+
end_time: int | None = None,
|
|
28
|
+
include_embedding: bool = False,
|
|
29
|
+
tags: list[str] | None = None,
|
|
30
|
+
offset: int = 0,
|
|
31
|
+
user_playbook_id: int | None = None,
|
|
32
|
+
request_id: str | None = None,
|
|
33
|
+
query: str | None = None,
|
|
34
|
+
) -> list[UserPlaybook]:
|
|
35
|
+
"""Get user playbooks from storage.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
limit (int): Maximum number of playbooks to return
|
|
39
|
+
user_playbook_id (int, optional): Exact user playbook ID to retrieve.
|
|
40
|
+
user_id (str, optional): The user ID to filter by. If None, returns playbooks for all users.
|
|
41
|
+
request_id (str, optional): Request ID that generated the playbook.
|
|
42
|
+
query (str, optional): Case-insensitive text filter across visible fields.
|
|
43
|
+
playbook_name (str, optional): The playbook name to filter by. If None, returns all user playbooks.
|
|
44
|
+
agent_version (str, optional): The agent version to filter by. If None, returns all agent versions.
|
|
45
|
+
status_filter (list[Optional[Status]], optional): List of status values to filter by.
|
|
46
|
+
Can include None (current), Status.PENDING (from rerun), Status.ARCHIVED (old).
|
|
47
|
+
If None, returns playbooks with all statuses.
|
|
48
|
+
start_time (int, optional): Unix timestamp. Only return playbooks created at or after this time.
|
|
49
|
+
end_time (int, optional): Unix timestamp. Only return playbooks created at or before this time.
|
|
50
|
+
include_embedding (bool): If True, fetch and parse embedding vectors. Defaults to False.
|
|
51
|
+
tags (list[str], optional): Match playbooks having any of these tags.
|
|
52
|
+
offset (int): Number of matching rows to skip. Defaults to 0.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
list[UserPlaybook]: List of user playbook objects
|
|
56
|
+
"""
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def count_user_playbooks(
|
|
61
|
+
self,
|
|
62
|
+
user_id: str | None = None,
|
|
63
|
+
playbook_name: str | None = None,
|
|
64
|
+
min_user_playbook_id: int | None = None,
|
|
65
|
+
agent_version: str | None = None,
|
|
66
|
+
status_filter: list[Status | None] | None = None,
|
|
67
|
+
) -> int:
|
|
68
|
+
"""Count user playbooks in storage efficiently.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
user_id (str, optional): The user ID to filter by. If None, counts playbooks for all users.
|
|
72
|
+
playbook_name (str, optional): The playbook name to filter by. If None, counts all user playbooks.
|
|
73
|
+
min_user_playbook_id (int, optional): Only count playbooks with user_playbook_id greater than this value.
|
|
74
|
+
agent_version (str, optional): The agent version to filter by. If None, counts all agent versions.
|
|
75
|
+
status_filter (list[Optional[Status]], optional): List of status values to filter by.
|
|
76
|
+
Can include None (current), Status.PENDING (from rerun), Status.ARCHIVED (old).
|
|
77
|
+
If None, returns playbooks with all statuses.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
int: Count of user playbooks matching the filters
|
|
81
|
+
"""
|
|
82
|
+
raise NotImplementedError
|
|
83
|
+
|
|
84
|
+
@abstractmethod
|
|
85
|
+
def count_user_playbooks_by_session(self, session_id: str) -> int:
|
|
86
|
+
"""Count user playbooks linked to a session via request_id -> requests.session_id.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
session_id (str): The session ID to count user playbooks for
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
int: Count of user playbooks linked to the session
|
|
93
|
+
"""
|
|
94
|
+
raise NotImplementedError
|
|
95
|
+
|
|
96
|
+
@abstractmethod
|
|
97
|
+
def delete_all_user_playbooks(self) -> None:
|
|
98
|
+
"""Delete all user playbooks from storage."""
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
@abstractmethod
|
|
102
|
+
def delete_all_user_playbooks_by_playbook_name(
|
|
103
|
+
self, playbook_name: str, agent_version: str | None = None
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Delete all user playbooks by playbook name from storage.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
playbook_name (str): The playbook name to delete
|
|
109
|
+
agent_version (str, optional): The agent version to filter by. If None, deletes all agent versions.
|
|
110
|
+
"""
|
|
111
|
+
raise NotImplementedError
|
|
112
|
+
|
|
113
|
+
@abstractmethod
|
|
114
|
+
def delete_user_playbook(self, user_playbook_id: int) -> None:
|
|
115
|
+
"""Delete a user playbook by ID.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
user_playbook_id (int): The ID of the user playbook to delete
|
|
119
|
+
"""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
def update_all_user_playbooks_status(
|
|
124
|
+
self,
|
|
125
|
+
old_status: Status | None,
|
|
126
|
+
new_status: Status | None,
|
|
127
|
+
agent_version: str | None = None,
|
|
128
|
+
playbook_name: str | None = None,
|
|
129
|
+
) -> int:
|
|
130
|
+
"""Update all user playbooks with old_status to new_status atomically.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
old_status: The current status to match (None for CURRENT)
|
|
134
|
+
new_status: The new status to set (None for CURRENT)
|
|
135
|
+
agent_version: Optional filter by agent version
|
|
136
|
+
playbook_name: Optional filter by playbook name
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
int: Number of user playbooks updated
|
|
140
|
+
"""
|
|
141
|
+
raise NotImplementedError
|
|
142
|
+
|
|
143
|
+
@abstractmethod
|
|
144
|
+
def delete_all_user_playbooks_by_status(
|
|
145
|
+
self,
|
|
146
|
+
status: Status,
|
|
147
|
+
agent_version: str | None = None,
|
|
148
|
+
playbook_name: str | None = None,
|
|
149
|
+
) -> int:
|
|
150
|
+
"""Delete all user playbooks with the given status atomically.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
status: The status of user playbooks to delete
|
|
154
|
+
agent_version: Optional filter by agent version
|
|
155
|
+
playbook_name: Optional filter by playbook name
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
int: Number of user playbooks deleted
|
|
159
|
+
"""
|
|
160
|
+
raise NotImplementedError
|
|
161
|
+
|
|
162
|
+
@abstractmethod
|
|
163
|
+
def delete_user_playbooks_by_ids(
|
|
164
|
+
self, user_playbook_ids: list[int], *, emit_hard_delete: bool = True
|
|
165
|
+
) -> int:
|
|
166
|
+
"""Delete user playbooks by their IDs.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
user_playbook_ids: List of user_playbook_id values to delete
|
|
170
|
+
emit_hard_delete: When True (default), append a ``hard_delete``
|
|
171
|
+
lineage event per id (genuine erasure). Set False for rollback
|
|
172
|
+
cleanup of a never-live row (e.g. a lost supersede CAS), so no
|
|
173
|
+
spurious audit event is recorded.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
int: Number of user playbooks deleted
|
|
177
|
+
"""
|
|
178
|
+
raise NotImplementedError
|
|
179
|
+
|
|
180
|
+
@abstractmethod
|
|
181
|
+
def get_user_playbooks_by_ids(
|
|
182
|
+
self,
|
|
183
|
+
user_id: str,
|
|
184
|
+
user_playbook_ids: list[int],
|
|
185
|
+
status_filter: list[Status | None] | None = None,
|
|
186
|
+
) -> list[UserPlaybook]:
|
|
187
|
+
"""Fetch the subset of a user's playbooks whose ids are in the list.
|
|
188
|
+
|
|
189
|
+
Server-side filter on (``user_id``, ``user_playbook_id IN (...)``)
|
|
190
|
+
so callers (e.g. the reflection service resolving a small set of
|
|
191
|
+
cited playbook ids) avoid scanning every playbook for the user.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
user_id (str): Owning user id.
|
|
195
|
+
user_playbook_ids (list[int]): Playbook ids to fetch. Empty
|
|
196
|
+
list returns ``[]`` without hitting storage.
|
|
197
|
+
status_filter (list[Status | None] | None): Statuses to
|
|
198
|
+
include. ``None`` (default) means CURRENT only — same
|
|
199
|
+
default as ``get_user_playbooks`` for consistency.
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
list[UserPlaybook]: Matching playbooks. Order is unspecified.
|
|
203
|
+
Ids that do not exist (or do not match the user / status
|
|
204
|
+
filter) are silently omitted.
|
|
205
|
+
"""
|
|
206
|
+
raise NotImplementedError
|
|
207
|
+
|
|
208
|
+
@abstractmethod
|
|
209
|
+
def get_user_playbook_by_id(
|
|
210
|
+
self, user_playbook_id: int, *, include_tombstones: bool = False
|
|
211
|
+
) -> UserPlaybook | None:
|
|
212
|
+
"""Fetch one user playbook by primary key.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
user_playbook_id: The user_playbook_id to look up.
|
|
216
|
+
include_tombstones: When False (default), MERGED/SUPERSEDED rows
|
|
217
|
+
return None. Set to True for lineage resolution (resolve_current).
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
The UserPlaybook if found and not filtered, otherwise None.
|
|
221
|
+
"""
|
|
222
|
+
raise NotImplementedError
|
|
223
|
+
|
|
224
|
+
@abstractmethod
|
|
225
|
+
def get_user_playbooks_by_ids_any_user(
|
|
226
|
+
self,
|
|
227
|
+
user_playbook_ids: list[int],
|
|
228
|
+
status_filter: list[Status | None] | None = None,
|
|
229
|
+
) -> list[UserPlaybook]:
|
|
230
|
+
"""Fetch user playbooks by ids without requiring a single owner id."""
|
|
231
|
+
raise NotImplementedError
|
|
232
|
+
|
|
233
|
+
@abstractmethod
|
|
234
|
+
def archive_user_playbook_by_id(self, user_id: str, user_playbook_id: int) -> bool:
|
|
235
|
+
"""Atomically archive a single user playbook by id, only if CURRENT.
|
|
236
|
+
|
|
237
|
+
Flips the row's ``status`` from ``None`` (CURRENT) to
|
|
238
|
+
``Status.ARCHIVED``. No-op when the playbook does not exist, has
|
|
239
|
+
a different ``user_id``, or is already non-current.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
user_id (str): Owning user id; used as a guard so callers
|
|
243
|
+
cannot accidentally archive another user's playbook.
|
|
244
|
+
user_playbook_id (int): The user_playbook_id to archive.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
bool: True if a row was archived; False otherwise.
|
|
248
|
+
"""
|
|
249
|
+
raise NotImplementedError
|
|
250
|
+
|
|
251
|
+
@abstractmethod
|
|
252
|
+
def has_user_playbooks_with_status(
|
|
253
|
+
self,
|
|
254
|
+
status: Status | None,
|
|
255
|
+
agent_version: str | None = None,
|
|
256
|
+
playbook_name: str | None = None,
|
|
257
|
+
) -> bool:
|
|
258
|
+
"""Check if any user playbooks exist with given status and filters.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
status: The status to check for (None for CURRENT)
|
|
262
|
+
agent_version: Optional filter by agent version
|
|
263
|
+
playbook_name: Optional filter by playbook name
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
bool: True if any matching user playbooks exist
|
|
267
|
+
"""
|
|
268
|
+
raise NotImplementedError
|
|
269
|
+
|
|
270
|
+
@abstractmethod
|
|
271
|
+
def update_user_playbook(
|
|
272
|
+
self,
|
|
273
|
+
user_playbook_id: int,
|
|
274
|
+
playbook_name: str | None = None,
|
|
275
|
+
content: str | None = None,
|
|
276
|
+
trigger: str | None = None,
|
|
277
|
+
rationale: str | None = None,
|
|
278
|
+
blocking_issue: BlockingIssue | None = None,
|
|
279
|
+
tags: list[str] | None = None,
|
|
280
|
+
) -> None:
|
|
281
|
+
"""Update editable fields of a user playbook. Only non-None fields are updated.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
user_playbook_id (int): The ID of the user playbook to update
|
|
285
|
+
playbook_name (str, optional): New playbook name
|
|
286
|
+
content (str, optional): New content text
|
|
287
|
+
trigger (str, optional): New trigger text
|
|
288
|
+
rationale (str, optional): New rationale text
|
|
289
|
+
blocking_issue (BlockingIssue, optional): New blocking issue
|
|
290
|
+
tags (list[str], optional): Replacement tags
|
|
291
|
+
|
|
292
|
+
Raises:
|
|
293
|
+
ValueError: If user playbook with the given ID is not found
|
|
294
|
+
"""
|
|
295
|
+
raise NotImplementedError
|
|
296
|
+
|
|
297
|
+
@abstractmethod
|
|
298
|
+
def supersede_user_playbooks_by_ids(
|
|
299
|
+
self, user_playbook_ids: list[int], request_id: str
|
|
300
|
+
) -> int:
|
|
301
|
+
"""Soft-delete user playbooks by setting status to SUPERSEDED.
|
|
302
|
+
|
|
303
|
+
Eligible rows (CURRENT, PENDING, or ARCHIVED; not already MERGED /
|
|
304
|
+
SUPERSEDED) are transitioned to SUPERSEDED and emit one status_change
|
|
305
|
+
lineage event under the shared request id. This is the user-playbook
|
|
306
|
+
analogue of the existing agent/profile soft-supersede helpers and
|
|
307
|
+
preserves dead-source content for point-in-time attribution reads.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
user_playbook_ids (list[int]): User playbook ids to supersede.
|
|
311
|
+
request_id (str): Shared request id for all emitted lineage events.
|
|
312
|
+
|
|
313
|
+
Returns:
|
|
314
|
+
int: Number of user playbooks actually updated.
|
|
315
|
+
"""
|
|
316
|
+
raise NotImplementedError
|
|
317
|
+
|
|
318
|
+
@abstractmethod
|
|
319
|
+
def search_user_playbooks(
|
|
320
|
+
self,
|
|
321
|
+
request: SearchUserPlaybookRequest,
|
|
322
|
+
options: SearchOptions | None = None,
|
|
323
|
+
) -> list[UserPlaybook]:
|
|
324
|
+
"""Search user playbooks with advanced filtering including semantic search.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
request (SearchUserPlaybookRequest): Search request with query, filters, and pagination
|
|
328
|
+
options (SearchOptions, optional): Engine-level search parameters (e.g. pre-computed embedding)
|
|
329
|
+
|
|
330
|
+
Returns:
|
|
331
|
+
list[UserPlaybook]: List of matching user playbook objects
|
|
332
|
+
"""
|
|
333
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
|
|
3
|
+
from reflexio.models.api_schema.domain import (
|
|
4
|
+
DeleteUserInteractionRequest,
|
|
5
|
+
Interaction,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InteractionStoreMixin:
|
|
10
|
+
"""Mixin for interaction-store CRUD methods."""
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def get_all_interactions(self, limit: int = 100) -> list[Interaction]:
|
|
14
|
+
raise NotImplementedError
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def get_user_interaction(self, user_id: str) -> list[Interaction]:
|
|
18
|
+
raise NotImplementedError
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def get_all_user_ids(self) -> list[str]:
|
|
22
|
+
"""Return distinct user IDs that have stored interactions."""
|
|
23
|
+
raise NotImplementedError
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def add_user_interaction(self, user_id: str, interaction: Interaction) -> None:
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def add_user_interactions_bulk(
|
|
31
|
+
self, user_id: str, interactions: list[Interaction]
|
|
32
|
+
) -> None:
|
|
33
|
+
"""Add multiple user interactions with batched embedding generation.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
user_id: The user ID
|
|
37
|
+
interactions: List of interactions to add
|
|
38
|
+
"""
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def delete_user_interaction(self, request: DeleteUserInteractionRequest) -> None:
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
|
|
45
|
+
@abstractmethod
|
|
46
|
+
def delete_all_interactions_for_user(self, user_id: str) -> None:
|
|
47
|
+
raise NotImplementedError
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def delete_all_interactions(self) -> None:
|
|
51
|
+
"""Delete all interactions across all users."""
|
|
52
|
+
raise NotImplementedError
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def count_all_interactions(self) -> int:
|
|
56
|
+
"""Count total interactions across all users.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
int: Total number of interactions
|
|
60
|
+
"""
|
|
61
|
+
raise NotImplementedError
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def delete_oldest_interactions(self, count: int) -> int:
|
|
65
|
+
"""Delete the oldest N interactions based on created_at timestamp.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
count (int): Number of oldest interactions to delete
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
int: Number of interactions actually deleted
|
|
72
|
+
"""
|
|
73
|
+
raise NotImplementedError
|
|
@@ -1,72 +1,73 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
2
|
|
|
3
3
|
from reflexio.models.api_schema.domain import (
|
|
4
|
-
DeleteUserInteractionRequest,
|
|
5
4
|
DeleteUserProfileRequest,
|
|
6
|
-
Interaction,
|
|
7
5
|
Status,
|
|
8
6
|
UserProfile,
|
|
9
7
|
)
|
|
10
|
-
from reflexio.models.api_schema.retriever_schema import (
|
|
11
|
-
SearchInteractionRequest,
|
|
12
|
-
SearchUserProfileRequest,
|
|
13
|
-
)
|
|
14
8
|
|
|
15
9
|
|
|
16
|
-
class
|
|
17
|
-
"""Mixin for profile
|
|
10
|
+
class ProfileStoreMixin:
|
|
11
|
+
"""Mixin for profile-store CRUD methods."""
|
|
18
12
|
|
|
19
|
-
# read methods
|
|
20
13
|
@abstractmethod
|
|
21
14
|
def get_all_profiles(
|
|
22
15
|
self,
|
|
23
16
|
limit: int = 100,
|
|
24
17
|
status_filter: list[Status | None] | None = None,
|
|
18
|
+
user_id: str | None = None,
|
|
19
|
+
profile_id: str | None = None,
|
|
20
|
+
query: str | None = None,
|
|
21
|
+
source: str | None = None,
|
|
22
|
+
profile_time_to_live: str | None = None,
|
|
23
|
+
start_time: int | None = None,
|
|
24
|
+
end_time: int | None = None,
|
|
25
25
|
) -> list[UserProfile]:
|
|
26
26
|
raise NotImplementedError
|
|
27
27
|
|
|
28
|
-
@abstractmethod
|
|
29
|
-
def get_all_interactions(self, limit: int = 100) -> list[Interaction]:
|
|
30
|
-
raise NotImplementedError
|
|
31
|
-
|
|
32
28
|
@abstractmethod
|
|
33
29
|
def get_user_profile(
|
|
34
30
|
self,
|
|
35
31
|
user_id: str,
|
|
36
32
|
status_filter: list[Status | None] | None = None,
|
|
37
33
|
tags: list[str] | None = None,
|
|
34
|
+
profile_id: str | None = None,
|
|
35
|
+
query: str | None = None,
|
|
36
|
+
source: str | None = None,
|
|
37
|
+
profile_time_to_live: str | None = None,
|
|
38
|
+
start_time: int | None = None,
|
|
39
|
+
end_time: int | None = None,
|
|
40
|
+
include_expired: bool = False,
|
|
38
41
|
) -> list[UserProfile]:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@abstractmethod
|
|
42
|
-
def get_user_interaction(self, user_id: str) -> list[Interaction]:
|
|
43
|
-
raise NotImplementedError
|
|
44
|
-
|
|
45
|
-
# create or update methods
|
|
46
|
-
@abstractmethod
|
|
47
|
-
def add_user_profile(self, user_id: str, user_profiles: list[UserProfile]) -> None:
|
|
48
|
-
"""Add the user profile for a given user id."""
|
|
49
|
-
raise NotImplementedError
|
|
50
|
-
|
|
51
|
-
@abstractmethod
|
|
52
|
-
def add_user_interaction(self, user_id: str, interaction: Interaction) -> None:
|
|
53
|
-
raise NotImplementedError
|
|
54
|
-
|
|
55
|
-
@abstractmethod
|
|
56
|
-
def add_user_interactions_bulk(
|
|
57
|
-
self, user_id: str, interactions: list[Interaction]
|
|
58
|
-
) -> None:
|
|
59
|
-
"""Add multiple user interactions with batched embedding generation.
|
|
42
|
+
"""Return profiles for a user, optionally including expired rows.
|
|
60
43
|
|
|
61
44
|
Args:
|
|
62
|
-
user_id: The user
|
|
63
|
-
|
|
45
|
+
user_id: The user whose profiles to return.
|
|
46
|
+
status_filter: Statuses to include (``None`` element = CURRENT).
|
|
47
|
+
Defaults to ``[None]`` (CURRENT only) when not supplied.
|
|
48
|
+
tags: If provided, only return profiles whose ``tags`` overlap.
|
|
49
|
+
profile_id: If provided, filter to this exact profile id.
|
|
50
|
+
query: Free-text substring match across content, profile_id, user_id.
|
|
51
|
+
source: If provided, filter to this exact source value.
|
|
52
|
+
profile_time_to_live: If provided, filter to this TTL value.
|
|
53
|
+
start_time: If provided, lower bound on last_modified_timestamp.
|
|
54
|
+
end_time: If provided, upper bound on last_modified_timestamp.
|
|
55
|
+
include_expired: When ``False`` (default), rows whose
|
|
56
|
+
``expiration_timestamp`` is in the past are excluded
|
|
57
|
+
(byte-for-byte prior behaviour — every existing caller is
|
|
58
|
+
unaffected). Pass ``True`` to omit the expiry filter so
|
|
59
|
+
EXPIRED tombstones (``expiration_timestamp < now``) are
|
|
60
|
+
returned. Required by ``clear_user_data`` to reach every
|
|
61
|
+
profile a user owns regardless of TTL state.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
list[UserProfile]: Matching profiles in unspecified order.
|
|
64
65
|
"""
|
|
65
66
|
raise NotImplementedError
|
|
66
67
|
|
|
67
|
-
# delete methods
|
|
68
68
|
@abstractmethod
|
|
69
|
-
def
|
|
69
|
+
def add_user_profile(self, user_id: str, user_profiles: list[UserProfile]) -> None:
|
|
70
|
+
"""Add the user profile for a given user id."""
|
|
70
71
|
raise NotImplementedError
|
|
71
72
|
|
|
72
73
|
@abstractmethod
|
|
@@ -86,10 +87,6 @@ class ProfileMixin:
|
|
|
86
87
|
"""Replace only the tags of a profile, leaving content and embedding untouched."""
|
|
87
88
|
raise NotImplementedError
|
|
88
89
|
|
|
89
|
-
@abstractmethod
|
|
90
|
-
def delete_all_interactions_for_user(self, user_id: str) -> None:
|
|
91
|
-
raise NotImplementedError
|
|
92
|
-
|
|
93
90
|
@abstractmethod
|
|
94
91
|
def delete_all_profiles_for_user(self, user_id: str) -> None:
|
|
95
92
|
raise NotImplementedError
|
|
@@ -99,20 +96,6 @@ class ProfileMixin:
|
|
|
99
96
|
"""Delete all profiles across all users."""
|
|
100
97
|
raise NotImplementedError
|
|
101
98
|
|
|
102
|
-
@abstractmethod
|
|
103
|
-
def delete_all_interactions(self) -> None:
|
|
104
|
-
"""Delete all interactions across all users."""
|
|
105
|
-
raise NotImplementedError
|
|
106
|
-
|
|
107
|
-
@abstractmethod
|
|
108
|
-
def count_all_interactions(self) -> int:
|
|
109
|
-
"""Count total interactions across all users.
|
|
110
|
-
|
|
111
|
-
Returns:
|
|
112
|
-
int: Total number of interactions
|
|
113
|
-
"""
|
|
114
|
-
raise NotImplementedError
|
|
115
|
-
|
|
116
99
|
@abstractmethod
|
|
117
100
|
def count_all_profiles(self) -> int:
|
|
118
101
|
"""Count total profiles across all users without hydrating rows.
|
|
@@ -127,18 +110,6 @@ class ProfileMixin:
|
|
|
127
110
|
"""
|
|
128
111
|
raise NotImplementedError
|
|
129
112
|
|
|
130
|
-
@abstractmethod
|
|
131
|
-
def delete_oldest_interactions(self, count: int) -> int:
|
|
132
|
-
"""Delete the oldest N interactions based on created_at timestamp.
|
|
133
|
-
|
|
134
|
-
Args:
|
|
135
|
-
count (int): Number of oldest interactions to delete
|
|
136
|
-
|
|
137
|
-
Returns:
|
|
138
|
-
int: Number of interactions actually deleted
|
|
139
|
-
"""
|
|
140
|
-
raise NotImplementedError
|
|
141
|
-
|
|
142
113
|
@abstractmethod
|
|
143
114
|
def update_all_profiles_status(
|
|
144
115
|
self,
|
|
@@ -158,6 +129,24 @@ class ProfileMixin:
|
|
|
158
129
|
"""
|
|
159
130
|
raise NotImplementedError
|
|
160
131
|
|
|
132
|
+
@abstractmethod
|
|
133
|
+
def expire_active_profiles(self, *, now: int, limit: int = 1000) -> int:
|
|
134
|
+
"""Tombstone active profiles whose TTL has elapsed.
|
|
135
|
+
|
|
136
|
+
Selects ``status IS NULL AND expiration_timestamp < now`` and transitions
|
|
137
|
+
each to ``status=EXPIRED, retired_at=now``, emitting a ``status_change``
|
|
138
|
+
lineage event (reason ``ttl-expired``). Returns the number tombstoned.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
now: Current epoch timestamp (seconds). Profiles with
|
|
142
|
+
``expiration_timestamp < now`` are tombstoned.
|
|
143
|
+
limit: Maximum number of profiles to tombstone in one call (default 1000).
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
int: Number of profiles tombstoned.
|
|
147
|
+
"""
|
|
148
|
+
raise NotImplementedError
|
|
149
|
+
|
|
161
150
|
@abstractmethod
|
|
162
151
|
def get_profiles_by_ids(
|
|
163
152
|
self,
|
|
@@ -350,21 +339,3 @@ class ProfileMixin:
|
|
|
350
339
|
commit-atomic legacy change-log "removed" entry.
|
|
351
340
|
"""
|
|
352
341
|
raise NotImplementedError
|
|
353
|
-
|
|
354
|
-
# Search methods
|
|
355
|
-
@abstractmethod
|
|
356
|
-
def search_interaction(
|
|
357
|
-
self,
|
|
358
|
-
search_interaction_request: SearchInteractionRequest,
|
|
359
|
-
query_embedding: list[float] | None = None,
|
|
360
|
-
) -> list[Interaction]:
|
|
361
|
-
raise NotImplementedError
|
|
362
|
-
|
|
363
|
-
@abstractmethod
|
|
364
|
-
def search_user_profile(
|
|
365
|
-
self,
|
|
366
|
-
search_user_profile_request: SearchUserProfileRequest,
|
|
367
|
-
status_filter: list[Status | None] | None = None,
|
|
368
|
-
query_embedding: list[float] | None = None,
|
|
369
|
-
) -> list[UserProfile]:
|
|
370
|
-
raise NotImplementedError
|