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
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { spawn } from "node:child_process"
|
|
2
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs"
|
|
3
|
+
import { homedir } from "node:os"
|
|
4
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path"
|
|
5
|
+
import { fileURLToPath } from "node:url"
|
|
6
|
+
|
|
7
|
+
import { AssistantBuffer } from "./assistant-buffer.js"
|
|
8
|
+
import { sessionIDFrom } from "./internal.js"
|
|
9
|
+
import { chatMessagePayload, eventPayload, stopPayload, toolAfterPayload } from "./payload.js"
|
|
10
|
+
|
|
11
|
+
type HookResult = Record<string, unknown>
|
|
12
|
+
|
|
13
|
+
type PluginInput = {
|
|
14
|
+
directory: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type EventInput = {
|
|
18
|
+
event: {
|
|
19
|
+
type?: string
|
|
20
|
+
properties?: Record<string, unknown>
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const MODULE_DIR = dirname(fileURLToPath(import.meta.url))
|
|
25
|
+
|
|
26
|
+
function homeDir(): string {
|
|
27
|
+
return process.env.HOME || homedir()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function textFilePluginRoot(): string | undefined {
|
|
31
|
+
try {
|
|
32
|
+
return readFileSync(join(homeDir(), ".reflexio", "plugin-root.txt"), "utf8").trim() || undefined
|
|
33
|
+
} catch {
|
|
34
|
+
return undefined
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isPluginRoot(candidate: string | undefined): candidate is string {
|
|
39
|
+
return !!candidate
|
|
40
|
+
&& existsSync(join(candidate, "pyproject.toml"))
|
|
41
|
+
&& existsSync(join(candidate, "uv.lock"))
|
|
42
|
+
&& existsSync(join(candidate, "scripts", "hook_entry.sh"))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function canonicalPluginRoot(candidate: string | undefined): string | undefined {
|
|
46
|
+
if (!isPluginRoot(candidate)) return undefined
|
|
47
|
+
try {
|
|
48
|
+
return realpathSync(candidate)
|
|
49
|
+
} catch {
|
|
50
|
+
return undefined
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function pathParts(candidate: string): string[] {
|
|
55
|
+
return candidate.split(/[\\/]+/).filter(Boolean)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isDescendantOrSame(child: string, parent: string): boolean {
|
|
59
|
+
const path = relative(parent, child)
|
|
60
|
+
return path === "" || (!path.startsWith("..") && !isAbsolute(path))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isReflexioSessionCopy(candidate: string): boolean {
|
|
64
|
+
try {
|
|
65
|
+
const reflexioRoot = realpathSync(join(homeDir(), ".reflexio"))
|
|
66
|
+
return isDescendantOrSame(candidate, reflexioRoot)
|
|
67
|
+
} catch {
|
|
68
|
+
return false
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isTransientPackageRoot(candidate: string): boolean {
|
|
73
|
+
return pathParts(candidate).includes("_npx") || isReflexioSessionCopy(candidate)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function resolvePluginRoot(): string {
|
|
77
|
+
const current = resolve(MODULE_DIR, "../..")
|
|
78
|
+
const explicit = canonicalPluginRoot(process.env.CLAUDE_SMART_PLUGIN_ROOT)
|
|
79
|
+
if (explicit) return explicit
|
|
80
|
+
|
|
81
|
+
const currentRoot = canonicalPluginRoot(current)
|
|
82
|
+
if (currentRoot && !isTransientPackageRoot(currentRoot)) return currentRoot
|
|
83
|
+
|
|
84
|
+
const candidates = [
|
|
85
|
+
join(homeDir(), ".reflexio", "plugin-root"),
|
|
86
|
+
textFilePluginRoot(),
|
|
87
|
+
]
|
|
88
|
+
for (const candidate of candidates) {
|
|
89
|
+
const root = canonicalPluginRoot(candidate)
|
|
90
|
+
if (root) return root
|
|
91
|
+
}
|
|
92
|
+
if (currentRoot) return currentRoot
|
|
93
|
+
try {
|
|
94
|
+
return realpathSync(current)
|
|
95
|
+
} catch {
|
|
96
|
+
return current
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const PLUGIN_ROOT = resolvePluginRoot()
|
|
101
|
+
const SCRIPTS_DIR = resolve(PLUGIN_ROOT, "scripts")
|
|
102
|
+
const HOOK_ENTRY = resolve(SCRIPTS_DIR, "hook_entry.sh")
|
|
103
|
+
const BACKEND_SERVICE = resolve(SCRIPTS_DIR, "backend-service.sh")
|
|
104
|
+
const DASHBOARD_SERVICE = resolve(SCRIPTS_DIR, "dashboard-service.sh")
|
|
105
|
+
|
|
106
|
+
function contextFrom(result: HookResult): string {
|
|
107
|
+
const hookOutput = result.hookSpecificOutput
|
|
108
|
+
if (!hookOutput || typeof hookOutput !== "object") return ""
|
|
109
|
+
const additional = (hookOutput as Record<string, unknown>).additionalContext
|
|
110
|
+
return typeof additional === "string" ? additional : ""
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseFirstJsonObject(text: string): HookResult {
|
|
114
|
+
for (const line of text.split(/\r?\n/)) {
|
|
115
|
+
const trimmed = line.trim()
|
|
116
|
+
if (!trimmed.startsWith("{")) continue
|
|
117
|
+
try {
|
|
118
|
+
const parsed = JSON.parse(trimmed)
|
|
119
|
+
if (parsed && typeof parsed === "object") return parsed as HookResult
|
|
120
|
+
} catch {
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function runScript(script: string, args: string[], payload?: Record<string, unknown>): Promise<HookResult> {
|
|
128
|
+
return new Promise((resolvePromise) => {
|
|
129
|
+
const child = spawn("bash", [script, ...args], {
|
|
130
|
+
cwd: PLUGIN_ROOT,
|
|
131
|
+
env: {
|
|
132
|
+
...process.env,
|
|
133
|
+
CLAUDE_PLUGIN_ROOT: PLUGIN_ROOT,
|
|
134
|
+
CLAUDE_SMART_HOST: "opencode",
|
|
135
|
+
},
|
|
136
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
137
|
+
})
|
|
138
|
+
let stdout = ""
|
|
139
|
+
child.stdout.on("data", (chunk) => {
|
|
140
|
+
stdout += chunk.toString()
|
|
141
|
+
})
|
|
142
|
+
child.stderr.on("data", (chunk) => {
|
|
143
|
+
process.stderr.write(chunk)
|
|
144
|
+
})
|
|
145
|
+
child.stdin.on("error", () => {
|
|
146
|
+
// Hooks can exit before reading stdin on marker-gated setup failures.
|
|
147
|
+
})
|
|
148
|
+
child.on("error", () => resolvePromise({}))
|
|
149
|
+
child.on("close", () => resolvePromise(parseFirstJsonObject(stdout)))
|
|
150
|
+
try {
|
|
151
|
+
if (payload) child.stdin.write(JSON.stringify(payload))
|
|
152
|
+
child.stdin.end()
|
|
153
|
+
} catch {
|
|
154
|
+
resolvePromise({})
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function runService(script: string, subcommand: string): Promise<void> {
|
|
160
|
+
return runScript(script, [subcommand]).then(() => undefined)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function cacheContext(cache: Map<string, string[]>, sessionID: string, result: HookResult): void {
|
|
164
|
+
const context = contextFrom(result)
|
|
165
|
+
if (!sessionID || !context) return
|
|
166
|
+
const pending = cache.get(sessionID) ?? []
|
|
167
|
+
pending.push(context)
|
|
168
|
+
cache.set(sessionID, pending)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async function server(input: PluginInput) {
|
|
172
|
+
const pendingContext = new Map<string, string[]>()
|
|
173
|
+
const activeSessions = new Set<string>()
|
|
174
|
+
const completedAssistantText = new Map<string, string>()
|
|
175
|
+
const assistant = new AssistantBuffer()
|
|
176
|
+
const cwd = input.directory
|
|
177
|
+
|
|
178
|
+
async function flushStop(sessionID: string): Promise<void> {
|
|
179
|
+
if (!sessionID || !activeSessions.has(sessionID)) return
|
|
180
|
+
activeSessions.delete(sessionID)
|
|
181
|
+
const text = assistant.text(sessionID) || completedAssistantText.get(sessionID) || ""
|
|
182
|
+
completedAssistantText.delete(sessionID)
|
|
183
|
+
await runScript(
|
|
184
|
+
HOOK_ENTRY,
|
|
185
|
+
["opencode", "stop"],
|
|
186
|
+
stopPayload({ properties: { sessionID, info: { directory: cwd } } }, cwd, text),
|
|
187
|
+
)
|
|
188
|
+
assistant.clear(sessionID)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
event: async ({ event }: EventInput) => {
|
|
193
|
+
const type = event.type
|
|
194
|
+
assistant.update(event)
|
|
195
|
+
if (type === "session.created") {
|
|
196
|
+
const payload = eventPayload(event, cwd)
|
|
197
|
+
const sessionID = String(payload.session_id || "")
|
|
198
|
+
if (!sessionID) return
|
|
199
|
+
activeSessions.add(sessionID)
|
|
200
|
+
await runService(BACKEND_SERVICE, "start")
|
|
201
|
+
await runService(DASHBOARD_SERVICE, "start")
|
|
202
|
+
const result = await runScript(HOOK_ENTRY, ["opencode", "session-start"], payload)
|
|
203
|
+
cacheContext(pendingContext, sessionID, result)
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
if (type === "session.idle") {
|
|
207
|
+
const payload = eventPayload(event, cwd)
|
|
208
|
+
const sessionID = String(payload.session_id || "")
|
|
209
|
+
if (!sessionID) return
|
|
210
|
+
await flushStop(sessionID)
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"chat.message": async (hookInput: Record<string, unknown>, output: Record<string, unknown>) => {
|
|
214
|
+
const payload = chatMessagePayload(hookInput, output, cwd)
|
|
215
|
+
if (!payload.session_id || !payload.prompt) return
|
|
216
|
+
activeSessions.add(String(payload.session_id || ""))
|
|
217
|
+
const result = await runScript(HOOK_ENTRY, ["opencode", "user-prompt"], payload)
|
|
218
|
+
cacheContext(pendingContext, String(payload.session_id || ""), result)
|
|
219
|
+
},
|
|
220
|
+
"experimental.chat.system.transform": async (hookInput: Record<string, unknown>, output: { system: string[] }) => {
|
|
221
|
+
const sessionID = sessionIDFrom(hookInput)
|
|
222
|
+
const pending = pendingContext.get(sessionID)
|
|
223
|
+
if (!pending?.length) return
|
|
224
|
+
output.system.push(...pending)
|
|
225
|
+
pendingContext.delete(sessionID)
|
|
226
|
+
},
|
|
227
|
+
"tool.execute.after": async (hookInput: Record<string, unknown>, output: Record<string, unknown>) => {
|
|
228
|
+
const payload = toolAfterPayload(hookInput, output, cwd)
|
|
229
|
+
if (!payload.session_id || !payload.tool_name) return
|
|
230
|
+
await runScript(HOOK_ENTRY, ["opencode", "post-tool"], payload)
|
|
231
|
+
},
|
|
232
|
+
"experimental.text.complete": async (
|
|
233
|
+
hookInput: { sessionID?: string },
|
|
234
|
+
output: { text?: string },
|
|
235
|
+
) => {
|
|
236
|
+
const sessionID = typeof hookInput.sessionID === "string" ? hookInput.sessionID : ""
|
|
237
|
+
if (!sessionID) return
|
|
238
|
+
if (typeof output.text === "string") completedAssistantText.set(sessionID, output.text)
|
|
239
|
+
},
|
|
240
|
+
dispose: async () => {
|
|
241
|
+
await Promise.all([...activeSessions].map((sessionID) => flushStop(sessionID)))
|
|
242
|
+
await runService(DASHBOARD_SERVICE, "session-end")
|
|
243
|
+
await runService(BACKEND_SERVICE, "session-end")
|
|
244
|
+
},
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export default {
|
|
249
|
+
id: "claude-smart",
|
|
250
|
+
server,
|
|
251
|
+
}
|
package/plugin/pyproject.toml
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "claude-smart"
|
|
3
|
-
version = "0.2.
|
|
4
|
-
description = "Self-improving Claude Code and
|
|
3
|
+
version = "0.2.47"
|
|
4
|
+
description = "Self-improving Claude Code, Codex, and OpenCode plugin that turns corrections into Preferences, Project-specific skills, and Shared skills"
|
|
5
|
+
keywords = [
|
|
6
|
+
"claude",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"claude-code-plugin",
|
|
9
|
+
"codex",
|
|
10
|
+
"codex-plugin",
|
|
11
|
+
"opencode",
|
|
12
|
+
"opencode-plugin",
|
|
13
|
+
"memory",
|
|
14
|
+
"agent-memory",
|
|
15
|
+
"plugin",
|
|
16
|
+
"reflexio",
|
|
17
|
+
"self-improvement",
|
|
18
|
+
"self-improving-agents",
|
|
19
|
+
"skills",
|
|
20
|
+
"learning",
|
|
21
|
+
]
|
|
5
22
|
readme = "README.md"
|
|
6
23
|
requires-python = ">=3.12"
|
|
7
24
|
dependencies = [
|
|
@@ -9,7 +26,7 @@ dependencies = [
|
|
|
9
26
|
# normal installs; vendor releases may override it after uv sync by
|
|
10
27
|
# installing plugin/vendor/reflexio. Keep in sync via
|
|
11
28
|
# scripts/sync-reflexio-dep.py.
|
|
12
|
-
"reflexio-ai>=0.2.
|
|
29
|
+
"reflexio-ai>=0.2.27",
|
|
13
30
|
# Needed when Reflexio runs the local embedding provider (ONNXMiniLM_L6_V2).
|
|
14
31
|
# Pulls in onnxruntime + tokenizers; the ~80 MB ONNX model itself is
|
|
15
32
|
# downloaded on first use, not at install time.
|
|
@@ -21,9 +38,13 @@ dependencies = [
|
|
|
21
38
|
"sqlite-vec>=0.1.6",
|
|
22
39
|
]
|
|
23
40
|
|
|
41
|
+
# claude-smart is distributed via npm only (see bin/claude-smart.js); it is not
|
|
42
|
+
# published to PyPI, so there is no `claude-smart` console script / uvx entry
|
|
43
|
+
# point. These two scripts are resolved by the runtime from the plugin venv
|
|
44
|
+
# (session_start.py locates claude-smart-optimizer-assistant; the hook is invoked
|
|
45
|
+
# via `python -m claude_smart.hook`), so they stay.
|
|
24
46
|
[project.scripts]
|
|
25
47
|
claude-smart-hook = "claude_smart.hook:main"
|
|
26
|
-
claude-smart = "claude_smart.cli:main"
|
|
27
48
|
claude-smart-optimizer-assistant = "claude_smart.optimizer_assistant:main"
|
|
28
49
|
|
|
29
50
|
[build-system]
|
package/plugin/scripts/_lib.sh
CHANGED
|
@@ -87,8 +87,12 @@ claude_smart_env_unquote() {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
claude_smart_source_reflexio_env() {
|
|
90
|
+
# claude-smart's env lives at ~/.claude-smart/.env (kept separate from the OSS
|
|
91
|
+
# reflexio default ~/.reflexio/.env). Stays in sync with
|
|
92
|
+
# env_config.REFLEXIO_ENV_PATH and the REFLEXIO_ENV_FILE export in
|
|
93
|
+
# backend-service.sh.
|
|
90
94
|
local env_file line key value
|
|
91
|
-
env_file="$HOME/.
|
|
95
|
+
env_file="$HOME/.claude-smart/.env"
|
|
92
96
|
[ -f "$env_file" ] || return 0
|
|
93
97
|
while IFS= read -r line || [ -n "$line" ]; do
|
|
94
98
|
line="${line#"${line%%[![:space:]]*}"}"
|
|
@@ -34,6 +34,21 @@ EMBEDDING_PORT="${EMBEDDING_PORT:-8072}"
|
|
|
34
34
|
export BACKEND_PORT="$PORT"
|
|
35
35
|
export EMBEDDING_PORT
|
|
36
36
|
|
|
37
|
+
# Run claude-smart's backend under its own org id. The reflexio no-auth resolver
|
|
38
|
+
# reads REFLEXIO_DEFAULT_ORG_ID, which scopes the request org -> config file
|
|
39
|
+
# name (config_<org>.json) and SQLite data. Hard-set (not :-defaulted) so a
|
|
40
|
+
# value in the shared ~/.reflexio/.env can't drag claude-smart back onto
|
|
41
|
+
# "self-host-org" and collide with the enterprise self-host backend over
|
|
42
|
+
# config_self-host-org.json. Must stay in sync with cli.py's config path.
|
|
43
|
+
export REFLEXIO_DEFAULT_ORG_ID="claude-smart"
|
|
44
|
+
|
|
45
|
+
# Load claude-smart's env from ~/.claude-smart/.env instead of the reflexio
|
|
46
|
+
# default ~/.reflexio/.env, so an OSS reflexio backend's .env on this machine
|
|
47
|
+
# can't leak in. The data dir is independent (LOCAL_STORAGE_PATH), so both still
|
|
48
|
+
# share ~/.reflexio/data. Must stay in sync with env_config.REFLEXIO_ENV_PATH and
|
|
49
|
+
# the source path in _lib.sh (claude_smart_source_reflexio_env).
|
|
50
|
+
export REFLEXIO_ENV_FILE="$HOME/.claude-smart/.env"
|
|
51
|
+
|
|
37
52
|
# Default: route extraction through the active host CLI + ONNX embedder
|
|
38
53
|
# so claude-smart works without any LLM API key. Users can opt out by
|
|
39
54
|
# pre-exporting these to 0.
|
|
@@ -50,7 +65,12 @@ PLUGIN_ROOT="$(cd "$HERE/.." && pwd)"
|
|
|
50
65
|
claude_smart_reexec_stable_plugin_root_if_needed "$PLUGIN_ROOT" "backend-service.sh" "$@"
|
|
51
66
|
|
|
52
67
|
if [ -z "${CLAUDE_SMART_CLI_PATH:-}" ]; then
|
|
53
|
-
if [ "${CLAUDE_SMART_HOST:-claude-code}" = "
|
|
68
|
+
if [ "${CLAUDE_SMART_HOST:-claude-code}" = "opencode" ] && command -v opencode >/dev/null 2>&1; then
|
|
69
|
+
# Preserve Reflexio's Claude CLI provider contract while routing
|
|
70
|
+
# generation through the user's authenticated OpenCode setup.
|
|
71
|
+
claude_smart_prepend_node_bins
|
|
72
|
+
export CLAUDE_SMART_CLI_PATH="$PLUGIN_ROOT/scripts/opencode-claude-compat"
|
|
73
|
+
elif [ "${CLAUDE_SMART_HOST:-claude-code}" = "codex" ]; then
|
|
54
74
|
# Reflexio's provider still calls CLAUDE_SMART_CLI_PATH with Claude CLI
|
|
55
75
|
# flags. Use a small compatibility executable that translates that narrow
|
|
56
76
|
# contract to `codex exec`.
|
|
@@ -286,7 +306,7 @@ case "$CMD" in
|
|
|
286
306
|
# Keep plugin runtime data in ~/.reflexio even when the backend imports
|
|
287
307
|
# Reflexio from an editable checkout inside a larger repo with its own
|
|
288
308
|
# .env. python-dotenv respects pre-existing env vars, so this prevents a
|
|
289
|
-
# parent REFLEXIO_LOG_DIR from sending claude-smart to
|
|
309
|
+
# parent REFLEXIO_LOG_DIR from sending claude-smart to unrelated configs.
|
|
290
310
|
export REFLEXIO_LOG_DIR="${REFLEXIO_LOG_DIR:-$HOME}"
|
|
291
311
|
|
|
292
312
|
# Force sqlite: the plugin venv ships only the open-source reflexio
|
|
@@ -32,12 +32,12 @@ if [ "$FORCE" = "--force" ]; then
|
|
|
32
32
|
fi
|
|
33
33
|
|
|
34
34
|
# Opt-in: when CLAUDE_SMART_PLUGIN_ROOT_FOLLOW_SESSION=1 (set in the
|
|
35
|
-
# environment or in ~/.
|
|
35
|
+
# environment or in ~/.claude-smart/.env), always relink to $TARGET so the
|
|
36
36
|
# symlink tracks the currently loaded plugin.
|
|
37
37
|
FOLLOW="${CLAUDE_SMART_PLUGIN_ROOT_FOLLOW_SESSION:-}"
|
|
38
|
-
if [ -z "$FOLLOW" ] && [ -f "$HOME/.
|
|
39
|
-
FOLLOW="$(grep -E '^CLAUDE_SMART_PLUGIN_ROOT_FOLLOW_SESSION=' "$HOME/.
|
|
40
|
-
| tail -n1 |
|
|
38
|
+
if [ -z "$FOLLOW" ] && [ -f "$HOME/.claude-smart/.env" ]; then
|
|
39
|
+
FOLLOW="$(grep -E '^(export[[:space:]]+)?CLAUDE_SMART_PLUGIN_ROOT_FOLLOW_SESSION=' "$HOME/.claude-smart/.env" \
|
|
40
|
+
| tail -n1 | sed -E 's/^(export[[:space:]]+)?CLAUDE_SMART_PLUGIN_ROOT_FOLLOW_SESSION=//')"
|
|
41
41
|
# Strip a single pair of surrounding double or single quotes, if present.
|
|
42
42
|
FOLLOW="${FOLLOW#\"}"; FOLLOW="${FOLLOW%\"}"
|
|
43
43
|
FOLLOW="${FOLLOW#\'}"; FOLLOW="${FOLLOW%\'}"
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* Translate Reflexio's Claude CLI provider contract to `opencode run`.
|
|
6
|
+
*
|
|
7
|
+
* Reflexio shells out to CLAUDE_SMART_CLI_PATH as if it were Claude Code:
|
|
8
|
+
*
|
|
9
|
+
* <path> -p --output-format stream-json --model <model> ...
|
|
10
|
+
*
|
|
11
|
+
* Under OpenCode, this bridge preserves that executable contract while routing
|
|
12
|
+
* generation through the user's authenticated OpenCode CLI/provider setup.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { spawnSync } = require("node:child_process");
|
|
16
|
+
const fs = require("node:fs");
|
|
17
|
+
const os = require("node:os");
|
|
18
|
+
const path = require("node:path");
|
|
19
|
+
|
|
20
|
+
const DEFAULT_TIMEOUT_MS = 120_000;
|
|
21
|
+
const AGENT_NAME = "claude-smart-extractor";
|
|
22
|
+
|
|
23
|
+
function main(argv) {
|
|
24
|
+
let workDir = null;
|
|
25
|
+
try {
|
|
26
|
+
const { outputFormat, systemPrompt, model } = parseSupportedArgs(argv);
|
|
27
|
+
const prompt = fs.readFileSync(0, "utf8");
|
|
28
|
+
workDir = prepareWorkDir();
|
|
29
|
+
const content = runOpenCode({
|
|
30
|
+
prompt: combinedPrompt({ prompt, systemPrompt }),
|
|
31
|
+
model,
|
|
32
|
+
workDir,
|
|
33
|
+
});
|
|
34
|
+
const payload =
|
|
35
|
+
outputFormat === "stream-json"
|
|
36
|
+
? { type: "result", subtype: "success", result: content }
|
|
37
|
+
: { result: content };
|
|
38
|
+
process.stdout.write(`${JSON.stringify(payload)}\n`);
|
|
39
|
+
return 0;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
process.stderr.write(`opencode-claude-compat: ${message}\n`);
|
|
43
|
+
return 1;
|
|
44
|
+
} finally {
|
|
45
|
+
if (workDir) {
|
|
46
|
+
try {
|
|
47
|
+
fs.rmSync(workDir, { recursive: true, force: true });
|
|
48
|
+
} catch {
|
|
49
|
+
// Best effort cleanup only.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function parseSupportedArgs(argv) {
|
|
56
|
+
let outputFormat = "json";
|
|
57
|
+
let systemPrompt = "";
|
|
58
|
+
let model = "";
|
|
59
|
+
let idx = 0;
|
|
60
|
+
while (idx < argv.length) {
|
|
61
|
+
const arg = argv[idx];
|
|
62
|
+
if (arg === "-p") {
|
|
63
|
+
idx += 1;
|
|
64
|
+
} else if (arg === "--output-format") {
|
|
65
|
+
outputFormat = requireValue(argv, idx, arg);
|
|
66
|
+
idx += 2;
|
|
67
|
+
} else if (arg === "--model") {
|
|
68
|
+
model = requireValue(argv, idx, arg);
|
|
69
|
+
idx += 2;
|
|
70
|
+
} else if (arg === "--verbose" || arg === "--include-partial-messages") {
|
|
71
|
+
idx += 1;
|
|
72
|
+
} else if (arg === "--append-system-prompt") {
|
|
73
|
+
systemPrompt = requireValue(argv, idx, arg);
|
|
74
|
+
idx += 2;
|
|
75
|
+
} else {
|
|
76
|
+
throw new Error(`unsupported Claude CLI argument: ${arg}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (outputFormat !== "json" && outputFormat !== "stream-json") {
|
|
80
|
+
throw new Error(`unsupported --output-format: ${outputFormat}`);
|
|
81
|
+
}
|
|
82
|
+
return { outputFormat, systemPrompt, model };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function requireValue(argv, idx, name) {
|
|
86
|
+
if (idx + 1 >= argv.length) {
|
|
87
|
+
throw new Error(`${name} requires a value`);
|
|
88
|
+
}
|
|
89
|
+
return argv[idx + 1];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function prepareWorkDir() {
|
|
93
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "claude-smart-opencode-"));
|
|
94
|
+
const config = {
|
|
95
|
+
agent: {
|
|
96
|
+
[AGENT_NAME]: {
|
|
97
|
+
description: "Internal claude-smart learning extraction",
|
|
98
|
+
prompt:
|
|
99
|
+
"You are running as an internal claude-smart extraction subprocess. " +
|
|
100
|
+
"Return only the requested text or JSON. Do not use tools, edit files, " +
|
|
101
|
+
"search the workspace, or ask follow-up questions.",
|
|
102
|
+
steps: 2,
|
|
103
|
+
permission: "deny",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
const opencodeDir = path.join(dir, ".opencode");
|
|
108
|
+
fs.mkdirSync(opencodeDir, { recursive: true });
|
|
109
|
+
fs.writeFileSync(path.join(opencodeDir, "opencode.json"), `${JSON.stringify(config, null, 2)}\n`);
|
|
110
|
+
return dir;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function runOpenCode({ prompt, model, workDir }) {
|
|
114
|
+
const opencodePath = process.env.CLAUDE_SMART_OPENCODE_PATH || commandPath(opencodeNames());
|
|
115
|
+
if (!opencodePath) {
|
|
116
|
+
throw new Error("opencode CLI not found on PATH");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const args = [
|
|
120
|
+
"run",
|
|
121
|
+
"--pure",
|
|
122
|
+
"--format",
|
|
123
|
+
"json",
|
|
124
|
+
"--agent",
|
|
125
|
+
AGENT_NAME,
|
|
126
|
+
"--dir",
|
|
127
|
+
workDir,
|
|
128
|
+
];
|
|
129
|
+
const selectedModel = opencodeModel(model);
|
|
130
|
+
if (selectedModel) {
|
|
131
|
+
args.push("--model", selectedModel);
|
|
132
|
+
}
|
|
133
|
+
const variant = (process.env.CLAUDE_SMART_OPENCODE_VARIANT || "").trim();
|
|
134
|
+
if (variant) {
|
|
135
|
+
args.push("--variant", variant);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const proc = spawnSync(opencodePath, args, {
|
|
139
|
+
input: prompt,
|
|
140
|
+
cwd: workDir,
|
|
141
|
+
encoding: "utf8",
|
|
142
|
+
env: {
|
|
143
|
+
...process.env,
|
|
144
|
+
CLAUDE_SMART_HOST: "opencode",
|
|
145
|
+
CLAUDE_SMART_INTERNAL: "1",
|
|
146
|
+
CLAUDE_CODE_ENTRYPOINT: "optimizer",
|
|
147
|
+
},
|
|
148
|
+
timeout: timeoutMs(),
|
|
149
|
+
windowsHide: true,
|
|
150
|
+
shell: process.platform === "win32" && /\.(?:cmd|bat)$/i.test(opencodePath),
|
|
151
|
+
});
|
|
152
|
+
if (proc.error) {
|
|
153
|
+
if (proc.error.code === "ETIMEDOUT") {
|
|
154
|
+
throw new Error(`opencode CLI timed out after ${timeoutMs() / 1000}s`);
|
|
155
|
+
}
|
|
156
|
+
throw proc.error;
|
|
157
|
+
}
|
|
158
|
+
if (proc.status !== 0) {
|
|
159
|
+
const stderr = String(proc.stderr || "").trim().slice(0, 500);
|
|
160
|
+
throw new Error(`opencode CLI exited ${proc.status}: ${stderr}`);
|
|
161
|
+
}
|
|
162
|
+
const content = parseOpenCodeJson(proc.stdout);
|
|
163
|
+
if (!content) {
|
|
164
|
+
throw new Error("opencode CLI returned empty output");
|
|
165
|
+
}
|
|
166
|
+
return content;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function opencodeModel(modelFromArgs) {
|
|
170
|
+
const explicit = (process.env.CLAUDE_SMART_OPENCODE_MODEL || "").trim();
|
|
171
|
+
if (explicit) return explicit;
|
|
172
|
+
const candidate = (modelFromArgs || "").trim();
|
|
173
|
+
return candidate.includes("/") ? candidate : "";
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function parseOpenCodeJson(stdout) {
|
|
177
|
+
const chunks = [];
|
|
178
|
+
for (const line of String(stdout || "").split(/\r?\n/)) {
|
|
179
|
+
const trimmed = line.trim();
|
|
180
|
+
if (!trimmed) continue;
|
|
181
|
+
let event;
|
|
182
|
+
try {
|
|
183
|
+
event = JSON.parse(trimmed);
|
|
184
|
+
} catch {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const part = event && typeof event === "object" ? event.part : null;
|
|
188
|
+
if (part && part.type === "text" && typeof part.text === "string") {
|
|
189
|
+
chunks.push(part.text);
|
|
190
|
+
} else if (event.type === "text" && typeof event.text === "string") {
|
|
191
|
+
chunks.push(event.text);
|
|
192
|
+
} else if (event.type === "result" && typeof event.result === "string") {
|
|
193
|
+
chunks.push(event.result);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return chunks.join("").trim();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function timeoutMs() {
|
|
200
|
+
const raw = Number(process.env.CLAUDE_SMART_CLI_TIMEOUT || "");
|
|
201
|
+
if (Number.isFinite(raw) && raw > 0) return raw * 1000;
|
|
202
|
+
return DEFAULT_TIMEOUT_MS;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function opencodeNames() {
|
|
206
|
+
return process.platform === "win32" ? ["opencode.cmd", "opencode.exe", "opencode"] : ["opencode"];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function commandPath(names) {
|
|
210
|
+
const pathParts = (process.env.PATH || "").split(path.delimiter).filter(Boolean);
|
|
211
|
+
for (const dir of pathParts) {
|
|
212
|
+
for (const name of names) {
|
|
213
|
+
const candidate = path.join(dir, name);
|
|
214
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function combinedPrompt({ prompt, systemPrompt }) {
|
|
221
|
+
if (!systemPrompt) return prompt;
|
|
222
|
+
return `${systemPrompt}\n\n## Task\n${prompt}`;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
process.exitCode = main(process.argv.slice(2));
|