basic-memory 0.13.1__py3-none-any.whl → 0.13.3__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 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.3"
5
+
3
6
  # API version for FastAPI - independent of package version
4
- __version__ = "v0"
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, f"{project_url}/project/projects"))
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, f"{project_url}/project/projects", json=data))
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
- project_url = config.project_url
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
- project_url = config.project_url
121
+ project_name = generate_permalink(name)
130
122
 
131
- response = asyncio.run(call_put(client, f"{project_url}/project/projects/{name}/default"))
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 projects between configuration file and database."""
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, f"{project_url}/project/sync"))
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
 
basic_memory/config.py CHANGED
@@ -4,7 +4,7 @@ import json
4
4
  import os
5
5
  from dataclasses import dataclass
6
6
  from pathlib import Path
7
- from typing import Any, Dict, Literal, Optional, List
7
+ from typing import Any, Dict, Literal, Optional, List, Tuple
8
8
 
9
9
  from loguru import logger
10
10
  from pydantic import Field, field_validator
@@ -196,7 +196,8 @@ class ConfigManager:
196
196
 
197
197
  def add_project(self, name: str, path: str) -> ProjectConfig:
198
198
  """Add a new project to the configuration."""
199
- if name in self.config.projects: # pragma: no cover
199
+ project_name, _ = self.get_project(name)
200
+ if project_name: # pragma: no cover
200
201
  raise ValueError(f"Project '{name}' already exists")
201
202
 
202
203
  # Ensure the path exists
@@ -209,10 +210,12 @@ class ConfigManager:
209
210
 
210
211
  def remove_project(self, name: str) -> None:
211
212
  """Remove a project from the configuration."""
212
- if name not in self.config.projects: # pragma: no cover
213
+
214
+ project_name, path = self.get_project(name)
215
+ if not project_name: # pragma: no cover
213
216
  raise ValueError(f"Project '{name}' not found")
214
217
 
215
- if name == self.config.default_project: # pragma: no cover
218
+ if project_name == self.config.default_project: # pragma: no cover
216
219
  raise ValueError(f"Cannot remove the default project '{name}'")
217
220
 
218
221
  del self.config.projects[name]
@@ -220,12 +223,21 @@ class ConfigManager:
220
223
 
221
224
  def set_default_project(self, name: str) -> None:
222
225
  """Set the default project."""
223
- if name not in self.config.projects: # pragma: no cover
226
+ project_name, path = self.get_project(name)
227
+ if not project_name: # pragma: no cover
224
228
  raise ValueError(f"Project '{name}' not found")
225
229
 
226
230
  self.config.default_project = name
227
231
  self.save_config(self.config)
228
232
 
233
+ def get_project(self, name: str) -> Tuple[str, str] | Tuple[None, None]:
234
+ """Look up a project from the configuration by name or permalink"""
235
+ project_permalink = generate_permalink(name)
236
+ for name, path in app_config.projects.items():
237
+ if project_permalink == generate_permalink(name):
238
+ return name, path
239
+ return None, None
240
+
229
241
 
230
242
  def get_project_config(project_name: Optional[str] = None) -> ProjectConfig:
231
243
  """
@@ -256,11 +268,14 @@ def get_project_config(project_name: Optional[str] = None) -> ProjectConfig:
256
268
  # the config contains a dict[str,str] of project names and absolute paths
257
269
  assert actual_project_name is not None, "actual_project_name cannot be None"
258
270
 
259
- project_path = app_config.projects.get(actual_project_name)
260
- if not project_path: # pragma: no cover
261
- raise ValueError(f"Project '{actual_project_name}' not found")
271
+ project_permalink = generate_permalink(actual_project_name)
272
+
273
+ for name, path in app_config.projects.items():
274
+ if project_permalink == generate_permalink(name):
275
+ return ProjectConfig(name=name, home=Path(path))
262
276
 
263
- return ProjectConfig(name=actual_project_name, home=Path(project_path))
277
+ # otherwise raise error
278
+ raise ValueError(f"Project '{actual_project_name}' not found")
264
279
 
265
280
 
