|
4 | 4 | providing context from previous interactions to maintain continuity. |
5 | 5 | """ |
6 | 6 |
|
| 7 | +from textwrap import dedent |
7 | 8 | from typing import Annotated, Optional |
8 | 9 |
|
9 | 10 | from loguru import logger |
10 | 11 | from pydantic import Field |
11 | 12 |
|
12 | | -from basic_memory.config import ConfigManager |
13 | | -from basic_memory.mcp.async_client import get_client |
14 | | -from basic_memory.mcp.project_context import get_active_project |
15 | 13 | from basic_memory.mcp.server import mcp |
16 | | -from basic_memory.mcp.tools.utils import call_post |
17 | | -from basic_memory.schemas.prompt import ContinueConversationRequest |
| 14 | +from basic_memory.mcp.tools.recent_activity import recent_activity |
| 15 | +from basic_memory.mcp.tools.search import search_notes |
| 16 | +from basic_memory.schemas.search import SearchResponse |
18 | 17 |
|
19 | 18 |
|
20 | 19 | @mcp.prompt( |
@@ -42,22 +41,94 @@ async def continue_conversation( |
42 | 41 | """ |
43 | 42 | logger.info(f"Continuing session, topic: {topic}, timeframe: {timeframe}") |
44 | 43 |
|
45 | | - async with get_client() as client: |
46 | | - config = ConfigManager().config |
47 | | - active_project = await get_active_project(client, project=config.default_project) |
48 | | - |
49 | | - # Create request model |
50 | | - request = ContinueConversationRequest( # pyright: ignore [reportCallIssue] |
51 | | - topic=topic, timeframe=timeframe |
52 | | - ) |
53 | | - |
54 | | - # Call the prompt API endpoint |
55 | | - response = await call_post( |
56 | | - client, |
57 | | - f"/v2/projects/{active_project.external_id}/prompt/continue-conversation", |
58 | | - json=request.model_dump(exclude_none=True), |
59 | | - ) |
60 | | - |
61 | | - # Extract the rendered prompt from the response |
62 | | - result = response.json() |
63 | | - return result["prompt"] |
| 44 | + if topic: |
| 45 | + # Search for the topic using the search tool directly |
| 46 | + result = await search_notes(query=topic, after_date=timeframe) |
| 47 | + |
| 48 | + if isinstance(result, SearchResponse): |
| 49 | + context_text = _format_continuation_results(result, topic) |
| 50 | + result_count = len(result.results) |
| 51 | + elif isinstance(result, dict): |
| 52 | + results = result.get("results", []) |
| 53 | + context_text = str(result) |
| 54 | + result_count = len(results) |
| 55 | + else: |
| 56 | + # Error string |
| 57 | + context_text = str(result) |
| 58 | + result_count = 0 |
| 59 | + else: |
| 60 | + # No topic — show recent activity |
| 61 | + effective_timeframe = timeframe or "7d" |
| 62 | + activity_text = await recent_activity(timeframe=effective_timeframe) |
| 63 | + context_text = str(activity_text) |
| 64 | + result_count = -1 # Signals we used recent_activity |
| 65 | + |
| 66 | + target = f"'{topic}'" if topic else "recent activity" |
| 67 | + |
| 68 | + prompt = dedent(f""" |
| 69 | + # Continuing conversation on: {target} |
| 70 | +
|
| 71 | + This is a memory retrieval session. |
| 72 | +
|
| 73 | + Please use the available basic-memory tools to gather relevant context before responding. |
| 74 | + Start by executing one of the suggested commands below to retrieve content. |
| 75 | +
|
| 76 | + {context_text} |
| 77 | +
|
| 78 | + --- |
| 79 | +
|
| 80 | + ## Next Steps |
| 81 | + """) |
| 82 | + |
| 83 | + if topic and result_count > 0: |
| 84 | + prompt += dedent(f""" |
| 85 | + Found {result_count} results related to '{topic}'. |
| 86 | +
|
| 87 | + 1. **Read full content** - Use `read_note("permalink")` to dive into specific notes |
| 88 | + 2. **Build context** - Use `build_context("memory://path")` to see relationships |
| 89 | + 3. **Search deeper** - Use `search_notes("{topic}")` with different filters |
| 90 | +
|
| 91 | + > **Knowledge Capture:** As you continue this conversation, actively look for |
| 92 | + > opportunities to record new information, decisions, or insights using `write_note()`. |
| 93 | + """) |
| 94 | + elif topic: |
| 95 | + prompt += dedent(f""" |
| 96 | + No previous context found for '{topic}'. |
| 97 | +
|
| 98 | + This is an opportunity to start documenting this topic: |
| 99 | +
|
| 100 | + 1. **Create a new note** - Use `write_note(title="{topic}", content="...")` to start |
| 101 | + 2. **Search with variations** - Try `search_notes("{topic}")` with different terms |
| 102 | + 3. **Check recent activity** - Use `recent_activity(timeframe="7d")` to see what's new |
| 103 | + """) |
| 104 | + else: |
| 105 | + prompt += dedent(""" |
| 106 | + 1. **Explore specific items** - Use `read_note("permalink")` to dive deeper |
| 107 | + 2. **Search for topics** - Use `search_notes("topic")` to find specific content |
| 108 | + 3. **Build context** - Use `build_context("memory://path")` to see relationships |
| 109 | + """) |
| 110 | + |
| 111 | + return prompt |
| 112 | + |
| 113 | + |
| 114 | +def _format_continuation_results(result: SearchResponse, topic: str) -> str: |
| 115 | + """Format search results for conversation continuation context.""" |
| 116 | + if not result.results: |
| 117 | + return f"No previous context found for '{topic}'." |
| 118 | + |
| 119 | + lines = [f"## Previous Context for '{topic}'\n"] |
| 120 | + |
| 121 | + for item in result.results: |
| 122 | + title = item.title or "Untitled" |
| 123 | + permalink = item.permalink or "" |
| 124 | + |
| 125 | + lines.append(f"### {title}") |
| 126 | + if permalink: |
| 127 | + lines.append(f"permalink: {permalink}") |
| 128 | + lines.append(f"Read with: `read_note(\"{permalink}\")`") |
| 129 | + if item.content: |
| 130 | + content = item.content[:300] + "..." if len(item.content) > 300 else item.content |
| 131 | + lines.append(f"\n{content}") |
| 132 | + lines.append("") |
| 133 | + |
| 134 | + return "\n".join(lines) |
0 commit comments