claude-smart 0.2.47 → 0.2.49
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 +6 -2
- package/bin/claude-smart.js +289 -56
- 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/opencode/dist/server.mjs +60 -2
- package/plugin/opencode/server.mts +64 -2
- package/plugin/pyproject.toml +2 -2
- package/plugin/scripts/_lib.sh +58 -6
- package/plugin/scripts/backend-service.sh +15 -10
- package/plugin/scripts/codex-hook.js +16 -4
- package/plugin/scripts/dashboard-service.sh +1 -1
- package/plugin/scripts/ensure-plugin-root.sh +106 -8
- package/plugin/scripts/opencode-claude-compat.js +8 -1
- package/plugin/scripts/smart-install.sh +101 -20
- package/plugin/src/README.md +1 -1
- package/plugin/src/claude_smart/cli.py +79 -29
- package/plugin/src/claude_smart/env_config.py +53 -11
- package/plugin/uv.lock +5 -5
- 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/cli/README.md +3 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +40 -6
- 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/entities.py +18 -0
- 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 +148 -3277
- 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 +72 -1817
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +56 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +183 -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/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 +320 -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/durable_learning/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/durable_learning/scheduler.py +142 -0
- package/plugin/vendor/reflexio/reflexio/server/services/durable_learning/worker.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +24 -41
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +335 -113
- 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/profile/service.py +44 -22
- 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 +31 -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 +196 -353
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +0 -1513
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_learning_jobs.py +379 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +17 -6
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +7 -1281
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +8 -3
- 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 +216 -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 +22 -10
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +8 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +25 -12
- 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 +308 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_profile_store.py +920 -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 -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/_commit_scope.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_learning_jobs.py +219 -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/profiles/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_interaction_store.py +95 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/{_profiles.py → profiles/_profile_store.py} +60 -80
- 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
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from ._agent_run_store import AgentRunStoreABC
|
|
2
|
+
from ._pending_tool_call_store import PendingToolCallStoreABC
|
|
3
|
+
from ._run_tool_dependency_store import RunToolDependencyStoreABC
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"AgentRunStoreABC",
|
|
7
|
+
"PendingToolCallStoreABC",
|
|
8
|
+
"RunToolDependencyStoreABC",
|
|
9
|
+
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Backend-neutral AgentRunStore contract (the AgentRunStore bucket).
|
|
2
|
+
|
|
3
|
+
Extracted verbatim from ``_agent_run.py`` (the AgentRunStore bucket): the seven
|
|
4
|
+
agent-run lifecycle methods. The residual ``AgentRunMixin`` composite stays
|
|
5
|
+
composed alongside this class and holds the remaining pending-tool-call /
|
|
6
|
+
run-tool-dependency stubs plus the shared ``build_scope_hash`` /
|
|
7
|
+
``human_feedback_scope`` / ``build_pending_tool_call_dedup_key`` staticmethods.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from ._models import AgentRunRecord, AgentRunStatus
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AgentRunStoreABC:
|
|
19
|
+
"""Backend-neutral agent-run lifecycle store contract."""
|
|
20
|
+
|
|
21
|
+
def create_agent_run(self, record: AgentRunRecord) -> AgentRunRecord:
|
|
22
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
23
|
+
|
|
24
|
+
def get_agent_run(self, run_id: str) -> AgentRunRecord | None:
|
|
25
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
26
|
+
|
|
27
|
+
def update_agent_run_status(
|
|
28
|
+
self,
|
|
29
|
+
run_id: str,
|
|
30
|
+
status: AgentRunStatus,
|
|
31
|
+
*,
|
|
32
|
+
committed_output: dict[str, Any] | None = None,
|
|
33
|
+
pending_tool_call_ids: list[str] | None = None,
|
|
34
|
+
max_steps_remaining: int | None = None,
|
|
35
|
+
next_resume_at: datetime | None = None,
|
|
36
|
+
last_error: str | None = None,
|
|
37
|
+
increment_finalization_attempts: bool = False,
|
|
38
|
+
expected_statuses: tuple[AgentRunStatus, ...] | None = None,
|
|
39
|
+
) -> AgentRunRecord | None:
|
|
40
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
41
|
+
|
|
42
|
+
def fail_running_agent_runs_for_request(
|
|
43
|
+
self,
|
|
44
|
+
*,
|
|
45
|
+
org_id: str,
|
|
46
|
+
extractor_kind: str,
|
|
47
|
+
user_id: str | None,
|
|
48
|
+
request_id: str,
|
|
49
|
+
last_error: str,
|
|
50
|
+
) -> int:
|
|
51
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
52
|
+
|
|
53
|
+
def claim_ready_agent_run(
|
|
54
|
+
self,
|
|
55
|
+
*,
|
|
56
|
+
org_id: str,
|
|
57
|
+
worker_id: str,
|
|
58
|
+
now: datetime | None = None,
|
|
59
|
+
claim_ttl_seconds: int = 600,
|
|
60
|
+
) -> AgentRunRecord | None:
|
|
61
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
62
|
+
|
|
63
|
+
def claim_finalization_failed_agent_run(
|
|
64
|
+
self,
|
|
65
|
+
*,
|
|
66
|
+
org_id: str,
|
|
67
|
+
worker_id: str,
|
|
68
|
+
now: datetime | None = None,
|
|
69
|
+
claim_ttl_seconds: int = 600,
|
|
70
|
+
) -> AgentRunRecord | None:
|
|
71
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
72
|
+
|
|
73
|
+
def list_resumable_work_org_ids(
|
|
74
|
+
self,
|
|
75
|
+
*,
|
|
76
|
+
now: datetime | None = None,
|
|
77
|
+
limit: int = 1000,
|
|
78
|
+
) -> list[str]:
|
|
79
|
+
"""Return distinct org_ids that have actionable resumable-extraction work.
|
|
80
|
+
|
|
81
|
+
Cross-org maintenance query (intentionally NOT scoped to ``self.org_id``):
|
|
82
|
+
the resume scheduler uses it to discover every org that has a run ready
|
|
83
|
+
to resume, a run awaiting finalization retry, or a pending tool call that
|
|
84
|
+
can be expired, so per-org workers can be driven for all of them.
|
|
85
|
+
"""
|
|
86
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_models.py
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Shared storage types and helpers for resumable extraction agent runs.
|
|
2
|
+
|
|
3
|
+
Leaf module (imports NO mixin, so it never participates in an import cycle).
|
|
4
|
+
The three ``agent_run`` ABC sub-mixins and the residual ``AgentRunMixin``
|
|
5
|
+
composite import their records/enums/helpers from here.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import hashlib
|
|
11
|
+
import json
|
|
12
|
+
import re
|
|
13
|
+
import unicodedata
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from datetime import datetime
|
|
16
|
+
from enum import StrEnum
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from reflexio.models.api_schema.pending_tool_call_schema import PendingToolCallStatus
|
|
20
|
+
|
|
21
|
+
_WHITESPACE_RE = re.compile(r"\s+")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AgentRunStatus(StrEnum):
|
|
25
|
+
RUNNING = "running"
|
|
26
|
+
AGENT_COMPLETED = "agent_completed"
|
|
27
|
+
FINALIZING = "finalizing"
|
|
28
|
+
FINALIZED = "finalized"
|
|
29
|
+
FINALIZED_PENDING_TOOL = "finalized_pending_tool"
|
|
30
|
+
RESUME_READY = "resume_ready"
|
|
31
|
+
RESUMING = "resuming"
|
|
32
|
+
FINALIZATION_FAILED = "finalization_failed"
|
|
33
|
+
FAILED = "failed"
|
|
34
|
+
EXPIRED = "expired"
|
|
35
|
+
CANCELLED = "cancelled"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
NOT_APPLICABLE_ANSWER = "User does not have information about this question."
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class RunToolDependencyKind(StrEnum):
|
|
42
|
+
FOLLOWUP = "followup"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class AgentBinding:
|
|
47
|
+
"""Logical run binding flattened into `_agent_runs` storage columns."""
|
|
48
|
+
|
|
49
|
+
org_id: str
|
|
50
|
+
extractor_kind: str
|
|
51
|
+
user_id: str | None
|
|
52
|
+
request_id: str
|
|
53
|
+
agent_version: str | None
|
|
54
|
+
source: str | None
|
|
55
|
+
source_interaction_ids: list[int] = field(default_factory=list)
|
|
56
|
+
window_start_interaction_id: int | None = None
|
|
57
|
+
window_end_interaction_id: int | None = None
|
|
58
|
+
extractor_config_hash: str | None = None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class AgentRunRecord:
|
|
63
|
+
id: str
|
|
64
|
+
binding: AgentBinding
|
|
65
|
+
status: AgentRunStatus
|
|
66
|
+
generation_request_snapshot: dict[str, Any]
|
|
67
|
+
service_config_snapshot: dict[str, Any] | None = None
|
|
68
|
+
agent_context_snapshot: str | None = None
|
|
69
|
+
committed_output: dict[str, Any] | None = None
|
|
70
|
+
pending_tool_call_ids: list[str] = field(default_factory=list)
|
|
71
|
+
max_steps_remaining: int | None = None
|
|
72
|
+
resume_attempts: int = 0
|
|
73
|
+
finalization_attempts: int = 0
|
|
74
|
+
next_resume_at: datetime | None = None
|
|
75
|
+
claimed_by: str | None = None
|
|
76
|
+
claimed_at: datetime | None = None
|
|
77
|
+
agent_completed_at: datetime | None = None
|
|
78
|
+
finalized_at: datetime | None = None
|
|
79
|
+
created_at: datetime | None = None
|
|
80
|
+
updated_at: datetime | None = None
|
|
81
|
+
expires_at: datetime | None = None
|
|
82
|
+
last_error: str | None = None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@dataclass(frozen=True)
|
|
86
|
+
class PendingToolCallRecord:
|
|
87
|
+
id: str
|
|
88
|
+
org_id: str
|
|
89
|
+
scope: dict[str, Any]
|
|
90
|
+
scope_hash: str
|
|
91
|
+
tool_name: str
|
|
92
|
+
dedup_key: str
|
|
93
|
+
status: PendingToolCallStatus
|
|
94
|
+
question_text: str
|
|
95
|
+
args: dict[str, Any] = field(default_factory=dict)
|
|
96
|
+
tags: list[str] = field(default_factory=list)
|
|
97
|
+
user_id: str | None = None
|
|
98
|
+
answer_format: str | None = None
|
|
99
|
+
result: dict[str, Any] | None = None
|
|
100
|
+
embedding: list[float] | None = None
|
|
101
|
+
superseded_by: str | None = None
|
|
102
|
+
created_at: datetime | None = None
|
|
103
|
+
resolved_at: datetime | None = None
|
|
104
|
+
expires_at: datetime | None = None
|
|
105
|
+
cache_until: datetime | None = None
|
|
106
|
+
valid_until: datetime | None = None
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@dataclass(frozen=True)
|
|
110
|
+
class RunToolDependencyRecord:
|
|
111
|
+
run_id: str
|
|
112
|
+
pending_tool_call_id: str
|
|
113
|
+
dependency_kind: RunToolDependencyKind = RunToolDependencyKind.FOLLOWUP
|
|
114
|
+
resolved_at: datetime | None = None
|
|
115
|
+
consumed_at: datetime | None = None
|
|
116
|
+
created_at: datetime | None = None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(frozen=True)
|
|
120
|
+
class PendingToolCallUpsertResult:
|
|
121
|
+
pending_tool_call: PendingToolCallRecord
|
|
122
|
+
created: bool
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass(frozen=True)
|
|
126
|
+
class PriorAnswerMatch:
|
|
127
|
+
pending_tool_call_id: str
|
|
128
|
+
status: PendingToolCallStatus
|
|
129
|
+
question_text: str
|
|
130
|
+
result: dict[str, Any] | None
|
|
131
|
+
valid_until: datetime | None
|
|
132
|
+
answer_format: str | None = None
|
|
133
|
+
created_at: datetime | None = None
|
|
134
|
+
resolved_at: datetime | None = None
|
|
135
|
+
expires_at: datetime | None = None
|
|
136
|
+
similarity: float | None = None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def canonical_json(value: Any) -> str:
|
|
140
|
+
"""Return deterministic compact JSON for storage hashes."""
|
|
141
|
+
return json.dumps(value, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def build_scope_hash(scope: dict[str, Any]) -> str:
|
|
145
|
+
"""Stable hash for a tool scope dictionary."""
|
|
146
|
+
return hashlib.sha256(canonical_json(scope).encode("utf-8")).hexdigest()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def human_feedback_scope(org_id: str) -> dict[str, str]:
|
|
150
|
+
"""Human feedback is always org-scoped, never user-scoped."""
|
|
151
|
+
return {"org_id": org_id, "scope_kind": "org"}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def normalize_dedup_text(value: str | None) -> str:
|
|
155
|
+
"""Normalize text before pending-tool-call dedup hashing."""
|
|
156
|
+
if value is None:
|
|
157
|
+
return ""
|
|
158
|
+
normalized = unicodedata.normalize("NFKC", value)
|
|
159
|
+
normalized = _WHITESPACE_RE.sub(" ", normalized.strip())
|
|
160
|
+
return normalized.casefold()
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def build_pending_tool_call_dedup_key(
|
|
164
|
+
*,
|
|
165
|
+
tool_name: str,
|
|
166
|
+
question_text: str,
|
|
167
|
+
answer_format: str | None = None,
|
|
168
|
+
) -> str:
|
|
169
|
+
"""Stable dedup hash for a normalized tool question."""
|
|
170
|
+
parts = (
|
|
171
|
+
normalize_dedup_text(tool_name),
|
|
172
|
+
normalize_dedup_text(question_text),
|
|
173
|
+
normalize_dedup_text(answer_format),
|
|
174
|
+
)
|
|
175
|
+
return hashlib.sha256("\n".join(parts).encode("utf-8")).hexdigest()
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def not_applicable_tool_result() -> dict[str, Any]:
|
|
179
|
+
return {"answer": NOT_APPLICABLE_ANSWER, "not_applicable": True}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def is_not_applicable_tool_result(result: dict[str, Any] | None) -> bool:
|
|
183
|
+
return isinstance(result, dict) and result.get("not_applicable") is True
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def embedding_similarity(a: list[float] | None, b: list[float] | None) -> float | None:
|
|
187
|
+
"""Cosine similarity for optional embedding vectors."""
|
|
188
|
+
if not a or not b or len(a) != len(b):
|
|
189
|
+
return None
|
|
190
|
+
dot = sum(x * y for x, y in zip(a, b, strict=True))
|
|
191
|
+
mag_a_sq = sum(x * x for x in a)
|
|
192
|
+
mag_b_sq = sum(y * y for y in b)
|
|
193
|
+
if mag_a_sq == 0.0 or mag_b_sq == 0.0:
|
|
194
|
+
return None
|
|
195
|
+
return dot / ((mag_a_sq**0.5) * (mag_b_sq**0.5))
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Backend-neutral PendingToolCallStore contract (the PendingToolCallStore bucket).
|
|
2
|
+
|
|
3
|
+
Extracted verbatim from ``_agent_run.py`` (the PendingToolCallStore bucket): the
|
|
4
|
+
twelve pending-tool-call methods. The residual ``AgentRunMixin`` composite stays
|
|
5
|
+
composed alongside this class and holds the remaining run-tool-dependency stubs
|
|
6
|
+
plus the shared ``build_scope_hash`` / ``human_feedback_scope`` /
|
|
7
|
+
``build_pending_tool_call_dedup_key`` staticmethods.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from ._models import (
|
|
16
|
+
PendingToolCallRecord,
|
|
17
|
+
PendingToolCallStatus,
|
|
18
|
+
PendingToolCallUpsertResult,
|
|
19
|
+
PriorAnswerMatch,
|
|
20
|
+
RunToolDependencyRecord,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class PendingToolCallStoreABC:
|
|
25
|
+
"""Backend-neutral pending-tool-call store contract."""
|
|
26
|
+
|
|
27
|
+
def create_pending_tool_call(
|
|
28
|
+
self, record: PendingToolCallRecord
|
|
29
|
+
) -> PendingToolCallRecord:
|
|
30
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
31
|
+
|
|
32
|
+
def create_or_attach_pending_tool_call(
|
|
33
|
+
self,
|
|
34
|
+
*,
|
|
35
|
+
record: PendingToolCallRecord,
|
|
36
|
+
dependency: RunToolDependencyRecord,
|
|
37
|
+
now: datetime | None = None,
|
|
38
|
+
) -> PendingToolCallUpsertResult:
|
|
39
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
40
|
+
|
|
41
|
+
def get_pending_tool_call(self, call_id: str) -> PendingToolCallRecord | None:
|
|
42
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
43
|
+
|
|
44
|
+
def list_pending_tool_calls(
|
|
45
|
+
self,
|
|
46
|
+
*,
|
|
47
|
+
status: PendingToolCallStatus | None = None,
|
|
48
|
+
limit: int = 100,
|
|
49
|
+
) -> list[PendingToolCallRecord]:
|
|
50
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
51
|
+
|
|
52
|
+
def cancel_pending_tool_call(
|
|
53
|
+
self,
|
|
54
|
+
call_id: str,
|
|
55
|
+
*,
|
|
56
|
+
cancelled_at: datetime | None = None,
|
|
57
|
+
) -> PendingToolCallRecord | None:
|
|
58
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
59
|
+
|
|
60
|
+
def expire_pending_tool_calls(
|
|
61
|
+
self,
|
|
62
|
+
*,
|
|
63
|
+
now: datetime | None = None,
|
|
64
|
+
limit: int = 100,
|
|
65
|
+
) -> int:
|
|
66
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
67
|
+
|
|
68
|
+
def delete_expired_pending_tool_calls(
|
|
69
|
+
self,
|
|
70
|
+
*,
|
|
71
|
+
now: int,
|
|
72
|
+
grace_seconds: int,
|
|
73
|
+
limit: int = 1000,
|
|
74
|
+
) -> int:
|
|
75
|
+
"""Physically delete terminal 'expired'-status rows past the grace window.
|
|
76
|
+
|
|
77
|
+
Only rows with ``status = 'expired'`` (the terminal marker set by
|
|
78
|
+
``expire_pending_tool_calls``) are candidates. RESOLVED rows are never
|
|
79
|
+
deleted — even if their ``expires_at`` is in the past — because their
|
|
80
|
+
``valid_until`` may still be live and their cached result is needed by
|
|
81
|
+
resumable extraction resume paths.
|
|
82
|
+
|
|
83
|
+
The deletion cutoff is ``now - grace_seconds`` expressed as an ISO-8601
|
|
84
|
+
string (``expires_at`` is stored as TEXT/ISO in SQLite and as
|
|
85
|
+
``timestamp with time zone`` in Postgres).
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
now: Current Unix epoch seconds.
|
|
89
|
+
grace_seconds: Extra TTL buffer; a row is only deleted if its
|
|
90
|
+
``expires_at < datetime(now - grace_seconds)``.
|
|
91
|
+
limit: Maximum rows to delete in one call (default 1000).
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Number of rows actually deleted.
|
|
95
|
+
"""
|
|
96
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
97
|
+
|
|
98
|
+
def find_active_pending_tool_call(
|
|
99
|
+
self,
|
|
100
|
+
*,
|
|
101
|
+
org_id: str,
|
|
102
|
+
scope_hash: str,
|
|
103
|
+
tool_name: str,
|
|
104
|
+
dedup_key: str,
|
|
105
|
+
now: datetime | None = None,
|
|
106
|
+
) -> PendingToolCallRecord | None:
|
|
107
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
108
|
+
|
|
109
|
+
def search_prior_tool_calls(
|
|
110
|
+
self,
|
|
111
|
+
*,
|
|
112
|
+
org_id: str,
|
|
113
|
+
scope_hash: str,
|
|
114
|
+
tool_name: str,
|
|
115
|
+
query_embedding: list[float] | None = None,
|
|
116
|
+
now: datetime | None = None,
|
|
117
|
+
limit: int = 8,
|
|
118
|
+
) -> list[PriorAnswerMatch]:
|
|
119
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
120
|
+
|
|
121
|
+
def resolve_pending_tool_call(
|
|
122
|
+
self,
|
|
123
|
+
call_id: str,
|
|
124
|
+
*,
|
|
125
|
+
result: dict[str, Any],
|
|
126
|
+
resolved_at: datetime | None = None,
|
|
127
|
+
valid_for_seconds: int,
|
|
128
|
+
) -> PendingToolCallRecord | None:
|
|
129
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
130
|
+
|
|
131
|
+
def update_resolved_pending_tool_call_result(
|
|
132
|
+
self,
|
|
133
|
+
call_id: str,
|
|
134
|
+
*,
|
|
135
|
+
result: dict[str, Any],
|
|
136
|
+
resolved_at: datetime | None = None,
|
|
137
|
+
valid_for_seconds: int,
|
|
138
|
+
) -> PendingToolCallRecord | None:
|
|
139
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
140
|
+
|
|
141
|
+
def mark_pending_tool_call_not_applicable(
|
|
142
|
+
self,
|
|
143
|
+
call_id: str,
|
|
144
|
+
*,
|
|
145
|
+
resolved_at: datetime | None = None,
|
|
146
|
+
valid_for_seconds: int,
|
|
147
|
+
) -> PendingToolCallRecord | None:
|
|
148
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Backend-neutral RunToolDependencyStore contract (the RunToolDependencyStore bucket).
|
|
2
|
+
|
|
3
|
+
Extracted verbatim from ``_agent_run.py`` (the RunToolDependencyStore bucket):
|
|
4
|
+
the four run-tool-dependency methods. This is the LAST bucket — after this
|
|
5
|
+
extraction all twenty-three agent-run methods live in the three ``agent_run``
|
|
6
|
+
sub-mixins and the residual ``_agent_run.py`` module is helpers-only. The
|
|
7
|
+
composite ``AgentRunMixin`` now inherits all three ABCs and retains only the
|
|
8
|
+
shared ``build_scope_hash`` / ``human_feedback_scope`` /
|
|
9
|
+
``build_pending_tool_call_dedup_key`` staticmethods.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from ._models import RunToolDependencyRecord
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RunToolDependencyStoreABC:
|
|
18
|
+
"""Backend-neutral run-tool-dependency store contract."""
|
|
19
|
+
|
|
20
|
+
def attach_run_tool_dependency(
|
|
21
|
+
self, record: RunToolDependencyRecord
|
|
22
|
+
) -> RunToolDependencyRecord:
|
|
23
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
24
|
+
|
|
25
|
+
def count_unresolved_followup_dependencies(
|
|
26
|
+
self,
|
|
27
|
+
*,
|
|
28
|
+
org_id: str,
|
|
29
|
+
extractor_kind: str,
|
|
30
|
+
tool_name: str,
|
|
31
|
+
) -> int:
|
|
32
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
33
|
+
|
|
34
|
+
def list_run_tool_dependencies(self, run_id: str) -> list[RunToolDependencyRecord]:
|
|
35
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
|
36
|
+
|
|
37
|
+
def consume_run_tool_dependencies(self, run_id: str) -> int:
|
|
38
|
+
raise NotImplementedError(f"{type(self).__name__} does not support agent runs")
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from ._audit import AuditEventStoreMixin
|
|
2
|
+
from ._erase_execution import GovernanceEraseExecutionMixin
|
|
3
|
+
from ._purge import PurgeOperationStoreMixin
|
|
4
|
+
from ._rebuild_hide import RebuildHideMixin
|
|
5
|
+
from ._subject_barrier import SubjectBarrierMixin
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"AuditEventStoreMixin",
|
|
9
|
+
"GovernanceEraseExecutionMixin",
|
|
10
|
+
"PurgeOperationStoreMixin",
|
|
11
|
+
"RebuildHideMixin",
|
|
12
|
+
"SubjectBarrierMixin",
|
|
13
|
+
]
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_audit.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
|
|
5
|
+
from reflexio.models.api_schema.domain.governance import AuditEvent
|
|
6
|
+
from reflexio.models.config_schema import GovernanceRetentionConfig
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AuditEventStoreMixin(ABC):
|
|
10
|
+
"""Backend-neutral audit-event store contract.
|
|
11
|
+
|
|
12
|
+
Extracted verbatim from ``_governance.py`` (the AuditEventStore bucket). The
|
|
13
|
+
residual ``GovernanceMixin`` ABC stays composed alongside this mixin and
|
|
14
|
+
holds the remaining purge / barrier abstract methods.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def append_audit_event(self, event: AuditEvent) -> bool:
|
|
19
|
+
raise NotImplementedError
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def list_audit_events(
|
|
23
|
+
self, subject_ref: str | None = None, *, org_id: str | None = None
|
|
24
|
+
) -> list[AuditEvent]:
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def gc_governance_retention(self, *, config: GovernanceRetentionConfig) -> int:
|
|
29
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class GovernanceEraseExecutionMixin(ABC):
|
|
12
|
+
"""Backend-neutral governance-erase-execution store contract.
|
|
13
|
+
|
|
14
|
+
Extracted verbatim from ``_governance.py`` (the GovernanceEraseExecution
|
|
15
|
+
bucket). The residual ``GovernanceMixin`` ABC stays composed alongside this
|
|
16
|
+
mixin and holds the remaining rebuild-hide / agent-playbook-rebuild abstract
|
|
17
|
+
methods.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def apply_governance_user_data_delete(
|
|
22
|
+
self, purge_id: str, user_id: str
|
|
23
|
+
) -> dict[str, int]:
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def complete_purge_operation_with_audit(
|
|
28
|
+
self, purge_id: str, audit_event: AuditEvent
|
|
29
|
+
) -> PurgeOperation:
|
|
30
|
+
raise NotImplementedError
|
package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_purge.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from reflexio.models.api_schema.domain.governance import (
|
|
7
|
+
PurgeOperation,
|
|
8
|
+
PurgeOperationTarget,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PurgeOperationStoreMixin(ABC):
|
|
13
|
+
"""Backend-neutral purge-operation store contract.
|
|
14
|
+
|
|
15
|
+
Extracted verbatim from ``_governance.py`` (the PurgeOperationStore bucket).
|
|
16
|
+
The residual ``GovernanceMixin`` ABC stays composed alongside this mixin and
|
|
17
|
+
holds the remaining rebuild-hide / governance-erase-execution / barrier
|
|
18
|
+
abstract methods.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def begin_purge_operation(
|
|
23
|
+
self,
|
|
24
|
+
purge_id: str,
|
|
25
|
+
idempotency_key: str,
|
|
26
|
+
operation_type: Literal["user_erasure", "org_purge"],
|
|
27
|
+
scope_type: Literal["user", "org"],
|
|
28
|
+
subject_ref: str | None,
|
|
29
|
+
request_ref: str,
|
|
30
|
+
) -> PurgeOperation:
|
|
31
|
+
raise NotImplementedError
|
|
32
|
+
|
|
33
|
+
@abstractmethod
|
|
34
|
+
def record_purge_target(
|
|
35
|
+
self,
|
|
36
|
+
purge_id: str,
|
|
37
|
+
target_name: str,
|
|
38
|
+
phase: str,
|
|
39
|
+
status: Literal["pending", "running", "failed", "complete"],
|
|
40
|
+
target_ref: str = "",
|
|
41
|
+
detail: dict[str, object] | None = None,
|
|
42
|
+
deleted_count: int = 0,
|
|
43
|
+
error_detail: str | None = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
def list_purge_targets(
|
|
49
|
+
self, purge_id: str, phase: str | None = None
|
|
50
|
+
) -> list[PurgeOperationTarget]:
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def purge_targets_prepared(self, purge_id: str) -> bool:
|
|
55
|
+
raise NotImplementedError
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def prepare_governance_erase_targets(
|
|
59
|
+
self,
|
|
60
|
+
purge_id: str,
|
|
61
|
+
user_id: str,
|
|
62
|
+
owned_user_playbook_ids: set[int] | None = None,
|
|
63
|
+
) -> None:
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def fail_purge_operation(
|
|
68
|
+
self, purge_id: str, error_code: str, error_detail: str
|
|
69
|
+
) -> PurgeOperation:
|
|
70
|
+
raise NotImplementedError
|
|
71
|
+
|
|
72
|
+
@abstractmethod
|
|
73
|
+
def get_purge_operation(self, purge_id: str) -> PurgeOperation:
|
|
74
|
+
raise NotImplementedError
|
|
@@ -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
|