claude-smart 0.2.45 → 0.2.46
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 +3 -3
- package/README.md +34 -5
- package/bin/claude-smart.js +295 -5
- package/package.json +22 -3
- package/plugin/.claude-plugin/plugin.json +4 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +22 -2
- package/plugin/commands/clear-all.md +1 -0
- package/plugin/commands/dashboard.md +1 -0
- package/plugin/commands/learn.md +1 -0
- package/plugin/commands/restart.md +1 -0
- package/plugin/commands/show.md +1 -0
- package/plugin/dashboard/app/configure/env/page.tsx +40 -14
- package/plugin/dashboard/app/configure/server/page.tsx +51 -1
- package/plugin/dashboard/app/preferences/[id]/page.tsx +8 -8
- package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
- package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
- package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
- package/plugin/dashboard/lib/reflexio-client.ts +16 -0
- package/plugin/dashboard/lib/status.ts +10 -3
- package/plugin/dashboard/lib/types.ts +18 -6
- package/plugin/hooks/codex-hooks.json +0 -1
- package/plugin/opencode/assistant-buffer.ts +108 -0
- package/plugin/opencode/dist/assistant-buffer.js +96 -0
- package/plugin/opencode/dist/internal.js +12 -0
- package/plugin/opencode/dist/payload.js +85 -0
- package/plugin/opencode/dist/server.mjs +158 -0
- package/plugin/opencode/internal.ts +18 -0
- package/plugin/opencode/package.json +3 -0
- package/plugin/opencode/payload.ts +90 -0
- package/plugin/opencode/server.mts +174 -0
- package/plugin/opencode/tsconfig.json +13 -0
- package/plugin/pyproject.toml +20 -3
- package/plugin/scripts/_lib.sh +5 -1
- package/plugin/scripts/backend-service.sh +22 -2
- package/plugin/scripts/ensure-plugin-root.sh +4 -4
- package/plugin/scripts/hook_entry.sh +1 -1
- package/plugin/scripts/opencode-claude-compat +4 -0
- package/plugin/scripts/opencode-claude-compat.cmd +3 -0
- package/plugin/scripts/opencode-claude-compat.js +225 -0
- package/plugin/scripts/smart-install.sh +10 -8
- package/plugin/src/README.md +1 -1
- package/plugin/src/claude_smart/cli.py +304 -6
- package/plugin/src/claude_smart/env_config.py +12 -4
- package/plugin/src/claude_smart/events/session_start.py +26 -7
- package/plugin/src/claude_smart/events/stop.py +1 -1
- package/plugin/src/claude_smart/ids.py +1 -1
- package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
- package/plugin/src/claude_smart/runtime.py +7 -1
- package/plugin/uv.lock +1 -1
- package/plugin/vendor/reflexio/.env.example +54 -30
- package/plugin/vendor/reflexio/README.md +14 -8
- package/plugin/vendor/reflexio/pyproject.toml +13 -1
- package/plugin/vendor/reflexio/reflexio/README.md +1 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +210 -50
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
- package/plugin/vendor/reflexio/reflexio/client/client.py +57 -13
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +238 -10
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +16 -5
- package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +198 -6
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +29 -20
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +2 -1
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +52 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +88 -7
- package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
- package/plugin/vendor/reflexio/reflexio/server/README.md +45 -32
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +65 -2
- package/plugin/vendor/reflexio/reflexio/server/api.py +734 -85
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +3 -1
- package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
- package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
- package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +266 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +26 -11
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +39 -16
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +11 -12
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +316 -178
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/user_detail_stripping.py +84 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +30 -22
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +83 -6
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +27 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +642 -197
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +61 -104
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +628 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +978 -184
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +519 -128
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +77 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +131 -20
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +36 -53
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +243 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +121 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +229 -32
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
- package/scripts/setup-claude-smart.sh +8 -3
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
- /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
|
@@ -12,6 +12,7 @@ from typing import Literal, Self
|
|
|
12
12
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
13
13
|
|
|
14
14
|
from reflexio.models.api_schema.validators import NonEmptyStr
|
|
15
|
+
from reflexio.models.structured_output import StrictStructuredOutput
|
|
15
16
|
|
|
16
17
|
HeroStateLiteral = Literal["full", "early", "shadow_off", "empty"]
|
|
17
18
|
BucketLiteral = Literal["day", "week"]
|
|
@@ -98,6 +99,24 @@ class ScoreDistribution(BaseModel):
|
|
|
98
99
|
labels: list[str]
|
|
99
100
|
|
|
100
101
|
|
|
102
|
+
class EvaluationSourceSetRequest(BaseModel):
|
|
103
|
+
"""One labeled request-source cohort for evaluation comparison.
|
|
104
|
+
|
|
105
|
+
``sources`` match ``Request.source`` exactly. The empty string is valid and
|
|
106
|
+
represents requests published without a source.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
label: NonEmptyStr
|
|
110
|
+
sources: list[str] = Field(min_length=1)
|
|
111
|
+
|
|
112
|
+
@model_validator(mode="after")
|
|
113
|
+
def validate_sources_are_unique(self) -> Self:
|
|
114
|
+
"""Reject duplicate source values within a single set."""
|
|
115
|
+
if len(set(self.sources)) != len(self.sources):
|
|
116
|
+
raise ValueError("source set sources must be unique")
|
|
117
|
+
return self
|
|
118
|
+
|
|
119
|
+
|
|
101
120
|
class GetEvaluationOverviewRequest(BaseModel):
|
|
102
121
|
"""Input for the overview endpoint.
|
|
103
122
|
|
|
@@ -107,18 +126,34 @@ class GetEvaluationOverviewRequest(BaseModel):
|
|
|
107
126
|
bucket (BucketLiteral): Granularity of the hero trend buckets.
|
|
108
127
|
include_shadow (bool): When False, skip the shadow-side aggregations
|
|
109
128
|
(cheaper) — the hero will degrade to shadow_off state.
|
|
129
|
+
source_sets (list[EvaluationSourceSetRequest]): Optional labeled
|
|
130
|
+
request-source cohorts to compare. Sources are matched exactly
|
|
131
|
+
against the first request in each evaluated session.
|
|
110
132
|
"""
|
|
111
133
|
|
|
112
134
|
from_ts: int = Field(ge=0)
|
|
113
135
|
to_ts: int = Field(ge=0)
|
|
114
136
|
bucket: BucketLiteral = "week"
|
|
115
137
|
include_shadow: bool = True
|
|
138
|
+
source_sets: list[EvaluationSourceSetRequest] = Field(default_factory=list)
|
|
116
139
|
|
|
117
140
|
@model_validator(mode="after")
|
|
118
|
-
def
|
|
119
|
-
"""Ensure the requested time window
|
|
141
|
+
def validate_request(self) -> Self:
|
|
142
|
+
"""Ensure the requested time window and source sets are valid."""
|
|
120
143
|
if self.from_ts > self.to_ts:
|
|
121
144
|
raise ValueError("from_ts must be <= to_ts")
|
|
145
|
+
labels = [s.label for s in self.source_sets]
|
|
146
|
+
if len(set(labels)) != len(labels):
|
|
147
|
+
raise ValueError("source set labels must be unique")
|
|
148
|
+
seen_sources: set[str] = set()
|
|
149
|
+
for source_set in self.source_sets:
|
|
150
|
+
overlap = seen_sources.intersection(source_set.sources)
|
|
151
|
+
if overlap:
|
|
152
|
+
overlap_list = ", ".join(sorted(repr(s) for s in overlap))
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"source values cannot appear in multiple source sets: {overlap_list}"
|
|
155
|
+
)
|
|
156
|
+
seen_sources.update(source_set.sources)
|
|
122
157
|
return self
|
|
123
158
|
|
|
124
159
|
|
|
@@ -139,41 +174,6 @@ class BraintrustTileRow(BaseModel):
|
|
|
139
174
|
delta: float
|
|
140
175
|
|
|
141
176
|
|
|
142
|
-
class TrendPoint(BaseModel):
|
|
143
|
-
"""One point on a grouped success-rate trend curve (F2).
|
|
144
|
-
|
|
145
|
-
Args:
|
|
146
|
-
ts (int): Unix epoch seconds — bucket start.
|
|
147
|
-
rate (float): Success rate for sessions in this bucket, [0.0, 1.0].
|
|
148
|
-
n (int): Session count backing the rate. Must be non-negative.
|
|
149
|
-
"""
|
|
150
|
-
|
|
151
|
-
ts: int
|
|
152
|
-
rate: float
|
|
153
|
-
n: int = Field(ge=0)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
class SuccessRateTrendByGroup(BaseModel):
|
|
157
|
-
"""Group-split trend data for the dashboard's dual-curve chart (F2).
|
|
158
|
-
|
|
159
|
-
Grouping is by ``Request.metadata.reflexio_retrieval_enabled``, read from
|
|
160
|
-
the first request of each session in the window. Sessions whose first
|
|
161
|
-
request has the key absent OR a non-bool value land in ``untagged``.
|
|
162
|
-
|
|
163
|
-
Args:
|
|
164
|
-
treatment (list[TrendPoint]): Curve for sessions where the first
|
|
165
|
-
request had ``metadata.reflexio_retrieval_enabled = True``.
|
|
166
|
-
control (list[TrendPoint]): Curve for ``... = False``.
|
|
167
|
-
untagged (list[TrendPoint]): Curve for sessions where the key is
|
|
168
|
-
absent or non-bool — surfaced (not silently coerced) so
|
|
169
|
-
customers can see how many of their sessions are untagged.
|
|
170
|
-
"""
|
|
171
|
-
|
|
172
|
-
treatment: list[TrendPoint] = Field(default_factory=list)
|
|
173
|
-
control: list[TrendPoint] = Field(default_factory=list)
|
|
174
|
-
untagged: list[TrendPoint] = Field(default_factory=list)
|
|
175
|
-
|
|
176
|
-
|
|
177
177
|
class ShadowWinRateTrendPoint(BaseModel):
|
|
178
178
|
"""One daily bucket of per-turn shadow-comparison verdicts (F1).
|
|
179
179
|
|
|
@@ -243,18 +243,41 @@ class ShadowWinRateTrend(BaseModel):
|
|
|
243
243
|
judge_prompt_version: str = Field(default="v1.0.0")
|
|
244
244
|
|
|
245
245
|
|
|
246
|
+
class SourceSetEvaluationMetrics(BaseModel):
|
|
247
|
+
"""Metrics for one labeled request-source set."""
|
|
248
|
+
|
|
249
|
+
label: str
|
|
250
|
+
sources: list[str]
|
|
251
|
+
session_count: int = Field(ge=0)
|
|
252
|
+
session_ids: list[str] = Field(default_factory=list)
|
|
253
|
+
success_rate_pp: float
|
|
254
|
+
buckets: list[HeroBucket]
|
|
255
|
+
context_tiles: ContextTile
|
|
256
|
+
score_distribution: ScoreDistribution
|
|
257
|
+
rule_attribution: list[RuleAttributionRow]
|
|
258
|
+
braintrust_tiles: list[BraintrustTileRow] = Field(default_factory=list)
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class SourceSetComparison(BaseModel):
|
|
262
|
+
"""Comparison payload for request-source cohorts."""
|
|
263
|
+
|
|
264
|
+
available_sources: list[str] = Field(default_factory=list)
|
|
265
|
+
sets: list[SourceSetEvaluationMetrics] = Field(default_factory=list)
|
|
266
|
+
unmatched_session_count: int = Field(default=0, ge=0)
|
|
267
|
+
|
|
268
|
+
|
|
246
269
|
class GetEvaluationOverviewResponse(BaseModel):
|
|
247
270
|
hero: HeroBlock
|
|
248
271
|
context_tiles: ContextTile
|
|
249
272
|
rule_attribution: list[RuleAttributionRow]
|
|
250
273
|
score_distribution: ScoreDistribution
|
|
251
274
|
braintrust_tiles: list[BraintrustTileRow] = Field(default_factory=list)
|
|
252
|
-
success_rate_trend_by_group: SuccessRateTrendByGroup = Field(
|
|
253
|
-
default_factory=SuccessRateTrendByGroup
|
|
254
|
-
)
|
|
255
275
|
shadow_win_rate_trend: ShadowWinRateTrend = Field(
|
|
256
276
|
default_factory=ShadowWinRateTrend
|
|
257
277
|
)
|
|
278
|
+
source_set_comparison: SourceSetComparison = Field(
|
|
279
|
+
default_factory=SourceSetComparison
|
|
280
|
+
)
|
|
258
281
|
|
|
259
282
|
|
|
260
283
|
# ---------------------------------------------------------------------------
|
|
@@ -406,7 +429,7 @@ class GradeOnDemandResponse(BaseModel):
|
|
|
406
429
|
# ---------------------------------------------------------------------------
|
|
407
430
|
|
|
408
431
|
|
|
409
|
-
class ShadowComparisonOutput(
|
|
432
|
+
class ShadowComparisonOutput(StrictStructuredOutput):
|
|
410
433
|
"""LLM judge verdict for a per-turn Reflexio-vs-Shadow comparison (F1).
|
|
411
434
|
|
|
412
435
|
Args:
|
|
@@ -26,3 +26,22 @@ class SessionDescriptor(NamedTuple):
|
|
|
26
26
|
session_id: str
|
|
27
27
|
agent_version: str
|
|
28
28
|
source: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SessionFirstRequest(NamedTuple):
|
|
32
|
+
"""Earliest request metadata for one session."""
|
|
33
|
+
|
|
34
|
+
session_id: str
|
|
35
|
+
user_id: str
|
|
36
|
+
source: str
|
|
37
|
+
created_at: int
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class SessionCitation(NamedTuple):
|
|
41
|
+
"""One cited rule/profile occurrence, keyed by user/session."""
|
|
42
|
+
|
|
43
|
+
user_id: str
|
|
44
|
+
session_id: str
|
|
45
|
+
kind: str
|
|
46
|
+
real_id: str
|
|
47
|
+
title: str
|
|
@@ -3,14 +3,21 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from
|
|
6
|
+
from enum import StrEnum
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
7
8
|
|
|
8
9
|
from pydantic import BaseModel, ConfigDict, Field
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
PendingToolCallRecord
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from reflexio.server.services.storage.storage_base import PendingToolCallRecord
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PendingToolCallStatus(StrEnum):
|
|
16
|
+
PENDING = "pending"
|
|
17
|
+
RESOLVED = "resolved"
|
|
18
|
+
EXPIRED = "expired"
|
|
19
|
+
SUPERSEDED = "superseded"
|
|
20
|
+
CANCELLED = "cancelled"
|
|
14
21
|
|
|
15
22
|
|
|
16
23
|
class PendingToolCallResponse(BaseModel):
|
|
@@ -50,6 +50,11 @@ class SearchInteractionRequest(BaseModel):
|
|
|
50
50
|
class SearchUserProfileRequest(BaseModel):
|
|
51
51
|
user_id: NonEmptyStr
|
|
52
52
|
generated_from_request_id: str | None = None
|
|
53
|
+
# Caller correlation IDs for billing attribution on the Application line.
|
|
54
|
+
# Optional; when populated they flow into the usage event request_id /
|
|
55
|
+
# session_id columns via _meter_applied_learnings in server/api.py.
|
|
56
|
+
request_id: str | None = None
|
|
57
|
+
session_id: str | None = None
|
|
53
58
|
query: str | None = None
|
|
54
59
|
start_time: datetime | None = None
|
|
55
60
|
end_time: datetime | None = None
|
|
@@ -59,6 +64,7 @@ class SearchUserProfileRequest(BaseModel):
|
|
|
59
64
|
extractor_name: str | None = (
|
|
60
65
|
None # Deprecated compatibility field; accepted but ignored.
|
|
61
66
|
)
|
|
67
|
+
tags: list[str] | None = None
|
|
62
68
|
threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
|
|
63
69
|
enable_reformulation: bool | None = False
|
|
64
70
|
search_mode: SearchMode = SearchMode.HYBRID
|
|
@@ -185,6 +191,7 @@ class GetUserProfilesRequest(BaseModel):
|
|
|
185
191
|
end_time: datetime | None = None
|
|
186
192
|
top_k: int | None = Field(default=30, gt=0)
|
|
187
193
|
status_filter: list[Status | None] | None = None
|
|
194
|
+
tags: list[str] | None = None
|
|
188
195
|
|
|
189
196
|
@model_validator(mode="after")
|
|
190
197
|
def check_time_range(self) -> Self:
|
|
@@ -219,6 +226,7 @@ class GetUserPlaybooksRequest(BaseModel):
|
|
|
219
226
|
playbook_name: str | None = None
|
|
220
227
|
agent_version: str | None = None
|
|
221
228
|
status_filter: list[Status | None] | None = None
|
|
229
|
+
tags: list[str] | None = None
|
|
222
230
|
|
|
223
231
|
|
|
224
232
|
class GetUserPlaybooksResponse(BaseModel):
|
|
@@ -233,6 +241,11 @@ class GetAgentPlaybooksRequest(BaseModel):
|
|
|
233
241
|
agent_version: str | None = None
|
|
234
242
|
status_filter: list[Status | None] | None = None
|
|
235
243
|
playbook_status_filter: PlaybookStatus | None = None
|
|
244
|
+
tags: list[str] | None = None
|
|
245
|
+
# Caller correlation IDs for billing attribution on the Application line.
|
|
246
|
+
# Optional; consumed by _meter_applied_learnings in server/api.py.
|
|
247
|
+
request_id: str | None = None
|
|
248
|
+
session_id: str | None = None
|
|
236
249
|
|
|
237
250
|
|
|
238
251
|
class GetAgentPlaybooksResponse(BaseModel):
|
|
@@ -241,6 +254,30 @@ class GetAgentPlaybooksResponse(BaseModel):
|
|
|
241
254
|
msg: str | None = None
|
|
242
255
|
|
|
243
256
|
|
|
257
|
+
class GetLearningProvenanceRequest(BaseModel):
|
|
258
|
+
kind: Literal["profile", "user_playbook", "agent_playbook"]
|
|
259
|
+
id: str
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class SourceUserPlaybookProvenanceView(BaseModel):
|
|
263
|
+
user_playbook: UserPlaybookView
|
|
264
|
+
interactions: list[InteractionView] = Field(default_factory=list)
|
|
265
|
+
source_interaction_ids: list[int] = Field(default_factory=list)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class LearningProvenanceViewResponse(BaseModel):
|
|
269
|
+
success: bool
|
|
270
|
+
target_kind: Literal["profile", "user_playbook", "agent_playbook"]
|
|
271
|
+
target_id: str
|
|
272
|
+
provenance_status: Literal["exact", "best_effort", "unavailable"] = "unavailable"
|
|
273
|
+
trigger_request_id: str | None = None
|
|
274
|
+
interactions: list[InteractionView] = Field(default_factory=list)
|
|
275
|
+
source_user_playbooks: list[SourceUserPlaybookProvenanceView] = Field(
|
|
276
|
+
default_factory=list
|
|
277
|
+
)
|
|
278
|
+
msg: str | None = None
|
|
279
|
+
|
|
280
|
+
|
|
244
281
|
class SearchUserPlaybookRequest(BaseModel):
|
|
245
282
|
"""Request for searching user playbooks with semantic/text search and filtering.
|
|
246
283
|
|
|
@@ -263,10 +300,15 @@ class SearchUserPlaybookRequest(BaseModel):
|
|
|
263
300
|
start_time: datetime | None = None
|
|
264
301
|
end_time: datetime | None = None
|
|
265
302
|
status_filter: list[Status | None] | None = None
|
|
303
|
+
tags: list[str] | None = None
|
|
266
304
|
top_k: int | None = Field(default=10, gt=0)
|
|
267
305
|
threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
|
|
268
306
|
enable_reformulation: bool | None = False
|
|
269
307
|
search_mode: SearchMode = SearchMode.HYBRID
|
|
308
|
+
# Caller correlation IDs for billing attribution on the Application line.
|
|
309
|
+
# Optional; consumed by _meter_applied_learnings in server/api.py.
|
|
310
|
+
request_id: str | None = None
|
|
311
|
+
session_id: str | None = None
|
|
270
312
|
|
|
271
313
|
@model_validator(mode="after")
|
|
272
314
|
def check_time_range(self) -> Self:
|
|
@@ -316,10 +358,15 @@ class SearchAgentPlaybookRequest(BaseModel):
|
|
|
316
358
|
end_time: datetime | None = None
|
|
317
359
|
status_filter: list[Status | None] | None = None
|
|
318
360
|
playbook_status_filter: PlaybookStatus | list[PlaybookStatus] | None = None
|
|
361
|
+
tags: list[str] | None = None
|
|
319
362
|
top_k: int | None = Field(default=10, gt=0)
|
|
320
363
|
threshold: float | None = Field(default=0.4, ge=0.0, le=1.0)
|
|
321
364
|
enable_reformulation: bool | None = False
|
|
322
365
|
search_mode: SearchMode = SearchMode.HYBRID
|
|
366
|
+
# Caller correlation IDs for billing attribution on the Application line.
|
|
367
|
+
# Optional; consumed by _meter_applied_learnings in server/api.py.
|
|
368
|
+
request_id: str | None = None
|
|
369
|
+
session_id: str | None = None
|
|
323
370
|
|
|
324
371
|
@model_validator(mode="after")
|
|
325
372
|
def check_time_range(self) -> Self:
|
|
@@ -621,6 +668,11 @@ class UnifiedSearchRequest(BaseModel):
|
|
|
621
668
|
enable_reformulation: bool | None = False
|
|
622
669
|
enable_agent_answer: bool | None = False
|
|
623
670
|
search_mode: SearchMode = SearchMode.HYBRID
|
|
671
|
+
# Caller correlation IDs for billing attribution on the Application line.
|
|
672
|
+
# Optional; consumed by _meter_applied_learnings in server/api.py.
|
|
673
|
+
request_id: str | None = None
|
|
674
|
+
session_id: str | None = None
|
|
675
|
+
interaction_id: int | None = Field(default=None, gt=0)
|
|
624
676
|
|
|
625
677
|
|
|
626
678
|
class UnifiedSearchResponse(BaseModel):
|
|
@@ -78,6 +78,8 @@ def to_profile_view(profile: UserProfile) -> ProfileView:
|
|
|
78
78
|
status=profile.status,
|
|
79
79
|
extractor_names=profile.extractor_names,
|
|
80
80
|
source_span=profile.source_span,
|
|
81
|
+
source_interaction_ids=profile.source_interaction_ids,
|
|
82
|
+
tags=profile.tags or [],
|
|
81
83
|
)
|
|
82
84
|
|
|
83
85
|
|
|
@@ -104,6 +106,7 @@ def to_user_playbook_view(rf: UserPlaybook) -> UserPlaybookView:
|
|
|
104
106
|
source=rf.source,
|
|
105
107
|
source_interaction_ids=rf.source_interaction_ids,
|
|
106
108
|
source_span=rf.source_span,
|
|
109
|
+
tags=rf.tags or [],
|
|
107
110
|
)
|
|
108
111
|
|
|
109
112
|
|
|
@@ -127,6 +130,7 @@ def to_agent_playbook_view(fb: AgentPlaybook) -> AgentPlaybookView:
|
|
|
127
130
|
playbook_status=fb.playbook_status,
|
|
128
131
|
playbook_metadata=fb.playbook_metadata,
|
|
129
132
|
status=fb.status,
|
|
133
|
+
tags=fb.tags or [],
|
|
130
134
|
)
|
|
131
135
|
|
|
132
136
|
|
|
@@ -143,6 +147,7 @@ def to_evaluation_result_view(
|
|
|
143
147
|
"""
|
|
144
148
|
return EvaluationResultView(
|
|
145
149
|
result_id=result.result_id,
|
|
150
|
+
user_id=result.user_id,
|
|
146
151
|
agent_version=result.agent_version,
|
|
147
152
|
session_id=result.session_id,
|
|
148
153
|
is_success=result.is_success,
|
|
@@ -173,5 +178,4 @@ def to_profile_change_log_view(log: ProfileChangeLog) -> ProfileChangeLogView:
|
|
|
173
178
|
created_at=log.created_at,
|
|
174
179
|
added_profiles=[to_profile_view(p) for p in log.added_profiles],
|
|
175
180
|
removed_profiles=[to_profile_view(p) for p in log.removed_profiles],
|
|
176
|
-
mentioned_profiles=[to_profile_view(p) for p in log.mentioned_profiles],
|
|
177
181
|
)
|
|
@@ -65,6 +65,8 @@ class ProfileView(BaseModel):
|
|
|
65
65
|
status: Status | None = None
|
|
66
66
|
extractor_names: list[str] | None = None
|
|
67
67
|
source_span: str | None = None
|
|
68
|
+
source_interaction_ids: list[int] = Field(default_factory=list)
|
|
69
|
+
tags: list[str] = Field(default_factory=list)
|
|
68
70
|
|
|
69
71
|
|
|
70
72
|
class UserPlaybookView(BaseModel):
|
|
@@ -83,6 +85,7 @@ class UserPlaybookView(BaseModel):
|
|
|
83
85
|
source: str | None = None
|
|
84
86
|
source_interaction_ids: list[int] = Field(default_factory=list)
|
|
85
87
|
source_span: str | None = None
|
|
88
|
+
tags: list[str] = Field(default_factory=list)
|
|
86
89
|
|
|
87
90
|
|
|
88
91
|
class AgentPlaybookView(BaseModel):
|
|
@@ -98,12 +101,14 @@ class AgentPlaybookView(BaseModel):
|
|
|
98
101
|
playbook_status: PlaybookStatus = PlaybookStatus.PENDING
|
|
99
102
|
playbook_metadata: str = ""
|
|
100
103
|
status: Status | None = None
|
|
104
|
+
tags: list[str] = Field(default_factory=list)
|
|
101
105
|
|
|
102
106
|
|
|
103
107
|
class EvaluationResultView(BaseModel):
|
|
104
108
|
"""User-facing AgentSuccessEvaluationResult — excludes embedding."""
|
|
105
109
|
|
|
106
110
|
result_id: int = 0
|
|
111
|
+
user_id: str = ""
|
|
107
112
|
agent_version: str
|
|
108
113
|
session_id: str
|
|
109
114
|
is_success: bool
|
|
@@ -126,4 +131,3 @@ class ProfileChangeLogView(BaseModel):
|
|
|
126
131
|
created_at: int = Field(default_factory=lambda: int(datetime.now(UTC).timestamp()))
|
|
127
132
|
added_profiles: list[ProfileView]
|
|
128
133
|
removed_profiles: list[ProfileView]
|
|
129
|
-
mentioned_profiles: list[ProfileView]
|
|
@@ -95,7 +95,13 @@ def _migrate_dict(data: Any, mapping: dict[str, str]) -> Any:
|
|
|
95
95
|
if isinstance(data, dict):
|
|
96
96
|
data = dict(data)
|
|
97
97
|
for old, new in mapping.items():
|
|
98
|
-
if old
|
|
98
|
+
if old not in data:
|
|
99
|
+
continue
|
|
100
|
+
# New name wins when both are present; always drop the old key so it
|
|
101
|
+
# doesn't survive into validation and trip ``extra="forbid"``.
|
|
102
|
+
if new in data:
|
|
103
|
+
data.pop(old)
|
|
104
|
+
else:
|
|
99
105
|
data[new] = data.pop(old)
|
|
100
106
|
return data
|
|
101
107
|
|
|
@@ -397,6 +403,16 @@ class DeduplicationConfig(BaseModel):
|
|
|
397
403
|
SINGLETON_PROFILE_EXTRACTOR_NAME = "profile"
|
|
398
404
|
SINGLETON_USER_PLAYBOOK_NAME = "playbook"
|
|
399
405
|
SINGLETON_AGENT_SUCCESS_EVALUATION_NAME = "agent_success"
|
|
406
|
+
DEFAULT_AGENT_SUCCESS_SAMPLING_RATE = 0.05
|
|
407
|
+
DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT = (
|
|
408
|
+
"Evaluate whether the AI agent successfully handled the user's session.\n\n"
|
|
409
|
+
"Mark the session successful when, by the end of the conversation, the agent:\n"
|
|
410
|
+
"1. Identified and addressed the user's main goal or question.\n"
|
|
411
|
+
"2. Provided a correct, useful, and actionable response or completed the requested action.\n"
|
|
412
|
+
"Mark the session unsuccessful when the agent failed to understand the request,\n"
|
|
413
|
+
"gave incorrect or unhelpful guidance, did not complete an available action,\n"
|
|
414
|
+
"ignored important constraints, or left the user unsatisfied."
|
|
415
|
+
)
|
|
400
416
|
|
|
401
417
|
|
|
402
418
|
class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
|
|
@@ -405,7 +421,7 @@ class ProfileExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
|
|
|
405
421
|
extractor_name: NonEmptyStr | None = None
|
|
406
422
|
extraction_definition_prompt: SanitizedNonEmptyStr
|
|
407
423
|
context_prompt: str | None = None
|
|
408
|
-
|
|
424
|
+
tagging_definition_prompt: str | None = None
|
|
409
425
|
should_extract_profile_prompt_override: str | None = None
|
|
410
426
|
request_sources_enabled: list[str] | None = (
|
|
411
427
|
None # default enabled for all sources, if set, only extract profiles from the enabled request sources
|
|
@@ -456,7 +472,7 @@ class UserPlaybookExtractorConfig(_ExtractorWindowOverrideCompatMixin, BaseModel
|
|
|
456
472
|
extractor_name: NonEmptyStr | None = None
|
|
457
473
|
extraction_definition_prompt: SanitizedNonEmptyStr
|
|
458
474
|
context_prompt: str | None = None
|
|
459
|
-
|
|
475
|
+
tagging_definition_prompt: str | None = None
|
|
460
476
|
aggregation_config: PlaybookAggregatorConfig | None = None
|
|
461
477
|
deduplication_config: DeduplicationConfig | None = None
|
|
462
478
|
request_sources_enabled: list[str] | None = (
|
|
@@ -488,9 +504,15 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
|
|
|
488
504
|
evaluation_name: NonEmptyStr | None = None
|
|
489
505
|
success_definition_prompt: SanitizedNonEmptyStr
|
|
490
506
|
metadata_definition_prompt: str | None = None
|
|
507
|
+
request_sources_enabled: list[str] | None = (
|
|
508
|
+
None # default enabled for all sources, if set, only evaluate requests from the enabled request sources
|
|
509
|
+
)
|
|
491
510
|
sampling_rate: float = Field(
|
|
492
|
-
default=
|
|
493
|
-
|
|
511
|
+
default=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
|
|
512
|
+
ge=0.0,
|
|
513
|
+
le=1.0,
|
|
514
|
+
description="Fraction of sessions to evaluate automatically.",
|
|
515
|
+
)
|
|
494
516
|
window_size_override: int | None = Field(default=None, gt=0)
|
|
495
517
|
stride_size_override: int | None = Field(default=None, gt=0)
|
|
496
518
|
|
|
@@ -500,6 +522,14 @@ class AgentSuccessConfig(_ExtractorWindowOverrideCompatMixin, BaseModel):
|
|
|
500
522
|
return _migrate_dict(data, _EXTRACTOR_OVERRIDE_MIGRATION)
|
|
501
523
|
|
|
502
524
|
|
|
525
|
+
def _default_agent_success_config() -> AgentSuccessConfig:
|
|
526
|
+
return AgentSuccessConfig(
|
|
527
|
+
evaluation_name=SINGLETON_AGENT_SUCCESS_EVALUATION_NAME,
|
|
528
|
+
success_definition_prompt=DEFAULT_AGENT_SUCCESS_DEFINITION_PROMPT,
|
|
529
|
+
sampling_rate=DEFAULT_AGENT_SUCCESS_SAMPLING_RATE,
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
|
|
503
533
|
class ReflectionConfig(BaseModel):
|
|
504
534
|
"""Configuration for the sliding-window reflection step.
|
|
505
535
|
|
|
@@ -559,7 +589,7 @@ class RetrievalFloorConfig(BaseModel):
|
|
|
559
589
|
weak tail that drives false-positive citations. Calibrate per arm on real data.
|
|
560
590
|
"""
|
|
561
591
|
|
|
562
|
-
enabled: bool =
|
|
592
|
+
enabled: bool = False
|
|
563
593
|
pool_size: int = Field(
|
|
564
594
|
default=30,
|
|
565
595
|
gt=0,
|
|
@@ -634,6 +664,50 @@ class PlaybookOptimizerConfig(BaseModel):
|
|
|
634
664
|
return self
|
|
635
665
|
|
|
636
666
|
|
|
667
|
+
class LineageGCConfig(BaseModel):
|
|
668
|
+
"""Configuration for the tombstone garbage-collection job (enabled by default).
|
|
669
|
+
|
|
670
|
+
Purpose
|
|
671
|
+
-------
|
|
672
|
+
Retains tombstone content for ``tombstone_grace_window_days`` days after the
|
|
673
|
+
row's *retirement instant* (``retired_at``) to support audit, replay of dedup
|
|
674
|
+
and aggregation runs, and rollback. After the window expires the row is
|
|
675
|
+
hard-deleted and a ``hard_delete`` lineage event is recorded.
|
|
676
|
+
|
|
677
|
+
Age basis
|
|
678
|
+
---------
|
|
679
|
+
The GC ages on ``retired_at`` — the INTEGER epoch set when a row is tombstoned
|
|
680
|
+
(merged, superseded, or archived). Rows with ``retired_at = NULL`` (created
|
|
681
|
+
before the column was added) are never eligible; they have no retirement clock.
|
|
682
|
+
|
|
683
|
+
Grace window
|
|
684
|
+
------------
|
|
685
|
+
90 days is the default grace window. This matches common 90-day soft-delete
|
|
686
|
+
retention policies and satisfies GDPR Art. 5(1)(e) storage-limitation for
|
|
687
|
+
personal data in profiles. The value is a per-deployment policy knob; ratify
|
|
688
|
+
with your DPO before shortening it in production. The 90-day floor also
|
|
689
|
+
preserves tombstones long enough for B3 changelog replay and rollback
|
|
690
|
+
consumers — raise ``tombstone_grace_window_days`` further if your replay
|
|
691
|
+
horizon exceeds 90 days.
|
|
692
|
+
|
|
693
|
+
Enabled by default
|
|
694
|
+
------------------
|
|
695
|
+
GC is ON by default so tombstones created by the soft-delete flags (also ON by
|
|
696
|
+
default) are reclaimed automatically. Disabling GC while soft-delete is enabled
|
|
697
|
+
allows tombstone counts to grow without bound — only do this deliberately (e.g.
|
|
698
|
+
extended audit hold) and with a plan to re-enable.
|
|
699
|
+
|
|
700
|
+
Disabling
|
|
701
|
+
---------
|
|
702
|
+
Set ``enabled = False`` in your deployment config to hold all tombstones
|
|
703
|
+
indefinitely (e.g. for an extended audit window or rollback standby period).
|
|
704
|
+
"""
|
|
705
|
+
|
|
706
|
+
enabled: bool = True
|
|
707
|
+
tombstone_grace_window_days: int = Field(default=90, gt=0)
|
|
708
|
+
poll_interval_seconds: int = Field(default=86400, gt=0)
|
|
709
|
+
|
|
710
|
+
|
|
637
711
|
@dataclass(frozen=True)
|
|
638
712
|
class EffectivePendingToolCallConfig:
|
|
639
713
|
"""Resolved pending-tool-call settings after applying tool overrides."""
|
|
@@ -733,6 +807,8 @@ def _default_user_playbook_extractor_config() -> UserPlaybookExtractorConfig:
|
|
|
733
807
|
|
|
734
808
|
|
|
735
809
|
class Config(BaseModel):
|
|
810
|
+
model_config = ConfigDict(extra="forbid")
|
|
811
|
+
|
|
736
812
|
# define where user configuration is stored at
|
|
737
813
|
storage_config: StorageConfig
|
|
738
814
|
storage_config_test: StorageConfigTest | None = StorageConfigTest.UNKNOWN
|
|
@@ -749,7 +825,9 @@ class Config(BaseModel):
|
|
|
749
825
|
default_factory=_default_user_playbook_extractor_config
|
|
750
826
|
)
|
|
751
827
|
# agent level success
|
|
752
|
-
agent_success_config: AgentSuccessConfig | None =
|
|
828
|
+
agent_success_config: AgentSuccessConfig | None = Field(
|
|
829
|
+
default_factory=_default_agent_success_config
|
|
830
|
+
)
|
|
753
831
|
# extraction preset — selects bundled window_size/stride_size values
|
|
754
832
|
extraction_preset: ExtractionPreset | None = None
|
|
755
833
|
# extraction parameters
|
|
@@ -767,6 +845,8 @@ class Config(BaseModel):
|
|
|
767
845
|
playbook_optimizer_config: PlaybookOptimizerConfig = Field(
|
|
768
846
|
default_factory=PlaybookOptimizerConfig
|
|
769
847
|
)
|
|
848
|
+
# Tombstone GC job gate (opt-in, off by default — see LineageGCConfig)
|
|
849
|
+
lineage_gc: LineageGCConfig = Field(default_factory=LineageGCConfig)
|
|
770
850
|
# Optional non-blocking async information tools for classic extraction.
|
|
771
851
|
pending_tool_call_config: PendingToolCallConfig = Field(
|
|
772
852
|
default_factory=PendingToolCallConfig
|
|
@@ -824,6 +904,7 @@ class Config(BaseModel):
|
|
|
824
904
|
"stride_size",
|
|
825
905
|
"reflection_config",
|
|
826
906
|
"playbook_optimizer_config",
|
|
907
|
+
"lineage_gc",
|
|
827
908
|
"pending_tool_call_config",
|
|
828
909
|
"retrieval_floor",
|
|
829
910
|
):
|