hanzo-mcp 0.3.8__py3-none-any.whl → 0.5.1__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 hanzo-mcp might be problematic. Click here for more details.

Files changed (93) hide show
  1. hanzo_mcp/__init__.py +1 -1
  2. hanzo_mcp/cli.py +118 -170
  3. hanzo_mcp/cli_enhanced.py +438 -0
  4. hanzo_mcp/config/__init__.py +19 -0
  5. hanzo_mcp/config/settings.py +449 -0
  6. hanzo_mcp/config/tool_config.py +197 -0
  7. hanzo_mcp/prompts/__init__.py +117 -0
  8. hanzo_mcp/prompts/compact_conversation.py +77 -0
  9. hanzo_mcp/prompts/create_release.py +38 -0
  10. hanzo_mcp/prompts/project_system.py +120 -0
  11. hanzo_mcp/prompts/project_todo_reminder.py +111 -0
  12. hanzo_mcp/prompts/utils.py +286 -0
  13. hanzo_mcp/server.py +117 -99
  14. hanzo_mcp/tools/__init__.py +121 -33
  15. hanzo_mcp/tools/agent/__init__.py +8 -11
  16. hanzo_mcp/tools/agent/agent_tool.py +290 -224
  17. hanzo_mcp/tools/agent/prompt.py +16 -13
  18. hanzo_mcp/tools/agent/tool_adapter.py +9 -9
  19. hanzo_mcp/tools/common/__init__.py +17 -16
  20. hanzo_mcp/tools/common/base.py +79 -110
  21. hanzo_mcp/tools/common/batch_tool.py +330 -0
  22. hanzo_mcp/tools/common/config_tool.py +396 -0
  23. hanzo_mcp/tools/common/context.py +26 -292
  24. hanzo_mcp/tools/common/permissions.py +12 -12
  25. hanzo_mcp/tools/common/thinking_tool.py +153 -0
  26. hanzo_mcp/tools/common/validation.py +1 -63
  27. hanzo_mcp/tools/filesystem/__init__.py +97 -57
  28. hanzo_mcp/tools/filesystem/base.py +32 -24
  29. hanzo_mcp/tools/filesystem/content_replace.py +114 -107
  30. hanzo_mcp/tools/filesystem/directory_tree.py +129 -105
  31. hanzo_mcp/tools/filesystem/edit.py +279 -0
  32. hanzo_mcp/tools/filesystem/grep.py +458 -0
  33. hanzo_mcp/tools/filesystem/grep_ast_tool.py +250 -0
  34. hanzo_mcp/tools/filesystem/multi_edit.py +362 -0
  35. hanzo_mcp/tools/filesystem/read.py +255 -0
  36. hanzo_mcp/tools/filesystem/unified_search.py +689 -0
  37. hanzo_mcp/tools/filesystem/write.py +156 -0
  38. hanzo_mcp/tools/jupyter/__init__.py +41 -29
  39. hanzo_mcp/tools/jupyter/base.py +66 -57
  40. hanzo_mcp/tools/jupyter/{edit_notebook.py → notebook_edit.py} +162 -139
  41. hanzo_mcp/tools/jupyter/notebook_read.py +152 -0
  42. hanzo_mcp/tools/shell/__init__.py +29 -20
  43. hanzo_mcp/tools/shell/base.py +87 -45
  44. hanzo_mcp/tools/shell/bash_session.py +731 -0
  45. hanzo_mcp/tools/shell/bash_session_executor.py +295 -0
  46. hanzo_mcp/tools/shell/command_executor.py +435 -384
  47. hanzo_mcp/tools/shell/run_command.py +284 -131
  48. hanzo_mcp/tools/shell/run_command_windows.py +328 -0
  49. hanzo_mcp/tools/shell/session_manager.py +196 -0
  50. hanzo_mcp/tools/shell/session_storage.py +325 -0
  51. hanzo_mcp/tools/todo/__init__.py +66 -0
  52. hanzo_mcp/tools/todo/base.py +319 -0
  53. hanzo_mcp/tools/todo/todo_read.py +148 -0
  54. hanzo_mcp/tools/todo/todo_write.py +378 -0
  55. hanzo_mcp/tools/vector/__init__.py +99 -0
  56. hanzo_mcp/tools/vector/ast_analyzer.py +459 -0
  57. hanzo_mcp/tools/vector/git_ingester.py +482 -0
  58. hanzo_mcp/tools/vector/infinity_store.py +731 -0
  59. hanzo_mcp/tools/vector/mock_infinity.py +162 -0
  60. hanzo_mcp/tools/vector/project_manager.py +361 -0
  61. hanzo_mcp/tools/vector/vector_index.py +116 -0
  62. hanzo_mcp/tools/vector/vector_search.py +225 -0
  63. hanzo_mcp-0.5.1.dist-info/METADATA +276 -0
  64. hanzo_mcp-0.5.1.dist-info/RECORD +68 -0
  65. {hanzo_mcp-0.3.8.dist-info → hanzo_mcp-0.5.1.dist-info}/WHEEL +1 -1
  66. hanzo_mcp/tools/agent/base_provider.py +0 -73
  67. hanzo_mcp/tools/agent/litellm_provider.py +0 -45
  68. hanzo_mcp/tools/agent/lmstudio_agent.py +0 -385
  69. hanzo_mcp/tools/agent/lmstudio_provider.py +0 -219
  70. hanzo_mcp/tools/agent/provider_registry.py +0 -120
  71. hanzo_mcp/tools/common/error_handling.py +0 -86
  72. hanzo_mcp/tools/common/logging_config.py +0 -115
  73. hanzo_mcp/tools/common/session.py +0 -91
  74. hanzo_mcp/tools/common/think_tool.py +0 -123
  75. hanzo_mcp/tools/common/version_tool.py +0 -120
  76. hanzo_mcp/tools/filesystem/edit_file.py +0 -287
  77. hanzo_mcp/tools/filesystem/get_file_info.py +0 -170
  78. hanzo_mcp/tools/filesystem/read_files.py +0 -199
  79. hanzo_mcp/tools/filesystem/search_content.py +0 -275
  80. hanzo_mcp/tools/filesystem/write_file.py +0 -162
  81. hanzo_mcp/tools/jupyter/notebook_operations.py +0 -514
  82. hanzo_mcp/tools/jupyter/read_notebook.py +0 -165
  83. hanzo_mcp/tools/project/__init__.py +0 -64
  84. hanzo_mcp/tools/project/analysis.py +0 -886
  85. hanzo_mcp/tools/project/base.py +0 -66
  86. hanzo_mcp/tools/project/project_analyze.py +0 -173
  87. hanzo_mcp/tools/shell/run_script.py +0 -215
  88. hanzo_mcp/tools/shell/script_tool.py +0 -244
  89. hanzo_mcp-0.3.8.dist-info/METADATA +0 -196
  90. hanzo_mcp-0.3.8.dist-info/RECORD +0 -53
  91. {hanzo_mcp-0.3.8.dist-info → hanzo_mcp-0.5.1.dist-info}/entry_points.txt +0 -0
  92. {hanzo_mcp-0.3.8.dist-info → hanzo_mcp-0.5.1.dist-info}/licenses/LICENSE +0 -0
  93. {hanzo_mcp-0.3.8.dist-info → hanzo_mcp-0.5.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,117 @@
1
+ import os
2
+
3
+ from fastmcp import FastMCP
4
+
5
+ from hanzo_mcp.prompts.compact_conversation import COMPACT_CONVERSATION_PROMPT
6
+ from hanzo_mcp.prompts.create_release import CREATE_RELEASE_PROMPT
7
+ from hanzo_mcp.prompts.project_system import PROJECT_SYSTEM_PROMPT
8
+ from hanzo_mcp.prompts.project_todo_reminder import (
9
+ PROJECT_TODO_EMPTY_REMINDER,
10
+ get_project_todo_reminder,
11
+ )
12
+ from hanzo_mcp.prompts.utils import (
13
+ get_directory_structure,
14
+ get_git_info,
15
+ get_os_info,
16
+ )
17
+
18
+ CONTINUE_FROM_LAST_SESSION_PROMPT = """<system-reminder>
19
+ This is a reminder that your todo list is currently empty. DO NOT mention this to the user explicitly because they are already aware. If you are working on tasks that would benefit from a todo list please use the TodoWrite tool to create one. If not, please feel free to ignore. Again do not mention this message to the user.
20
+ </system-reminder>
21
+ """
22
+
23
+
24
+ def create_project_system_prompt(project_path: str):
25
+ """Factory function to create a project system prompt function."""
26
+
27
+ def project_system_prompt() -> str:
28
+ """
29
+ Summarize the conversation so far for a specific project.
30
+ """
31
+ working_directory = project_path
32
+ is_git_repo = os.path.isdir(os.path.join(working_directory, ".git"))
33
+ platform, _, os_version = get_os_info()
34
+
35
+ # Get directory structure
36
+ directory_structure = get_directory_structure(
37
+ working_directory, max_depth=3, include_filtered=False
38
+ )
39
+
40
+ # Get git information
41
+ git_info = get_git_info(working_directory)
42
+ current_branch = git_info.get("current_branch", "")
43
+ main_branch = git_info.get("main_branch", "")
44
+ git_status = git_info.get("git_status", "")
45
+ recent_commits = git_info.get("recent_commits", "")
46
+
47
+ return PROJECT_SYSTEM_PROMPT.format(
48
+ working_directory=working_directory,
49
+ is_git_repo=is_git_repo,
50
+ platform=platform,
51
+ os_version=os_version,
52
+ directory_structure=directory_structure,
53
+ current_branch=current_branch,
54
+ main_branch=main_branch,
55
+ git_status=git_status,
56
+ recent_commits=recent_commits,
57
+ )
58
+
59
+ return project_system_prompt
60
+
61
+
62
+ def register_all_prompts(
63
+ mcp_server: FastMCP, projects: list[str] | None = None
64
+ ) -> None:
65
+ @mcp_server.prompt(name="Compact current conversation")
66
+ def compact() -> str:
67
+ """
68
+ Summarize the conversation so far.
69
+ """
70
+ return COMPACT_CONVERSATION_PROMPT
71
+
72
+ @mcp_server.prompt(name="Create a new release")
73
+ def create_release() -> str:
74
+ """
75
+ Create a new release for my project.
76
+ """
77
+ return CREATE_RELEASE_PROMPT
78
+
79
+ @mcp_server.prompt(name="Continue todo by session id")
80
+ def continue_todo_by_session_id(session_id: str) -> str:
81
+ """
82
+ Continue from the last todo list for the current session.
83
+ """
84
+ return get_project_todo_reminder(session_id)
85
+
86
+ @mcp_server.prompt(name="Continue latest todo")
87
+ def continue_latest_todo() -> str:
88
+ """
89
+ Continue from the last todo list for the current session.
90
+ """
91
+ return get_project_todo_reminder()
92
+
93
+ @mcp_server.prompt(name="System prompt")
94
+ def manual_project_system_prompt(project_path: str) -> str:
95
+ """
96
+ Detailed system prompt include env,git etc information about the specified project.
97
+ """
98
+ return create_project_system_prompt(project_path)()
99
+
100
+ if projects is None:
101
+ return
102
+
103
+ for project in projects:
104
+ # Register the prompt with the factory function
105
+ mcp_server.prompt(
106
+ name=f"System prompt for {os.path.basename(project)}",
107
+ description=f"Detailed system prompt include env,git etc information about {project}",
108
+ )(create_project_system_prompt(project))
109
+
110
+ return
111
+
112
+
113
+ __all__ = [
114
+ "register_all_prompts",
115
+ "get_project_todo_reminder",
116
+ "PROJECT_TODO_EMPTY_REMINDER",
117
+ ]
@@ -0,0 +1,77 @@
1
+ COMPACT_CONVERSATION_PROMPT = """Your task is to create a detailed summary of the conversation so far, paying close attention to the user's explicit requests and your previous actions.
2
+ This summary should be thorough in capturing technical details, code patterns, and architectural decisions that would be essential for continuing development work without losing context.
3
+
4
+ Before providing your final summary, wrap your analysis in <analysis> tags to organize your thoughts and ensure you've covered all necessary points. In your analysis process:
5
+
6
+ 1. Chronologically analyze each message and section of the conversation. For each section thoroughly identify:
7
+ - The user's explicit requests and intents
8
+ - Your approach to addressing the user's requests
9
+ - Key decisions, technical concepts and code patterns
10
+ - Specific details like file names, full code snippets, function signatures, file edits, etc
11
+ 2. Double-check for technical accuracy and completeness, addressing each required element thoroughly.
12
+
13
+ Your summary should include the following sections:
14
+
15
+ 1. Primary Request and Intent: Capture all of the user's explicit requests and intents in detail
16
+ 2. Key Technical Concepts: List all important technical concepts, technologies, and frameworks discussed.
17
+ 3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
18
+ 4. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
19
+ 5. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
20
+ 6. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
21
+ 7. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests without confirming with the user first.
22
+ If there is a next step, include direct quotes from the most recent conversation showing exactly what task you were working on and where you left off. This should be verbatim to ensure there's no drift in task interpretation.
23
+
24
+ Here's an example of how your output should be structured:
25
+
26
+ <example>
27
+ <analysis>
28
+ [Your thought process, ensuring all points are covered thoroughly and accurately]
29
+ </analysis>
30
+
31
+ <summary>
32
+ 1. Primary Request and Intent:
33
+ [Detailed description]
34
+
35
+ 2. Key Technical Concepts:
36
+ - [Concept 1]
37
+ - [Concept 2]
38
+ - [...]
39
+
40
+ 3. Files and Code Sections:
41
+ - [File Name 1]
42
+ - [Summary of why this file is important]
43
+ - [Summary of the changes made to this file, if any]
44
+ - [Important Code Snippet]
45
+ - [File Name 2]
46
+ - [Important Code Snippet]
47
+ - [...]
48
+
49
+ 4. Problem Solving:
50
+ [Description of solved problems and ongoing troubleshooting]
51
+
52
+ 5. Pending Tasks:
53
+ - [Task 1]
54
+ - [Task 2]
55
+ - [...]
56
+
57
+ 6. Current Work:
58
+ [Precise description of current work]
59
+
60
+ 7. Optional Next Step:
61
+ [Optional Next step to take]
62
+
63
+ </summary>
64
+ </example>
65
+
66
+ Please provide your summary based on the conversation so far, following this structure and ensuring precision and thoroughness in your response.
67
+
68
+ There may be additional summarization instructions provided in the included context. If so, remember to follow these instructions when creating the above summary. Examples of instructions include:
69
+ <example>
70
+ ## Compact Instructions
71
+ When summarizing the conversation focus on typescript code changes and also remember the mistakes you made and how you fixed them.
72
+ </example>
73
+
74
+ <example>
75
+ # Summary instructions
76
+ When you are using compact - please focus on test output and code changes. Include file reads verbatim.
77
+ </example>"""
@@ -0,0 +1,38 @@
1
+ CREATE_RELEASE_PROMPT = """Help me create a new release for my project. Follow these steps:
2
+
3
+ ## Initial Analysis
4
+ 1. Examine the project version files (typically `__init__.py`, `package.json`, `pyproject.toml`, etc.)
5
+ 2. Review the current CHANGELOG.md format and previous releases
6
+ 3. Check the release workflow configuration (GitHub Actions, CI/CD pipelines)
7
+ 4. Review commits since the last release tag:
8
+ ```bash
9
+ git log <last-tag>..HEAD --pretty=format:"%h %s%n%b" --name-status
10
+ ```
11
+
12
+ ## Version Update
13
+ 1. Identify all files containing version numbers
14
+ 2. Update version numbers consistently across all files
15
+ 3. Follow semantic versioning guidelines (MAJOR.MINOR.PATCH)
16
+
17
+ ## Changelog Creation
18
+ 1. Add a new section at the top of CHANGELOG.md with the new version and today's date
19
+ 2. Group changes by type: Added, Changed, Fixed, Removed, etc.
20
+ 3. Include commit hashes in parentheses for reference
21
+ 4. Write clear, detailed descriptions for each change
22
+ 5. Follow established project conventions for changelog format
23
+
24
+ ## Release Commit and Tag
25
+ 1. Commit the version and changelog updates:
26
+ ```bash
27
+ git add <changed-files>
28
+ git commit -m "chore: bump version to X.Y.Z"
29
+ ```
30
+ 2. Create an annotated tag:
31
+ ```bash
32
+ git tag -a "vX.Y.Z" -m "Release vX.Y.Z"
33
+ ```
34
+ 3. Push the changes and tag:
35
+ ```bash
36
+ git push origin main
37
+ git push origin vX.Y.Z
38
+ ```"""
@@ -0,0 +1,120 @@
1
+ PROJECT_SYSTEM_PROMPT = """Your are assisting me with a project.
2
+
3
+ Here is useful information about the environment you are running in:
4
+
5
+ <env>
6
+ Working directory: {working_directory} (You need cd to this directory by yourself)
7
+ Is directory a git repo: {is_git_repo}
8
+ Platform: {platform}
9
+ OS Version: {os_version}
10
+ </env>
11
+
12
+ <project_info>
13
+ directoryStructure: Below is a snapshot of this project's file structure at the start of the conversation. This snapshot will NOT update during the conversation. It skips over .gitignore patterns.
14
+
15
+ {directory_structure}
16
+
17
+ gitStatus: This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.
18
+
19
+ Current branch: {current_branch}
20
+
21
+ Main branch (you will usually use this for PRs): {main_branch}
22
+
23
+ Status:
24
+
25
+ {git_status}
26
+
27
+ Recent commits:
28
+
29
+ {recent_commits}
30
+ </project_info>
31
+
32
+
33
+ <preferences>
34
+ IMPORTANT: Always use the todo_write tool to plan and track tasks throughout the conversation.
35
+
36
+ # Code References
37
+ When referencing specific functions or pieces of code include the pattern `file_path:line_number` to allow me to easily navigate to the source code location.
38
+
39
+ <example>
40
+ user: Where are errors from the client handled?
41
+ assistant: Clients are marked as failed in the `connectToServer` function in src/services/process.ts:712.
42
+ </example>
43
+
44
+ Do what has been asked; nothing more, nothing less.
45
+ ALWAYS prefer editing an existing file to creating a new one.
46
+ NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
47
+
48
+ # Proactiveness
49
+ You are allowed to be proactive, but only when I ask you to do something. You should strive to strike a balance between:
50
+ 1. Doing the right thing when asked, including taking actions and follow-up actions
51
+ 2. Not surprising me with actions you take without asking
52
+ For example, if I ask you how to approach something, you should do your best to answer their question first, and not immediately jump into taking actions.
53
+ 3. Do not add additional code explanation summary unless requested by me. After working on a file, just stop, rather than providing an explanation of what you did.
54
+
55
+ # Following conventions
56
+ When making changes to files, first understand the file's code conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.
57
+ - NEVER assume that a given library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses the given library. For example, you might look at neighboring files, or check the package.json (or cargo.toml, and so on depending on the language).
58
+ - When you create a new component, first look at existing components to see how they're written; then consider framework choice, naming conventions, typing, and other conventions.
59
+ - When you edit a piece of code, first look at the code's surrounding context (especially its imports) to understand the code's choice of frameworks and libraries. Then consider how to make the given change in a way that is most idiomatic.
60
+ - Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.
61
+ </preferences>
62
+
63
+
64
+ <task_management>
65
+ # Task Management
66
+ You have access to the todo_write and todo_read tools to help you manage and plan tasks. Use these tools VERY frequently to ensure that you are tracking your tasks and giving me visibility into your progress.
67
+ These tools are also EXTREMELY helpful for planning tasks, and for breaking down larger complex tasks into smaller steps. If you do not use this tool when planning, you may forget to do important tasks - and that is unacceptable.
68
+
69
+ It is critical that you mark todos as completed as soon as you are done with a task. Do not batch up multiple tasks before marking them as completed.
70
+
71
+ Examples:
72
+ <example>
73
+ user: Run the build and fix any type errors
74
+ assistant: I'm going to use the todo_write tool to write the following items to the todo list:
75
+ - Run the build
76
+ - Fix any type errors
77
+
78
+ I'm now going to run the build using Bash.
79
+
80
+ Looks like I found 10 type errors. I'm going to use the todo_write tool to write 10 items to the todo list.
81
+
82
+ marking the first todo as in_progress
83
+
84
+ Let me start working on the first item...
85
+
86
+ The first item has been fixed, let me mark the first todo as completed, and move on to the second item...
87
+ </example>
88
+
89
+ In the above example, the assistant completes all the tasks, including the 10 error fixes and running the build and fixing all errors.
90
+
91
+ <example>
92
+ user: Help me write a new feature that allows users to track their usage metrics and export them to various formats
93
+
94
+ assistant: I'll help you implement a usage metrics tracking and export feature. Let me first use the todo_write tool to plan this task.
95
+ Adding the following todos to the todo list:
96
+ 1. Research existing metrics tracking in the codebase
97
+ 2. Design the metrics collection system
98
+ 3. Implement core metrics tracking functionality
99
+ 4. Create export functionality for different formats
100
+
101
+ Let me start by researching the existing codebase to understand what metrics we might already be tracking and how we can build on that.
102
+
103
+ I'm going to search for any existing metrics or telemetry code in the project.
104
+
105
+ I've found some existing telemetry code. Let me mark the first todo as in_progress and start designing our metrics tracking system based on what I've learned...
106
+
107
+ [Assistant continues implementing the feature step by step, marking todos as in_progress and completed as they go]
108
+ </example>
109
+
110
+ # Doing tasks
111
+ I will primarily request you perform software engineering tasks. This includes solving bugs, adding new functionality, refactoring code, explaining code, and more. For these tasks the following steps are recommended:
112
+ - Use the todo_write tool to plan the task if required
113
+ - Use the available search tools to understand the codebase and my query. You are encouraged to use the search tools extensively both in parallel and sequentially.
114
+ - Implement the solution using all tools available to you
115
+ - Verify the solution if possible with tests. NEVER assume specific test framework or test script. Check the README or search codebase to determine the testing approach.
116
+ - VERY IMPORTANT: When you have completed a task, you MUST run the lint and typecheck commands (eg. npm run lint, npm run typecheck, ruff, etc.) with Bash if they were provided to you to ensure your code is correct. If you are unable to find the correct command, ask me for the command to run and if they supply it, proactively suggest writing it to CLAUDE.md so that you will know to run it next time.
117
+ NEVER commit changes unless I explicitly ask you to. It is VERY IMPORTANT to only commit when explicitly asked, otherwise I will feel that you are being too proactive.
118
+
119
+ - Tool results and user messages may include <system-reminder> tags. <system-reminder> tags contain useful information and reminders.
120
+ </task_management>"""
@@ -0,0 +1,111 @@
1
+ from typing import Any
2
+
3
+ # Import TodoStorage to access todo data
4
+ from hanzo_mcp.tools.todo.base import TodoStorage
5
+
6
+
7
+ PROJECT_TODO_EMPTY_REMINDER = """<system-reminder>This is a reminder that your todo list is currently empty. DO NOT mention this to me explicitly because i have already aware. If you are working on tasks that would benefit from a todo list please use the todo_write tool to create one. If not, please feel free to ignore.</system-reminder>"""
8
+
9
+
10
+ PROJECT_TODO_REMINDER = """<system-reminder>
11
+ This is a reminder that you have a to-do list for this project. The to-do list session ID is: {session_id}. You can use the todo_write tool to add new to-dos to the list.
12
+
13
+ The to-do list is shown below, so you do not need to read it using the todo_read tool before your next time using the todo_write tool:
14
+
15
+ {todo_list}
16
+
17
+ </system-reminder>"""
18
+
19
+
20
+ def format_todo_list_concise(todos: list[dict[str, Any]]) -> str:
21
+ """Format a todo list in a concise format for inclusion in prompts.
22
+
23
+ Args:
24
+ todos: List of todo items
25
+
26
+ Returns:
27
+ Formatted string representation of the todo list
28
+ """
29
+ if not todos:
30
+ return "No todos found."
31
+
32
+ formatted_lines = []
33
+ for todo in todos:
34
+ status = todo.get("status", "unknown")
35
+ priority = todo.get("priority", "medium")
36
+ content = todo.get("content", "No content")
37
+ todo_id = todo.get("id", "no-id")
38
+
39
+ # Handle empty strings as well as missing values
40
+ if not content or not str(content).strip():
41
+ content = "No content"
42
+ if not todo_id or not str(todo_id).strip():
43
+ todo_id = "no-id"
44
+
45
+ # Create status indicator
46
+ status_indicator = {
47
+ "pending": "[ ]",
48
+ "in_progress": "[~]",
49
+ "completed": "[✓]",
50
+ }.get(status, "[?]")
51
+
52
+ # Create priority indicator
53
+ priority_indicator = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(
54
+ priority, "⚪"
55
+ )
56
+
57
+ formatted_lines.append(
58
+ f"{status_indicator} {priority_indicator} {content} (id: {todo_id})"
59
+ )
60
+
61
+ return "\n".join(formatted_lines)
62
+
63
+
64
+ def has_unfinished_todos(todos: list[dict[str, Any]]) -> bool:
65
+ """Check if there are any unfinished todos in the list.
66
+
67
+ Args:
68
+ todos: List of todo items
69
+
70
+ Returns:
71
+ True if there are unfinished todos, False otherwise
72
+ """
73
+ if not todos:
74
+ return False
75
+
76
+ for todo in todos:
77
+ status = todo.get("status", "pending")
78
+ if status in ["pending", "in_progress"]:
79
+ return True
80
+
81
+ return False
82
+
83
+
84
+ def get_project_todo_reminder(session_id: str | None = None) -> str:
85
+ """Get the appropriate todo reminder for a session.
86
+
87
+ Args:
88
+ session_id: Session ID to check todos for. If None, finds the latest active session.
89
+
90
+ Returns:
91
+ Either PROJECT_TODO_EMPTY_REMINDER or PROJECT_TODO_REMINDER with formatted content
92
+ """
93
+ # If no session_id provided, try to find the latest active session
94
+ if session_id is None:
95
+ session_id = TodoStorage.find_latest_active_session()
96
+ if session_id is None:
97
+ # No active sessions found
98
+ return PROJECT_TODO_EMPTY_REMINDER
99
+
100
+ # Get todos for the session
101
+ todos = TodoStorage.get_todos(session_id)
102
+
103
+ # Check if we have unfinished todos
104
+ if not has_unfinished_todos(todos):
105
+ return PROJECT_TODO_EMPTY_REMINDER
106
+
107
+ # Format the todo list and return the reminder with content
108
+ formatted_todos = format_todo_list_concise(todos)
109
+ return PROJECT_TODO_REMINDER.format(
110
+ session_id=session_id, todo_list=formatted_todos
111
+ )