266
281
  # Create config manager
@@ -9,13 +9,13 @@ from textwrap import dedent
9
9
  from fastmcp import Context
10
10
  from loguru import logger
11
11
 
12
- from basic_memory.config import get_project_config
13
12
  from basic_memory.mcp.async_client import client
14
13
  from basic_memory.mcp.project_session import session, add_project_metadata
15
14
  from basic_memory.mcp.server import mcp
16
15
  from basic_memory.mcp.tools.utils import call_get, call_put, call_post, call_delete
17
16
  from basic_memory.schemas import ProjectInfoResponse
18
17
  from basic_memory.schemas.project_info import ProjectList, ProjectStatusResponse, ProjectInfoRequest
18
+ from basic_memory.utils import generate_permalink
19
19
 
20
20
 
21
21
  @mcp.tool()
@@ -77,33 +77,45 @@ async def switch_project(project_name: str, ctx: Context | None = None) -> str:
77
77
  if ctx: # pragma: no cover
78
78
  await ctx.info(f"Switching to project: {project_name}")
79
79
 
80
+ project_permalink = generate_permalink(project_name)
80
81
  current_project = session.get_current_project()
81
82
  try:
82
83
  # Validate project exists by getting project list
83
84
  response = await call_get(client, "/projects/projects")
84
85
  project_list = ProjectList.model_validate(response.json())
85
86
 
86
- # Check if project exists
87
- project_exists = any(p.name == project_name for p in project_list.projects)
88
- if not project_exists:
87
+ # Find the project by name (case-insensitive) or permalink
88
+ target_project = None
89
+ for p in project_list.projects:
90
+ # Match by permalink (handles case-insensitive input)
91
+ if p.permalink == project_permalink:
92
+ target_project = p
93
+ break
94
+ # Also match by name comparison (case-insensitive)
95
+ if p.name.lower() == project_name.lower():
96
+ target_project = p
97
+ break
98
+
99
+ if not target_project:
89
100
  available_projects = [p.name for p in project_list.projects]
90
101
  return f"Error: Project '{project_name}' not found. Available projects: {', '.join(available_projects)}"
91
102
 
92
- # Switch to the project
93
- session.set_current_project(project_name)
103
+ # Switch to the project using the canonical name from database
104
+ canonical_name = target_project.name
105
+ session.set_current_project(canonical_name)
94
106
  current_project = session.get_current_project()
95
- project_config = get_project_config(current_project)
96
107
 
97
108
  # Get project info to show summary
98
109
  try:
110
+ current_project_permalink = generate_permalink(canonical_name)
99
111
  response = await call_get(
100
112
  client,
101
- f"{project_config.project_url}/project/info",
102
- params={"project_name": project_name},
113
+ f"/{current_project_permalink}/project/info",
114
+ params={"project_name": canonical_name},
103
115
  )
104
116
  project_info = ProjectInfoResponse.model_validate(response.json())
105
117
 
106
- result = f"✓ Switched to {project_name} project\n\n"
118
+ result = f"✓ Switched to {canonical_name} project\n\n"
107
119
  result += "Project Summary:\n"
108
120
  result += f"• {project_info.statistics.total_entities} entities\n"
109
121
  result += f"• {project_info.statistics.total_observations} observations\n"
@@ -111,11 +123,11 @@ async def switch_project(project_name: str, ctx: Context | None = None) -> str:
111
123
 
112
124
  except Exception as e:
113
125
  # If we can't get project info, still confirm the switch
114
- logger.warning(f"Could not get project info for {project_name}: {e}")
115
- result = f"✓ Switched to {project_name} project\n\n"
126
+ logger.warning(f"Could not get project info for {canonical_name}: {e}")
127
+ result = f"✓ Switched to {canonical_name} project\n\n"
116
128
  result += "Project summary unavailable.\n"
117
129
 
118
- return add_project_metadata(result, project_name)
130
+ return add_project_metadata(result, canonical_name)
119
131
 
120
132
  except Exception as e:
121
133
  logger.error(f"Error switching to project {project_name}: {e}")
