claude-smart 0.2.45 → 0.2.47
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 +47 -10
- package/bin/claude-smart.js +535 -23
- 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 +27 -6
- 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/layout.tsx +20 -0
- 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 +232 -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 +251 -0
- package/plugin/opencode/tsconfig.json +13 -0
- package/plugin/pyproject.toml +25 -4
- 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 +17 -9
- package/plugin/src/README.md +1 -1
- package/plugin/src/claude_smart/cli.py +498 -12
- package/plugin/src/claude_smart/context_format.py +9 -9
- package/plugin/src/claude_smart/cs_cite.py +66 -19
- 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 +5 -5
- package/plugin/vendor/reflexio/.env.example +54 -30
- package/plugin/vendor/reflexio/README.md +17 -11
- package/plugin/vendor/reflexio/pyproject.toml +13 -1
- package/plugin/vendor/reflexio/reflexio/README.md +4 -1
- 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 +212 -52
- 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/cli/utils.py +44 -1
- package/plugin/vendor/reflexio/reflexio/client/client.py +154 -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 +246 -10
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +15 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +17 -5
- package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +224 -21
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +52 -25
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +11 -1
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +1 -0
- 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/domain/governance.py +117 -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 +97 -3
- 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 +104 -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 +58 -33
- 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/api.py +899 -103
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +4 -2
- package/plugin/vendor/reflexio/reflexio/server/auth.py +90 -0
- 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/extensions.py +213 -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/model_defaults.py +4 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1 -1
- 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/rerank/cross_encoder_reranker.py +12 -1
- 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 +278 -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 +28 -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 +47 -16
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
- package/plugin/vendor/reflexio/reflexio/server/services/governance/config.py +52 -0
- package/plugin/vendor/reflexio/reflexio/server/services/governance/service.py +378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/governance/subject_refs.py +34 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +219 -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 +18 -11
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/aggregation_prompt_processing.py +100 -0
- 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} +334 -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_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} +31 -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/recency.py +211 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +99 -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 +31 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/governance_validation.py +681 -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 +16 -2
- 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 +644 -197
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +106 -119
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_governance.py +1965 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +630 -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 +31 -1369
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +756 -210
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +148 -34
- 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/sqlite_storage/playbook/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_agent.py +952 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_eval_results.py +189 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_optimization.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_source_linkage.py +145 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/playbook/_user.py +838 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +150 -23
- 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 +40 -57
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_governance.py +148 -0
- 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 +4 -677
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +134 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +62 -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/storage/storage_base/playbook/__init__.py +13 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_agent.py +365 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_eval_results.py +124 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_optimization.py +85 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_source_linkage.py +47 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/playbook/_user.py +333 -0
- package/plugin/vendor/reflexio/reflexio/server/services/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 +372 -34
- 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/_auth.py +0 -25
- 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
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import os
|
|
5
|
+
import uuid
|
|
5
6
|
from datetime import UTC, datetime
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
@@ -12,11 +13,11 @@ from reflexio.models.api_schema.service_schemas import (
|
|
|
12
13
|
from reflexio.models.config_schema import ProfileExtractorConfig
|
|
13
14
|
from reflexio.server.api_endpoints.request_context import RequestContext
|
|
14
15
|
from reflexio.server.llm.litellm_client import LiteLLMClient
|
|
16
|
+
from reflexio.server.llm.token_accounting import RunTokenTotals, sum_trace_tokens
|
|
15
17
|
from reflexio.server.services.extraction.outcome import ExtractionOutcome
|
|
16
18
|
from reflexio.server.services.extraction.resumable_agent import (
|
|
17
19
|
run_resumable_extraction_agent,
|
|
18
20
|
)
|
|
19
|
-
from reflexio.server.services.extraction.tools import new_profile_id
|
|
20
21
|
from reflexio.server.services.extractor_config_utils import get_extractor_name
|
|
21
22
|
from reflexio.server.services.extractor_interaction_utils import (
|
|
22
23
|
get_effective_source_filter,
|
|
@@ -25,7 +26,7 @@ from reflexio.server.services.extractor_interaction_utils import (
|
|
|
25
26
|
from reflexio.server.services.operation_state_utils import OperationStateManager
|
|
26
27
|
|
|
27
28
|
if TYPE_CHECKING:
|
|
28
|
-
from reflexio.server.services.profile.
|
|
29
|
+
from reflexio.server.services.profile.service import (
|
|
29
30
|
ProfileGenerationServiceConfig,
|
|
30
31
|
)
|
|
31
32
|
from reflexio.server.llm.model_defaults import ModelRole, resolve_model_name
|
|
@@ -50,13 +51,26 @@ PROFILE_EXTRACTION_MAX_RETRIES = 2
|
|
|
50
51
|
MAX_EXISTING_PROFILES_FOR_CONTEXT = 5
|
|
51
52
|
|
|
52
53
|
|
|
54
|
+
def new_profile_id() -> str:
|
|
55
|
+
"""Generate a short (12-char hex) profile id.
|
|
56
|
+
|
|
57
|
+
Format chosen for LLM copy fidelity: full ``str(uuid.uuid4())`` is 36
|
|
58
|
+
characters of hex+dashes, error-prone for smaller LLMs to copy verbatim.
|
|
59
|
+
Twelve hex chars is short enough for high-fidelity copy and long enough
|
|
60
|
+
that birthday-paradox collision probability is vanishingly small at any
|
|
61
|
+
realistic per-user scale (16^12 ~= 2.8e14 unique values; PRIMARY KEY
|
|
62
|
+
constraint catches the rare collision).
|
|
63
|
+
"""
|
|
64
|
+
return uuid.uuid4().hex[:12]
|
|
65
|
+
|
|
66
|
+
|
|
53
67
|
class ProfileExtractor:
|
|
54
68
|
"""
|
|
55
69
|
Extract user profile information from interactions.
|
|
56
70
|
|
|
57
71
|
This class analyzes user interactions to extract new user profile information.
|
|
58
72
|
It focuses purely on extraction — deduplication against existing profiles
|
|
59
|
-
is handled separately by
|
|
73
|
+
is handled separately by ProfileConsolidator.
|
|
60
74
|
"""
|
|
61
75
|
|
|
62
76
|
def __init__(
|
|
@@ -83,6 +97,7 @@ class ProfileExtractor:
|
|
|
83
97
|
self.service_config: ProfileGenerationServiceConfig = service_config
|
|
84
98
|
self.agent_context = agent_context
|
|
85
99
|
self._last_resumable_run_id: str | None = None
|
|
100
|
+
self._last_resumable_token_totals: RunTokenTotals | None = None
|
|
86
101
|
|
|
87
102
|
# Get LLM config overrides from configuration
|
|
88
103
|
config = self.request_context.configurator.get_config()
|
|
@@ -230,20 +245,17 @@ class ProfileExtractor:
|
|
|
230
245
|
) from e
|
|
231
246
|
|
|
232
247
|
logger.info("Generated raw profiles: %s", raw_profiles)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
self._update_operation_state(request_interaction_data_models)
|
|
240
|
-
return ExtractionOutcome.completed(
|
|
241
|
-
user_profiles, run_id=raw_profiles.run_id
|
|
242
|
-
)
|
|
248
|
+
source_interaction_ids = [
|
|
249
|
+
interaction.interaction_id
|
|
250
|
+
for request_model in request_interaction_data_models
|
|
251
|
+
for interaction in request_model.interactions
|
|
252
|
+
if interaction.interaction_id
|
|
253
|
+
]
|
|
243
254
|
user_profiles = self._convert_raw_to_user_profiles(
|
|
244
255
|
raw_profiles=raw_profiles or [],
|
|
245
256
|
user_id=self.service_config.user_id,
|
|
246
257
|
request_id=self.service_config.request_id,
|
|
258
|
+
source_interaction_ids=source_interaction_ids,
|
|
247
259
|
)
|
|
248
260
|
if raw_profiles:
|
|
249
261
|
# Update operation state (bookmark) only when output was produced.
|
|
@@ -258,6 +270,7 @@ class ProfileExtractor:
|
|
|
258
270
|
return ExtractionOutcome.completed(
|
|
259
271
|
user_profiles,
|
|
260
272
|
run_id=self._last_resumable_run_id,
|
|
273
|
+
token_totals=self._last_resumable_token_totals,
|
|
261
274
|
)
|
|
262
275
|
return user_profiles or None
|
|
263
276
|
|
|
@@ -266,6 +279,7 @@ class ProfileExtractor:
|
|
|
266
279
|
raw_profiles: list[dict],
|
|
267
280
|
user_id: str,
|
|
268
281
|
request_id: str,
|
|
282
|
+
source_interaction_ids: list[int] | None = None,
|
|
269
283
|
) -> list[UserProfile]:
|
|
270
284
|
"""
|
|
271
285
|
Convert raw profile dicts from LLM to UserProfile objects.
|
|
@@ -274,11 +288,13 @@ class ProfileExtractor:
|
|
|
274
288
|
raw_profiles: List of profile dicts with content, time_to_live, and optional metadata
|
|
275
289
|
user_id: User ID
|
|
276
290
|
request_id: Request ID
|
|
291
|
+
source_interaction_ids: Stored interaction ids used as the extraction window
|
|
277
292
|
|
|
278
293
|
Returns:
|
|
279
294
|
List of UserProfile objects
|
|
280
295
|
"""
|
|
281
296
|
new_profiles = []
|
|
297
|
+
profile_source_interaction_ids = list(source_interaction_ids or [])
|
|
282
298
|
for profile_content in raw_profiles:
|
|
283
299
|
if (
|
|
284
300
|
not isinstance(profile_content, dict)
|
|
@@ -307,6 +323,7 @@ class ProfileExtractor:
|
|
|
307
323
|
expiration_timestamp=calculate_expiration_timestamp(now_ts, ttl),
|
|
308
324
|
custom_features=custom_features or None,
|
|
309
325
|
extractor_names=None,
|
|
326
|
+
source_interaction_ids=profile_source_interaction_ids,
|
|
310
327
|
)
|
|
311
328
|
|
|
312
329
|
new_profiles.append(added_profile)
|
|
@@ -342,11 +359,6 @@ class ProfileExtractor:
|
|
|
342
359
|
self.config.context_prompt.strip() if self.config.context_prompt else ""
|
|
343
360
|
),
|
|
344
361
|
extraction_definition_prompt=self.config.extraction_definition_prompt.strip(),
|
|
345
|
-
metadata_definition_prompt=(
|
|
346
|
-
self.config.metadata_definition_prompt.strip()
|
|
347
|
-
if self.config.metadata_definition_prompt
|
|
348
|
-
else None
|
|
349
|
-
),
|
|
350
362
|
existing_profiles=existing_profiles,
|
|
351
363
|
)
|
|
352
364
|
|
|
@@ -392,6 +404,7 @@ class ProfileExtractor:
|
|
|
392
404
|
log_label="Profile extraction",
|
|
393
405
|
)
|
|
394
406
|
self._last_resumable_run_id = result.run_id
|
|
407
|
+
self._last_resumable_token_totals = sum_trace_tokens(result.trace)
|
|
395
408
|
if not isinstance(result.output, StructuredProfilesOutput):
|
|
396
409
|
logger.warning(
|
|
397
410
|
"Profile extraction did not finish: %s", result.finished_reason
|
|
@@ -455,8 +468,4 @@ class ProfileExtractor:
|
|
|
455
468
|
"time_to_live": "one_month",
|
|
456
469
|
}
|
|
457
470
|
|
|
458
|
-
# If metadata definition exists, add mock metadata
|
|
459
|
-
if self.config.metadata_definition_prompt:
|
|
460
|
-
mock_profile["metadata"] = "mock_metadata_value"
|
|
461
|
-
|
|
462
471
|
return [mock_profile]
|
package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py
CHANGED
|
@@ -14,6 +14,7 @@ from reflexio.models.api_schema.service_schemas import (
|
|
|
14
14
|
ProfileTimeToLive,
|
|
15
15
|
UserProfile,
|
|
16
16
|
)
|
|
17
|
+
from reflexio.models.structured_output import StrictStructuredOutput
|
|
17
18
|
from reflexio.server.prompt.prompt_manager import PromptManager
|
|
18
19
|
from reflexio.server.services.service_utils import (
|
|
19
20
|
MessageConstructionConfig,
|
|
@@ -74,7 +75,6 @@ class ProfileAddItem(BaseModel):
|
|
|
74
75
|
Attributes:
|
|
75
76
|
content (str): The profile content based on content definition
|
|
76
77
|
time_to_live (str): Time to live for the profile - one of: 'one_day', 'one_week', 'one_month', 'one_quarter', 'one_year', 'infinity'
|
|
77
|
-
metadata (str, optional): Metadata extracted for the profile based on metadata definition
|
|
78
78
|
"""
|
|
79
79
|
|
|
80
80
|
content: str = Field(description="Profile content based on content definition")
|
|
@@ -83,10 +83,6 @@ class ProfileAddItem(BaseModel):
|
|
|
83
83
|
] = Field(
|
|
84
84
|
description="Time to live for the profile - determines when the profile expires"
|
|
85
85
|
)
|
|
86
|
-
metadata: str | None = Field(
|
|
87
|
-
default=None,
|
|
88
|
-
description="Metadata extracted for the profile based on metadata definition",
|
|
89
|
-
)
|
|
90
86
|
source_span: str | None = Field(
|
|
91
87
|
default=None,
|
|
92
88
|
description="Verbatim excerpt from the source that most directly supports this profile item",
|
|
@@ -107,7 +103,7 @@ class ProfileAddItem(BaseModel):
|
|
|
107
103
|
)
|
|
108
104
|
|
|
109
105
|
|
|
110
|
-
class ProfileUpdateOutput(
|
|
106
|
+
class ProfileUpdateOutput(StrictStructuredOutput):
|
|
111
107
|
"""
|
|
112
108
|
Legacy output schema for profile_update_main prompt (kept for backward compatibility).
|
|
113
109
|
Represents the complete set of profile updates including additions, deletions, and mentions.
|
|
@@ -120,7 +116,7 @@ class ProfileUpdateOutput(BaseModel):
|
|
|
120
116
|
|
|
121
117
|
add: list[ProfileAddItem] | None = Field(
|
|
122
118
|
default=None,
|
|
123
|
-
description="List of new profiles to be added with their content
|
|
119
|
+
description="List of new profiles to be added with their content and time to live",
|
|
124
120
|
)
|
|
125
121
|
delete: list[str] | None = Field(
|
|
126
122
|
default=None,
|
|
@@ -138,18 +134,18 @@ class ProfileUpdateOutput(BaseModel):
|
|
|
138
134
|
)
|
|
139
135
|
|
|
140
136
|
|
|
141
|
-
class StructuredProfilesOutput(
|
|
137
|
+
class StructuredProfilesOutput(StrictStructuredOutput):
|
|
142
138
|
"""
|
|
143
139
|
Output schema for extraction-only profile extraction.
|
|
144
140
|
Only extracts profiles — no delete/mention operations.
|
|
145
141
|
|
|
146
142
|
Attributes:
|
|
147
|
-
profiles (list[ProfileAddItem], optional): List of extracted profiles with content
|
|
143
|
+
profiles (list[ProfileAddItem], optional): List of extracted profiles with content and time_to_live
|
|
148
144
|
"""
|
|
149
145
|
|
|
150
146
|
profiles: list[ProfileAddItem] | None = Field(
|
|
151
147
|
default=None,
|
|
152
|
-
description="List of extracted profiles with content
|
|
148
|
+
description="List of extracted profiles with content and time_to_live",
|
|
153
149
|
)
|
|
154
150
|
|
|
155
151
|
model_config = ConfigDict(
|
|
@@ -225,7 +221,6 @@ def construct_profile_extraction_messages_from_sessions(
|
|
|
225
221
|
agent_context_prompt: str,
|
|
226
222
|
context_prompt: str,
|
|
227
223
|
extraction_definition_prompt: str,
|
|
228
|
-
metadata_definition_prompt: str | None = None,
|
|
229
224
|
) -> list[dict]:
|
|
230
225
|
"""
|
|
231
226
|
Construct LLM messages for profile extraction from sessions.
|
|
@@ -241,7 +236,6 @@ def construct_profile_extraction_messages_from_sessions(
|
|
|
241
236
|
agent_context_prompt: Context about the agent for system message
|
|
242
237
|
context_prompt: Additional context for system message
|
|
243
238
|
extraction_definition_prompt: Definition of what profiles should contain
|
|
244
|
-
metadata_definition_prompt: Optional definition for profile metadata
|
|
245
239
|
|
|
246
240
|
Returns:
|
|
247
241
|
list[dict]: List of messages ready for profile extraction
|
|
@@ -259,7 +253,6 @@ def construct_profile_extraction_messages_from_sessions(
|
|
|
259
253
|
"agent_context_prompt": agent_context_prompt,
|
|
260
254
|
"context_prompt": context_prompt,
|
|
261
255
|
"extraction_definition_prompt": extraction_definition_prompt,
|
|
262
|
-
"metadata_definition_prompt": metadata_definition_prompt,
|
|
263
256
|
},
|
|
264
257
|
)
|
|
265
258
|
|
|
@@ -5,7 +5,6 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
import uuid
|
|
7
7
|
from dataclasses import dataclass
|
|
8
|
-
from datetime import UTC, datetime
|
|
9
8
|
from typing import TYPE_CHECKING, Any
|
|
10
9
|
|
|
11
10
|
if TYPE_CHECKING:
|
|
@@ -14,11 +13,9 @@ if TYPE_CHECKING:
|
|
|
14
13
|
|
|
15
14
|
from reflexio.models.api_schema.internal_schema import RequestInteractionDataModel
|
|
16
15
|
from reflexio.models.api_schema.service_schemas import (
|
|
17
|
-
DeleteUserProfileRequest,
|
|
18
16
|
DowngradeProfilesResponse,
|
|
19
17
|
ManualProfileGenerationRequest,
|
|
20
18
|
ManualProfileGenerationResponse,
|
|
21
|
-
ProfileChangeLog,
|
|
22
19
|
RerunProfileGenerationRequest,
|
|
23
20
|
RerunProfileGenerationResponse,
|
|
24
21
|
Status,
|
|
@@ -30,7 +27,7 @@ from reflexio.server.services.base_generation_service import (
|
|
|
30
27
|
BaseGenerationService,
|
|
31
28
|
StatusChangeOperation,
|
|
32
29
|
)
|
|
33
|
-
from reflexio.server.services.profile.
|
|
30
|
+
from reflexio.server.services.profile.components.extractor import ProfileExtractor
|
|
34
31
|
from reflexio.server.services.profile.profile_generation_service_utils import (
|
|
35
32
|
ProfileGenerationRequest,
|
|
36
33
|
ProfileGenerationServiceConstants,
|
|
@@ -38,7 +35,7 @@ from reflexio.server.services.profile.profile_generation_service_utils import (
|
|
|
38
35
|
from reflexio.server.services.service_utils import (
|
|
39
36
|
format_sessions_to_history_string,
|
|
40
37
|
)
|
|
41
|
-
from reflexio.server.tracing import sentry_tags
|
|
38
|
+
from reflexio.server.tracing import capture_anomaly, sentry_tags
|
|
42
39
|
|
|
43
40
|
logger = logging.getLogger(__name__)
|
|
44
41
|
|
|
@@ -81,6 +78,9 @@ class ProfileGenerationService(
|
|
|
81
78
|
):
|
|
82
79
|
"""Service to generate user profiles from interactions"""
|
|
83
80
|
|
|
81
|
+
# Profile generation produces learnings — opt in to ② Learning billing.
|
|
82
|
+
EMITS_LEARNING_BILLING: bool = True
|
|
83
|
+
|
|
84
84
|
def __init__(
|
|
85
85
|
self,
|
|
86
86
|
llm_client: LiteLLMClient,
|
|
@@ -154,24 +154,23 @@ class ProfileGenerationService(
|
|
|
154
154
|
request_id = self.service_config.request_id # type: ignore[reportOptionalMemberAccess]
|
|
155
155
|
|
|
156
156
|
existing_ids_to_delete: list[str] = []
|
|
157
|
-
superseded_profiles: list[UserProfile] = []
|
|
158
157
|
|
|
159
158
|
# Always run deduplicator when enabled and there are new profiles
|
|
160
159
|
if all_new_profiles:
|
|
161
160
|
from reflexio.server.site_var.feature_flags import is_deduplicator_enabled
|
|
162
161
|
|
|
163
162
|
if is_deduplicator_enabled(self.org_id):
|
|
164
|
-
from reflexio.server.services.profile.
|
|
165
|
-
|
|
163
|
+
from reflexio.server.services.profile.components.consolidator import (
|
|
164
|
+
ProfileConsolidator,
|
|
166
165
|
)
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
consolidator = ProfileConsolidator(
|
|
169
168
|
request_context=self.request_context,
|
|
170
169
|
llm_client=self.client,
|
|
171
170
|
output_pending_status=self.output_pending_status,
|
|
172
171
|
)
|
|
173
|
-
all_new_profiles, existing_ids_to_delete,
|
|
174
|
-
|
|
172
|
+
all_new_profiles, existing_ids_to_delete, _superseded_profiles = (
|
|
173
|
+
consolidator.deduplicate(all_new_profiles, user_id, request_id)
|
|
175
174
|
)
|
|
176
175
|
logger.info(
|
|
177
176
|
"Profile updates after deduplication: %d profiles, %d existing to delete",
|
|
@@ -203,59 +202,42 @@ class ProfileGenerationService(
|
|
|
203
202
|
)
|
|
204
203
|
return
|
|
205
204
|
|
|
206
|
-
#
|
|
205
|
+
# Always soft-supersede superseded existing profiles (never hard-delete on
|
|
206
|
+
# the dedup path). This emits the lineage events that the profile change log
|
|
207
|
+
# is reconstructed from (the legacy `profile_change_logs` table is no longer
|
|
208
|
+
# written — see reconstruct_profile_change_log).
|
|
207
209
|
if existing_ids_to_delete:
|
|
208
|
-
|
|
210
|
+
if not request_id:
|
|
211
|
+
# An empty request_id makes the removal unreconstructable (the lineage
|
|
212
|
+
# events are keyed on it). Fail loud and skip removal entirely — never
|
|
213
|
+
# silently hard-delete.
|
|
214
|
+
capture_anomaly(
|
|
215
|
+
"lineage.dedup.missing_request_id",
|
|
216
|
+
level="error",
|
|
217
|
+
org_id=self.org_id,
|
|
218
|
+
user_id=user_id,
|
|
219
|
+
)
|
|
220
|
+
else:
|
|
209
221
|
try:
|
|
210
|
-
self.storage.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
)
|
|
222
|
+
self.storage.supersede_profiles_by_ids( # type: ignore[reportOptionalMemberAccess]
|
|
223
|
+
user_id=user_id,
|
|
224
|
+
profile_ids=existing_ids_to_delete,
|
|
225
|
+
request_id=request_id,
|
|
215
226
|
)
|
|
216
|
-
except Exception as e:
|
|
227
|
+
except Exception as e:
|
|
217
228
|
with sentry_tags(
|
|
218
229
|
subsystem="profile_generation",
|
|
219
|
-
op="
|
|
230
|
+
op="supersede_profiles",
|
|
220
231
|
org_id=self.org_id,
|
|
221
232
|
user_id=user_id,
|
|
222
233
|
request_id=request_id,
|
|
223
|
-
profile_id=profile_id,
|
|
224
234
|
error_type=type(e).__name__,
|
|
225
235
|
):
|
|
226
236
|
logger.exception(
|
|
227
|
-
"Failed to delete superseded
|
|
228
|
-
profile_id,
|
|
237
|
+
"Failed to soft-delete superseded profiles for user %s",
|
|
229
238
|
user_id,
|
|
230
239
|
)
|
|
231
240
|
|
|
232
|
-
# Create profile changelog post-deduplication
|
|
233
|
-
if all_new_profiles or superseded_profiles:
|
|
234
|
-
try:
|
|
235
|
-
profile_change_log = ProfileChangeLog(
|
|
236
|
-
id=0, # Auto-generated by storage
|
|
237
|
-
user_id=user_id,
|
|
238
|
-
request_id=request_id,
|
|
239
|
-
created_at=int(datetime.now(UTC).timestamp()),
|
|
240
|
-
added_profiles=all_new_profiles,
|
|
241
|
-
removed_profiles=superseded_profiles,
|
|
242
|
-
mentioned_profiles=[],
|
|
243
|
-
)
|
|
244
|
-
self.storage.add_profile_change_log(profile_change_log) # type: ignore[reportOptionalMemberAccess]
|
|
245
|
-
except Exception as e:
|
|
246
|
-
with sentry_tags(
|
|
247
|
-
subsystem="profile_generation",
|
|
248
|
-
op="add_profile_change_log",
|
|
249
|
-
org_id=self.org_id,
|
|
250
|
-
user_id=user_id,
|
|
251
|
-
request_id=request_id,
|
|
252
|
-
error_type=type(e).__name__,
|
|
253
|
-
):
|
|
254
|
-
logger.exception(
|
|
255
|
-
"Failed to add profile change log for user %s",
|
|
256
|
-
user_id,
|
|
257
|
-
)
|
|
258
|
-
|
|
259
241
|
def check_and_update_profiles(self, profiles: list[UserProfile]) -> None:
|
|
260
242
|
"""check if the profiles are expired and update them if they are"""
|
|
261
243
|
raise NotImplementedError
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
"""Reflection service
|
|
1
|
+
"""Reflection service package."""
|
|
2
2
|
|
|
3
|
-
from reflexio.server.services.reflection.reflection_service import ReflectionService
|
|
4
3
|
from reflexio.server.services.reflection.reflection_service_utils import (
|
|
5
|
-
|
|
6
|
-
ReflectionOutput,
|
|
7
|
-
ReflectionResult,
|
|
4
|
+
REFLECTION_OPERATION_NAME,
|
|
8
5
|
ReflectionServiceRequest,
|
|
9
6
|
)
|
|
7
|
+
from reflexio.server.services.reflection.service import ReflectionService
|
|
10
8
|
|
|
11
9
|
__all__ = [
|
|
10
|
+
"REFLECTION_OPERATION_NAME",
|
|
12
11
|
"ReflectionService",
|
|
13
12
|
"ReflectionServiceRequest",
|
|
14
|
-
"ReflectionDecision",
|
|
15
|
-
"ReflectionOutput",
|
|
16
|
-
"ReflectionResult",
|
|
17
13
|
]
|
package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py
CHANGED
|
@@ -11,11 +11,14 @@ in light of how they were applied across the window.
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
+
import uuid
|
|
14
15
|
from typing import Literal
|
|
15
16
|
|
|
16
17
|
from pydantic import BaseModel, Field
|
|
17
18
|
|
|
18
19
|
from reflexio.models.api_schema.domain.enums import ProfileTimeToLive
|
|
20
|
+
from reflexio.models.api_schema.validators import NonEmptyStr
|
|
21
|
+
from reflexio.models.structured_output import StrictStructuredOutput
|
|
19
22
|
|
|
20
23
|
REFLECTION_OPERATION_NAME = "reflection"
|
|
21
24
|
|
|
@@ -29,6 +32,13 @@ class ReflectionServiceRequest(BaseModel):
|
|
|
29
32
|
|
|
30
33
|
Args:
|
|
31
34
|
user_id (str): User to scope the bookmark and window to.
|
|
35
|
+
request_id (NonEmptyStr): The publish pass's own request id; used as the
|
|
36
|
+
lineage event ``request_id`` on revise events so B3
|
|
37
|
+
reconstruction can link revisions back to the triggering pass.
|
|
38
|
+
Defaults to a fresh UUID hex so two passes on the same profile
|
|
39
|
+
with no explicit request_id produce distinct lineage events.
|
|
40
|
+
Empty strings and whitespace-only values are rejected at
|
|
41
|
+
construction (``ValidationError``), before any storage write.
|
|
32
42
|
agent_version (str): Agent version of the current publish; copied
|
|
33
43
|
into replacement playbooks.
|
|
34
44
|
source (str | None): Optional source filter for the window.
|
|
@@ -37,6 +47,7 @@ class ReflectionServiceRequest(BaseModel):
|
|
|
37
47
|
"""
|
|
38
48
|
|
|
39
49
|
user_id: str
|
|
50
|
+
request_id: NonEmptyStr = Field(default_factory=lambda: uuid.uuid4().hex)
|
|
40
51
|
agent_version: str = ""
|
|
41
52
|
source: str | None = None
|
|
42
53
|
|
|
@@ -88,7 +99,7 @@ class ReflectionDecision(BaseModel):
|
|
|
88
99
|
reason: str = ""
|
|
89
100
|
|
|
90
101
|
|
|
91
|
-
class ReflectionOutput(
|
|
102
|
+
class ReflectionOutput(StrictStructuredOutput):
|
|
92
103
|
"""Structured LLM output for one reflection pass."""
|
|
93
104
|
|
|
94
105
|
decisions: list[ReflectionDecision] = Field(default_factory=list)
|
|
@@ -34,12 +34,14 @@ from typing import TYPE_CHECKING
|
|
|
34
34
|
from reflexio.models.api_schema.domain.entities import (
|
|
35
35
|
Citation,
|
|
36
36
|
Interaction,
|
|
37
|
+
LineageContext,
|
|
37
38
|
UserPlaybook,
|
|
38
39
|
UserProfile,
|
|
39
40
|
)
|
|
40
41
|
from reflexio.server.llm.litellm_client import LiteLLMClient
|
|
41
42
|
from reflexio.server.services.operation_state_utils import OperationStateManager
|
|
42
|
-
from reflexio.server.services.
|
|
43
|
+
from reflexio.server.services.playbook.playbook_edit_apply import apply_playbook_edit
|
|
44
|
+
from reflexio.server.services.reflection.components.extractor import (
|
|
43
45
|
ReflectionExtractor,
|
|
44
46
|
)
|
|
45
47
|
from reflexio.server.services.reflection.reflection_service_utils import (
|
|
@@ -446,15 +448,19 @@ class ReflectionService:
|
|
|
446
448
|
decision: ReflectionDecision,
|
|
447
449
|
cited: UserProfile,
|
|
448
450
|
) -> bool:
|
|
449
|
-
"""Insert the replacement profile, then
|
|
451
|
+
"""Insert the replacement profile, then supersede the cited row.
|
|
450
452
|
|
|
451
453
|
Insert-first ordering means that if ``add_user_profile`` raises,
|
|
452
454
|
the cited row stays current and the per-decision exception
|
|
453
455
|
handler reports ``failed_count``. Only after the new row is
|
|
454
|
-
durable do we
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
456
|
+
durable do we atomically supersede the cited row via
|
|
457
|
+
``supersede_record``, which sets ``status=SUPERSEDED`` with a
|
|
458
|
+
``superseded_by`` pointer and appends a ``revise`` lineage event.
|
|
459
|
+
If the CAS guard fails (incumbent no longer CURRENT), the
|
|
460
|
+
just-inserted successor is deleted (not audited); if that delete
|
|
461
|
+
itself raises the exception propagates to the caller. If
|
|
462
|
+
``supersede_record`` raises, log at ERROR and accept a transient
|
|
463
|
+
duplicate rather than silently dropping user data.
|
|
458
464
|
"""
|
|
459
465
|
storage = self.request_context.storage
|
|
460
466
|
if storage is None:
|
|
@@ -481,14 +487,22 @@ class ReflectionService:
|
|
|
481
487
|
new_content=new_profile.content,
|
|
482
488
|
)
|
|
483
489
|
storage.add_user_profile(cited.user_id, [new_profile])
|
|
490
|
+
ctx = LineageContext(
|
|
491
|
+
op_kind="revise",
|
|
492
|
+
actor="reflection",
|
|
493
|
+
request_id=request.request_id,
|
|
494
|
+
)
|
|
484
495
|
try:
|
|
485
|
-
|
|
486
|
-
|
|
496
|
+
superseded = storage.supersede_record(
|
|
497
|
+
entity_type="profile",
|
|
498
|
+
incumbent_id=str(cited.profile_id),
|
|
499
|
+
successor_id=str(new_profile.profile_id),
|
|
500
|
+
context=ctx,
|
|
487
501
|
)
|
|
488
502
|
except Exception as exc: # noqa: BLE001
|
|
489
503
|
with sentry_tags(
|
|
490
504
|
subsystem="reflection",
|
|
491
|
-
op="
|
|
505
|
+
op="supersede_after_insert",
|
|
492
506
|
kind="profile",
|
|
493
507
|
org_id=self.request_context.org_id,
|
|
494
508
|
user_id=cited.user_id,
|
|
@@ -503,7 +517,12 @@ class ReflectionService:
|
|
|
503
517
|
new_profile.profile_id,
|
|
504
518
|
)
|
|
505
519
|
return True
|
|
506
|
-
if not
|
|
520
|
+
if not superseded:
|
|
521
|
+
# lost the CAS race: incumbent was no longer CURRENT — drop the
|
|
522
|
+
# just-added successor (never live) without emitting an audit event.
|
|
523
|
+
storage.delete_profiles_by_ids(
|
|
524
|
+
[new_profile.profile_id], emit_hard_delete=False
|
|
525
|
+
)
|
|
507
526
|
with sentry_tags(
|
|
508
527
|
subsystem="reflection",
|
|
509
528
|
op="archive_after_insert_noop",
|
|
@@ -579,11 +598,13 @@ class ReflectionService:
|
|
|
579
598
|
(cited.content or "")[:120].replace('"', "'"),
|
|
580
599
|
(decision.new_rationale or "")[:120].replace('"', "'"),
|
|
581
600
|
)
|
|
582
|
-
storage.save_user_playbooks([new_playbook])
|
|
583
601
|
try:
|
|
584
|
-
archived =
|
|
585
|
-
|
|
586
|
-
|
|
602
|
+
archived = apply_playbook_edit(
|
|
603
|
+
storage,
|
|
604
|
+
incumbent_id=cited.user_playbook_id,
|
|
605
|
+
new_playbook=new_playbook,
|
|
606
|
+
source=new_playbook.source or "reflection",
|
|
607
|
+
request_id=request.request_id,
|
|
587
608
|
)
|
|
588
609
|
except Exception as exc: # noqa: BLE001
|
|
589
610
|
with sentry_tags(
|
|
@@ -603,7 +624,7 @@ class ReflectionService:
|
|
|
603
624
|
new_playbook.user_playbook_id,
|
|
604
625
|
)
|
|
605
626
|
return True
|
|
606
|
-
if
|
|
627
|
+
if archived < 0:
|
|
607
628
|
with sentry_tags(
|
|
608
629
|
subsystem="reflection",
|
|
609
630
|
op="archive_after_insert_noop",
|
|
@@ -799,5 +820,4 @@ def _filter_citations_by_horizon(
|
|
|
799
820
|
citation=cite, position=position, has_full_horizon=False
|
|
800
821
|
)
|
|
801
822
|
)
|
|
802
|
-
# else: deferred — not included
|
|
803
823
|
return out
|