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,371 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# Shared helpers for openclaw-smart plugin scripts. Source, do not execute.
|
|
3
|
+
|
|
4
|
+
# openClaw hooks run with a minimal non-interactive PATH that often omits
|
|
5
|
+
# nvm/asdf/brew shims where `npm`, `uv`, etc. live. Pull the user's login-shell
|
|
6
|
+
# PATH the same way claude-mem does so hook-spawned scripts find them without
|
|
7
|
+
# the user having to mutate their global PATH. Best-effort — failures silent.
|
|
8
|
+
openclaw_smart_source_login_path() {
|
|
9
|
+
local _SHELL_PATH
|
|
10
|
+
if [ -n "${SHELL:-}" ] && [ -x "$SHELL" ]; then
|
|
11
|
+
if _SHELL_PATH="$("$SHELL" -lc 'printf %s "$PATH"' 2>/dev/null)"; then
|
|
12
|
+
[ -n "$_SHELL_PATH" ] && export PATH="$_SHELL_PATH:$PATH"
|
|
13
|
+
fi
|
|
14
|
+
fi
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
# Prepend the astral.sh installer's default bin directories to PATH so a
|
|
18
|
+
# freshly-installed `uv` is reachable before the user re-sources their
|
|
19
|
+
# shell rc. Prepend (not append) so the just-installed binary wins over
|
|
20
|
+
# any stale copy earlier in PATH. Literals only — no subshell, so safe
|
|
21
|
+
# under `set -u`.
|
|
22
|
+
openclaw_smart_prepend_astral_bins() {
|
|
23
|
+
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:$PATH"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Prepend openclaw-smart's private Node.js install, if present. The Setup
|
|
27
|
+
# hook installs Node here when the user does not already have a suitable
|
|
28
|
+
# node/npm on PATH, so later hook-spawned dashboard scripts can run without
|
|
29
|
+
# requiring nvm/brew/global npm to be visible from openClaw's shell.
|
|
30
|
+
openclaw_smart_prepend_node_bins() {
|
|
31
|
+
local _OC_NODE_ROOT
|
|
32
|
+
_OC_NODE_ROOT="$HOME/.openclaw-smart/node/current"
|
|
33
|
+
export PATH="$_OC_NODE_ROOT/bin:$_OC_NODE_ROOT:$PATH"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
openclaw_smart_is_internal_invocation_env() {
|
|
37
|
+
if [ "${OPENCLAW_SMART_INTERNAL:-}" = "1" ]; then
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
return 1
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
openclaw_smart_dashboard_unavailable_marker() {
|
|
44
|
+
printf '%s\n' "$HOME/.openclaw-smart/dashboard-unavailable"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
openclaw_smart_node_recovery_hint() {
|
|
48
|
+
cat <<'EOF'
|
|
49
|
+
Recovery:
|
|
50
|
+
1. Restart openClaw to let openclaw-smart retry its private Node.js install.
|
|
51
|
+
2. If the retry is blocked by your network or OS policy, install Node.js 20.9+ manually:
|
|
52
|
+
EOF
|
|
53
|
+
if openclaw_smart_is_windows; then
|
|
54
|
+
cat <<'EOF'
|
|
55
|
+
- winget install OpenJS.NodeJS.LTS
|
|
56
|
+
- or download the LTS installer from https://nodejs.org/
|
|
57
|
+
EOF
|
|
58
|
+
elif [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then
|
|
59
|
+
cat <<'EOF'
|
|
60
|
+
- brew install node
|
|
61
|
+
- or download the LTS installer from https://nodejs.org/
|
|
62
|
+
EOF
|
|
63
|
+
else
|
|
64
|
+
cat <<'EOF'
|
|
65
|
+
- use your distro package manager for nodejs/npm
|
|
66
|
+
- or download the LTS archive from https://nodejs.org/
|
|
67
|
+
EOF
|
|
68
|
+
fi
|
|
69
|
+
cat <<'EOF'
|
|
70
|
+
3. Run /openclaw-smart:restart, then /openclaw-smart:dashboard.
|
|
71
|
+
EOF
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
openclaw_smart_write_dashboard_unavailable() {
|
|
75
|
+
local reason marker
|
|
76
|
+
reason="$1"
|
|
77
|
+
marker="$(openclaw_smart_dashboard_unavailable_marker)"
|
|
78
|
+
mkdir -p "$(dirname "$marker")"
|
|
79
|
+
{
|
|
80
|
+
printf 'openclaw-smart dashboard is unavailable: %s\n\n' "$reason"
|
|
81
|
+
printf 'The learning backend and hooks can still work; only the dashboard UI is affected.\n\n'
|
|
82
|
+
printf 'Private Node.js location: %s\n\n' "$HOME/.openclaw-smart/node/current"
|
|
83
|
+
openclaw_smart_node_recovery_hint
|
|
84
|
+
} > "$marker"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
openclaw_smart_clear_dashboard_unavailable() {
|
|
88
|
+
rm -f "$(openclaw_smart_dashboard_unavailable_marker)"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Return 0 (true) if running under a Windows-flavoured bash (Git Bash,
|
|
92
|
+
# MSYS, Cygwin). Used to gate POSIX-only primitives (setsid, process
|
|
93
|
+
# groups) and route around Windows-specific potholes (the python3 App
|
|
94
|
+
# Execution Alias stub at WindowsApps\python3.exe).
|
|
95
|
+
openclaw_smart_is_windows() {
|
|
96
|
+
case "$(uname -s 2>/dev/null)" in
|
|
97
|
+
MINGW*|MSYS*|CYGWIN*) return 0 ;;
|
|
98
|
+
*) return 1 ;;
|
|
99
|
+
esac
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Print the absolute path of a working python interpreter, or nothing
|
|
103
|
+
# (and return non-zero) if none is usable. On Windows, `python3` is
|
|
104
|
+
# usually the Microsoft Store "App Execution Alias" stub at
|
|
105
|
+
# %LocalAppData%\Microsoft\WindowsApps\python3.exe — `command -v python3`
|
|
106
|
+
# returns truthy but invoking it just prints a "Python was not found"
|
|
107
|
+
# message and exits non-zero. We probe with `-V` to filter the stub out
|
|
108
|
+
# and prefer `python` (the real interpreter when one is installed).
|
|
109
|
+
openclaw_smart_resolve_python() {
|
|
110
|
+
if openclaw_smart_is_windows; then
|
|
111
|
+
for cand in python python3; do
|
|
112
|
+
if command -v "$cand" >/dev/null 2>&1 && "$cand" -V >/dev/null 2>&1; then
|
|
113
|
+
command -v "$cand"
|
|
114
|
+
return 0
|
|
115
|
+
fi
|
|
116
|
+
done
|
|
117
|
+
return 1
|
|
118
|
+
fi
|
|
119
|
+
for cand in python3 python; do
|
|
120
|
+
if command -v "$cand" >/dev/null 2>&1 && "$cand" -V >/dev/null 2>&1; then
|
|
121
|
+
command -v "$cand"
|
|
122
|
+
return 0
|
|
123
|
+
fi
|
|
124
|
+
done
|
|
125
|
+
return 1
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
openclaw_smart_download() {
|
|
129
|
+
local url dest src _OC_PY
|
|
130
|
+
url="$1"
|
|
131
|
+
dest="$2"
|
|
132
|
+
mkdir -p "$(dirname "$dest")"
|
|
133
|
+
case "$url" in
|
|
134
|
+
file://*)
|
|
135
|
+
src="${url#file://}"
|
|
136
|
+
cp "$src" "$dest"
|
|
137
|
+
return $?
|
|
138
|
+
;;
|
|
139
|
+
esac
|
|
140
|
+
if command -v curl >/dev/null 2>&1; then
|
|
141
|
+
curl -fsSL "$url" -o "$dest"
|
|
142
|
+
return $?
|
|
143
|
+
fi
|
|
144
|
+
if command -v wget >/dev/null 2>&1; then
|
|
145
|
+
wget -q -O "$dest" "$url"
|
|
146
|
+
return $?
|
|
147
|
+
fi
|
|
148
|
+
if command -v powershell >/dev/null 2>&1; then
|
|
149
|
+
URL="$url" DEST="$dest" powershell -NoProfile -ExecutionPolicy Bypass -Command \
|
|
150
|
+
'$ProgressPreference="SilentlyContinue"; Invoke-WebRequest -Uri $env:URL -OutFile $env:DEST'
|
|
151
|
+
return $?
|
|
152
|
+
fi
|
|
153
|
+
if command -v pwsh >/dev/null 2>&1; then
|
|
154
|
+
URL="$url" DEST="$dest" pwsh -NoProfile -Command \
|
|
155
|
+
'$ProgressPreference="SilentlyContinue"; Invoke-WebRequest -Uri $env:URL -OutFile $env:DEST'
|
|
156
|
+
return $?
|
|
157
|
+
fi
|
|
158
|
+
_OC_PY=$(openclaw_smart_resolve_python || true)
|
|
159
|
+
if [ -n "$_OC_PY" ]; then
|
|
160
|
+
"$_OC_PY" - "$url" "$dest" <<'PY'
|
|
161
|
+
import sys
|
|
162
|
+
import urllib.request
|
|
163
|
+
|
|
164
|
+
url, dest = sys.argv[1], sys.argv[2]
|
|
165
|
+
with urllib.request.urlopen(url, timeout=60) as response:
|
|
166
|
+
data = response.read()
|
|
167
|
+
with open(dest, "wb") as fh:
|
|
168
|
+
fh.write(data)
|
|
169
|
+
PY
|
|
170
|
+
return $?
|
|
171
|
+
fi
|
|
172
|
+
return 1
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
openclaw_smart_sha256_file() {
|
|
176
|
+
local path _OC_PY
|
|
177
|
+
path="$1"
|
|
178
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
179
|
+
sha256sum "$path" | awk '{print $1}'
|
|
180
|
+
return "${PIPESTATUS[0]}"
|
|
181
|
+
fi
|
|
182
|
+
if command -v shasum >/dev/null 2>&1; then
|
|
183
|
+
shasum -a 256 "$path" | awk '{print $1}'
|
|
184
|
+
return "${PIPESTATUS[0]}"
|
|
185
|
+
fi
|
|
186
|
+
if command -v openssl >/dev/null 2>&1; then
|
|
187
|
+
openssl dgst -sha256 "$path" | awk '{print $NF}'
|
|
188
|
+
return "${PIPESTATUS[0]}"
|
|
189
|
+
fi
|
|
190
|
+
_OC_PY=$(openclaw_smart_resolve_python || true)
|
|
191
|
+
if [ -n "$_OC_PY" ]; then
|
|
192
|
+
"$_OC_PY" - "$path" <<'PY'
|
|
193
|
+
import hashlib
|
|
194
|
+
import sys
|
|
195
|
+
|
|
196
|
+
h = hashlib.sha256()
|
|
197
|
+
with open(sys.argv[1], "rb") as fh:
|
|
198
|
+
for chunk in iter(lambda: fh.read(1024 * 1024), b""):
|
|
199
|
+
h.update(chunk)
|
|
200
|
+
print(h.hexdigest())
|
|
201
|
+
PY
|
|
202
|
+
return $?
|
|
203
|
+
fi
|
|
204
|
+
return 1
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
# Return 0 if `node` exists and satisfies the minimum major/minor pair.
|
|
208
|
+
# Patch versions are intentionally ignored because our requirement is a
|
|
209
|
+
# floor, not an exact runtime pin.
|
|
210
|
+
openclaw_smart_node_satisfies() {
|
|
211
|
+
local min_major min_minor version major minor
|
|
212
|
+
min_major="$1"
|
|
213
|
+
min_minor="$2"
|
|
214
|
+
command -v node >/dev/null 2>&1 || return 1
|
|
215
|
+
version=$(node -v 2>/dev/null | sed 's/^v//') || return 1
|
|
216
|
+
major=$(printf '%s' "$version" | awk -F. '{print $1}')
|
|
217
|
+
minor=$(printf '%s' "$version" | awk -F. '{print $2}')
|
|
218
|
+
[ -n "$major" ] && [ -n "$minor" ] || return 1
|
|
219
|
+
case "$major:$minor" in
|
|
220
|
+
*[!0-9:]*|:*|*:) return 1 ;;
|
|
221
|
+
esac
|
|
222
|
+
[ "$major" -gt "$min_major" ] && return 0
|
|
223
|
+
[ "$major" -eq "$min_major" ] && [ "$minor" -ge "$min_minor" ]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
openclaw_smart_resolve_npm() {
|
|
227
|
+
local cand
|
|
228
|
+
for cand in npm npm.cmd; do
|
|
229
|
+
if command -v "$cand" >/dev/null 2>&1; then
|
|
230
|
+
command -v "$cand"
|
|
231
|
+
return 0
|
|
232
|
+
fi
|
|
233
|
+
done
|
|
234
|
+
return 1
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
openclaw_smart_npm_available() {
|
|
238
|
+
local npm_bin
|
|
239
|
+
npm_bin=$(openclaw_smart_resolve_npm || true)
|
|
240
|
+
[ -n "$npm_bin" ] || return 1
|
|
241
|
+
"$npm_bin" --version >/dev/null 2>&1
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
openclaw_smart_log_max_bytes() {
|
|
245
|
+
printf '%s\n' "10000000"
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
openclaw_smart_trim_log_file() {
|
|
249
|
+
local file max_bytes size tmp
|
|
250
|
+
file="$1"
|
|
251
|
+
max_bytes="${2:-$(openclaw_smart_log_max_bytes)}"
|
|
252
|
+
case "$max_bytes" in
|
|
253
|
+
''|*[!0-9]*) return 0 ;;
|
|
254
|
+
esac
|
|
255
|
+
[ -f "$file" ] || return 0
|
|
256
|
+
size=$(wc -c < "$file" 2>/dev/null | tr -d '[:space:]') || return 0
|
|
257
|
+
case "$size" in
|
|
258
|
+
''|*[!0-9]*) return 0 ;;
|
|
259
|
+
esac
|
|
260
|
+
[ "$size" -le "$max_bytes" ] && return 0
|
|
261
|
+
|
|
262
|
+
tmp="${file}.trim.$$"
|
|
263
|
+
if tail -c "$max_bytes" "$file" > "$tmp" 2>/dev/null; then
|
|
264
|
+
# Rewrite the existing path instead of replacing it, so a process with
|
|
265
|
+
# this file already open in append mode keeps writing to the capped file.
|
|
266
|
+
cat "$tmp" > "$file"
|
|
267
|
+
fi
|
|
268
|
+
rm -f "$tmp"
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
openclaw_smart_append_capped_log() {
|
|
272
|
+
local file max_bytes
|
|
273
|
+
file="$1"
|
|
274
|
+
max_bytes="${2:-$(openclaw_smart_log_max_bytes)}"
|
|
275
|
+
shift 2
|
|
276
|
+
mkdir -p "$(dirname "$file")"
|
|
277
|
+
openclaw_smart_trim_log_file "$file" "$max_bytes"
|
|
278
|
+
printf '%s\n' "$*" >> "$file"
|
|
279
|
+
openclaw_smart_trim_log_file "$file" "$max_bytes"
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
# Spawn a command fully detached from the current shell so a hook timeout
|
|
283
|
+
# (openClaw's install/SessionStart budget) cannot kill it mid-flight.
|
|
284
|
+
# POSIX: setsid → python3 os.setsid → nohup (in that order of strength).
|
|
285
|
+
# Windows: nohup alone — Git Bash has no setsid, no process groups, and
|
|
286
|
+
# `os.setsid()` is POSIX-only; nohup ignores SIGHUP which is enough to
|
|
287
|
+
# survive the parent console closing. The python3 fallback is gated on a
|
|
288
|
+
# real-interpreter probe (-V) so the Windows App Execution Alias stub
|
|
289
|
+
# doesn't get invoked. Caller is responsible for redirecting stdout/stderr;
|
|
290
|
+
# we do not impose a log destination here. Stdin is closed so the child
|
|
291
|
+
# cannot inherit a tty. Use `$!` after this call to capture the pid.
|
|
292
|
+
openclaw_smart_spawn_detached() {
|
|
293
|
+
if openclaw_smart_is_windows; then
|
|
294
|
+
nohup "$@" < /dev/null &
|
|
295
|
+
return 0
|
|
296
|
+
fi
|
|
297
|
+
if command -v setsid >/dev/null 2>&1; then
|
|
298
|
+
setsid nohup "$@" < /dev/null &
|
|
299
|
+
elif _OC_PY=$(openclaw_smart_resolve_python) && [ -n "$_OC_PY" ]; then
|
|
300
|
+
"$_OC_PY" -c 'import os,sys; os.setsid(); os.execvp(sys.argv[1], sys.argv[1:])' \
|
|
301
|
+
"$@" < /dev/null &
|
|
302
|
+
else
|
|
303
|
+
nohup "$@" < /dev/null &
|
|
304
|
+
fi
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
# Terminate a process and (on POSIX) its whole process group, escalating
|
|
308
|
+
# from TERM to KILL after a short grace period. On Windows there are no
|
|
309
|
+
# POSIX process groups, so we use `taskkill /T /F /PID` which walks the
|
|
310
|
+
# child-process tree via the Windows job-object/parent-pid relationships
|
|
311
|
+
# — the closest equivalent to a group kill.
|
|
312
|
+
#
|
|
313
|
+
# Windows-specific subtlety: in Git Bash / MSYS, `$!` for a backgrounded
|
|
314
|
+
# job returns the MSYS pid (an internal counter), NOT the native Windows
|
|
315
|
+
# pid that taskkill needs. `ps -W` (or `-o winpid=`) exposes the WINPID
|
|
316
|
+
# column for the translation. If the lookup fails we fall back to
|
|
317
|
+
# treating the input as a native pid, so callers can pass either an MSYS
|
|
318
|
+
# pid (recorded via $!) or a Windows pid (from tasklist) interchangeably.
|
|
319
|
+
# The `//T //F //PID` syntax escapes Git Bash's MSYS path-mangling of
|
|
320
|
+
# arguments that begin with `/`.
|
|
321
|
+
openclaw_smart_kill_tree() {
|
|
322
|
+
pid="$1"
|
|
323
|
+
[ -z "$pid" ] && return 0
|
|
324
|
+
if openclaw_smart_is_windows; then
|
|
325
|
+
# Git Bash's `ps` is the procps fork, not BSD/Linux ps; it has no
|
|
326
|
+
# -o option but its default header is `PID PPID PGID WINPID TTY ...`,
|
|
327
|
+
# so column 4 of the data row is the Windows pid. awk extracts it
|
|
328
|
+
# without depending on -o support.
|
|
329
|
+
target=""
|
|
330
|
+
if command -v ps >/dev/null 2>&1; then
|
|
331
|
+
target=$(ps -p "$pid" 2>/dev/null | awk 'NR==2 {print $4}' | tr -d ' \r\n' || true)
|
|
332
|
+
fi
|
|
333
|
+
[ -z "$target" ] && target="$pid"
|
|
334
|
+
if command -v taskkill >/dev/null 2>&1; then
|
|
335
|
+
taskkill //T //F //PID "$target" >/dev/null 2>&1 || true
|
|
336
|
+
else
|
|
337
|
+
kill -TERM "$pid" 2>/dev/null || true
|
|
338
|
+
sleep 0.5
|
|
339
|
+
kill -KILL "$pid" 2>/dev/null || true
|
|
340
|
+
fi
|
|
341
|
+
return 0
|
|
342
|
+
fi
|
|
343
|
+
current_pgid=""
|
|
344
|
+
if command -v ps >/dev/null 2>&1; then
|
|
345
|
+
current_pgid=$(ps -o pgid= -p "$$" 2>/dev/null | tr -d ' ')
|
|
346
|
+
fi
|
|
347
|
+
if [ -n "$current_pgid" ] && [ "$pid" = "$current_pgid" ]; then
|
|
348
|
+
return 0
|
|
349
|
+
fi
|
|
350
|
+
if ! kill -TERM -- "-$pid" 2>/dev/null; then
|
|
351
|
+
kill -TERM "$pid" 2>/dev/null || true
|
|
352
|
+
sleep 0.5
|
|
353
|
+
kill -KILL "$pid" 2>/dev/null || true
|
|
354
|
+
return 0
|
|
355
|
+
fi
|
|
356
|
+
for _ in 1 2 3 4 5; do
|
|
357
|
+
kill -0 -- "-$pid" 2>/dev/null || return 0
|
|
358
|
+
sleep 0.2
|
|
359
|
+
done
|
|
360
|
+
kill -KILL -- "-$pid" 2>/dev/null || true
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
# Return 0 (true) if $1 names a pid file whose pid is currently alive.
|
|
364
|
+
# Silent on missing/empty/stale files.
|
|
365
|
+
openclaw_smart_pid_alive_file() {
|
|
366
|
+
pid_file="$1"
|
|
367
|
+
[ -f "$pid_file" ] || return 1
|
|
368
|
+
pid=$(cat "$pid_file" 2>/dev/null || echo "")
|
|
369
|
+
[ -n "$pid" ] || return 1
|
|
370
|
+
kill -0 "$pid" 2>/dev/null
|
|
371
|
+
}
|
package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-log-runner.sh
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Run the backend command and stream its stdout/stderr into a capped log file.
|
|
3
|
+
set -eu
|
|
4
|
+
|
|
5
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
# shellcheck source=_lib.sh
|
|
7
|
+
. "$HERE/_lib.sh"
|
|
8
|
+
|
|
9
|
+
if [ "$#" -lt 4 ] || [ "$3" != "--" ]; then
|
|
10
|
+
exit 2
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
LOG_FILE="$1"
|
|
14
|
+
MAX_BYTES="$2"
|
|
15
|
+
shift 3
|
|
16
|
+
|
|
17
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
18
|
+
openclaw_smart_trim_log_file "$LOG_FILE" "$MAX_BYTES"
|
|
19
|
+
|
|
20
|
+
STATUS_FILE="${TMPDIR:-/tmp}/openclaw-smart-backend-log-runner.$$.status"
|
|
21
|
+
rm -f "$STATUS_FILE"
|
|
22
|
+
|
|
23
|
+
(
|
|
24
|
+
set +e
|
|
25
|
+
"$@" 2>&1
|
|
26
|
+
printf '%s\n' "$?" > "$STATUS_FILE"
|
|
27
|
+
) | while IFS= read -r line || [ -n "$line" ]; do
|
|
28
|
+
openclaw_smart_append_capped_log "$LOG_FILE" "$MAX_BYTES" "$line"
|
|
29
|
+
done
|
|
30
|
+
|
|
31
|
+
status=$(cat "$STATUS_FILE" 2>/dev/null || printf '1')
|
|
32
|
+
rm -f "$STATUS_FILE"
|
|
33
|
+
exit "$status"
|
package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/scripts/backend-service.sh
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Auto-start the reflexio FastAPI backend (port 8071) if it's not already
|
|
3
|
+
# running. Detached spawn, returns immediately so the SessionStart hook
|
|
4
|
+
# doesn't block the session.
|
|
5
|
+
#
|
|
6
|
+
# Port choice: openclaw-smart shares 8071/8072 with the sibling claude-smart
|
|
7
|
+
# plugin so the two plugins coexist on a single shared backend (one SQLite
|
|
8
|
+
# store, one extractor process) — not reflexio's 8061 default, which is
|
|
9
|
+
# reserved for a developer's own local reflexio instance.
|
|
10
|
+
#
|
|
11
|
+
# Subcommands:
|
|
12
|
+
# start probe /health; if nothing we recognize is on the port,
|
|
13
|
+
# spawn `uv run reflexio services start --only backend
|
|
14
|
+
# --no-reload` detached. Polls /health briefly so first
|
|
15
|
+
# use after session start lands on a warm server, then
|
|
16
|
+
# returns empty stdout regardless.
|
|
17
|
+
# stop SIGTERM the recorded process group, escalating to
|
|
18
|
+
# SIGKILL after a short grace period.
|
|
19
|
+
# session-end no-op by default; only stops the backend if
|
|
20
|
+
# OPENCLAW_SMART_BACKEND_STOP_ON_END=1 (opt-in — the
|
|
21
|
+
# backend is intended to be long-lived across sessions).
|
|
22
|
+
# status print "running on http://localhost:PORT" or "not running".
|
|
23
|
+
set -eu
|
|
24
|
+
|
|
25
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
26
|
+
# shellcheck source=_lib.sh
|
|
27
|
+
. "$HERE/_lib.sh"
|
|
28
|
+
openclaw_smart_source_login_path
|
|
29
|
+
openclaw_smart_prepend_astral_bins
|
|
30
|
+
|
|
31
|
+
CMD="${1:-start}"
|
|
32
|
+
PORT=8071
|
|
33
|
+
EMBEDDING_PORT="${EMBEDDING_PORT:-8072}"
|
|
34
|
+
# Pass through to `reflexio services start/stop` so the spawned backend
|
|
35
|
+
# binds to PORT.
|
|
36
|
+
export BACKEND_PORT="$PORT"
|
|
37
|
+
export EMBEDDING_PORT
|
|
38
|
+
|
|
39
|
+
# Default: route extraction through the active host CLI + ONNX embedder
|
|
40
|
+
# so openclaw-smart works without any LLM API key. Users can opt out by
|
|
41
|
+
# pre-exporting these to 0.
|
|
42
|
+
export OPENCLAW_SMART_USE_LOCAL_CLI="${OPENCLAW_SMART_USE_LOCAL_CLI:-1}"
|
|
43
|
+
export OPENCLAW_SMART_USE_LOCAL_EMBEDDING="${OPENCLAW_SMART_USE_LOCAL_EMBEDDING:-1}"
|
|
44
|
+
if [ "${OPENCLAW_SMART_USE_LOCAL_EMBEDDING:-}" = "1" ]; then
|
|
45
|
+
export REFLEXIO_EMBEDDING_PROVIDER="${REFLEXIO_EMBEDDING_PROVIDER:-local_service}"
|
|
46
|
+
export REFLEXIO_EMBEDDING_SERVICE_URL="${REFLEXIO_EMBEDDING_SERVICE_URL:-http://127.0.0.1:$EMBEDDING_PORT}"
|
|
47
|
+
fi
|
|
48
|
+
PLUGIN_ROOT="$(cd "$HERE/.." && pwd)"
|
|
49
|
+
|
|
50
|
+
# Pin the openclaw CLI explicitly so the reflexio backend's openclaw_provider
|
|
51
|
+
# can find it from a hook context whose PATH lacks the user's normal CLI dir.
|
|
52
|
+
if [ -z "${OPENCLAW_BIN:-}" ]; then
|
|
53
|
+
if _oc_cli_path=$(command -v openclaw 2>/dev/null) && [ -n "$_oc_cli_path" ]; then
|
|
54
|
+
export OPENCLAW_BIN="$_oc_cli_path"
|
|
55
|
+
elif [ -x "$HOME/.local/bin/openclaw" ]; then
|
|
56
|
+
export OPENCLAW_BIN="$HOME/.local/bin/openclaw"
|
|
57
|
+
fi
|
|
58
|
+
unset _oc_cli_path
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
STATE_DIR="$HOME/.openclaw-smart"
|
|
62
|
+
PID_FILE="$STATE_DIR/backend.pid"
|
|
63
|
+
LOG_FILE="$STATE_DIR/backend.log"
|
|
64
|
+
LOG_MAX_BYTES="$(openclaw_smart_log_max_bytes)"
|
|
65
|
+
mkdir -p "$STATE_DIR"
|
|
66
|
+
openclaw_smart_trim_log_file "$LOG_FILE" "$LOG_MAX_BYTES"
|
|
67
|
+
|
|
68
|
+
emit_ok() { echo ''; }
|
|
69
|
+
|
|
70
|
+
emit_start_failure() {
|
|
71
|
+
reason="$1"
|
|
72
|
+
if py=$(openclaw_smart_resolve_python 2>/dev/null); then
|
|
73
|
+
"$py" - "$reason" <<'PY'
|
|
74
|
+
import json
|
|
75
|
+
import sys
|
|
76
|
+
|
|
77
|
+
reason = sys.argv[1].strip()
|
|
78
|
+
message = (
|
|
79
|
+
"> **openclaw-smart learning backend is not running.** "
|
|
80
|
+
"Interactions are being buffered locally, but learning will not publish "
|
|
81
|
+
"until the backend starts.\n"
|
|
82
|
+
)
|
|
83
|
+
if reason:
|
|
84
|
+
message += f">\n> Last startup error: `{reason}`\n"
|
|
85
|
+
message += (
|
|
86
|
+
">\n> Make sure the openclaw CLI is on PATH so the local model provider "
|
|
87
|
+
"can be reached. Then run `/openclaw-smart:restart`."
|
|
88
|
+
)
|
|
89
|
+
print(json.dumps({"prependContext": message}))
|
|
90
|
+
PY
|
|
91
|
+
else
|
|
92
|
+
emit_ok
|
|
93
|
+
fi
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Tree-kill the recorded process.
|
|
97
|
+
kill_group() {
|
|
98
|
+
openclaw_smart_kill_tree "$1"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# True if /health returns 200. Reflexio's /health is a plain GET with no
|
|
102
|
+
# marker header, so we can't distinguish our backend from someone else's
|
|
103
|
+
# reflexio on the same port — if you run two reflexio instances on $PORT
|
|
104
|
+
# you'll get collision regardless of what we do here.
|
|
105
|
+
backend_healthy() {
|
|
106
|
+
command -v curl >/dev/null 2>&1 || return 1
|
|
107
|
+
curl -sf -o /dev/null "http://127.0.0.1:$PORT/health" 2>/dev/null
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# True only if the recorded PID is alive AND /health responds. A stale
|
|
111
|
+
# PID file from a crashed backend is not enough — we must see the port
|
|
112
|
+
# actually answer, so next hook retries cleanly.
|
|
113
|
+
is_our_backend_running() {
|
|
114
|
+
if [ -f "$PID_FILE" ]; then
|
|
115
|
+
pid=$(cat "$PID_FILE" 2>/dev/null || echo "")
|
|
116
|
+
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
|
117
|
+
backend_healthy && return 0
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
# Recover from a missing PID file if a foreign-but-functional reflexio
|
|
121
|
+
# is already serving — no need to start a second one.
|
|
122
|
+
backend_healthy && return 0
|
|
123
|
+
return 1
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# True if *anything* is listening on the port (even non-HTTP). Used to
|
|
127
|
+
# avoid stomping on a foreign listener with a failed-to-start uvicorn.
|
|
128
|
+
port_occupied() {
|
|
129
|
+
(echo >"/dev/tcp/127.0.0.1/$PORT") 2>/dev/null
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Reap any reflexio/uvicorn listener still holding $PORT after the PID
|
|
133
|
+
# file kill. Filters by cmdline so we don't knock over an unrelated
|
|
134
|
+
# service a user has bound to $PORT — symmetric with start's refusal to
|
|
135
|
+
# stomp on a foreign listener. Silent on failure.
|
|
136
|
+
reap_port_listeners() {
|
|
137
|
+
command -v lsof >/dev/null 2>&1 || return 0
|
|
138
|
+
candidates=$(lsof -ti:"$PORT" 2>/dev/null) || candidates=""
|
|
139
|
+
[ -z "$candidates" ] && return 0
|
|
140
|
+
ours=""
|
|
141
|
+
for pid in $candidates; do
|
|
142
|
+
cmdline=$(ps -p "$pid" -o command= 2>/dev/null || true)
|
|
143
|
+
case "$cmdline" in
|
|
144
|
+
*reflexio*|*uvicorn*) ours="$ours $pid" ;;
|
|
145
|
+
esac
|
|
146
|
+
done
|
|
147
|
+
[ -z "$ours" ] && return 0
|
|
148
|
+
# shellcheck disable=SC2086
|
|
149
|
+
kill -TERM $ours 2>/dev/null || true
|
|
150
|
+
sleep 1
|
|
151
|
+
remaining=""
|
|
152
|
+
for pid in $ours; do
|
|
153
|
+
kill -0 "$pid" 2>/dev/null && remaining="$remaining $pid"
|
|
154
|
+
done
|
|
155
|
+
[ -z "$remaining" ] && return 0
|
|
156
|
+
# shellcheck disable=SC2086
|
|
157
|
+
kill -KILL $remaining 2>/dev/null || true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# Full shutdown: kill the recorded process group (if any) then sweep the
|
|
161
|
+
# port for surviving reflexio listeners. Used by both `stop` and the
|
|
162
|
+
# opt-in `session-end` path so a stale/missing PID file doesn't produce
|
|
163
|
+
# a silent no-op.
|
|
164
|
+
full_stop() {
|
|
165
|
+
if [ -f "$PID_FILE" ]; then
|
|
166
|
+
kill_group "$(cat "$PID_FILE" 2>/dev/null)"
|
|
167
|
+
rm -f "$PID_FILE"
|
|
168
|
+
fi
|
|
169
|
+
reap_port_listeners
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
case "$CMD" in
|
|
173
|
+
start)
|
|
174
|
+
if openclaw_smart_is_internal_invocation_env; then
|
|
175
|
+
emit_ok; exit 0
|
|
176
|
+
fi
|
|
177
|
+
# Opt-out: users who don't want the backend managed by the hook can
|
|
178
|
+
# set OPENCLAW_SMART_BACKEND_AUTOSTART=0.
|
|
179
|
+
if [ "${OPENCLAW_SMART_BACKEND_AUTOSTART:-1}" = "0" ]; then
|
|
180
|
+
emit_ok; exit 0
|
|
181
|
+
fi
|
|
182
|
+
if is_our_backend_running; then emit_ok; exit 0; fi
|
|
183
|
+
if port_occupied; then
|
|
184
|
+
# Something answered the TCP probe but /health didn't — don't
|
|
185
|
+
# start a second uvicorn on top of it.
|
|
186
|
+
openclaw_smart_append_capped_log "$LOG_FILE" "$LOG_MAX_BYTES" "[openclaw-smart] backend: port $PORT held by another process; skipping"
|
|
187
|
+
emit_ok; exit 0
|
|
188
|
+
fi
|
|
189
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
190
|
+
if [ "${OPENCLAW_SMART_BOOTSTRAPPING:-}" != "1" ] && [ -x "$PLUGIN_ROOT/scripts/smart-install.sh" ]; then
|
|
191
|
+
openclaw_smart_append_capped_log "$LOG_FILE" "$LOG_MAX_BYTES" "[openclaw-smart] backend: uv not on PATH; running installer"
|
|
192
|
+
OPENCLAW_SMART_BOOTSTRAPPING=1 bash "$PLUGIN_ROOT/scripts/smart-install.sh" >>"$STATE_DIR/install.log" 2>&1 || true
|
|
193
|
+
openclaw_smart_source_login_path
|
|
194
|
+
openclaw_smart_prepend_astral_bins
|
|
195
|
+
fi
|
|
196
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
197
|
+
openclaw_smart_append_capped_log "$LOG_FILE" "$LOG_MAX_BYTES" "[openclaw-smart] backend: uv not on PATH after installer; skipping"
|
|
198
|
+
emit_ok; exit 0
|
|
199
|
+
fi
|
|
200
|
+
fi
|
|
201
|
+
# The reflexio project root lives four levels above the plugin dir:
|
|
202
|
+
# plugin/ -> integrations/openclaw -> reflexio/integrations -> reflexio -> open_source/reflexio
|
|
203
|
+
REFLEXIO_PROJECT="$(cd "$PLUGIN_ROOT/../../../.." && pwd)"
|
|
204
|
+
cd "$REFLEXIO_PROJECT"
|
|
205
|
+
|
|
206
|
+
# Cap local interaction history to keep the SQLite store small for
|
|
207
|
+
# openclaw-smart users. Reflexio's library defaults are much higher
|
|
208
|
+
# (250k/50k) for server deployments; here we override only in the
|
|
209
|
+
# openclaw-smart plugin context. Users can still override via env.
|
|
210
|
+
export INTERACTION_CLEANUP_THRESHOLD="${INTERACTION_CLEANUP_THRESHOLD:-500}"
|
|
211
|
+
export INTERACTION_CLEANUP_DELETE_COUNT="${INTERACTION_CLEANUP_DELETE_COUNT:-200}"
|
|
212
|
+
|
|
213
|
+
# backend-log-runner.sh owns stdout/stderr capture so process output
|
|
214
|
+
# cannot grow backend.log past its cap.
|
|
215
|
+
#
|
|
216
|
+
# --workers: reflexio defaults to 2 (zero-downtime worker recycling
|
|
217
|
+
# for server deployments). For a single-user openClaw plugin that's
|
|
218
|
+
# pure overhead: ~1.1 GB extra RSS, periodic 5–10 s spawn hiccups
|
|
219
|
+
# during worker rotation, and SQLite can't accept concurrent writers
|
|
220
|
+
# anyway. Default to 1 here; opt in to N via
|
|
221
|
+
# OPENCLAW_SMART_BACKEND_WORKERS for power users running concurrent
|
|
222
|
+
# openClaw sessions or wanting zero-downtime recycling.
|
|
223
|
+
workers="${OPENCLAW_SMART_BACKEND_WORKERS:-1}"
|
|
224
|
+
openclaw_smart_spawn_detached bash "$HERE/backend-log-runner.sh" \
|
|
225
|
+
"$LOG_FILE" "$LOG_MAX_BYTES" -- \
|
|
226
|
+
uv run --project "$REFLEXIO_PROJECT" --quiet \
|
|
227
|
+
reflexio services start --only backend --no-reload --workers "$workers"
|
|
228
|
+
svc_pid=$!
|
|
229
|
+
# Record the spawned pid, not a pgid sampled with ps. On POSIX,
|
|
230
|
+
# setsid/python os.setsid make this pid the new process group leader;
|
|
231
|
+
# sampling immediately can race and capture the caller's pgid instead.
|
|
232
|
+
echo "$svc_pid" > "$PID_FILE"
|
|
233
|
+
|
|
234
|
+
# Give uvicorn up to ~10s to answer /health. The very first boot
|
|
235
|
+
# after a fresh checkout may be slower (LiteLLM import, chromadb
|
|
236
|
+
# warmup). We always return ok; the backend catches up in background
|
|
237
|
+
# if it needs to.
|
|
238
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
239
|
+
backend_healthy && break
|
|
240
|
+
sleep 1
|
|
241
|
+
done
|
|
242
|
+
if ! backend_healthy; then
|
|
243
|
+
pid=$(cat "$PID_FILE" 2>/dev/null || echo "")
|
|
244
|
+
if [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null; then
|
|
245
|
+
reason=$(tail -n 120 "$LOG_FILE" 2>/dev/null | grep -E "No LLM provider available|No generation-capable LLM provider available|CLI not found|skipping provider registration|Application startup failed" | tail -n 1 | sed 's/^[[:space:]]*//')
|
|
246
|
+
emit_start_failure "$reason"
|
|
247
|
+
exit 0
|
|
248
|
+
fi
|
|
249
|
+
fi
|
|
250
|
+
emit_ok
|
|
251
|
+
;;
|
|
252
|
+
stop)
|
|
253
|
+
full_stop
|
|
254
|
+
emit_ok
|
|
255
|
+
;;
|
|
256
|
+
session-end)
|
|
257
|
+
# Default: leave the backend running so learning keeps flowing
|
|
258
|
+
# between sessions. Opt in to teardown with
|
|
259
|
+
# OPENCLAW_SMART_BACKEND_STOP_ON_END=1.
|
|
260
|
+
if [ "${OPENCLAW_SMART_BACKEND_STOP_ON_END:-0}" = "1" ]; then
|
|
261
|
+
full_stop
|
|
262
|
+
fi
|
|
263
|
+
emit_ok
|
|
264
|
+
;;
|
|
265
|
+
status)
|
|
266
|
+
if is_our_backend_running; then echo "running on http://localhost:$PORT"; else echo "not running"; fi
|
|
267
|
+
;;
|
|
268
|
+
*)
|
|
269
|
+
emit_ok
|
|
270
|
+
;;
|
|
271
|
+
esac
|