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
package/plugin/commands/show.md
CHANGED
|
@@ -6,10 +6,21 @@ import { PageHeader } from "@/components/common/page-header";
|
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
|
+
import {
|
|
10
|
+
Select,
|
|
11
|
+
SelectContent,
|
|
12
|
+
SelectItem,
|
|
13
|
+
SelectTrigger,
|
|
14
|
+
SelectValue,
|
|
15
|
+
} from "@/components/ui/select";
|
|
9
16
|
import { Switch } from "@/components/ui/switch";
|
|
10
17
|
import { Separator } from "@/components/ui/separator";
|
|
11
18
|
import { SETTINGS_CHANGED_EVENT } from "@/hooks/use-settings";
|
|
12
|
-
import type {
|
|
19
|
+
import type {
|
|
20
|
+
ClaudeCodeHookConfig,
|
|
21
|
+
ClaudeSmartConfig,
|
|
22
|
+
OptimizerMode,
|
|
23
|
+
} from "@/lib/types";
|
|
13
24
|
|
|
14
25
|
export default function ConfigureEnvPage() {
|
|
15
26
|
const [config, setConfig] = useState<ClaudeSmartConfig | null>(null);
|
|
@@ -44,14 +55,14 @@ export default function ConfigureEnvPage() {
|
|
|
44
55
|
setSaved(false);
|
|
45
56
|
};
|
|
46
57
|
|
|
47
|
-
const updateOptimizer = (
|
|
58
|
+
const updateOptimizer = (mode: OptimizerMode) => {
|
|
48
59
|
setHookConfig((prev) =>
|
|
49
60
|
prev
|
|
50
61
|
? {
|
|
51
62
|
...prev,
|
|
52
|
-
CLAUDE_SMART_ENABLE_OPTIMIZER:
|
|
53
|
-
effectiveValue:
|
|
54
|
-
localValue:
|
|
63
|
+
CLAUDE_SMART_ENABLE_OPTIMIZER: mode,
|
|
64
|
+
effectiveValue: mode,
|
|
65
|
+
localValue: mode === "auto" ? null : mode,
|
|
55
66
|
}
|
|
56
67
|
: prev,
|
|
57
68
|
);
|
|
@@ -280,15 +291,29 @@ export default function ConfigureEnvPage() {
|
|
|
280
291
|
CLAUDE_SMART_ENABLE_OPTIMIZER
|
|
281
292
|
</Label>
|
|
282
293
|
<p className="text-xs text-muted-foreground mt-0.5">
|
|
283
|
-
|
|
284
|
-
SessionStart.
|
|
294
|
+
Control shared skill optimization and rollups during
|
|
295
|
+
SessionStart. Auto applies only to local Reflexio.
|
|
285
296
|
</p>
|
|
286
297
|
</div>
|
|
287
|
-
<
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
298
|
+
<Select
|
|
299
|
+
value={hookConfig.CLAUDE_SMART_ENABLE_OPTIMIZER}
|
|
300
|
+
onValueChange={(value) =>
|
|
301
|
+
updateOptimizer((value as OptimizerMode) ?? "auto")
|
|
302
|
+
}
|
|
303
|
+
>
|
|
304
|
+
<SelectTrigger
|
|
305
|
+
id="enable-optimizer"
|
|
306
|
+
size="sm"
|
|
307
|
+
className="w-40 text-xs bg-background/80"
|
|
308
|
+
>
|
|
309
|
+
<SelectValue placeholder="Mode" />
|
|
310
|
+
</SelectTrigger>
|
|
311
|
+
<SelectContent align="end">
|
|
312
|
+
<SelectItem value="auto">Auto</SelectItem>
|
|
313
|
+
<SelectItem value="enabled">Enabled</SelectItem>
|
|
314
|
+
<SelectItem value="disabled">Disabled</SelectItem>
|
|
315
|
+
</SelectContent>
|
|
316
|
+
</Select>
|
|
292
317
|
</div>
|
|
293
318
|
<div className="rounded-md border border-border bg-background/60 p-3 text-xs text-muted-foreground space-y-2">
|
|
294
319
|
<div className="flex items-center justify-between gap-4">
|
|
@@ -332,7 +357,8 @@ export default function ConfigureEnvPage() {
|
|
|
332
357
|
);
|
|
333
358
|
}
|
|
334
359
|
|
|
335
|
-
function formatSettingValue(value:
|
|
360
|
+
function formatSettingValue(value: OptimizerMode | null): string {
|
|
336
361
|
if (value === null) return "Not set";
|
|
337
|
-
|
|
362
|
+
if (value === "auto") return "Auto (local only)";
|
|
363
|
+
return value === "enabled" ? "Enabled" : "Disabled";
|
|
338
364
|
}
|
|
@@ -6,12 +6,30 @@ import { PageHeader } from "@/components/common/page-header";
|
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
7
|
import { Input } from "@/components/ui/input";
|
|
8
8
|
import { Label } from "@/components/ui/label";
|
|
9
|
-
import
|
|
9
|
+
import { Switch } from "@/components/ui/switch";
|
|
10
|
+
import type { ReflexioConfig, ReflexioRetrievalFloorConfig } from "@/lib/types";
|
|
10
11
|
|
|
11
12
|
type ExtractorField =
|
|
12
13
|
| "profile_extractor_configs"
|
|
13
14
|
| "user_playbook_extractor_configs";
|
|
14
15
|
|
|
16
|
+
const DEFAULT_RETRIEVAL_FLOOR: Required<
|
|
17
|
+
Pick<
|
|
18
|
+
ReflexioRetrievalFloorConfig,
|
|
19
|
+
| "enabled"
|
|
20
|
+
| "pool_size"
|
|
21
|
+
| "profile_floor"
|
|
22
|
+
| "user_playbook_floor"
|
|
23
|
+
| "agent_playbook_floor"
|
|
24
|
+
>
|
|
25
|
+
> = {
|
|
26
|
+
enabled: false,
|
|
27
|
+
pool_size: 30,
|
|
28
|
+
profile_floor: -3,
|
|
29
|
+
user_playbook_floor: -3,
|
|
30
|
+
agent_playbook_floor: -3,
|
|
31
|
+
};
|
|
32
|
+
|
|
15
33
|
export default function ConfigureServerPage() {
|
|
16
34
|
const [srvConfig, setSrvConfig] = useState<ReflexioConfig | null>(null);
|
|
17
35
|
const [srvError, setSrvError] = useState<string | null>(null);
|
|
@@ -73,6 +91,22 @@ export default function ConfigureServerPage() {
|
|
|
73
91
|
setSrvSaved(false);
|
|
74
92
|
};
|
|
75
93
|
|
|
94
|
+
const updateReranker = (enabled: boolean) => {
|
|
95
|
+
setSrvConfig((prev) =>
|
|
96
|
+
prev
|
|
97
|
+
? {
|
|
98
|
+
...prev,
|
|
99
|
+
retrieval_floor: {
|
|
100
|
+
...DEFAULT_RETRIEVAL_FLOOR,
|
|
101
|
+
...(prev.retrieval_floor ?? {}),
|
|
102
|
+
enabled,
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
: prev,
|
|
106
|
+
);
|
|
107
|
+
setSrvSaved(false);
|
|
108
|
+
};
|
|
109
|
+
|
|
76
110
|
const saveSrv = async () => {
|
|
77
111
|
if (!srvConfig) return;
|
|
78
112
|
setSrvSaving(true);
|
|
@@ -191,6 +225,22 @@ export default function ConfigureServerPage() {
|
|
|
191
225
|
/>
|
|
192
226
|
</div>
|
|
193
227
|
|
|
228
|
+
<div className="flex items-start justify-between gap-4 rounded-md border border-border bg-background/60 p-3">
|
|
229
|
+
<div className="min-w-0">
|
|
230
|
+
<Label htmlFor="search-reranker">Search reranker</Label>
|
|
231
|
+
<p className="text-xs text-muted-foreground mt-0.5">
|
|
232
|
+
Use the local cross-encoder relevance floor for injected
|
|
233
|
+
memory search. The first enabled search loads the model into
|
|
234
|
+
the backend process.
|
|
235
|
+
</p>
|
|
236
|
+
</div>
|
|
237
|
+
<Switch
|
|
238
|
+
id="search-reranker"
|
|
239
|
+
checked={!!srvConfig.retrieval_floor?.enabled}
|
|
240
|
+
onCheckedChange={updateReranker}
|
|
241
|
+
/>
|
|
242
|
+
</div>
|
|
243
|
+
|
|
194
244
|
<div className="space-y-2">
|
|
195
245
|
<Label>Preference focus area</Label>
|
|
196
246
|
<p className="text-xs text-muted-foreground">
|
|
@@ -53,12 +53,9 @@ export default function PreferenceDetailPage({
|
|
|
53
53
|
useEffect(() => {
|
|
54
54
|
let cancelled = false;
|
|
55
55
|
reflexio
|
|
56
|
-
.
|
|
57
|
-
.then((
|
|
56
|
+
.getProfileById(id, { includeTombstones: true })
|
|
57
|
+
.then((found) => {
|
|
58
58
|
if (cancelled) return;
|
|
59
|
-
const found = (res.user_profiles ?? []).find(
|
|
60
|
-
(p) => p.profile_id === id,
|
|
61
|
-
);
|
|
62
59
|
if (!found) {
|
|
63
60
|
setNotFound(true);
|
|
64
61
|
return;
|
|
@@ -397,12 +394,12 @@ function Prose({ text }: { text: string }) {
|
|
|
397
394
|
function StatusBadge({
|
|
398
395
|
status,
|
|
399
396
|
}: {
|
|
400
|
-
status: "CURRENT" | "ARCHIVED" | "PENDING";
|
|
397
|
+
status: "CURRENT" | "ARCHIVED" | "PENDING" | "MERGED" | "SUPERSEDED";
|
|
401
398
|
}) {
|
|
402
399
|
const variant =
|
|
403
400
|
status === "CURRENT"
|
|
404
401
|
? "secondary"
|
|
405
|
-
: status === "ARCHIVED"
|
|
402
|
+
: status === "ARCHIVED" || status === "MERGED" || status === "SUPERSEDED"
|
|
406
403
|
? "outline"
|
|
407
404
|
: "default";
|
|
408
405
|
return (
|
|
@@ -412,7 +409,10 @@ function StatusBadge({
|
|
|
412
409
|
"h-1.5 w-1.5 rounded-full",
|
|
413
410
|
status === "CURRENT" && "bg-emerald-500",
|
|
414
411
|
status === "PENDING" && "bg-amber-500",
|
|
415
|
-
status === "ARCHIVED"
|
|
412
|
+
(status === "ARCHIVED" ||
|
|
413
|
+
status === "MERGED" ||
|
|
414
|
+
status === "SUPERSEDED") &&
|
|
415
|
+
"bg-muted-foreground",
|
|
416
416
|
)}
|
|
417
417
|
/>
|
|
418
418
|
{status}
|
|
@@ -28,6 +28,7 @@ import { reflexio } from "@/lib/reflexio-client";
|
|
|
28
28
|
import { formatTimestamp, truncateId } from "@/lib/format";
|
|
29
29
|
import { cn } from "@/lib/utils";
|
|
30
30
|
import { statusLabel } from "@/lib/status";
|
|
31
|
+
import type { StatusLabel } from "@/lib/status";
|
|
31
32
|
import type { UserPlaybook } from "@/lib/types";
|
|
32
33
|
|
|
33
34
|
type FormState = { content: string; trigger: string; rationale: string };
|
|
@@ -464,12 +465,12 @@ function AutoTextarea({
|
|
|
464
465
|
function StatusBadge({
|
|
465
466
|
status,
|
|
466
467
|
}: {
|
|
467
|
-
status:
|
|
468
|
+
status: StatusLabel;
|
|
468
469
|
}) {
|
|
469
470
|
const variant =
|
|
470
471
|
status === "CURRENT"
|
|
471
472
|
? "secondary"
|
|
472
|
-
: status === "ARCHIVED"
|
|
473
|
+
: status === "ARCHIVED" || status === "MERGED" || status === "SUPERSEDED"
|
|
473
474
|
? "outline"
|
|
474
475
|
: "default";
|
|
475
476
|
return (
|
|
@@ -479,7 +480,10 @@ function StatusBadge({
|
|
|
479
480
|
"h-1.5 w-1.5 rounded-full",
|
|
480
481
|
status === "CURRENT" && "bg-emerald-500",
|
|
481
482
|
status === "PENDING" && "bg-amber-500",
|
|
482
|
-
status === "ARCHIVED"
|
|
483
|
+
(status === "ARCHIVED" ||
|
|
484
|
+
status === "MERGED" ||
|
|
485
|
+
status === "SUPERSEDED") &&
|
|
486
|
+
"bg-muted-foreground",
|
|
483
487
|
)}
|
|
484
488
|
/>
|
|
485
489
|
{status}
|
|
@@ -35,6 +35,7 @@ import { reflexio } from "@/lib/reflexio-client";
|
|
|
35
35
|
import { formatTimestamp, truncateId } from "@/lib/format";
|
|
36
36
|
import { cn } from "@/lib/utils";
|
|
37
37
|
import { agentPlaybookStatusLabel, statusLabel } from "@/lib/status";
|
|
38
|
+
import type { StatusLabel } from "@/lib/status";
|
|
38
39
|
import type { AgentPlaybook, AgentPlaybookStatus } from "@/lib/types";
|
|
39
40
|
|
|
40
41
|
type FormState = {
|
|
@@ -571,12 +572,15 @@ function AutoTextarea({
|
|
|
571
572
|
function StatusBadge({
|
|
572
573
|
status,
|
|
573
574
|
}: {
|
|
574
|
-
status:
|
|
575
|
+
status: StatusLabel | "APPROVED" | "REJECTED";
|
|
575
576
|
}) {
|
|
576
577
|
const variant =
|
|
577
578
|
status === "CURRENT" || status === "APPROVED"
|
|
578
579
|
? "secondary"
|
|
579
|
-
: status === "ARCHIVED" ||
|
|
580
|
+
: status === "ARCHIVED" ||
|
|
581
|
+
status === "MERGED" ||
|
|
582
|
+
status === "SUPERSEDED" ||
|
|
583
|
+
status === "REJECTED"
|
|
580
584
|
? "outline"
|
|
581
585
|
: "default";
|
|
582
586
|
return (
|
|
@@ -588,7 +592,10 @@ function StatusBadge({
|
|
|
588
592
|
status === "APPROVED" && "bg-emerald-500",
|
|
589
593
|
status === "PENDING" && "bg-amber-500",
|
|
590
594
|
status === "REJECTED" && "bg-destructive",
|
|
591
|
-
status === "ARCHIVED"
|
|
595
|
+
(status === "ARCHIVED" ||
|
|
596
|
+
status === "MERGED" ||
|
|
597
|
+
status === "SUPERSEDED") &&
|
|
598
|
+
"bg-muted-foreground",
|
|
592
599
|
)}
|
|
593
600
|
/>
|
|
594
601
|
{status}
|
|
@@ -10,7 +10,7 @@ import fs from "node:fs/promises";
|
|
|
10
10
|
import { existsSync } from "node:fs";
|
|
11
11
|
import os from "node:os";
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import type { ClaudeCodeHookConfig } from "./types";
|
|
13
|
+
import type { ClaudeCodeHookConfig, OptimizerMode } from "./types";
|
|
14
14
|
|
|
15
15
|
const ENV_KEY = "CLAUDE_SMART_ENABLE_OPTIMIZER";
|
|
16
16
|
|
|
@@ -52,17 +52,22 @@ function asRecord(value: unknown): Record<string, unknown> {
|
|
|
52
52
|
return value as Record<string, unknown>;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
function
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
function parseOptimizerMode(value: unknown): OptimizerMode {
|
|
56
|
+
if (
|
|
57
|
+
value === false ||
|
|
58
|
+
value === 0 ||
|
|
59
|
+
(typeof value === "string" &&
|
|
60
|
+
["0", "false", "no", "off"].includes(value.trim().toLowerCase()))
|
|
61
|
+
) {
|
|
62
|
+
return "disabled";
|
|
63
|
+
}
|
|
64
|
+
return "enabled";
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
function optimizerValue(settings: Record<string, unknown>):
|
|
67
|
+
function optimizerValue(settings: Record<string, unknown>): OptimizerMode | null {
|
|
63
68
|
const env = asRecord(settings.env);
|
|
64
69
|
if (!(ENV_KEY in env)) return null;
|
|
65
|
-
return
|
|
70
|
+
return parseOptimizerMode(env[ENV_KEY]);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
async function readSettingsFile(file: string): Promise<Record<string, unknown>> {
|
|
@@ -84,7 +89,7 @@ export async function readClaudeCodeHookConfig(): Promise<ClaudeCodeHookConfig>
|
|
|
84
89
|
]);
|
|
85
90
|
const localValue = optimizerValue(localSettings);
|
|
86
91
|
const userValue = optimizerValue(userSettings);
|
|
87
|
-
const effectiveValue = localValue ?? userValue ??
|
|
92
|
+
const effectiveValue = localValue ?? userValue ?? "auto";
|
|
88
93
|
return {
|
|
89
94
|
CLAUDE_SMART_ENABLE_OPTIMIZER: effectiveValue,
|
|
90
95
|
effectiveValue,
|
|
@@ -103,7 +108,12 @@ export async function writeClaudeCodeHookConfig(
|
|
|
103
108
|
const env = asRecord(settings.env);
|
|
104
109
|
|
|
105
110
|
if (!("CLAUDE_SMART_ENABLE_OPTIMIZER" in update)) return;
|
|
106
|
-
|
|
111
|
+
if (update.CLAUDE_SMART_ENABLE_OPTIMIZER === "auto") {
|
|
112
|
+
delete env[ENV_KEY];
|
|
113
|
+
} else {
|
|
114
|
+
env[ENV_KEY] =
|
|
115
|
+
update.CLAUDE_SMART_ENABLE_OPTIMIZER === "enabled" ? "1" : "0";
|
|
116
|
+
}
|
|
107
117
|
|
|
108
118
|
settings.env = env;
|
|
109
119
|
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
@@ -93,6 +93,22 @@ export const reflexio = {
|
|
|
93
93
|
return get(`get_all_profiles?${qs.toString()}`);
|
|
94
94
|
},
|
|
95
95
|
|
|
96
|
+
async getProfileById(
|
|
97
|
+
profileId: string,
|
|
98
|
+
opts: { includeTombstones?: boolean } = {},
|
|
99
|
+
): Promise<UserProfile | null> {
|
|
100
|
+
const qs = new URLSearchParams();
|
|
101
|
+
qs.set("profile_id", profileId);
|
|
102
|
+
if (opts.includeTombstones) qs.set("include_tombstones", "true");
|
|
103
|
+
const res = await get<{ user_profiles: UserProfile[] }>(
|
|
104
|
+
`get_all_profiles?${qs.toString()}`,
|
|
105
|
+
);
|
|
106
|
+
return (
|
|
107
|
+
res.user_profiles?.find((profile) => profile.profile_id === profileId) ??
|
|
108
|
+
null
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
|
|
96
112
|
/** GET /api/get_all_interactions — global, unfiltered. */
|
|
97
113
|
async getAllInteractions(
|
|
98
114
|
opts: { limit?: number } = {},
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
// Wire status comes from Python's Status
|
|
2
|
-
// ("archived", "pending"). CURRENT rows are omitted from JSON entirely
|
|
1
|
+
// Wire status comes from Python's Status enum: lowercase strings
|
|
2
|
+
// ("archived", "pending", "merged", "superseded"). CURRENT rows are omitted from JSON entirely
|
|
3
3
|
// (response_model_exclude_none) and arrive as `null`/undefined.
|
|
4
4
|
// Normalize to the uppercase label the dashboard renders.
|
|
5
5
|
|
|
6
|
-
export type StatusLabel =
|
|
6
|
+
export type StatusLabel =
|
|
7
|
+
| "CURRENT"
|
|
8
|
+
| "ARCHIVED"
|
|
9
|
+
| "PENDING"
|
|
10
|
+
| "MERGED"
|
|
11
|
+
| "SUPERSEDED";
|
|
7
12
|
export type AgentPlaybookStatusLabel = "PENDING" | "APPROVED" | "REJECTED";
|
|
8
13
|
|
|
9
14
|
export function statusLabel(p: { status?: string | null }): StatusLabel {
|
|
@@ -11,6 +16,8 @@ export function statusLabel(p: { status?: string | null }): StatusLabel {
|
|
|
11
16
|
const s = String(p.status).toLowerCase();
|
|
12
17
|
if (s === "archived") return "ARCHIVED";
|
|
13
18
|
if (s === "pending") return "PENDING";
|
|
19
|
+
if (s === "merged") return "MERGED";
|
|
20
|
+
if (s === "superseded") return "SUPERSEDED";
|
|
14
21
|
return "CURRENT";
|
|
15
22
|
}
|
|
16
23
|
|
|
@@ -9,11 +9,11 @@ export type UserActionType =
|
|
|
9
9
|
// (response_model_exclude_none strips it from the JSON entirely), so the type
|
|
10
10
|
// only enumerates the non-null values. The values are lowercase because they
|
|
11
11
|
// come from Python's Status StrEnum.
|
|
12
|
-
export type LifecycleStatus = "pending" | "archived";
|
|
12
|
+
export type LifecycleStatus = "pending" | "archived" | "merged" | "superseded";
|
|
13
13
|
|
|
14
14
|
export type AgentPlaybookStatus = "pending" | "approved" | "rejected";
|
|
15
15
|
|
|
16
|
-
export type ProfileStatus = "pending" | "archived";
|
|
16
|
+
export type ProfileStatus = "pending" | "archived" | "merged" | "superseded";
|
|
17
17
|
|
|
18
18
|
export interface ToolUsed {
|
|
19
19
|
tool_name: string;
|
|
@@ -124,11 +124,13 @@ export interface ClaudeSmartConfig {
|
|
|
124
124
|
[extra: string]: string | boolean | undefined;
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
export type OptimizerMode = "auto" | "enabled" | "disabled";
|
|
128
|
+
|
|
127
129
|
export interface ClaudeCodeHookConfig {
|
|
128
|
-
CLAUDE_SMART_ENABLE_OPTIMIZER:
|
|
129
|
-
effectiveValue:
|
|
130
|
-
localValue:
|
|
131
|
-
userValue:
|
|
130
|
+
CLAUDE_SMART_ENABLE_OPTIMIZER: OptimizerMode;
|
|
131
|
+
effectiveValue: OptimizerMode;
|
|
132
|
+
localValue: OptimizerMode | null;
|
|
133
|
+
userValue: OptimizerMode | null;
|
|
132
134
|
settingsPath: string;
|
|
133
135
|
userSettingsPath: string;
|
|
134
136
|
}
|
|
@@ -138,10 +140,20 @@ export interface ReflexioExtractorConfig {
|
|
|
138
140
|
[k: string]: unknown;
|
|
139
141
|
}
|
|
140
142
|
|
|
143
|
+
export interface ReflexioRetrievalFloorConfig {
|
|
144
|
+
enabled?: boolean;
|
|
145
|
+
pool_size?: number;
|
|
146
|
+
profile_floor?: number;
|
|
147
|
+
user_playbook_floor?: number;
|
|
148
|
+
agent_playbook_floor?: number;
|
|
149
|
+
[k: string]: unknown;
|
|
150
|
+
}
|
|
151
|
+
|
|
141
152
|
export interface ReflexioConfig {
|
|
142
153
|
agent_context_prompt?: string | null;
|
|
143
154
|
window_size?: number;
|
|
144
155
|
stride_size?: number;
|
|
156
|
+
retrieval_floor?: ReflexioRetrievalFloorConfig | null;
|
|
145
157
|
profile_extractor_configs?: ReflexioExtractorConfig[] | null;
|
|
146
158
|
user_playbook_extractor_configs?: ReflexioExtractorConfig[] | null;
|
|
147
159
|
[k: string]: unknown;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { eventProperties, type EventLike, sessionIDFrom } from "./internal.js"
|
|
2
|
+
|
|
3
|
+
type PartLike = {
|
|
4
|
+
id?: string
|
|
5
|
+
type?: string
|
|
6
|
+
text?: string
|
|
7
|
+
messageID?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type SessionText = {
|
|
11
|
+
messageID?: string
|
|
12
|
+
parts: Map<string, string>
|
|
13
|
+
textPartIDs: Set<string>
|
|
14
|
+
ignoredPartIDs: Set<string>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function textFromPart(part: unknown): { id: string; text: string; messageID?: string } | undefined {
|
|
18
|
+
if (!part || typeof part !== "object") return undefined
|
|
19
|
+
const item = part as PartLike
|
|
20
|
+
if (item.type !== "text") return undefined
|
|
21
|
+
if (typeof item.text !== "string") return undefined
|
|
22
|
+
return {
|
|
23
|
+
id: item.id || `${item.messageID || "message"}:${item.type}`,
|
|
24
|
+
text: item.text,
|
|
25
|
+
messageID: item.messageID,
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function partIDFrom(part: unknown): string | undefined {
|
|
30
|
+
if (!part || typeof part !== "object") return undefined
|
|
31
|
+
const item = part as PartLike
|
|
32
|
+
return item.id || (item.messageID && item.type ? `${item.messageID}:${item.type}` : undefined)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function emptySession(messageID?: string): SessionText {
|
|
36
|
+
return { messageID, parts: new Map(), textPartIDs: new Set(), ignoredPartIDs: new Set() }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class AssistantBuffer {
|
|
40
|
+
private readonly sessions = new Map<string, SessionText>()
|
|
41
|
+
|
|
42
|
+
update(event: EventLike): void {
|
|
43
|
+
const type = event.type
|
|
44
|
+
const properties = eventProperties(event)
|
|
45
|
+
const sessionID = sessionIDFrom(properties)
|
|
46
|
+
if (!sessionID || !type) return
|
|
47
|
+
|
|
48
|
+
if (type === "message.updated") {
|
|
49
|
+
const info = properties.info
|
|
50
|
+
if (!info || typeof info !== "object") return
|
|
51
|
+
const message = info as { id?: string; role?: string }
|
|
52
|
+
if (message.role !== "assistant") return
|
|
53
|
+
const current = this.sessions.get(sessionID)
|
|
54
|
+
if (!current || current.messageID !== message.id) {
|
|
55
|
+
this.sessions.set(sessionID, emptySession(message.id))
|
|
56
|
+
}
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (type === "message.part.updated") {
|
|
61
|
+
const hit = textFromPart(properties.part)
|
|
62
|
+
if (!hit) {
|
|
63
|
+
const ignoredID = partIDFrom(properties.part)
|
|
64
|
+
if (!ignoredID) return
|
|
65
|
+
const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
|
|
66
|
+
current.ignoredPartIDs.add(ignoredID)
|
|
67
|
+
current.textPartIDs.delete(ignoredID)
|
|
68
|
+
current.parts.delete(ignoredID)
|
|
69
|
+
this.sessions.set(sessionID, current)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
|
|
73
|
+
if (hit.messageID && current.messageID && hit.messageID !== current.messageID) {
|
|
74
|
+
current.messageID = hit.messageID
|
|
75
|
+
current.parts.clear()
|
|
76
|
+
current.textPartIDs.clear()
|
|
77
|
+
current.ignoredPartIDs.clear()
|
|
78
|
+
} else if (hit.messageID) {
|
|
79
|
+
current.messageID = hit.messageID
|
|
80
|
+
}
|
|
81
|
+
current.ignoredPartIDs.delete(hit.id)
|
|
82
|
+
current.textPartIDs.add(hit.id)
|
|
83
|
+
current.parts.set(hit.id, hit.text)
|
|
84
|
+
this.sessions.set(sessionID, current)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (type === "message.part.delta") {
|
|
89
|
+
const partID = typeof properties.partID === "string" ? properties.partID : undefined
|
|
90
|
+
const delta = typeof properties.delta === "string" ? properties.delta : undefined
|
|
91
|
+
if (!partID || !delta) return
|
|
92
|
+
const current: SessionText = this.sessions.get(sessionID) ?? emptySession()
|
|
93
|
+
if (current.ignoredPartIDs.has(partID) || !current.textPartIDs.has(partID)) return
|
|
94
|
+
current.parts.set(partID, `${current.parts.get(partID) || ""}${delta}`)
|
|
95
|
+
this.sessions.set(sessionID, current)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
text(sessionID: string): string {
|
|
100
|
+
const current = this.sessions.get(sessionID)
|
|
101
|
+
if (!current) return ""
|
|
102
|
+
return Array.from(current.parts.values()).filter(Boolean).join("\n\n")
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
clear(sessionID: string): void {
|
|
106
|
+
this.sessions.delete(sessionID)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { eventProperties, sessionIDFrom } from "./internal.js";
|
|
2
|
+
function textFromPart(part) {
|
|
3
|
+
if (!part || typeof part !== "object")
|
|
4
|
+
return undefined;
|
|
5
|
+
const item = part;
|
|
6
|
+
if (item.type !== "text")
|
|
7
|
+
return undefined;
|
|
8
|
+
if (typeof item.text !== "string")
|
|
9
|
+
return undefined;
|
|
10
|
+
return {
|
|
11
|
+
id: item.id || `${item.messageID || "message"}:${item.type}`,
|
|
12
|
+
text: item.text,
|
|
13
|
+
messageID: item.messageID,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function partIDFrom(part) {
|
|
17
|
+
if (!part || typeof part !== "object")
|
|
18
|
+
return undefined;
|
|
19
|
+
const item = part;
|
|
20
|
+
return item.id || (item.messageID && item.type ? `${item.messageID}:${item.type}` : undefined);
|
|
21
|
+
}
|
|
22
|
+
function emptySession(messageID) {
|
|
23
|
+
return { messageID, parts: new Map(), textPartIDs: new Set(), ignoredPartIDs: new Set() };
|
|
24
|
+
}
|
|
25
|
+
export class AssistantBuffer {
|
|
26
|
+
sessions = new Map();
|
|
27
|
+
update(event) {
|
|
28
|
+
const type = event.type;
|
|
29
|
+
const properties = eventProperties(event);
|
|
30
|
+
const sessionID = sessionIDFrom(properties);
|
|
31
|
+
if (!sessionID || !type)
|
|
32
|
+
return;
|
|
33
|
+
if (type === "message.updated") {
|
|
34
|
+
const info = properties.info;
|
|
35
|
+
if (!info || typeof info !== "object")
|
|
36
|
+
return;
|
|
37
|
+
const message = info;
|
|
38
|
+
if (message.role !== "assistant")
|
|
39
|
+
return;
|
|
40
|
+
const current = this.sessions.get(sessionID);
|
|
41
|
+
if (!current || current.messageID !== message.id) {
|
|
42
|
+
this.sessions.set(sessionID, emptySession(message.id));
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (type === "message.part.updated") {
|
|
47
|
+
const hit = textFromPart(properties.part);
|
|
48
|
+
if (!hit) {
|
|
49
|
+
const ignoredID = partIDFrom(properties.part);
|
|
50
|
+
if (!ignoredID)
|
|
51
|
+
return;
|
|
52
|
+
const current = this.sessions.get(sessionID) ?? emptySession();
|
|
53
|
+
current.ignoredPartIDs.add(ignoredID);
|
|
54
|
+
current.textPartIDs.delete(ignoredID);
|
|
55
|
+
current.parts.delete(ignoredID);
|
|
56
|
+
this.sessions.set(sessionID, current);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const current = this.sessions.get(sessionID) ?? emptySession();
|
|
60
|
+
if (hit.messageID && current.messageID && hit.messageID !== current.messageID) {
|
|
61
|
+
current.messageID = hit.messageID;
|
|
62
|
+
current.parts.clear();
|
|
63
|
+
current.textPartIDs.clear();
|
|
64
|
+
current.ignoredPartIDs.clear();
|
|
65
|
+
}
|
|
66
|
+
else if (hit.messageID) {
|
|
67
|
+
current.messageID = hit.messageID;
|
|
68
|
+
}
|
|
69
|
+
current.ignoredPartIDs.delete(hit.id);
|
|
70
|
+
current.textPartIDs.add(hit.id);
|
|
71
|
+
current.parts.set(hit.id, hit.text);
|
|
72
|
+
this.sessions.set(sessionID, current);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (type === "message.part.delta") {
|
|
76
|
+
const partID = typeof properties.partID === "string" ? properties.partID : undefined;
|
|
77
|
+
const delta = typeof properties.delta === "string" ? properties.delta : undefined;
|
|
78
|
+
if (!partID || !delta)
|
|
79
|
+
return;
|
|
80
|
+
const current = this.sessions.get(sessionID) ?? emptySession();
|
|
81
|
+
if (current.ignoredPartIDs.has(partID) || !current.textPartIDs.has(partID))
|
|
82
|
+
return;
|
|
83
|
+
current.parts.set(partID, `${current.parts.get(partID) || ""}${delta}`);
|
|
84
|
+
this.sessions.set(sessionID, current);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
text(sessionID) {
|
|
88
|
+
const current = this.sessions.get(sessionID);
|
|
89
|
+
if (!current)
|
|
90
|
+
return "";
|
|
91
|
+
return Array.from(current.parts.values()).filter(Boolean).join("\n\n");
|
|
92
|
+
}
|
|
93
|
+
clear(sessionID) {
|
|
94
|
+
this.sessions.delete(sessionID);
|
|
95
|
+
}
|
|
96
|
+
}
|