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,578 @@
|
|
|
1
|
+
"""Playbook route handlers (extracted from api.py, Tier3 A2)."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
from fastapi import (
|
|
10
|
+
APIRouter,
|
|
11
|
+
BackgroundTasks,
|
|
12
|
+
Depends,
|
|
13
|
+
Request,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from reflexio.models.api_schema.retriever_schema import (
|
|
17
|
+
GetAgentPlaybooksRequest,
|
|
18
|
+
GetAgentPlaybooksViewResponse,
|
|
19
|
+
GetPlaybookApplicationStatsRequest,
|
|
20
|
+
GetPlaybookApplicationStatsResponse,
|
|
21
|
+
GetUserPlaybooksRequest,
|
|
22
|
+
GetUserPlaybooksViewResponse,
|
|
23
|
+
UpdateAgentPlaybookRequest,
|
|
24
|
+
UpdateAgentPlaybookResponse,
|
|
25
|
+
UpdatePlaybookStatusRequest,
|
|
26
|
+
UpdatePlaybookStatusResponse,
|
|
27
|
+
UpdateUserPlaybookRequest,
|
|
28
|
+
UpdateUserPlaybookResponse,
|
|
29
|
+
)
|
|
30
|
+
from reflexio.models.api_schema.service_schemas import (
|
|
31
|
+
AddAgentPlaybookRequest,
|
|
32
|
+
AddAgentPlaybookResponse,
|
|
33
|
+
AddUserPlaybookRequest,
|
|
34
|
+
AddUserPlaybookResponse,
|
|
35
|
+
BulkDeleteResponse,
|
|
36
|
+
DeleteAgentPlaybookRequest,
|
|
37
|
+
DeleteAgentPlaybookResponse,
|
|
38
|
+
DeleteAgentPlaybooksByIdsRequest,
|
|
39
|
+
DeleteUserPlaybookRequest,
|
|
40
|
+
DeleteUserPlaybookResponse,
|
|
41
|
+
DeleteUserPlaybooksByIdsRequest,
|
|
42
|
+
DowngradeUserPlaybooksRequest,
|
|
43
|
+
DowngradeUserPlaybooksResponse,
|
|
44
|
+
ManualPlaybookGenerationRequest,
|
|
45
|
+
ManualPlaybookGenerationResponse,
|
|
46
|
+
PlaybookAggregationChangeLogResponse,
|
|
47
|
+
RerunPlaybookGenerationRequest,
|
|
48
|
+
RerunPlaybookGenerationResponse,
|
|
49
|
+
RunPlaybookAggregationRequest,
|
|
50
|
+
RunPlaybookAggregationResponse,
|
|
51
|
+
UpgradeUserPlaybooksRequest,
|
|
52
|
+
UpgradeUserPlaybooksResponse,
|
|
53
|
+
)
|
|
54
|
+
from reflexio.models.api_schema.ui.converters import (
|
|
55
|
+
to_agent_playbook_view,
|
|
56
|
+
to_user_playbook_view,
|
|
57
|
+
)
|
|
58
|
+
from reflexio.server.api_endpoints import (
|
|
59
|
+
publisher_api,
|
|
60
|
+
)
|
|
61
|
+
from reflexio.server.auth import (
|
|
62
|
+
default_billing_gate,
|
|
63
|
+
default_get_caller_type,
|
|
64
|
+
default_get_org_id,
|
|
65
|
+
)
|
|
66
|
+
from reflexio.server.cache import reflexio_cache
|
|
67
|
+
from reflexio.server.rate_limit import limiter
|
|
68
|
+
from reflexio.server.routes._common import _run_limited_api
|
|
69
|
+
from reflexio.server.routes._metering import (
|
|
70
|
+
_meter_applied_learnings,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
logger = logging.getLogger(__name__)
|
|
74
|
+
router = APIRouter()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@router.post(
|
|
78
|
+
"/api/add_user_playbook",
|
|
79
|
+
response_model=AddUserPlaybookResponse,
|
|
80
|
+
response_model_exclude_none=True,
|
|
81
|
+
)
|
|
82
|
+
@limiter.limit("60/minute") # Rate limit for write operations
|
|
83
|
+
def add_user_playbook_endpoint(
|
|
84
|
+
request: Request,
|
|
85
|
+
payload: AddUserPlaybookRequest,
|
|
86
|
+
org_id: str = Depends(default_get_org_id),
|
|
87
|
+
) -> AddUserPlaybookResponse:
|
|
88
|
+
"""Add user playbook directly to storage.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
request (Request): The HTTP request object (for rate limiting)
|
|
92
|
+
payload (AddUserPlaybookRequest): The request containing user playbooks
|
|
93
|
+
org_id (str): Organization ID
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
AddUserPlaybookResponse: Response containing success status, message, and added count
|
|
97
|
+
"""
|
|
98
|
+
return publisher_api.add_user_playbook(org_id=org_id, request=payload)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@router.post(
|
|
102
|
+
"/api/add_agent_playbook",
|
|
103
|
+
response_model=AddAgentPlaybookResponse,
|
|
104
|
+
response_model_exclude_none=True,
|
|
105
|
+
)
|
|
106
|
+
@limiter.limit("60/minute") # Rate limit for write operations
|
|
107
|
+
def add_agent_playbook_endpoint(
|
|
108
|
+
request: Request,
|
|
109
|
+
payload: AddAgentPlaybookRequest,
|
|
110
|
+
org_id: str = Depends(default_get_org_id),
|
|
111
|
+
) -> AddAgentPlaybookResponse:
|
|
112
|
+
"""Add agent playbook directly to storage.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
request (Request): The HTTP request object (for rate limiting)
|
|
116
|
+
payload (AddAgentPlaybookRequest): The request containing agent playbooks
|
|
117
|
+
org_id (str): Organization ID
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
AddAgentPlaybookResponse: Response containing success status, message, and added count
|
|
121
|
+
"""
|
|
122
|
+
return publisher_api.add_agent_playbook(org_id=org_id, request=payload)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@router.get(
|
|
126
|
+
"/api/playbook_aggregation_change_logs",
|
|
127
|
+
response_model=PlaybookAggregationChangeLogResponse,
|
|
128
|
+
)
|
|
129
|
+
def get_playbook_aggregation_change_logs(
|
|
130
|
+
playbook_name: str,
|
|
131
|
+
agent_version: str,
|
|
132
|
+
org_id: str = Depends(default_get_org_id),
|
|
133
|
+
) -> PlaybookAggregationChangeLogResponse:
|
|
134
|
+
return reflexio_cache.get_reflexio(
|
|
135
|
+
org_id=org_id
|
|
136
|
+
).get_playbook_aggregation_change_logs(
|
|
137
|
+
playbook_name=playbook_name,
|
|
138
|
+
agent_version=agent_version,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@router.delete(
|
|
143
|
+
"/api/delete_agent_playbook",
|
|
144
|
+
response_model=DeleteAgentPlaybookResponse,
|
|
145
|
+
response_model_exclude_none=True,
|
|
146
|
+
)
|
|
147
|
+
def delete_agent_playbook(
|
|
148
|
+
request: DeleteAgentPlaybookRequest,
|
|
149
|
+
org_id: str = Depends(default_get_org_id),
|
|
150
|
+
) -> DeleteAgentPlaybookResponse:
|
|
151
|
+
return publisher_api.delete_agent_playbook(org_id=org_id, request=request)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@router.delete(
|
|
155
|
+
"/api/delete_user_playbook",
|
|
156
|
+
response_model=DeleteUserPlaybookResponse,
|
|
157
|
+
response_model_exclude_none=True,
|
|
158
|
+
)
|
|
159
|
+
def delete_user_playbook(
|
|
160
|
+
request: DeleteUserPlaybookRequest,
|
|
161
|
+
org_id: str = Depends(default_get_org_id),
|
|
162
|
+
) -> DeleteUserPlaybookResponse:
|
|
163
|
+
return publisher_api.delete_user_playbook(org_id=org_id, request=request)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@router.delete(
|
|
167
|
+
"/api/delete_agent_playbooks_by_ids",
|
|
168
|
+
response_model=BulkDeleteResponse,
|
|
169
|
+
response_model_exclude_none=True,
|
|
170
|
+
)
|
|
171
|
+
def delete_agent_playbooks_by_ids(
|
|
172
|
+
request: DeleteAgentPlaybooksByIdsRequest,
|
|
173
|
+
org_id: str = Depends(default_get_org_id),
|
|
174
|
+
) -> BulkDeleteResponse:
|
|
175
|
+
"""Delete multiple agent playbooks by their IDs.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
request (DeleteAgentPlaybooksByIdsRequest): Request containing list of agent playbook IDs to delete
|
|
179
|
+
org_id (str): Organization ID
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
183
|
+
"""
|
|
184
|
+
return publisher_api.delete_agent_playbooks_by_ids_bulk(
|
|
185
|
+
org_id=org_id, request=request
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@router.delete(
|
|
190
|
+
"/api/delete_user_playbooks_by_ids",
|
|
191
|
+
response_model=BulkDeleteResponse,
|
|
192
|
+
response_model_exclude_none=True,
|
|
193
|
+
)
|
|
194
|
+
def delete_user_playbooks_by_ids(
|
|
195
|
+
request: DeleteUserPlaybooksByIdsRequest,
|
|
196
|
+
org_id: str = Depends(default_get_org_id),
|
|
197
|
+
) -> BulkDeleteResponse:
|
|
198
|
+
"""Delete multiple user playbooks by their IDs.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
request (DeleteUserPlaybooksByIdsRequest): Request containing list of user playbook IDs to delete
|
|
202
|
+
org_id (str): Organization ID
|
|
203
|
+
|
|
204
|
+
Returns:
|
|
205
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
206
|
+
"""
|
|
207
|
+
return publisher_api.delete_user_playbooks_by_ids_bulk(
|
|
208
|
+
org_id=org_id, request=request
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
@router.delete(
|
|
213
|
+
"/api/delete_all_playbooks",
|
|
214
|
+
response_model=BulkDeleteResponse,
|
|
215
|
+
response_model_exclude_none=True,
|
|
216
|
+
)
|
|
217
|
+
@limiter.limit("10/minute")
|
|
218
|
+
def delete_all_playbooks(
|
|
219
|
+
request: Request,
|
|
220
|
+
org_id: str = Depends(default_get_org_id),
|
|
221
|
+
) -> BulkDeleteResponse:
|
|
222
|
+
"""Delete all playbooks (both user and agent).
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
org_id (str): Organization ID
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
229
|
+
"""
|
|
230
|
+
return publisher_api.delete_all_playbooks_bulk(org_id=org_id)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
@router.delete(
|
|
234
|
+
"/api/delete_all_user_playbooks",
|
|
235
|
+
response_model=BulkDeleteResponse,
|
|
236
|
+
response_model_exclude_none=True,
|
|
237
|
+
)
|
|
238
|
+
@limiter.limit("10/minute")
|
|
239
|
+
def delete_all_user_playbooks(
|
|
240
|
+
request: Request,
|
|
241
|
+
org_id: str = Depends(default_get_org_id),
|
|
242
|
+
) -> BulkDeleteResponse:
|
|
243
|
+
"""Delete all user playbooks (user only, not agent).
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
org_id (str): Organization ID
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
250
|
+
"""
|
|
251
|
+
return publisher_api.delete_all_user_playbooks_bulk(org_id=org_id)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@router.delete(
|
|
255
|
+
"/api/delete_all_agent_playbooks",
|
|
256
|
+
response_model=BulkDeleteResponse,
|
|
257
|
+
response_model_exclude_none=True,
|
|
258
|
+
)
|
|
259
|
+
@limiter.limit("10/minute")
|
|
260
|
+
def delete_all_agent_playbooks(
|
|
261
|
+
request: Request,
|
|
262
|
+
org_id: str = Depends(default_get_org_id),
|
|
263
|
+
) -> BulkDeleteResponse:
|
|
264
|
+
"""Delete all agent playbooks (agent only, not user).
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
org_id (str): Organization ID
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
BulkDeleteResponse: Response containing success status and deleted count
|
|
271
|
+
"""
|
|
272
|
+
return publisher_api.delete_all_agent_playbooks_bulk(org_id=org_id)
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@router.post(
|
|
276
|
+
"/api/run_playbook_aggregation",
|
|
277
|
+
response_model=RunPlaybookAggregationResponse,
|
|
278
|
+
response_model_exclude_none=True,
|
|
279
|
+
)
|
|
280
|
+
@limiter.limit("10/minute") # Strict limit for expensive operations
|
|
281
|
+
def run_playbook_aggregation(
|
|
282
|
+
request: Request,
|
|
283
|
+
payload: RunPlaybookAggregationRequest,
|
|
284
|
+
org_id: str = Depends(default_get_org_id),
|
|
285
|
+
) -> RunPlaybookAggregationResponse:
|
|
286
|
+
return _run_limited_api(
|
|
287
|
+
org_id,
|
|
288
|
+
"aggregation",
|
|
289
|
+
lambda: publisher_api.run_playbook_aggregation(org_id=org_id, request=payload),
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
@router.post(
|
|
294
|
+
"/api/get_user_playbooks",
|
|
295
|
+
response_model=GetUserPlaybooksViewResponse,
|
|
296
|
+
response_model_exclude_none=True,
|
|
297
|
+
)
|
|
298
|
+
def get_user_playbooks(
|
|
299
|
+
request: GetUserPlaybooksRequest,
|
|
300
|
+
org_id: str = Depends(default_get_org_id),
|
|
301
|
+
) -> GetUserPlaybooksViewResponse:
|
|
302
|
+
"""Get user playbooks with internal fields filtered out.
|
|
303
|
+
|
|
304
|
+
Args:
|
|
305
|
+
request (GetUserPlaybooksRequest): The get request
|
|
306
|
+
org_id (str): Organization ID
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
GetUserPlaybooksViewResponse: Response containing user playbooks without internal fields
|
|
310
|
+
"""
|
|
311
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
312
|
+
response = reflexio.get_user_playbooks(request)
|
|
313
|
+
return GetUserPlaybooksViewResponse(
|
|
314
|
+
success=response.success,
|
|
315
|
+
user_playbooks=[to_user_playbook_view(rf) for rf in response.user_playbooks],
|
|
316
|
+
msg=response.msg,
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
@router.post(
|
|
321
|
+
"/api/get_agent_playbooks",
|
|
322
|
+
response_model=GetAgentPlaybooksViewResponse,
|
|
323
|
+
response_model_exclude_none=True,
|
|
324
|
+
)
|
|
325
|
+
@limiter.limit("120/minute") # Rate limit for read operations
|
|
326
|
+
def get_agent_playbooks(
|
|
327
|
+
request: Request,
|
|
328
|
+
payload: GetAgentPlaybooksRequest,
|
|
329
|
+
org_id: str = Depends(default_get_org_id),
|
|
330
|
+
caller_type: str = Depends(default_get_caller_type),
|
|
331
|
+
_gate: None = Depends(default_billing_gate("application")), # noqa: B008
|
|
332
|
+
) -> GetAgentPlaybooksViewResponse:
|
|
333
|
+
"""Get agent playbooks with internal fields filtered out.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
request (Request): The HTTP request object (for rate limiting)
|
|
337
|
+
payload (GetAgentPlaybooksRequest): The get request
|
|
338
|
+
org_id (str): Organization ID
|
|
339
|
+
caller_type (str): Billing caller classification (injected via dependency).
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
GetAgentPlaybooksViewResponse: Response containing agent playbooks without internal fields
|
|
343
|
+
"""
|
|
344
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
345
|
+
response = reflexio.get_agent_playbooks(payload)
|
|
346
|
+
resp = GetAgentPlaybooksViewResponse(
|
|
347
|
+
success=response.success,
|
|
348
|
+
agent_playbooks=[to_agent_playbook_view(fb) for fb in response.agent_playbooks],
|
|
349
|
+
msg=response.msg,
|
|
350
|
+
)
|
|
351
|
+
_meter_applied_learnings(
|
|
352
|
+
org_id=org_id,
|
|
353
|
+
caller_type=caller_type,
|
|
354
|
+
surfaced_count=len(resp.agent_playbooks),
|
|
355
|
+
request_id=getattr(payload, "request_id", None),
|
|
356
|
+
session_id=getattr(payload, "session_id", None),
|
|
357
|
+
)
|
|
358
|
+
return resp
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
@router.put(
|
|
362
|
+
"/api/update_agent_playbook_status",
|
|
363
|
+
response_model=UpdatePlaybookStatusResponse,
|
|
364
|
+
response_model_exclude_none=True,
|
|
365
|
+
)
|
|
366
|
+
def update_agent_playbook_status_endpoint(
|
|
367
|
+
request: UpdatePlaybookStatusRequest,
|
|
368
|
+
org_id: str = Depends(default_get_org_id),
|
|
369
|
+
) -> UpdatePlaybookStatusResponse:
|
|
370
|
+
"""Update the status of a specific playbook.
|
|
371
|
+
|
|
372
|
+
Args:
|
|
373
|
+
request (UpdatePlaybookStatusRequest): The update request
|
|
374
|
+
org_id (str): Organization ID
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
UpdatePlaybookStatusResponse: Response containing success status and message
|
|
378
|
+
"""
|
|
379
|
+
return publisher_api.update_agent_playbook_status(org_id=org_id, request=request)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@router.put(
|
|
383
|
+
"/api/update_agent_playbook",
|
|
384
|
+
response_model=UpdateAgentPlaybookResponse,
|
|
385
|
+
response_model_exclude_none=True,
|
|
386
|
+
)
|
|
387
|
+
def update_agent_playbook_endpoint(
|
|
388
|
+
request: UpdateAgentPlaybookRequest,
|
|
389
|
+
org_id: str = Depends(default_get_org_id),
|
|
390
|
+
) -> UpdateAgentPlaybookResponse:
|
|
391
|
+
"""Update editable fields of a specific agent playbook.
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
request (UpdateAgentPlaybookRequest): The update request
|
|
395
|
+
org_id (str): Organization ID
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
UpdateAgentPlaybookResponse: Response containing success status and message
|
|
399
|
+
"""
|
|
400
|
+
return publisher_api.update_agent_playbook(org_id=org_id, request=request)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
@router.put(
|
|
404
|
+
"/api/update_user_playbook",
|
|
405
|
+
response_model=UpdateUserPlaybookResponse,
|
|
406
|
+
response_model_exclude_none=True,
|
|
407
|
+
)
|
|
408
|
+
def update_user_playbook_endpoint(
|
|
409
|
+
request: UpdateUserPlaybookRequest,
|
|
410
|
+
org_id: str = Depends(default_get_org_id),
|
|
411
|
+
) -> UpdateUserPlaybookResponse:
|
|
412
|
+
"""Update editable fields of a specific user playbook.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
request (UpdateUserPlaybookRequest): The update request
|
|
416
|
+
org_id (str): Organization ID
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
UpdateUserPlaybookResponse: Response containing success status and message
|
|
420
|
+
"""
|
|
421
|
+
return publisher_api.update_user_playbook(org_id=org_id, request=request)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
@router.post(
|
|
425
|
+
"/api/get_playbook_application_stats",
|
|
426
|
+
response_model=GetPlaybookApplicationStatsResponse,
|
|
427
|
+
response_model_exclude_none=True,
|
|
428
|
+
)
|
|
429
|
+
def get_playbook_application_stats(
|
|
430
|
+
request: GetPlaybookApplicationStatsRequest,
|
|
431
|
+
org_id: str = Depends(default_get_org_id),
|
|
432
|
+
) -> GetPlaybookApplicationStatsResponse:
|
|
433
|
+
"""Get per-rule citation counts aggregated from interactions.
|
|
434
|
+
|
|
435
|
+
Returns one row per cited (kind, real_id) over the look-back window,
|
|
436
|
+
sorted by applied_count descending. Lets the dashboard show users a
|
|
437
|
+
per-rule "track record" — how often each playbook or profile has been
|
|
438
|
+
applied and when it last fired.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
request (GetPlaybookApplicationStatsRequest): Request containing
|
|
442
|
+
days_back.
|
|
443
|
+
org_id (str): Organization ID.
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
GetPlaybookApplicationStatsResponse: Response containing aggregated
|
|
447
|
+
stats.
|
|
448
|
+
"""
|
|
449
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
450
|
+
return reflexio.get_playbook_application_stats(request)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
@router.post(
|
|
454
|
+
"/api/rerun_playbook_generation",
|
|
455
|
+
response_model=RerunPlaybookGenerationResponse,
|
|
456
|
+
response_model_exclude_none=True,
|
|
457
|
+
)
|
|
458
|
+
@limiter.limit("5/minute") # Strict limit for expensive operations
|
|
459
|
+
def rerun_playbook_generation_endpoint(
|
|
460
|
+
request: Request,
|
|
461
|
+
payload: RerunPlaybookGenerationRequest,
|
|
462
|
+
background_tasks: BackgroundTasks,
|
|
463
|
+
org_id: str = Depends(default_get_org_id),
|
|
464
|
+
) -> RerunPlaybookGenerationResponse:
|
|
465
|
+
"""Rerun playbook generation with filtered interactions.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
request (Request): The HTTP request object (for rate limiting)
|
|
469
|
+
payload (RerunPlaybookGenerationRequest): Request containing agent_version, time filters, and optional playbook_name
|
|
470
|
+
background_tasks (BackgroundTasks): Background task runner
|
|
471
|
+
org_id (str): Organization ID
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
RerunPlaybookGenerationResponse: Response containing success status and playbooks generated count
|
|
475
|
+
"""
|
|
476
|
+
# Create Reflexio instance
|
|
477
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
478
|
+
|
|
479
|
+
# Run the long-running task in the background to avoid proxy timeout
|
|
480
|
+
# Client polls get_operation_status for progress
|
|
481
|
+
background_tasks.add_task(reflexio.rerun_playbook_generation, payload)
|
|
482
|
+
|
|
483
|
+
return RerunPlaybookGenerationResponse(
|
|
484
|
+
success=True, msg="Playbook generation started"
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
@router.post(
|
|
489
|
+
"/api/manual_playbook_generation",
|
|
490
|
+
response_model=ManualPlaybookGenerationResponse,
|
|
491
|
+
response_model_exclude_none=True,
|
|
492
|
+
)
|
|
493
|
+
@limiter.limit("5/minute") # Strict limit for expensive operations
|
|
494
|
+
def manual_playbook_generation_endpoint(
|
|
495
|
+
request: Request,
|
|
496
|
+
payload: ManualPlaybookGenerationRequest,
|
|
497
|
+
org_id: str = Depends(default_get_org_id),
|
|
498
|
+
) -> ManualPlaybookGenerationResponse:
|
|
499
|
+
"""Manually trigger playbook generation with window-sized interactions and CURRENT output.
|
|
500
|
+
|
|
501
|
+
Runs with auto_run=False, which bypasses the regular stride/should_run
|
|
502
|
+
gates. Only playbook extraction is triggered. Each extractor uses its own
|
|
503
|
+
window_size_override when present, falling back to the global window_size.
|
|
504
|
+
Output is CURRENT playbooks only.
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
request (Request): The HTTP request object (for rate limiting)
|
|
508
|
+
payload (ManualPlaybookGenerationRequest): Request containing agent_version, source, and playbook_name
|
|
509
|
+
org_id (str): Organization ID
|
|
510
|
+
|
|
511
|
+
Returns:
|
|
512
|
+
ManualPlaybookGenerationResponse: Response containing success status and playbooks generated count
|
|
513
|
+
"""
|
|
514
|
+
# Create Reflexio instance
|
|
515
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
516
|
+
|
|
517
|
+
# Call manual_playbook_generation
|
|
518
|
+
return reflexio.manual_playbook_generation(payload)
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
@router.post(
|
|
522
|
+
"/api/upgrade_all_user_playbooks",
|
|
523
|
+
response_model=UpgradeUserPlaybooksResponse,
|
|
524
|
+
response_model_exclude_none=True,
|
|
525
|
+
)
|
|
526
|
+
def upgrade_all_user_playbooks_endpoint(
|
|
527
|
+
request: UpgradeUserPlaybooksRequest,
|
|
528
|
+
org_id: str = Depends(default_get_org_id),
|
|
529
|
+
) -> UpgradeUserPlaybooksResponse:
|
|
530
|
+
"""Upgrade all user playbooks by deleting old ARCHIVED, archiving CURRENT, and promoting PENDING.
|
|
531
|
+
|
|
532
|
+
This operation performs three atomic steps:
|
|
533
|
+
1. Delete all ARCHIVED user playbooks (old archived from previous upgrades)
|
|
534
|
+
2. Archive all CURRENT user playbooks → ARCHIVED (save current state for potential rollback)
|
|
535
|
+
3. Promote all PENDING user playbooks → CURRENT (activate new user playbooks)
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
request (UpgradeUserPlaybooksRequest): The upgrade request with optional agent_version and playbook_name filters
|
|
539
|
+
org_id (str): Organization ID
|
|
540
|
+
|
|
541
|
+
Returns:
|
|
542
|
+
UpgradeUserPlaybooksResponse: Response containing success status and counts
|
|
543
|
+
"""
|
|
544
|
+
# Create Reflexio instance
|
|
545
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
546
|
+
|
|
547
|
+
# Call upgrade_all_user_playbooks with request
|
|
548
|
+
return reflexio.upgrade_all_user_playbooks(request=request)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
@router.post(
|
|
552
|
+
"/api/downgrade_all_user_playbooks",
|
|
553
|
+
response_model=DowngradeUserPlaybooksResponse,
|
|
554
|
+
response_model_exclude_none=True,
|
|
555
|
+
)
|
|
556
|
+
def downgrade_all_user_playbooks_endpoint(
|
|
557
|
+
request: DowngradeUserPlaybooksRequest,
|
|
558
|
+
org_id: str = Depends(default_get_org_id),
|
|
559
|
+
) -> DowngradeUserPlaybooksResponse:
|
|
560
|
+
"""Downgrade all user playbooks by archiving CURRENT and restoring ARCHIVED.
|
|
561
|
+
|
|
562
|
+
This operation performs three atomic steps:
|
|
563
|
+
1. Mark all CURRENT user playbooks → ARCHIVE_IN_PROGRESS (temporary status)
|
|
564
|
+
2. Restore all ARCHIVED user playbooks → CURRENT
|
|
565
|
+
3. Move all ARCHIVE_IN_PROGRESS user playbooks → ARCHIVED
|
|
566
|
+
|
|
567
|
+
Args:
|
|
568
|
+
request (DowngradeUserPlaybooksRequest): The downgrade request with optional agent_version and playbook_name filters
|
|
569
|
+
org_id (str): Organization ID
|
|
570
|
+
|
|
571
|
+
Returns:
|
|
572
|
+
DowngradeUserPlaybooksResponse: Response containing success status and counts
|
|
573
|
+
"""
|
|
574
|
+
# Create Reflexio instance
|
|
575
|
+
reflexio = reflexio_cache.get_reflexio(org_id=org_id)
|
|
576
|
+
|
|
577
|
+
# Call downgrade_all_user_playbooks with request
|
|
578
|
+
return reflexio.downgrade_all_user_playbooks(request=request)
|