@@ -163,13 +175,13 @@ async def get_current_project(ctx: Context | None = None) -> str:
163
175
  await ctx.info("Getting current project information")
164
176
 
165
177
  current_project = session.get_current_project()
166
- project_config = get_project_config(current_project)
167
178
  result = f"Current project: {current_project}\n\n"
168
179
 
169
- # get project stats
180
+ # get project stats (use permalink in URL path)
181
+ current_project_permalink = generate_permalink(current_project)
170
182
  response = await call_get(
171
183
  client,
172
- f"{project_config.project_url}/project/info",
184
+ f"/{current_project_permalink}/project/info",
173
185
  params={"project_name": current_project},
174
186
  )
175
187
  project_info = ProjectInfoResponse.model_validate(response.json())
@@ -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."""
@@ -184,6 +186,10 @@ class ProjectItem(BaseModel):
184
186
  path: str
185
187
  is_default: bool = False
186
188
 
189
+ @property
190
+ def permalink(self) -> str: # pragma: no cover
191
+ return generate_permalink(self.name)
192
+
187
193
 
188
194
  class ProjectList(BaseModel):
189
195
  """Response model for listing projects."""
@@ -64,8 +64,10 @@ class ProjectService:
64
64
  return await self.repository.find_all()
65
65
 
66
66
  async def get_project(self, name: str) -> Optional[Project]:
67
- """Get the file path for a project by name."""
68
- return await self.repository.get_by_name(name)
67
+ """Get the file path for a project by name or permalink."""
68
+ return await self.repository.get_by_name(name) or await self.repository.get_by_permalink(
69
+ name
70
+ )
69
71
 
70
72
  async def add_project(self, name: str, path: str, set_default: bool = False) -> None:
71
73
  """Add a new project to the configuration and database.
@@ -207,7 +209,7 @@ class ProjectService:
207
209
 
208
210
  # Get all projects from database
209
211
  db_projects = await self.repository.get_active_projects()
210
- db_projects_by_name = {p.name: p for p in db_projects}
212
+ db_projects_by_permalink = {p.permalink: p for p in db_projects}
211
213
 
212
214
  # Get all projects from configuration and normalize names if needed
213
215
  config_projects = config_manager.projects.copy()
@@ -235,7 +237,7 @@ class ProjectService:
235
237
 
236
238
  # Add projects that exist in config but not in DB
237
239
  for name, path in config_projects.items():
238
- if name not in db_projects_by_name:
240
+ if name not in db_projects_by_permalink:
239
241
  logger.info(f"Adding project '{name}' to database")
