claude-smart 0.2.45 → 0.2.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/README.md +34 -5
- package/bin/claude-smart.js +295 -5
- package/package.json +22 -3
- package/plugin/.claude-plugin/plugin.json +4 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +22 -2
- package/plugin/commands/clear-all.md +1 -0
- package/plugin/commands/dashboard.md +1 -0
- package/plugin/commands/learn.md +1 -0
- package/plugin/commands/restart.md +1 -0
- package/plugin/commands/show.md +1 -0
- package/plugin/dashboard/app/configure/env/page.tsx +40 -14
- package/plugin/dashboard/app/configure/server/page.tsx +51 -1
- package/plugin/dashboard/app/preferences/[id]/page.tsx +8 -8
- package/plugin/dashboard/app/skills/project/[id]/page.tsx +7 -3
- package/plugin/dashboard/app/skills/shared/[id]/page.tsx +10 -3
- package/plugin/dashboard/lib/claude-settings-file.ts +20 -10
- package/plugin/dashboard/lib/reflexio-client.ts +16 -0
- package/plugin/dashboard/lib/status.ts +10 -3
- package/plugin/dashboard/lib/types.ts +18 -6
- package/plugin/hooks/codex-hooks.json +0 -1
- package/plugin/opencode/assistant-buffer.ts +108 -0
- package/plugin/opencode/dist/assistant-buffer.js +96 -0
- package/plugin/opencode/dist/internal.js +12 -0
- package/plugin/opencode/dist/payload.js +85 -0
- package/plugin/opencode/dist/server.mjs +158 -0
- package/plugin/opencode/internal.ts +18 -0
- package/plugin/opencode/package.json +3 -0
- package/plugin/opencode/payload.ts +90 -0
- package/plugin/opencode/server.mts +174 -0
- package/plugin/opencode/tsconfig.json +13 -0
- package/plugin/pyproject.toml +20 -3
- package/plugin/scripts/_lib.sh +5 -1
- package/plugin/scripts/backend-service.sh +22 -2
- package/plugin/scripts/ensure-plugin-root.sh +4 -4
- package/plugin/scripts/hook_entry.sh +1 -1
- package/plugin/scripts/opencode-claude-compat +4 -0
- package/plugin/scripts/opencode-claude-compat.cmd +3 -0
- package/plugin/scripts/opencode-claude-compat.js +225 -0
- package/plugin/scripts/smart-install.sh +10 -8
- package/plugin/src/README.md +1 -1
- package/plugin/src/claude_smart/cli.py +304 -6
- package/plugin/src/claude_smart/env_config.py +12 -4
- package/plugin/src/claude_smart/events/session_start.py +26 -7
- package/plugin/src/claude_smart/events/stop.py +1 -1
- package/plugin/src/claude_smart/ids.py +1 -1
- package/plugin/src/claude_smart/reflexio_adapter.py +5 -5
- package/plugin/src/claude_smart/runtime.py +7 -1
- package/plugin/uv.lock +1 -1
- package/plugin/vendor/reflexio/.env.example +54 -30
- package/plugin/vendor/reflexio/README.md +14 -8
- package/plugin/vendor/reflexio/pyproject.toml +13 -1
- package/plugin/vendor/reflexio/reflexio/README.md +1 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +9 -7
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +10 -1
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +22 -5
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +34 -4
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +12 -7
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +13 -6
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +210 -50
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +15 -2
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +292 -22
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +29 -4
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +17 -8
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +13 -10
- package/plugin/vendor/reflexio/reflexio/client/client.py +57 -13
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +135 -257
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/bin/openclaw-smart.js +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/npm/openclaw-smart/package.json +15 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/README.md +38 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +151 -110
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +20 -10
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +28 -6
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/pyproject.toml +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/_lib.sh +371 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh +271 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/cli.sh +68 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/dashboard-open.sh +15 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/ensure-plugin-root.sh +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/hook_entry.sh +106 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/npm-cli.js +219 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/smart-install.sh +269 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/clear-all/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/dashboard/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/learn/SKILL.md +10 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +15 -44
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/restart/SKILL.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/show/SKILL.md +8 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/cli.py +634 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_format.py +224 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/context_inject.py +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/after_tool_call.py +160 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/agent_end.py +187 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_prompt_build.py +69 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/before_tool_call.py +30 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_end.py +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/events/session_start.py +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/hook.py +131 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/ids.py +94 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/internal_call.py +75 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/oc_cite.py +196 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/optimizer_assistant.py +272 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/publish.py +96 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/query_compose.py +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/reflexio_adapter.py +336 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/runtime.py +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/stall_banner.py +61 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/src/openclaw_smart/state.py +323 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_e2e_session_loop.py +190 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_publish_to_local_reflexio_integration.py +112 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_recursion_guard_integration.py +86 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/integration/test_search_inject_integration.py +144 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_cli.py +184 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_after_tool_call.py +142 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_agent_end.py +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_prompt_build.py +116 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_before_tool_call.py +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_end.py +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_events_session_start.py +109 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_hook_dispatch.py +117 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_ids.py +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_internal_call.py +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_oc_cite.py +88 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_publish.py +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_query_compose.py +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_reflexio_adapter.py +188 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_runtime.py +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests/test_state.py +235 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/__mocks__/plugin-entry-stub.ts +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_npm_cli.test.ts +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tests-ts/test_shim_dispatch.test.ts +171 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/tsconfig.build.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{tsconfig.json → plugin/tsconfig.json} +2 -2
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/uv.lock +3835 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/vitest.config.ts +18 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +238 -10
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +11 -4
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +16 -5
- package/plugin/vendor/reflexio/reflexio/lib/_lineage_parity_readers.py +187 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +198 -6
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +1 -1
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +29 -20
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +2 -1
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +127 -38
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +4 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +64 -41
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +19 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +12 -5
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +52 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +5 -1
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +5 -1
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +88 -7
- package/plugin/vendor/reflexio/reflexio/models/structured_output.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +3 -3
- package/plugin/vendor/reflexio/reflexio/server/README.md +45 -32
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +29 -5
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +2 -2
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +65 -2
- package/plugin/vendor/reflexio/reflexio/server/api.py +734 -85
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +3 -1
- package/plugin/vendor/reflexio/reflexio/server/billing_meter.py +173 -0
- package/plugin/vendor/reflexio/reflexio/server/billing_signals.py +64 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +46 -16
- package/plugin/vendor/reflexio/reflexio/server/env_utils.py +65 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +19 -4
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +264 -77
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +69 -7
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +75 -16
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/openclaw_provider.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/token_accounting.py +48 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +107 -17
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +360 -4
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.7.0.prompt.md +85 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.3.0.prompt.md +253 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.3.prompt.md +74 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.3.0.prompt.md +266 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.4.0.prompt.md +266 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.4.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +1 -1
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.3.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +5 -12
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +5 -12
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.2.0.prompt.md +155 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/tagging/v1.0.0.prompt.md +23 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +89 -32
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +26 -11
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/README.md +22 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +4 -2
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/components/__init__.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluator.py → components/evaluator.py} +3 -16
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +28 -72
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{group_evaluation_runner.py → runner.py} +12 -10
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{delayed_group_evaluator.py → scheduler.py} +10 -2
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/{agent_success_evaluation_service.py → service.py} +36 -1
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +160 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +1 -1
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/README.md +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/components/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{rule_attribution.py → components/rule_attribution.py} +10 -9
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +15 -24
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +238 -164
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/README.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +13 -3
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +3 -2
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +32 -118
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +39 -16
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +105 -23
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/gc_scheduler.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/lineage/resolve.py +98 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +11 -12
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/components/__init__.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_aggregator.py → components/aggregator.py} +316 -178
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_consolidator.py → components/consolidator.py} +168 -62
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_extractor.py → components/extractor.py} +5 -1
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_edit_apply.py +74 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +33 -3
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/{playbook_generation_service.py → service.py} +121 -19
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/user_detail_stripping.py +84 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/README.md +10 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +2 -1
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +178 -30
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/README.md +9 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/components/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_deduplicator.py → components/consolidator.py} +7 -6
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_extractor.py → components/extractor.py} +30 -22
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +6 -13
- package/plugin/vendor/reflexio/reflexio/server/services/profile/{profile_generation_service.py → service.py} +32 -50
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +4 -8
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/components/__init__.py +7 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +12 -1
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_service.py → service.py} +36 -16
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +83 -6
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +36 -1
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/README.md +8 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +1 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +27 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +9 -9
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +4 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +642 -197
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +61 -104
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_lineage.py +628 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +38 -6
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +978 -184
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +519 -128
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +77 -3
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +23 -9
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +5 -2
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +131 -20
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +2 -8
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +5 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +36 -53
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_lineage.py +215 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +20 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +243 -7
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +121 -1
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_retrieval_log.py +51 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/README.md +8 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/service.py +200 -0
- package/plugin/vendor/reflexio/reflexio/server/services/tagging/tagging_scheduler.py +149 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +229 -32
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +2 -1
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +120 -1
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +4 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/search_settings.json +5 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +18 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +61 -26
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +41 -4
- package/scripts/setup-claude-smart.sh +8 -3
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +0 -517
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +0 -473
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +0 -2156
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +0 -18
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +0 -241
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +0 -140
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +0 -113
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +0 -52
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +0 -103
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +0 -156
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +0 -134
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +0 -24
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +0 -278
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +0 -164
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +0 -36
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +0 -35
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +0 -27
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +0 -31
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +0 -42
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +0 -49
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +0 -91
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +0 -50
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +0 -13
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +0 -192
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +0 -303
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +0 -138
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +0 -1125
- /package/plugin/vendor/reflexio/reflexio/integrations/{__init__.py → openclaw/plugin/src/openclaw_smart/__init__.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/integrations/openclaw/{types → plugin/types}/openclaw.d.ts +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{distribution.py → components/distribution.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{hero_state.py → components/hero_state.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/{shadow_aggregation.py → components/shadow_aggregation.py} +0 -0
- /package/plugin/vendor/reflexio/reflexio/server/services/reflection/{reflection_extractor.py → components/extractor.py} +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Exposes the following subcommands:
|
|
4
4
|
|
|
5
5
|
- ``install``: register the GitHub marketplace and install the plugin into
|
|
6
|
-
Claude Code, then seed ``~/.
|
|
6
|
+
Claude Code, then seed ``~/.claude-smart/.env`` with the local-provider flags.
|
|
7
7
|
- ``update``: update the plugin to the latest version via the native Claude
|
|
8
8
|
Code plugin CLI.
|
|
9
9
|
- ``uninstall``: remove the plugin from Claude Code via the native plugin
|
|
@@ -56,6 +56,8 @@ _CODEX_PLUGIN_CACHE_DIR = (
|
|
|
56
56
|
/ "claude-smart"
|
|
57
57
|
)
|
|
58
58
|
_CODEX_CLI_TIMEOUT_SECONDS = 30
|
|
59
|
+
_OPENCODE_PLUGIN_SPEC = "claude-smart"
|
|
60
|
+
_OPENCODE_CONFIG_NAMES = ("opencode.json", "opencode.jsonc")
|
|
59
61
|
_REFLEXIO_UNREACHABLE_MSG = (
|
|
60
62
|
"Failed to reach reflexio. Check ~/.claude-smart/backend.log "
|
|
61
63
|
"or restart Claude Code.\n"
|
|
@@ -83,7 +85,12 @@ _LOCAL_DATA_NOTICE = (
|
|
|
83
85
|
_INSTALL_FAILURE_MARKER = _STATE_DIR / "install-failed"
|
|
84
86
|
_SERVICE_STATUS_PROBE_FAILED = "probe_failed"
|
|
85
87
|
_DEFAULT_STORAGE_ROOT = _REFLEXIO_DIR / "data"
|
|
86
|
-
|
|
88
|
+
# Org id claude-smart's backend runs under (set via REFLEXIO_DEFAULT_ORG_ID in
|
|
89
|
+
# backend-service.sh). reflexio names the config file config_<org>.json, so this
|
|
90
|
+
# must stay in sync with that export; using our own org keeps us off the
|
|
91
|
+
# enterprise self-host backend's config_self-host-org.json.
|
|
92
|
+
_REFLEXIO_ORG_ID = "claude-smart"
|
|
93
|
+
_REFLEXIO_CONFIG_PATH = _REFLEXIO_DIR / "configs" / f"config_{_REFLEXIO_ORG_ID}.json"
|
|
87
94
|
_LOCAL_STORAGE_ENV = "LOCAL_STORAGE_PATH"
|
|
88
95
|
_CODEX_REQUIRED_FILES = (
|
|
89
96
|
Path(".agents/plugins/marketplace.json"),
|
|
@@ -92,6 +99,9 @@ _CODEX_REQUIRED_FILES = (
|
|
|
92
99
|
Path("plugin/scripts/codex-claude-compat"),
|
|
93
100
|
Path("plugin/scripts/codex-claude-compat.cmd"),
|
|
94
101
|
Path("plugin/scripts/codex-claude-compat.js"),
|
|
102
|
+
Path("plugin/scripts/opencode-claude-compat"),
|
|
103
|
+
Path("plugin/scripts/opencode-claude-compat.cmd"),
|
|
104
|
+
Path("plugin/scripts/opencode-claude-compat.js"),
|
|
95
105
|
Path("plugin/scripts/codex-hook.js"),
|
|
96
106
|
Path("plugin/scripts/backend-log-runner.sh"),
|
|
97
107
|
Path("plugin/scripts/_codex_env.sh"),
|
|
@@ -963,6 +973,237 @@ def _configure_reflexio_setup() -> bool:
|
|
|
963
973
|
return read_only
|
|
964
974
|
|
|
965
975
|
|
|
976
|
+
def _strip_jsonc(text: str) -> str:
|
|
977
|
+
"""Remove JSONC comments and trailing commas without touching strings."""
|
|
978
|
+
|
|
979
|
+
def skip_trivia(index: int) -> int:
|
|
980
|
+
while index < len(text):
|
|
981
|
+
while index < len(text) and text[index].isspace():
|
|
982
|
+
index += 1
|
|
983
|
+
if text[index : index + 2] == "//":
|
|
984
|
+
index += 2
|
|
985
|
+
while index < len(text) and text[index] not in "\r\n":
|
|
986
|
+
index += 1
|
|
987
|
+
continue
|
|
988
|
+
if text[index : index + 2] == "/*":
|
|
989
|
+
index += 2
|
|
990
|
+
while index + 1 < len(text) and text[index : index + 2] != "*/":
|
|
991
|
+
index += 1
|
|
992
|
+
index = min(index + 2, len(text))
|
|
993
|
+
continue
|
|
994
|
+
break
|
|
995
|
+
return index
|
|
996
|
+
|
|
997
|
+
out: list[str] = []
|
|
998
|
+
in_string = False
|
|
999
|
+
escaped = False
|
|
1000
|
+
i = 0
|
|
1001
|
+
while i < len(text):
|
|
1002
|
+
ch = text[i]
|
|
1003
|
+
nxt = text[i + 1] if i + 1 < len(text) else ""
|
|
1004
|
+
if in_string:
|
|
1005
|
+
out.append(ch)
|
|
1006
|
+
if escaped:
|
|
1007
|
+
escaped = False
|
|
1008
|
+
elif ch == "\\":
|
|
1009
|
+
escaped = True
|
|
1010
|
+
elif ch == '"':
|
|
1011
|
+
in_string = False
|
|
1012
|
+
i += 1
|
|
1013
|
+
continue
|
|
1014
|
+
if ch == '"':
|
|
1015
|
+
in_string = True
|
|
1016
|
+
out.append(ch)
|
|
1017
|
+
i += 1
|
|
1018
|
+
continue
|
|
1019
|
+
if ch == "/" and nxt == "/":
|
|
1020
|
+
while i < len(text) and text[i] not in "\r\n":
|
|
1021
|
+
i += 1
|
|
1022
|
+
continue
|
|
1023
|
+
if ch == "/" and nxt == "*":
|
|
1024
|
+
i += 2
|
|
1025
|
+
while i + 1 < len(text) and not (text[i] == "*" and text[i + 1] == "/"):
|
|
1026
|
+
i += 1
|
|
1027
|
+
i += 2
|
|
1028
|
+
continue
|
|
1029
|
+
if ch == ",":
|
|
1030
|
+
j = skip_trivia(i + 1)
|
|
1031
|
+
if j < len(text) and text[j] in "}]":
|
|
1032
|
+
i += 1
|
|
1033
|
+
continue
|
|
1034
|
+
out.append(ch)
|
|
1035
|
+
i += 1
|
|
1036
|
+
return "".join(out)
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
def _read_jsonc_object(path: Path) -> dict[str, object]:
|
|
1040
|
+
try:
|
|
1041
|
+
text = path.read_text() if path.exists() else "{}"
|
|
1042
|
+
parsed = json.loads(_strip_jsonc(text or "{}"))
|
|
1043
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
1044
|
+
raise ValueError(f"could not parse OpenCode config {path}: {exc}") from exc
|
|
1045
|
+
if not isinstance(parsed, dict):
|
|
1046
|
+
raise ValueError(f"OpenCode config {path} must be a JSON object")
|
|
1047
|
+
return parsed
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
def _opencode_global_config_dir() -> Path:
|
|
1051
|
+
xdg = os.environ.get("XDG_CONFIG_HOME", "").strip()
|
|
1052
|
+
base = Path(xdg) if xdg else Path.home() / ".config"
|
|
1053
|
+
return base / "opencode"
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
def _opencode_config_path(*, global_config: bool = False, cwd: Path | None = None) -> Path:
|
|
1057
|
+
if global_config:
|
|
1058
|
+
config_dir = _opencode_global_config_dir()
|
|
1059
|
+
for name in _OPENCODE_CONFIG_NAMES:
|
|
1060
|
+
candidate = config_dir / name
|
|
1061
|
+
if candidate.exists():
|
|
1062
|
+
return candidate
|
|
1063
|
+
return config_dir / "opencode.json"
|
|
1064
|
+
base = cwd or Path.cwd()
|
|
1065
|
+
candidates = [
|
|
1066
|
+
*(base / name for name in _OPENCODE_CONFIG_NAMES),
|
|
1067
|
+
*(base / ".opencode" / name for name in _OPENCODE_CONFIG_NAMES),
|
|
1068
|
+
]
|
|
1069
|
+
for candidate in candidates:
|
|
1070
|
+
if candidate.exists():
|
|
1071
|
+
return candidate
|
|
1072
|
+
return base / "opencode.json"
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
def _opencode_plugin_spec(entry: object) -> str | None:
|
|
1076
|
+
if isinstance(entry, str):
|
|
1077
|
+
return entry
|
|
1078
|
+
if isinstance(entry, list) and entry and isinstance(entry[0], str):
|
|
1079
|
+
return entry[0]
|
|
1080
|
+
return None
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
def _patch_opencode_plugin_config(
|
|
1084
|
+
config_path: Path, *, install: bool
|
|
1085
|
+
) -> tuple[bool, Path]:
|
|
1086
|
+
data = _read_jsonc_object(config_path)
|
|
1087
|
+
for field in ("plugins", "plugin"):
|
|
1088
|
+
value = data.get(field)
|
|
1089
|
+
if value is not None and not isinstance(value, list):
|
|
1090
|
+
raise ValueError(
|
|
1091
|
+
f'OpenCode config {config_path} field "{field}" must be a JSON array'
|
|
1092
|
+
)
|
|
1093
|
+
current_plugin = data.get("plugin")
|
|
1094
|
+
plugins: list[object] = []
|
|
1095
|
+
if isinstance(current_plugin, list):
|
|
1096
|
+
plugins.extend(current_plugin)
|
|
1097
|
+
legacy_plugins = data.get("plugins")
|
|
1098
|
+
if isinstance(legacy_plugins, list):
|
|
1099
|
+
plugins.extend(legacy_plugins)
|
|
1100
|
+
kept = [
|
|
1101
|
+
item
|
|
1102
|
+
for item in plugins
|
|
1103
|
+
if _opencode_plugin_spec(item) != _OPENCODE_PLUGIN_SPEC
|
|
1104
|
+
]
|
|
1105
|
+
next_plugins = [*kept, _OPENCODE_PLUGIN_SPEC] if install else kept
|
|
1106
|
+
if isinstance(current_plugin, list):
|
|
1107
|
+
changed = ("plugins" in data) or next_plugins != current_plugin
|
|
1108
|
+
else:
|
|
1109
|
+
changed = ("plugins" in data) or (install and bool(next_plugins))
|
|
1110
|
+
if not changed:
|
|
1111
|
+
return False, config_path
|
|
1112
|
+
if config_path.exists():
|
|
1113
|
+
original = config_path.read_text()
|
|
1114
|
+
if original.strip() and original != _strip_jsonc(original):
|
|
1115
|
+
config_path.with_suffix(config_path.suffix + ".bak").write_text(original)
|
|
1116
|
+
data["plugin"] = next_plugins
|
|
1117
|
+
data.pop("plugins", None)
|
|
1118
|
+
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1119
|
+
config_path.write_text(json.dumps(data, indent=2) + "\n")
|
|
1120
|
+
return True, config_path
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
def _has_extraction_provider() -> bool:
|
|
1124
|
+
env_config.load_reflexio_env(_REFLEXIO_ENV_PATH)
|
|
1125
|
+
if os.environ.get(env_config.REFLEXIO_API_KEY_ENV, "").strip():
|
|
1126
|
+
return True
|
|
1127
|
+
cli_path = os.environ.get("CLAUDE_SMART_CLI_PATH", "").strip()
|
|
1128
|
+
if cli_path:
|
|
1129
|
+
resolved = Path(cli_path).expanduser()
|
|
1130
|
+
if resolved.is_file() and os.access(resolved, os.X_OK):
|
|
1131
|
+
return True
|
|
1132
|
+
return bool(shutil.which("claude") or shutil.which("codex") or shutil.which("opencode"))
|
|
1133
|
+
|
|
1134
|
+
|
|
1135
|
+
def _extraction_provider_error() -> str:
|
|
1136
|
+
return (
|
|
1137
|
+
"error: OpenCode support needs a working learning/extraction provider.\n"
|
|
1138
|
+
"Run `npx claude-smart setup` to configure Reflexio, or install "
|
|
1139
|
+
"OpenCode, Claude Code, or Codex so local extraction can use a supported CLI.\n"
|
|
1140
|
+
)
|
|
1141
|
+
|
|
1142
|
+
|
|
1143
|
+
def _opencode_install_supported_from_this_package() -> bool:
|
|
1144
|
+
return (_SCRIPTS_DIR / "smart-install.sh").is_file()
|
|
1145
|
+
|
|
1146
|
+
|
|
1147
|
+
def _bootstrap_opencode_install(read_only: bool) -> tuple[bool, str]:
|
|
1148
|
+
if not _opencode_install_supported_from_this_package():
|
|
1149
|
+
return (
|
|
1150
|
+
False,
|
|
1151
|
+
"OpenCode install is supported from the npm package. "
|
|
1152
|
+
"Run `npx claude-smart install --host opencode`.",
|
|
1153
|
+
)
|
|
1154
|
+
try:
|
|
1155
|
+
_force_plugin_root(_PLUGIN_ROOT)
|
|
1156
|
+
except OSError as exc:
|
|
1157
|
+
return False, str(exc)
|
|
1158
|
+
bash = _resolve_bash()
|
|
1159
|
+
if not bash:
|
|
1160
|
+
return False, "bash is required to bootstrap claude-smart dependencies"
|
|
1161
|
+
result = subprocess.run([bash, str(_SCRIPTS_DIR / "smart-install.sh")], cwd=_PLUGIN_ROOT)
|
|
1162
|
+
if result.returncode != 0:
|
|
1163
|
+
return False, f"smart-install.sh failed in {_PLUGIN_ROOT}"
|
|
1164
|
+
if _INSTALL_FAILURE_MARKER.is_file():
|
|
1165
|
+
first_line = _INSTALL_FAILURE_MARKER.read_text().splitlines()
|
|
1166
|
+
reason = (first_line[0].strip() if first_line else "") or "unknown error"
|
|
1167
|
+
return False, reason
|
|
1168
|
+
if read_only:
|
|
1169
|
+
_prune_publish_hooks_for_read_only(_PLUGIN_ROOT)
|
|
1170
|
+
return True, str(_PLUGIN_ROOT)
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
def cmd_install_opencode(args: argparse.Namespace) -> int:
|
|
1174
|
+
if not _opencode_install_supported_from_this_package():
|
|
1175
|
+
sys.stderr.write(
|
|
1176
|
+
"error: OpenCode install is supported from the npm package. "
|
|
1177
|
+
"Run `npx claude-smart install --host opencode`.\n"
|
|
1178
|
+
)
|
|
1179
|
+
return 1
|
|
1180
|
+
read_only = _configure_reflexio_setup()
|
|
1181
|
+
if not _has_extraction_provider():
|
|
1182
|
+
sys.stderr.write(_extraction_provider_error())
|
|
1183
|
+
return 1
|
|
1184
|
+
bootstrapped, message = _bootstrap_opencode_install(read_only)
|
|
1185
|
+
if not bootstrapped:
|
|
1186
|
+
sys.stderr.write(
|
|
1187
|
+
f"error: claude-smart OpenCode setup failed during dependency bootstrap: {message}\n"
|
|
1188
|
+
)
|
|
1189
|
+
return 1
|
|
1190
|
+
config_path = _opencode_config_path(
|
|
1191
|
+
global_config=bool(getattr(args, "global_config", False))
|
|
1192
|
+
)
|
|
1193
|
+
try:
|
|
1194
|
+
changed, config_path = _patch_opencode_plugin_config(config_path, install=True)
|
|
1195
|
+
except ValueError as exc:
|
|
1196
|
+
sys.stderr.write(f"error: {exc}\n")
|
|
1197
|
+
return 1
|
|
1198
|
+
action = "Updated" if changed else "OpenCode config already includes"
|
|
1199
|
+
sys.stdout.write(
|
|
1200
|
+
f"{action} `{_OPENCODE_PLUGIN_SPEC}` in {config_path}.\n"
|
|
1201
|
+
f"Prepared claude-smart runtime at {message}.\n"
|
|
1202
|
+
"Restart OpenCode in your project so it loads the plugin.\n"
|
|
1203
|
+
)
|
|
1204
|
+
return 0
|
|
1205
|
+
|
|
1206
|
+
|
|
966
1207
|
def cmd_install_codex(args: argparse.Namespace) -> int:
|
|
967
1208
|
"""Install the claude-smart plugin marketplace for Codex.
|
|
968
1209
|
|
|
@@ -1073,7 +1314,7 @@ def cmd_install(args: argparse.Namespace) -> int:
|
|
|
1073
1314
|
|
|
1074
1315
|
Runs ``claude plugin marketplace add`` (pointed at the bundled marketplace
|
|
1075
1316
|
at ``_REPO_ROOT``) followed by ``claude plugin install``, then appends the
|
|
1076
|
-
local-provider flags to ``~/.
|
|
1317
|
+
local-provider flags to ``~/.claude-smart/.env`` so reflexio can route
|
|
1077
1318
|
generation through the local Claude Code CLI.
|
|
1078
1319
|
|
|
1079
1320
|
Args:
|
|
@@ -1084,6 +1325,8 @@ def cmd_install(args: argparse.Namespace) -> int:
|
|
|
1084
1325
|
"""
|
|
1085
1326
|
if getattr(args, "host", "claude-code") == "codex":
|
|
1086
1327
|
return cmd_install_codex(args)
|
|
1328
|
+
if getattr(args, "host", "claude-code") == "opencode":
|
|
1329
|
+
return cmd_install_opencode(args)
|
|
1087
1330
|
|
|
1088
1331
|
if not shutil.which("claude"):
|
|
1089
1332
|
sys.stderr.write(
|
|
@@ -1156,6 +1399,8 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
1156
1399
|
"""
|
|
1157
1400
|
if getattr(args, "host", "claude-code") == "codex":
|
|
1158
1401
|
return cmd_update_codex(args)
|
|
1402
|
+
if getattr(args, "host", "claude-code") == "opencode":
|
|
1403
|
+
return cmd_update_opencode(args)
|
|
1159
1404
|
|
|
1160
1405
|
_run_service(_DASHBOARD_SCRIPT, "stop")
|
|
1161
1406
|
_run_service(_BACKEND_SCRIPT, "stop")
|
|
@@ -1182,6 +1427,17 @@ def cmd_update_codex(_args: argparse.Namespace) -> int:
|
|
|
1182
1427
|
return cmd_install_codex(install_args)
|
|
1183
1428
|
|
|
1184
1429
|
|
|
1430
|
+
def cmd_update_opencode(args: argparse.Namespace) -> int:
|
|
1431
|
+
_run_service(_DASHBOARD_SCRIPT, "stop")
|
|
1432
|
+
_run_service(_BACKEND_SCRIPT, "stop")
|
|
1433
|
+
sys.stdout.write(
|
|
1434
|
+
"Updating claude-smart OpenCode support by reinstalling from this package...\n"
|
|
1435
|
+
)
|
|
1436
|
+
install_args = argparse.Namespace(**vars(args))
|
|
1437
|
+
install_args.host = "opencode"
|
|
1438
|
+
return cmd_install_opencode(install_args)
|
|
1439
|
+
|
|
1440
|
+
|
|
1185
1441
|
def cmd_uninstall(_args: argparse.Namespace) -> int:
|
|
1186
1442
|
"""Uninstall claude-smart from Claude Code via the native plugin CLI.
|
|
1187
1443
|
|
|
@@ -1196,6 +1452,8 @@ def cmd_uninstall(_args: argparse.Namespace) -> int:
|
|
|
1196
1452
|
"""
|
|
1197
1453
|
if getattr(_args, "host", "claude-code") == "codex":
|
|
1198
1454
|
return cmd_uninstall_codex(_args)
|
|
1455
|
+
if getattr(_args, "host", "claude-code") == "opencode":
|
|
1456
|
+
return cmd_uninstall_opencode(_args)
|
|
1199
1457
|
|
|
1200
1458
|
if not shutil.which("claude"):
|
|
1201
1459
|
sys.stderr.write(
|
|
@@ -1256,6 +1514,28 @@ def cmd_uninstall_codex(_args: argparse.Namespace) -> int:
|
|
|
1256
1514
|
return 0
|
|
1257
1515
|
|
|
1258
1516
|
|
|
1517
|
+
def cmd_uninstall_opencode(args: argparse.Namespace) -> int:
|
|
1518
|
+
_run_service(_DASHBOARD_SCRIPT, "stop")
|
|
1519
|
+
_run_service(_BACKEND_SCRIPT, "stop")
|
|
1520
|
+
config_path = _opencode_config_path(
|
|
1521
|
+
global_config=bool(getattr(args, "global_config", False))
|
|
1522
|
+
)
|
|
1523
|
+
try:
|
|
1524
|
+
changed, config_path = _patch_opencode_plugin_config(config_path, install=False)
|
|
1525
|
+
except ValueError as exc:
|
|
1526
|
+
sys.stderr.write(f"error: {exc}\n")
|
|
1527
|
+
return 1
|
|
1528
|
+
if changed:
|
|
1529
|
+
sys.stdout.write(f"Removed `{_OPENCODE_PLUGIN_SPEC}` from {config_path}.\n")
|
|
1530
|
+
else:
|
|
1531
|
+
sys.stdout.write(f"OpenCode config did not include `{_OPENCODE_PLUGIN_SPEC}`.\n")
|
|
1532
|
+
sys.stdout.write(
|
|
1533
|
+
"Restart OpenCode to apply. "
|
|
1534
|
+
f"{_LOCAL_DATA_NOTICE}"
|
|
1535
|
+
)
|
|
1536
|
+
return 0
|
|
1537
|
+
|
|
1538
|
+
|
|
1259
1539
|
def cmd_show(args: argparse.Namespace) -> int:
|
|
1260
1540
|
"""Print this project's skills + preferences, plus globally-shared skills.
|
|
1261
1541
|
|
|
@@ -1981,28 +2261,46 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1981
2261
|
inst = sub.add_parser("install", help="Install claude-smart")
|
|
1982
2262
|
inst.add_argument(
|
|
1983
2263
|
"--host",
|
|
1984
|
-
choices=("claude-code", "codex"),
|
|
2264
|
+
choices=("claude-code", "codex", "opencode"),
|
|
1985
2265
|
default="claude-code",
|
|
1986
2266
|
help="Install target host",
|
|
1987
2267
|
)
|
|
2268
|
+
inst.add_argument(
|
|
2269
|
+
"--global",
|
|
2270
|
+
dest="global_config",
|
|
2271
|
+
action="store_true",
|
|
2272
|
+
help="For OpenCode, patch ~/.config/opencode instead of the project config",
|
|
2273
|
+
)
|
|
1988
2274
|
inst.set_defaults(func=cmd_install)
|
|
1989
2275
|
|
|
1990
2276
|
upd = sub.add_parser("update", help="Update claude-smart to the latest version")
|
|
1991
2277
|
upd.add_argument(
|
|
1992
2278
|
"--host",
|
|
1993
|
-
choices=("claude-code", "codex"),
|
|
2279
|
+
choices=("claude-code", "codex", "opencode"),
|
|
1994
2280
|
default="claude-code",
|
|
1995
2281
|
help="Update target host",
|
|
1996
2282
|
)
|
|
2283
|
+
upd.add_argument(
|
|
2284
|
+
"--global",
|
|
2285
|
+
dest="global_config",
|
|
2286
|
+
action="store_true",
|
|
2287
|
+
help="For OpenCode, patch ~/.config/opencode instead of the project config",
|
|
2288
|
+
)
|
|
1997
2289
|
upd.set_defaults(func=cmd_update)
|
|
1998
2290
|
|
|
1999
2291
|
uni = sub.add_parser("uninstall", help="Remove claude-smart")
|
|
2000
2292
|
uni.add_argument(
|
|
2001
2293
|
"--host",
|
|
2002
|
-
choices=("claude-code", "codex"),
|
|
2294
|
+
choices=("claude-code", "codex", "opencode"),
|
|
2003
2295
|
default="claude-code",
|
|
2004
2296
|
help="Uninstall target host",
|
|
2005
2297
|
)
|
|
2298
|
+
uni.add_argument(
|
|
2299
|
+
"--global",
|
|
2300
|
+
dest="global_config",
|
|
2301
|
+
action="store_true",
|
|
2302
|
+
help="For OpenCode, patch ~/.config/opencode instead of the project config",
|
|
2303
|
+
)
|
|
2006
2304
|
uni.set_defaults(func=cmd_uninstall)
|
|
2007
2305
|
|
|
2008
2306
|
sh = sub.add_parser(
|
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
"""Shared ``~/.
|
|
1
|
+
"""Shared ``~/.claude-smart/.env`` helpers for claude-smart.
|
|
2
|
+
|
|
3
|
+
claude-smart keeps its env under ``~/.claude-smart`` (not ``~/.reflexio``) so an
|
|
4
|
+
OSS reflexio backend sharing this machine never leaks its ``.env`` into
|
|
5
|
+
claude-smart. The data directory stays shared at ``~/.reflexio/data``. This path
|
|
6
|
+
must stay in sync with the ``REFLEXIO_ENV_FILE`` export in
|
|
7
|
+
``scripts/backend-service.sh`` and the source path in
|
|
8
|
+
``scripts/_lib.sh`` (``claude_smart_source_reflexio_env``).
|
|
9
|
+
"""
|
|
2
10
|
|
|
3
11
|
from __future__ import annotations
|
|
4
12
|
|
|
5
13
|
import os
|
|
6
14
|
from pathlib import Path
|
|
7
15
|
|
|
8
|
-
REFLEXIO_ENV_PATH = Path.home() / ".
|
|
16
|
+
REFLEXIO_ENV_PATH = Path.home() / ".claude-smart" / ".env"
|
|
9
17
|
MANAGED_REFLEXIO_URL = "https://www.reflexio.ai/"
|
|
10
18
|
REFLEXIO_URL_ENV = "REFLEXIO_URL"
|
|
11
19
|
REFLEXIO_API_KEY_ENV = "REFLEXIO_API_KEY"
|
|
@@ -60,7 +68,7 @@ def parse_env_line(line: str) -> tuple[str, str] | None:
|
|
|
60
68
|
|
|
61
69
|
|
|
62
70
|
def load_reflexio_env(path: Path | None = None) -> None:
|
|
63
|
-
"""Load ``~/.
|
|
71
|
+
"""Load ``~/.claude-smart/.env`` into ``os.environ`` without overriding values."""
|
|
64
72
|
path = path or REFLEXIO_ENV_PATH
|
|
65
73
|
try:
|
|
66
74
|
text = path.read_text()
|
|
@@ -111,7 +119,7 @@ def set_env_vars(path: Path, values: dict[str, str]) -> list[str]:
|
|
|
111
119
|
|
|
112
120
|
|
|
113
121
|
def ensure_local_env_defaults(path: Path | None = None) -> list[str]:
|
|
114
|
-
"""Create or augment ``~/.
|
|
122
|
+
"""Create or augment ``~/.claude-smart/.env`` for claude-smart local mode.
|
|
115
123
|
|
|
116
124
|
Existing active assignments win. This repairs first installs and deleted
|
|
117
125
|
env files without clobbering explicit user overrides such as
|
|
@@ -5,8 +5,10 @@ from __future__ import annotations
|
|
|
5
5
|
import json
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
+
from contextlib import suppress
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Any
|
|
11
|
+
from urllib.parse import urlparse
|
|
10
12
|
|
|
11
13
|
from claude_smart import hook
|
|
12
14
|
from claude_smart.reflexio_adapter import Adapter
|
|
@@ -41,10 +43,12 @@ def _int_env(name: str, default: int) -> int:
|
|
|
41
43
|
|
|
42
44
|
_CLAUDE_SMART_WINDOW_SIZE = _int_env("CLAUDE_SMART_WINDOW_SIZE", 5)
|
|
43
45
|
_CLAUDE_SMART_STRIDE_SIZE = _int_env("CLAUDE_SMART_STRIDE_SIZE", 3)
|
|
44
|
-
# Optimizer
|
|
45
|
-
# claude-smart
|
|
46
|
-
|
|
46
|
+
# Optimizer defaults are local-only by default because they store an absolute
|
|
47
|
+
# path to the claude-smart helper process. Set this env var to "1" to force
|
|
48
|
+
# enabling against a non-local Reflexio URL, or "0" to disable everywhere.
|
|
49
|
+
_OPTIMIZER_ENV = "CLAUDE_SMART_ENABLE_OPTIMIZER"
|
|
47
50
|
_OPTIMIZER_TIMEOUT_SECONDS = 300
|
|
51
|
+
_LOCAL_REFLEXIO_HOSTS = {"", "localhost", "127.0.0.1", "::1"}
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
def _adapter() -> Adapter:
|
|
@@ -109,7 +113,7 @@ def handle(payload: dict[str, Any]) -> None:
|
|
|
109
113
|
window_size=_CLAUDE_SMART_WINDOW_SIZE,
|
|
110
114
|
stride_size=_CLAUDE_SMART_STRIDE_SIZE,
|
|
111
115
|
)
|
|
112
|
-
if
|
|
116
|
+
if _should_apply_optimizer_defaults(adapter):
|
|
113
117
|
adapter.apply_optimizer_defaults(
|
|
114
118
|
script_path=_optimizer_assistant_path(),
|
|
115
119
|
timeout_seconds=_OPTIMIZER_TIMEOUT_SECONDS,
|
|
@@ -131,13 +135,28 @@ def handle(payload: dict[str, Any]) -> None:
|
|
|
131
135
|
)
|
|
132
136
|
sys.stdout.write("\n")
|
|
133
137
|
|
|
134
|
-
|
|
138
|
+
with suppress(Exception):
|
|
135
139
|
adapter.mark_stall_notified()
|
|
136
|
-
except Exception: # noqa: BLE001 — telemetry must not break session.
|
|
137
|
-
pass
|
|
138
140
|
|
|
139
141
|
|
|
140
142
|
def _optimizer_assistant_path() -> str:
|
|
141
143
|
executable = Path(sys.executable)
|
|
142
144
|
suffix = ".exe" if os.name == "nt" else ""
|
|
143
145
|
return str(executable.with_name(f"claude-smart-optimizer-assistant{suffix}"))
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _should_apply_optimizer_defaults(adapter: Any) -> bool:
|
|
149
|
+
flag = os.environ.get(_OPTIMIZER_ENV, "").strip().lower()
|
|
150
|
+
if flag in {"0", "false", "no", "off"}:
|
|
151
|
+
return False
|
|
152
|
+
if flag in {"1", "true", "yes", "on"}:
|
|
153
|
+
return True
|
|
154
|
+
return _is_local_reflexio_url(getattr(adapter, "url", ""))
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _is_local_reflexio_url(url: str) -> bool:
|
|
158
|
+
if not url:
|
|
159
|
+
return True
|
|
160
|
+
parsed = urlparse(url)
|
|
161
|
+
host = parsed.hostname if parsed.scheme else url.split(":", 1)[0]
|
|
162
|
+
return (host or "").lower() in _LOCAL_REFLEXIO_HOSTS
|
|
@@ -377,7 +377,7 @@ def handle(payload: dict[str, Any]) -> tuple[publish.PublishStatus, int] | None:
|
|
|
377
377
|
last_assistant_message = payload.get("last_assistant_message")
|
|
378
378
|
assistant_text = (
|
|
379
379
|
last_assistant_message
|
|
380
|
-
if runtime.is_codex()
|
|
380
|
+
if (runtime.is_codex() or runtime.is_opencode())
|
|
381
381
|
and isinstance(last_assistant_message, str)
|
|
382
382
|
and last_assistant_message
|
|
383
383
|
else _scan_transcript_for_assistant_text(entries)
|
|
@@ -77,7 +77,7 @@ def resolve_user_id(cwd: str | os.PathLike[str] | None = None) -> str:
|
|
|
77
77
|
Honors the ``REFLEXIO_USER_ID`` env var as an explicit override (e.g. so a
|
|
78
78
|
user can point multiple projects at a single Reflexio identity), and
|
|
79
79
|
otherwise falls back to :func:`resolve_project_id`. The env var is
|
|
80
|
-
loaded from ``~/.
|
|
80
|
+
loaded from ``~/.claude-smart/.env`` before reading the process environment so
|
|
81
81
|
CLI commands and hooks use the same identity resolution.
|
|
82
82
|
|
|
83
83
|
Args:
|
|
@@ -6,16 +6,15 @@ Exists so hook handlers (a) don't import reflexio directly at module scope
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
import inspect
|
|
9
10
|
import logging
|
|
10
11
|
import os
|
|
11
|
-
import inspect
|
|
12
12
|
from collections.abc import Sequence
|
|
13
13
|
from concurrent.futures import ThreadPoolExecutor
|
|
14
14
|
from dataclasses import dataclass, field
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
-
from claude_smart import env_config
|
|
18
|
-
from claude_smart import runtime
|
|
17
|
+
from claude_smart import env_config, runtime
|
|
19
18
|
|
|
20
19
|
_LOGGER = logging.getLogger(__name__)
|
|
21
20
|
|
|
@@ -174,8 +173,9 @@ class Adapter:
|
|
|
174
173
|
|
|
175
174
|
Idempotent compare-then-write: reads ``Config``, only issues a
|
|
176
175
|
``set_config`` when the server-side values differ from the desired
|
|
177
|
-
dict below.
|
|
178
|
-
|
|
176
|
+
dict below. SessionStart calls this only for local Reflexio URLs by
|
|
177
|
+
default; ``CLAUDE_SMART_ENABLE_OPTIMIZER=1`` forces hosted URLs, and
|
|
178
|
+
``CLAUDE_SMART_ENABLE_OPTIMIZER=0`` disables it everywhere.
|
|
179
179
|
"""
|
|
180
180
|
client = self._get_client()
|
|
181
181
|
if client is None:
|
|
@@ -14,7 +14,8 @@ INTERNAL_ENV = "CLAUDE_SMART_INTERNAL"
|
|
|
14
14
|
|
|
15
15
|
HOST_CLAUDE_CODE = "claude-code"
|
|
16
16
|
HOST_CODEX = "codex"
|
|
17
|
-
|
|
17
|
+
HOST_OPENCODE = "opencode"
|
|
18
|
+
VALID_HOSTS = frozenset({HOST_CLAUDE_CODE, HOST_CODEX, HOST_OPENCODE})
|
|
18
19
|
|
|
19
20
|
_SHARED_AGENT_VERSION = "claude-code"
|
|
20
21
|
_current_host: str | None = None
|
|
@@ -42,6 +43,11 @@ def is_codex() -> bool:
|
|
|
42
43
|
return host() == HOST_CODEX
|
|
43
44
|
|
|
44
45
|
|
|
46
|
+
def is_opencode() -> bool:
|
|
47
|
+
"""True when the current hook invocation came from OpenCode."""
|
|
48
|
+
return host() == HOST_OPENCODE
|
|
49
|
+
|
|
50
|
+
|
|
45
51
|
def agent_version() -> str:
|
|
46
52
|
"""Reflexio agent version used for shared learning across hosts."""
|
|
47
53
|
return _SHARED_AGENT_VERSION
|