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,32 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class RebuildHideMixin(ABC):
|
|
7
|
+
"""Backend-neutral governance rebuild-hide store contract.
|
|
8
|
+
|
|
9
|
+
Extracted verbatim from ``_governance.py`` (the RebuildHide bucket): the two
|
|
10
|
+
public methods (``hide_governance_agent_playbooks_for_rebuild``,
|
|
11
|
+
``apply_governance_agent_playbook_rebuild``). The residual ``GovernanceMixin``
|
|
12
|
+
ABC stays composed alongside this mixin.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@abstractmethod
|
|
16
|
+
def hide_governance_agent_playbooks_for_rebuild(self, purge_id: str) -> list[int]:
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def apply_governance_agent_playbook_rebuild(
|
|
21
|
+
self,
|
|
22
|
+
purge_id: str,
|
|
23
|
+
agent_playbook_id: int,
|
|
24
|
+
remaining_source_windows: list[dict[str, object]],
|
|
25
|
+
content: str | None,
|
|
26
|
+
trigger: str | None,
|
|
27
|
+
rationale: str | None,
|
|
28
|
+
blocking_issue: dict[str, object] | None,
|
|
29
|
+
expanded_terms: str | None,
|
|
30
|
+
tags: list[str] | None,
|
|
31
|
+
) -> None:
|
|
32
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from reflexio.models.api_schema.domain.governance import (
|
|
6
|
+
AuditEvent,
|
|
7
|
+
PurgeOperation,
|
|
8
|
+
SubjectWriteBarrier,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SubjectBarrierMixin(ABC):
|
|
13
|
+
"""Backend-neutral subject-erasure-barrier store contract.
|
|
14
|
+
|
|
15
|
+
Extracted verbatim from ``_governance.py`` (the SubjectBarrier bucket). The
|
|
16
|
+
residual ``GovernanceMixin`` ABC stays composed alongside this mixin and
|
|
17
|
+
holds the remaining rebuild-hide / governance-erase-execution / purge-complete
|
|
18
|
+
abstract methods.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def begin_subject_erasure_barrier(
|
|
23
|
+
self, subject_ref: str, purge_id: str
|
|
24
|
+
) -> SubjectWriteBarrier:
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def assert_subject_writable(self, subject_ref: str) -> None:
|
|
29
|
+
raise NotImplementedError
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def complete_subject_erasure_barrier_after_empty_check(
|
|
33
|
+
self, purge_id: str, audit_event: AuditEvent
|
|
34
|
+
) -> PurgeOperation:
|
|
35
|
+
raise NotImplementedError
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def fail_subject_erasure_barrier(
|
|
39
|
+
self,
|
|
40
|
+
subject_ref: str,
|
|
41
|
+
purge_id: str,
|
|
42
|
+
error_code: str,
|
|
43
|
+
error_detail: str,
|
|
44
|
+
) -> SubjectWriteBarrier:
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def get_subject_write_barrier(self, subject_ref: str) -> SubjectWriteBarrier | None:
|
|
49
|
+
raise NotImplementedError
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from ._agent import AgentPlaybookStoreMixin
|
|
2
|
+
from ._eval_results import AgentEvaluationResultStoreMixin
|
|
3
|
+
from ._optimization import OptimizationJobStoreMixin
|
|
4
|
+
from ._source_linkage import PlaybookSourceLinkageMixin
|
|
5
|
+
from ._user import UserPlaybookStoreMixin
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"AgentEvaluationResultStoreMixin",
|
|
9
|
+
"AgentPlaybookStoreMixin",
|
|
10
|
+
"OptimizationJobStoreMixin",
|
|
11
|
+
"PlaybookSourceLinkageMixin",
|
|
12
|
+
"UserPlaybookStoreMixin",
|
|
13
|
+
]
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_agent.py
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"""Abstract agent playbook CRUD + search declarations."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from abc import abstractmethod
|
|
5
|
+
|
|
6
|
+
from reflexio.models.api_schema.common import BlockingIssue
|
|
7
|
+
from reflexio.models.api_schema.domain import (
|
|
8
|
+
AgentPlaybook,
|
|
9
|
+
PlaybookStatus,
|
|
10
|
+
Status,
|
|
11
|
+
)
|
|
12
|
+
from reflexio.models.api_schema.domain.entities import LineageEvent
|
|
13
|
+
from reflexio.models.api_schema.retriever_schema import (
|
|
14
|
+
SearchAgentPlaybookRequest,
|
|
15
|
+
)
|
|
16
|
+
from reflexio.models.config_schema import SearchOptions
|
|
17
|
+
from reflexio.server.tracing import capture_anomaly
|
|
18
|
+
|
|
19
|
+
from .._playbook import AGGREGATE_REASON_PREFIX
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
_AGGREGATE_EVENT_EMIT_ATTEMPTS = 3
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AgentPlaybookStoreMixin:
|
|
27
|
+
"""Abstract agent playbook CRUD + search methods."""
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def save_agent_playbooks(
|
|
31
|
+
self, agent_playbooks: list[AgentPlaybook]
|
|
32
|
+
) -> list[AgentPlaybook]:
|
|
33
|
+
"""Save agent playbooks with embeddings.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
agent_playbooks (list[AgentPlaybook]): List of agent playbook objects to save
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
list[AgentPlaybook]: Saved agent playbooks with agent_playbook_id populated from storage
|
|
40
|
+
"""
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
|
|
43
|
+
def save_agent_playbook_with_aggregate_event(
|
|
44
|
+
self,
|
|
45
|
+
agent_playbook: AgentPlaybook,
|
|
46
|
+
*,
|
|
47
|
+
source_ids: list[str],
|
|
48
|
+
request_id: str,
|
|
49
|
+
run_mode: str,
|
|
50
|
+
) -> AgentPlaybook:
|
|
51
|
+
"""Persist an agent playbook AND its ``op=aggregate`` lineage event.
|
|
52
|
+
|
|
53
|
+
Backends SHOULD override this so the row insert and the event commit in ONE
|
|
54
|
+
transaction (the event is the sole record of the run->playbook membership for
|
|
55
|
+
reconstruction). This base default is a non-atomic save-then-emit fallback
|
|
56
|
+
with bounded retry + loud (level=error) on final failure.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
agent_playbook (AgentPlaybook): The playbook to persist.
|
|
60
|
+
source_ids (list[str]): IDs of the source entities that produced this playbook.
|
|
61
|
+
request_id (str): The aggregation run ID (used as the lineage event request_id).
|
|
62
|
+
run_mode (str): The aggregation run mode (e.g. ``full_archive`` or ``incremental``).
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
AgentPlaybook: The saved playbook with ``agent_playbook_id`` populated.
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
ValueError: If ``request_id`` is empty (would produce an unreconstructable event).
|
|
69
|
+
"""
|
|
70
|
+
if not request_id or not request_id.strip():
|
|
71
|
+
raise ValueError(
|
|
72
|
+
"save_agent_playbook_with_aggregate_event requires a non-empty request_id"
|
|
73
|
+
)
|
|
74
|
+
saved = self.save_agent_playbooks([agent_playbook])[0]
|
|
75
|
+
event = LineageEvent(
|
|
76
|
+
org_id=self.org_id, # type: ignore[attr-defined]
|
|
77
|
+
entity_type="agent_playbook",
|
|
78
|
+
entity_id=str(saved.agent_playbook_id),
|
|
79
|
+
op="aggregate",
|
|
80
|
+
prov_relation="wasDerivedFrom",
|
|
81
|
+
source_ids=source_ids,
|
|
82
|
+
actor="aggregator",
|
|
83
|
+
request_id=request_id,
|
|
84
|
+
reason=f"{AGGREGATE_REASON_PREFIX}{run_mode}",
|
|
85
|
+
)
|
|
86
|
+
# The row is already committed; this default is non-atomic (SQLite overrides it to
|
|
87
|
+
# make the INSERT + event one transaction). The event is the sole reconstruction signal
|
|
88
|
+
# for the run, so make the emit durable: bounded retry (idempotent on retrying the
|
|
89
|
+
# same row's emit — entity_id is a fresh autoincrement per run, so this is NOT
|
|
90
|
+
# cross-run idempotency), and on final failure fail LOUD at level=error so the gap
|
|
91
|
+
# is paged + backfillable rather than silently lost. Never raise — the playbook
|
|
92
|
+
# itself is saved and must not be lost.
|
|
93
|
+
for attempt in range(_AGGREGATE_EVENT_EMIT_ATTEMPTS):
|
|
94
|
+
try:
|
|
95
|
+
self.append_lineage_event(event) # type: ignore[attr-defined]
|
|
96
|
+
return saved
|
|
97
|
+
except Exception: # noqa: BLE001
|
|
98
|
+
logger.warning(
|
|
99
|
+
"aggregate lineage event append failed (attempt %d/%d) for agent_playbook %s",
|
|
100
|
+
attempt + 1,
|
|
101
|
+
_AGGREGATE_EVENT_EMIT_ATTEMPTS,
|
|
102
|
+
saved.agent_playbook_id,
|
|
103
|
+
exc_info=True,
|
|
104
|
+
)
|
|
105
|
+
capture_anomaly(
|
|
106
|
+
"lineage.aggregate.append_failed",
|
|
107
|
+
level="error",
|
|
108
|
+
entity_id=str(saved.agent_playbook_id),
|
|
109
|
+
org_id=self.org_id, # type: ignore[attr-defined]
|
|
110
|
+
request_id=request_id,
|
|
111
|
+
)
|
|
112
|
+
return saved
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def get_agent_playbooks(
|
|
116
|
+
self,
|
|
117
|
+
limit: int = 100,
|
|
118
|
+
playbook_name: str | None = None,
|
|
119
|
+
agent_version: str | None = None,
|
|
120
|
+
status_filter: list[Status | None] | None = None,
|
|
121
|
+
playbook_status_filter: list[PlaybookStatus] | None = None,
|
|
122
|
+
tags: list[str] | None = None,
|
|
123
|
+
agent_playbook_id: int | None = None,
|
|
124
|
+
query: str | None = None,
|
|
125
|
+
start_time: int | None = None,
|
|
126
|
+
end_time: int | None = None,
|
|
127
|
+
) -> list[AgentPlaybook]:
|
|
128
|
+
"""Get agent playbooks from storage.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
limit (int): Maximum number of agent playbooks to return
|
|
132
|
+
agent_playbook_id (int, optional): Exact agent playbook ID to retrieve.
|
|
133
|
+
query (str, optional): Case-insensitive text filter across visible fields.
|
|
134
|
+
playbook_name (str, optional): The playbook name to filter by. If None, returns all agent playbooks.
|
|
135
|
+
agent_version (str, optional): The agent version to filter by. If None, returns all versions.
|
|
136
|
+
start_time (int, optional): Unix timestamp. Only return playbooks created at or after this time.
|
|
137
|
+
end_time (int, optional): Unix timestamp. Only return playbooks created at or before this time.
|
|
138
|
+
status_filter (list[Optional[Status]], optional): List of Status values to filter by. None in the list means CURRENT status.
|
|
139
|
+
playbook_status_filter (Optional[list[PlaybookStatus]]): List of PlaybookStatus values to filter by.
|
|
140
|
+
If None, returns all playbook statuses.
|
|
141
|
+
tags (list[str], optional): Match playbooks having any of these tags.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
list[AgentPlaybook]: List of agent playbook objects
|
|
145
|
+
"""
|
|
146
|
+
raise NotImplementedError
|
|
147
|
+
|
|
148
|
+
@abstractmethod
|
|
149
|
+
def get_agent_playbook_by_id(
|
|
150
|
+
self, agent_playbook_id: int, *, include_tombstones: bool = False
|
|
151
|
+
) -> AgentPlaybook | None:
|
|
152
|
+
"""Fetch one agent playbook by primary key.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
agent_playbook_id: The agent_playbook_id to look up.
|
|
156
|
+
include_tombstones: When False (default), MERGED/SUPERSEDED rows
|
|
157
|
+
return None. Set to True for lineage resolution (resolve_current).
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
The AgentPlaybook if found and not filtered, otherwise None.
|
|
161
|
+
"""
|
|
162
|
+
raise NotImplementedError
|
|
163
|
+
|
|
164
|
+
@abstractmethod
|
|
165
|
+
def delete_all_agent_playbooks(self) -> None:
|
|
166
|
+
"""Delete all agent playbooks from storage."""
|
|
167
|
+
raise NotImplementedError
|
|
168
|
+
|
|
169
|
+
@abstractmethod
|
|
170
|
+
def delete_agent_playbook(self, agent_playbook_id: int) -> None:
|
|
171
|
+
"""Delete an agent playbook by ID.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
agent_playbook_id (int): The ID of the agent playbook to delete
|
|
175
|
+
"""
|
|
176
|
+
raise NotImplementedError
|
|
177
|
+
|
|
178
|
+
@abstractmethod
|
|
179
|
+
def delete_all_agent_playbooks_by_playbook_name(
|
|
180
|
+
self, playbook_name: str, agent_version: str | None = None
|
|
181
|
+
) -> None:
|
|
182
|
+
"""Delete all agent playbooks by playbook name from storage.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
playbook_name (str): The playbook name to delete
|
|
186
|
+
agent_version (str, optional): The agent version to filter by. If None, deletes all agent versions.
|
|
187
|
+
"""
|
|
188
|
+
raise NotImplementedError
|
|
189
|
+
|
|
190
|
+
@abstractmethod
|
|
191
|
+
def update_agent_playbook_status(
|
|
192
|
+
self, agent_playbook_id: int, playbook_status: PlaybookStatus
|
|
193
|
+
) -> None:
|
|
194
|
+
"""Update the status of a specific agent playbook.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
agent_playbook_id (int): The ID of the agent playbook to update
|
|
198
|
+
playbook_status (PlaybookStatus): The new status to set
|
|
199
|
+
|
|
200
|
+
Raises:
|
|
201
|
+
ValueError: If agent playbook with the given ID is not found
|
|
202
|
+
"""
|
|
203
|
+
raise NotImplementedError
|
|
204
|
+
|
|
205
|
+
@abstractmethod
|
|
206
|
+
def update_agent_playbook(
|
|
207
|
+
self,
|
|
208
|
+
agent_playbook_id: int,
|
|
209
|
+
playbook_name: str | None = None,
|
|
210
|
+
content: str | None = None,
|
|
211
|
+
trigger: str | None = None,
|
|
212
|
+
rationale: str | None = None,
|
|
213
|
+
blocking_issue: BlockingIssue | None = None,
|
|
214
|
+
playbook_status: PlaybookStatus | None = None,
|
|
215
|
+
tags: list[str] | None = None,
|
|
216
|
+
) -> None:
|
|
217
|
+
"""Update editable fields of an agent playbook. Only non-None fields are updated.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
agent_playbook_id (int): The ID of the agent playbook to update
|
|
221
|
+
playbook_name (str, optional): New playbook name
|
|
222
|
+
content (str, optional): New content text
|
|
223
|
+
trigger (str, optional): New trigger text
|
|
224
|
+
rationale (str, optional): New rationale text
|
|
225
|
+
blocking_issue (BlockingIssue, optional): New blocking issue
|
|
226
|
+
playbook_status (PlaybookStatus, optional): New playbook status
|
|
227
|
+
tags (list[str], optional): Replacement tags
|
|
228
|
+
|
|
229
|
+
Raises:
|
|
230
|
+
ValueError: If agent playbook with the given ID is not found
|
|
231
|
+
"""
|
|
232
|
+
raise NotImplementedError
|
|
233
|
+
|
|
234
|
+
@abstractmethod
|
|
235
|
+
def archive_agent_playbooks_by_playbook_name(
|
|
236
|
+
self, playbook_name: str, agent_version: str | None = None
|
|
237
|
+
) -> None:
|
|
238
|
+
"""Archive non-APPROVED agent playbooks by setting their status field to 'archived'.
|
|
239
|
+
APPROVED agent playbooks are left untouched to preserve user-approved playbooks.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
playbook_name (str): The playbook name to archive
|
|
243
|
+
agent_version (str, optional): The agent version to filter by. If None, archives all agent versions.
|
|
244
|
+
"""
|
|
245
|
+
raise NotImplementedError
|
|
246
|
+
|
|
247
|
+
@abstractmethod
|
|
248
|
+
def archive_agent_playbooks_by_ids(self, agent_playbook_ids: list[int]) -> None:
|
|
249
|
+
"""Archive non-APPROVED agent playbooks by IDs, setting their status field to 'archived'.
|
|
250
|
+
APPROVED agent playbooks are left untouched. No-op if agent_playbook_ids is empty.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
agent_playbook_ids (list[int]): List of agent playbook IDs to archive
|
|
254
|
+
"""
|
|
255
|
+
raise NotImplementedError
|
|
256
|
+
|
|
257
|
+
@abstractmethod
|
|
258
|
+
def supersede_agent_playbooks_by_ids(
|
|
259
|
+
self, agent_playbook_ids: list[int], request_id: str
|
|
260
|
+
) -> int:
|
|
261
|
+
"""Soft-delete agent playbooks by setting status to SUPERSEDED, emitting set-based lineage.
|
|
262
|
+
|
|
263
|
+
For each eligible id (not APPROVED, not already tombstoned), updates status to
|
|
264
|
+
SUPERSEDED and emits one status_change event under the shared request_id.
|
|
265
|
+
Atomic: mutation and event in one commit, guarded on rowcount.
|
|
266
|
+
FTS/vec rows are NOT removed.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
agent_playbook_ids (list[int]): Agent playbook ids to supersede.
|
|
270
|
+
request_id (str): Shared request id for all emitted lineage events.
|
|
271
|
+
|
|
272
|
+
Returns:
|
|
273
|
+
int: Number of agent playbooks actually updated.
|
|
274
|
+
"""
|
|
275
|
+
raise NotImplementedError
|
|
276
|
+
|
|
277
|
+
@abstractmethod
|
|
278
|
+
def supersede_agent_playbooks_by_playbook_name(
|
|
279
|
+
self, playbook_name: str, agent_version: str | None, request_id: str
|
|
280
|
+
) -> int:
|
|
281
|
+
"""Soft-delete archived agent playbooks by name/version via SUPERSEDED status.
|
|
282
|
+
|
|
283
|
+
Selects rows with playbook_name matching and status='archived', then
|
|
284
|
+
soft-supersedes each one with a status_change lineage event under request_id.
|
|
285
|
+
Atomic: one commit at the end.
|
|
286
|
+
FTS/vec rows are NOT removed.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
playbook_name (str): Playbook name to supersede.
|
|
290
|
+
agent_version (str | None): Agent version filter. None matches all versions.
|
|
291
|
+
request_id (str): Shared request id for all emitted lineage events.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
int: Number of agent playbooks actually updated.
|
|
295
|
+
"""
|
|
296
|
+
raise NotImplementedError
|
|
297
|
+
|
|
298
|
+
@abstractmethod
|
|
299
|
+
def restore_archived_agent_playbooks_by_playbook_name(
|
|
300
|
+
self, playbook_name: str, agent_version: str | None = None
|
|
301
|
+
) -> None:
|
|
302
|
+
"""Restore archived agent playbooks by setting their status field to null.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
playbook_name (str): The playbook name to restore
|
|
306
|
+
agent_version (str, optional): The agent version to filter by. If None, restores all agent versions.
|
|
307
|
+
"""
|
|
308
|
+
raise NotImplementedError
|
|
309
|
+
|
|
310
|
+
@abstractmethod
|
|
311
|
+
def restore_archived_agent_playbooks_by_ids(
|
|
312
|
+
self, agent_playbook_ids: list[int]
|
|
313
|
+
) -> None:
|
|
314
|
+
"""Restore archived agent playbooks by IDs, setting their status field to null.
|
|
315
|
+
No-op if agent_playbook_ids is empty.
|
|
316
|
+
|
|
317
|
+
Args:
|
|
318
|
+
agent_playbook_ids (list[int]): List of agent playbook IDs to restore
|
|
319
|
+
"""
|
|
320
|
+
raise NotImplementedError
|
|
321
|
+
|
|
322
|
+
@abstractmethod
|
|
323
|
+
def delete_archived_agent_playbooks_by_playbook_name(
|
|
324
|
+
self, playbook_name: str, agent_version: str | None = None
|
|
325
|
+
) -> None:
|
|
326
|
+
"""Permanently delete agent playbooks that have status='archived'.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
playbook_name (str): The playbook name to delete
|
|
330
|
+
agent_version (str, optional): The agent version to filter by. If None, deletes all agent versions.
|
|
331
|
+
"""
|
|
332
|
+
raise NotImplementedError
|
|
333
|
+
|
|
334
|
+
@abstractmethod
|
|
335
|
+
def delete_agent_playbooks_by_ids(
|
|
336
|
+
self, agent_playbook_ids: list[int], *, emit_hard_delete: bool = True
|
|
337
|
+
) -> None:
|
|
338
|
+
"""Permanently delete agent playbooks by their IDs.
|
|
339
|
+
No-op if agent_playbook_ids is empty.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
agent_playbook_ids (list[int]): List of agent playbook IDs to delete
|
|
343
|
+
emit_hard_delete: When True (default), append a ``hard_delete``
|
|
344
|
+
lineage event per id (genuine erasure). Set False for rollback
|
|
345
|
+
cleanup of a never-live row (e.g. a lost supersede CAS), so no
|
|
346
|
+
spurious audit event is recorded.
|
|
347
|
+
"""
|
|
348
|
+
raise NotImplementedError
|
|
349
|
+
|
|
350
|
+
@abstractmethod
|
|
351
|
+
def search_agent_playbooks(
|
|
352
|
+
self,
|
|
353
|
+
request: SearchAgentPlaybookRequest,
|
|
354
|
+
options: SearchOptions | None = None,
|
|
355
|
+
) -> list[AgentPlaybook]:
|
|
356
|
+
"""Search agent playbooks with advanced filtering including semantic search.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
request (SearchAgentPlaybookRequest): Search request with query, filters, and pagination
|
|
360
|
+
options (SearchOptions, optional): Engine-level search parameters (e.g. pre-computed embedding)
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
list[AgentPlaybook]: List of matching agent playbook objects
|
|
364
|
+
"""
|
|
365
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Abstract agent success evaluation result store declarations."""
|
|
2
|
+
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
|
|
5
|
+
from reflexio.models.api_schema.domain import (
|
|
6
|
+
AgentSuccessEvaluationResult,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgentEvaluationResultStoreMixin:
|
|
11
|
+
"""Abstract agent success evaluation result store methods."""
|
|
12
|
+
|
|
13
|
+
# ==============================
|
|
14
|
+
# Agent Success Evaluation methods
|
|
15
|
+
# ==============================
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def save_agent_success_evaluation_results(
|
|
19
|
+
self, results: list[AgentSuccessEvaluationResult]
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Save agent success evaluation results to storage.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
results (list[AgentSuccessEvaluationResult]): List of agent success evaluation results to save
|
|
25
|
+
"""
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
@abstractmethod
|
|
29
|
+
def get_agent_success_evaluation_results(
|
|
30
|
+
self, limit: int = 100, agent_version: str | None = None
|
|
31
|
+
) -> list[AgentSuccessEvaluationResult]:
|
|
32
|
+
"""Get agent success evaluation results from storage.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
limit (int): Maximum number of results to return
|
|
36
|
+
agent_version (str, optional): The agent version to filter by. If None, returns all results.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
list[AgentSuccessEvaluationResult]: List of agent success evaluation result objects
|
|
40
|
+
"""
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
|
|
43
|
+
def get_agent_success_evaluation_results_in_window(
|
|
44
|
+
self,
|
|
45
|
+
from_ts: int,
|
|
46
|
+
to_ts: int,
|
|
47
|
+
agent_version: str | None = None,
|
|
48
|
+
limit: int | None = None,
|
|
49
|
+
) -> list[AgentSuccessEvaluationResult]:
|
|
50
|
+
"""Return eval results in ``[from_ts, to_ts]``.
|
|
51
|
+
|
|
52
|
+
Default implementation filters the existing latest-results method.
|
|
53
|
+
SQL backends should override so callers do not depend on an arbitrary
|
|
54
|
+
latest-row cap.
|
|
55
|
+
"""
|
|
56
|
+
rows = self.get_agent_success_evaluation_results(
|
|
57
|
+
limit=limit or 10_000,
|
|
58
|
+
agent_version=agent_version,
|
|
59
|
+
)
|
|
60
|
+
return [r for r in rows if from_ts <= r.created_at <= to_ts]
|
|
61
|
+
|
|
62
|
+
def get_agent_success_evaluation_result_ids(
|
|
63
|
+
self,
|
|
64
|
+
user_id: str,
|
|
65
|
+
session_id: str,
|
|
66
|
+
evaluation_name: str,
|
|
67
|
+
agent_version: str,
|
|
68
|
+
) -> list[int]:
|
|
69
|
+
"""Return result ids for one eval identity tuple."""
|
|
70
|
+
rows = self.get_agent_success_evaluation_results(
|
|
71
|
+
limit=10_000,
|
|
72
|
+
agent_version=agent_version,
|
|
73
|
+
)
|
|
74
|
+
return [
|
|
75
|
+
r.result_id
|
|
76
|
+
for r in rows
|
|
77
|
+
if r.user_id == user_id
|
|
78
|
+
and r.session_id == session_id
|
|
79
|
+
and r.evaluation_name == evaluation_name
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
@abstractmethod
|
|
83
|
+
def delete_all_agent_success_evaluation_results(self) -> None:
|
|
84
|
+
"""Delete all agent success evaluation results from storage."""
|
|
85
|
+
raise NotImplementedError
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def delete_agent_success_evaluation_results_for_session(
|
|
89
|
+
self,
|
|
90
|
+
user_id: str,
|
|
91
|
+
session_id: str,
|
|
92
|
+
evaluation_name: str,
|
|
93
|
+
agent_version: str,
|
|
94
|
+
) -> int:
|
|
95
|
+
"""Delete stored results for (user_id, session_id, evaluation_name, agent_version).
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
user_id (str): User whose session results to clear.
|
|
99
|
+
session_id (str): Session whose results to clear.
|
|
100
|
+
evaluation_name (str): Which evaluator's results to clear.
|
|
101
|
+
agent_version (str): Agent version scope.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
int: Number of rows deleted.
|
|
105
|
+
"""
|
|
106
|
+
raise NotImplementedError
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
def delete_agent_success_evaluation_results_by_ids(
|
|
110
|
+
self, result_ids: list[int]
|
|
111
|
+
) -> int:
|
|
112
|
+
"""Delete agent success eval results matching specific result_ids.
|
|
113
|
+
|
|
114
|
+
Used by the regenerate flow to remove only the prior-run rows after the
|
|
115
|
+
new rows have been saved durably (so an LLM/save failure cannot leave
|
|
116
|
+
the session with zero rows).
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
result_ids (list[int]): Primary-key result_ids to delete.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
int: Number of rows deleted.
|
|
123
|
+
"""
|
|
124
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Abstract playbook optimization job store declarations."""
|
|
2
|
+
|
|
3
|
+
from abc import abstractmethod
|
|
4
|
+
|
|
5
|
+
from reflexio.models.api_schema.domain import (
|
|
6
|
+
PlaybookOptimizationCandidate,
|
|
7
|
+
PlaybookOptimizationEvaluation,
|
|
8
|
+
PlaybookOptimizationEvent,
|
|
9
|
+
PlaybookOptimizationJob,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class OptimizationJobStoreMixin:
|
|
14
|
+
"""Abstract playbook optimization job/candidate/evaluation store methods."""
|
|
15
|
+
|
|
16
|
+
# ==============================
|
|
17
|
+
# Playbook optimization methods
|
|
18
|
+
# ==============================
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def create_playbook_optimization_job(
|
|
22
|
+
self, job: PlaybookOptimizationJob
|
|
23
|
+
) -> PlaybookOptimizationJob:
|
|
24
|
+
"""Persist a playbook optimization job and return it with id populated."""
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def update_playbook_optimization_job(
|
|
29
|
+
self,
|
|
30
|
+
job_id: int,
|
|
31
|
+
*,
|
|
32
|
+
status: str | None = None,
|
|
33
|
+
best_candidate_id: int | None = None,
|
|
34
|
+
successor_target_id: int | None = None,
|
|
35
|
+
decision_reason: str | None = None,
|
|
36
|
+
metadata_json: str | None = None,
|
|
37
|
+
) -> None:
|
|
38
|
+
"""Update mutable fields on a playbook optimization job."""
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def insert_playbook_optimization_candidate(
|
|
43
|
+
self, candidate: PlaybookOptimizationCandidate
|
|
44
|
+
) -> PlaybookOptimizationCandidate:
|
|
45
|
+
"""Persist an optimizer candidate and return it with id populated."""
|
|
46
|
+
raise NotImplementedError
|
|
47
|
+
|
|
48
|
+
@abstractmethod
|
|
49
|
+
def list_playbook_optimization_candidates(
|
|
50
|
+
self, job_id: int
|
|
51
|
+
) -> list[PlaybookOptimizationCandidate]:
|
|
52
|
+
"""List optimizer candidates for a job."""
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def update_playbook_optimization_candidate(
|
|
57
|
+
self,
|
|
58
|
+
candidate_id: int,
|
|
59
|
+
*,
|
|
60
|
+
aggregate_score: float | None = None,
|
|
61
|
+
is_winner: bool | None = None,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Update mutable optimizer candidate result fields."""
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def insert_playbook_optimization_evaluation(
|
|
68
|
+
self, evaluation: PlaybookOptimizationEvaluation
|
|
69
|
+
) -> PlaybookOptimizationEvaluation:
|
|
70
|
+
"""Persist an optimizer evaluation and return it with id populated."""
|
|
71
|
+
raise NotImplementedError
|
|
72
|
+
|
|
73
|
+
@abstractmethod
|
|
74
|
+
def list_playbook_optimization_evaluations(
|
|
75
|
+
self, job_id: int
|
|
76
|
+
) -> list[PlaybookOptimizationEvaluation]:
|
|
77
|
+
"""List optimizer evaluations for a job."""
|
|
78
|
+
raise NotImplementedError
|
|
79
|
+
|
|
80
|
+
@abstractmethod
|
|
81
|
+
def insert_playbook_optimization_event(
|
|
82
|
+
self, event: PlaybookOptimizationEvent
|
|
83
|
+
) -> PlaybookOptimizationEvent:
|
|
84
|
+
"""Persist an optimizer callback/event and return it with id populated."""
|
|
85
|
+
raise NotImplementedError
|