basic-memory 0.8.0__py3-none-any.whl → 0.10.0__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 +1 -1
- basic_memory/alembic/migrations.py +4 -9
- basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +106 -0
- basic_memory/api/app.py +9 -6
- basic_memory/api/routers/__init__.py +2 -1
- basic_memory/api/routers/knowledge_router.py +30 -4
- basic_memory/api/routers/memory_router.py +3 -2
- basic_memory/api/routers/project_info_router.py +274 -0
- basic_memory/api/routers/search_router.py +22 -4
- basic_memory/cli/app.py +54 -3
- basic_memory/cli/commands/__init__.py +15 -2
- basic_memory/cli/commands/db.py +9 -13
- basic_memory/cli/commands/import_chatgpt.py +31 -36
- basic_memory/cli/commands/import_claude_conversations.py +32 -35
- basic_memory/cli/commands/import_claude_projects.py +34 -37
- basic_memory/cli/commands/import_memory_json.py +26 -28
- basic_memory/cli/commands/mcp.py +7 -1
- basic_memory/cli/commands/project.py +119 -0
- basic_memory/cli/commands/project_info.py +167 -0
- basic_memory/cli/commands/status.py +7 -9
- basic_memory/cli/commands/sync.py +54 -9
- basic_memory/cli/commands/{tools.py → tool.py} +92 -19
- basic_memory/cli/main.py +40 -1
- basic_memory/config.py +157 -10
- basic_memory/db.py +19 -4
- basic_memory/deps.py +10 -3
- basic_memory/file_utils.py +34 -18
- basic_memory/markdown/markdown_processor.py +1 -1
- basic_memory/markdown/utils.py +5 -0
- basic_memory/mcp/main.py +1 -2
- basic_memory/mcp/prompts/__init__.py +6 -2
- basic_memory/mcp/prompts/ai_assistant_guide.py +9 -10
- basic_memory/mcp/prompts/continue_conversation.py +65 -126
- basic_memory/mcp/prompts/recent_activity.py +55 -13
- basic_memory/mcp/prompts/search.py +72 -17
- basic_memory/mcp/prompts/utils.py +139 -82
- basic_memory/mcp/server.py +1 -1
- basic_memory/mcp/tools/__init__.py +11 -22
- basic_memory/mcp/tools/build_context.py +85 -0
- basic_memory/mcp/tools/canvas.py +17 -19
- basic_memory/mcp/tools/delete_note.py +28 -0
- basic_memory/mcp/tools/project_info.py +51 -0
- basic_memory/mcp/tools/{resource.py → read_content.py} +42 -5
- basic_memory/mcp/tools/read_note.py +190 -0
- basic_memory/mcp/tools/recent_activity.py +100 -0
- basic_memory/mcp/tools/search.py +56 -17
- basic_memory/mcp/tools/utils.py +245 -17
- basic_memory/mcp/tools/write_note.py +124 -0
- basic_memory/models/search.py +2 -1
- basic_memory/repository/entity_repository.py +3 -2
- basic_memory/repository/project_info_repository.py +9 -0
- basic_memory/repository/repository.py +23 -6
- basic_memory/repository/search_repository.py +33 -10
- basic_memory/schemas/__init__.py +12 -0
- basic_memory/schemas/memory.py +3 -2
- basic_memory/schemas/project_info.py +96 -0
- basic_memory/schemas/search.py +27 -32
- basic_memory/services/context_service.py +3 -3
- basic_memory/services/entity_service.py +8 -2
- basic_memory/services/file_service.py +107 -57
- basic_memory/services/link_resolver.py +5 -45
- basic_memory/services/search_service.py +45 -16
- basic_memory/sync/sync_service.py +274 -39
- basic_memory/sync/watch_service.py +174 -34
- basic_memory/utils.py +40 -40
- basic_memory-0.10.0.dist-info/METADATA +386 -0
- basic_memory-0.10.0.dist-info/RECORD +99 -0
- basic_memory/mcp/prompts/json_canvas_spec.py +0 -25
- basic_memory/mcp/tools/knowledge.py +0 -68
- basic_memory/mcp/tools/memory.py +0 -177
- basic_memory/mcp/tools/notes.py +0 -201
- basic_memory-0.8.0.dist-info/METADATA +0 -379
- basic_memory-0.8.0.dist-info/RECORD +0 -91
- {basic_memory-0.8.0.dist-info → basic_memory-0.10.0.dist-info}/WHEEL +0 -0
- {basic_memory-0.8.0.dist-info → basic_memory-0.10.0.dist-info}/entry_points.txt +0 -0
- {basic_memory-0.8.0.dist-info → basic_memory-0.10.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,22 +5,23 @@ providing context from previous interactions to maintain continuity.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from textwrap import dedent
|
|
8
|
-
from typing import Optional,
|
|
8
|
+
from typing import Optional, Annotated
|
|
9
9
|
|
|
10
10
|
from loguru import logger
|
|
11
|
-
import logfire
|
|
12
11
|
from pydantic import Field
|
|
13
12
|
|
|
13
|
+
from basic_memory.mcp.prompts.utils import format_prompt_context, PromptContext, PromptContextItem
|
|
14
14
|
from basic_memory.mcp.server import mcp
|
|
15
|
-
from basic_memory.mcp.tools.
|
|
15
|
+
from basic_memory.mcp.tools.build_context import build_context
|
|
16
|
+
from basic_memory.mcp.tools.recent_activity import recent_activity
|
|
16
17
|
from basic_memory.mcp.tools.search import search
|
|
17
18
|
from basic_memory.schemas.base import TimeFrame
|
|
18
19
|
from basic_memory.schemas.memory import GraphContext
|
|
19
|
-
from basic_memory.schemas.search import SearchQuery
|
|
20
|
+
from basic_memory.schemas.search import SearchQuery, SearchItemType
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
@mcp.prompt(
|
|
23
|
-
name="
|
|
24
|
+
name="Continue Conversation",
|
|
24
25
|
description="Continue a previous conversation",
|
|
25
26
|
)
|
|
26
27
|
async def continue_conversation(
|
|
@@ -42,131 +43,69 @@ async def continue_conversation(
|
|
|
42
43
|
Returns:
|
|
43
44
|
Context from previous sessions on this topic
|
|
44
45
|
"""
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
logger.info(f"Continuing session, topic: {topic}, timeframe: {timeframe}")
|
|
47
|
+
|
|
48
|
+
# If topic provided, search for it
|
|
49
|
+
if topic:
|
|
50
|
+
search_results = await search(
|
|
51
|
+
SearchQuery(text=topic, after_date=timeframe, types=[SearchItemType.ENTITY])
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Build context from results
|
|
55
|
+
contexts = []
|
|
56
|
+
for result in search_results.results:
|
|
57
|
+
if hasattr(result, "permalink") and result.permalink:
|
|
58
|
+
context: GraphContext = await build_context(f"memory://{result.permalink}")
|
|
59
|
+
if context.primary_results:
|
|
60
|
+
contexts.append(
|
|
61
|
+
PromptContextItem(
|
|
62
|
+
primary_results=context.primary_results[:1], # pyright: ignore
|
|
63
|
+
related_results=context.related_results[:3], # pyright: ignore
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
# get context for the top 3 results
|
|
68
|
+
prompt_context = format_prompt_context(
|
|
69
|
+
PromptContext(topic=topic, timeframe=timeframe, results=contexts) # pyright: ignore
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
else:
|
|
61
73
|
# If no topic, get recent activity
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return dedent(f"""
|
|
81
|
-
# Continuing conversation on: {topic}
|
|
82
|
-
|
|
83
|
-
This is a memory retrieval session.
|
|
84
|
-
Please use the available basic-memory tools to gather relevant context before responding.
|
|
85
|
-
Start by executing one of the suggested commands below to retrieve content.
|
|
86
|
-
|
|
87
|
-
I couldn't find any recent work specifically on this topic.
|
|
88
|
-
|
|
89
|
-
## Suggestions
|
|
90
|
-
- Try a different search term
|
|
91
|
-
- Check recent activity with `recent_activity(timeframe="1w")`
|
|
92
|
-
- Start a new topic with `write_note(...)`
|
|
93
|
-
""")
|
|
94
|
-
|
|
95
|
-
# Start building our summary with header
|
|
96
|
-
summary = dedent(f"""
|
|
97
|
-
# Continuing conversation on: {topic}
|
|
98
|
-
|
|
99
|
-
This is a memory retrieval session.
|
|
100
|
-
Please use the available basic-memory tools to gather relevant context before responding.
|
|
101
|
-
Start by executing one of the suggested commands below to retrieve content.
|
|
102
|
-
|
|
103
|
-
Here's what I found about the previous conversation:
|
|
104
|
-
""")
|
|
105
|
-
|
|
106
|
-
# Track what we've added to avoid duplicates
|
|
107
|
-
added_permalinks = set()
|
|
108
|
-
sections = []
|
|
109
|
-
|
|
110
|
-
# Process each context
|
|
111
|
-
for context in contexts:
|
|
112
|
-
# Add primary results
|
|
113
|
-
for primary in context.primary_results:
|
|
114
|
-
if hasattr(primary, "permalink") and primary.permalink not in added_permalinks:
|
|
115
|
-
added_permalinks.add(primary.permalink)
|
|
116
|
-
|
|
117
|
-
section = dedent(f"""
|
|
118
|
-
## {primary.title}
|
|
119
|
-
- **Type**: {primary.type}
|
|
120
|
-
""")
|
|
121
|
-
|
|
122
|
-
# Add creation date if available
|
|
123
|
-
if hasattr(primary, "created_at"):
|
|
124
|
-
section += f"- **Created**: {primary.created_at.strftime('%Y-%m-%d %H:%M')}\n"
|
|
125
|
-
|
|
126
|
-
section += dedent(f"""
|
|
127
|
-
|
|
128
|
-
You can read this document with: `read_note("{primary.permalink}")`
|
|
129
|
-
""")
|
|
130
|
-
|
|
131
|
-
# Add related documents if available
|
|
132
|
-
related_by_type = {}
|
|
133
|
-
if context.related_results:
|
|
134
|
-
for related in context.related_results:
|
|
135
|
-
if hasattr(related, "relation_type") and related.relation_type: # pyright: ignore
|
|
136
|
-
if related.relation_type not in related_by_type: # pyright: ignore
|
|
137
|
-
related_by_type[related.relation_type] = [] # pyright: ignore
|
|
138
|
-
related_by_type[related.relation_type].append(related) # pyright: ignore
|
|
139
|
-
|
|
140
|
-
if related_by_type:
|
|
141
|
-
section += dedent("""
|
|
142
|
-
### Related Documents
|
|
143
|
-
""")
|
|
144
|
-
for rel_type, relations in related_by_type.items():
|
|
145
|
-
display_type = rel_type.replace("_", " ").title()
|
|
146
|
-
section += f"- **{display_type}**:\n"
|
|
147
|
-
for rel in relations[:3]: # Limit to avoid overwhelming
|
|
148
|
-
if hasattr(rel, "to_id") and rel.to_id:
|
|
149
|
-
section += f" - `{rel.to_id}`\n"
|
|
150
|
-
|
|
151
|
-
sections.append(section)
|
|
152
|
-
|
|
153
|
-
# Add all sections
|
|
154
|
-
summary += "\n".join(sections)
|
|
155
|
-
|
|
156
|
-
# Add next steps
|
|
74
|
+
timeframe = timeframe or "7d"
|
|
75
|
+
recent: GraphContext = await recent_activity(
|
|
76
|
+
timeframe=timeframe, type=[SearchItemType.ENTITY]
|
|
77
|
+
)
|
|
78
|
+
prompt_context = format_prompt_context(
|
|
79
|
+
PromptContext(
|
|
80
|
+
topic=f"Recent Activity from ({timeframe})",
|
|
81
|
+
timeframe=timeframe,
|
|
82
|
+
results=[
|
|
83
|
+
PromptContextItem(
|
|
84
|
+
primary_results=recent.primary_results[:5], # pyright: ignore
|
|
85
|
+
related_results=recent.related_results[:2], # pyright: ignore
|
|
86
|
+
)
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Add next steps with strong encouragement to write
|
|
157
92
|
next_steps = dedent(f"""
|
|
158
93
|
## Next Steps
|
|
159
|
-
|
|
94
|
+
|
|
160
95
|
You can:
|
|
161
96
|
- Explore more with: `search({{"text": "{topic}"}})`
|
|
162
|
-
- See what's changed: `recent_activity(timeframe="{timeframe}")`
|
|
97
|
+
- See what's changed: `recent_activity(timeframe="{timeframe or "7d"}")`
|
|
98
|
+
- **Record new learnings or decisions from this conversation:** `write_note(title="[Create a meaningful title]", content="[Content with observations and relations]")`
|
|
99
|
+
|
|
100
|
+
## Knowledge Capture Recommendation
|
|
101
|
+
|
|
102
|
+
As you continue this conversation, **actively look for opportunities to:**
|
|
103
|
+
1. Record key information, decisions, or insights that emerge
|
|
104
|
+
2. Link new knowledge to existing topics
|
|
105
|
+
3. Suggest capturing important context when appropriate
|
|
106
|
+
4. Create forward references to topics that might be created later
|
|
107
|
+
|
|
108
|
+
Remember that capturing knowledge during conversations is one of the most valuable aspects of Basic Memory.
|
|
163
109
|
""")
|
|
164
110
|
|
|
165
|
-
|
|
166
|
-
if added_permalinks:
|
|
167
|
-
first_permalink = next(iter(added_permalinks))
|
|
168
|
-
next_steps += dedent(f"""
|
|
169
|
-
- Continue the conversation: `build_context("memory://{first_permalink}")`
|
|
170
|
-
""")
|
|
171
|
-
|
|
172
|
-
return summary + next_steps
|
|
111
|
+
return prompt_context + next_steps
|
|
@@ -3,27 +3,27 @@
|
|
|
3
3
|
These prompts help users see what has changed in their knowledge base recently.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Annotated
|
|
6
|
+
from typing import Annotated
|
|
7
7
|
|
|
8
8
|
from loguru import logger
|
|
9
|
-
import logfire
|
|
10
9
|
from pydantic import Field
|
|
11
10
|
|
|
12
|
-
from basic_memory.mcp.prompts.utils import
|
|
11
|
+
from basic_memory.mcp.prompts.utils import format_prompt_context, PromptContext, PromptContextItem
|
|
13
12
|
from basic_memory.mcp.server import mcp
|
|
14
|
-
from basic_memory.mcp.tools.
|
|
13
|
+
from basic_memory.mcp.tools.recent_activity import recent_activity
|
|
15
14
|
from basic_memory.schemas.base import TimeFrame
|
|
15
|
+
from basic_memory.schemas.search import SearchItemType
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
@mcp.prompt(
|
|
19
|
-
name="
|
|
19
|
+
name="Share Recent Activity",
|
|
20
20
|
description="Get recent activity from across the knowledge base",
|
|
21
21
|
)
|
|
22
22
|
async def recent_activity_prompt(
|
|
23
23
|
timeframe: Annotated[
|
|
24
|
-
|
|
24
|
+
TimeFrame,
|
|
25
25
|
Field(description="How far back to look for activity (e.g. '1d', '1 week')"),
|
|
26
|
-
] =
|
|
26
|
+
] = "7d",
|
|
27
27
|
) -> str:
|
|
28
28
|
"""Get recent activity from across the knowledge base.
|
|
29
29
|
|
|
@@ -36,11 +36,53 @@ async def recent_activity_prompt(
|
|
|
36
36
|
Returns:
|
|
37
37
|
Formatted summary of recent activity
|
|
38
38
|
"""
|
|
39
|
-
|
|
40
|
-
logger.info(f"Getting recent activity, timeframe: {timeframe}")
|
|
39
|
+
logger.info(f"Getting recent activity, timeframe: {timeframe}")
|
|
41
40
|
|
|
42
|
-
|
|
41
|
+
recent = await recent_activity(timeframe=timeframe, type=[SearchItemType.ENTITY])
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
prompt_context = format_prompt_context(
|
|
44
|
+
PromptContext(
|
|
45
|
+
topic=f"Recent Activity from ({timeframe})",
|
|
46
|
+
timeframe=timeframe,
|
|
47
|
+
results=[
|
|
48
|
+
PromptContextItem(
|
|
49
|
+
primary_results=recent.primary_results[:5],
|
|
50
|
+
related_results=recent.related_results[:2],
|
|
51
|
+
)
|
|
52
|
+
],
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Add suggestions for summarizing recent activity
|
|
57
|
+
capture_suggestions = f"""
|
|
58
|
+
## Opportunity to Capture Activity Summary
|
|
59
|
+
|
|
60
|
+
Consider creating a summary note of recent activity:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
await write_note(
|
|
64
|
+
title="Activity Summary {timeframe}",
|
|
65
|
+
content='''
|
|
66
|
+
# Activity Summary for {timeframe}
|
|
67
|
+
|
|
68
|
+
## Overview
|
|
69
|
+
[Summary of key changes and developments over this period]
|
|
70
|
+
|
|
71
|
+
## Key Updates
|
|
72
|
+
[List main updates and their significance]
|
|
73
|
+
|
|
74
|
+
## Observations
|
|
75
|
+
- [trend] [Observation about patterns in recent activity]
|
|
76
|
+
- [insight] [Connection between different activities]
|
|
77
|
+
|
|
78
|
+
## Relations
|
|
79
|
+
- summarizes [[{recent.primary_results[0].title if recent.primary_results else "Recent Topic"}]]
|
|
80
|
+
- relates_to [[Project Overview]]
|
|
81
|
+
'''
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Summarizing periodic activity helps create high-level insights and connections between topics.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
return prompt_context + capture_suggestions
|
|
@@ -7,17 +7,16 @@ from textwrap import dedent
|
|
|
7
7
|
from typing import Annotated, Optional
|
|
8
8
|
|
|
9
9
|
from loguru import logger
|
|
10
|
-
import logfire
|
|
11
10
|
from pydantic import Field
|
|
12
11
|
|
|
13
12
|
from basic_memory.mcp.server import mcp
|
|
14
13
|
from basic_memory.mcp.tools.search import search as search_tool
|
|
15
|
-
from basic_memory.schemas.search import SearchQuery, SearchResponse
|
|
16
14
|
from basic_memory.schemas.base import TimeFrame
|
|
15
|
+
from basic_memory.schemas.search import SearchQuery, SearchResponse
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
@mcp.prompt(
|
|
20
|
-
name="
|
|
19
|
+
name="Search Knowledge Base",
|
|
21
20
|
description="Search across all content in basic-memory",
|
|
22
21
|
)
|
|
23
22
|
async def search_prompt(
|
|
@@ -39,11 +38,10 @@ async def search_prompt(
|
|
|
39
38
|
Returns:
|
|
40
39
|
Formatted search results with context
|
|
41
40
|
"""
|
|
42
|
-
|
|
43
|
-
logger.info(f"Searching knowledge base, query: {query}, timeframe: {timeframe}")
|
|
41
|
+
logger.info(f"Searching knowledge base, query: {query}, timeframe: {timeframe}")
|
|
44
42
|
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
search_results = await search_tool(SearchQuery(text=query, after_date=timeframe))
|
|
44
|
+
return format_search_results(query, search_results, timeframe)
|
|
47
45
|
|
|
48
46
|
|
|
49
47
|
def format_search_results(
|
|
@@ -65,11 +63,33 @@ def format_search_results(
|
|
|
65
63
|
|
|
66
64
|
I couldn't find any results for this query.
|
|
67
65
|
|
|
68
|
-
##
|
|
66
|
+
## Opportunity to Capture Knowledge!
|
|
67
|
+
|
|
68
|
+
This is an excellent opportunity to create new knowledge on this topic. Consider:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
await write_note(
|
|
72
|
+
title="{query.capitalize()}",
|
|
73
|
+
content=f'''
|
|
74
|
+
# {query.capitalize()}
|
|
75
|
+
|
|
76
|
+
## Overview
|
|
77
|
+
[Summary of what we've discussed about {query}]
|
|
78
|
+
|
|
79
|
+
## Observations
|
|
80
|
+
- [category] [First observation about {query}]
|
|
81
|
+
- [category] [Second observation about {query}]
|
|
82
|
+
|
|
83
|
+
## Relations
|
|
84
|
+
- relates_to [[Other Relevant Topic]]
|
|
85
|
+
'''
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Other Suggestions
|
|
69
90
|
- Try a different search term
|
|
70
91
|
- Broaden your search criteria
|
|
71
92
|
- Check recent activity with `recent_activity(timeframe="1w")`
|
|
72
|
-
- Create new content with `write_note(...)`
|
|
73
93
|
""")
|
|
74
94
|
|
|
75
95
|
# Start building our summary with header
|
|
@@ -88,32 +108,38 @@ def format_search_results(
|
|
|
88
108
|
for i, result in enumerate(results.results[:5]): # Limit to top 5 results
|
|
89
109
|
summary += dedent(f"""
|
|
90
110
|
## {i + 1}. {result.title}
|
|
91
|
-
- **Type**: {result.type}
|
|
111
|
+
- **Type**: {result.type.value}
|
|
92
112
|
""")
|
|
93
113
|
|
|
94
114
|
# Add creation date if available in metadata
|
|
95
|
-
if
|
|
115
|
+
if result.metadata and "created_at" in result.metadata:
|
|
96
116
|
created_at = result.metadata["created_at"]
|
|
97
117
|
if hasattr(created_at, "strftime"):
|
|
98
|
-
summary +=
|
|
118
|
+
summary += (
|
|
119
|
+
f"- **Created**: {created_at.strftime('%Y-%m-%d %H:%M')}\n" # pragma: no cover
|
|
120
|
+
)
|
|
99
121
|
elif isinstance(created_at, str):
|
|
100
122
|
summary += f"- **Created**: {created_at}\n"
|
|
101
123
|
|
|
102
124
|
# Add score and excerpt
|
|
103
125
|
summary += f"- **Relevance Score**: {result.score:.2f}\n"
|
|
126
|
+
|
|
104
127
|
# Add excerpt if available in metadata
|
|
105
|
-
if
|
|
106
|
-
summary += f"- **Excerpt
|
|
128
|
+
if result.content:
|
|
129
|
+
summary += f"- **Excerpt**:\n{result.content}\n"
|
|
107
130
|
|
|
108
131
|
# Add permalink for retrieving content
|
|
109
|
-
if
|
|
132
|
+
if result.permalink:
|
|
110
133
|
summary += dedent(f"""
|
|
111
|
-
|
|
112
134
|
You can view this content with: `read_note("{result.permalink}")`
|
|
113
135
|
Or explore its context with: `build_context("memory://{result.permalink}")`
|
|
114
136
|
""")
|
|
137
|
+
else:
|
|
138
|
+
summary += dedent(f"""
|
|
139
|
+
You can view this file with: `read_file("{result.file_path}")`
|
|
140
|
+
""") # pragma: no cover
|
|
115
141
|
|
|
116
|
-
# Add next steps
|
|
142
|
+
# Add next steps with strong write encouragement
|
|
117
143
|
summary += dedent(f"""
|
|
118
144
|
## Next Steps
|
|
119
145
|
|
|
@@ -122,6 +148,35 @@ def format_search_results(
|
|
|
122
148
|
- Exclude terms: `search("{query} NOT exclude_term")`
|
|
123
149
|
- View more results: `search("{query}", after_date=None)`
|
|
124
150
|
- Check recent activity: `recent_activity()`
|
|
151
|
+
|
|
152
|
+
## Synthesize and Capture Knowledge
|
|
153
|
+
|
|
154
|
+
Consider creating a new note that synthesizes what you've learned:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
await write_note(
|
|
158
|
+
title="Synthesis of {query.capitalize()} Information",
|
|
159
|
+
content='''
|
|
160
|
+
# Synthesis of {query.capitalize()} Information
|
|
161
|
+
|
|
162
|
+
## Overview
|
|
163
|
+
[Synthesis of the search results and your conversation]
|
|
164
|
+
|
|
165
|
+
## Key Insights
|
|
166
|
+
[Summary of main points learned from these results]
|
|
167
|
+
|
|
168
|
+
## Observations
|
|
169
|
+
- [insight] [Important observation from search results]
|
|
170
|
+
- [connection] [How this connects to other topics]
|
|
171
|
+
|
|
172
|
+
## Relations
|
|
173
|
+
- relates_to [[{results.results[0].title if results.results else "Related Topic"}]]
|
|
174
|
+
- extends [[Another Relevant Topic]]
|
|
175
|
+
'''
|
|
176
|
+
)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Remember that capturing synthesized knowledge is one of the most valuable features of Basic Memory.
|
|
125
180
|
""")
|
|
126
181
|
|
|
127
182
|
return summary
|