hanzo-mcp 0.7.6__py3-none-any.whl → 0.8.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 hanzo-mcp might be problematic. Click here for more details.
- hanzo_mcp/__init__.py +7 -1
- hanzo_mcp/__main__.py +1 -1
- hanzo_mcp/analytics/__init__.py +2 -2
- hanzo_mcp/analytics/posthog_analytics.py +76 -82
- hanzo_mcp/cli.py +31 -36
- hanzo_mcp/cli_enhanced.py +94 -72
- hanzo_mcp/cli_plugin.py +27 -17
- hanzo_mcp/config/__init__.py +2 -2
- hanzo_mcp/config/settings.py +112 -88
- hanzo_mcp/config/tool_config.py +32 -34
- hanzo_mcp/dev_server.py +66 -67
- hanzo_mcp/prompts/__init__.py +94 -12
- hanzo_mcp/prompts/enhanced_prompts.py +809 -0
- hanzo_mcp/prompts/example_custom_prompt.py +6 -5
- hanzo_mcp/prompts/project_todo_reminder.py +0 -1
- hanzo_mcp/prompts/tool_explorer.py +10 -7
- hanzo_mcp/server.py +17 -21
- hanzo_mcp/server_enhanced.py +15 -22
- hanzo_mcp/tools/__init__.py +56 -28
- hanzo_mcp/tools/agent/__init__.py +16 -19
- hanzo_mcp/tools/agent/agent.py +82 -65
- hanzo_mcp/tools/agent/agent_tool.py +152 -122
- hanzo_mcp/tools/agent/agent_tool_v1_deprecated.py +66 -62
- hanzo_mcp/tools/agent/clarification_protocol.py +55 -50
- hanzo_mcp/tools/agent/clarification_tool.py +11 -10
- hanzo_mcp/tools/agent/claude_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/claude_desktop_auth.py +130 -144
- hanzo_mcp/tools/agent/cli_agent_base.py +59 -53
- hanzo_mcp/tools/agent/code_auth.py +102 -107
- hanzo_mcp/tools/agent/code_auth_tool.py +28 -27
- hanzo_mcp/tools/agent/codex_cli_tool.py +20 -19
- hanzo_mcp/tools/agent/critic_tool.py +86 -73
- hanzo_mcp/tools/agent/gemini_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/grok_cli_tool.py +21 -20
- hanzo_mcp/tools/agent/iching_tool.py +404 -139
- hanzo_mcp/tools/agent/network_tool.py +89 -73
- hanzo_mcp/tools/agent/prompt.py +2 -1
- hanzo_mcp/tools/agent/review_tool.py +101 -98
- hanzo_mcp/tools/agent/swarm_alias.py +87 -0
- hanzo_mcp/tools/agent/swarm_tool.py +246 -161
- hanzo_mcp/tools/agent/swarm_tool_v1_deprecated.py +134 -92
- hanzo_mcp/tools/agent/tool_adapter.py +21 -11
- hanzo_mcp/tools/common/__init__.py +1 -1
- hanzo_mcp/tools/common/base.py +3 -5
- hanzo_mcp/tools/common/batch_tool.py +46 -39
- hanzo_mcp/tools/common/config_tool.py +120 -84
- hanzo_mcp/tools/common/context.py +1 -5
- hanzo_mcp/tools/common/context_fix.py +5 -3
- hanzo_mcp/tools/common/critic_tool.py +4 -8
- hanzo_mcp/tools/common/decorators.py +58 -56
- hanzo_mcp/tools/common/enhanced_base.py +29 -32
- hanzo_mcp/tools/common/fastmcp_pagination.py +91 -94
- hanzo_mcp/tools/common/forgiving_edit.py +91 -87
- hanzo_mcp/tools/common/mode.py +15 -17
- hanzo_mcp/tools/common/mode_loader.py +27 -24
- hanzo_mcp/tools/common/paginated_base.py +61 -53
- hanzo_mcp/tools/common/paginated_response.py +72 -79
- hanzo_mcp/tools/common/pagination.py +50 -53
- hanzo_mcp/tools/common/permissions.py +4 -4
- hanzo_mcp/tools/common/personality.py +186 -138
- hanzo_mcp/tools/common/plugin_loader.py +54 -54
- hanzo_mcp/tools/common/stats.py +65 -47
- hanzo_mcp/tools/common/test_helpers.py +31 -0
- hanzo_mcp/tools/common/thinking_tool.py +4 -8
- hanzo_mcp/tools/common/tool_disable.py +17 -12
- hanzo_mcp/tools/common/tool_enable.py +13 -14
- hanzo_mcp/tools/common/tool_list.py +36 -28
- hanzo_mcp/tools/common/truncate.py +23 -23
- hanzo_mcp/tools/config/__init__.py +4 -4
- hanzo_mcp/tools/config/config_tool.py +42 -29
- hanzo_mcp/tools/config/index_config.py +37 -34
- hanzo_mcp/tools/config/mode_tool.py +175 -55
- hanzo_mcp/tools/database/__init__.py +15 -12
- hanzo_mcp/tools/database/database_manager.py +77 -75
- hanzo_mcp/tools/database/graph.py +137 -91
- hanzo_mcp/tools/database/graph_add.py +30 -18
- hanzo_mcp/tools/database/graph_query.py +178 -102
- hanzo_mcp/tools/database/graph_remove.py +33 -28
- hanzo_mcp/tools/database/graph_search.py +97 -75
- hanzo_mcp/tools/database/graph_stats.py +91 -59
- hanzo_mcp/tools/database/sql.py +107 -79
- hanzo_mcp/tools/database/sql_query.py +30 -24
- hanzo_mcp/tools/database/sql_search.py +29 -25
- hanzo_mcp/tools/database/sql_stats.py +47 -35
- hanzo_mcp/tools/editor/neovim_command.py +25 -28
- hanzo_mcp/tools/editor/neovim_edit.py +21 -23
- hanzo_mcp/tools/editor/neovim_session.py +60 -54
- hanzo_mcp/tools/filesystem/__init__.py +31 -30
- hanzo_mcp/tools/filesystem/ast_multi_edit.py +329 -249
- hanzo_mcp/tools/filesystem/ast_tool.py +4 -4
- hanzo_mcp/tools/filesystem/base.py +1 -1
- hanzo_mcp/tools/filesystem/batch_search.py +316 -224
- hanzo_mcp/tools/filesystem/content_replace.py +4 -4
- hanzo_mcp/tools/filesystem/diff.py +71 -59
- hanzo_mcp/tools/filesystem/directory_tree.py +7 -7
- hanzo_mcp/tools/filesystem/directory_tree_paginated.py +49 -37
- hanzo_mcp/tools/filesystem/edit.py +4 -4
- hanzo_mcp/tools/filesystem/find.py +173 -80
- hanzo_mcp/tools/filesystem/find_files.py +73 -52
- hanzo_mcp/tools/filesystem/git_search.py +157 -104
- hanzo_mcp/tools/filesystem/grep.py +8 -8
- hanzo_mcp/tools/filesystem/multi_edit.py +4 -8
- hanzo_mcp/tools/filesystem/read.py +12 -10
- hanzo_mcp/tools/filesystem/rules_tool.py +59 -43
- hanzo_mcp/tools/filesystem/search_tool.py +263 -207
- hanzo_mcp/tools/filesystem/symbols_tool.py +94 -54
- hanzo_mcp/tools/filesystem/tree.py +35 -33
- hanzo_mcp/tools/filesystem/unix_aliases.py +13 -18
- hanzo_mcp/tools/filesystem/watch.py +37 -36
- hanzo_mcp/tools/filesystem/write.py +4 -8
- hanzo_mcp/tools/jupyter/__init__.py +4 -4
- hanzo_mcp/tools/jupyter/base.py +4 -5
- hanzo_mcp/tools/jupyter/jupyter.py +67 -47
- hanzo_mcp/tools/jupyter/notebook_edit.py +4 -4
- hanzo_mcp/tools/jupyter/notebook_read.py +4 -7
- hanzo_mcp/tools/llm/__init__.py +5 -7
- hanzo_mcp/tools/llm/consensus_tool.py +72 -52
- hanzo_mcp/tools/llm/llm_manage.py +101 -60
- hanzo_mcp/tools/llm/llm_tool.py +226 -166
- hanzo_mcp/tools/llm/provider_tools.py +25 -26
- hanzo_mcp/tools/lsp/__init__.py +1 -1
- hanzo_mcp/tools/lsp/lsp_tool.py +228 -143
- hanzo_mcp/tools/mcp/__init__.py +2 -3
- hanzo_mcp/tools/mcp/mcp_add.py +27 -25
- hanzo_mcp/tools/mcp/mcp_remove.py +7 -8
- hanzo_mcp/tools/mcp/mcp_stats.py +23 -22
- hanzo_mcp/tools/mcp/mcp_tool.py +129 -98
- hanzo_mcp/tools/memory/__init__.py +39 -21
- hanzo_mcp/tools/memory/knowledge_tools.py +124 -99
- hanzo_mcp/tools/memory/memory_tools.py +90 -108
- hanzo_mcp/tools/search/__init__.py +7 -2
- hanzo_mcp/tools/search/find_tool.py +297 -212
- hanzo_mcp/tools/search/unified_search.py +366 -314
- hanzo_mcp/tools/shell/__init__.py +8 -7
- hanzo_mcp/tools/shell/auto_background.py +56 -49
- hanzo_mcp/tools/shell/base.py +1 -1
- hanzo_mcp/tools/shell/base_process.py +75 -75
- hanzo_mcp/tools/shell/bash_session.py +2 -2
- hanzo_mcp/tools/shell/bash_session_executor.py +4 -4
- hanzo_mcp/tools/shell/bash_tool.py +24 -31
- hanzo_mcp/tools/shell/command_executor.py +12 -12
- hanzo_mcp/tools/shell/logs.py +43 -33
- hanzo_mcp/tools/shell/npx.py +13 -13
- hanzo_mcp/tools/shell/npx_background.py +24 -21
- hanzo_mcp/tools/shell/npx_tool.py +18 -22
- hanzo_mcp/tools/shell/open.py +19 -21
- hanzo_mcp/tools/shell/pkill.py +31 -26
- hanzo_mcp/tools/shell/process_tool.py +32 -32
- hanzo_mcp/tools/shell/processes.py +57 -58
- hanzo_mcp/tools/shell/run_background.py +24 -25
- hanzo_mcp/tools/shell/run_command.py +5 -5
- hanzo_mcp/tools/shell/run_command_windows.py +5 -5
- hanzo_mcp/tools/shell/session_storage.py +3 -3
- hanzo_mcp/tools/shell/streaming_command.py +141 -126
- hanzo_mcp/tools/shell/uvx.py +24 -25
- hanzo_mcp/tools/shell/uvx_background.py +35 -33
- hanzo_mcp/tools/shell/uvx_tool.py +18 -22
- hanzo_mcp/tools/todo/__init__.py +6 -2
- hanzo_mcp/tools/todo/todo.py +50 -37
- hanzo_mcp/tools/todo/todo_read.py +5 -8
- hanzo_mcp/tools/todo/todo_write.py +5 -7
- hanzo_mcp/tools/vector/__init__.py +40 -28
- hanzo_mcp/tools/vector/ast_analyzer.py +176 -143
- hanzo_mcp/tools/vector/git_ingester.py +170 -179
- hanzo_mcp/tools/vector/index_tool.py +96 -44
- hanzo_mcp/tools/vector/infinity_store.py +283 -228
- hanzo_mcp/tools/vector/mock_infinity.py +39 -40
- hanzo_mcp/tools/vector/project_manager.py +88 -78
- hanzo_mcp/tools/vector/vector.py +59 -42
- hanzo_mcp/tools/vector/vector_index.py +30 -27
- hanzo_mcp/tools/vector/vector_search.py +64 -45
- hanzo_mcp/types.py +6 -4
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/METADATA +1 -1
- hanzo_mcp-0.8.0.dist-info/RECORD +185 -0
- hanzo_mcp-0.7.6.dist-info/RECORD +0 -182
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/WHEEL +0 -0
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/entry_points.txt +0 -0
- {hanzo_mcp-0.7.6.dist-info → hanzo_mcp-0.8.0.dist-info}/top_level.txt +0 -0
|
@@ -4,18 +4,18 @@ This module provides utilities for implementing cursor-based pagination
|
|
|
4
4
|
according to the MCP pagination protocol.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
import base64
|
|
8
7
|
import json
|
|
9
|
-
|
|
8
|
+
import base64
|
|
9
|
+
from typing import Any, Dict, List, Generic, TypeVar, Optional
|
|
10
10
|
from dataclasses import dataclass
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
T = TypeVar('T')
|
|
12
|
+
T = TypeVar("T")
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
@dataclass
|
|
17
16
|
class PaginationParams:
|
|
18
17
|
"""Parameters for pagination."""
|
|
18
|
+
|
|
19
19
|
cursor: Optional[str] = None
|
|
20
20
|
page_size: int = 100 # Default page size
|
|
21
21
|
|
|
@@ -23,15 +23,16 @@ class PaginationParams:
|
|
|
23
23
|
@dataclass
|
|
24
24
|
class PaginatedResponse(Generic[T]):
|
|
25
25
|
"""A paginated response containing items and optional next cursor."""
|
|
26
|
+
|
|
26
27
|
items: List[T]
|
|
27
28
|
next_cursor: Optional[str] = None
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
def to_dict(self, items_key: str = "items") -> Dict[str, Any]:
|
|
30
31
|
"""Convert to dictionary format for MCP response.
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
Args:
|
|
33
34
|
items_key: The key to use for items in the response
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
Returns:
|
|
36
37
|
Dictionary with items and optional nextCursor
|
|
37
38
|
"""
|
|
@@ -43,27 +44,27 @@ class PaginatedResponse(Generic[T]):
|
|
|
43
44
|
|
|
44
45
|
class CursorManager:
|
|
45
46
|
"""Manages cursor creation and parsing for pagination."""
|
|
46
|
-
|
|
47
|
+
|
|
47
48
|
@staticmethod
|
|
48
49
|
def create_cursor(data: Dict[str, Any]) -> str:
|
|
49
50
|
"""Create an opaque cursor from data.
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
Args:
|
|
52
53
|
data: Data to encode in the cursor
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
Returns:
|
|
55
56
|
Base64-encoded cursor string
|
|
56
57
|
"""
|
|
57
|
-
json_data = json.dumps(data, separators=(
|
|
58
|
+
json_data = json.dumps(data, separators=(",", ":"))
|
|
58
59
|
return base64.b64encode(json_data.encode()).decode()
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
@staticmethod
|
|
61
62
|
def parse_cursor(cursor: str) -> Optional[Dict[str, Any]]:
|
|
62
63
|
"""Parse a cursor string back to data.
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
Args:
|
|
65
66
|
cursor: Base64-encoded cursor string
|
|
66
|
-
|
|
67
|
+
|
|
67
68
|
Returns:
|
|
68
69
|
Decoded data or None if invalid
|
|
69
70
|
"""
|
|
@@ -72,141 +73,137 @@ class CursorManager:
|
|
|
72
73
|
return json.loads(decoded)
|
|
73
74
|
except (ValueError, json.JSONDecodeError):
|
|
74
75
|
return None
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
@staticmethod
|
|
77
78
|
def create_offset_cursor(offset: int) -> str:
|
|
78
79
|
"""Create a cursor for offset-based pagination.
|
|
79
|
-
|
|
80
|
+
|
|
80
81
|
Args:
|
|
81
82
|
offset: The offset for the next page
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
Returns:
|
|
84
85
|
Cursor string
|
|
85
86
|
"""
|
|
86
87
|
return CursorManager.create_cursor({"offset": offset})
|
|
87
|
-
|
|
88
|
+
|
|
88
89
|
@staticmethod
|
|
89
90
|
def parse_offset_cursor(cursor: Optional[str]) -> int:
|
|
90
91
|
"""Parse an offset cursor.
|
|
91
|
-
|
|
92
|
+
|
|
92
93
|
Args:
|
|
93
94
|
cursor: Cursor string or None
|
|
94
|
-
|
|
95
|
+
|
|
95
96
|
Returns:
|
|
96
97
|
Offset value (0 if cursor is None or invalid)
|
|
97
98
|
"""
|
|
98
99
|
if not cursor:
|
|
99
100
|
return 0
|
|
100
|
-
|
|
101
|
+
|
|
101
102
|
data = CursorManager.parse_cursor(cursor)
|
|
102
103
|
if not data or "offset" not in data:
|
|
103
104
|
return 0
|
|
104
|
-
|
|
105
|
+
|
|
105
106
|
return int(data["offset"])
|
|
106
107
|
|
|
107
108
|
|
|
108
109
|
class Paginator(Generic[T]):
|
|
109
110
|
"""Generic paginator for any list of items."""
|
|
110
|
-
|
|
111
|
+
|
|
111
112
|
def __init__(self, items: List[T], page_size: int = 100):
|
|
112
113
|
"""Initialize paginator.
|
|
113
|
-
|
|
114
|
+
|
|
114
115
|
Args:
|
|
115
116
|
items: List of items to paginate
|
|
116
117
|
page_size: Number of items per page
|
|
117
118
|
"""
|
|
118
119
|
self.items = items
|
|
119
120
|
self.page_size = page_size
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
def get_page(self, cursor: Optional[str] = None) -> PaginatedResponse[T]:
|
|
122
123
|
"""Get a page of results.
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
Args:
|
|
125
126
|
cursor: Optional cursor for the page
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
Returns:
|
|
128
129
|
Paginated response with items and next cursor
|
|
129
130
|
"""
|
|
130
131
|
offset = CursorManager.parse_offset_cursor(cursor)
|
|
131
|
-
|
|
132
|
+
|
|
132
133
|
# Get the page of items
|
|
133
134
|
start = offset
|
|
134
135
|
end = min(start + self.page_size, len(self.items))
|
|
135
136
|
page_items = self.items[start:end]
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
# Create next cursor if there are more items
|
|
138
139
|
next_cursor = None
|
|
139
140
|
if end < len(self.items):
|
|
140
141
|
next_cursor = CursorManager.create_offset_cursor(end)
|
|
141
|
-
|
|
142
|
+
|
|
142
143
|
return PaginatedResponse(items=page_items, next_cursor=next_cursor)
|
|
143
144
|
|
|
144
145
|
|
|
145
146
|
class StreamPaginator(Generic[T]):
|
|
146
147
|
"""Paginator for streaming/generator-based results."""
|
|
147
|
-
|
|
148
|
+
|
|
148
149
|
def __init__(self, page_size: int = 100):
|
|
149
150
|
"""Initialize stream paginator.
|
|
150
|
-
|
|
151
|
+
|
|
151
152
|
Args:
|
|
152
153
|
page_size: Number of items per page
|
|
153
154
|
"""
|
|
154
155
|
self.page_size = page_size
|
|
155
|
-
|
|
156
|
+
|
|
156
157
|
def paginate_stream(
|
|
157
|
-
self,
|
|
158
|
-
stream_generator,
|
|
159
|
-
cursor: Optional[str] = None
|
|
158
|
+
self, stream_generator, cursor: Optional[str] = None
|
|
160
159
|
) -> PaginatedResponse[T]:
|
|
161
160
|
"""Paginate results from a stream/generator.
|
|
162
|
-
|
|
161
|
+
|
|
163
162
|
Args:
|
|
164
163
|
stream_generator: Generator function that yields items
|
|
165
164
|
cursor: Optional cursor for resuming
|
|
166
|
-
|
|
165
|
+
|
|
167
166
|
Returns:
|
|
168
167
|
Paginated response
|
|
169
168
|
"""
|
|
170
169
|
items = []
|
|
171
170
|
skip_count = 0
|
|
172
|
-
|
|
171
|
+
|
|
173
172
|
# Parse cursor to get skip count
|
|
174
173
|
if cursor:
|
|
175
174
|
cursor_data = CursorManager.parse_cursor(cursor)
|
|
176
175
|
if cursor_data and "skip" in cursor_data:
|
|
177
176
|
skip_count = cursor_data["skip"]
|
|
178
|
-
|
|
177
|
+
|
|
179
178
|
# Skip items based on cursor
|
|
180
179
|
item_count = 0
|
|
181
180
|
for item in stream_generator():
|
|
182
181
|
if item_count < skip_count:
|
|
183
182
|
item_count += 1
|
|
184
183
|
continue
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
items.append(item)
|
|
187
186
|
if len(items) >= self.page_size:
|
|
188
187
|
# We have a full page, create cursor for next page
|
|
189
|
-
next_cursor = CursorManager.create_cursor(
|
|
190
|
-
"skip": skip_count + len(items)
|
|
191
|
-
|
|
188
|
+
next_cursor = CursorManager.create_cursor(
|
|
189
|
+
{"skip": skip_count + len(items)}
|
|
190
|
+
)
|
|
192
191
|
return PaginatedResponse(items=items, next_cursor=next_cursor)
|
|
193
|
-
|
|
192
|
+
|
|
194
193
|
# No more items
|
|
195
194
|
return PaginatedResponse(items=items, next_cursor=None)
|
|
196
195
|
|
|
197
196
|
|
|
198
197
|
def paginate_list(
|
|
199
|
-
items: List[T],
|
|
200
|
-
cursor: Optional[str] = None,
|
|
201
|
-
page_size: int = 100
|
|
198
|
+
items: List[T], cursor: Optional[str] = None, page_size: int = 100
|
|
202
199
|
) -> PaginatedResponse[T]:
|
|
203
200
|
"""Convenience function to paginate a list.
|
|
204
|
-
|
|
201
|
+
|
|
205
202
|
Args:
|
|
206
203
|
items: List to paginate
|
|
207
204
|
cursor: Optional cursor
|
|
208
205
|
page_size: Items per page
|
|
209
|
-
|
|
206
|
+
|
|
210
207
|
Returns:
|
|
211
208
|
Paginated response
|
|
212
209
|
"""
|
|
@@ -216,11 +213,11 @@ def paginate_list(
|
|
|
216
213
|
|
|
217
214
|
def validate_cursor(cursor: str) -> bool:
|
|
218
215
|
"""Validate that a cursor is properly formatted.
|
|
219
|
-
|
|
216
|
+
|
|
220
217
|
Args:
|
|
221
218
|
cursor: Cursor string to validate
|
|
222
|
-
|
|
219
|
+
|
|
223
220
|
Returns:
|
|
224
221
|
True if valid, False otherwise
|
|
225
222
|
"""
|
|
226
|
-
return CursorManager.parse_cursor(cursor) is not None
|
|
223
|
+
return CursorManager.parse_cursor(cursor) is not None
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"""Permission system for the Hanzo AI server."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
import os
|
|
5
4
|
import sys
|
|
5
|
+
import json
|
|
6
6
|
import tempfile
|
|
7
|
-
from collections.abc import Awaitable, Callable
|
|
8
|
-
from pathlib import Path
|
|
9
7
|
from typing import Any, TypeVar, final
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from collections.abc import Callable, Awaitable
|
|
10
10
|
|
|
11
11
|
# Define type variables for better type annotations
|
|
12
12
|
T = TypeVar("T")
|
|
@@ -28,7 +28,7 @@ class PermissionManager:
|
|
|
28
28
|
else: # Unix/Linux/Mac
|
|
29
29
|
self.allowed_paths.add(Path("/tmp").resolve())
|
|
30
30
|
self.allowed_paths.add(Path("/var").resolve())
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
# Also allow user's home directory work folders
|
|
33
33
|
home = Path.home()
|
|
34
34
|
if home.exists():
|