From 949abe6c5cad3c79bb2e86fca32dfd3ba193055f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=94=AF=20A06?= Date: Tue, 1 Sep 2026 19:07:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(skills):=20=E9=85=8D=E7=BD=AE=20holographi?= =?UTF-8?q?c=20memory=20plugin=20+=20=E6=B5=8B=E8=AF=95=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - config.yaml 启用 holographic plugin - plugins.hermes-memory-store 节(独立 db,不接管 zhiyi) - 备份 config.yaml.bak-pre-holographic - scripts/test_holographic.py 9 actions + feedback 测试通过 Holographic 是 v0.21.0 新增的本地 SQLite memory provider 作为织忆的极简备用方案(trust scoring + HRR + FTS5) --- config.yaml | 11 +- config.yaml.bak-pre-holographic | 737 ++++++++++++++++++++++++++++++++ scripts/test_holographic.py | 71 +++ 3 files changed, 818 insertions(+), 1 deletion(-) create mode 100644 config.yaml.bak-pre-holographic create mode 100644 scripts/test_holographic.py diff --git a/config.yaml b/config.yaml index 97cd0f36..f0beb1e2 100644 --- a/config.yaml +++ b/config.yaml @@ -192,7 +192,7 @@ cron: gateway_required: true model: glm-4-flash model_provider: zhipu - provider: auto + provider: '' wrap_response: true curator: archive_after_days: 90 @@ -459,6 +459,15 @@ plugins: - agentic-sms-gateway - cronalytics - rtk-rewrite + - holographic + hermes-memory-store: + db_path: /home/muc/.hermes/memory_store.db + auto_extract: false + default_trust: 0.5 + min_trust_threshold: 0.3 + temporal_decay_half_life: 0 + hrr_dim: 1024 + enabled: true prefill_messages_file: '' privacy: redact_pii: false diff --git a/config.yaml.bak-pre-holographic b/config.yaml.bak-pre-holographic new file mode 100644 index 00000000..0608e60c --- /dev/null +++ b/config.yaml.bak-pre-holographic @@ -0,0 +1,737 @@ +_config_version: 33 +agent: + api_max_retries: 2 + clarify_timeout: 600 + disabled_toolsets: [] + environment_hint: '' + environment_probe: true + gateway_auto_continue_freshness: 3600 + gateway_notify_interval: 180 + gateway_timeout: 1800 + gateway_timeout_warning: 900 + image_input_mode: auto + max_turns: 90 + restart_drain_timeout: 180 + service_tier: '' + task_completion_guidance: true + tool_use_enforcement: auto + verify_on_stop: false +approvals: + cron_mode: deny + destructive_slash_confirm: false + mcp_reload_confirm: true + mode: manual + timeout: 60 +auxiliary: + approval: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 30 + compression: + api_key: 0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP + base_url: http://127.0.0.1:3000/v1 + model: nvidia/nemotron-3-super-120b-a12b + provider: newapi-local + timeout: 120 + curator: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 600 + kanban_decomposer: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 180 + mcp: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 30 + profile_describer: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 60 + session_search: + api_key: '' + base_url: '' + extra_body: {} + max_concurrency: 3 + model: '' + provider: auto + timeout: 30 + skills_hub: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 30 + title_generation: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 30 + triage_specifier: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 120 + vision: + api_key: 0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP + base_url: http://127.0.0.1:3000/v1 + download_timeout: 30 + model: meta/llama-3.2-11b-vision-instruct + provider: newapi-local + timeout: 120 + web_extract: + api_key: '' + base_url: '' + model: '' + provider: auto + timeout: 360 +bedrock: + discovery: + enabled: true + provider_filter: [] + refresh_interval: 3600 + guardrail: + guardrail_identifier: '' + guardrail_version: '' + stream_processing_mode: async + trace: disabled + region: '' +browser: + allow_private_urls: false + auto_local_for_private_urls: true + camofox: + adopt_existing_tab: false + loopback_host_alias: host.docker.internal + managed_persistence: false + rewrite_loopback_urls: false + session_key: '' + user_id: '' + cdp_url: '' + cloud_provider: local + command_timeout: 30 + dialog_policy: must_respond + dialog_timeout_s: 300 + engine: auto + inactivity_timeout: 120 + record_sessions: false + use_gateway: false +checkpoints: + auto_prune: false + delete_orphans: true + enabled: true + max_file_size_mb: 10 + max_snapshots: 50 + max_total_size_mb: 500 + min_interval_hours: 24 + retention_days: 7 +code_execution: + mode: project +command_allowlist: +- script execution via heredoc +- shell command via -c/-lc flag +- delete in root path +- overwrite system file via tee +- stop/restart system service +- pipe remote content to shell +- sudo with combined-flag privilege escalation +- kill process via pgrep expansion (self-termination) +- execute_code +- overwrite system file via redirection +- copy/move file into /etc/ +- kill hermes/gateway process (self-termination) +- overwrite system config +- overwrite project env/config via redirection +- in-place edit of system config +- stop/restart hermes gateway (kills running agents) +- shell execution via heredoc +- copy/move file into sensitive credential/SSH/shell-rc path +- force kill processes (killall -KILL) +- find -delete +- in-place edit of Hermes config/env +- overwrite project env/config file +- script execution via -e/-c flag +- start gateway outside systemd (use 'systemctl --user restart hermes-gateway') +- git force push (rewrites remote history) +- disk copy +- hermes update (restarts gateway, kills running agents) +- recursive delete +- command parser limit or malformed executable payload +- SQL TRUNCATE +- copy/move file into system config path +- sudo with privilege flag (stdin/askpass/shell/list) +- world/other-writable permissions +- force kill processes +- git force push short flag (rewrites remote history) +compression: + abort_on_summary_failure: false + enabled: true + hygiene_hard_message_limit: 400 + protect_first_n: 3 + protect_last_n: 20 + target_ratio: 0.2 + threshold: 0.5 +context: + engine: compressor +cron: + default_deliver: origin,feishu:oc_81f6df701c872a1122f32080e366543f + fallback_model: agnes-2.0-flash + fallback_provider: agnes + gateway_required: true + model: glm-4-flash + model_provider: zhipu + provider: '' + wrap_response: true +curator: + archive_after_days: 90 + backup: + enabled: true + keep: 5 + enabled: true + interval_hours: 168 + min_idle_hours: 2 + stale_after_days: 30 +dashboard: + oauth: + client_id: '' + portal_url: '' + public_url: '' + show_token_analytics: false + theme: default +delegation: + api_key: '' + api_mode: '' + base_url: '' + child_timeout_seconds: 600 + inherit_mcp_toolsets: true + max_concurrent_children: 3 + max_iterations: 50 + max_spawn_depth: 1 + model: nvidia/nemotron-3-super-120b-a12b + orchestrator_enabled: true + provider: newapi-local + reasoning_effort: '' + subagent_auto_approve: false +discord: + allow_any_attachment: false + allowed_channels: '' + auto_thread: true + dm_role_auth_guild: '' + free_response_channels: '' + history_backfill: true + history_backfill_limit: 50 + max_attachment_bytes: 33554432 + reactions: true + require_mention: true + server_actions: '' + thread_require_mention: false +display: + bell_on_complete: false + busy_input_mode: interrupt + compact: false + copy_shortcut: auto + ephemeral_system_ttl: 0 + file_mutation_verifier: true + final_response_markdown: strip + inline_diffs: true + interim_assistant_messages: true + language: en + persistent_output: true + persistent_output_max_lines: 200 + personality: kawaii + resume_display: full + resume_exchanges: 10 + resume_max_assistant_chars: 200 + resume_max_assistant_lines: 3 + resume_max_user_chars: 300 + resume_skip_tool_only: true + runtime_footer: + fields: + - model + - context_pct + - cwd + show_cost: false + show_reasoning: false + skin: default + streaming: false + timestamps: false + tool_preview_length: 0 + tool_progress: all + tool_progress_command: false + tool_progress_style: accumulate + tui_auto_resume_recent: false + tui_status_indicator: kaomoji + user_message_preview: + first_lines: 2 + last_lines: 2 +fallback_providers: +- provider: agnes + model: agnes-2.0-flash +- provider: zhipu + model: glm-4-flash +- provider: sensenova + model: deepseek-v4-flash +- provider: opencode-free + model: x-preview-f-free +file_read_max_chars: 100000 +gateway: + media_delivery_allow_dirs: [] + multiplex_profiles: false + strict: false + trust_recent_files: true + trust_recent_files_seconds: 600 +goals: + max_turns: 20 +hooks_auto_accept: false +human_delay: + max_ms: 2500 + min_ms: 800 + mode: 'off' +kanban: + auto_decompose: true + auto_decompose_per_tick: 3 + default_assignee: '' + dispatch_in_gateway: true + dispatch_interval_seconds: 60 + dispatch_stale_timeout_seconds: 14400 + failure_limit: 2 + orchestrator_profile: '' + worker_log_backup_count: 1 + worker_log_rotate_bytes: 2097152 +known_plugin_toolsets: + cli: + - spotify +logging: + backup_count: 3 + level: INFO + max_size_mb: 5 + memory_monitor: + enabled: true + interval_seconds: 300 +lsp: + enabled: true + install_strategy: auto + wait_mode: document + wait_timeout: 5.0 +matrix: + allowed_rooms: '' + free_response_rooms: '' + require_mention: true +mattermost: + allowed_channels: '' + free_response_channels: '' + require_mention: true +mcp_servers: + codebase-memory-mcp: + command: /home/muc/.local/bin/codebase-memory-mcp + enabled: true + codegraph: + args: + - serve + - --mcp + command: codegraph + connect_timeout: 60 + enabled: true + timeout: 120 + dbx: + args: + - -y + - '@dbx-app/mcp-server' + command: npx + connect_timeout: 60 + enabled: true + timeout: 120 + firecrawl: + connect_timeout: 30 + timeout: 120 + url: https://mcp.firecrawl.dev/v2/mcp + github: + args: + - -y + - '@modelcontextprotocol/server-github' + command: npx + enabled: true + env: + GITHUB_PERSONAL_ACCESS_TOKEN: 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 + timeout: 60 + openclaw: + args: + - mcp + - serve + command: openclaw + connect_timeout: 60 + timeout: 300 +memory: + memory_char_limit: 2200 + memory_enabled: true + provider: zhiyi + user_char_limit: 1375 + user_profile_enabled: true +moa: + default_preset: expert-panel + presets: + expert-panel: + aggregator: + model: openai/gpt-oss-120b + provider: newapi-local + enabled: true + fanout: user_turn + reference_max_tokens: 800 + reference_models: + - model: openai/gpt-oss-120b + provider: newapi-local + - model: nvidia/llama-3.3-nemotron-super-49b-v1 + provider: newapi-local + - model: mistralai/mistral-large-3-675b-instruct-2512 + provider: newapi-local + save_traces: false +model: + api_key_env: '' + base_url: '' + default: MiniMaxAI/MiniMax-M3 + provider: gmi-cloud +model_catalog: + enabled: true + ttl_hours: 1 + url: https://hermes-agent.nousresearch.com/docs/api/model-catalog.json +network: + force_ipv4: false +onboarding: + seen: + busy_input_prompt: true + openclaw_residue_cleanup: true + tool_progress_prompt: true +openrouter: + min_coding_score: 0.65 + response_cache: true + response_cache_ttl: 300 +paste_collapse_char_threshold: 2000 +paste_collapse_threshold: 5 +paste_collapse_threshold_fallback: 5 +platform_toolsets: + cli: + - browser + - clarify + - code_execution + - computer_use + - cronjob + - delegation + - file + - image_gen + - memory + - session_search + - skills + - terminal + - todo + - tts + - vision + - web + - mcp-codegraph + firecrawl: + connect_timeout: 30 + timeout: 120 + url: https://mcp.firecrawl.dev/v2/mcp +platforms: + feishu: + app_id: cli_a95d7ff06b789bb4 + app_secret: Gm7eo0aD9Luka8mHxApRufYIDwmpGsGf + enabled: true + webhook: + enabled: true + extra: + host: 0.0.0.0 + port: 8644 +plugins: + disabled: [] + enabled: + - agentic-sms-gateway + - cronalytics + - rtk-rewrite +prefill_messages_file: '' +privacy: + redact_pii: false +prompt_caching: + cache_ttl: 5m + long_lived_prefix: true + long_lived_ttl: 1h +providers: + agnes: + base_url: https://apihub.agnes-ai.com/v1 + cost_factor: 0.0 + default_model: agnes-2.0-flash + key_env: AGNES_API_KEY + models: + - agnes-2.0-flash + - agnes-2.5-flash + rate_limit: 1000 + timeout: 60 + deepseek: + base_url: https://api.deepseek.com + cost_factor: 0.0 + default_model: deepseek-v4-flash + key_env: DEEPSEEK_API_KEY + models: + - deepseek-v4-flash + - deepseek-v4-pro + rate_limit: 1000 + timeout: 30 + mimo: + base_url: https://token-plan-cn.xiaomimimo.com/v1 + cost_factor: 0.0 + default_model: mimo-v2.5-pro + key_env: XIAOMI_API_KEY + models: + - mimo-v2.5-pro + - mimo-v2.5 + rate_limit: 1000 + timeout: 60 + newapi-local: + api_key: 0ExNiLblJvIWBDpkS50fwOBw4MmqLyKdHJK5iQtlw9dOMWBP + base_url: http://127.0.0.1:3000/v1 + cost_factor: 0.0 + default_model: agnes-2.0-flash + models: + - nvidia/nemotron-mini-4b-instruct + - openai/gpt-oss-120b + - nvidia/nvidia-nemotron-nano-9b-v2 + - meta/llama-3.1-8b-instruct + rate_limit: 1000 + timeout: 30 + omniroute-local: + api_key: local-test-key + base_url: http://127.0.0.1:3001/v1 + cost_factor: 0.0 + default_model: auto/chat + models: + - auto/chat + - auto/best-free + - auto/coding + rate_limit: 1000 + timeout: 30 + opencode-free: + api_key: opencode-zen-free-keyless + base_url: https://opencode.ai/zen/v1 + cost_factor: 0.0 + default_model: x-preview-f-free + models: + - x-preview-f-free + - hy3-free + - laguna-s-2.1-free + - nemotron-3-ultra-free + - nemotron-3.5-lightning-free + - muse-spark-1.2-contributor-free + rate_limit: 1000 + timeout: 30 + sensenova: + api_key: ${SENSENOVA_API_KEY} + base_url: https://token.sensenova.cn/v1 + cost_factor: 0.0 + default_model: deepseek-v4-flash + models: + - deepseek-v4-flash + - glm-5.2 + - sensenova-6.8-flash-lite + rate_limit: 1000 + timeout: 30 + zhipu: + api_key: ${ZHIPU_API_KEY} + base_url: https://open.bigmodel.cn/api/paas/v4 + models: + - glm-4-flash + - glm-4-air + - glm-4-long + type: openai + llama-local: + api_key: local-key + base_url: http://127.0.0.1:8080/v1 + cost_factor: 0.0 + default_model: qwen3b + models: + - qwen3b + - qwen7b + rate_limit: 100 + timeout: 300 + context_length: 131072 + gmi-cloud: + api_key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImFlZGEwZTJmLTI1N2ItNGEwYi04NzBhLWUwZjI3MzQ0NWM2YSIsInNjb3BlIjoiaWVfbW9kZWwiLCJwcm9kdWN0IjoiSUUiLCJvd25lcklkIjoiOTYxZGY1MWUtMjAyMi00ZDZjLWI2YTgtNWMxN2M5NzA1NjEyIn0.7v6kPl4VcNHtOcU3hN2FAMGVEuDxvym1h9FwXZBaD7M + base_url: https://api.gmi-serving.com/v1 + default_model: MiniMaxAI/MiniMax-M3 + cost_factor: 0.0 + timeout: 180 + rate_limit: 100 + context_length: 1048576 + default_headers: + User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like + Gecko) Chrome/120.0 Safari/537.36 +secrets: + bitwarden: + access_token_env: BWS_ACCESS_TOKEN + auto_install: true + cache_ttl_seconds: 300 + enabled: false + override_existing: true + project_id: '' + server_url: '' +security: + acked_advisories: [] + allow_lazy_installs: true + allow_private_urls: false + redact_secrets: true + tirith_enabled: true + tirith_fail_open: true + tirith_path: tirith + tirith_timeout: 5 + website_blocklist: + domains: [] + enabled: false + shared_files: [] +session_reset: {} +sessions: + auto_prune: false + min_interval_hours: 24 + retention_days: 90 + vacuum_after_prune: true + write_json_snapshots: false +skills: + external_dirs: [] + guard_agent_created: false + inline_shell: false + inline_shell_timeout: 10 + template_vars: true +slack: + allowed_channels: '' + free_response_channels: '' + require_mention: true +stt: + enabled: true + local: + language: '' + model: base + mistral: + model: voxtral-mini-latest + openai: + model: whisper-1 + provider: local +telegram: + allowed_chats: '' + reactions: false +terminal: + auto_source_bashrc: true + backend: local + container_cpu: 1 + container_disk: 51200 + container_memory: 5120 + container_persistent: true + cwd: . + daytona_image: nikolaik/python-nodejs:python3.11-nodejs20 + docker_extra_args: [] + docker_forward_env: [] + docker_image: nikolaik/python-nodejs:python3.11-nodejs20 + docker_mount_cwd_to_workspace: false + docker_run_as_host_user: false + docker_volumes: [] + env_passthrough: [] + modal_image: nikolaik/python-nodejs:python3.11-nodejs20 + modal_mode: auto + persistent_shell: true + shell_init_files: [] + singularity_image: docker://nikolaik/python-nodejs:python3.11-nodejs20 + timeout: 180 + vercel_runtime: node24 +timezone: '' +tool_loop_guardrails: + hard_stop_after: + exact_failure: 5 + idempotent_no_progress: 5 + same_tool_failure: 8 + hard_stop_enabled: false + warn_after: + exact_failure: 2 + idempotent_no_progress: 2 + same_tool_failure: 3 + warnings_enabled: true +tool_output: + max_bytes: 50000 + max_line_length: 2000 + max_lines: 2000 +tools: + tool_search: + enabled: auto + max_search_limit: 20 + search_default_limit: 5 + threshold_pct: 10 +toolsets: +- hermes-cli +- web +tts: + edge: + voice: zh-CN-XiaoyiNeural + elevenlabs: + model_id: eleven_multilingual_v2 + voice_id: pNInz6obpgDQGcFmaJgB + mistral: + model: voxtral-mini-tts-2603 + voice_id: c69964a6-ab8b-4f8a-9465-ec0925096ec8 + neutts: + device: cpu + model: neuphonic/neutts-air-q4-gguf + ref_audio: '' + ref_text: '' + openai: + model: gpt-4o-mini-tts + voice: alloy + piper: + voice: en_US-lessac-medium + provider: mimo + providers: + mimo: + command: bash /home/muc/.hermes/scripts/mimo_tts.sh {input_path} {output_path} + {voice} + output_format: opus + type: command + voice: 冰糖 + use_gateway: false + xai: + bit_rate: 128000 + language: en + sample_rate: 24000 + voice_id: eve +updates: + backup_keep: 5 + pre_update_backup: false +voice: + auto_tts: true + beep_enabled: true + max_recording_seconds: 120 + record_key: ctrl+b + silence_duration: 3.0 + silence_threshold: 200 +web: + backend: '' + extract_backend: '' + search_backend: '' +weixin: + enabled: true + extra: + account_id: bef3c3d39904@im.bot + base_url: https://ilinkai.weixin.qq.com + dm_policy: open + group_policy: open + token: bef3c3d39904@im.bot:060000740c190c21262c8edf68365d5d112e0d + user_id: o9cq800DqpnMoqzXmJ4zozKiM8OI@im.wechat +x_search: + model: grok-4.20-reasoning + retries: 2 + timeout_seconds: 180 diff --git a/scripts/test_holographic.py b/scripts/test_holographic.py new file mode 100644 index 00000000..80b230dd --- /dev/null +++ b/scripts/test_holographic.py @@ -0,0 +1,71 @@ +import os, sys +os.environ['HERMES_HOME'] = '/home/muc/.hermes' +sys.path.insert(0, '/home/muc/.hermes/hermes-agent') +from plugins.memory.holographic.store import MemoryStore +from plugins.memory.holographic.retrieval import FactRetriever + +DB = '/home/muc/.hermes/memory_store.db' +if os.path.exists(DB): os.remove(DB) + +print("=" * 60) +print("HOLO Test - 9 actions + feedback") +print("=" * 60) + +store = MemoryStore(DB) +retr = FactRetriever(store) + +print("\n[1] ADD_FACT 5 facts") +f1 = store.add_fact("小唯喜欢 16yo 172cm porcelain skin 人物设定", category="preference") +f2 = store.add_fact("商汤 SenseNova 出图大于 Agnes", category="tool") +f3 = store.add_fact("删 skill 前必须经牧尘同意", category="rule") +f4 = store.add_fact("v0.21.0 已升级 gateway 跑通", category="event") +f5 = store.add_fact("KOCR 修复铁律:只动需要改的列", category="rule") +print(f"IDs: {[f1, f2, f3, f4, f5]}") + +print("\n[2] LIST_FACTS") +for f in store.list_facts(): + print(f" [{f['fact_id']}] trust={f['trust_score']:.2f} {f['category']}: {f['content'][:50]}") + +print("\n[3] SEARCH 'KOCR'") +for r in retr.search("KOCR", limit=3): + print(f" [{r['fact_id']}] score={r.get('score',0):.3f}: {r['content'][:50]}") + +print("\n[4] PROBE '人物设定'") +for r in retr.probe("人物设定", limit=3): + print(f" [{r['fact_id']}] score={r.get('score',0):.3f}: {r['content'][:50]}") + +print("\n[5] RELATED 'KOCR'") +for r in retr.related("KOCR", limit=3): + print(f" [{r['fact_id']}]: {r['content'][:50]}") + +print("\n[6] REASON ['人物设定', 'preference']") +for r in retr.reason(["人物设定", "preference"], limit=3): + print(f" [{r['fact_id']}] conf={r.get('confidence',0):.3f}: {r['content'][:50]}") + +print("\n[7] CONTRADICT (scan all category=tool)") +f6 = store.add_fact("Agnes 出图比商汤好", category="tool") +contras = retr.contradict(category="tool", limit=5) +print(f" f6: {f6}, 矛盾扫描: {len(contras)}") +for c in contras[:5]: + print(f" [{c['fact_id']}]: {c['content'][:50]}") + +print("\n[8] UPDATE_FACT f4 trust_delta -0.25") +print(f" Result: {store.update_fact(f4, trust_delta=-0.25)}") + +print("\n[9] REMOVE_FACT f6") +print(f" Result: {store.remove_fact(f6)}") + +print("\n[10] FEEDBACK f1 helpful=True") +print(f" Result: {store.record_feedback(f1, helpful=True)}") + +print("\n[11] FEEDBACK f2 helpful=False") +print(f" Result: {store.record_feedback(f2, helpful=False)}") + +print("\n" + "=" * 60) +print("FINAL (含 trust 变化)") +print("=" * 60) +for f in store.list_facts(): + print(f" [{f['fact_id']}] trust={f['trust_score']:.2f} help={f['helpful_count']}: {f['content'][:50]}") +print(f"\nTotal: {len(store.list_facts())} facts") +print(f"DB size: {os.path.getsize(DB)} bytes") +store.close()