memu-cli 0.3.0__tar.gz → 0.4.0__tar.gz
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.
- {memu_cli-0.3.0 → memu_cli-0.4.0}/CHANGELOG.md +100 -0
- memu_cli-0.4.0/INSTALL-LATEST.md +134 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/PKG-INFO +9 -4
- {memu_cli-0.3.0 → memu_cli-0.4.0}/README.md +8 -3
- {memu_cli-0.3.0 → memu_cli-0.4.0}/SKILL.md +20 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/pyproject.toml +2 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/app/agentic.py +17 -4
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/cli.py +8 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/http_client.py +60 -5
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/openai_sdk.py +21 -2
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/env.py +20 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/layout.py +15 -2
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/manifest.py +8 -4
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/pipeline.py +24 -4
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/transcripts.py +14 -7
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/claude_code/BRIDGING_TASK.md +39 -6
- memu_cli-0.4.0/src/memu/hosts/claude_code/INSTALL.md +197 -0
- memu_cli-0.4.0/src/memu/hosts/claude_code/UNINSTALL.md +108 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/claude_code/cli.py +6 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/claude_code/sessions.py +11 -9
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/codex/BRIDGING_TASK.md +21 -10
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/codex/INSTALL.md +68 -19
- memu_cli-0.4.0/src/memu/hosts/codex/UNINSTALL.md +101 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/codex/cli.py +6 -0
- memu_cli-0.4.0/src/memu/hosts/codex/sessions.py +80 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/cursor/BRIDGING_TASK.md +37 -5
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/cursor/INSTALL.md +34 -1
- memu_cli-0.4.0/src/memu/hosts/cursor/UNINSTALL.md +105 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/cursor/cli.py +1 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/BRIDGING_TASK.md +47 -10
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/INSTALL.md +34 -1
- memu_cli-0.4.0/src/memu/hosts/generic/UNINSTALL.md +108 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/cli.py +1 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/hermes/BRIDGING_TASK.md +35 -3
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/hermes/INSTALL.md +57 -11
- memu_cli-0.4.0/src/memu/hosts/hermes/UNINSTALL.md +114 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/hermes/cli.py +8 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/hermes/sessions.py +4 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/host_cli.py +101 -5
- memu_cli-0.4.0/src/memu/hosts/instruction.py +320 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/openclaw/BRIDGING_TASK.md +40 -9
- memu_cli-0.4.0/src/memu/hosts/openclaw/INSTALL.md +179 -0
- memu_cli-0.4.0/src/memu/hosts/openclaw/UNINSTALL.md +112 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/openclaw/cli.py +8 -1
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/openclaw/sessions.py +17 -1
- memu_cli-0.4.0/src/memu/hosts/workbuddy/BRIDGING_TASK.md +115 -0
- {memu_cli-0.3.0/src/memu/hosts/claude_code → memu_cli-0.4.0/src/memu/hosts/workbuddy}/INSTALL.md +46 -37
- memu_cli-0.4.0/src/memu/hosts/workbuddy/UNINSTALL.md +96 -0
- memu_cli-0.4.0/src/memu/hosts/workbuddy/__init__.py +11 -0
- memu_cli-0.4.0/src/memu/hosts/workbuddy/cli.py +48 -0
- memu_cli-0.4.0/src/memu/hosts/workbuddy/sessions.py +86 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_agentic.py +8 -3
- memu_cli-0.4.0/tests/test_bridging_promotion.py +125 -0
- memu_cli-0.4.0/tests/test_cli_stdio.py +47 -0
- memu_cli-0.4.0/tests/test_doctor_proxy_hint.py +169 -0
- memu_cli-0.4.0/tests/test_embedding_proxy.py +200 -0
- memu_cli-0.4.0/tests/test_env_passthrough.py +72 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_host_generic.py +7 -6
- memu_cli-0.4.0/tests/test_host_instruction.py +294 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_host_sessions.py +199 -2
- memu_cli-0.3.0/src/memu/hosts/codex/sessions.py +0 -52
- memu_cli-0.3.0/src/memu/hosts/instruction.py +0 -167
- memu_cli-0.3.0/src/memu/hosts/openclaw/INSTALL.md +0 -129
- memu_cli-0.3.0/tests/test_host_instruction.py +0 -107
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/ISSUE_TEMPLATE/hackathon_task.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/ISSUE_TEMPLATE/improvement_suggestion.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/workflows/build.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/workflows/pr-title.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/workflows/publish-memu-cli.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.github/workflows/release-please.yml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.gitignore +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.pre-commit-config.yaml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/.python-version +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/AGENTS.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/CONTRIBUTING.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/Cargo.lock +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/Cargo.toml +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/LICENSE.txt +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/MANIFEST.in +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/Makefile +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/banner.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/benchmark.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/memUbot.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/memorize.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/Clawdchat.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/LazyLLM.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/buddie.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/bytebase.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/jazz.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/openagents.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/partners/xroute.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/qrcode.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/retrieve.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/star.gif +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/structure-v2.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/structure.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_companion-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_creation-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_edu-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_ip-0000.png +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_robot-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_role_play-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/assets/usecase/ai_therapy-0000.jpg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0001-workflow-pipeline-architecture.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0002-pluggable-storage-and-vector-strategy.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0003-user-scope-in-data-model.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0004-workspace-memorize-and-memory-file-system.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0005-dedicated-embedding-package.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0006-from-memory-item-category-to-tracked-workspace-memorization.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0007-three-independent-memory-lines-wiki-graph.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0008-two-integration-surfaces-hooks-and-api.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0009-codex-packaging-cli-and-config.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0010-multi-host-adapters.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/0011-generic-host-adapter.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/adr/README.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/docs/sqlite.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/npm/README.md +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/npm/bin/memu.js +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/npm/package.json +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/scripts/db.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/setup.cfg +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/lib.rs +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/__main__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/_core.pyi +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/app/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/app/client_pool.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/app/service.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/app/settings.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/factory.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/models.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/filter.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/repositories/resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/state.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/inmemory/vector.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/interfaces.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/models.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/migration.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/migrations/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/migrations/env.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/migrations/script.py.mako +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/migrations/versions/20260703_0001_initial_schema.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/models.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/postgres.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/base.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/repositories/resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/schema.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/postgres/session.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/repositories/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/repositories/recall_file.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/repositories/recall_file_resource.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/repositories/recall_file_segment.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/repositories/resource.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/models.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/base.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/repositories/resource_repo.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/schema.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/session.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/sqlite/sqlite.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/database/state.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/base.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/doubao.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/jina.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/openai.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/openrouter.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/backends/voyage.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/base.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/defaults.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/embedding/gateway.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/base.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/instructions.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/recall_files.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/bridging/resources.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/claude_code/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/codex/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/cursor/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/cursor/sessions.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/detect.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/generic/sessions.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/hermes/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/openclaw/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/hosts/retrieval.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/src/memu/vector.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/__init__.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/rust_entry_test.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_cli.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_embedding.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_postgres_migration_config.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/tests/test_vector.py +0 -0
- {memu_cli-0.3.0 → memu_cli-0.4.0}/uv.lock +0 -0
|
@@ -1,5 +1,105 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.0-beta.0](https://github.com/NevaMind-AI/memU/compare/v1.5.1...v2.0.0-beta.0) (2026-07-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **blob:** ingest rich documents (PDF/Office/HTML) via MarkItDown ([#447](https://github.com/NevaMind-AI/memU/issues/447)) ([1e16341](https://github.com/NevaMind-AI/memU/commit/1e1634131f84ceb023d03cd87bcf062317abd5ba))
|
|
9
|
+
* Codex session-bridging pipeline and scheduled-task skill ([#477](https://github.com/NevaMind-AI/memU/issues/477)) ([1a8edb5](https://github.com/NevaMind-AI/memU/commit/1a8edb57110ebfd208b2fe1f52e3998058fed408))
|
|
10
|
+
* **doctor:** diagnose proxy hijacking instead of printing a bare 502 ([7c41eec](https://github.com/NevaMind-AI/memU/commit/7c41eecd53e4c13b1a5c25b01b70f484147295fb))
|
|
11
|
+
* **env:** config.env carries NO_PROXY; MEMU_HTTP_PROXY works from the file ([5265945](https://github.com/NevaMind-AI/memU/commit/5265945e3063529819415194e79c46b7614d6081))
|
|
12
|
+
* from memory item/category to tracked entry/file for workspace memorization (ADR 0006) ([#456](https://github.com/NevaMind-AI/memU/issues/456)) ([68877da](https://github.com/NevaMind-AI/memU/commit/68877da10a1a18be5c708ec1ab7eb6c45b80ae50))
|
|
13
|
+
* **hermes:** install retrieval as a skill ([#536](https://github.com/NevaMind-AI/memU/issues/536)) ([8766d3d](https://github.com/NevaMind-AI/memU/commit/8766d3d3903383a3d4ff38d0f0d620cdf97418ec))
|
|
14
|
+
* **hosts:** add Claude Code, Cursor, OpenClaw, and Hermes host adapters ([#494](https://github.com/NevaMind-AI/memU/issues/494)) ([24d1b3b](https://github.com/NevaMind-AI/memU/commit/24d1b3b4f345106f07f1262dc2756b49fb7102cf))
|
|
15
|
+
* **hosts:** add memu-agent, a generic adapter for any other agent ([#496](https://github.com/NevaMind-AI/memU/issues/496)) ([e46a1f0](https://github.com/NevaMind-AI/memU/commit/e46a1f04a216a80b3a38064866420c79205fbe22))
|
|
16
|
+
* **hosts:** agent-driven uninstall — remove-instruction, docs uninstall, per-host guides ([#509](https://github.com/NevaMind-AI/memU/issues/509)) ([f51673e](https://github.com/NevaMind-AI/memU/commit/f51673e6e80b23c570a7364b415bf61481956971))
|
|
17
|
+
* **hosts:** install retrieval as a skill on Codex and Claude Code ([#535](https://github.com/NevaMind-AI/memU/issues/535)) ([2ed480e](https://github.com/NevaMind-AI/memU/commit/2ed480ebe462fe4008fdb4315cf5ab9e0316dba4))
|
|
18
|
+
* layered, track-aware workspace memorize & retrieve ([#466](https://github.com/NevaMind-AI/memU/issues/466)) ([094e22f](https://github.com/NevaMind-AI/memU/commit/094e22f0e10e7fe71c079608407b6a01b4d67e55))
|
|
19
|
+
* **llm,vlm:** multi-provider LLM gateway, modular preprocessing, and VLM package ([#442](https://github.com/NevaMind-AI/memU/issues/442)) ([6f1b0bc](https://github.com/NevaMind-AI/memU/commit/6f1b0bc19d600e77abe7d6ec82d4196d1efe1516))
|
|
20
|
+
* **memory_fs:** workspace memorize + markdown memory file system ([#439](https://github.com/NevaMind-AI/memU/issues/439)) ([1b1ad61](https://github.com/NevaMind-AI/memU/commit/1b1ad61bdb96030f00e169b14d7864c1f6adb931))
|
|
21
|
+
* memu CLI, npm launcher, and agent skills for the workspace pair ([#467](https://github.com/NevaMind-AI/memU/issues/467)) ([c861974](https://github.com/NevaMind-AI/memU/commit/c8619744b13c67f7efc3322c060e6090255a8522))
|
|
22
|
+
* **npm:** point the launcher at the memu-cli PyPI channel ([#483](https://github.com/NevaMind-AI/memU/issues/483)) ([5056389](https://github.com/NevaMind-AI/memU/commit/505638905f279e0b2fac61572ea551f819007aa1))
|
|
23
|
+
* **openclaw:** install retrieval as a skill ([#537](https://github.com/NevaMind-AI/memU/issues/537)) ([3cef5ae](https://github.com/NevaMind-AI/memU/commit/3cef5ae2610ce9227de6471a63cc139ff09cf63c))
|
|
24
|
+
* **preprocess:** classify audio type and add an overview on ingest ([#448](https://github.com/NevaMind-AI/memU/issues/448)) ([f7601da](https://github.com/NevaMind-AI/memU/commit/f7601daf4ed89815af5c1c1c9011db6af63c1fa5))
|
|
25
|
+
* **vlm,preprocess:** native whole-video understanding via OpenRouter ([#450](https://github.com/NevaMind-AI/memU/issues/450)) ([1de5784](https://github.com/NevaMind-AI/memU/commit/1de57847e0ffc430cbf5d6dc17183f33d08be8fe))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* **app:** unpack the (vectors, raw_response) tuple embed() returns ([#504](https://github.com/NevaMind-AI/memU/issues/504)) ([9b2a70c](https://github.com/NevaMind-AI/memU/commit/9b2a70ca214cd3a5b22e902cad0dc19ad07bfeb9))
|
|
31
|
+
* **bridging:** advance the cursor and snapshot at commit, not prepare ([#531](https://github.com/NevaMind-AI/memU/issues/531)) ([0ceaa19](https://github.com/NevaMind-AI/memU/commit/0ceaa190d92f8c7c6705db0dcfd6628581d10213))
|
|
32
|
+
* **ci:** sort workbuddy cli imports so make check passes ([#522](https://github.com/NevaMind-AI/memU/issues/522)) ([151298c](https://github.com/NevaMind-AI/memU/commit/151298c3c03a6b3cc9ef371d8211b469fffc2469))
|
|
33
|
+
* **cli:** force UTF-8 stdio so piped output survives non-UTF-8 Windows code pages ([#513](https://github.com/NevaMind-AI/memU/issues/513)) ([b521453](https://github.com/NevaMind-AI/memU/commit/b5214536c5fce628c174c9c074b9c1d0a53da2ca))
|
|
34
|
+
* **codex:** drop harness-injected user records from the conversation seam ([#511](https://github.com/NevaMind-AI/memU/issues/511)) ([c827157](https://github.com/NevaMind-AI/memU/commit/c827157ead066f0a859cb2f1e5deac62ffbe63a5))
|
|
35
|
+
* **embedding:** never route loopback embedding calls through a proxy ([#519](https://github.com/NevaMind-AI/memU/issues/519)) ([df6cfba](https://github.com/NevaMind-AI/memU/commit/df6cfba6b9741cc062b7d219af042ddddffcbb5c))
|
|
36
|
+
* handle multiple root-level XML elements from non-conformant LLMs ([#409](https://github.com/NevaMind-AI/memU/issues/409)) ([fed42b6](https://github.com/NevaMind-AI/memU/commit/fed42b6142ec1e9f9820e46d8899823d68de8276))
|
|
37
|
+
* **hermes:** escape the state.db path when building the SQLite URI ([#503](https://github.com/NevaMind-AI/memU/issues/503)) ([3135132](https://github.com/NevaMind-AI/memU/commit/313513204d87e7156d6a7d459df1bcac64469044))
|
|
38
|
+
* **llm/vlm:** correct OpenAI token-limit param and simplify conversation preprocess ([#449](https://github.com/NevaMind-AI/memU/issues/449)) ([ff3c2be](https://github.com/NevaMind-AI/memU/commit/ff3c2bee2ec96ebd303f3e22dae1977ff6388120))
|
|
39
|
+
* make lazyllm an optional dependency (fixes [#373](https://github.com/NevaMind-AI/memU/issues/373)) ([#402](https://github.com/NevaMind-AI/memU/issues/402)) ([7652982](https://github.com/NevaMind-AI/memU/commit/7652982a016b2a2426d20bc11c46491d909704d0))
|
|
40
|
+
* **memory_fs:** restore LLM-free skill bypass and unify synthesis paths ([#444](https://github.com/NevaMind-AI/memU/issues/444)) ([bc13bd4](https://github.com/NevaMind-AI/memU/commit/bc13bd43c6ed3d480b671736bab987434675c717))
|
|
41
|
+
* **openclaw:** scan only main session transcripts, not trajectory/checkpoint sidecars ([0245de9](https://github.com/NevaMind-AI/memU/commit/0245de9710f8f73a8b21361442ac3dfd6c7829c7))
|
|
42
|
+
* optimize category initialization to avoid unnecessary embedding ([#388](https://github.com/NevaMind-AI/memU/issues/388)) ([a92f266](https://github.com/NevaMind-AI/memU/commit/a92f2666bf94336f8c6bf950088249e611915e7d))
|
|
43
|
+
* remove broken memu-server entry point (fixes [#354](https://github.com/NevaMind-AI/memU/issues/354)) ([#398](https://github.com/NevaMind-AI/memU/issues/398)) ([0672b56](https://github.com/NevaMind-AI/memU/commit/0672b56725e12c35bd46061bb23ccd93690a5fbb))
|
|
44
|
+
* remove duplicate document text from preprocess prompt ([#420](https://github.com/NevaMind-AI/memU/issues/420)) ([44aa5ff](https://github.com/NevaMind-AI/memU/commit/44aa5ff0cbceae56ab283848e722a9d4bd8eddd0))
|
|
45
|
+
* remove stale memu-server script entry point (fixes [#393](https://github.com/NevaMind-AI/memU/issues/393)) ([#403](https://github.com/NevaMind-AI/memU/issues/403)) ([c5fe493](https://github.com/NevaMind-AI/memU/commit/c5fe493b0596d68479b0ce6c6d83e362ffb04e90))
|
|
46
|
+
* resolve SQLite embedding TypeError by using sa_column=False ([#401](https://github.com/NevaMind-AI/memU/issues/401)) ([7e198f3](https://github.com/NevaMind-AI/memU/commit/7e198f3718fa6028c809ba7d816a96541fe7e13f))
|
|
47
|
+
* return empty list for non-positive top_k in cosine_topk ([#423](https://github.com/NevaMind-AI/memU/issues/423)) ([39023a8](https://github.com/NevaMind-AI/memU/commit/39023a81d758eb4447ed7d88503b8d782aecaf73))
|
|
48
|
+
* **tests:** pin UTF-8 on test file I/O so the suite passes on non-UTF-8-locale Windows ([#501](https://github.com/NevaMind-AI/memU/issues/501)) ([dda515a](https://github.com/NevaMind-AI/memU/commit/dda515a4eb3117ff804cd7ce1ae66e03c23028b6))
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Documentation
|
|
52
|
+
|
|
53
|
+
* add ADR 0008 — trajectory as the source, hooks over API ([#476](https://github.com/NevaMind-AI/memU/issues/476)) ([ff90dac](https://github.com/NevaMind-AI/memU/commit/ff90dac6976bc920667e03d295a75d5da8626f75))
|
|
54
|
+
* add INSTALL-LATEST.md and register the WorkBuddy adapter ([#527](https://github.com/NevaMind-AI/memU/issues/527)) ([4871c55](https://github.com/NevaMind-AI/memU/commit/4871c558d5b84c7649d822015dab617a095d678f))
|
|
55
|
+
* add SKILL.md, one routing entry point for agent-driven install ([#497](https://github.com/NevaMind-AI/memU/issues/497)) ([bf7aaf3](https://github.com/NevaMind-AI/memU/commit/bf7aaf3bf95cb37f723e7a81b6d5bcdaf35a0f2e))
|
|
56
|
+
* add the architecture image the README references ([#492](https://github.com/NevaMind-AI/memU/issues/492)) ([c07b905](https://github.com/NevaMind-AI/memU/commit/c07b9055dc245680c67df02199d4c95cd7a9a62f))
|
|
57
|
+
* add under-construction notice, stabilizing ~July 15 ([#472](https://github.com/NevaMind-AI/memU/issues/472)) ([6426ff0](https://github.com/NevaMind-AI/memU/commit/6426ff02aacca12e9d4efbcfc89f53eeed2ae55b))
|
|
58
|
+
* ADR 0007 — drop the graph, retrieval is hybrid (embedding + BM25) ([#464](https://github.com/NevaMind-AI/memU/issues/464)) ([3dd7d5c](https://github.com/NevaMind-AI/memU/commit/3dd7d5c055fc6a3244d4c2390f7b8e6bc4321857))
|
|
59
|
+
* ADR 0007 — invert L1/L2 (L1 = coarse doc, L2 = item slices) ([#465](https://github.com/NevaMind-AI/memU/issues/465)) ([0afbcc5](https://github.com/NevaMind-AI/memU/commit/0afbcc550ac5b816e5ae9ad309e62adbdf4b80b4))
|
|
60
|
+
* ADR 0007 — replace the explicit item graph with entity linking ([#463](https://github.com/NevaMind-AI/memU/issues/463)) ([0bd3c77](https://github.com/NevaMind-AI/memU/commit/0bd3c7765ac791020941de8791ba5b7c50ecc5e0))
|
|
61
|
+
* ADR 0007 — three independent memory lines on a layered wiki-graph kernel ([#461](https://github.com/NevaMind-AI/memU/issues/461)) ([a6cf62e](https://github.com/NevaMind-AI/memU/commit/a6cf62e069765b7b234597e537ec170d169d751c))
|
|
62
|
+
* align architecture.md and READMEs with ADR 0006 data model ([#460](https://github.com/NevaMind-AI/memU/issues/460)) ([8062b91](https://github.com/NevaMind-AI/memU/commit/8062b91776e69757fd467e79e56cd72eba62c72c))
|
|
63
|
+
* consolidate agent skills into one memu SKILL.md, link it atop README ([#469](https://github.com/NevaMind-AI/memU/issues/469)) ([6f0ae82](https://github.com/NevaMind-AI/memU/commit/6f0ae82aaf9d1193841b8e082a2f9fed8753ed70))
|
|
64
|
+
* drop the API and CLI reference sections from the README ([#489](https://github.com/NevaMind-AI/memU/issues/489)) ([94a1111](https://github.com/NevaMind-AI/memU/commit/94a11117cf5684888fb7858356c51203c903e9bb))
|
|
65
|
+
* expand the README; rename provider var to MEMU_EMBED_PROVIDER ([#486](https://github.com/NevaMind-AI/memU/issues/486)) ([96da89b](https://github.com/NevaMind-AI/memU/commit/96da89bfe048b86516faa4b86f69b508fb4c4c3c))
|
|
66
|
+
* focus readme on workspace APIs ([9241f31](https://github.com/NevaMind-AI/memU/commit/9241f3112e912bd47add2fabe6dc2611a4bdac8c))
|
|
67
|
+
* **grok:** fix MemoryService initialization example ([#405](https://github.com/NevaMind-AI/memU/issues/405)) ([96e693a](https://github.com/NevaMind-AI/memU/commit/96e693aa09add032f67b342e21b86fa96078611b))
|
|
68
|
+
* highlight self-evolving skills in README and description ([#452](https://github.com/NevaMind-AI/memU/issues/452)) ([fb68d22](https://github.com/NevaMind-AI/memU/commit/fb68d22c3caa4a9b6f5cb2a57d185bb9b5e22a5f))
|
|
69
|
+
* **hosts:** bind the session cursor's lifecycle to the store's ([75959a6](https://github.com/NevaMind-AI/memU/commit/75959a6e72727c35929f4296c087ed00c97971bf))
|
|
70
|
+
* **hosts:** correct the Claude Code multi-block claim and pin it with tests ([#502](https://github.com/NevaMind-AI/memU/issues/502)) ([5995e05](https://github.com/NevaMind-AI/memU/commit/5995e05f27c7d90231468bcb062713af30813b08))
|
|
71
|
+
* **hosts:** default bridging schedule to hourly ([#516](https://github.com/NevaMind-AI/memU/issues/516)) ([c1046bb](https://github.com/NevaMind-AI/memU/commit/c1046bb1954c3dd7b16ced769da030d8a02c8d32))
|
|
72
|
+
* **hosts:** name the OS system-wide proxy as a 502 source ([#523](https://github.com/NevaMind-AI/memU/issues/523)) ([2b79803](https://github.com/NevaMind-AI/memU/commit/2b79803612872e65201a40dde95ac00541f93fae))
|
|
73
|
+
* **hosts:** no-key local fallback hint; default bridging schedule to cron ([#508](https://github.com/NevaMind-AI/memU/issues/508)) ([d155c48](https://github.com/NevaMind-AI/memU/commit/d155c48ac6a35465ad47848927b271f34e2dc4d0))
|
|
74
|
+
* **hosts:** scheduled runs drain leftover jobs first; config repairs stay at the connection layer ([9195d14](https://github.com/NevaMind-AI/memU/commit/9195d14cef2d308cff3fcb853a6274e1f0db9d31))
|
|
75
|
+
* **hosts:** the scheduler's PATH is not your shell's — fix and honest verify for the bridging guides ([#530](https://github.com/NevaMind-AI/memU/issues/530)) ([19302d2](https://github.com/NevaMind-AI/memU/commit/19302d24260c7b941bdfee66bba8f16b6b47c8c2))
|
|
76
|
+
* lead the README with the one-message agent-driven install ([#498](https://github.com/NevaMind-AI/memU/issues/498)) ([aae3d44](https://github.com/NevaMind-AI/memU/commit/aae3d44b0a4332981c4459e7da9258298bcc0fb1))
|
|
77
|
+
* make the workspace pair primary, mark memorize/retrieve as legacy ([#470](https://github.com/NevaMind-AI/memU/issues/470)) ([6f3c1be](https://github.com/NevaMind-AI/memU/commit/6f3c1beb36bba21a7d640b0dbdead9361a90a811))
|
|
78
|
+
* never fall back to legacy memorize/retrieve ([#471](https://github.com/NevaMind-AI/memU/issues/471)) ([28ee09d](https://github.com/NevaMind-AI/memU/commit/28ee09de54de5bd74f4f6bb1e0185c854ecf1053))
|
|
79
|
+
* pitch memU as a 500-line memory system ([#488](https://github.com/NevaMind-AI/memU/issues/488)) ([2a8f8b3](https://github.com/NevaMind-AI/memU/commit/2a8f8b3403548a8d8917a19d5ac0015adf4eab17))
|
|
80
|
+
* point the README at the memu-cli package ([#491](https://github.com/NevaMind-AI/memU/issues/491)) ([9ceea5b](https://github.com/NevaMind-AI/memU/commit/9ceea5b32a2694cf4ab5e5f0069b029ac13800b3))
|
|
81
|
+
* **readme:** readme accuracy updates ([#430](https://github.com/NevaMind-AI/memU/issues/430)) ([5f17725](https://github.com/NevaMind-AI/memU/commit/5f1772579c8d0881ec1c9ab071404aea6b3bfadc))
|
|
82
|
+
* **readme:** reframe intro around MEMORY.md, SKILL.md, and INDEX.md ([#434](https://github.com/NevaMind-AI/memU/issues/434)) ([ca0c755](https://github.com/NevaMind-AI/memU/commit/ca0c755dcc06874c227df811d6b7a3ca972f6be2))
|
|
83
|
+
* **readme:** reframe README around file-system-as-memory narrative ([#432](https://github.com/NevaMind-AI/memU/issues/432)) ([cd8150a](https://github.com/NevaMind-AI/memU/commit/cd8150ac7d68f4972d9a9e8268e3169da9b4cfc3))
|
|
84
|
+
* **readme:** reframe README around workspace-runtime narrative ([#438](https://github.com/NevaMind-AI/memU/issues/438)) ([7c104b1](https://github.com/NevaMind-AI/memU/commit/7c104b1eb0883437d49bea0edae3a24eea12f275))
|
|
85
|
+
* **readme:** sync translated READMEs to file-system-as-memory narrative ([#433](https://github.com/NevaMind-AI/memU/issues/433)) ([f4e82ce](https://github.com/NevaMind-AI/memU/commit/f4e82cec1898e34f82612ec3628f8de1faedf701))
|
|
86
|
+
* refine ADR 0007 with the L0/L1/L2 layer model ([#462](https://github.com/NevaMind-AI/memU/issues/462)) ([6456c35](https://github.com/NevaMind-AI/memU/commit/6456c357b22039a3b12ba2f2bc0294a8693bceb5))
|
|
87
|
+
* Refine OpenClaw reference and feature descriptions ([#410](https://github.com/NevaMind-AI/memU/issues/410)) ([707b80e](https://github.com/NevaMind-AI/memU/commit/707b80e5f4394b8e4aafff1ef23fd331a8b557f8))
|
|
88
|
+
* refine README memory filesystem positioning ([#429](https://github.com/NevaMind-AI/memU/issues/429)) ([dda0374](https://github.com/NevaMind-AI/memU/commit/dda03743b007c0863c7fe7237592f7e4a0de32b6))
|
|
89
|
+
* refine README positioning around personal memory as files ([#455](https://github.com/NevaMind-AI/memU/issues/455)) ([88982d3](https://github.com/NevaMind-AI/memU/commit/88982d3d22640501be09ced1876520e95d956312))
|
|
90
|
+
* reframe README and description around personal-information memory ([#451](https://github.com/NevaMind-AI/memU/issues/451)) ([6b5b11c](https://github.com/NevaMind-AI/memU/commit/6b5b11c0787704c119b8d2e2d3c779bd56ee66fa))
|
|
91
|
+
* refresh memory diagrams ([#473](https://github.com/NevaMind-AI/memU/issues/473)) ([0d8770f](https://github.com/NevaMind-AI/memU/commit/0d8770f0c9d49f3a09e6ac33ca72b34c8128a855))
|
|
92
|
+
* retitle around file-based memory and trim README ([#453](https://github.com/NevaMind-AI/memU/issues/453)) ([2c1cc86](https://github.com/NevaMind-AI/memU/commit/2c1cc86ba66f31ffb7c6afcd0717f7e1880c0fd0))
|
|
93
|
+
* rewrite README — raw data → memory → agent ([#426](https://github.com/NevaMind-AI/memU/issues/426)) ([c2a2aac](https://github.com/NevaMind-AI/memU/commit/c2a2aac52b4424583955f85f5a35776e76beb68a))
|
|
94
|
+
* swap the tagline to lead with Across Agents ([#490](https://github.com/NevaMind-AI/memU/issues/490)) ([6e0fc06](https://github.com/NevaMind-AI/memU/commit/6e0fc068a1e3a2212dfea52f52438b438dae88f3))
|
|
95
|
+
* tagline across sessions/agents/devices, lowercase memU in banner alt ([#515](https://github.com/NevaMind-AI/memU/issues/515)) ([1f4f831](https://github.com/NevaMind-AI/memU/commit/1f4f8315bc0a68a6d2c2fa8018d64e7f22e5b164))
|
|
96
|
+
* tighten the README intro to two sentences ([#487](https://github.com/NevaMind-AI/memU/issues/487)) ([da160f2](https://github.com/NevaMind-AI/memU/commit/da160f2155439923bfe744ac770733c1c9824cd9))
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
### Miscellaneous Chores
|
|
100
|
+
|
|
101
|
+
* release 2.0.0-beta.0 ([#541](https://github.com/NevaMind-AI/memU/issues/541)) ([3dc60ce](https://github.com/NevaMind-AI/memU/commit/3dc60cea094e29f86ead2fad148ea0fbeab198c3))
|
|
102
|
+
|
|
3
103
|
## [1.5.1](https://github.com/NevaMind-AI/memU/compare/v1.5.0...v1.5.1) (2026-03-23)
|
|
4
104
|
|
|
5
105
|
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: install-memu-latest
|
|
3
|
+
description: Install the latest development build of memU-cli from git (main HEAD). Use when the user wants the newest unreleased code — clean any old install, install from git, verify, then set up.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Install the latest (development) memU
|
|
7
|
+
|
|
8
|
+
> **Audience: the agent.** A user pointed you here ("read this and install the
|
|
9
|
+
> latest memU"). Do the install yourself — the user should not run commands by
|
|
10
|
+
> hand. This installs memU-cli from **git `main`**, the latest source.
|
|
11
|
+
|
|
12
|
+
## Step 1 — remove any existing memU install
|
|
13
|
+
|
|
14
|
+
An older memU already on the machine can stay on `PATH` and **shadow the one you
|
|
15
|
+
are about to install**, so the version that actually runs would not be the
|
|
16
|
+
latest. Remove it first — try each installer, ignore "not installed":
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
uv tool uninstall memu-cli
|
|
20
|
+
pipx uninstall memu-cli
|
|
21
|
+
pip uninstall -y memu-cli
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Tell the user what you removed** — the name and version, or "no previous
|
|
25
|
+
install found" — so they know their old version is gone before you continue.
|
|
26
|
+
|
|
27
|
+
This removes only the memU **package** (the binaries). The store and
|
|
28
|
+
`~/.memu/config.env` live under `~/.memu/` and are **not** touched, so the
|
|
29
|
+
user's memories and settings carry straight over — Step 4 reuses the existing
|
|
30
|
+
`config.env` instead of asking again. (If this newer build needs a config value
|
|
31
|
+
the old file lacks, Step 4's `doctor` gate names exactly what to add.)
|
|
32
|
+
|
|
33
|
+
## Step 2 — install from git, persistently
|
|
34
|
+
|
|
35
|
+
The install **must persist on `PATH`**: the scheduled bridging task will call
|
|
36
|
+
these binaries later from a bare, non-interactive shell. So install as a durable
|
|
37
|
+
tool — **never** with an ephemeral runner (`uvx`, `npx`), which vanish after one
|
|
38
|
+
command and leave nothing for the task to find.
|
|
39
|
+
|
|
40
|
+
Requirement: `git` on `PATH`. Then take the first option that fits the machine:
|
|
41
|
+
|
|
42
|
+
- **uv (preferred — isolated, global, on `PATH`):**
|
|
43
|
+
```
|
|
44
|
+
uv tool install "git+https://github.com/NevaMind-AI/memU"
|
|
45
|
+
```
|
|
46
|
+
- **no uv, but you can install it:** install uv, then run the command above.
|
|
47
|
+
```
|
|
48
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
|
|
49
|
+
powershell -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
|
|
50
|
+
```
|
|
51
|
+
- **pip fallback (only into a stable, on-`PATH` environment):**
|
|
52
|
+
```
|
|
53
|
+
pip install "git+https://github.com/NevaMind-AI/memU"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
To pin an exact commit instead of the moving `main`, append `@<sha>` to the URL.
|
|
57
|
+
|
|
58
|
+
The installer prints the exact commit it resolved — with uv, a line like
|
|
59
|
+
`Building memu-cli @ git+…@<sha>`. Note that SHA; you confirm it to the user in
|
|
60
|
+
Step 3, before the setup.
|
|
61
|
+
|
|
62
|
+
## Step 3 — verify, then confirm the version with the user
|
|
63
|
+
|
|
64
|
+
From a **fresh** shell (not the one that ran the installer, whose `PATH` may be
|
|
65
|
+
stale):
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
memu --help
|
|
69
|
+
memu-<your-host> --help # e.g. memu-claude-code, memu-codex
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Both must print usage. If they do not, the install's bin directory is not on
|
|
73
|
+
`PATH` (with uv it is `~/.local/bin`) — fix that before continuing, since the
|
|
74
|
+
scheduled task depends on the same resolution.
|
|
75
|
+
|
|
76
|
+
Then confirm the version with the user — **before the setup below**, since setup
|
|
77
|
+
is the long part and a wrong or stale build is painful to discover afterward. A
|
|
78
|
+
bare SHA is hard to judge, so report what the commit actually **is**:
|
|
79
|
+
|
|
80
|
+
- the SHA (from Step 2),
|
|
81
|
+
- its **subject line and date**, and
|
|
82
|
+
- the link to inspect it: `https://github.com/NevaMind-AI/memU/commit/<sha>`.
|
|
83
|
+
|
|
84
|
+
Fetch the subject and date from the GitHub API — no clone needed:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
curl -s https://api.github.com/repos/NevaMind-AI/memU/commits/<sha>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
read `.commit.message` (first line) and `.commit.author.date`. Then offer a
|
|
91
|
+
**one-tap choice** — not an open question the user has to answer in a sentence.
|
|
92
|
+
If your host can render selectable options, present exactly these two; otherwise
|
|
93
|
+
accept a plain "yes":
|
|
94
|
+
|
|
95
|
+
- **Use this version** → continue straight into Step 4 and run it to completion
|
|
96
|
+
**yourself**; do not make the user run `docs install` or any setup command.
|
|
97
|
+
Pause again only if you genuinely need them (e.g. an embedding API key).
|
|
98
|
+
- **Pick a different commit** → ask which, reinstall it (Step 2 with `@<sha>`),
|
|
99
|
+
then confirm again here.
|
|
100
|
+
|
|
101
|
+
A bare "yes" / "ok" means **Use this version** — default to proceeding.
|
|
102
|
+
|
|
103
|
+
## Step 4 — set up memU
|
|
104
|
+
|
|
105
|
+
You now have the latest binaries. Identify **which agent you are** and use its
|
|
106
|
+
binary — memU has seven host adapters:
|
|
107
|
+
|
|
108
|
+
| You are | Your binary |
|
|
109
|
+
| --- | --- |
|
|
110
|
+
| Codex | `memu-codex` |
|
|
111
|
+
| Claude Code | `memu-claude-code` |
|
|
112
|
+
| Cursor | `memu-cursor` |
|
|
113
|
+
| OpenClaw | `memu-openclaw` |
|
|
114
|
+
| Hermes | `memu-hermes` |
|
|
115
|
+
| WorkBuddy | `memu-workbuddy` |
|
|
116
|
+
| anything else | `memu-agent` — run `memu-agent detect` if unsure |
|
|
117
|
+
|
|
118
|
+
Then print your host's packaged guide and follow it to the letter:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
memu-<your-host> docs install
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
It walks you through configuring the store in `~/.memu/config.env`, registering
|
|
125
|
+
the scheduled bridging task, and patching your instruction file, each behind a
|
|
126
|
+
verify gate.
|
|
127
|
+
|
|
128
|
+
Because the existing `config.env` is reused, also **check it against the settings
|
|
129
|
+
this build documents** (the guide lists them): if this version recognizes any
|
|
130
|
+
`MEMU_*` option the user's file does not set, tell the user its name and what it
|
|
131
|
+
does — that is configuration this newer build introduces. Optional ones keep
|
|
132
|
+
working on their defaults; a required one is caught by the `doctor` gate.
|
|
133
|
+
|
|
134
|
+
When done, report which seams (memorization / retrieval) are now active.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memu-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Classifier: Development Status :: 4 - Beta
|
|
5
5
|
Classifier: Intended Audience :: Developers
|
|
6
6
|
Classifier: Operating System :: OS Independent
|
|
@@ -26,7 +26,7 @@ Project-URL: Bug Tracker, https://github.com/NevaMind-AI/MemU/issues
|
|
|
26
26
|
Project-URL: Documentation, https://github.com/NevaMind-AI/MemU#readme
|
|
27
27
|
Project-URL: Homepage, https://github.com/NevaMind-AI/MemU
|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
31
|
<div align="center">
|
|
32
32
|
|
|
@@ -34,7 +34,7 @@ Project-URL: Homepage, https://github.com/NevaMind-AI/MemU
|
|
|
34
34
|
|
|
35
35
|
### Personal memory, stored as files
|
|
36
36
|
|
|
37
|
-
**Across
|
|
37
|
+
**Across Sessions. Across Agents. Across Devices.**
|
|
38
38
|
|
|
39
39
|
[](https://badge.fury.io/py/memu-cli)
|
|
40
40
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
@@ -54,7 +54,11 @@ memU is a 500-line memory system for AI agents. Agents write what's worth keepin
|
|
|
54
54
|
|
|
55
55
|
> Read https://raw.githubusercontent.com/NevaMind-AI/MemU/main/SKILL.md and follow it to install memU.
|
|
56
56
|
|
|
57
|
-
It works for Codex, Claude Code, Cursor, OpenClaw, Hermes — and any other agent, via detection. Details in [Host adapters](#host-adapters-memory-for-desktop-coding-agents).
|
|
57
|
+
It works for Codex, Claude Code, Cursor, OpenClaw, Hermes, WorkBuddy — and any other agent, via detection. Details in [Host adapters](#host-adapters-memory-for-desktop-coding-agents).
|
|
58
|
+
|
|
59
|
+
Want to follow the latest development instead? Install from the newest source (git `main`) — tell your agent:
|
|
60
|
+
|
|
61
|
+
> Read https://raw.githubusercontent.com/NevaMind-AI/MemU/main/INSTALL-LATEST.md and follow it to install the latest memU.
|
|
58
62
|
|
|
59
63
|
## Quick start
|
|
60
64
|
|
|
@@ -143,6 +147,7 @@ memU runs as a sidecar to a desktop agent (ADR 0008/0009/0010), one binary per h
|
|
|
143
147
|
| Cursor (Agent/CLI) | `memu-cursor` | `~/.cursor/projects/<project>/agent-transcripts/**.jsonl` | `./AGENTS.md` (per project) |
|
|
144
148
|
| OpenClaw | `memu-openclaw` | `~/.openclaw/agents/<agentId>/sessions/*.jsonl` | `~/.openclaw/workspace/AGENTS.md` |
|
|
145
149
|
| Hermes Agent | `memu-hermes` | `~/.hermes/state.db` (SQLite, read-only) | `~/.hermes/SOUL.md` |
|
|
150
|
+
| WorkBuddy | `memu-workbuddy` | `~/.workbuddy/projects/<project>/<session>.jsonl` | `~/.workbuddy/MEMORY.md` |
|
|
146
151
|
| **any other agent** | `memu-agent` | found by `memu-agent detect` (JSONL dialect sniffed) | found by `detect` (AGENTS.md / CLAUDE.md / SOUL.md / …) |
|
|
147
152
|
|
|
148
153
|
For agents without a dedicated binary, `memu-agent detect` probes the machine and reports per agent whether **memorization** works (a recognizable session log exists) and whether **retrieval** works (an instruction file exists to patch) — then the same verbs run against what it found.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
### Personal memory, stored as files
|
|
8
8
|
|
|
9
|
-
**Across
|
|
9
|
+
**Across Sessions. Across Agents. Across Devices.**
|
|
10
10
|
|
|
11
11
|
[](https://badge.fury.io/py/memu-cli)
|
|
12
12
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
@@ -26,7 +26,11 @@ memU is a 500-line memory system for AI agents. Agents write what's worth keepin
|
|
|
26
26
|
|
|
27
27
|
> Read https://raw.githubusercontent.com/NevaMind-AI/MemU/main/SKILL.md and follow it to install memU.
|
|
28
28
|
|
|
29
|
-
It works for Codex, Claude Code, Cursor, OpenClaw, Hermes — and any other agent, via detection. Details in [Host adapters](#host-adapters-memory-for-desktop-coding-agents).
|
|
29
|
+
It works for Codex, Claude Code, Cursor, OpenClaw, Hermes, WorkBuddy — and any other agent, via detection. Details in [Host adapters](#host-adapters-memory-for-desktop-coding-agents).
|
|
30
|
+
|
|
31
|
+
Want to follow the latest development instead? Install from the newest source (git `main`) — tell your agent:
|
|
32
|
+
|
|
33
|
+
> Read https://raw.githubusercontent.com/NevaMind-AI/MemU/main/INSTALL-LATEST.md and follow it to install the latest memU.
|
|
30
34
|
|
|
31
35
|
## Quick start
|
|
32
36
|
|
|
@@ -115,6 +119,7 @@ memU runs as a sidecar to a desktop agent (ADR 0008/0009/0010), one binary per h
|
|
|
115
119
|
| Cursor (Agent/CLI) | `memu-cursor` | `~/.cursor/projects/<project>/agent-transcripts/**.jsonl` | `./AGENTS.md` (per project) |
|
|
116
120
|
| OpenClaw | `memu-openclaw` | `~/.openclaw/agents/<agentId>/sessions/*.jsonl` | `~/.openclaw/workspace/AGENTS.md` |
|
|
117
121
|
| Hermes Agent | `memu-hermes` | `~/.hermes/state.db` (SQLite, read-only) | `~/.hermes/SOUL.md` |
|
|
122
|
+
| WorkBuddy | `memu-workbuddy` | `~/.workbuddy/projects/<project>/<session>.jsonl` | `~/.workbuddy/MEMORY.md` |
|
|
118
123
|
| **any other agent** | `memu-agent` | found by `memu-agent detect` (JSONL dialect sniffed) | found by `detect` (AGENTS.md / CLAUDE.md / SOUL.md / …) |
|
|
119
124
|
|
|
120
125
|
For agents without a dedicated binary, `memu-agent detect` probes the machine and reports per agent whether **memorization** works (a recognizable session log exists) and whether **retrieval** works (an instruction file exists to patch) — then the same verbs run against what it found.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: install-memu
|
|
3
|
-
description: Install memU for whatever agent you are — identify your host, print its packaged
|
|
3
|
+
description: Install or uninstall memU for whatever agent you are — identify your host, print its packaged guide, and follow it to wire (or unwire) both seams (record and inject). Use when the user asks to install, set up, integrate, remove, or uninstall memU.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Install memU
|
|
@@ -41,6 +41,7 @@ executing this skill):
|
|
|
41
41
|
| Cursor (Agent/CLI) | `memu-cursor` |
|
|
42
42
|
| OpenClaw | `memu-openclaw` |
|
|
43
43
|
| Hermes Agent | `memu-hermes` |
|
|
44
|
+
| WorkBuddy | `memu-workbuddy` |
|
|
44
45
|
| anything else | `memu-agent` |
|
|
45
46
|
|
|
46
47
|
Unsure, or not in the table? You are `memu-agent`. Run:
|
|
@@ -76,3 +77,21 @@ Two rules that hold for every host:
|
|
|
76
77
|
the instruction file patched). For `memu-agent`, the detect report decides
|
|
77
78
|
this; a retrieval-only integration is a valid outcome to report, not a
|
|
78
79
|
failure to hide.
|
|
80
|
+
|
|
81
|
+
## Uninstall
|
|
82
|
+
|
|
83
|
+
Same routing, in reverse. If the user asked to **uninstall** memU instead:
|
|
84
|
+
identify your binary exactly as in Step 2, then print and follow its removal
|
|
85
|
+
guide —
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
<your-binary> docs uninstall
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
It unregisters the bridging task, removes the instruction block
|
|
92
|
+
(`<your-binary> remove-instruction` — never hand-edit it out), then applies
|
|
93
|
+
the defaults: the user's memory — the shared store and `~/.memu/config.env` —
|
|
94
|
+
is **kept** (deleted only if they explicitly asked to erase it), while this
|
|
95
|
+
host's residue and, if no other host still uses it, the package are
|
|
96
|
+
**removed**. Close by reporting exactly those two things: what was kept, and
|
|
97
|
+
what was removed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "memu-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{name = "MemU Team", email = "contact@nevamind.ai"},
|
|
6
6
|
]
|
|
@@ -66,6 +66,7 @@ memu-claude-code = "memu.hosts.claude_code.cli:main"
|
|
|
66
66
|
memu-cursor = "memu.hosts.cursor.cli:main"
|
|
67
67
|
memu-openclaw = "memu.hosts.openclaw.cli:main"
|
|
68
68
|
memu-hermes = "memu.hosts.hermes.cli:main"
|
|
69
|
+
memu-workbuddy = "memu.hosts.workbuddy.cli:main"
|
|
69
70
|
# The generic adapter: any agent without a dedicated binary. `memu-agent
|
|
70
71
|
# detect` finds the session log and instruction file, then reports which of
|
|
71
72
|
# the two seams (memorization / retrieval) work for that agent.
|
|
@@ -13,6 +13,19 @@ if TYPE_CHECKING:
|
|
|
13
13
|
from memu.database.models import RecallFile, Resource
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
async def _embed_one(embed_client: Any, text: str) -> list[float]:
|
|
17
|
+
"""One text in, one vector out.
|
|
18
|
+
|
|
19
|
+
``embed`` returns ``(vectors, raw_response)`` — the raw response carries
|
|
20
|
+
provider usage metadata (see :class:`memu.embedding.base.EmbeddingClient`).
|
|
21
|
+
Every call site here wants just the vector; indexing the tuple with ``[0]``
|
|
22
|
+
would hand back the whole vectors list instead.
|
|
23
|
+
"""
|
|
24
|
+
vectors: list[list[float]]
|
|
25
|
+
vectors, _ = await embed_client.embed([text])
|
|
26
|
+
return vectors[0]
|
|
27
|
+
|
|
28
|
+
|
|
16
29
|
class AgenticMixin:
|
|
17
30
|
if TYPE_CHECKING:
|
|
18
31
|
_get_database: Callable[[], Database]
|
|
@@ -64,7 +77,7 @@ class AgenticMixin:
|
|
|
64
77
|
where_filters = self._normalize_where(where)
|
|
65
78
|
config = self.progressive_retrieve_config
|
|
66
79
|
embed_client = self._get_embedding_client("embedding")
|
|
67
|
-
query_vector =
|
|
80
|
+
query_vector = await _embed_one(embed_client, query)
|
|
68
81
|
|
|
69
82
|
segment_hits, segment_pool = self._recall_segments(
|
|
70
83
|
store=store, where_filters=where_filters, query_vector=query_vector, enabled=config.file.enabled
|
|
@@ -265,7 +278,7 @@ class AgenticMixin:
|
|
|
265
278
|
store.recall_file_resource_repo.unlink_resource(res.id)
|
|
266
279
|
store.resource_repo.delete_resource(res.id)
|
|
267
280
|
|
|
268
|
-
caption_embedding =
|
|
281
|
+
caption_embedding = await _embed_one(embed_client, caption) if caption else None
|
|
269
282
|
res = store.resource_repo.create_resource(
|
|
270
283
|
url=url,
|
|
271
284
|
local_path=url,
|
|
@@ -307,7 +320,7 @@ class AgenticMixin:
|
|
|
307
320
|
file = {f.name: f for f in existing.values()}.get(name)
|
|
308
321
|
if file is None:
|
|
309
322
|
emb_text = f"{name}: {description}" if description else name
|
|
310
|
-
embedding =
|
|
323
|
+
embedding = await _embed_one(embed_client, emb_text)
|
|
311
324
|
file = store.recall_file_repo.get_or_create_category(
|
|
312
325
|
name=name,
|
|
313
326
|
description=description,
|
|
@@ -372,7 +385,7 @@ class AgenticMixin:
|
|
|
372
385
|
to_add = [text for text in new_texts if text not in existing_texts]
|
|
373
386
|
if not to_add:
|
|
374
387
|
return
|
|
375
|
-
vecs = await embed_client.embed(to_add)
|
|
388
|
+
vecs, _ = await embed_client.embed(to_add)
|
|
376
389
|
for text, vec in zip(to_add, vecs, strict=True):
|
|
377
390
|
store.recall_file_segment_repo.create_segment(
|
|
378
391
|
recall_file_id=file.id, track=file_track, text=text, embedding=vec, user_data=dict(user_scope)
|
|
@@ -167,6 +167,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
167
167
|
|
|
168
168
|
|
|
169
169
|
def main(argv: list[str] | None = None) -> int:
|
|
170
|
+
# Piped stdio on Windows falls back to the ANSI code page (gbk, cp1252, …),
|
|
171
|
+
# which cannot encode retrieved memory content printed raw (ensure_ascii=False)
|
|
172
|
+
# — and agents read every command through a pipe. Force UTF-8; on UTF-8 stdio
|
|
173
|
+
# it's a no-op.
|
|
174
|
+
for stream in (sys.stdout, sys.stderr):
|
|
175
|
+
reconfigure = getattr(stream, "reconfigure", None)
|
|
176
|
+
if reconfigure is not None:
|
|
177
|
+
reconfigure(encoding="utf-8", errors="replace")
|
|
170
178
|
args = build_parser().parse_args(argv)
|
|
171
179
|
handler: Callable[[argparse.Namespace], Coroutine[Any, Any, int]] = args.handler
|
|
172
180
|
try:
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import ipaddress
|
|
3
4
|
import logging
|
|
4
5
|
import os
|
|
6
|
+
import urllib.parse
|
|
5
7
|
from collections.abc import Callable
|
|
6
8
|
from typing import Any, Literal
|
|
7
9
|
|
|
@@ -15,8 +17,52 @@ from memu.embedding.backends.openrouter import OpenRouterEmbeddingBackend
|
|
|
15
17
|
from memu.embedding.backends.voyage import VoyageEmbeddingBackend
|
|
16
18
|
|
|
17
19
|
|
|
18
|
-
def
|
|
19
|
-
|
|
20
|
+
def is_loopback_url(url: str) -> bool:
|
|
21
|
+
"""True when ``url`` targets the local machine (``localhost``, ``127.x``, ``::1``).
|
|
22
|
+
|
|
23
|
+
A request to the machine itself must never be routed through a proxy: the
|
|
24
|
+
proxy sits on another host, where "localhost" means the proxy, not the
|
|
25
|
+
caller. Sandboxed hosts that force all traffic through a proxy (Codex's
|
|
26
|
+
sandbox, corporate CI) would otherwise turn every local-embedding-server
|
|
27
|
+
call into a 502 unless the user hand-writes a ``NO_PROXY`` exemption.
|
|
28
|
+
"""
|
|
29
|
+
host = urllib.parse.urlsplit(url).hostname or ""
|
|
30
|
+
if host == "localhost" or host.endswith(".localhost"):
|
|
31
|
+
return True
|
|
32
|
+
try:
|
|
33
|
+
return ipaddress.ip_address(host).is_loopback
|
|
34
|
+
except ValueError:
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def proxy_bypass_mounts(url: str) -> dict[str, httpx.AsyncBaseTransport | None] | None:
|
|
39
|
+
"""httpx ``mounts`` that exempt a loopback target from env proxies, else ``None``.
|
|
40
|
+
|
|
41
|
+
httpx gives scheme-specific env-proxy mounts (``HTTP_PROXY`` mounts on
|
|
42
|
+
``http://``) priority over a generic ``all://`` unmount, so the bypass must
|
|
43
|
+
be *host*-specific — more specific than any env mount. Unmounting (rather
|
|
44
|
+
than ``trust_env=False``) keeps the rest of the environment —
|
|
45
|
+
``SSL_CERT_FILE``, ``.netrc``, the user's own ``NO_PROXY`` — working.
|
|
46
|
+
"""
|
|
47
|
+
if not is_loopback_url(url):
|
|
48
|
+
return None
|
|
49
|
+
host = urllib.parse.urlsplit(url).hostname or ""
|
|
50
|
+
if ":" in host: # IPv6 literal needs its brackets back
|
|
51
|
+
host = f"[{host}]"
|
|
52
|
+
return {f"all://{host}": None}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _load_proxy(base_url: str) -> str | None:
|
|
56
|
+
from memu.env import env as memu_env
|
|
57
|
+
|
|
58
|
+
explicit = memu_env("MEMU_HTTP_PROXY") or None
|
|
59
|
+
if is_loopback_url(base_url):
|
|
60
|
+
# Ambient proxies (HTTP_PROXY, HTTPS_PROXY) are aimed at the network at
|
|
61
|
+
# large, never at the machine itself. An explicit MEMU_HTTP_PROXY is
|
|
62
|
+
# different — it states intent about memU's own traffic (e.g. capturing
|
|
63
|
+
# it with a local debugging proxy) — so it still wins.
|
|
64
|
+
return explicit
|
|
65
|
+
return explicit or os.getenv("HTTP_PROXY") or os.getenv("HTTPS_PROXY") or None
|
|
20
66
|
|
|
21
67
|
|
|
22
68
|
logger = logging.getLogger(__name__)
|
|
@@ -63,7 +109,12 @@ class HTTPEmbeddingClient:
|
|
|
63
109
|
# Strip leading "/" so httpx resolves relative to base_url
|
|
64
110
|
self.embedding_endpoint = raw_embedding_ep.lstrip("/")
|
|
65
111
|
self.timeout = timeout
|
|
66
|
-
self.proxy = _load_proxy()
|
|
112
|
+
self.proxy = _load_proxy(self.base_url)
|
|
113
|
+
# httpx falls back to env proxies even when proxy=None, so a loopback
|
|
114
|
+
# target explicitly unmounts them (host-specifically — see
|
|
115
|
+
# proxy_bypass_mounts). An explicit MEMU_HTTP_PROXY means self.proxy is
|
|
116
|
+
# set and no bypass applies.
|
|
117
|
+
self.mounts = proxy_bypass_mounts(self.base_url) if self.proxy is None else None
|
|
67
118
|
|
|
68
119
|
async def embed(self, inputs: list[str]) -> tuple[list[list[float]], dict[str, Any]]:
|
|
69
120
|
"""
|
|
@@ -78,7 +129,9 @@ class HTTPEmbeddingClient:
|
|
|
78
129
|
track token consumption.
|
|
79
130
|
"""
|
|
80
131
|
payload = self.backend.build_embedding_payload(inputs=inputs, embed_model=self.embed_model)
|
|
81
|
-
async with httpx.AsyncClient(
|
|
132
|
+
async with httpx.AsyncClient(
|
|
133
|
+
base_url=self.base_url, timeout=self.timeout, proxy=self.proxy, mounts=self.mounts
|
|
134
|
+
) as client:
|
|
82
135
|
resp = await client.post(self.embedding_endpoint, json=payload, headers=self._headers())
|
|
83
136
|
resp.raise_for_status()
|
|
84
137
|
data = resp.json()
|
|
@@ -140,7 +193,9 @@ class HTTPEmbeddingClient:
|
|
|
140
193
|
)
|
|
141
194
|
|
|
142
195
|
endpoint = self.backend.multimodal_embedding_endpoint.lstrip("/")
|
|
143
|
-
async with httpx.AsyncClient(
|
|
196
|
+
async with httpx.AsyncClient(
|
|
197
|
+
base_url=self.base_url, timeout=self.timeout, proxy=self.proxy, mounts=self.mounts
|
|
198
|
+
) as client:
|
|
144
199
|
resp = await client.post(endpoint, json=payload, headers=self._headers())
|
|
145
200
|
resp.raise_for_status()
|
|
146
201
|
data = resp.json()
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import cast
|
|
3
3
|
|
|
4
|
-
from openai import AsyncOpenAI
|
|
4
|
+
from openai import AsyncOpenAI, DefaultAsyncHttpxClient
|
|
5
5
|
from openai.types import CreateEmbeddingResponse
|
|
6
6
|
|
|
7
|
+
from memu.embedding.http_client import proxy_bypass_mounts
|
|
8
|
+
from memu.env import env as memu_env
|
|
9
|
+
|
|
7
10
|
logger = logging.getLogger(__name__)
|
|
8
11
|
|
|
9
12
|
|
|
@@ -15,7 +18,23 @@ class OpenAIEmbeddingSDKClient:
|
|
|
15
18
|
self.api_key = api_key or ""
|
|
16
19
|
self.embed_model = embed_model
|
|
17
20
|
self.batch_size = batch_size
|
|
18
|
-
|
|
21
|
+
# The SDK's default transport trusts env proxies; a loopback target
|
|
22
|
+
# (local Ollama & co.) must bypass them — the proxy is on another host,
|
|
23
|
+
# where "localhost" no longer means the caller. Unmounting the target
|
|
24
|
+
# host (rather than trust_env=False) keeps SSL_CERT_FILE/.netrc
|
|
25
|
+
# working, and DefaultAsyncHttpxClient (rather than a bare httpx
|
|
26
|
+
# client) keeps the SDK's own timeouts, limits, and lifecycle. An
|
|
27
|
+
# explicit MEMU_HTTP_PROXY states intent about memU's own traffic, so
|
|
28
|
+
# it is wired into the transport for real — the same semantics as
|
|
29
|
+
# HTTPEmbeddingClient — and beats both the bypass and ambient proxies.
|
|
30
|
+
explicit_proxy = memu_env("MEMU_HTTP_PROXY") or None
|
|
31
|
+
http_client: DefaultAsyncHttpxClient | None
|
|
32
|
+
if explicit_proxy:
|
|
33
|
+
http_client = DefaultAsyncHttpxClient(proxy=explicit_proxy)
|
|
34
|
+
else:
|
|
35
|
+
mounts = proxy_bypass_mounts(self.base_url)
|
|
36
|
+
http_client = DefaultAsyncHttpxClient(mounts=mounts) if mounts else None
|
|
37
|
+
self.client = AsyncOpenAI(api_key=self.api_key, base_url=self.base_url, http_client=http_client)
|
|
19
38
|
|
|
20
39
|
async def embed(self, inputs: list[str]) -> tuple[list[list[float]], CreateEmbeddingResponse | None]:
|
|
21
40
|
"""
|