basic-memory 0.13.0b6__py3-none-any.whl → 0.13.2__py3-none-any.whl
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.
Potentially problematic release.
This version of basic-memory might be problematic. Click here for more details.
- basic_memory/__init__.py +4 -1
- basic_memory/cli/commands/project.py +10 -25
- basic_memory/mcp/tools/project_management.py +7 -5
- basic_memory/schemas/project_info.py +6 -0
- basic_memory/services/project_service.py +4 -4
- {basic_memory-0.13.0b6.dist-info → basic_memory-0.13.2.dist-info}/METADATA +1 -1
- {basic_memory-0.13.0b6.dist-info → basic_memory-0.13.2.dist-info}/RECORD +10 -10
- {basic_memory-0.13.0b6.dist-info → basic_memory-0.13.2.dist-info}/WHEEL +0 -0
- {basic_memory-0.13.0b6.dist-info → basic_memory-0.13.2.dist-info}/entry_points.txt +0 -0
- {basic_memory-0.13.0b6.dist-info → basic_memory-0.13.2.dist-info}/licenses/LICENSE +0 -0
basic_memory/__init__.py
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"""basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
|
|
2
2
|
|
|
3
|
+
# Package version - updated by release automation
|
|
4
|
+
__version__ = "0.13.2"
|
|
5
|
+
|
|
3
6
|
# API version for FastAPI - independent of package version
|
|
4
|
-
|
|
7
|
+
__api_version__ = "v0"
|
|
@@ -9,7 +9,6 @@ from rich.console import Console
|
|
|
9
9
|
from rich.table import Table
|
|
10
10
|
|
|
11
11
|
from basic_memory.cli.app import app
|
|
12
|
-
from basic_memory.config import config
|
|
13
12
|
from basic_memory.mcp.project_session import session
|
|
14
13
|
from basic_memory.mcp.resources.project_info import project_info
|
|
15
14
|
import json
|
|
@@ -24,6 +23,7 @@ from basic_memory.mcp.tools.utils import call_post
|
|
|
24
23
|
from basic_memory.schemas.project_info import ProjectStatusResponse
|
|
25
24
|
from basic_memory.mcp.tools.utils import call_delete
|
|
26
25
|
from basic_memory.mcp.tools.utils import call_put
|
|
26
|
+
from basic_memory.utils import generate_permalink
|
|
27
27
|
|
|
28
28
|
console = Console()
|
|
29
29
|
|
|
@@ -44,11 +44,8 @@ def format_path(path: str) -> str:
|
|
|
44
44
|
def list_projects() -> None:
|
|
45
45
|
"""List all configured projects."""
|
|
46
46
|
# Use API to list projects
|
|
47
|
-
|
|
48
|
-
project_url = config.project_url
|
|
49
|
-
|
|
50
47
|
try:
|
|
51
|
-
response = asyncio.run(call_get(client,
|
|
48
|
+
response = asyncio.run(call_get(client, "/projects/projects"))
|
|
52
49
|
result = ProjectList.model_validate(response.json())
|
|
53
50
|
|
|
54
51
|
table = Table(title="Basic Memory Projects")
|
|
@@ -65,7 +62,6 @@ def list_projects() -> None:
|
|
|
65
62
|
console.print(table)
|
|
66
63
|
except Exception as e:
|
|
67
64
|
console.print(f"[red]Error listing projects: {str(e)}[/red]")
|
|
68
|
-
console.print("[yellow]Note: Make sure the Basic Memory server is running.[/yellow]")
|
|
69
65
|
raise typer.Exit(1)
|
|
70
66
|
|
|
71
67
|
|
|
@@ -80,16 +76,14 @@ def add_project(
|
|
|
80
76
|
resolved_path = os.path.abspath(os.path.expanduser(path))
|
|
81
77
|
|
|
82
78
|
try:
|
|
83
|
-
project_url = config.project_url
|
|
84
79
|
data = {"name": name, "path": resolved_path, "set_default": set_default}
|
|
85
80
|
|
|
86
|
-
response = asyncio.run(call_post(client,
|
|
81
|
+
response = asyncio.run(call_post(client, "/projects/projects", json=data))
|
|
87
82
|
result = ProjectStatusResponse.model_validate(response.json())
|
|
88
83
|
|
|
89
84
|
console.print(f"[green]{result.message}[/green]")
|
|
90
85
|
except Exception as e:
|
|
91
86
|
console.print(f"[red]Error adding project: {str(e)}[/red]")
|
|
92
|
-
console.print("[yellow]Note: Make sure the Basic Memory server is running.[/yellow]")
|
|
93
87
|
raise typer.Exit(1)
|
|
94
88
|
|
|
95
89
|
# Display usage hint
|
|
@@ -105,15 +99,13 @@ def remove_project(
|
|
|
105
99
|
) -> None:
|
|
106
100
|
"""Remove a project from configuration."""
|
|
107
101
|
try:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
response = asyncio.run(call_delete(client, f"{project_url}/project/projects/{name}"))
|
|
102
|
+
project_name = generate_permalink(name)
|
|
103
|
+
response = asyncio.run(call_delete(client, f"/projects/{project_name}"))
|
|
111
104
|
result = ProjectStatusResponse.model_validate(response.json())
|
|
112
105
|
|
|
113
106
|
console.print(f"[green]{result.message}[/green]")
|
|
114
107
|
except Exception as e:
|
|
115
108
|
console.print(f"[red]Error removing project: {str(e)}[/red]")
|
|
116
|
-
console.print("[yellow]Note: Make sure the Basic Memory server is running.[/yellow]")
|
|
117
109
|
raise typer.Exit(1)
|
|
118
110
|
|
|
119
111
|
# Show this message regardless of method used
|
|
@@ -126,20 +118,16 @@ def set_default_project(
|
|
|
126
118
|
) -> None:
|
|
127
119
|
"""Set the default project and activate it for the current session."""
|
|
128
120
|
try:
|
|
129
|
-
|
|
121
|
+
project_name = generate_permalink(name)
|
|
130
122
|
|
|
131
|
-
response = asyncio.run(call_put(client, f"
|
|
123
|
+
response = asyncio.run(call_put(client, f"projects/{project_name}/default"))
|
|
132
124
|
result = ProjectStatusResponse.model_validate(response.json())
|
|
133
125
|
|
|
134
126
|
console.print(f"[green]{result.message}[/green]")
|
|
135
127
|
except Exception as e:
|
|
136
128
|
console.print(f"[red]Error setting default project: {str(e)}[/red]")
|
|
137
|
-
console.print("[yellow]Note: Make sure the Basic Memory server is running.[/yellow]")
|
|
138
129
|
raise typer.Exit(1)
|
|
139
130
|
|
|
140
|
-
# Always activate it for the current session
|
|
141
|
-
os.environ["BASIC_MEMORY_PROJECT"] = name
|
|
142
|
-
|
|
143
131
|
# Reload configuration to apply the change
|
|
144
132
|
from importlib import reload
|
|
145
133
|
from basic_memory import config as config_module
|
|
@@ -149,21 +137,18 @@ def set_default_project(
|
|
|
149
137
|
console.print("[green]Project activated for current session[/green]")
|
|
150
138
|
|
|
151
139
|
|
|
152
|
-
@project_app.command("sync")
|
|
140
|
+
@project_app.command("sync-config")
|
|
153
141
|
def synchronize_projects() -> None:
|
|
154
|
-
"""Synchronize
|
|
142
|
+
"""Synchronize project config between configuration file and database."""
|
|
155
143
|
# Call the API to synchronize projects
|
|
156
144
|
|
|
157
|
-
project_url = config.project_url
|
|
158
|
-
|
|
159
145
|
try:
|
|
160
|
-
response = asyncio.run(call_post(client,
|
|
146
|
+
response = asyncio.run(call_post(client, "/projects/sync"))
|
|
161
147
|
result = ProjectStatusResponse.model_validate(response.json())
|
|
162
148
|
|
|
163
149
|
console.print(f"[green]{result.message}[/green]")
|
|
164
150
|
except Exception as e: # pragma: no cover
|
|
165
151
|
console.print(f"[red]Error synchronizing projects: {str(e)}[/red]")
|
|
166
|
-
console.print("[yellow]Note: Make sure the Basic Memory server is running.[/yellow]")
|
|
167
152
|
raise typer.Exit(1)
|
|
168
153
|
|
|
169
154
|
|
|
@@ -16,6 +16,7 @@ from basic_memory.mcp.server import mcp
|
|
|
16
16
|
from basic_memory.mcp.tools.utils import call_get, call_put, call_post, call_delete
|
|
17
17
|
from basic_memory.schemas import ProjectInfoResponse
|
|
18
18
|
from basic_memory.schemas.project_info import ProjectList, ProjectStatusResponse, ProjectInfoRequest
|
|
19
|
+
from basic_memory.utils import generate_permalink
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@mcp.tool()
|
|
@@ -77,6 +78,7 @@ async def switch_project(project_name: str, ctx: Context | None = None) -> str:
|
|
|
77
78
|
if ctx: # pragma: no cover
|
|
78
79
|
await ctx.info(f"Switching to project: {project_name}")
|
|
79
80
|
|
|
81
|
+
project_permalink = generate_permalink(project_name)
|
|
80
82
|
current_project = session.get_current_project()
|
|
81
83
|
try:
|
|
82
84
|
# Validate project exists by getting project list
|
|
@@ -84,13 +86,13 @@ async def switch_project(project_name: str, ctx: Context | None = None) -> str:
|
|
|
84
86
|
project_list = ProjectList.model_validate(response.json())
|
|
85
87
|
|
|
86
88
|
# Check if project exists
|
|
87
|
-
project_exists = any(p.
|
|
89
|
+
project_exists = any(p.permalink == project_permalink for p in project_list.projects)
|
|
88
90
|
if not project_exists:
|
|
89
91
|
available_projects = [p.name for p in project_list.projects]
|
|
90
92
|
return f"Error: Project '{project_name}' not found. Available projects: {', '.join(available_projects)}"
|
|
91
93
|
|
|
92
94
|
# Switch to the project
|
|
93
|
-
session.set_current_project(
|
|
95
|
+
session.set_current_project(project_permalink)
|
|
94
96
|
current_project = session.get_current_project()
|
|
95
97
|
project_config = get_project_config(current_project)
|
|
96
98
|
|
|
@@ -99,11 +101,11 @@ async def switch_project(project_name: str, ctx: Context | None = None) -> str:
|
|
|
99
101
|
response = await call_get(
|
|
100
102
|
client,
|
|
101
103
|
f"{project_config.project_url}/project/info",
|
|
102
|
-
params={"project_name":
|
|
104
|
+
params={"project_name": project_permalink},
|
|
103
105
|
)
|
|
104
106
|
project_info = ProjectInfoResponse.model_validate(response.json())
|
|
105
107
|
|
|
106
|
-
result = f"✓ Switched to {
|
|
108
|
+
result = f"✓ Switched to {project_permalink} project\n\n"
|
|
107
109
|
result += "Project Summary:\n"
|
|
108
110
|
result += f"• {project_info.statistics.total_entities} entities\n"
|
|
109
111
|
result += f"• {project_info.statistics.total_observations} observations\n"
|
|
@@ -329,4 +331,4 @@ async def delete_project(project_name: str, ctx: Context | None = None) -> str:
|
|
|
329
331
|
result += "Files remain on disk but project is no longer tracked by Basic Memory.\n"
|
|
330
332
|
result += "Re-add the project to access its content again.\n"
|
|
331
333
|
|
|
332
|
-
return add_project_metadata(result, session.get_current_project())
|
|
334
|
+
return add_project_metadata(result, session.get_current_project())
|
|
@@ -6,6 +6,8 @@ from typing import Dict, List, Optional, Any
|
|
|
6
6
|
|
|
7
7
|
from pydantic import Field, BaseModel
|
|
8
8
|
|
|
9
|
+
from basic_memory.utils import generate_permalink
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
class ProjectStatistics(BaseModel):
|
|
11
13
|
"""Statistics about the current project."""
|
|
@@ -183,6 +185,10 @@ class ProjectItem(BaseModel):
|
|
|
183
185
|
name: str
|
|
184
186
|
path: str
|
|
185
187
|
is_default: bool = False
|
|
188
|
+
|
|
189
|
+
@property
|
|
190
|
+
def permalink(self) -> str: # pragma: no cover
|
|
191
|
+
return generate_permalink(self.name)
|
|
186
192
|
|
|
187
193
|
|
|
188
194
|
class ProjectList(BaseModel):
|
|
@@ -207,7 +207,7 @@ class ProjectService:
|
|
|
207
207
|
|
|
208
208
|
# Get all projects from database
|
|
209
209
|
db_projects = await self.repository.get_active_projects()
|
|
210
|
-
|
|
210
|
+
db_projects_by_permalink = {p.permalink: p for p in db_projects}
|
|
211
211
|
|
|
212
212
|
# Get all projects from configuration and normalize names if needed
|
|
213
213
|
config_projects = config_manager.projects.copy()
|
|
@@ -235,7 +235,7 @@ class ProjectService:
|
|
|
235
235
|
|
|
236
236
|
# Add projects that exist in config but not in DB
|
|
237
237
|
for name, path in config_projects.items():
|
|
238
|
-
if name not in
|
|
238
|
+
if name not in db_projects_by_permalink:
|
|
239
239
|
logger.info(f"Adding project '{name}' to database")
|
|
240
240
|
project_data = {
|
|
241
241
|
"name": name,
|
|
@@ -247,7 +247,7 @@ class ProjectService:
|
|
|
247
247
|
await self.repository.create(project_data)
|
|
248
248
|
|
|
249
249
|
# Add projects that exist in DB but not in config to config
|
|
250
|
-
for name, project in
|
|
250
|
+
for name, project in db_projects_by_permalink.items():
|
|
251
251
|
if name not in config_projects:
|
|
252
252
|
logger.info(f"Adding project '{name}' to configuration")
|
|
253
253
|
config_manager.add_project(name, project.path)
|
|
@@ -668,4 +668,4 @@ class ProjectService:
|
|
|
668
668
|
database_size=db_size_readable,
|
|
669
669
|
watch_status=watch_status,
|
|
670
670
|
timestamp=datetime.now(),
|
|
671
|
-
)
|
|
671
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: basic-memory
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.2
|
|
4
4
|
Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
|
|
5
5
|
Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
|
|
6
6
|
Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
basic_memory/__init__.py,sha256=
|
|
1
|
+
basic_memory/__init__.py,sha256=s4xkAkIj-yvZFc_ImULxCYGhhrih4z5rAGrb5c81sqc,256
|
|
2
2
|
basic_memory/config.py,sha256=lNpbn-b1k9nunQ-htciYQHC8XatRIhc_m6SN2Pbvp-E,11101
|
|
3
3
|
basic_memory/db.py,sha256=X4-uyEZdJXVLfFDTpcNZxWzawRZXhDdKoEFWAGgE4Lk,6193
|
|
4
4
|
basic_memory/deps.py,sha256=zXOhqXCoSVIa1iIcO8U6uUiofJn5eT4ycwJkH9I2kX4,12102
|
|
@@ -39,7 +39,7 @@ basic_memory/cli/commands/import_claude_conversations.py,sha256=sXnP0hjfwUapwHQD
|
|
|
39
39
|
basic_memory/cli/commands/import_claude_projects.py,sha256=mWYIeA-mu_Pq23R7OEtY2XHXG5CAh1dMGIBhckB4zRk,2811
|
|
40
40
|
basic_memory/cli/commands/import_memory_json.py,sha256=Vz5rt7KCel5B3Dtv57WPEUJTHCMwFUqQlOCm2djwUi8,2867
|
|
41
41
|
basic_memory/cli/commands/mcp.py,sha256=jmRUv1U5FT3AQ1cDbvTfAUnjhBw6UsNEmIkpbNr-_qQ,3093
|
|
42
|
-
basic_memory/cli/commands/project.py,sha256=
|
|
42
|
+
basic_memory/cli/commands/project.py,sha256=MqRxfIvPJ7BD823gXXeEC0sEMutIdKVsoTMC2XCka94,12258
|
|
43
43
|
basic_memory/cli/commands/status.py,sha256=708EK8-iPjyc1iE5MPECzAyZraGYoGpvYjLwTm-BlQs,5719
|
|
44
44
|
basic_memory/cli/commands/sync.py,sha256=gOU_onrMj9_IRiIe8FWU_FLEvfjcOt-qhrvvFJuU-ws,8010
|
|
45
45
|
basic_memory/cli/commands/tool.py,sha256=my-kALn3khv1W2Avi736NrHsfkpbyP57mDi5LjHwqe0,9540
|
|
@@ -79,7 +79,7 @@ basic_memory/mcp/tools/delete_note.py,sha256=tSyRc_VgBmLyVeenClwX1Sk--LKcGahAMzT
|
|
|
79
79
|
basic_memory/mcp/tools/edit_note.py,sha256=q4x-f7-j_l-wzm17-AVFT1_WGCo0Cq4lI3seYSe21aY,13570
|
|
80
80
|
basic_memory/mcp/tools/list_directory.py,sha256=-FxDsCru5YD02M4qkQDAurEJWyRaC7YI4YR6zg0atR8,5236
|
|
81
81
|
basic_memory/mcp/tools/move_note.py,sha256=esnbddG2OcmIgRNuQwx5OhlwZ1CWcOheg3hUobsEcq0,11320
|
|
82
|
-
basic_memory/mcp/tools/project_management.py,sha256=
|
|
82
|
+
basic_memory/mcp/tools/project_management.py,sha256=aLkfgEL3RlRztzERQur283cIed4mv14eAP7kh6gzHpw,12293
|
|
83
83
|
basic_memory/mcp/tools/read_content.py,sha256=4FTw13B8UjVVhR78NJB9HKeJb_nA6-BGT1WdGtekN5Q,8596
|
|
84
84
|
basic_memory/mcp/tools/read_note.py,sha256=GdsJLkcDrCBnmNeM9BZRx9Xs2LUqH5ty_E471T9Kf1Y,7493
|
|
85
85
|
basic_memory/mcp/tools/recent_activity.py,sha256=XVjNJAJnmxvzx9_Ls1A-QOd2yTR7pJlSTTuRxSivmN4,4833
|
|
@@ -107,7 +107,7 @@ basic_memory/schemas/delete.py,sha256=UAR2JK99WMj3gP-yoGWlHD3eZEkvlTSRf8QoYIE-Wf
|
|
|
107
107
|
basic_memory/schemas/directory.py,sha256=F9_LrJqRqb_kO08GDKJzXLb2nhbYG2PdVUo5eDD_Kf4,881
|
|
108
108
|
basic_memory/schemas/importer.py,sha256=FAh-RGxuhFW2rz3HFxwLzENJOiGgbTR2hUeXZZpM3OA,663
|
|
109
109
|
basic_memory/schemas/memory.py,sha256=6YjEyJ9GJLC4VrFD0EnoRDTfg-Sf6g0D4bhL9rwNBi4,5816
|
|
110
|
-
basic_memory/schemas/project_info.py,sha256=
|
|
110
|
+
basic_memory/schemas/project_info.py,sha256=4yM51eGchS75ao2qyyVsk8_JyWRKJ0cJM3UzQF3G2ls,7050
|
|
111
111
|
basic_memory/schemas/prompt.py,sha256=SpIVfZprQT8E5uP40j3CpBc2nHKflwOo3iZD7BFPIHE,3648
|
|
112
112
|
basic_memory/schemas/request.py,sha256=Mv5EvrLZlFIiPr8dOjo_4QXvkseYhQI7cd_X2zDsxQM,3760
|
|
113
113
|
basic_memory/schemas/response.py,sha256=lVYR31DTtSeFRddGWX_wQWnQgyiwX0LEpNJ4f4lKpTM,6440
|
|
@@ -121,7 +121,7 @@ basic_memory/services/file_service.py,sha256=jCrmnEkTQ4t9HF7L_M6BL7tdDqjjzty9hpT
|
|
|
121
121
|
basic_memory/services/initialization.py,sha256=6ZeuTInPksyre4pjmiK_GXi5o_mJk3mfqGGH6apHxko,9271
|
|
122
122
|
basic_memory/services/link_resolver.py,sha256=1-_VFsvqdT5rVBHe8Jrq63U59XQ0hxGezxY8c24Tiow,4594
|
|
123
123
|
basic_memory/services/migration_service.py,sha256=pFJCSD7UgHLx1CHvtN4Df1CzDEp-CZ9Vqx4XYn1m1M0,6096
|
|
124
|
-
basic_memory/services/project_service.py,sha256=
|
|
124
|
+
basic_memory/services/project_service.py,sha256=Nz6N-2rk6DLLKBmtTBcPQATh_nzkLuD8LWWDAwgl6Oc,26875
|
|
125
125
|
basic_memory/services/search_service.py,sha256=c5Ky0ufz7YPFgHhVzNRQ4OecF_JUrt7nALzpMjobW4M,12782
|
|
126
126
|
basic_memory/services/service.py,sha256=V-d_8gOV07zGIQDpL-Ksqs3ZN9l3qf3HZOK1f_YNTag,336
|
|
127
127
|
basic_memory/services/sync_status_service.py,sha256=PRAnYrsNJY8EIlxaxCrDsY0TjySDdhktjta8ReQZyiY,6838
|
|
@@ -131,8 +131,8 @@ basic_memory/sync/sync_service.py,sha256=AxC5J1YTcPWTmA0HdzvOZBthi4-_LZ44kNF0KQo
|
|
|
131
131
|
basic_memory/sync/watch_service.py,sha256=JAumrHUjV1lF9NtEK32jgg0myWBfLXotNXxONeIV9SM,15316
|
|
132
132
|
basic_memory/templates/prompts/continue_conversation.hbs,sha256=begMFHOPN3aCm5sHz5PlKMLOfZ8hlpFxFJ-hgy0T9K4,3075
|
|
133
133
|
basic_memory/templates/prompts/search.hbs,sha256=H1cCIsHKp4VC1GrH2KeUB8pGe5vXFPqb2VPotypmeCA,3098
|
|
134
|
-
basic_memory-0.13.
|
|
135
|
-
basic_memory-0.13.
|
|
136
|
-
basic_memory-0.13.
|
|
137
|
-
basic_memory-0.13.
|
|
138
|
-
basic_memory-0.13.
|
|
134
|
+
basic_memory-0.13.2.dist-info/METADATA,sha256=kTZGjOSHLa84vzIf6BuhEpDxzos3c-MWFGi-VcgLe2o,15469
|
|
135
|
+
basic_memory-0.13.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
136
|
+
basic_memory-0.13.2.dist-info/entry_points.txt,sha256=wvE2mRF6-Pg4weIYcfQ-86NOLZD4WJg7F7TIsRVFLb8,90
|
|
137
|
+
basic_memory-0.13.2.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
138
|
+
basic_memory-0.13.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|