claude-smart 0.2.47 → 0.2.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/dashboard/app/sessions/[sessionId]/page.tsx +36 -2
- package/plugin/dashboard/package-lock.json +61 -390
- package/plugin/dashboard/package.json +2 -2
- package/plugin/pyproject.toml +1 -1
- package/plugin/uv.lock +1 -1
- package/plugin/vendor/reflexio/.env.example +7 -0
- package/plugin/vendor/reflexio/pyproject.toml +2 -1
- package/plugin/vendor/reflexio/reflexio/README.md +8 -5
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +23 -18
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +16 -1
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +15 -11
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +1 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +24 -3
- package/plugin/vendor/reflexio/reflexio/server/README.md +25 -8
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +21 -2
- package/plugin/vendor/reflexio/reflexio/server/api.py +133 -3273
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +4 -3
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +16 -1
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +62 -36
- package/plugin/vendor/reflexio/reflexio/server/deployment_profile.py +69 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_embedding.py +424 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_json_extraction.py +249 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_structured_output.py +195 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_subprocess.py +152 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_text_generation.py +980 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/_litellm_types.py +110 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +73 -1819
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +56 -4
- package/plugin/vendor/reflexio/reflexio/server/middleware.py +244 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +9 -1
- package/plugin/vendor/reflexio/reflexio/server/rate_limit.py +79 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/_common.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/_metering.py +98 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/braintrust.py +129 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/config.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/evaluation.py +549 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/interactions.py +259 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/playbooks.py +578 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/profiles.py +423 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/provenance.py +345 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/search.py +349 -0
- package/plugin/vendor/reflexio/reflexio/server/routes/system.py +261 -0
- package/plugin/vendor/reflexio/reflexio/server/scheduling.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +3 -2
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/__init__.py +38 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_batch_progress.py +298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_config_filter.py +152 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_extraction_lifecycle.py +243 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_should_run.py +299 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_status_change.py +273 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation/_usage_billing.py +258 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +17 -1183
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +8 -1
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +26 -41
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +232 -123
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +362 -81
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator.py +68 -490
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_clustering.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_postprocessing.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/aggregator_prompt_formatting.py +212 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/consolidator.py +258 -69
- package/plugin/vendor/reflexio/reflexio/server/services/publish_learning_worker.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +29 -4
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +10 -1167
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +56 -351
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +0 -1513
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +6 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +7 -1281
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_agent_run_store.py +506 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_pending_tool_call_store.py +704 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/agent_run/_run_tool_dependency_store.py +123 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/_deletion.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/base/_fts_vec.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_audit.py +122 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_erase_execution.py +465 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_purge.py +387 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_rebuild_hide.py +332 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/governance/_subject_barrier.py +511 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +6 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +13 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_interaction_store.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_profile_store.py +896 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/profiles/_search.py +270 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +33 -8
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +64 -370
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +20 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_agent_run_store.py +86 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_models.py +195 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_pending_tool_call_store.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/agent_run/_run_tool_dependency_store.py +38 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_audit.py +29 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_erase_execution.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_purge.py +74 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_rebuild_hide.py +32 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/governance/_subject_barrier.py +49 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/__init__.py +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_interaction_store.py +73 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/{_profiles.py → profiles/_profile_store.py} +44 -86
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/profiles/_search.py +32 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_governance.py +0 -148
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"lint": "eslint"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
+
"@tailwindcss/postcss": "^4",
|
|
12
13
|
"@base-ui/react": "^1.3.0",
|
|
13
14
|
"class-variance-authority": "^0.7.1",
|
|
14
15
|
"clsx": "^2.1.1",
|
|
@@ -17,17 +18,16 @@
|
|
|
17
18
|
"next-themes": "^0.4.6",
|
|
18
19
|
"react": "19.2.4",
|
|
19
20
|
"react-dom": "19.2.4",
|
|
21
|
+
"shadcn": "^4.0.8",
|
|
20
22
|
"tailwind-merge": "^3.5.0",
|
|
21
23
|
"tw-animate-css": "^1.4.0"
|
|
22
24
|
},
|
|
23
25
|
"devDependencies": {
|
|
24
|
-
"@tailwindcss/postcss": "^4",
|
|
25
26
|
"@types/node": "^20",
|
|
26
27
|
"@types/react": "^19",
|
|
27
28
|
"@types/react-dom": "^19",
|
|
28
29
|
"eslint": "^9",
|
|
29
30
|
"eslint-config-next": "16.2.6",
|
|
30
|
-
"shadcn": "^4.0.8",
|
|
31
31
|
"tailwindcss": "^4",
|
|
32
32
|
"typescript": "^5"
|
|
33
33
|
},
|
package/plugin/pyproject.toml
CHANGED
package/plugin/uv.lock
CHANGED
|
@@ -67,6 +67,13 @@ REFLEXIO_DEFAULT_ORG_ID=self-host-org
|
|
|
67
67
|
# elided. (optional; default 512; set <= 0 to disable slicing and pass full
|
|
68
68
|
# content)
|
|
69
69
|
REFLEXIO_MAX_INTERACTION_CONTENT_TOKENS=512
|
|
70
|
+
# Warn when queued post-persist async publish learning jobs reach this depth.
|
|
71
|
+
# The queue is unbounded so acknowledged publishes do not drop learning due to
|
|
72
|
+
# transient limiter pressure. (optional; default 1000)
|
|
73
|
+
REFLEXIO_PUBLISH_LEARNING_QUEUE_WARN_SIZE=1000
|
|
74
|
+
# Worker threads for post-persist async publish learning. (optional; default
|
|
75
|
+
# matches the configured publish concurrency limit, currently 4)
|
|
76
|
+
REFLEXIO_PUBLISH_LEARNING_WORKERS=
|
|
70
77
|
# Inactivity delay in seconds before a quiet session is evaluated by agent-success
|
|
71
78
|
# evaluation. (optional; default 600 = 10 minutes)
|
|
72
79
|
GROUP_EVALUATION_DELAY_SECONDS=600
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "reflexio-ai"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.28"
|
|
4
4
|
description = "A Python library for the Reflexio"
|
|
5
5
|
authors = [{name = "Reflexio Team"}]
|
|
6
6
|
readme = "README.md"
|
|
@@ -218,6 +218,7 @@ ignore = [
|
|
|
218
218
|
"reflexio/scripts/**" = ["S101", "G004", "ANN"]
|
|
219
219
|
"reflexio/benchmarks/**" = ["S311"]
|
|
220
220
|
"reflexio/server/api.py" = ["B008", "ARG001", "ARG002"]
|
|
221
|
+
"reflexio/server/routes/**" = ["B008", "ARG001", "ARG002"]
|
|
221
222
|
"reflexio/server/api_endpoints/**" = ["B008", "ARG001", "ARG002"]
|
|
222
223
|
"reflexio/integrations/**" = ["ARG002"]
|
|
223
224
|
# The openclaw plugin is a nested package; its tests/scripts/cli are not reached
|
|
@@ -101,9 +101,10 @@ Description: FastAPI backend server that processes user interactions to generate
|
|
|
101
101
|
**Detailed Documentation**: See [`reflexio/server/README.md`](server/README.md) for component details, including the [Prompt Bank](server/prompt/prompt_bank/README.md), [Playbook Service](server/services/playbook/README.md), and [Site Variables](server/site_var/README.md)
|
|
102
102
|
|
|
103
103
|
### Main Entry Points
|
|
104
|
-
- **API**: `api.py` -
|
|
104
|
+
- **API composer**: `api.py` - `create_app()` factory, middleware/capability wiring, and `core_router` aggregation
|
|
105
|
+
- **Domain routes**: `server/routes/` - FastAPI route modules grouped by system, interactions, profiles, playbooks, search, provenance, evaluation, Braintrust, and config
|
|
105
106
|
- **Extension Registry**: `extensions.py` - optional capability/service registration for OSS and enterprise integrations
|
|
106
|
-
- **Endpoint Helpers**: `api_endpoints/` -
|
|
107
|
+
- **Endpoint Helpers**: `api_endpoints/` - Shared handler/helper functions and `RequestContext` used by route modules
|
|
107
108
|
- **Core Service**: `services/generation_service.py` - Main orchestrator
|
|
108
109
|
|
|
109
110
|
### Purpose
|
|
@@ -115,8 +116,9 @@ Receives user interactions from clients and processes them to:
|
|
|
115
116
|
### Component Relationships
|
|
116
117
|
```
|
|
117
118
|
client (Python SDK)
|
|
118
|
-
-> api.py (
|
|
119
|
-
->
|
|
119
|
+
-> api.py (create_app + core_router)
|
|
120
|
+
-> routes/ (domain FastAPI routers)
|
|
121
|
+
-> api_endpoints/ (shared handlers + RequestContext)
|
|
120
122
|
-> reflexio_lib.Reflexio (main entry)
|
|
121
123
|
-> services/generation_service.py (orchestrator)
|
|
122
124
|
├─> services/profile/ -> storage (BaseStorage)
|
|
@@ -126,12 +128,13 @@ client (Python SDK)
|
|
|
126
128
|
|
|
127
129
|
### Key Components
|
|
128
130
|
- **`api_endpoints/`**: Request handling, `RequestContext` (bundles storage/config/prompts), auth
|
|
131
|
+
- **`routes/`**: Domain route modules (`system.py`, `interactions.py`, `profiles.py`, `playbooks.py`, `search.py`, `provenance.py`, `evaluation.py`, `braintrust.py`, `config.py`) included into `api.py`'s `core_router`
|
|
129
132
|
- **`db/`**: Auth & config storage only (SQLite) - NOT for profiles/interactions
|
|
130
133
|
- **`llm/`**: Unified LLM client (auto-detects OpenAI/Claude from model name)
|
|
131
134
|
- **`prompt/`**: Versioned prompt templates in `prompt_bank/`
|
|
132
135
|
- **`services/`**: Core business logic
|
|
133
136
|
- `generation_service.py` - Orchestrator (runs profile/playbook/success services)
|
|
134
|
-
- `base_generation_service.py` - Abstract base for parallel actor execution
|
|
137
|
+
- `base_generation_service.py` + `base_generation/` - Abstract base plus mixins for parallel actor execution, batch progress, should-run prechecks, status transitions, and usage billing
|
|
135
138
|
- `profile/` - Profile extraction & updates
|
|
136
139
|
- `playbook/` - Playbook extraction, consolidation, and aggregation
|
|
137
140
|
- `agent_success_evaluation/` - Success evaluation
|
|
@@ -29,32 +29,37 @@ class ConfigMixin(ReflexioBase):
|
|
|
29
29
|
# security). Without this, the marker reaches the readiness check as
|
|
30
30
|
# an unfillable StorageConfigManagedSupabase and fails with
|
|
31
31
|
# "Storage configuration is incomplete".
|
|
32
|
+
current_storage_config = configurator.get_current_storage_configuration()
|
|
32
33
|
storage_config = config.storage_config
|
|
33
34
|
if storage_config is None or isinstance(
|
|
34
35
|
storage_config, StorageConfigManagedSupabase
|
|
35
36
|
):
|
|
36
|
-
storage_config =
|
|
37
|
+
storage_config = current_storage_config
|
|
37
38
|
config.storage_config = storage_config
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
if
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
storage_config_changed = storage_config != current_storage_config
|
|
41
|
+
if storage_config_changed or current_storage_config is None:
|
|
42
|
+
# Storage validation initializes the backend and may run
|
|
43
|
+
# migrations, so only do it when the storage target changes.
|
|
44
|
+
if not configurator.is_storage_config_ready_to_test(
|
|
45
|
+
storage_config=storage_config
|
|
46
|
+
):
|
|
47
|
+
return SetConfigResponse(
|
|
48
|
+
success=False, msg="Storage configuration is incomplete"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
(
|
|
52
|
+
success,
|
|
53
|
+
error_msg,
|
|
54
|
+
) = configurator.test_and_init_storage_config(
|
|
55
|
+
storage_config=storage_config
|
|
45
56
|
)
|
|
46
57
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if not success:
|
|
54
|
-
return SetConfigResponse(
|
|
55
|
-
success=False,
|
|
56
|
-
msg=f"Failed to validate storage connection: {error_msg}",
|
|
57
|
-
)
|
|
58
|
+
if not success:
|
|
59
|
+
return SetConfigResponse(
|
|
60
|
+
success=False,
|
|
61
|
+
msg=f"Failed to validate storage connection: {error_msg}",
|
|
62
|
+
)
|
|
58
63
|
|
|
59
64
|
# Only set config if validation passed
|
|
60
65
|
configurator.set_config(config)
|
|
@@ -53,11 +53,21 @@ class InteractionsMixin(ReflexioBase):
|
|
|
53
53
|
def publish_interaction(
|
|
54
54
|
self,
|
|
55
55
|
request: PublishUserInteractionRequest | dict,
|
|
56
|
+
*,
|
|
57
|
+
use_publish_limiter: bool = True,
|
|
58
|
+
publish_limiter_wait_forever: bool = True,
|
|
59
|
+
defer_learning: bool = False,
|
|
56
60
|
) -> PublishUserInteractionResponse:
|
|
57
61
|
"""Publish user interactions.
|
|
58
62
|
|
|
59
63
|
Args:
|
|
60
64
|
request (Union[PublishUserInteractionRequest, dict]): The publish user interaction request
|
|
65
|
+
use_publish_limiter: Whether GenerationService should throttle the
|
|
66
|
+
post-write learning pipeline.
|
|
67
|
+
publish_limiter_wait_forever: Whether GenerationService should queue
|
|
68
|
+
indefinitely for that post-write learning limiter.
|
|
69
|
+
defer_learning: Whether to enqueue post-persist learning instead of
|
|
70
|
+
running it inline.
|
|
61
71
|
|
|
62
72
|
Returns:
|
|
63
73
|
PublishUserInteractionResponse: Response containing success status and message
|
|
@@ -87,7 +97,12 @@ class InteractionsMixin(ReflexioBase):
|
|
|
87
97
|
# Convert dict to PublishUserInteractionRequest if needed
|
|
88
98
|
if isinstance(request, dict):
|
|
89
99
|
request = PublishUserInteractionRequest(**request)
|
|
90
|
-
result = generation_service.run(
|
|
100
|
+
result = generation_service.run(
|
|
101
|
+
request,
|
|
102
|
+
use_publish_limiter=use_publish_limiter,
|
|
103
|
+
publish_limiter_wait_forever=publish_limiter_wait_forever,
|
|
104
|
+
defer_learning=defer_learning,
|
|
105
|
+
)
|
|
91
106
|
after_profiles = _safe_count(storage.count_all_profiles)
|
|
92
107
|
after_playbooks = _safe_count(storage.count_user_playbooks)
|
|
93
108
|
# Don't concatenate warnings into the message field — they
|
|
@@ -42,17 +42,21 @@ class SearchMixin(ReflexioBase):
|
|
|
42
42
|
|
|
43
43
|
try:
|
|
44
44
|
if request.start_time or request.end_time:
|
|
45
|
-
results =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
results = (
|
|
46
|
+
self._get_storage().get_agent_success_evaluation_results_in_window(
|
|
47
|
+
from_ts=(
|
|
48
|
+
int(request.start_time.timestamp())
|
|
49
|
+
if request.start_time
|
|
50
|
+
else 0
|
|
51
|
+
),
|
|
52
|
+
to_ts=(
|
|
53
|
+
int(request.end_time.timestamp())
|
|
54
|
+
if request.end_time
|
|
55
|
+
else 2**31 - 1
|
|
56
|
+
),
|
|
57
|
+
limit=request.limit or 100,
|
|
58
|
+
agent_version=request.agent_version,
|
|
59
|
+
)
|
|
56
60
|
)
|
|
57
61
|
else:
|
|
58
62
|
results = self._get_storage().get_agent_success_evaluation_results(
|
|
@@ -46,6 +46,7 @@ class Status(str, Enum): # noqa: UP042 - CURRENT=None is not compatible with St
|
|
|
46
46
|
SUPERSEDED = (
|
|
47
47
|
"superseded" # tombstone: replaced by a new version (superseded_by set)
|
|
48
48
|
)
|
|
49
|
+
EXPIRED = "expired" # tombstone: TTL elapsed while active (see expiry reclamation)
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
class OperationStatus(StrEnum):
|
|
@@ -708,11 +708,27 @@ class LineageGCConfig(BaseModel):
|
|
|
708
708
|
poll_interval_seconds: int = Field(default=86400, gt=0)
|
|
709
709
|
|
|
710
710
|
|
|
711
|
+
class ExpiryReclamationConfig(BaseModel):
|
|
712
|
+
"""Direct-delete reclamation of expired plain rows (non-audited).
|
|
713
|
+
|
|
714
|
+
Independent of ``lineage_gc``: these rows carry no PII/audit/grace obligation,
|
|
715
|
+
so they can be reclaimed whenever this is enabled even if tombstone GC is off.
|
|
716
|
+
|
|
717
|
+
Opt-in by default (``enabled=False``) so operators control a staged rollout
|
|
718
|
+
of the direct-delete Class B sweeps and are not surprised by deletions on
|
|
719
|
+
upgrade. ``lineage_gc.enabled`` (which defaults to True) is unaffected and
|
|
720
|
+
continues to drive the Class A profile-expiry and tombstone-GC paths.
|
|
721
|
+
"""
|
|
722
|
+
|
|
723
|
+
enabled: bool = False
|
|
724
|
+
|
|
725
|
+
|
|
711
726
|
class GovernanceRetentionConfig(BaseModel):
|
|
712
727
|
"""Audit-event retention policy. **Enterprise-only:** reclamation is performed
|
|
713
|
-
by
|
|
714
|
-
|
|
715
|
-
|
|
728
|
+
by an enterprise per-org reclamation sweep registered via
|
|
729
|
+
``register_per_org_sweep``. In an OSS-only deployment these knobs are accepted
|
|
730
|
+
but inert (the OSS lineage scheduler does not reclaim audit events) and the
|
|
731
|
+
server logs a startup warning when retention is enabled.
|
|
716
732
|
"""
|
|
717
733
|
|
|
718
734
|
audit_events_retention_enabled: bool = False
|
|
@@ -859,6 +875,10 @@ class Config(BaseModel):
|
|
|
859
875
|
)
|
|
860
876
|
# Tombstone GC job gate (opt-in, off by default — see LineageGCConfig)
|
|
861
877
|
lineage_gc: LineageGCConfig = Field(default_factory=LineageGCConfig)
|
|
878
|
+
# Direct-delete reclamation of expired plain rows (share links, pending tool calls)
|
|
879
|
+
expiry_reclamation: ExpiryReclamationConfig = Field(
|
|
880
|
+
default_factory=ExpiryReclamationConfig
|
|
881
|
+
)
|
|
862
882
|
governance_retention: GovernanceRetentionConfig = Field(
|
|
863
883
|
default_factory=GovernanceRetentionConfig
|
|
864
884
|
)
|
|
@@ -920,6 +940,7 @@ class Config(BaseModel):
|
|
|
920
940
|
"reflection_config",
|
|
921
941
|
"playbook_optimizer_config",
|
|
922
942
|
"lineage_gc",
|
|
943
|
+
"expiry_reclamation",
|
|
923
944
|
"governance_retention",
|
|
924
945
|
"pending_tool_call_config",
|
|
925
946
|
"retrieval_floor",
|
|
@@ -33,8 +33,9 @@ Description: FastAPI backend server that processes user interactions to generate
|
|
|
33
33
|
|
|
34
34
|
## Main Entry Points
|
|
35
35
|
|
|
36
|
-
- **API**: `api.py` -
|
|
37
|
-
- **
|
|
36
|
+
- **API composer**: `api.py` - `create_app()` factory, middleware/capability wiring, OpenAPI auth decoration, and `core_router` aggregation
|
|
37
|
+
- **Domain routes**: `routes/` - FastAPI route modules; add new public API surfaces here and include their routers in `api.py`
|
|
38
|
+
- **Endpoint Helpers**: `api_endpoints/` - Shared handlers/helpers plus `RequestContext` used by route modules
|
|
38
39
|
- **Extension Registry**: `extensions.py` - Capability and service registry for optional OSS/enterprise integrations
|
|
39
40
|
- **Core Service**: `services/generation_service.py` - Main orchestrator
|
|
40
41
|
|
|
@@ -57,7 +58,19 @@ Description: FastAPI backend server that processes user interactions to generate
|
|
|
57
58
|
|
|
58
59
|
**Directory**: `api_endpoints/`
|
|
59
60
|
|
|
60
|
-
**Detailed
|
|
61
|
+
**Route modules** live in `routes/` and are grouped by domain. `api.py` remains the composition root: it creates `core_router`, includes each domain router, and mounts the aggregate router into the FastAPI app. **Detailed handler documentation**: See [`api_endpoints/README.md`](api_endpoints/README.md) for the `RequestContext` contract and helper map.
|
|
62
|
+
|
|
63
|
+
| Route file | Purpose |
|
|
64
|
+
|------|---------|
|
|
65
|
+
| `routes/system.py` | Root/health/version and operation status/cancel surfaces. |
|
|
66
|
+
| `routes/interactions.py` | Publish, request/session/interaction retrieval, direct interaction writes, and clear-data operations. |
|
|
67
|
+
| `routes/profiles.py` | Profile retrieval, statistics, rerun/manual generation, upgrade/downgrade, update/delete lifecycle routes. |
|
|
68
|
+
| `routes/playbooks.py` | User/agent playbook retrieval, aggregation, lifecycle, status/update/delete, and application stats routes. |
|
|
69
|
+
| `routes/search.py` | Unified search and entity-specific search/rerank routes. |
|
|
70
|
+
| `routes/provenance.py` | Learning provenance and approval routes. |
|
|
71
|
+
| `routes/evaluation.py` | Evaluation overview, regenerate jobs, grade-on-demand, shadow comparisons, pending tool calls, and stall-state routes. |
|
|
72
|
+
| `routes/braintrust.py` | Braintrust connection/project/status/sync routes. |
|
|
73
|
+
| `routes/config.py` | Config read/write and account identity routes. |
|
|
61
74
|
|
|
62
75
|
| File | Purpose |
|
|
63
76
|
|------|---------|
|
|
@@ -97,10 +110,13 @@ Description: FastAPI backend server that processes user interactions to generate
|
|
|
97
110
|
## LLM Client
|
|
98
111
|
|
|
99
112
|
**Directory**: `llm/`
|
|
100
|
-
**Entry Point**: `litellm_client.py` - `LiteLLMClient`
|
|
113
|
+
**Entry Point**: `litellm_client.py` - `LiteLLMClient` facade composed from focused mixins
|
|
101
114
|
|
|
102
115
|
Key files:
|
|
103
|
-
- `litellm_client.py`:
|
|
116
|
+
- `litellm_client.py`: Stable import surface, client config/credential resolution, and `LiteLLMClient` facade
|
|
117
|
+
- `_litellm_text_generation.py`, `_litellm_embedding.py`, `_litellm_structured_output.py`: Completion/tool-call, embedding, and structured-output mixins
|
|
118
|
+
- `_litellm_json_extraction.py`, `_litellm_subprocess.py`, `_litellm_types.py`: JSON parsing, hard-timeout subprocess snapshots/workers, and shared public types/errors
|
|
119
|
+
- `providers/`: Optional local/provider adapters (`claude-code/`, OpenClaw, local embedding, Nomic embedding); registration is opt-in via environment/config
|
|
104
120
|
- `openai_client.py`: OpenAI implementation (legacy, do not use directly)
|
|
105
121
|
- `claude_client.py`: Claude implementation (legacy, do not use directly)
|
|
106
122
|
- `llm_utils.py`: Helper functions for Pydantic model conversion
|
|
@@ -230,7 +246,8 @@ Called by API endpoints via `Reflexio`
|
|
|
230
246
|
|
|
231
247
|
### Base Infrastructure
|
|
232
248
|
|
|
233
|
-
- `base_generation_service.py`:
|
|
249
|
+
- `base_generation_service.py`: Stable `BaseGenerationService` import surface plus service-specific orchestration hooks (parallel extractor execution via ThreadPoolExecutor, `EXTRACTOR_TIMEOUT_SECONDS = 300` per-extractor safety timeout)
|
|
250
|
+
- `base_generation/`: Mixins for batch progress, config filtering, extraction lifecycle, should-run prechecks, status transitions, and usage billing that keep `base_generation_service.py` navigable without changing caller imports
|
|
234
251
|
- `extractor_config_utils.py`: Shared utility for filtering extractor configs by source, `allow_manual_trigger`, and extractor names
|
|
235
252
|
- `extractor_interaction_utils.py`: Per-extractor utilities for stride_size checking and source filtering
|
|
236
253
|
- `operation_state_utils.py`: Centralized `OperationStateManager` for all `_operation_state` table interactions (progress tracking, concurrency locks, extractor/aggregator bookmarks, simple locks)
|
|
@@ -488,8 +505,8 @@ Pre-computed embeddings passed to storage methods via `query_embedding` paramete
|
|
|
488
505
|
|
|
489
506
|
| File | Purpose |
|
|
490
507
|
|------|---------|
|
|
491
|
-
| `storage_base/` | BaseStorage interface split by domain (`_profiles.py`, `_playbook.py`, `
|
|
492
|
-
| `sqlite_storage/` | SQLite-backed implementation split across
|
|
508
|
+
| `storage_base/` | BaseStorage interface split by domain. Legacy facades (`_profiles.py`, `_playbook.py`, `_agent_run.py`, etc.) preserve imports while subpackages (`profiles/`, `playbook/`, `agent_run/`, `governance/`) hold focused abstract store contracts. |
|
|
509
|
+
| `sqlite_storage/` | SQLite-backed implementation split across matching facades and subpackages (`profiles/`, `playbook/`, `agent_run/`, `governance/`, `base/`), including governance-aware retention/barrier handling and lineage/tombstone support. |
|
|
493
510
|
| `governance_validation.py` | Shared validation helpers for subject references and governance contracts before storage writes. |
|
|
494
511
|
| `retention.py`, `retention_mixin.py` | Data retention and cleanup helpers |
|
|
495
512
|
| `constants.py`, `error.py` | Storage constants and shared errors |
|
|
@@ -230,5 +230,24 @@ if DEBUG_LOG_TO_CONSOLE:
|
|
|
230
230
|
logging.ERROR
|
|
231
231
|
)
|
|
232
232
|
else:
|
|
233
|
-
#
|
|
234
|
-
|
|
233
|
+
# Production (DEBUG_LOG_TO_CONSOLE off): emit INFO+ app logs to stdout so the
|
|
234
|
+
# container log driver (e.g. CloudWatch awslogs) captures business-logic audit
|
|
235
|
+
# lines — billing/webhook/enforcement, etc. Without an explicit handler the
|
|
236
|
+
# stdlib "handler of last resort" emits only WARNING+ to stderr, so INFO logs
|
|
237
|
+
# were silently dropped in production. Plain formatter (no colors/files/dedup)
|
|
238
|
+
# keeps this lean and log-driver friendly — none of the DEBUG-branch overhead.
|
|
239
|
+
root_logger.setLevel(logging.INFO)
|
|
240
|
+
if not any(isinstance(h, logging.StreamHandler) for h in root_logger.handlers):
|
|
241
|
+
prod_console_handler = logging.StreamHandler(sys.stdout)
|
|
242
|
+
prod_console_handler.setLevel(logging.INFO)
|
|
243
|
+
prod_console_handler.setFormatter(
|
|
244
|
+
logging.Formatter("%(asctime)s %(name)s %(levelname)s %(message)s")
|
|
245
|
+
)
|
|
246
|
+
root_logger.addHandler(prod_console_handler)
|
|
247
|
+
|
|
248
|
+
# Keep noisy loggers quiet even at INFO (mirror the debug branch's suppression).
|
|
249
|
+
for _noisy in ("litellm", "LiteLLM", "httpx", "httpcore", "openai", "urllib3"):
|
|
250
|
+
logging.getLogger(_noisy).setLevel(logging.WARNING)
|
|
251
|
+
logging.getLogger("reflexio.server.site_var.site_var_manager").setLevel(
|
|
252
|
+
logging.ERROR
|
|
253
|
+
)
|