240
242
  project_data = {
241
243
  "name": name,
@@ -247,7 +249,7 @@ class ProjectService:
247
249
  await self.repository.create(project_data)
248
250
 
249
251
  # Add projects that exist in DB but not in config to config
250
- for name, project in db_projects_by_name.items():
252
+ for name, project in db_projects_by_permalink.items():
251
253
  if name not in config_projects:
252
254
  logger.info(f"Adding project '{name}' to configuration")
253
255
  config_manager.add_project(name, project.path)
@@ -347,12 +349,15 @@ class ProjectService:
347
349
  # Use specified project or fall back to config project
348
350
  project_name = project_name or config.project
349
351
  # Get project path from configuration
350
- project_path = config_manager.projects.get(project_name)
351
- if not project_path: # pragma: no cover
352
+ name, project_path = config_manager.get_project(project_name)
353
+ if not name: # pragma: no cover
352
354
  raise ValueError(f"Project '{project_name}' not found in configuration")
353
355
 
356
+ assert project_path is not None
357
+ project_permalink = generate_permalink(project_name)
358
+
354
359
  # Get project from database to get project_id
355
- db_project = await self.repository.get_by_name(project_name)
360
+ db_project = await self.repository.get_by_permalink(project_permalink)
356
361
  if not db_project: # pragma: no cover
357
362
  raise ValueError(f"Project '{project_name}' not found in database")
358
363
 
@@ -367,7 +372,7 @@ class ProjectService:
367
372
 
368
373
  # Get enhanced project information from database
369
374
  db_projects = await self.repository.get_active_projects()
370
- db_projects_by_name = {p.name: p for p in db_projects}
375
+ db_projects_by_permalink = {p.permalink: p for p in db_projects}
371
376
 
372
377
  # Get default project info
373
378
  default_project = config_manager.default_project
@@ -375,7 +380,8 @@ class ProjectService:
375
380
  # Convert config projects to include database info
376
381
  enhanced_projects = {}
377
382
  for name, path in config_manager.projects.items():
378
- db_project = db_projects_by_name.get(name)
383
+ config_permalink = generate_permalink(name)
384
+ db_project = db_projects_by_permalink.get(config_permalink)
379
385
  enhanced_projects[name] = {
380
386
  "path": path,
381
387
  "active": db_project.is_active if db_project else True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.13.1
3
+ Version: 0.13.3
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,5 +1,5 @@
1
- basic_memory/__init__.py,sha256=kYTgbNYjpTOTrVbmkdvP8eII6KD0j3qf2LgF-q01dQQ,178
2
- basic_memory/config.py,sha256=lNpbn-b1k9nunQ-htciYQHC8XatRIhc_m6SN2Pbvp-E,11101
1
+ basic_memory/__init__.py,sha256=gFZyAxMhYIZW4hrgsq2HqiV8YOzz-s3ySX0gg0SYwZw,256
2
+ basic_memory/config.py,sha256=20Na6lkEIZ00T-a5PDKnebWocF_L_q3Qf6pg8i4RQfU,11680
3
3
  basic_memory/db.py,sha256=X4-uyEZdJXVLfFDTpcNZxWzawRZXhDdKoEFWAGgE4Lk,6193
4
4
  basic_memory/deps.py,sha256=zXOhqXCoSVIa1iIcO8U6uUiofJn5eT4ycwJkH9I2kX4,12102
5
5
  basic_memory/file_utils.py,sha256=eaxTKLLEbTIy_Mb_Iv_Dmt4IXAJSrZGVi-Knrpyci3E,6700
@@ -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=YkVYcjxQOVhxIX1M0g_vMaP5dTinYvSnUQIjeOPg8HE,12971
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=XtZTFWi7--ku6yUR_vwHQx2Ka3vz3pCcWMhVa_y4CQs,12162
82
+ basic_memory/mcp/tools/project_management.py,sha256=sqDnIn1CCkxjH4NoJlqvzVYsZEEeX0zaCqrydKyTOeQ,12734
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=cHXgp9k4RbgolIpCIEcrb-RR9m7WL72KFGwknig4H-E,6884
110
+ basic_memory/schemas/project_info.py,sha256=fcNjUpe25_5uMmKy142ib3p5qEakzs1WJPLkgol5zyw,7047
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=nWnrlnjISqtGP6ui1BR8rSTNFzwExW8u7mRYPtWJLok,26856
124
+ basic_memory/services/project_service.py,sha256=YDZl_e7R36D6KcObpBeMqIiM05oh9nOIfZFIFgIRxbY,27151
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.1.dist-info/METADATA,sha256=QvMkk2cw4_9jp63Zg4DJw3X20RnS9bCjHoBTyhFlLug,15469
135
- basic_memory-0.13.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
136
- basic_memory-0.13.1.dist-info/entry_points.txt,sha256=wvE2mRF6-Pg4weIYcfQ-86NOLZD4WJg7F7TIsRVFLb8,90
137
- basic_memory-0.13.1.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
138
- basic_memory-0.13.1.dist-info/RECORD,,
134
+ basic_memory-0.13.3.dist-info/METADATA,sha256=PCN1ddrrnPGZqD454E0_D3dykPuOMZ9163efIr1vzH4,15469
135
+ basic_memory-0.13.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
136
+ basic_memory-0.13.3.dist-info/entry_points.txt,sha256=wvE2mRF6-Pg4weIYcfQ-86NOLZD4WJg7F7TIsRVFLb8,90
137
+ basic_memory-0.13.3.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
138
+ basic_memory-0.13.3.dist-info/RECORD,,