basic-memory 0.7.0__py3-none-any.whl → 0.17.4__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 +5 -1
- basic_memory/alembic/alembic.ini +119 -0
- basic_memory/alembic/env.py +130 -20
- basic_memory/alembic/migrations.py +4 -9
- basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +131 -0
- basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +51 -0
- basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +120 -0
- basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +112 -0
- basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +24 -0
- basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +49 -0
- basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +49 -0
- basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +56 -0
- basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +44 -0
- basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +113 -0
- basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +37 -0
- basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +239 -0
- basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +173 -0
- basic_memory/api/app.py +87 -20
- basic_memory/api/container.py +133 -0
- basic_memory/api/routers/__init__.py +4 -1
- basic_memory/api/routers/directory_router.py +84 -0
- basic_memory/api/routers/importer_router.py +152 -0
- basic_memory/api/routers/knowledge_router.py +180 -23
- basic_memory/api/routers/management_router.py +80 -0
- basic_memory/api/routers/memory_router.py +9 -64
- basic_memory/api/routers/project_router.py +460 -0
- basic_memory/api/routers/prompt_router.py +260 -0
- basic_memory/api/routers/resource_router.py +136 -11
- basic_memory/api/routers/search_router.py +5 -5
- basic_memory/api/routers/utils.py +169 -0
- basic_memory/api/template_loader.py +292 -0
- basic_memory/api/v2/__init__.py +35 -0
- basic_memory/api/v2/routers/__init__.py +21 -0
- basic_memory/api/v2/routers/directory_router.py +93 -0
- basic_memory/api/v2/routers/importer_router.py +181 -0
- basic_memory/api/v2/routers/knowledge_router.py +427 -0
- basic_memory/api/v2/routers/memory_router.py +130 -0
- basic_memory/api/v2/routers/project_router.py +359 -0
- basic_memory/api/v2/routers/prompt_router.py +269 -0
- basic_memory/api/v2/routers/resource_router.py +286 -0
- basic_memory/api/v2/routers/search_router.py +73 -0
- basic_memory/cli/app.py +80 -10
- basic_memory/cli/auth.py +300 -0
- basic_memory/cli/commands/__init__.py +15 -2
- basic_memory/cli/commands/cloud/__init__.py +6 -0
- basic_memory/cli/commands/cloud/api_client.py +127 -0
- basic_memory/cli/commands/cloud/bisync_commands.py +110 -0
- basic_memory/cli/commands/cloud/cloud_utils.py +108 -0
- basic_memory/cli/commands/cloud/core_commands.py +195 -0
- basic_memory/cli/commands/cloud/rclone_commands.py +397 -0
- basic_memory/cli/commands/cloud/rclone_config.py +110 -0
- basic_memory/cli/commands/cloud/rclone_installer.py +263 -0
- basic_memory/cli/commands/cloud/upload.py +240 -0
- basic_memory/cli/commands/cloud/upload_command.py +124 -0
- basic_memory/cli/commands/command_utils.py +99 -0
- basic_memory/cli/commands/db.py +87 -12
- basic_memory/cli/commands/format.py +198 -0
- basic_memory/cli/commands/import_chatgpt.py +47 -223
- basic_memory/cli/commands/import_claude_conversations.py +48 -171
- basic_memory/cli/commands/import_claude_projects.py +53 -160
- basic_memory/cli/commands/import_memory_json.py +55 -111
- basic_memory/cli/commands/mcp.py +67 -11
- basic_memory/cli/commands/project.py +889 -0
- basic_memory/cli/commands/status.py +52 -34
- basic_memory/cli/commands/telemetry.py +81 -0
- basic_memory/cli/commands/tool.py +341 -0
- basic_memory/cli/container.py +84 -0
- basic_memory/cli/main.py +14 -6
- basic_memory/config.py +580 -26
- basic_memory/db.py +285 -28
- basic_memory/deps/__init__.py +293 -0
- basic_memory/deps/config.py +26 -0
- basic_memory/deps/db.py +56 -0
- basic_memory/deps/importers.py +200 -0
- basic_memory/deps/projects.py +238 -0
- basic_memory/deps/repositories.py +179 -0
- basic_memory/deps/services.py +480 -0
- basic_memory/deps.py +16 -185
- basic_memory/file_utils.py +318 -54
- basic_memory/ignore_utils.py +297 -0
- basic_memory/importers/__init__.py +27 -0
- basic_memory/importers/base.py +100 -0
- basic_memory/importers/chatgpt_importer.py +245 -0
- basic_memory/importers/claude_conversations_importer.py +192 -0
- basic_memory/importers/claude_projects_importer.py +184 -0
- basic_memory/importers/memory_json_importer.py +128 -0
- basic_memory/importers/utils.py +61 -0
- basic_memory/markdown/entity_parser.py +182 -23
- basic_memory/markdown/markdown_processor.py +70 -7
- basic_memory/markdown/plugins.py +43 -23
- basic_memory/markdown/schemas.py +1 -1
- basic_memory/markdown/utils.py +38 -14
- basic_memory/mcp/async_client.py +135 -4
- basic_memory/mcp/clients/__init__.py +28 -0
- basic_memory/mcp/clients/directory.py +70 -0
- basic_memory/mcp/clients/knowledge.py +176 -0
- basic_memory/mcp/clients/memory.py +120 -0
- basic_memory/mcp/clients/project.py +89 -0
- basic_memory/mcp/clients/resource.py +71 -0
- basic_memory/mcp/clients/search.py +65 -0
- basic_memory/mcp/container.py +110 -0
- basic_memory/mcp/project_context.py +155 -0
- basic_memory/mcp/prompts/__init__.py +19 -0
- basic_memory/mcp/prompts/ai_assistant_guide.py +70 -0
- basic_memory/mcp/prompts/continue_conversation.py +62 -0
- basic_memory/mcp/prompts/recent_activity.py +188 -0
- basic_memory/mcp/prompts/search.py +57 -0
- basic_memory/mcp/prompts/utils.py +162 -0
- basic_memory/mcp/resources/ai_assistant_guide.md +283 -0
- basic_memory/mcp/resources/project_info.py +71 -0
- basic_memory/mcp/server.py +61 -9
- basic_memory/mcp/tools/__init__.py +33 -21
- basic_memory/mcp/tools/build_context.py +120 -0
- basic_memory/mcp/tools/canvas.py +152 -0
- basic_memory/mcp/tools/chatgpt_tools.py +190 -0
- basic_memory/mcp/tools/delete_note.py +249 -0
- basic_memory/mcp/tools/edit_note.py +325 -0
- basic_memory/mcp/tools/list_directory.py +157 -0
- basic_memory/mcp/tools/move_note.py +549 -0
- basic_memory/mcp/tools/project_management.py +204 -0
- basic_memory/mcp/tools/read_content.py +281 -0
- basic_memory/mcp/tools/read_note.py +265 -0
- basic_memory/mcp/tools/recent_activity.py +528 -0
- basic_memory/mcp/tools/search.py +377 -24
- basic_memory/mcp/tools/utils.py +402 -16
- basic_memory/mcp/tools/view_note.py +78 -0
- basic_memory/mcp/tools/write_note.py +230 -0
- basic_memory/models/__init__.py +3 -2
- basic_memory/models/knowledge.py +82 -17
- basic_memory/models/project.py +93 -0
- basic_memory/models/search.py +68 -8
- basic_memory/project_resolver.py +222 -0
- basic_memory/repository/__init__.py +2 -0
- basic_memory/repository/entity_repository.py +437 -8
- basic_memory/repository/observation_repository.py +36 -3
- basic_memory/repository/postgres_search_repository.py +451 -0
- basic_memory/repository/project_info_repository.py +10 -0
- basic_memory/repository/project_repository.py +140 -0
- basic_memory/repository/relation_repository.py +79 -4
- basic_memory/repository/repository.py +148 -29
- basic_memory/repository/search_index_row.py +95 -0
- basic_memory/repository/search_repository.py +79 -268
- basic_memory/repository/search_repository_base.py +241 -0
- basic_memory/repository/sqlite_search_repository.py +437 -0
- basic_memory/runtime.py +61 -0
- basic_memory/schemas/__init__.py +22 -9
- basic_memory/schemas/base.py +131 -12
- basic_memory/schemas/cloud.py +50 -0
- basic_memory/schemas/directory.py +31 -0
- basic_memory/schemas/importer.py +35 -0
- basic_memory/schemas/memory.py +194 -25
- basic_memory/schemas/project_info.py +213 -0
- basic_memory/schemas/prompt.py +90 -0
- basic_memory/schemas/request.py +56 -2
- basic_memory/schemas/response.py +85 -28
- basic_memory/schemas/search.py +36 -35
- basic_memory/schemas/sync_report.py +72 -0
- basic_memory/schemas/v2/__init__.py +27 -0
- basic_memory/schemas/v2/entity.py +133 -0
- basic_memory/schemas/v2/resource.py +47 -0
- basic_memory/services/__init__.py +2 -1
- basic_memory/services/context_service.py +451 -138
- basic_memory/services/directory_service.py +310 -0
- basic_memory/services/entity_service.py +636 -71
- basic_memory/services/exceptions.py +21 -0
- basic_memory/services/file_service.py +402 -33
- basic_memory/services/initialization.py +216 -0
- basic_memory/services/link_resolver.py +50 -56
- basic_memory/services/project_service.py +888 -0
- basic_memory/services/search_service.py +232 -37
- basic_memory/sync/__init__.py +4 -2
- basic_memory/sync/background_sync.py +26 -0
- basic_memory/sync/coordinator.py +160 -0
- basic_memory/sync/sync_service.py +1200 -109
- basic_memory/sync/watch_service.py +432 -135
- basic_memory/telemetry.py +249 -0
- basic_memory/templates/prompts/continue_conversation.hbs +110 -0
- basic_memory/templates/prompts/search.hbs +101 -0
- basic_memory/utils.py +407 -54
- basic_memory-0.17.4.dist-info/METADATA +617 -0
- basic_memory-0.17.4.dist-info/RECORD +193 -0
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/WHEEL +1 -1
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/entry_points.txt +1 -0
- basic_memory/alembic/README +0 -1
- basic_memory/cli/commands/sync.py +0 -206
- basic_memory/cli/commands/tools.py +0 -157
- basic_memory/mcp/tools/knowledge.py +0 -68
- basic_memory/mcp/tools/memory.py +0 -170
- basic_memory/mcp/tools/notes.py +0 -202
- basic_memory/schemas/discovery.py +0 -28
- basic_memory/sync/file_change_scanner.py +0 -158
- basic_memory/sync/utils.py +0 -31
- basic_memory-0.7.0.dist-info/METADATA +0 -378
- basic_memory-0.7.0.dist-info/RECORD +0 -82
- {basic_memory-0.7.0.dist-info → basic_memory-0.17.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""Read note tool for Basic Memory MCP server."""
|
|
2
|
+
|
|
3
|
+
from textwrap import dedent
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from loguru import logger
|
|
7
|
+
from fastmcp import Context
|
|
8
|
+
|
|
9
|
+
from basic_memory.mcp.async_client import get_client
|
|
10
|
+
from basic_memory.mcp.project_context import get_active_project
|
|
11
|
+
from basic_memory.mcp.server import mcp
|
|
12
|
+
from basic_memory.mcp.tools.search import search_notes
|
|
13
|
+
from basic_memory.telemetry import track_mcp_tool
|
|
14
|
+
from basic_memory.schemas.memory import memory_url_path
|
|
15
|
+
from basic_memory.utils import validate_project_path
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@mcp.tool(
|
|
19
|
+
description="Read a markdown note by title or permalink.",
|
|
20
|
+
)
|
|
21
|
+
async def read_note(
|
|
22
|
+
identifier: str,
|
|
23
|
+
project: Optional[str] = None,
|
|
24
|
+
page: int = 1,
|
|
25
|
+
page_size: int = 10,
|
|
26
|
+
context: Context | None = None,
|
|
27
|
+
) -> str:
|
|
28
|
+
"""Return the raw markdown for a note, or guidance text if no match is found.
|
|
29
|
+
|
|
30
|
+
Finds and retrieves a note by its title, permalink, or content search,
|
|
31
|
+
returning the raw markdown content including observations, relations, and metadata.
|
|
32
|
+
|
|
33
|
+
Project Resolution:
|
|
34
|
+
Server resolves projects in this order: Single Project Mode → project parameter → default project.
|
|
35
|
+
If project unknown, use list_memory_projects() or recent_activity() first.
|
|
36
|
+
|
|
37
|
+
This tool will try multiple lookup strategies to find the most relevant note:
|
|
38
|
+
1. Direct permalink lookup
|
|
39
|
+
2. Title search fallback
|
|
40
|
+
3. Text search as last resort
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
project: Project name to read from. Optional - server will resolve using the
|
|
44
|
+
hierarchy above. If unknown, use list_memory_projects() to discover
|
|
45
|
+
available projects.
|
|
46
|
+
identifier: The title or permalink of the note to read
|
|
47
|
+
Can be a full memory:// URL, a permalink, a title, or search text
|
|
48
|
+
page: Page number for paginated results (default: 1)
|
|
49
|
+
page_size: Number of items per page (default: 10)
|
|
50
|
+
context: Optional FastMCP context for performance caching.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
The full markdown content of the note if found, or helpful guidance if not found.
|
|
54
|
+
Content includes frontmatter, observations, relations, and all markdown formatting.
|
|
55
|
+
|
|
56
|
+
Examples:
|
|
57
|
+
# Read by permalink
|
|
58
|
+
read_note("my-research", "specs/search-spec")
|
|
59
|
+
|
|
60
|
+
# Read by title
|
|
61
|
+
read_note("work-project", "Search Specification")
|
|
62
|
+
|
|
63
|
+
# Read with memory URL
|
|
64
|
+
read_note("my-research", "memory://specs/search-spec")
|
|
65
|
+
|
|
66
|
+
# Read with pagination
|
|
67
|
+
read_note("work-project", "Project Updates", page=2, page_size=5)
|
|
68
|
+
|
|
69
|
+
# Read recent meeting notes
|
|
70
|
+
read_note("team-docs", "Weekly Standup")
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
HTTPError: If project doesn't exist or is inaccessible
|
|
74
|
+
SecurityError: If identifier attempts path traversal
|
|
75
|
+
|
|
76
|
+
Note:
|
|
77
|
+
If the exact note isn't found, this tool provides helpful suggestions
|
|
78
|
+
including related notes, search commands, and note creation templates.
|
|
79
|
+
"""
|
|
80
|
+
track_mcp_tool("read_note")
|
|
81
|
+
async with get_client() as client:
|
|
82
|
+
# Get and validate the project
|
|
83
|
+
active_project = await get_active_project(client, project, context)
|
|
84
|
+
|
|
85
|
+
# Validate identifier to prevent path traversal attacks
|
|
86
|
+
# We need to check both the raw identifier and the processed path
|
|
87
|
+
processed_path = memory_url_path(identifier)
|
|
88
|
+
project_path = active_project.home
|
|
89
|
+
|
|
90
|
+
if not validate_project_path(identifier, project_path) or not validate_project_path(
|
|
91
|
+
processed_path, project_path
|
|
92
|
+
):
|
|
93
|
+
logger.warning(
|
|
94
|
+
"Attempted path traversal attack blocked",
|
|
95
|
+
identifier=identifier,
|
|
96
|
+
processed_path=processed_path,
|
|
97
|
+
project=active_project.name,
|
|
98
|
+
)
|
|
99
|
+
return f"# Error\n\nIdentifier '{identifier}' is not allowed - paths must stay within project boundaries"
|
|
100
|
+
|
|
101
|
+
# Get the file via REST API - first try direct identifier resolution
|
|
102
|
+
entity_path = memory_url_path(identifier)
|
|
103
|
+
logger.info(
|
|
104
|
+
f"Attempting to read note from Project: {active_project.name} identifier: {entity_path}"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Import here to avoid circular import
|
|
108
|
+
from basic_memory.mcp.clients import KnowledgeClient, ResourceClient
|
|
109
|
+
|
|
110
|
+
# Use typed clients for API calls
|
|
111
|
+
knowledge_client = KnowledgeClient(client, active_project.external_id)
|
|
112
|
+
resource_client = ResourceClient(client, active_project.external_id)
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
# Try to resolve identifier to entity ID
|
|
116
|
+
entity_id = await knowledge_client.resolve_entity(entity_path)
|
|
117
|
+
|
|
118
|
+
# Fetch content using entity ID
|
|
119
|
+
response = await resource_client.read(entity_id, page=page, page_size=page_size)
|
|
120
|
+
|
|
121
|
+
# If successful, return the content
|
|
122
|
+
if response.status_code == 200:
|
|
123
|
+
logger.info("Returning read_note result from resource: {path}", path=entity_path)
|
|
124
|
+
return response.text
|
|
125
|
+
except Exception as e: # pragma: no cover
|
|
126
|
+
logger.info(f"Direct lookup failed for '{entity_path}': {e}")
|
|
127
|
+
# Continue to fallback methods
|
|
128
|
+
|
|
129
|
+
# Fallback 1: Try title search via API
|
|
130
|
+
logger.info(f"Search title for: {identifier}")
|
|
131
|
+
title_results = await search_notes.fn(
|
|
132
|
+
query=identifier, search_type="title", project=project, context=context
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Handle both SearchResponse object and error strings
|
|
136
|
+
if title_results and hasattr(title_results, "results") and title_results.results:
|
|
137
|
+
result = title_results.results[0] # Get the first/best match
|
|
138
|
+
if result.permalink:
|
|
139
|
+
try:
|
|
140
|
+
# Resolve the permalink to entity ID
|
|
141
|
+
entity_id = await knowledge_client.resolve_entity(result.permalink)
|
|
142
|
+
|
|
143
|
+
# Fetch content using the entity ID
|
|
144
|
+
response = await resource_client.read(entity_id, page=page, page_size=page_size)
|
|
145
|
+
|
|
146
|
+
if response.status_code == 200:
|
|
147
|
+
logger.info(f"Found note by title search: {result.permalink}")
|
|
148
|
+
return response.text
|
|
149
|
+
except Exception as e: # pragma: no cover
|
|
150
|
+
logger.info(
|
|
151
|
+
f"Failed to fetch content for found title match {result.permalink}: {e}"
|
|
152
|
+
)
|
|
153
|
+
else:
|
|
154
|
+
logger.info(
|
|
155
|
+
f"No results in title search for: {identifier} in project {active_project.name}"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Fallback 2: Text search as a last resort
|
|
159
|
+
logger.info(f"Title search failed, trying text search for: {identifier}")
|
|
160
|
+
text_results = await search_notes.fn(
|
|
161
|
+
query=identifier, search_type="text", project=project, context=context
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# We didn't find a direct match, construct a helpful error message
|
|
165
|
+
# Handle both SearchResponse object and error strings
|
|
166
|
+
if not text_results or not hasattr(text_results, "results") or not text_results.results:
|
|
167
|
+
# No results at all
|
|
168
|
+
return format_not_found_message(active_project.name, identifier)
|
|
169
|
+
else:
|
|
170
|
+
# We found some related results
|
|
171
|
+
return format_related_results(active_project.name, identifier, text_results.results[:5])
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def format_not_found_message(project: str | None, identifier: str) -> str:
|
|
175
|
+
"""Format a helpful message when no note was found."""
|
|
176
|
+
return dedent(f"""
|
|
177
|
+
# Note Not Found in {project}: "{identifier}"
|
|
178
|
+
|
|
179
|
+
I couldn't find any notes matching "{identifier}". Here are some suggestions:
|
|
180
|
+
|
|
181
|
+
## Check Identifier Type
|
|
182
|
+
- If you provided a title, try using the exact permalink instead
|
|
183
|
+
- If you provided a permalink, check for typos or try a broader search
|
|
184
|
+
|
|
185
|
+
## Search Instead
|
|
186
|
+
Try searching for related content:
|
|
187
|
+
```
|
|
188
|
+
search_notes(project="{project}", query="{identifier}")
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Recent Activity
|
|
192
|
+
Check recently modified notes:
|
|
193
|
+
```
|
|
194
|
+
recent_activity(timeframe="7d")
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Create New Note
|
|
198
|
+
This might be a good opportunity to create a new note on this topic:
|
|
199
|
+
```
|
|
200
|
+
write_note(
|
|
201
|
+
project="{project}",
|
|
202
|
+
title="{identifier.capitalize()}",
|
|
203
|
+
content='''
|
|
204
|
+
# {identifier.capitalize()}
|
|
205
|
+
|
|
206
|
+
## Overview
|
|
207
|
+
[Your content here]
|
|
208
|
+
|
|
209
|
+
## Observations
|
|
210
|
+
- [category] [Observation about {identifier}]
|
|
211
|
+
|
|
212
|
+
## Relations
|
|
213
|
+
- relates_to [[Related Topic]]
|
|
214
|
+
''',
|
|
215
|
+
folder="notes"
|
|
216
|
+
)
|
|
217
|
+
```
|
|
218
|
+
""")
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def format_related_results(project: str | None, identifier: str, results) -> str:
|
|
222
|
+
"""Format a helpful message with related results when an exact match wasn't found."""
|
|
223
|
+
message = dedent(f"""
|
|
224
|
+
# Note Not Found in {project}: "{identifier}"
|
|
225
|
+
|
|
226
|
+
I couldn't find an exact match for "{identifier}", but I found some related notes:
|
|
227
|
+
|
|
228
|
+
""")
|
|
229
|
+
|
|
230
|
+
for i, result in enumerate(results):
|
|
231
|
+
message += dedent(f"""
|
|
232
|
+
## {i + 1}. {result.title}
|
|
233
|
+
- **Type**: {result.type.value}
|
|
234
|
+
- **Permalink**: {result.permalink}
|
|
235
|
+
|
|
236
|
+
You can read this note with:
|
|
237
|
+
```
|
|
238
|
+
read_note(project="{project}", {result.permalink}")
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
""")
|
|
242
|
+
|
|
243
|
+
message += dedent(f"""
|
|
244
|
+
## Try More Specific Lookup
|
|
245
|
+
For exact matches, try using the full permalink from one of the results above.
|
|
246
|
+
|
|
247
|
+
## Search For More Results
|
|
248
|
+
To see more related content:
|
|
249
|
+
```
|
|
250
|
+
search_notes(project="{project}", query="{identifier}")
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Create New Note
|
|
254
|
+
If none of these match what you're looking for, consider creating a new note:
|
|
255
|
+
```
|
|
256
|
+
write_note(
|
|
257
|
+
project="{project}",
|
|
258
|
+
title="[Your title]",
|
|
259
|
+
content="[Your content]",
|
|
260
|
+
folder="notes"
|
|
261
|
+
)
|
|
262
|
+
```
|
|
263
|
+
""")
|
|
264
|
+
|
|
265
|
+
return message
|