cli-memory-os 0.1.7__tar.gz → 0.1.8__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.
- {cli_memory_os-0.1.7/cli_memory_os.egg-info → cli_memory_os-0.1.8}/PKG-INFO +1 -1
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8/cli_memory_os.egg-info}/PKG-INFO +1 -1
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/context_builder.py +2 -1
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/llm.py +35 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/pyproject.toml +1 -1
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_sync_ask_cli.py +30 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/LICENSE +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/MANIFEST.in +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/README.md +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/ask.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/benchmark.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/config_cmd.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/doctor.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/export.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/import_cmd.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/init.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/logs.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/monitor.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/plugins.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/restart.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/start.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/status.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/stop.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/sync.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/version.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/commands/workspace.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/main.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/parser.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/tui/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli/tui/app.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli_memory_os.egg-info/SOURCES.txt +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli_memory_os.egg-info/dependency_links.txt +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli_memory_os.egg-info/entry_points.txt +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli_memory_os.egg-info/requires.txt +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/cli_memory_os.egg-info/top_level.txt +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/base.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/github.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/gmail.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/notion.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/connectors/registry.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/chunker.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/embedder.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/core/vector_store.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/compose.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/config.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/docker.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/health.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/observability.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/infrastructure/workspace.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/models/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/models/memory.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/setup.cfg +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/storage/__init__.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/storage/db.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/storage/graph.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/storage/schema.sql +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/storage/tech_detector.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_cli_integration.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_commands_phase2.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_compose_manager.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_first_time_user_experience.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_infrastructure_stabilization.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_tui.py +0 -0
- {cli_memory_os-0.1.7 → cli_memory_os-0.1.8}/tests/test_v1_features.py +0 -0
|
@@ -50,7 +50,8 @@ class ContextBuilder:
|
|
|
50
50
|
return "Documentation Question"
|
|
51
51
|
|
|
52
52
|
# 5. Cross Repository Question
|
|
53
|
-
|
|
53
|
+
cross_keywords = ["projects", "repositories", "repos", "cross repository", "multiple repositories", "across all", "all my"]
|
|
54
|
+
if any(k in query_lower for k in cross_keywords) and not repo_filter:
|
|
54
55
|
return "Cross Repository Question"
|
|
55
56
|
|
|
56
57
|
# Default
|
|
@@ -86,6 +86,39 @@ def query_llm_with_retry(messages: list, model: str = None, max_retries: int = 3
|
|
|
86
86
|
time.sleep(0.5)
|
|
87
87
|
return ""
|
|
88
88
|
|
|
89
|
+
def inject_repository_summary_chunk(formatted_chunks: list, query_class: str) -> list:
|
|
90
|
+
"""If the query is a cross-repository query, pre-append a summary chunk listing all repos."""
|
|
91
|
+
if query_class != "Cross Repository Question":
|
|
92
|
+
return formatted_chunks
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
from storage.db import get_connection
|
|
96
|
+
conn = get_connection()
|
|
97
|
+
cursor = conn.cursor()
|
|
98
|
+
cursor.execute("SELECT repo_name, description, language FROM repositories")
|
|
99
|
+
all_repos = cursor.fetchall()
|
|
100
|
+
conn.close()
|
|
101
|
+
|
|
102
|
+
if all_repos:
|
|
103
|
+
repo_list_lines = ["All Connected Repositories:"]
|
|
104
|
+
for r in all_repos:
|
|
105
|
+
desc_str = f" - Description: {r[1]}" if r[1] else ""
|
|
106
|
+
lang_str = f" (Language: {r[2]})" if r[2] else ""
|
|
107
|
+
repo_list_lines.append(f"- {r[0]}{lang_str}{desc_str}")
|
|
108
|
+
repo_list_str = "\n".join(repo_list_lines)
|
|
109
|
+
|
|
110
|
+
# Pre-append to formatted_chunks with a high score to prevent trimming
|
|
111
|
+
formatted_chunks.insert(0, {
|
|
112
|
+
"text": repo_list_str,
|
|
113
|
+
"score": 999.0,
|
|
114
|
+
"type": "repository_summary"
|
|
115
|
+
})
|
|
116
|
+
except Exception as e:
|
|
117
|
+
import logging
|
|
118
|
+
logging.getLogger("llm").error(f"Failed to generate repository summary context chunk: {e}")
|
|
119
|
+
|
|
120
|
+
return formatted_chunks
|
|
121
|
+
|
|
89
122
|
def run_hybrid_rag(question: str) -> dict:
|
|
90
123
|
import time
|
|
91
124
|
import logging
|
|
@@ -155,6 +188,7 @@ def run_hybrid_rag(question: str) -> dict:
|
|
|
155
188
|
formatted_chunks, sources, repos, num_vector, num_keyword, num_graph, after_dedup = builder.build_context(
|
|
156
189
|
question, vector_results, keyword_results, graph_results, repo_filter=repo_filter, query_class=query_class
|
|
157
190
|
)
|
|
191
|
+
formatted_chunks = inject_repository_summary_chunk(formatted_chunks, query_class)
|
|
158
192
|
|
|
159
193
|
system_prompt = (
|
|
160
194
|
"You are an assistant answering ONLY from the supplied retrieved context.\n\n"
|
|
@@ -408,6 +442,7 @@ def run_hybrid_rag_stream(question: str):
|
|
|
408
442
|
formatted_chunks, sources, repos, num_vector, num_keyword, num_graph, after_dedup = builder.build_context(
|
|
409
443
|
question, vector_results, keyword_results, graph_results, repo_filter=repo_filter, query_class=query_class
|
|
410
444
|
)
|
|
445
|
+
formatted_chunks = inject_repository_summary_chunk(formatted_chunks, query_class)
|
|
411
446
|
|
|
412
447
|
system_prompt = (
|
|
413
448
|
"You are an assistant answering ONLY from the supplied retrieved context.\n\n"
|
|
@@ -106,6 +106,36 @@ class TestSyncAskCLI(unittest.TestCase):
|
|
|
106
106
|
# Verify that natural language query gets routed to ask and calls run_and_print_ask
|
|
107
107
|
mock_run_and_print_ask.assert_called_once_with("What projects use Python?")
|
|
108
108
|
|
|
109
|
+
@patch("storage.db.get_connection")
|
|
110
|
+
def test_inject_repository_summary_chunk(self, mock_get_connection):
|
|
111
|
+
"""Test repository summary chunk is injected for cross-repository questions."""
|
|
112
|
+
from core.llm import inject_repository_summary_chunk
|
|
113
|
+
|
|
114
|
+
# Mock database cursor to return some repositories
|
|
115
|
+
mock_conn = MagicMock()
|
|
116
|
+
mock_cursor = MagicMock()
|
|
117
|
+
mock_cursor.fetchall.return_value = [
|
|
118
|
+
("Bug-Tracker", "Bug tracking system", "JavaScript"),
|
|
119
|
+
("Memory-OS", "PKOS", "Python")
|
|
120
|
+
]
|
|
121
|
+
mock_conn.cursor.return_value = mock_cursor
|
|
122
|
+
mock_get_connection.return_value = mock_conn
|
|
123
|
+
|
|
124
|
+
formatted_chunks = [
|
|
125
|
+
{"text": "Some chunk text", "score": 0.5, "type": "document"}
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
# Calling with non-cross-repository query class should do nothing
|
|
129
|
+
res1 = inject_repository_summary_chunk(list(formatted_chunks), "General Knowledge Question")
|
|
130
|
+
self.assertEqual(len(res1), 1)
|
|
131
|
+
|
|
132
|
+
# Calling with Cross Repository Question should inject summary chunk
|
|
133
|
+
res2 = inject_repository_summary_chunk(list(formatted_chunks), "Cross Repository Question")
|
|
134
|
+
self.assertEqual(len(res2), 2)
|
|
135
|
+
self.assertEqual(res2[0]["type"], "repository_summary")
|
|
136
|
+
self.assertIn("Bug-Tracker", res2[0]["text"])
|
|
137
|
+
self.assertIn("Memory-OS", res2[0]["text"])
|
|
138
|
+
|
|
109
139
|
|
|
110
140
|
if __name__ == "__main__":
|
|
111
141
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|