claude-smart 0.2.44 → 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 +77 -29
- package/plugin/scripts/backend-service.sh +27 -5
- package/plugin/scripts/dashboard-service.sh +7 -5
- package/plugin/scripts/ensure-plugin-root.sh +4 -4
- package/plugin/scripts/hook_entry.sh +3 -3
- 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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Provider-safe base class for LLM structured-output Pydantic models.
|
|
2
|
+
|
|
3
|
+
Every Pydantic model sent to an LLM as a structured-output schema (a
|
|
4
|
+
``response_format`` or a tool's parameter schema) should inherit
|
|
5
|
+
``StrictStructuredOutput``. It carries a ``__get_pydantic_json_schema__`` hook
|
|
6
|
+
(via ``ProviderSafeUnionMixin``) that folds a discriminated union's ``oneOf`` into
|
|
7
|
+
``anyOf`` and drops ``discriminator`` in the *emitted* JSON schema, so strict
|
|
8
|
+
structured-output endpoints (OpenAI, minimax) accept it **by construction** — with
|
|
9
|
+
no provider-detection gate and no post-processing. Only the wire schema is
|
|
10
|
+
rewritten; the core (validation) schema keeps the discriminator, so keyed dispatch
|
|
11
|
+
and precise per-variant errors are preserved.
|
|
12
|
+
|
|
13
|
+
This module lives under ``models/`` (depending only on pydantic) so both
|
|
14
|
+
``models/api_schema/`` schemas and ``server/services/*`` models can inherit the
|
|
15
|
+
base without a layering inversion (a ``models/`` file importing from
|
|
16
|
+
``server/llm/`` would invert the dependency direction).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
from pydantic import BaseModel, GetJsonSchemaHandler
|
|
22
|
+
from pydantic.json_schema import JsonSchemaValue
|
|
23
|
+
from pydantic_core import CoreSchema
|
|
24
|
+
|
|
25
|
+
# Keys whose *values* are name→subschema maps: their entries are user-chosen names
|
|
26
|
+
# (field names, $def names), not JSON-Schema keywords. Traversals must recurse into
|
|
27
|
+
# the subschemas but never treat the names themselves as keywords — otherwise a
|
|
28
|
+
# model with a field literally named ``oneOf`` would be mishandled.
|
|
29
|
+
_SCHEMA_NAME_MAP_KEYS = ("properties", "$defs", "definitions", "patternProperties")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _fold_oneof_to_anyof(node: Any) -> None:
|
|
33
|
+
"""Rewrite ``oneOf`` to ``anyOf`` and drop ``discriminator`` in place (recursive).
|
|
34
|
+
|
|
35
|
+
Pydantic emits ``oneOf`` + ``discriminator`` for a discriminated union, which
|
|
36
|
+
strict structured-output endpoints (OpenAI, minimax) reject. Folding into
|
|
37
|
+
``anyOf`` keeps the identical variant set so generation stays constrained;
|
|
38
|
+
Pydantic still enforces the discriminator after parse, so semantics are
|
|
39
|
+
preserved.
|
|
40
|
+
|
|
41
|
+
Structure-aware: under a name→subschema map (``properties``/``$defs``/…) it
|
|
42
|
+
recurses into the subschemas but does NOT treat a property/``$def`` *name* as a
|
|
43
|
+
keyword — so a model field literally named ``oneOf``/``discriminator`` is
|
|
44
|
+
preserved (only keyword-position occurrences are folded). Precondition:
|
|
45
|
+
``node`` is a finite acyclic tree, as produced by ``model_json_schema()``
|
|
46
|
+
(which expresses recursion via ``$ref``/``$defs`` strings, never in-memory
|
|
47
|
+
cycles) — there is no cycle guard.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
node (Any): A JSON-schema fragment (dict, list, or scalar); mutated in place.
|
|
51
|
+
"""
|
|
52
|
+
if isinstance(node, dict):
|
|
53
|
+
one_of = node.pop("oneOf", None)
|
|
54
|
+
node.pop("discriminator", None)
|
|
55
|
+
if isinstance(one_of, list):
|
|
56
|
+
node["anyOf"] = node.get("anyOf", []) + one_of
|
|
57
|
+
for key, value in node.items():
|
|
58
|
+
if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
|
|
59
|
+
for sub in value.values():
|
|
60
|
+
_fold_oneof_to_anyof(sub)
|
|
61
|
+
else:
|
|
62
|
+
_fold_oneof_to_anyof(value)
|
|
63
|
+
elif isinstance(node, list):
|
|
64
|
+
for item in node:
|
|
65
|
+
_fold_oneof_to_anyof(item)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# Statically the mixin must appear to derive from ``BaseModel`` so the ``super()``
|
|
69
|
+
# call below type-checks; at runtime it is a bare mixin (``object`` base), and
|
|
70
|
+
# ``super()`` resolves to ``BaseModel.__get_pydantic_json_schema__`` via the MRO
|
|
71
|
+
# of the concrete model (e.g. ``class X(ProviderSafeUnionMixin, BaseModel)``).
|
|
72
|
+
_ProviderSafeUnionBase = BaseModel if TYPE_CHECKING else object
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ProviderSafeUnionMixin(_ProviderSafeUnionBase):
|
|
76
|
+
"""Make a model emit a provider-safe JSON schema by construction.
|
|
77
|
+
|
|
78
|
+
A model containing a Pydantic discriminated union serializes to JSON Schema
|
|
79
|
+
with ``oneOf`` + ``discriminator``, which strict structured-output endpoints
|
|
80
|
+
reject (the Sentry ``PYTHON-FASTAPI-9J`` incident). Mixing this in folds
|
|
81
|
+
``oneOf`` into ``anyOf`` (and drops ``discriminator``) at the model boundary,
|
|
82
|
+
so every caller of ``model_json_schema()`` — litellm, instructor, our own
|
|
83
|
+
path — gets a provider-safe schema **unconditionally**, without depending on
|
|
84
|
+
a provider-detection gate (e.g. ``litellm.supports_response_schema``, which
|
|
85
|
+
under-reports some providers). Only the JSON (wire) schema is rewritten; the
|
|
86
|
+
core validation schema keeps the discriminator, so keyed dispatch and precise
|
|
87
|
+
per-variant errors are preserved.
|
|
88
|
+
|
|
89
|
+
Prefer inheriting ``StrictStructuredOutput`` (below) on output models rather
|
|
90
|
+
than mixing this in directly.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
@classmethod
|
|
94
|
+
def __get_pydantic_json_schema__(
|
|
95
|
+
cls, core_schema: CoreSchema, handler: GetJsonSchemaHandler
|
|
96
|
+
) -> JsonSchemaValue:
|
|
97
|
+
# Chain via super() (not handler() directly) so a cooperative base that
|
|
98
|
+
# also customizes __get_pydantic_json_schema__ is not silently shadowed;
|
|
99
|
+
# BaseModel's default impl just invokes handler(core_schema).
|
|
100
|
+
schema = super().__get_pydantic_json_schema__(core_schema, handler)
|
|
101
|
+
_fold_oneof_to_anyof(schema)
|
|
102
|
+
return schema
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class StrictStructuredOutput(ProviderSafeUnionMixin, BaseModel):
|
|
106
|
+
"""Base for every Pydantic model sent to an LLM as a structured-output schema.
|
|
107
|
+
|
|
108
|
+
Inherits the provider-safe schema hook from ``ProviderSafeUnionMixin`` so the
|
|
109
|
+
emitted JSON schema folds any discriminated union (``oneOf``→``anyOf``, drop
|
|
110
|
+
``discriminator``) by construction — accepted by strict structured-output
|
|
111
|
+
providers with no provider gate, including any *future* discriminated union.
|
|
112
|
+
|
|
113
|
+
Deliberately adds NO ``model_config``: each model keeps its own ``extra=`` and
|
|
114
|
+
``json_schema_extra`` exactly as before. This base unifies the *provider-safety
|
|
115
|
+
guarantee*, not the per-model config (centralizing config is a separate change —
|
|
116
|
+
``extra=`` is not uniform across models, so a blanket dedup would silently shift
|
|
117
|
+
validation/serialization behavior).
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def find_schema_keyword(node: Any, keyword: str) -> bool:
|
|
122
|
+
"""Report whether ``keyword`` appears as a JSON-Schema *keyword* anywhere in ``node``.
|
|
123
|
+
|
|
124
|
+
Structure-aware: an occurrence of ``keyword`` as a property/``$defs`` *name*
|
|
125
|
+
(e.g. a model field literally named ``oneOf``) is NOT a match — only an
|
|
126
|
+
occurrence in JSON-Schema keyword position counts. Use this (not a blind
|
|
127
|
+
``in``-walk) to check a schema for provider-unsafe keywords.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
node (Any): A JSON-schema fragment (dict, list, or scalar).
|
|
131
|
+
keyword (str): The JSON-Schema keyword to search for (e.g. ``"oneOf"``).
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
bool: True if ``keyword`` appears in keyword position, else False.
|
|
135
|
+
"""
|
|
136
|
+
if isinstance(node, dict):
|
|
137
|
+
if keyword in node:
|
|
138
|
+
return True
|
|
139
|
+
for key, value in node.items():
|
|
140
|
+
if key in _SCHEMA_NAME_MAP_KEYS and isinstance(value, dict):
|
|
141
|
+
if any(find_schema_keyword(sub, keyword) for sub in value.values()):
|
|
142
|
+
return True
|
|
143
|
+
elif find_schema_keyword(value, keyword):
|
|
144
|
+
return True
|
|
145
|
+
return False
|
|
146
|
+
if isinstance(node, list):
|
|
147
|
+
return any(find_schema_keyword(item, keyword) for item in node)
|
|
148
|
+
return False
|
|
@@ -23,7 +23,7 @@ Client (SDK/Web)
|
|
|
23
23
|
-> GenerationService (server/services/)
|
|
24
24
|
├─> ProfileGenerationService -> ProfileExtractor(s) -> Storage
|
|
25
25
|
├─> PlaybookGenerationService -> PlaybookExtractor(s) -> Storage
|
|
26
|
-
└─> GroupEvaluationScheduler (deferred 10 min) ->
|
|
26
|
+
└─> agent_success_evaluation/scheduler.py:GroupEvaluationScheduler (deferred 10 min) -> agent_success_evaluation/runner.py:run_group_evaluation -> agent_success_evaluation/service.py -> agent_success_evaluation/components/evaluator.py -> Storage
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Prerequisites
|
|
@@ -41,7 +41,7 @@ cp .env.example .env # Configure environment (set at lea
|
|
|
41
41
|
uv sync # Install Python dependencies (includes workspace packages)
|
|
42
42
|
npm --prefix src/website install # Install frontend dependencies
|
|
43
43
|
npm --prefix src/public_docs install # Install docs dependencies
|
|
44
|
-
./run_services.sh # Starts API (
|
|
44
|
+
./run_services.sh # Starts API (8061), Website (8080), Docs (8062)
|
|
45
45
|
./stop_services.sh # Stop all services
|
|
46
46
|
```
|
|
47
47
|
|
|
@@ -56,7 +56,7 @@ npm --prefix src/public_docs install # Install docs dependencies
|
|
|
56
56
|
**Testing:**
|
|
57
57
|
```python
|
|
58
58
|
import reflexio
|
|
59
|
-
client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:
|
|
59
|
+
client = reflexio.ReflexioClient(api_key="your-api-key", url_endpoint="http://127.0.0.1:8061/")
|
|
60
60
|
```
|
|
61
61
|
See `notebooks/reflexio_cookbook.ipynb` and `src/tests/readme.md`
|
|
62
62
|
|
|
@@ -19,6 +19,7 @@ Description: FastAPI backend server that processes user interactions to generate
|
|
|
19
19
|
- [Reflection and Async Extraction](#reflection-and-async-extraction)
|
|
20
20
|
- [Shadow Comparison and Evaluation Overview](#shadow-comparison-and-evaluation-overview)
|
|
21
21
|
- [Playbook Optimizer and Braintrust](#playbook-optimizer-and-braintrust)
|
|
22
|
+
- [Lineage](#lineage)
|
|
22
23
|
- [Query Reformulator](#query-reformulator)
|
|
23
24
|
- [Unified Search Service](#unified-search-service)
|
|
24
25
|
- [Storage](#storage)
|
|
@@ -182,10 +183,11 @@ python -m reflexio.server.scripts.manage_invitation_codes list --show-used
|
|
|
182
183
|
- **Publish pipeline**: `generation_service.py` coordinates interaction persistence, profile generation, playbook generation, reflection, and deferred evaluation scheduling.
|
|
183
184
|
- **Profile memory**: `profile/` extracts, deduplicates, and applies user profile updates.
|
|
184
185
|
- **Playbook memory**: `playbook/` extracts user playbooks, consolidates them against existing rows, aggregates them into agent playbooks, and tracks aggregation change logs.
|
|
185
|
-
- **Evaluation**: `agent_success_evaluation
|
|
186
|
+
- **Evaluation**: `agent_success_evaluation/service.py`, `agent_success_evaluation/runner.py`, `agent_success_evaluation/scheduler.py`, `agent_success_evaluation/components/evaluator.py`, `shadow_comparison/`, and `evaluation_overview/` handle session grading, per-turn shadow verdicts, regeneration jobs, and dashboard-facing rollups.
|
|
186
187
|
- **Async clarification**: `extraction/` and `reflection/` manage resumable agent runs, pending tool calls, prior-answer search, and long-horizon reflection updates.
|
|
187
188
|
- **Search preparation**: `pre_retrieval/` and `unified_search_service.py` handle query reformulation, document expansion, embeddings, and cross-entity search orchestration.
|
|
188
189
|
- **Optimization/integrations**: `playbook_optimizer/` and `braintrust/` run candidate playbook optimization, rollout support, and Braintrust export/sync.
|
|
190
|
+
- **Lineage**: `lineage/` resolves active records across superseded chains and schedules tombstone garbage collection for profile/playbook storage.
|
|
189
191
|
- **Persistence/config**: `storage/`, `configurator/`, and `operation_state_utils.py` provide storage abstractions, config loading, locks, bookmarks, progress, and cancellation.
|
|
190
192
|
|
|
191
193
|
### Orchestrator
|
|
@@ -221,7 +223,7 @@ Called by API endpoints via `Reflexio`
|
|
|
221
223
|
- `extractor_config_utils.py`: Shared utility for filtering extractor configs by source, `allow_manual_trigger`, and extractor names
|
|
222
224
|
- `extractor_interaction_utils.py`: Per-extractor utilities for stride_size checking and source filtering
|
|
223
225
|
- `operation_state_utils.py`: Centralized `OperationStateManager` for all `_operation_state` table interactions (progress tracking, concurrency locks, extractor/aggregator bookmarks, simple locks)
|
|
224
|
-
- `deduplication_utils.py`: Shared utilities for LLM-based deduplication (used by
|
|
226
|
+
- `deduplication_utils.py`: Shared utilities for LLM-based deduplication (used by ProfileConsolidator and PlaybookConsolidator)
|
|
225
227
|
- `service_utils.py`: Utilities (`construct_messages_from_interactions()`, `format_interactions_to_history_string()` (prepends tool usage info when `tools_used` is present), `extract_json_from_string()`, `log_model_response()` for colored LLM response logging)
|
|
226
228
|
|
|
227
229
|
**Operation State Management** (via `OperationStateManager` in `operation_state_utils.py`):
|
|
@@ -242,12 +244,11 @@ Called by API endpoints via `Reflexio`
|
|
|
242
244
|
**Directory**: `services/profile/`
|
|
243
245
|
|
|
244
246
|
Key files:
|
|
245
|
-
- `
|
|
246
|
-
- `
|
|
247
|
-
- `
|
|
248
|
-
- `profile_deduplicator.py`: Deduplicates newly extracted profiles against existing DB profiles using LLM
|
|
247
|
+
- `service.py`: Service orchestrator and profile persistence/finalization
|
|
248
|
+
- `components/extractor.py`: Extractor that generates profile updates
|
|
249
|
+
- `components/consolidator.py`: Consolidates newly extracted profiles against existing DB profiles using LLM
|
|
249
250
|
|
|
250
|
-
**Flow**: Interactions → ProfileExtractor (extraction-only) →
|
|
251
|
+
**Flow**: Interactions → ProfileExtractor (extraction-only) → ProfileConsolidator (deduplicates new vs existing DB profiles) → ProfileGenerationService → Storage
|
|
251
252
|
|
|
252
253
|
**Generation Modes** (detailed comparison):
|
|
253
254
|
|
|
@@ -308,10 +309,10 @@ Users can regenerate and manage profile versions using a four-state system:
|
|
|
308
309
|
**Detailed Documentation**: See [`services/playbook/README.md`](services/playbook/README.md) for detailed component documentation.
|
|
309
310
|
|
|
310
311
|
Key files:
|
|
311
|
-
- `
|
|
312
|
-
- `
|
|
313
|
-
- `
|
|
314
|
-
- `
|
|
312
|
+
- `service.py`: Service orchestrator
|
|
313
|
+
- `components/extractor.py`: Extractor that extracts user playbooks
|
|
314
|
+
- `components/aggregator.py`: Aggregates similar user playbooks (with cluster-level change detection to skip unchanged clusters)
|
|
315
|
+
- `components/consolidator.py`: Reconciles newly extracted playbooks against existing DB playbooks using LLM
|
|
315
316
|
|
|
316
317
|
**Flow**:
|
|
317
318
|
- Interactions → PlaybookExtractor (extraction-only) → PlaybookConsolidator (consolidates new vs existing DB playbooks) → UserPlaybook (with optional `blocking_issue`) → Storage
|
|
@@ -321,7 +322,7 @@ Key files:
|
|
|
321
322
|
|
|
322
323
|
**Rerun Behavior**: Groups interactions by `user_id` for per-user playbook extraction (fetches all users, then processes each user's interactions together)
|
|
323
324
|
|
|
324
|
-
**Playbook Aggregation with Cluster Change Detection** (`
|
|
325
|
+
**Playbook Aggregation with Cluster Change Detection** (`components/aggregator.py`):
|
|
325
326
|
|
|
326
327
|
Aggregation clusters user playbooks by embedding similarity, then calls LLM per cluster to produce aggregated agent playbooks. Cluster-level change detection avoids redundant LLM calls on subsequent runs:
|
|
327
328
|
|
|
@@ -339,7 +340,7 @@ Aggregation clusters user playbooks by embedding similarity, then calls LLM per
|
|
|
339
340
|
| No changes | Logs skip message, updates bookmark, returns early |
|
|
340
341
|
| Error during save | Restores only selectively archived playbooks |
|
|
341
342
|
|
|
342
|
-
**Change Log Tracking**:
|
|
343
|
+
**Change Log Tracking**: The legacy `playbook_aggregation_change_logs` table is retired (Track B, 2026-06-24) — the aggregator no longer writes it. The change-log view served by `GET /api/playbook_aggregation_change_logs` is reconstructed on demand from `lineage_event` rows via `reconstruct_playbook_aggregation_change_log` (`lib/_agent_playbook.py`): each run's `op=aggregate` events form the "added" side and its `status_change→superseded` events form the "removed" side, grouped by `request_id`. Per-row `updated` pairing is not reconstructed (`updated_agent_playbooks=[]`, a tolerated parity delta).
|
|
343
344
|
|
|
344
345
|
**Generation Modes** (detailed comparison):
|
|
345
346
|
|
|
@@ -381,16 +382,16 @@ Similar to profiles, user playbooks support versioning:
|
|
|
381
382
|
**Directory**: `services/agent_success_evaluation/`
|
|
382
383
|
|
|
383
384
|
Key files:
|
|
384
|
-
- `
|
|
385
|
-
- `
|
|
385
|
+
- `service.py`: `AgentSuccessEvaluationService`, the request-path service orchestrator (tracks run outcome flags: `last_run_result_count`, `has_run_failures()`)
|
|
386
|
+
- `components/evaluator.py`: `AgentSuccessEvaluator`, evaluates success at session level (all interactions as one group)
|
|
386
387
|
- `agent_success_evaluation_constants.py`: Output schema (`AgentSuccessEvaluationOutput`)
|
|
387
388
|
- `agent_success_evaluation_utils.py`: Message construction utilities
|
|
388
|
-
- `
|
|
389
|
-
- `
|
|
389
|
+
- `scheduler.py`: `GroupEvaluationScheduler` singleton - min-heap priority queue with daemon thread, defers evaluation until 10 min after last request in session
|
|
390
|
+
- `runner.py`: `run_group_evaluation()` - fetches all requests/interactions for a session, builds `RequestInteractionDataModel` list, runs `service.py`
|
|
390
391
|
|
|
391
|
-
**Flow**: Interactions →
|
|
392
|
+
**Flow**: Interactions → `agent_success_evaluation/scheduler.py` → `agent_success_evaluation/runner.py` → `agent_success_evaluation/service.py` → `agent_success_evaluation/components/evaluator.py` → `AgentSuccessEvaluationResult` → Storage
|
|
392
393
|
|
|
393
|
-
**Session-Level Evaluation**: Evaluator treats
|
|
394
|
+
**Session-Level Evaluation**: Evaluator treats one user's `request_interaction_data_models` in a session as a single conversation. Sampling rate checked once per session (not per-request). Results are keyed by `(user_id, session_id, evaluation_name)` so reused session IDs across users do not clobber each other.
|
|
394
395
|
|
|
395
396
|
**Tool Context**: Reads `tool_can_use` from root `Config` level (shared with playbook extraction).
|
|
396
397
|
|
|
@@ -401,14 +402,14 @@ Key files:
|
|
|
401
402
|
**Directories**: `services/reflection/`, `services/extraction/`
|
|
402
403
|
|
|
403
404
|
Key files:
|
|
404
|
-
- `reflection/
|
|
405
|
-
- `reflection/
|
|
405
|
+
- `reflection/service.py`: Post-horizon reflection orchestration for synthesizing longer-range memory artifacts
|
|
406
|
+
- `reflection/components/extractor.py`: LLM extractor used by the reflection service
|
|
406
407
|
- `extraction/resumable_agent.py`: Resumable extraction agent runtime
|
|
407
408
|
- `extraction/resume_scheduler.py` and `extraction/resume_worker.py`: Background scheduling/worker loop for paused extraction runs
|
|
408
|
-
- `extraction/
|
|
409
|
+
- `extraction/pending_tool_call_dispatch.py` and `extraction/prior_answer_search.py`: Tool surface and prior-answer context for async extraction agents
|
|
409
410
|
- `extraction/agent_run_records.py`: Persistence helpers for extraction-agent run state
|
|
410
411
|
|
|
411
|
-
**Pattern**: Synchronous profile/playbook/evaluation services still follow `BaseGenerationService`; async extraction uses resumable agent-run records and worker scheduling so long-running or tool-mediated extraction can continue outside the request path.
|
|
412
|
+
**Pattern**: Synchronous profile/playbook/evaluation services still follow `BaseGenerationService`; async extraction is a shared runtime package that uses resumable agent-run records and worker scheduling so long-running or tool-mediated extraction can continue outside the request path.
|
|
412
413
|
|
|
413
414
|
### Shadow Comparison and Evaluation Overview
|
|
414
415
|
|
|
@@ -418,7 +419,8 @@ Key files:
|
|
|
418
419
|
- `shadow_comparison/judge.py`: Per-turn regular-vs-shadow judge that writes shadow verdicts through storage
|
|
419
420
|
- `shadow_comparison/outcome.py`: Verdict outcome model helpers
|
|
420
421
|
- `evaluation_overview/service.py`: Aggregates evaluation-page metrics
|
|
421
|
-
- `evaluation_overview/hero_state.py`, `distribution.py`, `
|
|
422
|
+
- `evaluation_overview/components/hero_state.py`, `evaluation_overview/components/distribution.py`, `evaluation_overview/components/rule_attribution.py`, `evaluation_overview/components/shadow_aggregation.py`: Focused aggregation helpers
|
|
423
|
+
- `evaluation_overview/eval_sampler.py`: Evaluation sampling helpers that remain root-level
|
|
422
424
|
|
|
423
425
|
**Pattern**: Session-level agent success evaluation remains in `agent_success_evaluation/`; dashboard-facing rollups and per-turn shadow verdict analysis live in these companion directories.
|
|
424
426
|
|
|
@@ -435,6 +437,17 @@ Key files:
|
|
|
435
437
|
|
|
436
438
|
**Pattern**: These are evaluation/optimization integrations around the core playbook pipeline. Keep production extraction changes in `services/playbook/`; use optimizer/Braintrust modules for experiments, rollouts, and external eval sync.
|
|
437
439
|
|
|
440
|
+
### Lineage
|
|
441
|
+
|
|
442
|
+
**Directory**: `services/lineage/`
|
|
443
|
+
|
|
444
|
+
| File | Purpose |
|
|
445
|
+
|------|---------|
|
|
446
|
+
| `resolve.py` | Helpers for resolving current records across supersede chains and status transitions. |
|
|
447
|
+
| `gc_scheduler.py` | Tombstone garbage-collection scheduler for lineage-aware storage cleanup. |
|
|
448
|
+
|
|
449
|
+
**Pattern**: profile/playbook update paths preserve lineage metadata in storage; service code asks lineage helpers to find current records rather than walking superseded chains ad hoc.
|
|
450
|
+
|
|
438
451
|
### Query Reformulator
|
|
439
452
|
|
|
440
453
|
**File**: `services/pre_retrieval/_query_reformulator.py` - `QueryReformulator`
|
|
@@ -464,8 +477,8 @@ Pre-computed embeddings passed to storage methods via `query_embedding` paramete
|
|
|
464
477
|
|
|
465
478
|
| File | Purpose |
|
|
466
479
|
|------|---------|
|
|
467
|
-
| `storage_base/` | BaseStorage interface split by domain (`_profiles.py`, `_playbook.py`, `_requests.py`, `_operations.py`, `_agent_run.py`, `_shadow_verdicts.py`, `_stall_state.py`, `_share_links.py`) |
|
|
468
|
-
| `sqlite_storage/` | SQLite-backed implementation split across the same domains |
|
|
480
|
+
| `storage_base/` | BaseStorage interface split by domain (`_profiles.py`, `_playbook.py`, `_requests.py`, `_operations.py`, `_agent_run.py`, `_lineage.py`, `_shadow_verdicts.py`, `_stall_state.py`, `_share_links.py`) |
|
|
481
|
+
| `sqlite_storage/` | SQLite-backed implementation split across the same domains, including lineage/tombstone support in `_lineage.py` |
|
|
469
482
|
| `retention.py`, `retention_mixin.py` | Data retention and cleanup helpers |
|
|
470
483
|
| `constants.py`, `error.py` | Storage constants and shared errors |
|
|
471
484
|
|
|
@@ -513,7 +526,7 @@ API Request (api.py)
|
|
|
513
526
|
-> GenerationService
|
|
514
527
|
├─> ProfileGenerationService → Storage
|
|
515
528
|
├─> PlaybookGenerationService → Storage
|
|
516
|
-
└─> GroupEvaluationScheduler (deferred 10 min) → run_group_evaluation → Storage
|
|
529
|
+
└─> agent_success_evaluation/scheduler.py:GroupEvaluationScheduler (deferred 10 min) → agent_success_evaluation/runner.py:run_group_evaluation → agent_success_evaluation/service.py → Storage
|
|
517
530
|
```
|
|
518
531
|
|
|
519
532
|
```mermaid
|
|
@@ -529,9 +542,9 @@ flowchart TB
|
|
|
529
542
|
subgraph ProfileService["ProfileGenerationService"]
|
|
530
543
|
E --> F1[ProfileExtractor 1]
|
|
531
544
|
E --> F2[ProfileExtractor N]
|
|
532
|
-
F1 -->
|
|
533
|
-
F2 -->
|
|
534
|
-
|
|
545
|
+
F1 --> PC[ProfileConsolidator]
|
|
546
|
+
F2 --> PC
|
|
547
|
+
PC --> PU[ProfileUpdater]
|
|
535
548
|
end
|
|
536
549
|
|
|
537
550
|
subgraph PlaybookService["PlaybookGenerationService"]
|
|
@@ -542,7 +555,7 @@ flowchart TB
|
|
|
542
555
|
end
|
|
543
556
|
|
|
544
557
|
subgraph EvalService["AgentSuccessEvaluationService"]
|
|
545
|
-
E -.->|deferred 10 min| SCH[GroupEvaluationScheduler]
|
|
558
|
+
E -.->|deferred 10 min| SCH[agent_success_evaluation/scheduler.py<br/>GroupEvaluationScheduler]
|
|
546
559
|
SCH --> H1[AgentSuccessEvaluator 1]
|
|
547
560
|
SCH --> H2[AgentSuccessEvaluator N]
|
|
548
561
|
end
|
|
@@ -561,7 +574,7 @@ flowchart TB
|
|
|
561
574
|
J -.-> F1
|
|
562
575
|
J -.-> G1
|
|
563
576
|
J -.-> H1
|
|
564
|
-
J -.->
|
|
577
|
+
J -.-> PC
|
|
565
578
|
J -.-> FD
|
|
566
579
|
K -.-> F1
|
|
567
580
|
K -.-> G1
|
|
@@ -38,9 +38,6 @@ LOCAL_STORAGE_PATH = (
|
|
|
38
38
|
INTERACTION_CLEANUP_THRESHOLD = int(
|
|
39
39
|
os.environ.get("INTERACTION_CLEANUP_THRESHOLD", "250000")
|
|
40
40
|
)
|
|
41
|
-
INTERACTION_CLEANUP_DELETE_COUNT = int(
|
|
42
|
-
os.environ.get("INTERACTION_CLEANUP_DELETE_COUNT", "50000")
|
|
43
|
-
)
|
|
44
41
|
|
|
45
42
|
# Logging
|
|
46
43
|
|
|
@@ -131,10 +128,37 @@ class _LLMIOFormatter(_TZAwareFormatter):
|
|
|
131
128
|
)
|
|
132
129
|
|
|
133
130
|
|
|
134
|
-
|
|
131
|
+
def _truthy_env(name: str) -> bool:
|
|
132
|
+
"""Return whether an environment variable is explicitly truthy."""
|
|
133
|
+
raw = os.environ.get(name, "").strip().lower()
|
|
134
|
+
return raw in ("true", "yes", "1", "on")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _is_production_environment() -> bool:
|
|
138
|
+
"""Return whether this process is running in a production deployment."""
|
|
139
|
+
return os.environ.get("ENVIRONMENT", "").strip().lower() in ("prod", "production")
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _debug_log_to_console_enabled() -> bool:
|
|
143
|
+
"""Return whether verbose console logging should be enabled.
|
|
144
|
+
|
|
145
|
+
``DEBUG_LOG_TO_CONSOLE`` is a local/dev switch. Deployments with
|
|
146
|
+
``ENVIRONMENT=production`` must stay quiet by default even if a copied local
|
|
147
|
+
env file accidentally sets it;
|
|
148
|
+
use ``REFLEXIO_ALLOW_PRODUCTION_DEBUG_LOGS=true`` for a deliberate incident
|
|
149
|
+
override.
|
|
150
|
+
"""
|
|
151
|
+
if not _truthy_env("DEBUG_LOG_TO_CONSOLE"):
|
|
152
|
+
return False
|
|
153
|
+
return not _is_production_environment() or _truthy_env(
|
|
154
|
+
"REFLEXIO_ALLOW_PRODUCTION_DEBUG_LOGS"
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
DEBUG_LOG_TO_CONSOLE = _debug_log_to_console_enabled()
|
|
135
159
|
root_logger = logging.getLogger()
|
|
136
160
|
|
|
137
|
-
if DEBUG_LOG_TO_CONSOLE
|
|
161
|
+
if DEBUG_LOG_TO_CONSOLE:
|
|
138
162
|
# Correlation ID filter — injects %(correlation_id)s into every record
|
|
139
163
|
from reflexio.server.correlation import CorrelationIdFilter
|
|
140
164
|
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Run the FastAPI backend with Reflexio's uvicorn log config applied upfront::
|
|
4
4
|
|
|
5
5
|
# Dev mode (autoreload, single process):
|
|
6
|
-
python -m reflexio.server --port
|
|
6
|
+
python -m reflexio.server --port 8061 --reload
|
|
7
7
|
|
|
8
8
|
# Daemon mode (multi-worker with recycling):
|
|
9
|
-
python -m reflexio.server --port
|
|
9
|
+
python -m reflexio.server --port 8061 --workers 2 --max-requests 10000
|
|
10
10
|
|
|
11
11
|
Flags mirror the subset of ``uvicorn`` CLI options that
|
|
12
12
|
:func:`reflexio.cli.run_services.build_backend_service` uses.
|
|
@@ -9,17 +9,80 @@ import graph acyclic.
|
|
|
9
9
|
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from functools import cache
|
|
14
|
+
|
|
12
15
|
DEFAULT_ORG_ID = "self-host-org"
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
def default_get_org_id() -> str:
|
|
16
19
|
"""Return the default organization ID for local hosting.
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
Reads ``REFLEXIO_DEFAULT_ORG_ID`` (unset/blank falls back to
|
|
22
|
+
:data:`DEFAULT_ORG_ID`) so a no-auth deployment can run under a distinct
|
|
23
|
+
org id without colliding with another local backend that shares
|
|
24
|
+
``~/.reflexio/configs/``. claude-smart and the self-host backend otherwise
|
|
25
|
+
both default to ``self-host-org`` and fight over the same
|
|
26
|
+
``config_self-host-org.json``.
|
|
27
|
+
|
|
28
|
+
Enterprise deployments never reach this: they override the dependency via
|
|
19
29
|
``app.dependency_overrides[default_get_org_id] = <bearer_auth_resolver>``
|
|
20
30
|
inside :func:`reflexio.server.api.create_app`.
|
|
21
31
|
|
|
22
32
|
Returns:
|
|
23
33
|
str: The default org identifier used for self-hosted deployments.
|
|
24
34
|
"""
|
|
25
|
-
|
|
35
|
+
# Lazy import keeps this deliberately cycle-free module independent of the
|
|
36
|
+
# ``reflexio.server`` package init (see module docstring).
|
|
37
|
+
from reflexio.server.env_utils import env_str
|
|
38
|
+
|
|
39
|
+
return env_str("REFLEXIO_DEFAULT_ORG_ID", DEFAULT_ORG_ID)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def default_get_caller_type() -> str:
|
|
43
|
+
"""Return the default caller type for local / self-hosted deployments.
|
|
44
|
+
|
|
45
|
+
Every call is treated as ``"internal"`` (no billing discrimination) in the
|
|
46
|
+
OSS build. Enterprise deployments override this via
|
|
47
|
+
``app.dependency_overrides[default_get_caller_type] = <classifier>``
|
|
48
|
+
inside :func:`reflexio.server.api.create_app`, exactly like
|
|
49
|
+
:func:`default_get_org_id`.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
str: The literal ``"internal"`` — equals ``BillingCallerType.INTERNAL.value``
|
|
53
|
+
(kept as a plain string here so OSS stays free of reflexio_ext imports).
|
|
54
|
+
"""
|
|
55
|
+
return "internal" # == BillingCallerType.INTERNAL.value; literal keeps OSS clean
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@cache
|
|
59
|
+
def default_billing_gate(line: str) -> Callable[..., None]: # noqa: ARG001
|
|
60
|
+
"""Return a stable no-op FastAPI dependency for the billing gate.
|
|
61
|
+
|
|
62
|
+
OSS / self-hosted deployments run without enforcement — this factory
|
|
63
|
+
always returns a dependency that does nothing. Enterprise deployments
|
|
64
|
+
supply a real gate factory via the ``get_billing_gate`` parameter of
|
|
65
|
+
:func:`reflexio.server.api.create_app`, exactly mirroring how
|
|
66
|
+
``get_caller_type`` overrides :func:`default_get_caller_type`.
|
|
67
|
+
|
|
68
|
+
``lru_cache`` ensures the **same callable object** is returned for the
|
|
69
|
+
same ``line`` value. FastAPI uses callable identity for
|
|
70
|
+
``dependency_overrides``, so caching is essential: without it, each
|
|
71
|
+
``Depends(default_billing_gate("application"))`` would create a fresh
|
|
72
|
+
closure and overrides would silently never fire.
|
|
73
|
+
|
|
74
|
+
OSS code must never import from ``reflexio_ext`` — the gate wiring is
|
|
75
|
+
purely additive and backwards-compatible.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
line (str): Billing line (e.g. ``"application"``, ``"learnings_generated"``).
|
|
79
|
+
Accepted but unused in the default no-op implementation.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Callable[..., None]: A FastAPI dependency that always passes through.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
def _noop() -> None:
|
|
86
|
+
"""No-op billing gate for OSS / self-hosted deployments."""
|
|
87
|
+
|
|
88
|
+
return _noop
|