claude-smart 0.2.42 → 0.2.44
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 +1 -1
- package/bin/claude-smart.js +2 -2
- package/package.json +9 -3
- package/plugin/.claude-plugin/plugin.json +9 -3
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/README.md +23 -3
- package/plugin/pyproject.toml +3 -3
- package/plugin/scripts/_lib.sh +91 -0
- package/plugin/scripts/backend-service.sh +51 -4
- package/plugin/scripts/cli.sh +3 -1
- package/plugin/scripts/codex-hook.js +72 -4
- package/plugin/scripts/dashboard-build.sh +1 -0
- package/plugin/scripts/dashboard-service.sh +1 -0
- package/plugin/scripts/ensure-plugin-root.sh +1 -0
- package/plugin/scripts/hook_entry.sh +6 -3
- package/plugin/scripts/smart-install.sh +3 -2
- package/plugin/src/README.md +57 -0
- package/plugin/src/claude_smart/context_format.py +11 -12
- package/plugin/src/claude_smart/cs_cite.py +26 -12
- package/plugin/src/claude_smart/ids.py +13 -5
- package/plugin/uv.lock +126 -5
- package/plugin/vendor/reflexio/.env.example +62 -0
- package/plugin/vendor/reflexio/LICENSE +201 -0
- package/plugin/vendor/reflexio/README.md +338 -0
- package/plugin/vendor/reflexio/pyproject.toml +274 -0
- package/plugin/vendor/reflexio/reflexio/README.md +184 -0
- package/plugin/vendor/reflexio/reflexio/__init__.py +166 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/README.md +109 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/backends.py +175 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/bench.py +642 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/embed_cache.py +330 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/report.py +317 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/report.md +43 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/results/results.json +4478 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/scenarios.py +134 -0
- package/plugin/vendor/reflexio/reflexio/benchmarks/retrieval_latency/seed.py +255 -0
- package/plugin/vendor/reflexio/reflexio/cli/README.md +287 -0
- package/plugin/vendor/reflexio/reflexio/cli/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/__main__.py +56 -0
- package/plugin/vendor/reflexio/reflexio/cli/_client.py +86 -0
- package/plugin/vendor/reflexio/reflexio/cli/app.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/bootstrap_config.py +265 -0
- package/plugin/vendor/reflexio/reflexio/cli/codex_auth.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/admin_cmd.py +65 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/agent_playbooks.py +503 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/api.py +114 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/auth.py +109 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/config_cmd.py +511 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/doctor.py +127 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/embeddings.py +53 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/interactions.py +478 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/profiles.py +303 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/services.py +289 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/setup_cmd.py +964 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/shortcuts.py +285 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/status_cmd.py +143 -0
- package/plugin/vendor/reflexio/reflexio/cli/commands/user_playbooks.py +373 -0
- package/plugin/vendor/reflexio/reflexio/cli/env_loader.py +284 -0
- package/plugin/vendor/reflexio/reflexio/cli/errors.py +217 -0
- package/plugin/vendor/reflexio/reflexio/cli/log_format.py +247 -0
- package/plugin/vendor/reflexio/reflexio/cli/output.py +867 -0
- package/plugin/vendor/reflexio/reflexio/cli/paths.py +41 -0
- package/plugin/vendor/reflexio/reflexio/cli/run_services.py +391 -0
- package/plugin/vendor/reflexio/reflexio/cli/state.py +204 -0
- package/plugin/vendor/reflexio/reflexio/cli/stop_services.py +96 -0
- package/plugin/vendor/reflexio/reflexio/cli/utils.py +329 -0
- package/plugin/vendor/reflexio/reflexio/client/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/client/cache.py +150 -0
- package/plugin/vendor/reflexio/reflexio/client/client.py +2613 -0
- package/plugin/vendor/reflexio/reflexio/defaults.py +23 -0
- package/plugin/vendor/reflexio/reflexio/integrations/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/.clawhubignore +7 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/README.md +274 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/TESTING.md +517 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/hook/handler.js +473 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package-lock.json +2156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/handler.ts +241 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/hook/setup.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/index.ts +130 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/publish.ts +113 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/search.ts +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/server.ts +103 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/sqlite-buffer.ts +156 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/lib/user-id.ts +134 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/openclaw.plugin.json +41 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/package.json +17 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/rules/reflexio.md +24 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/plugin/skills/reflexio/SKILL.md +48 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/publish_clawhub.sh +278 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/references/HOOK.md +164 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/install.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/scripts/uninstall.sh +35 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/publish.test.ts +27 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/search.test.ts +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/server.test.ts +42 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/setup.test.ts +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/sqlite-buffer.test.ts +91 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tests/user-id.test.ts +50 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw/vitest.config.ts +13 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/README.md +120 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/TESTING.md +168 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package-lock.json +1657 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/package.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/HEARTBEAT.md +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/README.md +84 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/_meta.json +6 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/agents/reflexio-extractor.md +45 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/handler.ts +214 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/hook/setup.ts +55 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/index.ts +327 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts +233 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/dedup.ts +80 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/io.ts +155 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/openclaw-cli.ts +67 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/search.ts +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-playbook.ts +76 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/write-profile.ts +79 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/openclaw.plugin.json +46 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/package.json +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/README.md +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/full_consolidation.md +56 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/playbook_extraction.md +217 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/prompts/profile_extraction.md +132 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-consolidate/SKILL.md +33 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/skills/reflexio-embedded/SKILL.md +194 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/HOOK.md +18 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/architecture.md +49 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/comparison.md +31 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/future-work.md +47 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/references/porting-notes.md +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/install.sh +52 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/scripts/uninstall.sh +36 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/consolidate.test.ts +135 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/dedup.test.ts +104 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/io.test.ts +175 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/search.test.ts +66 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/smoke-test.ts +140 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-playbook.test.ts +93 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tests/write-profile.test.ts +174 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/tsconfig.json +16 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/types/openclaw.d.ts +230 -0
- package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/vitest.config.ts +7 -0
- package/plugin/vendor/reflexio/reflexio/lib/__init__.py +23 -0
- package/plugin/vendor/reflexio/reflexio/lib/_agent_playbook.py +310 -0
- package/plugin/vendor/reflexio/reflexio/lib/_base.py +225 -0
- package/plugin/vendor/reflexio/reflexio/lib/_config.py +83 -0
- package/plugin/vendor/reflexio/reflexio/lib/_dashboard.py +266 -0
- package/plugin/vendor/reflexio/reflexio/lib/_generation.py +176 -0
- package/plugin/vendor/reflexio/reflexio/lib/_interactions.py +334 -0
- package/plugin/vendor/reflexio/reflexio/lib/_operations.py +153 -0
- package/plugin/vendor/reflexio/reflexio/lib/_profiles.py +545 -0
- package/plugin/vendor/reflexio/reflexio/lib/_reflection.py +52 -0
- package/plugin/vendor/reflexio/reflexio/lib/_search.py +167 -0
- package/plugin/vendor/reflexio/reflexio/lib/_storage_labels.py +103 -0
- package/plugin/vendor/reflexio/reflexio/lib/_user_playbook.py +288 -0
- package/plugin/vendor/reflexio/reflexio/lib/reflexio_lib.py +27 -0
- package/plugin/vendor/reflexio/reflexio/models/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/braintrust_schema.py +141 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/common.py +41 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/entities.py +1112 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/domain/enums.py +63 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/eval_overview_schema.py +487 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/internal_schema.py +28 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/pending_tool_call_schema.py +83 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/retriever_schema.py +768 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/service_schemas.py +9 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/stall_state_schema.py +32 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/__init__.py +3 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/converters.py +177 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/entities.py +129 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/ui/enums.py +25 -0
- package/plugin/vendor/reflexio/reflexio/models/api_schema/validators.py +333 -0
- package/plugin/vendor/reflexio/reflexio/models/config_schema.py +908 -0
- package/plugin/vendor/reflexio/reflexio/models/py.typed +0 -0
- package/plugin/vendor/reflexio/reflexio/server/OVERVIEW.md +90 -0
- package/plugin/vendor/reflexio/reflexio/server/README.md +622 -0
- package/plugin/vendor/reflexio/reflexio/server/__init__.py +210 -0
- package/plugin/vendor/reflexio/reflexio/server/__main__.py +132 -0
- package/plugin/vendor/reflexio/reflexio/server/_auth.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/api.py +2868 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/README.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/account_api.py +143 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/health_api.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/pending_tool_call_api.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/precondition_checks.py +66 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/publisher_api.py +562 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/request_context.py +50 -0
- package/plugin/vendor/reflexio/reflexio/server/api_endpoints/stall_state_api.py +100 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/__init__.py +15 -0
- package/plugin/vendor/reflexio/reflexio/server/cache/reflexio_cache.py +208 -0
- package/plugin/vendor/reflexio/reflexio/server/correlation.py +46 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/__init__.py +30 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/embedding_service.py +359 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/image_utils.py +55 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/litellm_client.py +1871 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/llm_utils.py +140 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/model_defaults.py +479 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_provider.py +1122 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/claude_code_stream_parser.py +197 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/embedding_service_provider.py +338 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/local_embedding_provider.py +213 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/providers/nomic_embedding_provider.py +288 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/__init__.py +6 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/cross_encoder_reranker.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/rerank/llm_reranker.py +148 -0
- package/plugin/vendor/reflexio/reflexio/server/llm/tools.py +716 -0
- package/plugin/vendor/reflexio/reflexio/server/operation_limiter.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/_dispatchers.py +54 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/README.md +121 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation/v1.0.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/agent_success_evaluation_with_comparison/v1.0.0.prompt.md +76 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/answer_synthesis/v1.5.2.prompt.md +88 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/compress_session_for_query/v1.3.0.prompt.md +31 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/document_expansion/v1.0.0.prompt.md +20 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.0.0.prompt.md +53 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.1.0.prompt.md +57 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.2.0.prompt.md +68 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.3.0.prompt.md +70 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.4.0.prompt.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.5.0.prompt.md +82 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/memory_reflection/v1.6.0.prompt.md +83 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.1.0.prompt.md +193 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_aggregation/v2.2.0.prompt.md +206 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0-deprecated.prompt.md +66 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v1.1.0.prompt.md +46 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0-deprecated.prompt.md +64 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.0.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.1.0.prompt.md +39 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.2.0.prompt.md +47 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.0.prompt.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.1.prompt.md +69 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_consolidation/v2.3.2.prompt.md +71 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.0.2.prompt.md +254 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.1.0.prompt.md +274 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.0.prompt.md +283 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.2.prompt.md +234 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context/v4.2.3.prompt.md +244 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v1.0.0.prompt.md +73 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v2.0.0.prompt.md +86 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.0.0.prompt.md +97 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.1.0.prompt.md +119 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.2.0.prompt.md +123 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_context_expert/v3.3.0.prompt.md +137 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.1.0.prompt.md +24 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main/v1.2.0.prompt.md +29 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.0.0.prompt.md +11 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.1.0.prompt.md +21 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_extraction_main_expert/v1.2.0.prompt.md +25 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.0.0.prompt.md +37 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.1.0.prompt.md +40 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_optimizer_judge/v1.2.0.prompt.md +36 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v1.0.0.prompt.md +45 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v2.0.0.prompt.md +81 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate/v3.0.0.prompt.md +80 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/playbook_should_generate_expert/v1.0.0.prompt.md +34 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_deduplication/v1.0.0.prompt.md +116 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_should_generate_override/v1.0.0.prompt.md +16 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.0.0.prompt.md +140 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_instruction_start/v1.1.0.prompt.md +160 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/profile_update_main/v1.0.0.prompt.md +14 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/query_reformulation/v1.0.0.prompt.md +19 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/rerank_relevance/v1.1.0.prompt.md +44 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_comparison/v1.0.0.prompt.md +43 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_bank/shadow_content_evaluation/v1.0.0.prompt.md +33 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/feedback_extraction_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_evaluation/prompt_evaluation_dataset/profile_update_main_v1.jsonl +10 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_manager.py +280 -0
- package/plugin/vendor/reflexio/reflexio/server/prompt/prompt_schema.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/README.md +58 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/_eval_health.py +131 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_constants.py +60 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_service.py +228 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluation_utils.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/agent_success_evaluator.py +372 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/delayed_group_evaluator.py +156 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/group_evaluation_runner.py +336 -0
- package/plugin/vendor/reflexio/reflexio/server/services/agent_success_evaluation/regen_jobs.py +471 -0
- package/plugin/vendor/reflexio/reflexio/server/services/base_generation_service.py +1668 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_cron.py +196 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/_encryption.py +101 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/client.py +167 -0
- package/plugin/vendor/reflexio/reflexio/server/services/braintrust/service.py +281 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/base_configurator.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/config_storage.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/configurator.py +87 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/local_file_config_storage.py +187 -0
- package/plugin/vendor/reflexio/reflexio/server/services/configurator/test_config_storage.py +162 -0
- package/plugin/vendor/reflexio/reflexio/server/services/deduplication_utils.py +112 -0
- package/plugin/vendor/reflexio/reflexio/server/services/embedding_text.py +62 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/distribution.py +33 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/eval_sampler.py +126 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/group_aggregation.py +192 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/hero_state.py +75 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/rule_attribution.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/service.py +515 -0
- package/plugin/vendor/reflexio/reflexio/server/services/evaluation_overview/shadow_aggregation.py +90 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/agent_run_records.py +91 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/invariants.py +303 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/outcome.py +25 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/pending_tool_call_dispatch.py +358 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/plan.py +138 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/prior_answer_search.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resumable_agent.py +535 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_scheduler.py +171 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/resume_worker.py +779 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extraction/tools.py +1125 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_config_utils.py +94 -0
- package/plugin/vendor/reflexio/reflexio/server/services/extractor_interaction_utils.py +251 -0
- package/plugin/vendor/reflexio/reflexio/server/services/generation_service.py +702 -0
- package/plugin/vendor/reflexio/reflexio/server/services/operation_state_utils.py +835 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/README.md +89 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_aggregator.py +1388 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_consolidator.py +1045 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_extractor.py +436 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_generation_service.py +808 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_constants.py +28 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook/playbook_service_utils.py +362 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/__init__.py +24 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/assistant_webhook.py +246 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/gepa_adapter.py +291 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/judge.py +97 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/models.py +96 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/optimizer.py +645 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/rollout.py +35 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scenario_resolver.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/playbook_optimizer/scheduler.py +174 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/__init__.py +26 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_document_expander.py +179 -0
- package/plugin/vendor/reflexio/reflexio/server/services/pre_retrieval/_query_reformulator.py +297 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_deduplicator.py +772 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_extractor.py +462 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service.py +737 -0
- package/plugin/vendor/reflexio/reflexio/server/services/profile/profile_generation_service_utils.py +290 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/__init__.py +17 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_extractor.py +247 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service.py +803 -0
- package/plugin/vendor/reflexio/reflexio/server/services/reflection/reflection_service_utils.py +146 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/retrieval/relevance_floor.py +80 -0
- package/plugin/vendor/reflexio/reflexio/server/services/search/__init__.py +0 -0
- package/plugin/vendor/reflexio/reflexio/server/services/service_utils.py +756 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/judge.py +184 -0
- package/plugin/vendor/reflexio/reflexio/server/services/shadow_comparison/outcome.py +81 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/constants.py +2 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/error.py +11 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/retention_mixin.py +155 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/__init__.py +59 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_agent_run.py +1298 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_base.py +1945 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_extras.py +600 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_operations.py +346 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_playbook.py +1378 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_profiles.py +747 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_requests.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_shadow_verdicts.py +193 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_share_links.py +166 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/sqlite_storage/_stall_state.py +217 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/__init__.py +153 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_agent_run.py +384 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_base.py +71 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_extras.py +235 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_operations.py +170 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_playbook.py +677 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_profiles.py +250 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_requests.py +154 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_shadow_verdicts.py +130 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_share_links.py +93 -0
- package/plugin/vendor/reflexio/reflexio/server/services/storage/storage_base/_stall_state.py +76 -0
- package/plugin/vendor/reflexio/reflexio/server/services/unified_search_service.py +572 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/README.md +77 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/feature_flags.py +116 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_manager.py +263 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/feature_flags.json +13 -0
- package/plugin/vendor/reflexio/reflexio/server/site_var/site_var_sources/llm_model_setting.json +7 -0
- package/plugin/vendor/reflexio/reflexio/server/tracing.py +158 -0
- package/plugin/vendor/reflexio/reflexio/server/usage_metrics.py +113 -0
- package/plugin/vendor/reflexio/reflexio/server/uvicorn_logging.py +76 -0
- package/plugin/vendor/reflexio/reflexio/test_support/__init__.py +1 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_fixtures.py +62 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_mock.py +242 -0
- package/plugin/vendor/reflexio/reflexio/test_support/llm_model_registry.py +129 -0
- package/plugin/vendor/reflexio/reflexio/test_support/skip_decorators.py +43 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
// Reflexio Embedded — Openclaw plugin entry.
|
|
2
|
+
//
|
|
3
|
+
// Registers lifecycle hooks against the Openclaw Plugin API:
|
|
4
|
+
// - before_prompt_build: TTL sweep, workspace setup, system prompt injection
|
|
5
|
+
// - before_compaction: run extractor subagent over the session transcript
|
|
6
|
+
// - before_reset: run extractor subagent before the transcript is wiped
|
|
7
|
+
// - session_end: run extractor subagent on session termination
|
|
8
|
+
//
|
|
9
|
+
// The TTL sweep + extractor spawning logic lives in ./hook/handler.ts and is
|
|
10
|
+
// re-used verbatim — this file is only the SDK wiring.
|
|
11
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as os from "node:os";
|
|
14
|
+
import * as path from "node:path";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
injectBootstrapReminder,
|
|
18
|
+
spawnExtractor,
|
|
19
|
+
ttlSweepProfiles,
|
|
20
|
+
} from "./hook/handler.ts";
|
|
21
|
+
import { setupWorkspaceResources } from "./hook/setup.ts";
|
|
22
|
+
import { writeProfile } from "./lib/write-profile.ts";
|
|
23
|
+
import { writePlaybook } from "./lib/write-playbook.ts";
|
|
24
|
+
import { search } from "./lib/search.ts";
|
|
25
|
+
import type { InferFn } from "./lib/openclaw-cli.ts";
|
|
26
|
+
import { runConsolidation } from "./lib/consolidate.ts";
|
|
27
|
+
import {
|
|
28
|
+
prepareSimpleCompletionModelForAgent,
|
|
29
|
+
completeWithPreparedSimpleCompletionModel,
|
|
30
|
+
} from "openclaw/plugin-sdk/agent-runtime";
|
|
31
|
+
|
|
32
|
+
export default definePluginEntry({
|
|
33
|
+
id: "reflexio-embedded",
|
|
34
|
+
name: "Reflexio Embedded",
|
|
35
|
+
description:
|
|
36
|
+
"Reflexio-style user profile and playbook extraction using Openclaw's native memory engine, hooks, and sub-agents.",
|
|
37
|
+
register(api) {
|
|
38
|
+
const log = api.logger;
|
|
39
|
+
const pluginDir = import.meta.dirname || __dirname;
|
|
40
|
+
|
|
41
|
+
// Load agent system prompts from the plugin's own directory
|
|
42
|
+
let extractorSystemPrompt: string | undefined;
|
|
43
|
+
try {
|
|
44
|
+
extractorSystemPrompt = fs.readFileSync(
|
|
45
|
+
path.join(pluginDir, "agents", "reflexio-extractor.md"),
|
|
46
|
+
"utf8",
|
|
47
|
+
);
|
|
48
|
+
} catch {
|
|
49
|
+
log.warn?.("[reflexio-embedded] could not load reflexio-extractor.md agent definition");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// before_prompt_build: workspace setup, TTL sweep, and system-prompt injection.
|
|
53
|
+
api.on("before_prompt_build", async () => {
|
|
54
|
+
try {
|
|
55
|
+
setupWorkspaceResources(pluginDir);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
log.error?.(`[reflexio-embedded] workspace setup failed: ${err}`);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await ttlSweepProfiles(resolveWorkspaceDir());
|
|
61
|
+
} catch (err) {
|
|
62
|
+
log.error?.(`[reflexio-embedded] ttl sweep failed: ${err}`);
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
prependSystemContext: injectBootstrapReminder(),
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// before_compaction: spawn extractor BEFORE the LLM compacts history so we
|
|
70
|
+
// still have the raw transcript to extract from.
|
|
71
|
+
api.on("before_compaction", async (event, ctx) => {
|
|
72
|
+
try {
|
|
73
|
+
await ttlSweepProfiles(ctx.workspaceDir);
|
|
74
|
+
await spawnExtractor({
|
|
75
|
+
runtime: api.runtime,
|
|
76
|
+
workspaceDir: ctx.workspaceDir,
|
|
77
|
+
sessionKey: ctx.sessionKey,
|
|
78
|
+
messages: event.messages,
|
|
79
|
+
sessionFile: event.sessionFile,
|
|
80
|
+
extraSystemPrompt: extractorSystemPrompt,
|
|
81
|
+
log,
|
|
82
|
+
reason: "before_compaction",
|
|
83
|
+
});
|
|
84
|
+
} catch (err) {
|
|
85
|
+
log.error?.(`[reflexio-embedded] before_compaction failed: ${err}`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// before_reset: user ran /reset — flush current transcript to the extractor.
|
|
90
|
+
api.on("before_reset", async (event, ctx) => {
|
|
91
|
+
try {
|
|
92
|
+
await ttlSweepProfiles(ctx.workspaceDir);
|
|
93
|
+
await spawnExtractor({
|
|
94
|
+
runtime: api.runtime,
|
|
95
|
+
workspaceDir: ctx.workspaceDir,
|
|
96
|
+
sessionKey: ctx.sessionKey,
|
|
97
|
+
messages: event.messages,
|
|
98
|
+
sessionFile: event.sessionFile,
|
|
99
|
+
extraSystemPrompt: extractorSystemPrompt,
|
|
100
|
+
log,
|
|
101
|
+
reason: `before_reset:${event.reason ?? "unknown"}`,
|
|
102
|
+
});
|
|
103
|
+
} catch (err) {
|
|
104
|
+
log.error?.(`[reflexio-embedded] before_reset failed: ${err}`);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// session_end: fires when a session terminates for any reason (stop, idle,
|
|
109
|
+
// daily rollover, etc.).
|
|
110
|
+
api.on("session_end", async (event, ctx) => {
|
|
111
|
+
try {
|
|
112
|
+
await ttlSweepProfiles(ctx.workspaceDir);
|
|
113
|
+
await spawnExtractor({
|
|
114
|
+
runtime: api.runtime,
|
|
115
|
+
workspaceDir: ctx.workspaceDir,
|
|
116
|
+
sessionKey: ctx.sessionKey ?? event.sessionKey,
|
|
117
|
+
messages: undefined, // transcript lives on disk at this point
|
|
118
|
+
sessionFile: event.sessionFile,
|
|
119
|
+
extraSystemPrompt: extractorSystemPrompt,
|
|
120
|
+
log,
|
|
121
|
+
reason: `session_end:${event.reason ?? "unknown"}`,
|
|
122
|
+
});
|
|
123
|
+
} catch (err) {
|
|
124
|
+
log.error?.(`[reflexio-embedded] session_end failed: ${err}`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ──────────────────────────────────────────────────────────
|
|
129
|
+
// Agent tools — deterministic control flow for writes + search
|
|
130
|
+
// ──────────────────────────────────────────────────────────
|
|
131
|
+
const runner = api.runtime.system.runCommandWithTimeout;
|
|
132
|
+
|
|
133
|
+
// In-process LLM inference via SDK simple completion API.
|
|
134
|
+
// Bypasses sessions, lanes, and CLI — no lock contention.
|
|
135
|
+
const inferFn: InferFn = async (prompt) => {
|
|
136
|
+
try {
|
|
137
|
+
const cfg = api.runtime.config.loadConfig();
|
|
138
|
+
const prepared = await prepareSimpleCompletionModelForAgent({
|
|
139
|
+
cfg,
|
|
140
|
+
agentId: "main",
|
|
141
|
+
});
|
|
142
|
+
if ("error" in prepared) {
|
|
143
|
+
console.error(`[reflexio] inferFn: model preparation failed: ${prepared.error}`);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const result = await completeWithPreparedSimpleCompletionModel({
|
|
147
|
+
model: prepared.model,
|
|
148
|
+
auth: prepared.auth,
|
|
149
|
+
context: {
|
|
150
|
+
systemPrompt: "You are a concise assistant. Respond with only what is asked, no preamble.",
|
|
151
|
+
messages: [{ role: "user" as const, content: [{ type: "text" as const, text: prompt }], timestamp: Date.now() }],
|
|
152
|
+
},
|
|
153
|
+
options: { maxTokens: 800 },
|
|
154
|
+
});
|
|
155
|
+
const text = result.content
|
|
156
|
+
.filter((c: { type: string }) => c.type === "text")
|
|
157
|
+
.map((c: { type: string; text?: string }) => c.text ?? "")
|
|
158
|
+
.join("");
|
|
159
|
+
console.info(`[reflexio] inferFn: success, responseLen=${text.length}`);
|
|
160
|
+
return text.trim() || null;
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.error(`[reflexio] inferFn: failed: ${err}`);
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const config = api.pluginConfig ?? {
|
|
168
|
+
dedup: { shallow_threshold: 0.4, top_k: 5 },
|
|
169
|
+
consolidation: { threshold_hours: 24 },
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Resolve the agent's workspace directory.
|
|
174
|
+
* Mirrors Openclaw's resolveDefaultAgentWorkspaceDir logic:
|
|
175
|
+
* ~/.openclaw/workspace (default)
|
|
176
|
+
* ~/.openclaw/workspace-{profile} (if OPENCLAW_PROFILE is set)
|
|
177
|
+
*/
|
|
178
|
+
function resolveWorkspaceDir(): string {
|
|
179
|
+
const profile = process.env.OPENCLAW_PROFILE?.trim();
|
|
180
|
+
if (profile && profile.toLowerCase() !== "default") {
|
|
181
|
+
return path.join(os.homedir(), ".openclaw", `workspace-${profile}`);
|
|
182
|
+
}
|
|
183
|
+
return path.join(os.homedir(), ".openclaw", "workspace");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
api.registerTool({
|
|
187
|
+
name: "reflexio_write_profile",
|
|
188
|
+
description:
|
|
189
|
+
"Write a user profile to .reflexio/profiles/ with automatic query preprocessing, memory search, contradiction detection, dedup, and old-file cleanup. Returns the new file path.",
|
|
190
|
+
parameters: {
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: {
|
|
193
|
+
slug: { type: "string", description: "kebab-case topic, e.g. diet-vegan" },
|
|
194
|
+
ttl: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "one_day | one_week | one_month | one_quarter | one_year | infinity",
|
|
197
|
+
},
|
|
198
|
+
body: { type: "string", description: "1-3 sentences, one fact per profile" },
|
|
199
|
+
},
|
|
200
|
+
required: ["slug", "ttl", "body"],
|
|
201
|
+
},
|
|
202
|
+
optional: true,
|
|
203
|
+
async execute(_id: string, params: { slug: string; ttl: string; body: string }) {
|
|
204
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
205
|
+
const filePath = await writeProfile({
|
|
206
|
+
slug: params.slug,
|
|
207
|
+
ttl: params.ttl,
|
|
208
|
+
body: params.body,
|
|
209
|
+
workspace: workspaceDir,
|
|
210
|
+
config: config.dedup,
|
|
211
|
+
runner,
|
|
212
|
+
inferFn,
|
|
213
|
+
});
|
|
214
|
+
return { content: [{ type: "text" as const, text: filePath }] };
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
api.registerTool({
|
|
219
|
+
name: "reflexio_write_playbook",
|
|
220
|
+
description:
|
|
221
|
+
"Write a playbook to .reflexio/playbooks/ with automatic dedup and contradiction detection. Returns the new file path.",
|
|
222
|
+
parameters: {
|
|
223
|
+
type: "object",
|
|
224
|
+
properties: {
|
|
225
|
+
slug: { type: "string", description: "kebab-case trigger summary, e.g. commit-no-trailers" },
|
|
226
|
+
body: {
|
|
227
|
+
type: "string",
|
|
228
|
+
description: "Playbook body with ## When, ## What, ## Why sections",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
required: ["slug", "body"],
|
|
232
|
+
},
|
|
233
|
+
optional: true,
|
|
234
|
+
async execute(_id: string, params: { slug: string; body: string }) {
|
|
235
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
236
|
+
const filePath = await writePlaybook({
|
|
237
|
+
slug: params.slug,
|
|
238
|
+
body: params.body,
|
|
239
|
+
workspace: workspaceDir,
|
|
240
|
+
config: config.dedup,
|
|
241
|
+
runner,
|
|
242
|
+
inferFn,
|
|
243
|
+
});
|
|
244
|
+
return { content: [{ type: "text" as const, text: filePath }] };
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
api.registerTool({
|
|
249
|
+
name: "reflexio_search",
|
|
250
|
+
description:
|
|
251
|
+
"Search .reflexio/ memory with automatic query preprocessing for better results. Returns JSON with results array.",
|
|
252
|
+
parameters: {
|
|
253
|
+
type: "object",
|
|
254
|
+
properties: {
|
|
255
|
+
query: { type: "string", description: "raw query — preprocessing is automatic" },
|
|
256
|
+
},
|
|
257
|
+
required: ["query"],
|
|
258
|
+
},
|
|
259
|
+
async execute(_id: string, params: { query: string }) {
|
|
260
|
+
const results = await search(params.query, 5, undefined, runner, inferFn);
|
|
261
|
+
return {
|
|
262
|
+
content: [{ type: "text" as const, text: JSON.stringify({ results }, null, 2) }],
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// ──────────────────────────────────────────────────────────
|
|
268
|
+
// Consolidation + Heartbeat
|
|
269
|
+
// ──────────────────────────────────────────────────────────
|
|
270
|
+
let consolidationRunning = false;
|
|
271
|
+
|
|
272
|
+
function getConsolidationStateFile(): string {
|
|
273
|
+
return path.join(resolveWorkspaceDir(), ".reflexio", "consolidation-state.json");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
api.registerTool({
|
|
277
|
+
name: "reflexio_run_consolidation",
|
|
278
|
+
description:
|
|
279
|
+
"Run a full consolidation sweep: TTL sweep, cluster similar files, LLM-judge each cluster, write deduplicated facts, delete originals, reindex memory. Returns a summary.",
|
|
280
|
+
parameters: { type: "object", properties: {} },
|
|
281
|
+
optional: true,
|
|
282
|
+
async execute() {
|
|
283
|
+
if (consolidationRunning) {
|
|
284
|
+
return { content: [{ type: "text" as const, text: "Consolidation already running." }] };
|
|
285
|
+
}
|
|
286
|
+
consolidationRunning = true;
|
|
287
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
288
|
+
const stateFile = getConsolidationStateFile();
|
|
289
|
+
// Fire and forget — don't block the agent's turn
|
|
290
|
+
runConsolidation({ workspaceDir, runner, inferFn }).then((result) => {
|
|
291
|
+
const state = { last_consolidation: new Date().toISOString() };
|
|
292
|
+
fs.mkdirSync(path.dirname(stateFile), { recursive: true });
|
|
293
|
+
fs.writeFileSync(stateFile, JSON.stringify(state, null, 2), "utf8");
|
|
294
|
+
console.info(`[reflexio] consolidation: background complete. wrote=${result.filesWritten} deleted=${result.filesDeleted}`);
|
|
295
|
+
}).catch((err) => {
|
|
296
|
+
console.error(`[reflexio] consolidation: background failed: ${err}`);
|
|
297
|
+
}).finally(() => {
|
|
298
|
+
consolidationRunning = false;
|
|
299
|
+
});
|
|
300
|
+
return { content: [{ type: "text" as const, text: "Consolidation started in background." }] };
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
api.registerTool({
|
|
305
|
+
name: "reflexio_consolidation_check",
|
|
306
|
+
description:
|
|
307
|
+
"Check if reflexio consolidation is due. Returns OK or ALERT. Called by the agent on heartbeat.",
|
|
308
|
+
parameters: { type: "object", properties: {} },
|
|
309
|
+
async execute() {
|
|
310
|
+
const thresholdHours = config.consolidation?.threshold_hours ?? 24;
|
|
311
|
+
try {
|
|
312
|
+
const state = JSON.parse(fs.readFileSync(getConsolidationStateFile(), "utf8"));
|
|
313
|
+
const elapsedMs = Date.now() - new Date(state.last_consolidation).getTime();
|
|
314
|
+
const elapsedHours = elapsedMs / 3_600_000;
|
|
315
|
+
if (elapsedHours < thresholdHours) {
|
|
316
|
+
const remaining = Math.round(thresholdHours - elapsedHours);
|
|
317
|
+
return { content: [{ type: "text" as const, text: `OK: Last consolidation ${Math.round(elapsedHours)}h ago. Next due in ${remaining}h.` }] };
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
// no state file = never consolidated
|
|
321
|
+
}
|
|
322
|
+
return { content: [{ type: "text" as const, text: "ALERT: Consolidation due." }] };
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
},
|
|
327
|
+
});
|
package/plugin/vendor/reflexio/reflexio/integrations/openclaw-embedded/plugin/lib/consolidate.ts
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
import { writeProfileFile, writePlaybookFile, deleteFile, type Ttl } from "./io.ts";
|
|
5
|
+
import { memorySearch, reindexMemory, type CommandRunner, type InferFn } from "./openclaw-cli.ts";
|
|
6
|
+
import { ttlSweepProfiles } from "../hook/handler.ts";
|
|
7
|
+
|
|
8
|
+
export interface ConsolidationResult {
|
|
9
|
+
profilesClustered: number;
|
|
10
|
+
playbooksClustered: number;
|
|
11
|
+
filesWritten: number;
|
|
12
|
+
filesDeleted: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface FileEntry {
|
|
16
|
+
id: string;
|
|
17
|
+
path: string;
|
|
18
|
+
content: string;
|
|
19
|
+
ttl?: string;
|
|
20
|
+
created?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ConsolidationFact {
|
|
24
|
+
slug: string;
|
|
25
|
+
body: string;
|
|
26
|
+
source_ids: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface LlmConsolidationResult {
|
|
30
|
+
action: "keep_all" | "consolidate";
|
|
31
|
+
facts?: ConsolidationFact[];
|
|
32
|
+
ids_to_delete?: string[];
|
|
33
|
+
rationale?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CONSOLIDATION_PROMPT = `You consolidate a cluster of similar items (profiles or playbooks).
|
|
37
|
+
|
|
38
|
+
**One fact per file.** Each output entry must contain exactly ONE atomic fact (1-2 sentences). Do NOT combine unrelated facts.
|
|
39
|
+
|
|
40
|
+
Decisions:
|
|
41
|
+
- "keep_all" — items are already distinct, no redundancy.
|
|
42
|
+
- "consolidate" — deduplicate, resolve contradictions (most recent wins), split into individual facts.
|
|
43
|
+
|
|
44
|
+
Answer with ONLY a JSON object:
|
|
45
|
+
{"action": "keep_all"} or {"action": "consolidate", "facts": [{"slug": "kebab-case", "body": "single fact"}], "ids_to_delete": ["id1", "id2"], "rationale": "why"}
|
|
46
|
+
|
|
47
|
+
Cluster:
|
|
48
|
+
{cluster}`;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Load all .md files from a .reflexio subdirectory, extracting frontmatter fields.
|
|
52
|
+
*/
|
|
53
|
+
function loadFiles(dir: string): FileEntry[] {
|
|
54
|
+
if (!fs.existsSync(dir)) return [];
|
|
55
|
+
const entries: FileEntry[] = [];
|
|
56
|
+
for (const name of fs.readdirSync(dir)) {
|
|
57
|
+
if (!name.endsWith(".md")) continue;
|
|
58
|
+
const full = path.join(dir, name);
|
|
59
|
+
let raw: string;
|
|
60
|
+
try {
|
|
61
|
+
raw = fs.readFileSync(full, "utf8");
|
|
62
|
+
} catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const idMatch = /^id:\s*(\S+)/m.exec(raw);
|
|
66
|
+
const ttlMatch = /^ttl:\s*(\S+)/m.exec(raw);
|
|
67
|
+
const createdMatch = /^created:\s*(\S+)/m.exec(raw);
|
|
68
|
+
const body = raw.split("---").slice(2).join("---").trim();
|
|
69
|
+
if (!idMatch || !body) continue;
|
|
70
|
+
entries.push({
|
|
71
|
+
id: idMatch[1],
|
|
72
|
+
path: full,
|
|
73
|
+
content: body,
|
|
74
|
+
ttl: ttlMatch?.[1],
|
|
75
|
+
created: createdMatch?.[1],
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return entries;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Cluster files by similarity using memory search.
|
|
83
|
+
* Returns groups of 2+ related files. Each file appears in at most one cluster.
|
|
84
|
+
*/
|
|
85
|
+
async function clusterFiles(
|
|
86
|
+
files: FileEntry[],
|
|
87
|
+
type: "profile" | "playbook",
|
|
88
|
+
workspaceDir: string,
|
|
89
|
+
runner: CommandRunner
|
|
90
|
+
): Promise<FileEntry[][]> {
|
|
91
|
+
const visited = new Set<string>();
|
|
92
|
+
const clusters: FileEntry[][] = [];
|
|
93
|
+
|
|
94
|
+
for (const file of files) {
|
|
95
|
+
if (visited.has(file.id)) continue;
|
|
96
|
+
visited.add(file.id);
|
|
97
|
+
|
|
98
|
+
const results = await memorySearch(file.content, 10, runner);
|
|
99
|
+
console.info(`[reflexio] clustering: file=${file.id} searchResults=${results.length} paths=[${results.map((r) => r.path).join(", ")}]`);
|
|
100
|
+
const typeDir = type === "profile" ? "/profiles/" : "/playbooks/";
|
|
101
|
+
const neighbors = results
|
|
102
|
+
.filter((r) => r.path.includes(typeDir))
|
|
103
|
+
.map((r) => {
|
|
104
|
+
// Match by path — memory search returns relative paths, loaded files have absolute
|
|
105
|
+
const absPath = r.path.startsWith("/") ? r.path : path.join(workspaceDir, r.path);
|
|
106
|
+
const match = files.find((f) => f.path === absPath);
|
|
107
|
+
if (!match) console.info(`[reflexio] clustering: no file match for path=${r.path} absPath=${absPath}`);
|
|
108
|
+
return match;
|
|
109
|
+
})
|
|
110
|
+
.filter((f): f is FileEntry => f !== undefined && f.id !== file.id && !visited.has(f.id));
|
|
111
|
+
console.info(`[reflexio] clustering: file=${file.id} neighbors=${neighbors.length} neighborIds=[${neighbors.map((n) => n.id).join(", ")}]`);
|
|
112
|
+
|
|
113
|
+
if (neighbors.length === 0) continue;
|
|
114
|
+
|
|
115
|
+
const cluster = [file, ...neighbors.slice(0, 9)];
|
|
116
|
+
for (const member of cluster) visited.add(member.id);
|
|
117
|
+
clusters.push(cluster);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return clusters;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Format cluster items for the LLM prompt.
|
|
125
|
+
*/
|
|
126
|
+
function formatCluster(cluster: FileEntry[]): string {
|
|
127
|
+
return cluster
|
|
128
|
+
.map((f) => `- id: ${f.id}\n created: ${f.created ?? "unknown"}\n content: ${f.content}`)
|
|
129
|
+
.join("\n\n");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Pick the most conservative TTL from a cluster of profiles.
|
|
134
|
+
*/
|
|
135
|
+
function pickSmallestTtl(cluster: FileEntry[]): Ttl {
|
|
136
|
+
const order: Ttl[] = ["one_day", "one_week", "one_month", "one_quarter", "one_year", "infinity"];
|
|
137
|
+
let smallest = order.length - 1;
|
|
138
|
+
for (const file of cluster) {
|
|
139
|
+
const idx = order.indexOf(file.ttl as Ttl);
|
|
140
|
+
if (idx >= 0 && idx < smallest) smallest = idx;
|
|
141
|
+
}
|
|
142
|
+
return order[smallest];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Run a full consolidation sweep: TTL sweep → cluster → LLM judge → write/delete.
|
|
147
|
+
* Uses inferFn (SDK simple completion) for LLM — bypasses lanes entirely.
|
|
148
|
+
*/
|
|
149
|
+
export async function runConsolidation(opts: {
|
|
150
|
+
workspaceDir: string;
|
|
151
|
+
runner: CommandRunner;
|
|
152
|
+
inferFn: InferFn;
|
|
153
|
+
}): Promise<ConsolidationResult> {
|
|
154
|
+
const result: ConsolidationResult = { profilesClustered: 0, playbooksClustered: 0, filesWritten: 0, filesDeleted: 0 };
|
|
155
|
+
console.info(`[reflexio] consolidation: starting, workspace=${opts.workspaceDir}`);
|
|
156
|
+
|
|
157
|
+
// 1. TTL sweep
|
|
158
|
+
await ttlSweepProfiles(opts.workspaceDir);
|
|
159
|
+
console.info(`[reflexio] consolidation: TTL sweep done`);
|
|
160
|
+
|
|
161
|
+
// 2. Process profiles, then playbooks
|
|
162
|
+
for (const type of ["profile", "playbook"] as const) {
|
|
163
|
+
const dir = path.join(opts.workspaceDir, ".reflexio", type === "profile" ? "profiles" : "playbooks");
|
|
164
|
+
const files = loadFiles(dir);
|
|
165
|
+
console.info(`[reflexio] consolidation: loaded ${files.length} ${type} files`);
|
|
166
|
+
if (files.length < 2) continue;
|
|
167
|
+
|
|
168
|
+
const clusters = await clusterFiles(files, type, opts.workspaceDir, opts.runner);
|
|
169
|
+
console.info(`[reflexio] consolidation: found ${clusters.length} ${type} cluster(s) with >1 member`);
|
|
170
|
+
|
|
171
|
+
for (const cluster of clusters) {
|
|
172
|
+
console.info(`[reflexio] consolidation: processing ${type} cluster of ${cluster.length} items: ${cluster.map((f) => f.id).join(", ")}`);
|
|
173
|
+
|
|
174
|
+
const prompt = CONSOLIDATION_PROMPT.replace("{cluster}", formatCluster(cluster));
|
|
175
|
+
const llmResult = await opts.inferFn(prompt);
|
|
176
|
+
|
|
177
|
+
if (!llmResult) {
|
|
178
|
+
console.error(`[reflexio] consolidation: inferFn returned empty for cluster, skipping`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
let decision: LlmConsolidationResult;
|
|
183
|
+
try {
|
|
184
|
+
decision = JSON.parse(llmResult);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error(`[reflexio] consolidation: JSON parse failed: ${err}, skipping cluster`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
console.info(`[reflexio] consolidation: decision="${decision.action}" rationale="${(decision.rationale ?? "").slice(0, 100)}"`);
|
|
191
|
+
|
|
192
|
+
if (decision.action === "keep_all") continue;
|
|
193
|
+
|
|
194
|
+
if (decision.action === "consolidate" && decision.facts && decision.ids_to_delete) {
|
|
195
|
+
// Build id→file lookup for deletion
|
|
196
|
+
const idToFile = new Map(cluster.map((f) => [f.id, f]));
|
|
197
|
+
|
|
198
|
+
// Write new fact files
|
|
199
|
+
for (const fact of decision.facts) {
|
|
200
|
+
if (type === "profile") {
|
|
201
|
+
const sourceFiles = (fact.source_ids ?? []).map((id) => idToFile.get(id)).filter((f): f is FileEntry => f !== undefined);
|
|
202
|
+
const ttl = sourceFiles.length > 0 ? pickSmallestTtl(sourceFiles) : pickSmallestTtl(cluster);
|
|
203
|
+
const supersedes = fact.source_ids?.filter((id) => idToFile.has(id));
|
|
204
|
+
writeProfileFile({ slug: fact.slug, ttl, body: fact.body, supersedes, workspace: opts.workspaceDir });
|
|
205
|
+
result.filesWritten++;
|
|
206
|
+
} else {
|
|
207
|
+
const supersedes = fact.source_ids?.filter((id) => idToFile.has(id));
|
|
208
|
+
writePlaybookFile({ slug: fact.slug, body: fact.body, supersedes, workspace: opts.workspaceDir });
|
|
209
|
+
result.filesWritten++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Delete old files
|
|
214
|
+
for (const id of decision.ids_to_delete) {
|
|
215
|
+
const file = idToFile.get(id);
|
|
216
|
+
if (file) {
|
|
217
|
+
deleteFile(file.path);
|
|
218
|
+
result.filesDeleted++;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (type === "profile") result.profilesClustered += cluster.length;
|
|
223
|
+
else result.playbooksClustered += cluster.length;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 3. Reindex memory
|
|
229
|
+
await reindexMemory(opts.runner);
|
|
230
|
+
console.info(`[reflexio] consolidation: complete. wrote=${result.filesWritten} deleted=${result.filesDeleted}`);
|
|
231
|
+
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { InferFn } from "./openclaw-cli.ts";
|
|
2
|
+
|
|
3
|
+
const PREPROCESS_PROMPT = `Rewrite the following text into a single descriptive but concise sentence that captures the core facts or topics. Expand with 2-3 important synonyms or related terms to improve search matching. Remove conversational filler. Return ONLY the rewritten text.
|
|
4
|
+
|
|
5
|
+
Text: "{rawText}"`;
|
|
6
|
+
|
|
7
|
+
const DEDUP_PROMPT = `EXISTING: "{existingContent}"
|
|
8
|
+
NEW: "{newContent}"
|
|
9
|
+
|
|
10
|
+
Compare these two entries:
|
|
11
|
+
- If they are about different topics with no overlap, answer "keep_both".
|
|
12
|
+
- Otherwise, merge them: resolve contradictions (NEW wins over EXISTING), deduplicate redundant statements, preserve all non-contradicted facts from both. Return the merged result as 1-3 concise sentences.
|
|
13
|
+
|
|
14
|
+
Answer with ONLY a JSON object:
|
|
15
|
+
{"decision": "keep_both"} or {"decision": "merge_and_resolve", "resolved": "<merged, deduped, resolved body>"}`;
|
|
16
|
+
|
|
17
|
+
export type DedupResult =
|
|
18
|
+
| { decision: "keep_both" }
|
|
19
|
+
| { decision: "merge_and_resolve"; resolved: string };
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Rewrite raw text into a clean search query optimized for vector + FTS search.
|
|
23
|
+
* Falls back to raw text if openclaw infer is unavailable.
|
|
24
|
+
*/
|
|
25
|
+
export async function preprocessQuery(rawText: string, inferFn: InferFn): Promise<string> {
|
|
26
|
+
console.info(`[reflexio] preprocessQuery: inputLen=${rawText.length} input="${rawText.slice(0, 100)}"`);
|
|
27
|
+
const prompt = PREPROCESS_PROMPT.replace("{rawText}", rawText);
|
|
28
|
+
const result = await inferFn(prompt);
|
|
29
|
+
if (!result || result.trim().length === 0) {
|
|
30
|
+
console.info(`[reflexio] preprocessQuery: infer returned empty, falling back to raw text`);
|
|
31
|
+
return rawText;
|
|
32
|
+
}
|
|
33
|
+
console.info(`[reflexio] preprocessQuery: rewritten="${result.trim().slice(0, 120)}"`);
|
|
34
|
+
return result.trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Ask LLM to compare new content against existing content.
|
|
39
|
+
* Returns keep_both (different topics) or merge_and_resolve (with resolved body).
|
|
40
|
+
* Defaults to keep_both on any failure.
|
|
41
|
+
*/
|
|
42
|
+
export async function judgeDedup(
|
|
43
|
+
newContent: string,
|
|
44
|
+
existingContent: string,
|
|
45
|
+
inferFn: InferFn
|
|
46
|
+
): Promise<DedupResult> {
|
|
47
|
+
console.info(`[reflexio] judgeDedup: existingLen=${existingContent.length} newLen=${newContent.length}`);
|
|
48
|
+
console.info(`[reflexio] judgeDedup: existing="${existingContent.slice(0, 100)}" new="${newContent.slice(0, 100)}"`);
|
|
49
|
+
const prompt = DEDUP_PROMPT
|
|
50
|
+
.replace("{existingContent}", existingContent)
|
|
51
|
+
.replace("{newContent}", newContent);
|
|
52
|
+
|
|
53
|
+
const result = await inferFn(prompt);
|
|
54
|
+
if (!result) {
|
|
55
|
+
console.info(`[reflexio] judgeDedup: infer returned empty, defaulting to keep_both`);
|
|
56
|
+
return { decision: "keep_both" };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.info(`[reflexio] judgeDedup: raw result="${result.slice(0, 200)}"`);
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(result);
|
|
62
|
+
if (parsed.decision === "merge_and_resolve" && typeof parsed.resolved === "string" && parsed.resolved.trim()) {
|
|
63
|
+
console.info(`[reflexio] judgeDedup: decision="merge_and_resolve" resolvedLen=${parsed.resolved.length}`);
|
|
64
|
+
return { decision: "merge_and_resolve", resolved: parsed.resolved.trim() };
|
|
65
|
+
}
|
|
66
|
+
console.info(`[reflexio] judgeDedup: decision="keep_both"`);
|
|
67
|
+
return { decision: "keep_both" };
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(`[reflexio] judgeDedup: JSON parse failed: ${err}, defaulting to keep_both`);
|
|
70
|
+
return { decision: "keep_both" };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Extract the `id:` value from a memory search snippet containing YAML frontmatter.
|
|
76
|
+
*/
|
|
77
|
+
export function extractId(snippet: string): string | null {
|
|
78
|
+
const match = /^id:\s*(\S+)/m.exec(snippet);
|
|
79
|
+
return match ? match[1] : null;
|
|
80
|
+
}
|