memu-cli 0.1.0__tar.gz → 0.2.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.1.0 → memu_cli-0.2.0}/.github/workflows/build.yml +1 -1
- memu_cli-0.2.0/.github/workflows/publish-memu-cli.yml +167 -0
- memu_cli-0.2.0/AGENTS.md +77 -0
- memu_cli-0.2.0/PKG-INFO +216 -0
- memu_cli-0.2.0/README.md +187 -0
- memu_cli-0.2.0/assets/structure-v2.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/sqlite.md +16 -16
- memu_cli-0.2.0/npm/README.md +54 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/npm/bin/memu.js +10 -9
- {memu_cli-0.1.0 → memu_cli-0.2.0}/npm/package.json +2 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/pyproject.toml +1 -31
- memu_cli-0.2.0/src/memu/app/__init__.py +19 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/app/agentic.py +32 -47
- memu_cli-0.2.0/src/memu/app/service.py +95 -0
- memu_cli-0.2.0/src/memu/app/settings.py +168 -0
- memu_cli-0.2.0/src/memu/cli.py +184 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/__init__.py +0 -8
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/__init__.py +0 -4
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/models.py +0 -18
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repo.py +0 -16
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/__init__.py +0 -9
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/resource_repo.py +0 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/vector.py +3 -3
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/interfaces.py +0 -10
- memu_cli-0.2.0/src/memu/database/models.py +110 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/__init__.py +0 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/migrations/versions/20260703_0001_initial_schema.py +0 -43
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/models.py +2 -29
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/postgres.py +0 -33
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/__init__.py +0 -4
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/resource_repo.py +0 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/schema.py +0 -18
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/repositories/__init__.py +0 -4
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/repositories/resource.py +0 -1
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/models.py +0 -28
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/__init__.py +0 -4
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/resource_repo.py +0 -6
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/schema.py +0 -18
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/sqlite.py +0 -38
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/state.py +0 -4
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/__init__.py +1 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/base.py +1 -1
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/base.py +3 -5
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/defaults.py +8 -7
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/gateway.py +3 -23
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/env.py +14 -15
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/__init__.py +3 -6
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/codex/INSTALL.md +3 -3
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/codex/cli.py +2 -2
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/instruction.py +2 -3
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/retrieval.py +4 -6
- memu_cli-0.2.0/src/memu/vector.py +64 -0
- memu_cli-0.2.0/tests/test_agentic.py +116 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/test_cli.py +7 -21
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/test_embedding.py +5 -37
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/test_vector.py +1 -10
- memu_cli-0.2.0/uv.lock +1069 -0
- memu_cli-0.1.0/.claude/skills/memu/SKILL.md +0 -46
- memu_cli-0.1.0/AGENTS.md +0 -165
- memu_cli-0.1.0/PKG-INFO +0 -507
- memu_cli-0.1.0/README.md +0 -466
- memu_cli-0.1.0/docs/HACKATHON_ISSUE_DRAFT.md +0 -68
- memu_cli-0.1.0/docs/HACKATHON_MAD_COMBOS.md +0 -659
- memu_cli-0.1.0/docs/architecture.md +0 -392
- memu_cli-0.1.0/docs/integrations/grok.md +0 -53
- memu_cli-0.1.0/docs/langgraph_integration.md +0 -97
- memu_cli-0.1.0/docs/providers/grok.md +0 -70
- memu_cli-0.1.0/docs/sealos-devbox-guide.md +0 -410
- memu_cli-0.1.0/docs/sealos_use_case.md +0 -54
- memu_cli-0.1.0/docs/tutorials/getting_started.md +0 -181
- memu_cli-0.1.0/examples/example_1_conversation_memory.py +0 -117
- memu_cli-0.1.0/examples/example_2_skill_extraction.py +0 -274
- memu_cli-0.1.0/examples/example_3_multimodal_memory.py +0 -137
- memu_cli-0.1.0/examples/example_4_openrouter_memory.py +0 -112
- memu_cli-0.1.0/examples/example_5_with_lazyllm_client.py +0 -250
- memu_cli-0.1.0/examples/example_6_preprocess_modalities.py +0 -140
- memu_cli-0.1.0/examples/getting_started_robust.py +0 -107
- memu_cli-0.1.0/examples/langgraph_demo.py +0 -76
- memu_cli-0.1.0/examples/output/conversation_example/activities.md +0 -9
- memu_cli-0.1.0/examples/output/conversation_example/experiences.md +0 -5
- memu_cli-0.1.0/examples/output/conversation_example/goals.md +0 -17
- memu_cli-0.1.0/examples/output/conversation_example/habits.md +0 -13
- memu_cli-0.1.0/examples/output/conversation_example/knowledge.md +0 -29
- memu_cli-0.1.0/examples/output/conversation_example/opinions.md +0 -1
- memu_cli-0.1.0/examples/output/conversation_example/personal_info.md +0 -3
- memu_cli-0.1.0/examples/output/conversation_example/preferences.md +0 -6
- memu_cli-0.1.0/examples/output/conversation_example/relationships.md +0 -3
- memu_cli-0.1.0/examples/output/conversation_example/work_life.md +0 -12
- memu_cli-0.1.0/examples/proactive/memory/config.py +0 -66
- memu_cli-0.1.0/examples/proactive/memory/local/common.py +0 -31
- memu_cli-0.1.0/examples/proactive/memory/local/memorize.py +0 -38
- memu_cli-0.1.0/examples/proactive/memory/local/tools.py +0 -42
- memu_cli-0.1.0/examples/proactive/memory/platform/__init__.py +0 -0
- memu_cli-0.1.0/examples/proactive/memory/platform/memorize.py +0 -31
- memu_cli-0.1.0/examples/proactive/memory/platform/tools.py +0 -52
- memu_cli-0.1.0/examples/proactive/proactive.py +0 -198
- memu_cli-0.1.0/examples/resources/audio/audio_intro.mp3 +0 -0
- memu_cli-0.1.0/examples/resources/conversations/conv1.json +0 -54
- memu_cli-0.1.0/examples/resources/conversations/conv2.json +0 -67
- memu_cli-0.1.0/examples/resources/conversations/conv3.json +0 -67
- memu_cli-0.1.0/examples/resources/docs/doc1.txt +0 -330
- memu_cli-0.1.0/examples/resources/docs/doc2.txt +0 -433
- memu_cli-0.1.0/examples/resources/docs/doc_sample.pdf +0 -0
- memu_cli-0.1.0/examples/resources/images/image1.png +0 -0
- memu_cli-0.1.0/examples/resources/logs/log1.txt +0 -212
- memu_cli-0.1.0/examples/resources/logs/log2.txt +0 -226
- memu_cli-0.1.0/examples/resources/logs/log3.txt +0 -374
- memu_cli-0.1.0/examples/resources/video/video_test.mp4 +0 -0
- memu_cli-0.1.0/examples/sealos-assistant/README.md +0 -66
- memu_cli-0.1.0/examples/sealos-assistant/entrypoint.sh +0 -13
- memu_cli-0.1.0/examples/sealos-assistant/main.py +0 -286
- memu_cli-0.1.0/examples/sealos-assistant/requirements.txt +0 -4
- memu_cli-0.1.0/examples/sealos_support_agent.py +0 -70
- memu_cli-0.1.0/examples/test_nebius_provider.py +0 -228
- memu_cli-0.1.0/npm/README.md +0 -32
- memu_cli-0.1.0/readme/README_en.md +0 -542
- memu_cli-0.1.0/readme/README_es.md +0 -542
- memu_cli-0.1.0/readme/README_fr.md +0 -542
- memu_cli-0.1.0/readme/README_ja.md +0 -542
- memu_cli-0.1.0/readme/README_ko.md +0 -542
- memu_cli-0.1.0/readme/README_zh.md +0 -542
- memu_cli-0.1.0/src/memu/app/__init__.py +0 -37
- memu_cli-0.1.0/src/memu/app/crud.py +0 -792
- memu_cli-0.1.0/src/memu/app/memorize.py +0 -1210
- memu_cli-0.1.0/src/memu/app/memorize_workspace.py +0 -834
- memu_cli-0.1.0/src/memu/app/memory_files.py +0 -101
- memu_cli-0.1.0/src/memu/app/retrieve.py +0 -1427
- memu_cli-0.1.0/src/memu/app/retrieve_workspace.py +0 -276
- memu_cli-0.1.0/src/memu/app/service.py +0 -495
- memu_cli-0.1.0/src/memu/app/settings.py +0 -594
- memu_cli-0.1.0/src/memu/blob/__init__.py +0 -0
- memu_cli-0.1.0/src/memu/blob/document_text.py +0 -65
- memu_cli-0.1.0/src/memu/blob/folder.py +0 -185
- memu_cli-0.1.0/src/memu/blob/local_fs.py +0 -97
- memu_cli-0.1.0/src/memu/cli.py +0 -246
- memu_cli-0.1.0/src/memu/database/inmemory/repositories/recall_entry_repo.py +0 -263
- memu_cli-0.1.0/src/memu/database/inmemory/repositories/recall_file_entry_repo.py +0 -65
- memu_cli-0.1.0/src/memu/database/models.py +0 -197
- memu_cli-0.1.0/src/memu/database/postgres/repositories/recall_entry_repo.py +0 -401
- memu_cli-0.1.0/src/memu/database/postgres/repositories/recall_file_entry_repo.py +0 -145
- memu_cli-0.1.0/src/memu/database/repositories/recall_entry.py +0 -60
- memu_cli-0.1.0/src/memu/database/repositories/recall_file_entry.py +0 -31
- memu_cli-0.1.0/src/memu/database/sqlite/repositories/recall_entry_repo.py +0 -544
- memu_cli-0.1.0/src/memu/database/sqlite/repositories/recall_file_entry_repo.py +0 -211
- memu_cli-0.1.0/src/memu/integrations/__init__.py +0 -3
- memu_cli-0.1.0/src/memu/integrations/langgraph.py +0 -163
- memu_cli-0.1.0/src/memu/llm/anthropic_client.py +0 -149
- memu_cli-0.1.0/src/memu/llm/backends/__init__.py +0 -21
- memu_cli-0.1.0/src/memu/llm/backends/base.py +0 -43
- memu_cli-0.1.0/src/memu/llm/backends/claude.py +0 -84
- memu_cli-0.1.0/src/memu/llm/backends/deepseek.py +0 -14
- memu_cli-0.1.0/src/memu/llm/backends/doubao.py +0 -69
- memu_cli-0.1.0/src/memu/llm/backends/grok.py +0 -11
- memu_cli-0.1.0/src/memu/llm/backends/kimi.py +0 -14
- memu_cli-0.1.0/src/memu/llm/backends/minimax.py +0 -14
- memu_cli-0.1.0/src/memu/llm/backends/openai.py +0 -70
- memu_cli-0.1.0/src/memu/llm/backends/openrouter.py +0 -70
- memu_cli-0.1.0/src/memu/llm/gateway.py +0 -90
- memu_cli-0.1.0/src/memu/llm/http_client.py +0 -232
- memu_cli-0.1.0/src/memu/llm/lazyllm_client.py +0 -159
- memu_cli-0.1.0/src/memu/llm/openai_client.py +0 -202
- memu_cli-0.1.0/src/memu/llm/wrapper.py +0 -804
- memu_cli-0.1.0/src/memu/memory_fs/__init__.py +0 -23
- memu_cli-0.1.0/src/memu/memory_fs/exporter.py +0 -489
- memu_cli-0.1.0/src/memu/memory_fs/synthesizer.py +0 -115
- memu_cli-0.1.0/src/memu/preprocess/__init__.py +0 -99
- memu_cli-0.1.0/src/memu/preprocess/audio.py +0 -83
- memu_cli-0.1.0/src/memu/preprocess/base.py +0 -84
- memu_cli-0.1.0/src/memu/preprocess/conversation.py +0 -42
- memu_cli-0.1.0/src/memu/preprocess/document.py +0 -36
- memu_cli-0.1.0/src/memu/preprocess/image.py +0 -34
- memu_cli-0.1.0/src/memu/preprocess/video.py +0 -60
- memu_cli-0.1.0/src/memu/prompts/__init__.py +0 -13
- memu_cli-0.1.0/src/memu/prompts/category_patch/__init__.py +0 -7
- memu_cli-0.1.0/src/memu/prompts/category_patch/category.py +0 -45
- memu_cli-0.1.0/src/memu/prompts/category_summary/__init__.py +0 -22
- memu_cli-0.1.0/src/memu/prompts/category_summary/category.py +0 -296
- memu_cli-0.1.0/src/memu/prompts/category_summary/category_with_refs.py +0 -140
- memu_cli-0.1.0/src/memu/prompts/memory_fs/__init__.py +0 -213
- memu_cli-0.1.0/src/memu/prompts/memory_type/__init__.py +0 -46
- memu_cli-0.1.0/src/memu/prompts/memory_type/behavior.py +0 -176
- memu_cli-0.1.0/src/memu/prompts/memory_type/event.py +0 -182
- memu_cli-0.1.0/src/memu/prompts/memory_type/knowledge.py +0 -172
- memu_cli-0.1.0/src/memu/prompts/memory_type/profile.py +0 -190
- memu_cli-0.1.0/src/memu/prompts/memory_type/skill.py +0 -580
- memu_cli-0.1.0/src/memu/prompts/memory_type/tool.py +0 -120
- memu_cli-0.1.0/src/memu/prompts/preprocess/__init__.py +0 -11
- memu_cli-0.1.0/src/memu/prompts/preprocess/audio.py +0 -62
- memu_cli-0.1.0/src/memu/prompts/preprocess/conversation.py +0 -43
- memu_cli-0.1.0/src/memu/prompts/preprocess/document.py +0 -35
- memu_cli-0.1.0/src/memu/prompts/preprocess/image.py +0 -34
- memu_cli-0.1.0/src/memu/prompts/preprocess/video.py +0 -35
- memu_cli-0.1.0/src/memu/prompts/retrieve/__init__.py +0 -0
- memu_cli-0.1.0/src/memu/prompts/retrieve/judger.py +0 -39
- memu_cli-0.1.0/src/memu/prompts/retrieve/llm_category_ranker.py +0 -35
- memu_cli-0.1.0/src/memu/prompts/retrieve/llm_item_ranker.py +0 -40
- memu_cli-0.1.0/src/memu/prompts/retrieve/llm_resource_ranker.py +0 -40
- memu_cli-0.1.0/src/memu/prompts/retrieve/pre_retrieval_decision.py +0 -53
- memu_cli-0.1.0/src/memu/prompts/retrieve/query_rewriter.py +0 -44
- memu_cli-0.1.0/src/memu/prompts/retrieve/query_rewriter_judger.py +0 -48
- memu_cli-0.1.0/src/memu/utils/__init__.py +0 -5
- memu_cli-0.1.0/src/memu/utils/conversation.py +0 -89
- memu_cli-0.1.0/src/memu/utils/references.py +0 -172
- memu_cli-0.1.0/src/memu/utils/tool.py +0 -102
- memu_cli-0.1.0/src/memu/utils/video.py +0 -271
- memu_cli-0.1.0/src/memu/vector.py +0 -145
- memu_cli-0.1.0/src/memu/vlm/__init__.py +0 -24
- memu_cli-0.1.0/src/memu/vlm/anthropic_client.py +0 -80
- memu_cli-0.1.0/src/memu/vlm/backends/__init__.py +0 -19
- memu_cli-0.1.0/src/memu/vlm/backends/base.py +0 -65
- memu_cli-0.1.0/src/memu/vlm/backends/claude.py +0 -69
- memu_cli-0.1.0/src/memu/vlm/backends/doubao.py +0 -10
- memu_cli-0.1.0/src/memu/vlm/backends/grok.py +0 -9
- memu_cli-0.1.0/src/memu/vlm/backends/kimi.py +0 -9
- memu_cli-0.1.0/src/memu/vlm/backends/minimax.py +0 -10
- memu_cli-0.1.0/src/memu/vlm/backends/openai.py +0 -79
- memu_cli-0.1.0/src/memu/vlm/backends/openrouter.py +0 -19
- memu_cli-0.1.0/src/memu/vlm/base.py +0 -84
- memu_cli-0.1.0/src/memu/vlm/defaults.py +0 -30
- memu_cli-0.1.0/src/memu/vlm/gateway.py +0 -71
- memu_cli-0.1.0/src/memu/vlm/http_client.py +0 -142
- memu_cli-0.1.0/src/memu/vlm/openai_client.py +0 -76
- memu_cli-0.1.0/src/memu/workflow/__init__.py +0 -29
- memu_cli-0.1.0/src/memu/workflow/interceptor.py +0 -218
- memu_cli-0.1.0/src/memu/workflow/pipeline.py +0 -170
- memu_cli-0.1.0/src/memu/workflow/runner.py +0 -81
- memu_cli-0.1.0/src/memu/workflow/step.py +0 -101
- memu_cli-0.1.0/tests/__init__.py +0 -0
- memu_cli-0.1.0/tests/example/example_conversation.json +0 -704
- memu_cli-0.1.0/tests/integrations/test_langgraph.py +0 -80
- memu_cli-0.1.0/tests/llm/test_grok_provider.py +0 -45
- memu_cli-0.1.0/tests/test_audio_preprocess.py +0 -96
- memu_cli-0.1.0/tests/test_backend_conformance.py +0 -376
- memu_cli-0.1.0/tests/test_conversation_preprocess.py +0 -60
- memu_cli-0.1.0/tests/test_document_text.py +0 -101
- memu_cli-0.1.0/tests/test_folder_memorize.py +0 -295
- memu_cli-0.1.0/tests/test_inmemory.py +0 -89
- memu_cli-0.1.0/tests/test_lazyllm.py +0 -97
- memu_cli-0.1.0/tests/test_memory_files.py +0 -164
- memu_cli-0.1.0/tests/test_memory_fs_synthesis.py +0 -256
- memu_cli-0.1.0/tests/test_openai_max_tokens.py +0 -76
- memu_cli-0.1.0/tests/test_openrouter.py +0 -161
- memu_cli-0.1.0/tests/test_postgres.py +0 -82
- memu_cli-0.1.0/tests/test_references.py +0 -191
- memu_cli-0.1.0/tests/test_salience.py +0 -209
- memu_cli-0.1.0/tests/test_skill_track.py +0 -247
- memu_cli-0.1.0/tests/test_sqlite.py +0 -90
- memu_cli-0.1.0/tests/test_tool_memory.py +0 -327
- memu_cli-0.1.0/tests/test_vlm_preprocess.py +0 -217
- memu_cli-0.1.0/tests/utils/test_conversation.py +0 -91
- memu_cli-0.1.0/uv.lock +0 -2912
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/ISSUE_TEMPLATE/hackathon_task.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/ISSUE_TEMPLATE/improvement_suggestion.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/workflows/pr-title.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.github/workflows/release-please.yml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.gitignore +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.pre-commit-config.yaml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/.python-version +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/CHANGELOG.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/CONTRIBUTING.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/Cargo.lock +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/Cargo.toml +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/LICENSE.txt +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/MANIFEST.in +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/Makefile +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/banner.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/benchmark.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/memUbot.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/memorize.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/Clawdchat.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/LazyLLM.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/buddie.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/bytebase.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/jazz.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/openagents.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/partners/xroute.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/qrcode.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/retrieve.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/star.gif +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/structure.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_companion-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_creation-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_edu-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_ip-0000.png +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_robot-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_role_play-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/assets/usecase/ai_therapy-0000.jpg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0001-workflow-pipeline-architecture.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0002-pluggable-storage-and-vector-strategy.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0003-user-scope-in-data-model.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0004-workspace-memorize-and-memory-file-system.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0005-dedicated-embedding-package.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0006-from-memory-item-category-to-tracked-workspace-memorization.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0007-three-independent-memory-lines-wiki-graph.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0008-two-integration-surfaces-hooks-and-api.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/0009-codex-packaging-cli-and-config.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/docs/adr/README.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/scripts/db.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/setup.cfg +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/lib.rs +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/__main__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/_core.pyi +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/app/client_pool.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/factory.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/filter.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/inmemory/state.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/migration.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/migrations/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/migrations/env.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/migrations/script.py.mako +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/base.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/postgres/session.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/repositories/recall_file.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/repositories/recall_file_resource.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/repositories/recall_file_segment.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/base.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/recall_file_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/recall_file_resource_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/repositories/recall_file_segment_repo.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/database/sqlite/session.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/doubao.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/jina.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/openai.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/openrouter.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/backends/voyage.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/http_client.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/embedding/openai_sdk.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/base.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/instructions.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/layout.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/manifest.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/pipeline.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/recall_files.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/resources.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/bridging/transcripts.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/codex/BRIDGING_TASK.md +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/codex/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/src/memu/hosts/codex/sessions.py +0 -0
- {memu_cli-0.1.0/examples/proactive/memory/local → memu_cli-0.2.0/tests}/__init__.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/rust_entry_test.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/test_host_instruction.py +0 -0
- {memu_cli-0.1.0 → memu_cli-0.2.0}/tests/test_postgres_migration_config.py +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Publishes the engine snapshot to PyPI under the distribution name `memu-cli`.
|
|
2
|
+
#
|
|
3
|
+
# `memu-cli` is the CLI release channel: it ships the same `memu` module and
|
|
4
|
+
# entry points as `memu-py`, but versions independently of the release-please
|
|
5
|
+
# train so the npm launcher and docs can point at a stable install target.
|
|
6
|
+
# The rename happens at build time only — pyproject.toml in the repo always
|
|
7
|
+
# says `memu-py`.
|
|
8
|
+
#
|
|
9
|
+
# First-time setup: add a trusted publisher on PyPI for project `memu-cli`
|
|
10
|
+
# (workflow: publish-memu-cli.yml, environment: pypi).
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
inputs:
|
|
15
|
+
version:
|
|
16
|
+
description: "memu-cli version to publish (independent of memu-py, e.g. 0.1.1)"
|
|
17
|
+
required: true
|
|
18
|
+
type: string
|
|
19
|
+
|
|
20
|
+
name: publish-memu-cli
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build-wheels:
|
|
24
|
+
name: build wheels (${{ matrix.label }})
|
|
25
|
+
runs-on: ${{ matrix.os }}
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
include:
|
|
30
|
+
- os: ubuntu-latest
|
|
31
|
+
label: linux-x86_64
|
|
32
|
+
target: x86_64-unknown-linux-gnu
|
|
33
|
+
extra-args: "--compatibility manylinux_2_39"
|
|
34
|
+
python-version: "3.13"
|
|
35
|
+
- os: ubuntu-latest
|
|
36
|
+
label: linux-aarch64
|
|
37
|
+
target: aarch64-unknown-linux-gnu
|
|
38
|
+
extra-args: "--compatibility manylinux_2_39"
|
|
39
|
+
python-version: "3.13"
|
|
40
|
+
- os: macos-15-intel
|
|
41
|
+
label: macos-x86_64
|
|
42
|
+
target: ""
|
|
43
|
+
extra-args: ""
|
|
44
|
+
python-version: "3.13"
|
|
45
|
+
- os: macos-latest
|
|
46
|
+
label: macos-aarch64
|
|
47
|
+
target: ""
|
|
48
|
+
extra-args: ""
|
|
49
|
+
python-version: "3.13"
|
|
50
|
+
- os: windows-latest
|
|
51
|
+
label: windows-x86_64
|
|
52
|
+
target: ""
|
|
53
|
+
extra-args: ""
|
|
54
|
+
python-version: "3.13"
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v6
|
|
57
|
+
|
|
58
|
+
# No $ anchors: Windows runners check out with CRLF line endings,
|
|
59
|
+
# where a trailing \r sits between the closing quote and the newline.
|
|
60
|
+
- name: Rename distribution to memu-cli
|
|
61
|
+
shell: bash
|
|
62
|
+
run: |
|
|
63
|
+
perl -pi -e 's/^name = "memu-py"/name = "memu-cli"/' pyproject.toml
|
|
64
|
+
perl -pi -e 's/^version = "[^"]*"/version = "${{ inputs.version }}"/ if $. < 10' pyproject.toml
|
|
65
|
+
perl -pi -e 's/^description = "[^"]*"/description = "CLI distribution channel for memU (same engine as memu-py). Personal memory as files."/' pyproject.toml
|
|
66
|
+
grep -q '^name = "memu-cli"' pyproject.toml || { echo "::error::rename to memu-cli did not apply"; exit 1; }
|
|
67
|
+
grep -E '^(name|version|description) = ' pyproject.toml | head -3
|
|
68
|
+
|
|
69
|
+
- name: Install uv
|
|
70
|
+
uses: astral-sh/setup-uv@v7
|
|
71
|
+
with:
|
|
72
|
+
python-version: ${{ matrix.python-version }}
|
|
73
|
+
|
|
74
|
+
- name: Install maturin
|
|
75
|
+
run: uv tool install maturin
|
|
76
|
+
|
|
77
|
+
- name: Setup Rust
|
|
78
|
+
uses: dtolnay/rust-toolchain@stable
|
|
79
|
+
with:
|
|
80
|
+
targets: ${{ matrix.target }}
|
|
81
|
+
|
|
82
|
+
- name: Setup cross-compilation for Linux ARM64
|
|
83
|
+
if: matrix.label == 'linux-aarch64'
|
|
84
|
+
run: |
|
|
85
|
+
sudo apt-get update
|
|
86
|
+
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
|
|
87
|
+
|
|
88
|
+
- name: Build wheel
|
|
89
|
+
run: uvx maturin build --release --out dist ${{ matrix.extra-args }} ${{ matrix.target && format('--target {0}', matrix.target) || '' }}
|
|
90
|
+
env:
|
|
91
|
+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
|
92
|
+
|
|
93
|
+
- name: Smoke test wheel
|
|
94
|
+
if: matrix.label != 'linux-aarch64'
|
|
95
|
+
shell: bash
|
|
96
|
+
run: uvx --isolated --from ./dist/memu_cli-*.whl memu --help
|
|
97
|
+
|
|
98
|
+
- name: Upload wheel artifact
|
|
99
|
+
uses: actions/upload-artifact@v6
|
|
100
|
+
with:
|
|
101
|
+
name: memu-cli-wheels-${{ matrix.label }}
|
|
102
|
+
path: dist/*.whl
|
|
103
|
+
if-no-files-found: error
|
|
104
|
+
|
|
105
|
+
build-sdist:
|
|
106
|
+
name: build sdist
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
steps:
|
|
109
|
+
- uses: actions/checkout@v6
|
|
110
|
+
|
|
111
|
+
- name: Rename distribution to memu-cli
|
|
112
|
+
shell: bash
|
|
113
|
+
run: |
|
|
114
|
+
perl -pi -e 's/^name = "memu-py"/name = "memu-cli"/' pyproject.toml
|
|
115
|
+
perl -pi -e 's/^version = "[^"]*"/version = "${{ inputs.version }}"/ if $. < 10' pyproject.toml
|
|
116
|
+
perl -pi -e 's/^description = "[^"]*"/description = "CLI distribution channel for memU (same engine as memu-py). Personal memory as files."/' pyproject.toml
|
|
117
|
+
grep -q '^name = "memu-cli"' pyproject.toml || { echo "::error::rename to memu-cli did not apply"; exit 1; }
|
|
118
|
+
|
|
119
|
+
- name: Install uv
|
|
120
|
+
uses: astral-sh/setup-uv@v7
|
|
121
|
+
with:
|
|
122
|
+
python-version: "3.13"
|
|
123
|
+
|
|
124
|
+
- name: Setup Rust
|
|
125
|
+
uses: dtolnay/rust-toolchain@stable
|
|
126
|
+
|
|
127
|
+
- name: Install maturin
|
|
128
|
+
run: uv tool install maturin
|
|
129
|
+
|
|
130
|
+
- name: Build sdist
|
|
131
|
+
run: uvx maturin sdist --out dist
|
|
132
|
+
|
|
133
|
+
- name: Upload sdist artifact
|
|
134
|
+
uses: actions/upload-artifact@v6
|
|
135
|
+
with:
|
|
136
|
+
name: memu-cli-sdist
|
|
137
|
+
path: dist/*.tar.gz
|
|
138
|
+
if-no-files-found: error
|
|
139
|
+
|
|
140
|
+
publish:
|
|
141
|
+
name: publish memu-cli to PyPI
|
|
142
|
+
runs-on: ubuntu-latest
|
|
143
|
+
needs:
|
|
144
|
+
- build-wheels
|
|
145
|
+
- build-sdist
|
|
146
|
+
environment: pypi
|
|
147
|
+
permissions:
|
|
148
|
+
id-token: write
|
|
149
|
+
steps:
|
|
150
|
+
- name: Download wheel artifacts
|
|
151
|
+
uses: actions/download-artifact@v7
|
|
152
|
+
with:
|
|
153
|
+
pattern: memu-cli-wheels-*
|
|
154
|
+
merge-multiple: true
|
|
155
|
+
path: dist
|
|
156
|
+
|
|
157
|
+
- name: Download sdist artifact
|
|
158
|
+
uses: actions/download-artifact@v7
|
|
159
|
+
with:
|
|
160
|
+
name: memu-cli-sdist
|
|
161
|
+
path: dist
|
|
162
|
+
|
|
163
|
+
- name: Publish to PyPI
|
|
164
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
165
|
+
with:
|
|
166
|
+
packages-dir: dist/
|
|
167
|
+
skip-existing: true
|
memu_cli-0.2.0/AGENTS.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Operational guide for AI coding agents working in this repository.
|
|
4
|
+
|
|
5
|
+
## Mission
|
|
6
|
+
|
|
7
|
+
Ship small, verified feature and bugfix changes while preserving memU's current architecture.
|
|
8
|
+
|
|
9
|
+
Core invariants:
|
|
10
|
+
|
|
11
|
+
- `MemoryService` (`src/memu/app/service.py`) is the composition root: config, storage, and the embedding client pool. Its public surface is exactly the three `AgenticMixin` entry points — `list_all_recall_files`, `progressive_retrieve`, `commit_results`.
|
|
12
|
+
- memU is embedding-only. No LLM/chat call happens anywhere in the service; do not add one.
|
|
13
|
+
- Storage is pluggable across `inmemory`, `sqlite`, and `postgres`; repository contract changes require backend parity.
|
|
14
|
+
- Scope data comes from `UserConfig.model`; validate `where` filters (`_normalize_where`) and do not bypass scope filtering.
|
|
15
|
+
- Retrieval config lives in `ProgressiveRetrieveConfig` (`file` + `resource` layers); embedding profiles in `EmbeddingProfilesConfig`.
|
|
16
|
+
|
|
17
|
+
## Layer Map
|
|
18
|
+
|
|
19
|
+
- Service + three entry points: `src/memu/app/service.py`, `src/memu/app/agentic.py`
|
|
20
|
+
- Config models/defaults: `src/memu/app/settings.py`
|
|
21
|
+
- Storage protocols/factory: `src/memu/database/interfaces.py`, `src/memu/database/factory.py`
|
|
22
|
+
- Backends: `src/memu/database/{inmemory,sqlite,postgres}/*`
|
|
23
|
+
- Vector math/ranking: `src/memu/vector.py`
|
|
24
|
+
- Embedding clients: `src/memu/embedding/*`
|
|
25
|
+
- CLI (`memu`): `src/memu/cli.py`; shared `MEMU_*` config: `src/memu/env.py`
|
|
26
|
+
- Host adapters (`memu-codex`, bridging pipeline): `src/memu/hosts/*`
|
|
27
|
+
- Tests: `tests/*`
|
|
28
|
+
|
|
29
|
+
Read the relevant implementation and nearby tests first. Prefer local patterns over new abstractions.
|
|
30
|
+
|
|
31
|
+
## Implementation Rules
|
|
32
|
+
|
|
33
|
+
- Keep changes narrow and localized to the affected layer.
|
|
34
|
+
- Preserve async behavior and result shapes unless the task explicitly asks for a breaking change.
|
|
35
|
+
- Maintain type hints and mypy compatibility.
|
|
36
|
+
- Keep provider-specific logic inside `memu.embedding.backends`; storage-neutral logic outside concrete backends.
|
|
37
|
+
- Do not duplicate client caching — use the existing `ClientPool` pattern.
|
|
38
|
+
- Do not silently swallow errors that should be visible to callers or tests.
|
|
39
|
+
|
|
40
|
+
## Backend Parity
|
|
41
|
+
|
|
42
|
+
If a repository method, model field, filter behavior, or vector search contract changes:
|
|
43
|
+
|
|
44
|
+
1. Update the protocol in `src/memu/database/repositories/`.
|
|
45
|
+
2. Update `inmemory`, `sqlite`, and `postgres` implementations where applicable.
|
|
46
|
+
3. Extend `tests/test_agentic.py` (runs against inmemory + sqlite).
|
|
47
|
+
4. Check migrations/bootstrap behavior for SQL backends (`src/memu/database/postgres/migrations/`).
|
|
48
|
+
|
|
49
|
+
## Testing And Validation
|
|
50
|
+
|
|
51
|
+
Use `uv` for local runs.
|
|
52
|
+
|
|
53
|
+
- Setup: `make install`
|
|
54
|
+
- Run all tests: `make test`
|
|
55
|
+
- Run focused tests: `uv run python -m pytest tests/<target_test>.py`
|
|
56
|
+
- Full quality checks: `make check`
|
|
57
|
+
|
|
58
|
+
Useful focused areas:
|
|
59
|
+
|
|
60
|
+
- The three entry points end-to-end: `tests/test_agentic.py`
|
|
61
|
+
- Vector ranking: `tests/test_vector.py`
|
|
62
|
+
- Embedding providers/gateway: `tests/test_embedding.py`
|
|
63
|
+
- CLI surface: `tests/test_cli.py`
|
|
64
|
+
- Host adapter inject seam: `tests/test_host_instruction.py`
|
|
65
|
+
|
|
66
|
+
## Documentation Rules
|
|
67
|
+
|
|
68
|
+
- Update `README.md` or `npm/README.md` when user-visible behavior changes.
|
|
69
|
+
- Add or update ADRs under `docs/adr/` for architectural changes; existing ADRs are historical records — do not rewrite them.
|
|
70
|
+
- Do not document speculative features as implemented.
|
|
71
|
+
|
|
72
|
+
## Done Criteria
|
|
73
|
+
|
|
74
|
+
- Code compiles for touched paths; tests for changed behavior pass.
|
|
75
|
+
- New behavior has test coverage.
|
|
76
|
+
- Backend parity considered and implemented where needed.
|
|
77
|
+
- No unrelated files modified.
|
memu_cli-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: memu-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Classifier: Development Status :: 4 - Beta
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: Operating System :: OS Independent
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
+
Requires-Dist: httpx>=0.28.1
|
|
10
|
+
Requires-Dist: numpy>=2.3.4
|
|
11
|
+
Requires-Dist: openai>=2.8.0
|
|
12
|
+
Requires-Dist: pydantic>=2.12.4
|
|
13
|
+
Requires-Dist: sqlmodel>=0.0.27
|
|
14
|
+
Requires-Dist: alembic>=1.14.0
|
|
15
|
+
Requires-Dist: pendulum>=3.1.0
|
|
16
|
+
Requires-Dist: pgvector>=0.3.4 ; extra == 'postgres'
|
|
17
|
+
Requires-Dist: sqlalchemy[postgresql-psycopgbinary]>=2.0.36 ; extra == 'postgres'
|
|
18
|
+
Provides-Extra: postgres
|
|
19
|
+
License-File: LICENSE.txt
|
|
20
|
+
Summary: CLI distribution channel for memU (same engine as memu-py). Personal memory as files.
|
|
21
|
+
Keywords: agent,agentic,agent-harness,harness,loop-engineering,context-engineering,context-window,memory,personal-information,workspace,retrieval,llm
|
|
22
|
+
Author-email: MemU Team <contact@nevamind.ai>
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
25
|
+
Project-URL: Bug Tracker, https://github.com/NevaMind-AI/MemU/issues
|
|
26
|
+
Project-URL: Documentation, https://github.com/NevaMind-AI/MemU#readme
|
|
27
|
+
Project-URL: Homepage, https://github.com/NevaMind-AI/MemU
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
|
|
33
|
+
# memU
|
|
34
|
+
|
|
35
|
+
### Personal memory, stored as files
|
|
36
|
+
|
|
37
|
+
**Across Agents. Fast retrieval. Lower cost.**
|
|
38
|
+
|
|
39
|
+
[](https://badge.fury.io/py/memu-cli)
|
|
40
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
41
|
+
[](https://www.python.org/downloads/)
|
|
42
|
+
[](https://discord.com/invite/hQZntfGsbJ)
|
|
43
|
+
[](https://x.com/memU_ai)
|
|
44
|
+
|
|
45
|
+
<a href="https://trendshift.io/repositories/17374" target="_blank"><img src="https://trendshift.io/api/badge/repositories/17374" alt="NevaMind-AI%2FmemU | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
46
|
+
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
memU is a 500-line memory system for AI agents. Agents write what's worth keeping as Markdown; memU stores it, embeds it, and retrieves ranked context in a single call — embeddings are the only model calls it makes. The entire memory logic lives in [`agentic.py`](src/memu/app/agentic.py) + [`service.py`](src/memu/app/service.py); everything else is pluggable storage and embedding transport.
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from memu.app import MemoryService
|
|
57
|
+
|
|
58
|
+
service = MemoryService(
|
|
59
|
+
database_config={"metadata_store": {"provider": "sqlite", "dsn": "sqlite:///memu.sqlite3"}},
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# 1. Persist agent-prepared memory: recall files (memory/skill tracks) + resources
|
|
63
|
+
await service.commit_results(
|
|
64
|
+
recall_files=[
|
|
65
|
+
{
|
|
66
|
+
"name": "Profile",
|
|
67
|
+
"track": "memory",
|
|
68
|
+
"description": "who the user is",
|
|
69
|
+
"content": "# Profile\n- prefers dark roast coffee\n- ships on Fridays",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "deploy-checklist",
|
|
73
|
+
"track": "skill",
|
|
74
|
+
"description": "how to deploy this repo",
|
|
75
|
+
"content": "1. run tests\n2. tag\n3. push",
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
resource=[{"path": "/abs/path/notes.md", "description": "meeting notes from the launch review"}],
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# 2. See what is stored, across every track
|
|
82
|
+
files = await service.list_all_recall_files()
|
|
83
|
+
|
|
84
|
+
# 3. Single-shot embedding retrieval over segments / files / resources
|
|
85
|
+
context = await service.progressive_retrieve("What should I know about this user's launch preferences?")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or straight from the terminal — no code:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
export OPENAI_API_KEY=sk-... # embedding API key — the only model calls memU makes
|
|
92
|
+
|
|
93
|
+
npx memu-cli commit results.json # {"recall_files": [...], "resource": [...]}
|
|
94
|
+
npx memu-cli list-files
|
|
95
|
+
npx memu-cli retrieve "What should I know about this user's launch preferences?"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
State persists in a local SQLite database (`./data/memu.sqlite3` by default), so commit in one invocation and retrieve in the next.
|
|
99
|
+
|
|
100
|
+
## How it works
|
|
101
|
+
|
|
102
|
+

|
|
103
|
+
|
|
104
|
+
### The data model
|
|
105
|
+
|
|
106
|
+
Memory is a set of **recall files** — one Markdown document per topic (`track="memory"`) or per learned skill (`track="skill"`). Committing a file also writes its search index:
|
|
107
|
+
|
|
108
|
+
| Record | What it is | How it's embedded |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| **RecallFile** | The Markdown document itself (`name`, `track`, `description`, `content`) | `name: description`, once at creation |
|
|
111
|
+
| **RecallFileSegment** | Searchable slices of a file | memory track: one per content line (headings skipped); skill track: one `name: description` segment per skill |
|
|
112
|
+
| **Resource** | A raw source on disk (`url`, `caption`) | its one-line caption |
|
|
113
|
+
|
|
114
|
+
Segments are reconciled on every commit: lines that disappeared are deleted, only genuinely new lines are embedded, unchanged lines keep their vectors — so re-committing a lightly edited file is nearly free.
|
|
115
|
+
|
|
116
|
+
### Retrieval
|
|
117
|
+
|
|
118
|
+
`progressive_retrieve(query)` embeds the query **once** and returns three ranked layers:
|
|
119
|
+
|
|
120
|
+
- `segments` — the matched slices, narrowest and usually most on-point, each with a `score`
|
|
121
|
+
- `files` — the documents those segments belong to (usually what you want), each scored by its best segment and carrying its linked `resource_urls`
|
|
122
|
+
- `resources` — matching raw sources, for when summaries are not enough
|
|
123
|
+
|
|
124
|
+
There is no intention routing, sufficiency checking, or summarization — one embedding call in, ranked context out.
|
|
125
|
+
|
|
126
|
+
## Host adapter: memory for desktop coding agents
|
|
127
|
+
|
|
128
|
+
`memu-codex` runs memU as a sidecar to Codex-style agents (ADR 0008/0009). It binds two seams:
|
|
129
|
+
|
|
130
|
+
- **record** — a scheduled bridging task slices new session logs into self-contained job files; the agent itself distills them into memory/skill Markdown; `commit` submits whatever the agent left on disk back through `commit_results`.
|
|
131
|
+
- **inject** — a standing instruction in the host's global instruction file (`~/.codex/AGENTS.md`) tells the agent to run `memu-codex retrieve` (→ `progressive_retrieve`) before answering.
|
|
132
|
+
|
|
133
|
+
**Installation is agent-driven.** The install guide is written for the agent, not for you — install the package, then hand the guide to your agent and let it do the rest (configure the store, register the scheduled bridging task, patch the instruction file — each step ends with a verify gate):
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
pip install memu-cli # puts memu + memu-codex on PATH
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Then tell your agent:
|
|
140
|
+
|
|
141
|
+
> Run `memu-codex docs install`, read the guide it prints, and follow it to install memU.
|
|
142
|
+
|
|
143
|
+
Afterwards `memu-codex doctor` proves the whole loop resolves: config, store, and a live retrieval.
|
|
144
|
+
|
|
145
|
+
Adding another host means implementing one `TranscriptSource` (where its session logs live, how its records are shaped) plus a thin CLI — the pipeline and instruction text are shared.
|
|
146
|
+
|
|
147
|
+
## Installation
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pip install memu-cli # library + memu + memu-codex CLIs
|
|
151
|
+
npx memu-cli --help # CLI via npm launcher (engine: PyPI package memu-cli)
|
|
152
|
+
uvx --from memu-cli memu # CLI via uv, no install
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Configuration
|
|
156
|
+
|
|
157
|
+
Values resolve in order: process env → `~/.memu/config.env` → default. Every CLI flag has a matching variable:
|
|
158
|
+
|
|
159
|
+
| Setting | Env var | Default |
|
|
160
|
+
|---|---|---|
|
|
161
|
+
| Store | `MEMU_DB` | `./data/memu.sqlite3` (CLI); **required** for host adapters |
|
|
162
|
+
| Embedding provider | `MEMU_EMBED_PROVIDER` | `openai` (also: `jina`, `voyage`, `doubao`, `openrouter`); legacy `MEMU_LLM_PROVIDER` still read |
|
|
163
|
+
| API key | `MEMU_API_KEY` | the provider's env var, e.g. `OPENAI_API_KEY` |
|
|
164
|
+
| Embedding model | `MEMU_EMBED_MODEL` | the provider's default |
|
|
165
|
+
| Base URL | `MEMU_BASE_URL` | the provider's default |
|
|
166
|
+
|
|
167
|
+
### Storage backends
|
|
168
|
+
|
|
169
|
+
| Provider | DSN | Vector search | Use for |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| `inmemory` | — | brute-force cosine | tests, throwaway sessions |
|
|
172
|
+
| `sqlite` | `sqlite:///path.sqlite3` | brute-force cosine | local/default, single writer |
|
|
173
|
+
| `postgres` | `postgresql://...` | pgvector | concurrent access, large stores (`pip install "memu-cli[postgres]"`) |
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
service = MemoryService(
|
|
177
|
+
database_config={"metadata_store": {"provider": "postgres", "dsn": "postgresql://..."}},
|
|
178
|
+
embedding_profiles={"default": {"provider": "jina"}},
|
|
179
|
+
)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Multi-tenancy
|
|
183
|
+
|
|
184
|
+
Every record carries optional scope fields (`user_id`, `agent_id` by default). Pass `user=` on writes and `where=` on reads to partition one store:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
await service.commit_results(recall_files=[...], user={"user_id": "alice"})
|
|
188
|
+
await service.progressive_retrieve("launch preferences", where={"user_id": "alice"})
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Need different scope fields? Supply your own model — filters are validated against it, unknown fields raise:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from pydantic import BaseModel
|
|
195
|
+
|
|
196
|
+
class TeamScope(BaseModel):
|
|
197
|
+
team_id: str | None = None
|
|
198
|
+
user_id: str | None = None
|
|
199
|
+
|
|
200
|
+
service = MemoryService(user_config={"model": TeamScope})
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Development
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
make install # uv sync + pre-commit hooks
|
|
207
|
+
make test # pytest with coverage
|
|
208
|
+
make check # lock check, pre-commit, mypy, deptry
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Architecture decisions live in [`docs/adr/`](docs/adr/) — notably tracked workspace memorization (ADR 0006), the segment/file/resource retrieval lines (ADR 0007), and the host-adapter seams (ADR 0008/0009).
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
Apache-2.0
|
|
216
|
+
|
memu_cli-0.2.0/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
# memU
|
|
6
|
+
|
|
7
|
+
### Personal memory, stored as files
|
|
8
|
+
|
|
9
|
+
**Across Agents. Fast retrieval. Lower cost.**
|
|
10
|
+
|
|
11
|
+
[](https://badge.fury.io/py/memu-cli)
|
|
12
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
13
|
+
[](https://www.python.org/downloads/)
|
|
14
|
+
[](https://discord.com/invite/hQZntfGsbJ)
|
|
15
|
+
[](https://x.com/memU_ai)
|
|
16
|
+
|
|
17
|
+
<a href="https://trendshift.io/repositories/17374" target="_blank"><img src="https://trendshift.io/api/badge/repositories/17374" alt="NevaMind-AI%2FmemU | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
18
|
+
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
memU is a 500-line memory system for AI agents. Agents write what's worth keeping as Markdown; memU stores it, embeds it, and retrieves ranked context in a single call — embeddings are the only model calls it makes. The entire memory logic lives in [`agentic.py`](src/memu/app/agentic.py) + [`service.py`](src/memu/app/service.py); everything else is pluggable storage and embedding transport.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from memu.app import MemoryService
|
|
29
|
+
|
|
30
|
+
service = MemoryService(
|
|
31
|
+
database_config={"metadata_store": {"provider": "sqlite", "dsn": "sqlite:///memu.sqlite3"}},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# 1. Persist agent-prepared memory: recall files (memory/skill tracks) + resources
|
|
35
|
+
await service.commit_results(
|
|
36
|
+
recall_files=[
|
|
37
|
+
{
|
|
38
|
+
"name": "Profile",
|
|
39
|
+
"track": "memory",
|
|
40
|
+
"description": "who the user is",
|
|
41
|
+
"content": "# Profile\n- prefers dark roast coffee\n- ships on Fridays",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "deploy-checklist",
|
|
45
|
+
"track": "skill",
|
|
46
|
+
"description": "how to deploy this repo",
|
|
47
|
+
"content": "1. run tests\n2. tag\n3. push",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
resource=[{"path": "/abs/path/notes.md", "description": "meeting notes from the launch review"}],
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# 2. See what is stored, across every track
|
|
54
|
+
files = await service.list_all_recall_files()
|
|
55
|
+
|
|
56
|
+
# 3. Single-shot embedding retrieval over segments / files / resources
|
|
57
|
+
context = await service.progressive_retrieve("What should I know about this user's launch preferences?")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or straight from the terminal — no code:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
export OPENAI_API_KEY=sk-... # embedding API key — the only model calls memU makes
|
|
64
|
+
|
|
65
|
+
npx memu-cli commit results.json # {"recall_files": [...], "resource": [...]}
|
|
66
|
+
npx memu-cli list-files
|
|
67
|
+
npx memu-cli retrieve "What should I know about this user's launch preferences?"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
State persists in a local SQLite database (`./data/memu.sqlite3` by default), so commit in one invocation and retrieve in the next.
|
|
71
|
+
|
|
72
|
+
## How it works
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
### The data model
|
|
77
|
+
|
|
78
|
+
Memory is a set of **recall files** — one Markdown document per topic (`track="memory"`) or per learned skill (`track="skill"`). Committing a file also writes its search index:
|
|
79
|
+
|
|
80
|
+
| Record | What it is | How it's embedded |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| **RecallFile** | The Markdown document itself (`name`, `track`, `description`, `content`) | `name: description`, once at creation |
|
|
83
|
+
| **RecallFileSegment** | Searchable slices of a file | memory track: one per content line (headings skipped); skill track: one `name: description` segment per skill |
|
|
84
|
+
| **Resource** | A raw source on disk (`url`, `caption`) | its one-line caption |
|
|
85
|
+
|
|
86
|
+
Segments are reconciled on every commit: lines that disappeared are deleted, only genuinely new lines are embedded, unchanged lines keep their vectors — so re-committing a lightly edited file is nearly free.
|
|
87
|
+
|
|
88
|
+
### Retrieval
|
|
89
|
+
|
|
90
|
+
`progressive_retrieve(query)` embeds the query **once** and returns three ranked layers:
|
|
91
|
+
|
|
92
|
+
- `segments` — the matched slices, narrowest and usually most on-point, each with a `score`
|
|
93
|
+
- `files` — the documents those segments belong to (usually what you want), each scored by its best segment and carrying its linked `resource_urls`
|
|
94
|
+
- `resources` — matching raw sources, for when summaries are not enough
|
|
95
|
+
|
|
96
|
+
There is no intention routing, sufficiency checking, or summarization — one embedding call in, ranked context out.
|
|
97
|
+
|
|
98
|
+
## Host adapter: memory for desktop coding agents
|
|
99
|
+
|
|
100
|
+
`memu-codex` runs memU as a sidecar to Codex-style agents (ADR 0008/0009). It binds two seams:
|
|
101
|
+
|
|
102
|
+
- **record** — a scheduled bridging task slices new session logs into self-contained job files; the agent itself distills them into memory/skill Markdown; `commit` submits whatever the agent left on disk back through `commit_results`.
|
|
103
|
+
- **inject** — a standing instruction in the host's global instruction file (`~/.codex/AGENTS.md`) tells the agent to run `memu-codex retrieve` (→ `progressive_retrieve`) before answering.
|
|
104
|
+
|
|
105
|
+
**Installation is agent-driven.** The install guide is written for the agent, not for you — install the package, then hand the guide to your agent and let it do the rest (configure the store, register the scheduled bridging task, patch the instruction file — each step ends with a verify gate):
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install memu-cli # puts memu + memu-codex on PATH
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Then tell your agent:
|
|
112
|
+
|
|
113
|
+
> Run `memu-codex docs install`, read the guide it prints, and follow it to install memU.
|
|
114
|
+
|
|
115
|
+
Afterwards `memu-codex doctor` proves the whole loop resolves: config, store, and a live retrieval.
|
|
116
|
+
|
|
117
|
+
Adding another host means implementing one `TranscriptSource` (where its session logs live, how its records are shaped) plus a thin CLI — the pipeline and instruction text are shared.
|
|
118
|
+
|
|
119
|
+
## Installation
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
pip install memu-cli # library + memu + memu-codex CLIs
|
|
123
|
+
npx memu-cli --help # CLI via npm launcher (engine: PyPI package memu-cli)
|
|
124
|
+
uvx --from memu-cli memu # CLI via uv, no install
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Configuration
|
|
128
|
+
|
|
129
|
+
Values resolve in order: process env → `~/.memu/config.env` → default. Every CLI flag has a matching variable:
|
|
130
|
+
|
|
131
|
+
| Setting | Env var | Default |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| Store | `MEMU_DB` | `./data/memu.sqlite3` (CLI); **required** for host adapters |
|
|
134
|
+
| Embedding provider | `MEMU_EMBED_PROVIDER` | `openai` (also: `jina`, `voyage`, `doubao`, `openrouter`); legacy `MEMU_LLM_PROVIDER` still read |
|
|
135
|
+
| API key | `MEMU_API_KEY` | the provider's env var, e.g. `OPENAI_API_KEY` |
|
|
136
|
+
| Embedding model | `MEMU_EMBED_MODEL` | the provider's default |
|
|
137
|
+
| Base URL | `MEMU_BASE_URL` | the provider's default |
|
|
138
|
+
|
|
139
|
+
### Storage backends
|
|
140
|
+
|
|
141
|
+
| Provider | DSN | Vector search | Use for |
|
|
142
|
+
|---|---|---|---|
|
|
143
|
+
| `inmemory` | — | brute-force cosine | tests, throwaway sessions |
|
|
144
|
+
| `sqlite` | `sqlite:///path.sqlite3` | brute-force cosine | local/default, single writer |
|
|
145
|
+
| `postgres` | `postgresql://...` | pgvector | concurrent access, large stores (`pip install "memu-cli[postgres]"`) |
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
service = MemoryService(
|
|
149
|
+
database_config={"metadata_store": {"provider": "postgres", "dsn": "postgresql://..."}},
|
|
150
|
+
embedding_profiles={"default": {"provider": "jina"}},
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Multi-tenancy
|
|
155
|
+
|
|
156
|
+
Every record carries optional scope fields (`user_id`, `agent_id` by default). Pass `user=` on writes and `where=` on reads to partition one store:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
await service.commit_results(recall_files=[...], user={"user_id": "alice"})
|
|
160
|
+
await service.progressive_retrieve("launch preferences", where={"user_id": "alice"})
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Need different scope fields? Supply your own model — filters are validated against it, unknown fields raise:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
from pydantic import BaseModel
|
|
167
|
+
|
|
168
|
+
class TeamScope(BaseModel):
|
|
169
|
+
team_id: str | None = None
|
|
170
|
+
user_id: str | None = None
|
|
171
|
+
|
|
172
|
+
service = MemoryService(user_config={"model": TeamScope})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
make install # uv sync + pre-commit hooks
|
|
179
|
+
make test # pytest with coverage
|
|
180
|
+
make check # lock check, pre-commit, mypy, deptry
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Architecture decisions live in [`docs/adr/`](docs/adr/) — notably tracked workspace memorization (ADR 0006), the segment/file/resource retrieval lines (ADR 0007), and the host-adapter seams (ADR 0008/0009).
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
Apache-2.0
|
|
Binary file
|