cli-memory-os 0.1.0__tar.gz → 0.1.2__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.0/cli_memory_os.egg-info → cli_memory_os-0.1.2}/PKG-INFO +1 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/benchmark.py +1 -2
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/doctor.py +13 -2
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/import_cmd.py +0 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/init.py +83 -86
- cli_memory_os-0.1.2/cli/commands/restart.py +23 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/status.py +1 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/workspace.py +0 -2
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/main.py +3 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/parser.py +6 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2/cli_memory_os.egg-info}/PKG-INFO +1 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli_memory_os.egg-info/SOURCES.txt +3 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/embedder.py +0 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/llm.py +0 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/vector_store.py +0 -49
- cli_memory_os-0.1.2/infrastructure/compose.py +303 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/docker.py +24 -5
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/health.py +53 -14
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/observability.py +0 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/pyproject.toml +1 -1
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/storage/db.py +0 -38
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/storage/tech_detector.py +1 -39
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/tests/test_cli_integration.py +31 -2
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/tests/test_commands_phase2.py +24 -20
- cli_memory_os-0.1.2/tests/test_compose_manager.py +155 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/tests/test_first_time_user_experience.py +1 -1
- cli_memory_os-0.1.2/tests/test_infrastructure_stabilization.py +138 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/tests/test_v1_features.py +3 -5
- cli_memory_os-0.1.0/infrastructure/compose.py +0 -136
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/LICENSE +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/MANIFEST.in +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/README.md +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/config_cmd.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/export.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/logs.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/monitor.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/plugins.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/start.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/stop.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli/commands/version.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli_memory_os.egg-info/dependency_links.txt +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli_memory_os.egg-info/entry_points.txt +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli_memory_os.egg-info/requires.txt +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/cli_memory_os.egg-info/top_level.txt +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/base.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/github.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/gmail.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/notion.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/connectors/registry.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/chunker.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/core/context_builder.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/config.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/infrastructure/workspace.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/models/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/models/memory.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/setup.cfg +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/storage/__init__.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/storage/graph.py +0 -0
- {cli_memory_os-0.1.0 → cli_memory_os-0.1.2}/storage/schema.sql +0 -0
|
@@ -6,8 +6,7 @@ graph lookups, LLM invocation, and RAG pipelines.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import time
|
|
9
|
-
import
|
|
10
|
-
from infrastructure.health import check_neo4j, check_qdrant, check_groq_api, check_memory_usage
|
|
9
|
+
from infrastructure.health import check_qdrant, check_groq_api, check_memory_usage
|
|
11
10
|
from core.embedder import Embedder
|
|
12
11
|
|
|
13
12
|
|
|
@@ -53,8 +53,19 @@ def execute(args):
|
|
|
53
53
|
"Active Plugins": "No plugins are authenticated. Run 'memory-os init' to set up connector logins.",
|
|
54
54
|
}
|
|
55
55
|
for name, detail in failed:
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
if name == "Neo4j" and "Authentication failed" in detail:
|
|
57
|
+
print(" * Neo4j: Neo4j is running but authentication failed.")
|
|
58
|
+
print(" Recommendations:")
|
|
59
|
+
print(" memory-os config set neo4j.user <username>")
|
|
60
|
+
print(" memory-os config set neo4j.password <password>")
|
|
61
|
+
print(" or")
|
|
62
|
+
print(" memory-os init")
|
|
63
|
+
elif name == "Neo4j" and "Unreachable" in detail:
|
|
64
|
+
rec = recommendations.get(name, "Check log file logs/memory_os.log for errors.")
|
|
65
|
+
print(f" * {name}: {rec} (Detail: {detail})")
|
|
66
|
+
else:
|
|
67
|
+
rec = recommendations.get(name, "Check log file logs/memory_os.log for errors.")
|
|
68
|
+
print(f" * {name}: {rec} (Detail: {detail})")
|
|
58
69
|
print("─────────────────────────────")
|
|
59
70
|
else:
|
|
60
71
|
print("\n All checks passed.")
|
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Command: memory-os init
|
|
3
3
|
|
|
4
|
-
Performs first-time setup and onboarding for Memory-OS.
|
|
5
|
-
Provisions the workspace directory structure, creates config.toml,
|
|
6
|
-
spins up Neo4j and Qdrant via docker compose, initializes SQLite,
|
|
7
|
-
pre-warms the embedding model, and launches Composio toolkit OAuth flows.
|
|
4
|
+
Performs first-time setup and onboarding for Memory-OS using ComposeManager.
|
|
8
5
|
"""
|
|
9
6
|
|
|
10
7
|
import sys
|
|
11
8
|
import uuid
|
|
12
|
-
import time
|
|
13
9
|
import os
|
|
14
|
-
from pathlib import Path
|
|
15
10
|
from infrastructure.workspace import ensure_workspace, get_db_path
|
|
16
11
|
from infrastructure.config import generate_default_config, save_config, load_config
|
|
17
|
-
from infrastructure.
|
|
18
|
-
from infrastructure.
|
|
19
|
-
from infrastructure.health import run_all_checks
|
|
12
|
+
from infrastructure.compose import ComposeManager, wait_for_services
|
|
13
|
+
from infrastructure.health import run_all_checks, check_docker, check_neo4j, check_qdrant
|
|
20
14
|
from storage.db import init_db
|
|
21
15
|
from core.embedder import Embedder
|
|
22
16
|
|
|
23
17
|
|
|
18
|
+
|
|
24
19
|
def get_input(prompt: str, secret: bool = False, default: str = "") -> str:
|
|
25
20
|
"""Prompt the user for input with an optional default value."""
|
|
26
21
|
import getpass
|
|
@@ -38,14 +33,13 @@ def get_input(prompt: str, secret: bool = False, default: str = "") -> str:
|
|
|
38
33
|
|
|
39
34
|
|
|
40
35
|
def execute(args):
|
|
41
|
-
"""Run the init command."""
|
|
36
|
+
"""Run the init command wizard following the exact 11 steps."""
|
|
42
37
|
print("==================================================")
|
|
43
38
|
print("🧠 MEMORY-OS INITIALIZATION WIZARD")
|
|
44
39
|
print("==================================================")
|
|
45
40
|
|
|
46
|
-
# 1
|
|
47
|
-
print("\n[1/
|
|
48
|
-
|
|
41
|
+
# ── Step 1: Check Python ──────────────────────────────────
|
|
42
|
+
print("\n[Step 1/11] Checking Python version...")
|
|
49
43
|
python_ok = sys.version_info >= (3, 12)
|
|
50
44
|
py_ver = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
51
45
|
if not python_ok:
|
|
@@ -53,52 +47,73 @@ def execute(args):
|
|
|
53
47
|
sys.exit(1)
|
|
54
48
|
print(f" ✓ Python version: {py_ver}")
|
|
55
49
|
|
|
56
|
-
|
|
50
|
+
# ── Step 2: Check Docker daemon ──────────────────────────
|
|
51
|
+
print("\n[Step 2/11] Checking Docker daemon...")
|
|
52
|
+
docker_ok, docker_detail = check_docker()
|
|
57
53
|
if not docker_ok:
|
|
58
|
-
print("----------------------------------")
|
|
59
|
-
print("Docker is not installed or not in PATH.")
|
|
60
|
-
print("")
|
|
61
|
-
print("Please install Docker Desktop and rerun:")
|
|
62
|
-
print("memory-os init")
|
|
63
|
-
print("----------------------------------")
|
|
64
|
-
sys.exit(1)
|
|
65
|
-
print(f" ✓ Docker: {docker_ver}")
|
|
66
|
-
|
|
67
|
-
compose_ok, compose_ver = check_docker_compose_installed()
|
|
68
|
-
if not compose_ok:
|
|
69
|
-
print("----------------------------------")
|
|
70
|
-
print("Docker Compose is not installed.")
|
|
71
|
-
print("")
|
|
72
|
-
print("Please install Docker Compose and rerun:")
|
|
73
|
-
print("memory-os init")
|
|
74
|
-
print("----------------------------------")
|
|
75
|
-
sys.exit(1)
|
|
76
|
-
print(f" ✓ Docker Compose: {compose_ver}")
|
|
77
|
-
|
|
78
|
-
if not check_docker_running():
|
|
79
54
|
print("----------------------------------")
|
|
80
55
|
print("Docker Desktop is not running.")
|
|
81
56
|
print("")
|
|
57
|
+
print("stderr:")
|
|
58
|
+
print(docker_detail)
|
|
59
|
+
print("")
|
|
82
60
|
print("Start Docker Desktop and rerun:")
|
|
83
61
|
print("memory-os init")
|
|
84
62
|
print("----------------------------------")
|
|
85
63
|
sys.exit(1)
|
|
86
64
|
print(" ✓ Docker Daemon: Running")
|
|
87
65
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
print("\n[2/7] Creating workspace directories...")
|
|
66
|
+
# ── Step 3: Create workspace ─────────────────────────────
|
|
67
|
+
print("\n[Step 3/11] Creating workspace directories...")
|
|
91
68
|
ensure_workspace("default")
|
|
92
69
|
print(" ✓ Workspace path initialized at ~/.memory-os")
|
|
93
70
|
|
|
94
|
-
#
|
|
95
|
-
print("\n[
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
71
|
+
# ── Step 4: Generate docker-compose.yml ──────────────────
|
|
72
|
+
print("\n[Step 4/11] Generating docker-compose.yml...")
|
|
73
|
+
from infrastructure.config import get_config
|
|
74
|
+
existing_config = get_config()
|
|
75
|
+
existing_password = existing_config.get("neo4j", {}).get("password") or "memory_neo"
|
|
76
|
+
|
|
77
|
+
manager = ComposeManager()
|
|
78
|
+
manager.generate_compose(profile="default", password=existing_password)
|
|
79
|
+
print(" ✓ docker-compose.yml generated at ~/.memory-os/docker-compose.yml")
|
|
80
|
+
|
|
81
|
+
# ── Step 5: Launch Neo4j + Qdrant ─────────────────────────
|
|
82
|
+
print("\n[Step 5/11] Launching local services (Neo4j, Qdrant)...")
|
|
83
|
+
neo4j_ok, _ = check_neo4j()
|
|
84
|
+
qdrant_ok, _ = check_qdrant()
|
|
85
|
+
if neo4j_ok and qdrant_ok:
|
|
86
|
+
print(" ✓ Neo4j already running")
|
|
87
|
+
print(" ✓ Qdrant already running")
|
|
88
|
+
else:
|
|
89
|
+
if not manager.up(profile="default"):
|
|
90
|
+
print("❌ Failed to start docker compose services.")
|
|
91
|
+
sys.exit(1)
|
|
92
|
+
print(" ✓ Containers launched.")
|
|
93
|
+
|
|
94
|
+
# ── Step 6: Wait until healthy ────────────────────────────
|
|
95
|
+
print("\n[Step 6/11] Waiting for services to become healthy...")
|
|
96
|
+
if neo4j_ok and qdrant_ok:
|
|
97
|
+
print(" ✓ Services are healthy.")
|
|
98
|
+
else:
|
|
99
|
+
if not wait_for_services(timeout=60):
|
|
100
|
+
print("❌ Services failed to start or respond to health checks in time.")
|
|
101
|
+
sys.exit(1)
|
|
102
|
+
print(" ✓ Services are healthy.")
|
|
103
|
+
|
|
104
|
+
# ── Step 7: Initialize SQLite ─────────────────────────────
|
|
105
|
+
print("\n[Step 7/11] Initializing SQLite database...")
|
|
106
|
+
os.environ["MEMORY_OS_DB_PATH"] = str(get_db_path("default"))
|
|
107
|
+
init_db()
|
|
108
|
+
print(" ✓ SQLite database schema initialized.")
|
|
109
|
+
|
|
110
|
+
# ── Step 8: Configure API Keys ───────────────────────────
|
|
111
|
+
print("\n[Step 8/11] Configuring API keys & settings...")
|
|
112
|
+
neo4j_password = get_input("Set Neo4j database password", secret=True, default=existing_password)
|
|
113
|
+
groq_api_key = get_input("Enter Groq API Key", secret=True, default=existing_config.get("groq", {}).get("api_key", ""))
|
|
114
|
+
composio_api_key = get_input("Enter Composio API Key", secret=True, default=existing_config.get("composio", {}).get("api_key", ""))
|
|
99
115
|
|
|
100
|
-
|
|
101
|
-
composio_user_id = str(uuid.uuid4())
|
|
116
|
+
composio_user_id = existing_config.get("composio", {}).get("user_id") or str(uuid.uuid4())
|
|
102
117
|
|
|
103
118
|
answers = {
|
|
104
119
|
"neo4j_password": neo4j_password,
|
|
@@ -109,49 +124,16 @@ def execute(args):
|
|
|
109
124
|
|
|
110
125
|
config_dict = generate_default_config(answers)
|
|
111
126
|
save_config(config_dict)
|
|
112
|
-
|
|
113
|
-
# Force reload config in current process memory
|
|
114
127
|
load_config()
|
|
115
128
|
|
|
116
|
-
|
|
117
|
-
|
|
129
|
+
if neo4j_password != existing_password:
|
|
130
|
+
manager.generate_compose(profile="default", password=neo4j_password)
|
|
131
|
+
print(" ✓ docker-compose.yml updated with new password.")
|
|
118
132
|
|
|
119
133
|
print(" ✓ Configuration saved to ~/.memory-os/config.toml")
|
|
120
134
|
|
|
121
|
-
#
|
|
122
|
-
print("\n[
|
|
123
|
-
if not compose_up():
|
|
124
|
-
print("❌ Failed to start docker compose services.")
|
|
125
|
-
sys.exit(1)
|
|
126
|
-
print(" ✓ Containers launched. Waiting for services to become healthy...")
|
|
127
|
-
|
|
128
|
-
if not wait_for_services(timeout=60):
|
|
129
|
-
print("❌ Services failed to start or respond to health checks in time.")
|
|
130
|
-
sys.exit(1)
|
|
131
|
-
print(" ✓ Services are healthy.")
|
|
132
|
-
|
|
133
|
-
# 5. Schema & Database Initialization
|
|
134
|
-
print("\n[5/7] Initializing SQLite database...")
|
|
135
|
-
init_db()
|
|
136
|
-
print(" ✓ SQLite database schema initialized.")
|
|
137
|
-
|
|
138
|
-
# 6. Optional Embedding Model Warming
|
|
139
|
-
print("\n[6/7] Preparing embedding model...")
|
|
140
|
-
warm_model = get_input("Download and cache embedding model (all-MiniLM-L6-v2) now? (Y/n)", default="y").lower()
|
|
141
|
-
if warm_model == "y":
|
|
142
|
-
print(" Downloading model (this may take a minute)...")
|
|
143
|
-
try:
|
|
144
|
-
embedder = Embedder()
|
|
145
|
-
_ = embedder.model
|
|
146
|
-
print(" ✓ Embedding model cached successfully.")
|
|
147
|
-
except Exception as e:
|
|
148
|
-
print(f" ⚠️ Warning: Failed to cache model during setup: {e}")
|
|
149
|
-
print(" Model will be downloaded automatically on the first query.")
|
|
150
|
-
else:
|
|
151
|
-
print(" Skipped model download.")
|
|
152
|
-
|
|
153
|
-
# 7. Optional Composio Integration OAuth
|
|
154
|
-
print("\n[7/7] Configuring integration connectors...")
|
|
135
|
+
# ── Step 9: Authenticate Composio ────────────────────────
|
|
136
|
+
print("\n[Step 9/11] Configuring integration connectors...")
|
|
155
137
|
setup_connectors = get_input("Configure connectors (GitHub, Gmail, Notion) now? (Y/n)", default="y").lower()
|
|
156
138
|
if setup_connectors == "y" and composio_api_key:
|
|
157
139
|
try:
|
|
@@ -174,7 +156,6 @@ def execute(args):
|
|
|
174
156
|
print(f" 👉 Please open this URL in your browser to complete authentication:\n {req.redirect_url}")
|
|
175
157
|
print(" Waiting up to 30 seconds for completion...")
|
|
176
158
|
try:
|
|
177
|
-
# Wait for active connection
|
|
178
159
|
req.wait_for_connection(timeout=30000)
|
|
179
160
|
print(f" ✓ {name} connected successfully!")
|
|
180
161
|
except Exception:
|
|
@@ -186,8 +167,24 @@ def execute(args):
|
|
|
186
167
|
else:
|
|
187
168
|
print(" Skipped connectors configuration.")
|
|
188
169
|
|
|
189
|
-
#
|
|
190
|
-
print("\n
|
|
170
|
+
# ── Step 10: Warm embedding model ─────────────────────────
|
|
171
|
+
print("\n[Step 10/11] Preparing embedding model...")
|
|
172
|
+
warm_model = get_input("Download and cache embedding model (all-MiniLM-L6-v2) now? (Y/n)", default="y").lower()
|
|
173
|
+
if warm_model == "y":
|
|
174
|
+
print(" Downloading model (this may take a minute)...")
|
|
175
|
+
try:
|
|
176
|
+
embedder = Embedder()
|
|
177
|
+
_ = embedder.model
|
|
178
|
+
print(" ✓ Embedding model cached successfully.")
|
|
179
|
+
except Exception as e:
|
|
180
|
+
print(f" ⚠️ Warning: Failed to cache model during setup: {e}")
|
|
181
|
+
print(" Model will be downloaded automatically on the first query.")
|
|
182
|
+
else:
|
|
183
|
+
print(" Skipped model download.")
|
|
184
|
+
|
|
185
|
+
# ── Step 11: Done ─────────────────────────────────────────
|
|
186
|
+
print("\n[Step 11/11] Running initial health checks...")
|
|
187
|
+
print("==================================================")
|
|
191
188
|
print("🏥 RUNNING INITIAL HEALTH CHECKS")
|
|
192
189
|
print("==================================================")
|
|
193
190
|
checks = run_all_checks()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command: memory-os restart
|
|
3
|
+
|
|
4
|
+
Restarts the Docker services (Neo4j and Qdrant) via ComposeManager.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from infrastructure.compose import ComposeManager, wait_for_services
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def execute(args):
|
|
12
|
+
"""Run the restart command."""
|
|
13
|
+
print("Restarting Memory-OS local services (Neo4j, Qdrant)...")
|
|
14
|
+
if not ComposeManager().restart():
|
|
15
|
+
print("❌ Failed to restart docker compose services.")
|
|
16
|
+
sys.exit(1)
|
|
17
|
+
|
|
18
|
+
print("Waiting for services to become healthy...")
|
|
19
|
+
if not wait_for_services(timeout=60):
|
|
20
|
+
print("❌ Services failed to start or respond to health checks in time.")
|
|
21
|
+
sys.exit(1)
|
|
22
|
+
|
|
23
|
+
print("✓ Services restarted successfully and are healthy.")
|
|
@@ -414,6 +414,9 @@ def route_command(args):
|
|
|
414
414
|
elif command == "stop":
|
|
415
415
|
from cli.commands.stop import execute
|
|
416
416
|
execute(args)
|
|
417
|
+
elif command == "restart":
|
|
418
|
+
from cli.commands.restart import execute
|
|
419
|
+
execute(args)
|
|
417
420
|
elif command == "plugins":
|
|
418
421
|
from cli.commands.plugins import execute
|
|
419
422
|
execute(args)
|
|
@@ -118,6 +118,12 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
118
118
|
help="Stop Docker services (preserves data)",
|
|
119
119
|
)
|
|
120
120
|
|
|
121
|
+
# ── restart ────────────────────────────────────────────────
|
|
122
|
+
subparsers.add_parser(
|
|
123
|
+
"restart",
|
|
124
|
+
help="Restart Docker services (Neo4j, Qdrant)",
|
|
125
|
+
)
|
|
126
|
+
|
|
121
127
|
# ── version ───────────────────────────────────────────────
|
|
122
128
|
subparsers.add_parser(
|
|
123
129
|
"version",
|
|
@@ -15,6 +15,7 @@ cli/commands/init.py
|
|
|
15
15
|
cli/commands/logs.py
|
|
16
16
|
cli/commands/monitor.py
|
|
17
17
|
cli/commands/plugins.py
|
|
18
|
+
cli/commands/restart.py
|
|
18
19
|
cli/commands/start.py
|
|
19
20
|
cli/commands/status.py
|
|
20
21
|
cli/commands/stop.py
|
|
@@ -54,5 +55,7 @@ storage/schema.sql
|
|
|
54
55
|
storage/tech_detector.py
|
|
55
56
|
tests/test_cli_integration.py
|
|
56
57
|
tests/test_commands_phase2.py
|
|
58
|
+
tests/test_compose_manager.py
|
|
57
59
|
tests/test_first_time_user_experience.py
|
|
60
|
+
tests/test_infrastructure_stabilization.py
|
|
58
61
|
tests/test_v1_features.py
|
|
@@ -226,55 +226,6 @@ def get_vector_index_stats() -> dict:
|
|
|
226
226
|
"exists": False
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
def get_vector_chunks(repo_name: str, limit: int = 5) -> list:
|
|
230
|
-
"""Retrieve the first `limit` chunks for a given repository from Qdrant.
|
|
231
|
-
Returns a list of Record objects.
|
|
232
|
-
"""
|
|
233
|
-
client = get_qdrant_client()
|
|
234
|
-
try:
|
|
235
|
-
filter_expr = models.Filter(
|
|
236
|
-
must=[
|
|
237
|
-
models.FieldCondition(
|
|
238
|
-
key="repository_name",
|
|
239
|
-
match=models.MatchValue(value=repo_name)
|
|
240
|
-
)
|
|
241
|
-
]
|
|
242
|
-
)
|
|
243
|
-
points, _ = client.scroll(
|
|
244
|
-
collection_name=COLLECTION_NAME,
|
|
245
|
-
scroll_filter=filter_expr,
|
|
246
|
-
limit=limit,
|
|
247
|
-
with_payload=True,
|
|
248
|
-
with_vectors=False
|
|
249
|
-
)
|
|
250
|
-
return points
|
|
251
|
-
except Exception as e:
|
|
252
|
-
import logging
|
|
253
|
-
logging.getLogger("vector_store").error(f"Error fetching vector chunks: {e}")
|
|
254
|
-
return []
|
|
255
|
-
|
|
256
|
-
def count_vector_chunks(repo_name: str) -> int:
|
|
257
|
-
"""Count the total number of vectors for a given repository in Qdrant."""
|
|
258
|
-
client = get_qdrant_client()
|
|
259
|
-
try:
|
|
260
|
-
filter_expr = models.Filter(
|
|
261
|
-
must=[
|
|
262
|
-
models.FieldCondition(
|
|
263
|
-
key="repository_name",
|
|
264
|
-
match=models.MatchValue(value=repo_name)
|
|
265
|
-
)
|
|
266
|
-
]
|
|
267
|
-
)
|
|
268
|
-
result = client.count(
|
|
269
|
-
collection_name=COLLECTION_NAME,
|
|
270
|
-
count_filter=filter_expr,
|
|
271
|
-
exact=True
|
|
272
|
-
)
|
|
273
|
-
return result.count
|
|
274
|
-
except Exception as e:
|
|
275
|
-
import logging
|
|
276
|
-
logging.getLogger("vector_store").error(f"Error counting vector chunks: {e}")
|
|
277
|
-
return 0
|
|
278
229
|
|
|
279
230
|
def run_semantic_search(query: str, limit: int = 5, source_filter: str = None, raw_scores: bool = False, repo_filter: str = None) -> list:
|
|
280
231
|
"""Perform raw vector search on the Qdrant database, with optional source and repository filters."""
|