workspace-mcp 1.0.1__py3-none-any.whl → 1.0.2__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.
gchat/chat_tools.py CHANGED
@@ -13,11 +13,13 @@ from googleapiclient.errors import HttpError
13
13
  # Auth & server utilities
14
14
  from auth.service_decorator import require_google_service
15
15
  from core.server import server
16
+ from core.utils import handle_http_errors
16
17
 
17
18
  logger = logging.getLogger(__name__)
18
19
 
19
20
  @server.tool()
20
21
  @require_google_service("chat", "chat_read")
22
+ @handle_http_errors("list_spaces")
21
23
  async def list_spaces(
22
24
  service,
23
25
  user_google_email: str,
@@ -32,44 +34,37 @@ async def list_spaces(
32
34
  """
33
35
  logger.info(f"[list_spaces] Email={user_google_email}, Type={space_type}")
34
36
 
35
- try:
36
- # Build filter based on space_type
37
- filter_param = None
38
- if space_type == "room":
39
- filter_param = "spaceType = SPACE"
40
- elif space_type == "dm":
41
- filter_param = "spaceType = DIRECT_MESSAGE"
37
+ # Build filter based on space_type
38
+ filter_param = None
39
+ if space_type == "room":
40
+ filter_param = "spaceType = SPACE"
41
+ elif space_type == "dm":
42
+ filter_param = "spaceType = DIRECT_MESSAGE"
42
43
 
43
- request_params = {"pageSize": page_size}
44
- if filter_param:
45
- request_params["filter"] = filter_param
44
+ request_params = {"pageSize": page_size}
45
+ if filter_param:
46
+ request_params["filter"] = filter_param
46
47
 
47
- response = await asyncio.to_thread(
48
- service.spaces().list(**request_params).execute
49
- )
48
+ response = await asyncio.to_thread(
49
+ service.spaces().list(**request_params).execute
50
+ )
50
51
 
51
- spaces = response.get('spaces', [])
52
- if not spaces:
53
- return f"No Chat spaces found for type '{space_type}'."
52
+ spaces = response.get('spaces', [])
53
+ if not spaces:
54
+ return f"No Chat spaces found for type '{space_type}'."
54
55
 
55
- output = [f"Found {len(spaces)} Chat spaces (type: {space_type}):"]
56
- for space in spaces:
57
- space_name = space.get('displayName', 'Unnamed Space')
58
- space_id = space.get('name', '')
59
- space_type_actual = space.get('spaceType', 'UNKNOWN')
60
- output.append(f"- {space_name} (ID: {space_id}, Type: {space_type_actual})")
56
+ output = [f"Found {len(spaces)} Chat spaces (type: {space_type}):"]
57
+ for space in spaces:
58
+ space_name = space.get('displayName', 'Unnamed Space')
59
+ space_id = space.get('name', '')
60
+ space_type_actual = space.get('spaceType', 'UNKNOWN')
61
+ output.append(f"- {space_name} (ID: {space_id}, Type: {space_type_actual})")
61
62
 
62
- return "\n".join(output)
63
-
64
- except HttpError as e:
65
- logger.error(f"API error in list_spaces: {e}", exc_info=True)
66
- raise Exception(f"API error: {e}")
67
- except Exception as e:
68
- logger.exception(f"Unexpected error in list_spaces: {e}")
69
- raise Exception(f"Unexpected error: {e}")
63
+ return "\n".join(output)
70
64
 
71
65
  @server.tool()
72
66
  @require_google_service("chat", "chat_read")
67
+ @handle_http_errors("get_messages")
73
68
  async def get_messages(
74
69
  service,
75
70
  user_google_email: str,
@@ -85,48 +80,41 @@ async def get_messages(
85
80
  """
86
81
  logger.info(f"[get_messages] Space ID: '{space_id}' for user '{user_google_email}'")
87
82
 
88
- try:
89
- # Get space info first
90
- space_info = await asyncio.to_thread(
91
- service.spaces().get(name=space_id).execute
92
- )
93
- space_name = space_info.get('displayName', 'Unknown Space')
94
-
95
- # Get messages
96
- response = await asyncio.to_thread(
97
- service.spaces().messages().list(
98
- parent=space_id,
99
- pageSize=page_size,
100
- orderBy=order_by
101
- ).execute
102
- )
103
-
104
- messages = response.get('messages', [])
105
- if not messages:
106
- return f"No messages found in space '{space_name}' (ID: {space_id})."
107
-
108
- output = [f"Messages from '{space_name}' (ID: {space_id}):\n"]
109
- for msg in messages:
110
- sender = msg.get('sender', {}).get('displayName', 'Unknown Sender')
111
- create_time = msg.get('createTime', 'Unknown Time')
112
- text_content = msg.get('text', 'No text content')
113
- msg_name = msg.get('name', '')
114
-
115
- output.append(f"[{create_time}] {sender}:")
116
- output.append(f" {text_content}")
117
- output.append(f" (Message ID: {msg_name})\n")
118
-
119
- return "\n".join(output)
120
-
121
- except HttpError as error:
122
- logger.error(f"[get_messages] API error for space {space_id}: {error}", exc_info=True)
123
- raise Exception(f"API error accessing space {space_id}: {error}")
124
- except Exception as e:
125
- logger.exception(f"[get_messages] Unexpected error for space {space_id}: {e}")
126
- raise Exception(f"Unexpected error accessing space {space_id}: {e}")
83
+ # Get space info first
84
+ space_info = await asyncio.to_thread(
85
+ service.spaces().get(name=space_id).execute
86
+ )
87
+ space_name = space_info.get('displayName', 'Unknown Space')
88
+
89
+ # Get messages
90
+ response = await asyncio.to_thread(
91
+ service.spaces().messages().list(
92
+ parent=space_id,
93
+ pageSize=page_size,
94
+ orderBy=order_by
95
+ ).execute
96
+ )
97
+
98
+ messages = response.get('messages', [])
99
+ if not messages:
100
+ return f"No messages found in space '{space_name}' (ID: {space_id})."
101
+
102
+ output = [f"Messages from '{space_name}' (ID: {space_id}):\n"]
103
+ for msg in messages:
104
+ sender = msg.get('sender', {}).get('displayName', 'Unknown Sender')
105
+ create_time = msg.get('createTime', 'Unknown Time')
106
+ text_content = msg.get('text', 'No text content')
107
+ msg_name = msg.get('name', '')
108
+
109
+ output.append(f"[{create_time}] {sender}:")
110
+ output.append(f" {text_content}")
111
+ output.append(f" (Message ID: {msg_name})\n")
112
+
113
+ return "\n".join(output)
127
114
 
128
115
  @server.tool()
129
116
  @require_google_service("chat", "chat_write")
117
+ @handle_http_errors("send_message")
130
118
  async def send_message(
131
119
  service,
132
120
  user_google_email: str,
@@ -142,39 +130,32 @@ async def send_message(
142
130
  """
143
131
  logger.info(f"[send_message] Email: '{user_google_email}', Space: '{space_id}'")
144
132
 
145
- try:
146
- message_body = {
147
- 'text': message_text
148
- }
149
-
150
- # Add thread key if provided (for threaded replies)
151
- request_params = {
152
- 'parent': space_id,
153
- 'body': message_body
154
- }
155
- if thread_key:
156
- request_params['threadKey'] = thread_key
157
-
158
- message = await asyncio.to_thread(
159
- service.spaces().messages().create(**request_params).execute
160
- )
133
+ message_body = {
134
+ 'text': message_text
135
+ }
161
136
 
162
- message_name = message.get('name', '')
163
- create_time = message.get('createTime', '')
137
+ # Add thread key if provided (for threaded replies)
138
+ request_params = {
139
+ 'parent': space_id,
140
+ 'body': message_body
141
+ }
142
+ if thread_key:
143
+ request_params['threadKey'] = thread_key
164
144
 
165
- msg = f"Message sent to space '{space_id}' by {user_google_email}. Message ID: {message_name}, Time: {create_time}"
166
- logger.info(f"Successfully sent message to space '{space_id}' by {user_google_email}")
167
- return msg
145
+ message = await asyncio.to_thread(
146
+ service.spaces().messages().create(**request_params).execute
147
+ )
168
148
 
169
- except HttpError as e:
170
- logger.error(f"API error in send_message: {e}", exc_info=True)
171
- raise Exception(f"API error: {e}")
172
- except Exception as e:
173
- logger.exception(f"Unexpected error in send_message: {e}")
174
- raise Exception(f"Unexpected error: {e}")
149
+ message_name = message.get('name', '')
150
+ create_time = message.get('createTime', '')
151
+
152
+ msg = f"Message sent to space '{space_id}' by {user_google_email}. Message ID: {message_name}, Time: {create_time}"
153
+ logger.info(f"Successfully sent message to space '{space_id}' by {user_google_email}")
154
+ return msg
175
155
 
176
156
  @server.tool()
177
157
  @require_google_service("chat", "chat_read")
158
+ @handle_http_errors("search_messages")
178
159
  async def search_messages(
179
160
  service,
180
161
  user_google_email: str,
@@ -190,65 +171,57 @@ async def search_messages(
190
171
  """
191
172
  logger.info(f"[search_messages] Email={user_google_email}, Query='{query}'")
192
173
 
193
- try:
194
- # If specific space provided, search within that space
195
- if space_id:
196
- response = await asyncio.to_thread(
197
- service.spaces().messages().list(
198
- parent=space_id,
199
- pageSize=page_size,
200
- filter=f'text:"{query}"'
201
- ).execute
202
- )
203
- messages = response.get('messages', [])
204
- context = f"space '{space_id}'"
205
- else:
206
- # Search across all accessible spaces (this may require iterating through spaces)
207
- # For simplicity, we'll search the user's spaces first
208
- spaces_response = await asyncio.to_thread(
209
- service.spaces().list(pageSize=100).execute
210
- )
211
- spaces = spaces_response.get('spaces', [])
212
-
213
- messages = []
214
- for space in spaces[:10]: # Limit to first 10 spaces to avoid timeout
215
- try:
216
- space_messages = await asyncio.to_thread(
217
- service.spaces().messages().list(
218
- parent=space.get('name'),
219
- pageSize=5,
220
- filter=f'text:"{query}"'
221
- ).execute
222
- )
223
- space_msgs = space_messages.get('messages', [])
224
- for msg in space_msgs:
225
- msg['_space_name'] = space.get('displayName', 'Unknown')
226
- messages.extend(space_msgs)
227
- except HttpError:
228
- continue # Skip spaces we can't access
229
- context = "all accessible spaces"
230
-
231
- if not messages:
232
- return f"No messages found matching '{query}' in {context}."
233
-
234
- output = [f"Found {len(messages)} messages matching '{query}' in {context}:"]
235
- for msg in messages:
236
- sender = msg.get('sender', {}).get('displayName', 'Unknown Sender')
237
- create_time = msg.get('createTime', 'Unknown Time')
238
- text_content = msg.get('text', 'No text content')
239
- space_name = msg.get('_space_name', 'Unknown Space')
240
-
241
- # Truncate long messages
242
- if len(text_content) > 100:
243
- text_content = text_content[:100] + "..."
244
-
245
- output.append(f"- [{create_time}] {sender} in '{space_name}': {text_content}")
246
-
247
- return "\n".join(output)
248
-
249
- except HttpError as e:
250
- logger.error(f"API error in search_messages: {e}", exc_info=True)
251
- raise Exception(f"API error: {e}")
252
- except Exception as e:
253
- logger.exception(f"Unexpected error in search_messages: {e}")
254
- raise Exception(f"Unexpected error: {e}")
174
+ # If specific space provided, search within that space
175
+ if space_id:
176
+ response = await asyncio.to_thread(
177
+ service.spaces().messages().list(
178
+ parent=space_id,
179
+ pageSize=page_size,
180
+ filter=f'text:"{query}"'
181
+ ).execute
182
+ )
183
+ messages = response.get('messages', [])
184
+ context = f"space '{space_id}'"
185
+ else:
186
+ # Search across all accessible spaces (this may require iterating through spaces)
187
+ # For simplicity, we'll search the user's spaces first
188
+ spaces_response = await asyncio.to_thread(
189
+ service.spaces().list(pageSize=100).execute
190
+ )
191
+ spaces = spaces_response.get('spaces', [])
192
+
193
+ messages = []
194
+ for space in spaces[:10]: # Limit to first 10 spaces to avoid timeout
195
+ try:
196
+ space_messages = await asyncio.to_thread(
197
+ service.spaces().messages().list(
198
+ parent=space.get('name'),
199
+ pageSize=5,
200
+ filter=f'text:"{query}"'
201
+ ).execute
202
+ )
203
+ space_msgs = space_messages.get('messages', [])
204
+ for msg in space_msgs:
205
+ msg['_space_name'] = space.get('displayName', 'Unknown')
206
+ messages.extend(space_msgs)
207
+ except HttpError:
208
+ continue # Skip spaces we can't access
209
+ context = "all accessible spaces"
210
+
211
+ if not messages:
212
+ return f"No messages found matching '{query}' in {context}."
213
+
214
+ output = [f"Found {len(messages)} messages matching '{query}' in {context}:"]
215
+ for msg in messages:
216
+ sender = msg.get('sender', {}).get('displayName', 'Unknown Sender')
217
+ create_time = msg.get('createTime', 'Unknown Time')
218
+ text_content = msg.get('text', 'No text content')
219
+ space_name = msg.get('_space_name', 'Unknown Space')
220
+
221
+ # Truncate long messages
222
+ if len(text_content) > 100:
223
+ text_content = text_content[:100] + "..."
224
+
225
+ output.append(f"- [{create_time}] {sender} in '{space_name}': {text_content}")
226
+
227
+ return "\n".join(output)