fast-agent-mcp 0.1.13__py3-none-any.whl → 0.2.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.
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
- fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
- mcp_agent/__init__.py +75 -0
- mcp_agent/agents/agent.py +59 -371
- mcp_agent/agents/base_agent.py +522 -0
- mcp_agent/agents/workflow/__init__.py +1 -0
- mcp_agent/agents/workflow/chain_agent.py +173 -0
- mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
- mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
- mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +27 -11
- mcp_agent/agents/workflow/parallel_agent.py +182 -0
- mcp_agent/agents/workflow/router_agent.py +307 -0
- mcp_agent/app.py +3 -1
- mcp_agent/cli/commands/bootstrap.py +18 -7
- mcp_agent/cli/commands/setup.py +12 -4
- mcp_agent/cli/main.py +1 -1
- mcp_agent/cli/terminal.py +1 -1
- mcp_agent/config.py +24 -35
- mcp_agent/context.py +3 -1
- mcp_agent/context_dependent.py +3 -1
- mcp_agent/core/agent_types.py +10 -7
- mcp_agent/core/direct_agent_app.py +179 -0
- mcp_agent/core/direct_decorators.py +443 -0
- mcp_agent/core/direct_factory.py +476 -0
- mcp_agent/core/enhanced_prompt.py +15 -20
- mcp_agent/core/fastagent.py +151 -337
- mcp_agent/core/interactive_prompt.py +424 -0
- mcp_agent/core/mcp_content.py +19 -11
- mcp_agent/core/prompt.py +6 -2
- mcp_agent/core/validation.py +89 -16
- mcp_agent/executor/decorator_registry.py +6 -2
- mcp_agent/executor/temporal.py +35 -11
- mcp_agent/executor/workflow_signal.py +8 -2
- mcp_agent/human_input/handler.py +3 -1
- mcp_agent/llm/__init__.py +2 -0
- mcp_agent/{workflows/llm → llm}/augmented_llm.py +131 -256
- mcp_agent/{workflows/llm → llm}/augmented_llm_passthrough.py +35 -107
- mcp_agent/llm/augmented_llm_playback.py +83 -0
- mcp_agent/{workflows/llm → llm}/model_factory.py +26 -8
- mcp_agent/llm/providers/__init__.py +8 -0
- mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +5 -1
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +37 -141
- mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +112 -148
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +78 -35
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +73 -44
- mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +18 -4
- mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +3 -3
- mcp_agent/{workflows/llm → llm}/sampling_converter.py +0 -21
- mcp_agent/{workflows/llm → llm}/sampling_format_converter.py +16 -1
- mcp_agent/logging/logger.py +2 -2
- mcp_agent/mcp/gen_client.py +9 -3
- mcp_agent/mcp/interfaces.py +67 -45
- mcp_agent/mcp/logger_textio.py +97 -0
- mcp_agent/mcp/mcp_agent_client_session.py +12 -4
- mcp_agent/mcp/mcp_agent_server.py +3 -1
- mcp_agent/mcp/mcp_aggregator.py +124 -93
- mcp_agent/mcp/mcp_connection_manager.py +21 -7
- mcp_agent/mcp/prompt_message_multipart.py +59 -1
- mcp_agent/mcp/prompt_render.py +77 -0
- mcp_agent/mcp/prompt_serialization.py +20 -13
- mcp_agent/mcp/prompts/prompt_constants.py +18 -0
- mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
- mcp_agent/mcp/prompts/prompt_load.py +15 -5
- mcp_agent/mcp/prompts/prompt_server.py +154 -87
- mcp_agent/mcp/prompts/prompt_template.py +26 -35
- mcp_agent/mcp/resource_utils.py +3 -1
- mcp_agent/mcp/sampling.py +24 -15
- mcp_agent/mcp_server/agent_server.py +8 -5
- mcp_agent/mcp_server_registry.py +22 -9
- mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +1 -1
- mcp_agent/resources/examples/{data-analysis → in_dev}/slides.py +1 -1
- mcp_agent/resources/examples/internal/agent.py +4 -2
- mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
- mcp_agent/resources/examples/prompting/image_server.py +3 -1
- mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
- mcp_agent/ui/console_display.py +27 -7
- fast_agent_mcp-0.1.13.dist-info/RECORD +0 -164
- mcp_agent/core/agent_app.py +0 -570
- mcp_agent/core/agent_utils.py +0 -69
- mcp_agent/core/decorators.py +0 -448
- mcp_agent/core/factory.py +0 -422
- mcp_agent/core/proxies.py +0 -278
- mcp_agent/core/types.py +0 -22
- mcp_agent/eval/__init__.py +0 -0
- mcp_agent/mcp/stdio.py +0 -114
- mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
- mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
- mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
- mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
- mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
- mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/researcher-imp.py +0 -189
- mcp_agent/resources/examples/researcher/researcher.py +0 -39
- mcp_agent/resources/examples/workflows/chaining.py +0 -45
- mcp_agent/resources/examples/workflows/evaluator.py +0 -79
- mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
- mcp_agent/resources/examples/workflows/human_input.py +0 -26
- mcp_agent/resources/examples/workflows/orchestrator.py +0 -74
- mcp_agent/resources/examples/workflows/parallel.py +0 -79
- mcp_agent/resources/examples/workflows/router.py +0 -54
- mcp_agent/resources/examples/workflows/sse.py +0 -23
- mcp_agent/telemetry/__init__.py +0 -0
- mcp_agent/telemetry/usage_tracking.py +0 -19
- mcp_agent/workflows/__init__.py +0 -0
- mcp_agent/workflows/embedding/__init__.py +0 -0
- mcp_agent/workflows/embedding/embedding_base.py +0 -58
- mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
- mcp_agent/workflows/embedding/embedding_openai.py +0 -37
- mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -447
- mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -117
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -130
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -150
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -58
- mcp_agent/workflows/llm/__init__.py +0 -0
- mcp_agent/workflows/llm/augmented_llm_playback.py +0 -111
- mcp_agent/workflows/llm/providers/__init__.py +0 -8
- mcp_agent/workflows/orchestrator/__init__.py +0 -0
- mcp_agent/workflows/orchestrator/orchestrator.py +0 -535
- mcp_agent/workflows/parallel/__init__.py +0 -0
- mcp_agent/workflows/parallel/fan_in.py +0 -320
- mcp_agent/workflows/parallel/fan_out.py +0 -181
- mcp_agent/workflows/parallel/parallel_llm.py +0 -149
- mcp_agent/workflows/router/__init__.py +0 -0
- mcp_agent/workflows/router/router_base.py +0 -338
- mcp_agent/workflows/router/router_embedding.py +0 -226
- mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
- mcp_agent/workflows/router/router_embedding_openai.py +0 -59
- mcp_agent/workflows/router/router_llm.py +0 -304
- mcp_agent/workflows/swarm/__init__.py +0 -0
- mcp_agent/workflows/swarm/swarm.py +0 -292
- mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
- mcp_agent/workflows/swarm/swarm_openai.py +0 -41
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
- /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
- /mcp_agent/{workflows/llm → llm}/memory.py +0 -0
- /mcp_agent/{workflows/llm → llm}/prompt_utils.py +0 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
"""
|
2
|
+
Constants for the prompt system.
|
3
|
+
|
4
|
+
This module defines constants used throughout the prompt system, including
|
5
|
+
delimiters for parsing prompt files and serializing prompt messages.
|
6
|
+
"""
|
7
|
+
|
8
|
+
# Standard delimiters used for prompt template parsing and serialization
|
9
|
+
USER_DELIMITER = "---USER"
|
10
|
+
ASSISTANT_DELIMITER = "---ASSISTANT"
|
11
|
+
RESOURCE_DELIMITER = "---RESOURCE"
|
12
|
+
|
13
|
+
# Default delimiter mapping used by PromptTemplate and PromptTemplateLoader
|
14
|
+
DEFAULT_DELIMITER_MAP = {
|
15
|
+
USER_DELIMITER: "user",
|
16
|
+
ASSISTANT_DELIMITER: "assistant",
|
17
|
+
RESOURCE_DELIMITER: "resource",
|
18
|
+
}
|
@@ -0,0 +1,327 @@
|
|
1
|
+
"""
|
2
|
+
Helper functions for working with PromptMessage and PromptMessageMultipart objects.
|
3
|
+
|
4
|
+
These utilities simplify extracting content from nested message structures
|
5
|
+
without repetitive type checking.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from typing import List, Optional, Union, cast
|
9
|
+
|
10
|
+
from mcp.types import (
|
11
|
+
BlobResourceContents,
|
12
|
+
EmbeddedResource,
|
13
|
+
ImageContent,
|
14
|
+
PromptMessage,
|
15
|
+
TextContent,
|
16
|
+
TextResourceContents,
|
17
|
+
)
|
18
|
+
|
19
|
+
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
20
|
+
|
21
|
+
|
22
|
+
def get_text(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
|
23
|
+
"""
|
24
|
+
Extract text content from a content object if available.
|
25
|
+
|
26
|
+
Args:
|
27
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
The text content as a string or None if not a text content
|
31
|
+
"""
|
32
|
+
if isinstance(content, TextContent):
|
33
|
+
return content.text
|
34
|
+
|
35
|
+
if isinstance(content, EmbeddedResource):
|
36
|
+
if isinstance(content.resource, TextResourceContents):
|
37
|
+
return content.resource.text
|
38
|
+
|
39
|
+
return None
|
40
|
+
|
41
|
+
|
42
|
+
def get_image_data(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
|
43
|
+
"""
|
44
|
+
Extract image data from a content object if available.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
The image data as a base64 string or None if not an image content
|
51
|
+
"""
|
52
|
+
if isinstance(content, ImageContent):
|
53
|
+
return content.data
|
54
|
+
|
55
|
+
if isinstance(content, EmbeddedResource):
|
56
|
+
if isinstance(content.resource, BlobResourceContents):
|
57
|
+
# This assumes the blob might be an image, which isn't always true
|
58
|
+
# Consider checking the mimeType if needed
|
59
|
+
return content.resource.blob
|
60
|
+
|
61
|
+
return None
|
62
|
+
|
63
|
+
|
64
|
+
def get_resource_uri(content: Union[TextContent, ImageContent, EmbeddedResource]) -> Optional[str]:
|
65
|
+
"""
|
66
|
+
Extract resource URI from an EmbeddedResource if available.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
The resource URI as a string or None if not an embedded resource
|
73
|
+
"""
|
74
|
+
if isinstance(content, EmbeddedResource):
|
75
|
+
return str(content.resource.uri)
|
76
|
+
|
77
|
+
return None
|
78
|
+
|
79
|
+
|
80
|
+
def is_text_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
|
81
|
+
"""
|
82
|
+
Check if the content is text content.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
86
|
+
|
87
|
+
Returns:
|
88
|
+
True if the content is TextContent, False otherwise
|
89
|
+
"""
|
90
|
+
return isinstance(content, TextContent)
|
91
|
+
|
92
|
+
|
93
|
+
def is_image_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
|
94
|
+
"""
|
95
|
+
Check if the content is image content.
|
96
|
+
|
97
|
+
Args:
|
98
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
99
|
+
|
100
|
+
Returns:
|
101
|
+
True if the content is ImageContent, False otherwise
|
102
|
+
"""
|
103
|
+
return isinstance(content, ImageContent)
|
104
|
+
|
105
|
+
|
106
|
+
def is_resource_content(content: Union[TextContent, ImageContent, EmbeddedResource]) -> bool:
|
107
|
+
"""
|
108
|
+
Check if the content is an embedded resource.
|
109
|
+
|
110
|
+
Args:
|
111
|
+
content: A content object (TextContent, ImageContent, or EmbeddedResource)
|
112
|
+
|
113
|
+
Returns:
|
114
|
+
True if the content is EmbeddedResource, False otherwise
|
115
|
+
"""
|
116
|
+
return isinstance(content, EmbeddedResource)
|
117
|
+
|
118
|
+
|
119
|
+
class MessageContent:
|
120
|
+
"""
|
121
|
+
Helper class for working with message content in both PromptMessage and
|
122
|
+
PromptMessageMultipart objects.
|
123
|
+
"""
|
124
|
+
|
125
|
+
@staticmethod
|
126
|
+
def get_all_text(message: Union[PromptMessage, PromptMessageMultipart]) -> List[str]:
|
127
|
+
"""
|
128
|
+
Extract all text content from a message.
|
129
|
+
|
130
|
+
Args:
|
131
|
+
message: A PromptMessage or PromptMessageMultipart
|
132
|
+
|
133
|
+
Returns:
|
134
|
+
List of text strings from all text content parts
|
135
|
+
"""
|
136
|
+
if isinstance(message, PromptMessage):
|
137
|
+
text = get_text(message.content)
|
138
|
+
return [text] if text is not None else []
|
139
|
+
|
140
|
+
result = []
|
141
|
+
for content in message.content:
|
142
|
+
text = get_text(content)
|
143
|
+
if text is not None:
|
144
|
+
result.append(text)
|
145
|
+
|
146
|
+
return result
|
147
|
+
|
148
|
+
@staticmethod
|
149
|
+
def join_text(
|
150
|
+
message: Union[PromptMessage, PromptMessageMultipart], separator: str = "\n\n"
|
151
|
+
) -> str:
|
152
|
+
"""
|
153
|
+
Join all text content in a message with a separator.
|
154
|
+
|
155
|
+
Args:
|
156
|
+
message: A PromptMessage or PromptMessageMultipart
|
157
|
+
separator: String to use as separator (default: newlines)
|
158
|
+
|
159
|
+
Returns:
|
160
|
+
Joined text string
|
161
|
+
"""
|
162
|
+
return separator.join(MessageContent.get_all_text(message))
|
163
|
+
|
164
|
+
@staticmethod
|
165
|
+
def get_first_text(message: Union[PromptMessage, PromptMessageMultipart]) -> Optional[str]:
|
166
|
+
"""
|
167
|
+
Get the first available text content from a message.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
message: A PromptMessage or PromptMessageMultipart
|
171
|
+
|
172
|
+
Returns:
|
173
|
+
First text content or None if no text content exists
|
174
|
+
"""
|
175
|
+
if isinstance(message, PromptMessage):
|
176
|
+
return get_text(message.content)
|
177
|
+
|
178
|
+
for content in message.content:
|
179
|
+
text = get_text(content)
|
180
|
+
if text is not None:
|
181
|
+
return text
|
182
|
+
|
183
|
+
return None
|
184
|
+
|
185
|
+
@staticmethod
|
186
|
+
def has_text_at_first_position(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
|
187
|
+
"""
|
188
|
+
Check if a message has a TextContent at the first position.
|
189
|
+
This is a common case when dealing with messages that start with text.
|
190
|
+
|
191
|
+
Args:
|
192
|
+
message: A PromptMessage or PromptMessageMultipart
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
True if the message has TextContent at first position, False otherwise
|
196
|
+
"""
|
197
|
+
if isinstance(message, PromptMessage):
|
198
|
+
return isinstance(message.content, TextContent)
|
199
|
+
|
200
|
+
# For multipart messages, check if there's at least one item and the first is TextContent
|
201
|
+
return len(message.content) > 0 and isinstance(message.content[0], TextContent)
|
202
|
+
|
203
|
+
@staticmethod
|
204
|
+
def get_text_at_first_position(
|
205
|
+
message: Union[PromptMessage, PromptMessageMultipart],
|
206
|
+
) -> Optional[str]:
|
207
|
+
"""
|
208
|
+
Get the text from the first position of a message if it's TextContent.
|
209
|
+
|
210
|
+
Args:
|
211
|
+
message: A PromptMessage or PromptMessageMultipart
|
212
|
+
|
213
|
+
Returns:
|
214
|
+
The text content at the first position if it's TextContent,
|
215
|
+
None otherwise
|
216
|
+
"""
|
217
|
+
if not MessageContent.has_text_at_first_position(message):
|
218
|
+
return None
|
219
|
+
|
220
|
+
if isinstance(message, PromptMessage):
|
221
|
+
return cast("TextContent", message.content).text
|
222
|
+
|
223
|
+
# Safe to cast since we've verified the first item is TextContent
|
224
|
+
return cast("TextContent", message.content[0]).text
|
225
|
+
|
226
|
+
@staticmethod
|
227
|
+
def get_all_images(message: Union[PromptMessage, PromptMessageMultipart]) -> List[str]:
|
228
|
+
"""
|
229
|
+
Extract all image data from a message.
|
230
|
+
|
231
|
+
Args:
|
232
|
+
message: A PromptMessage or PromptMessageMultipart
|
233
|
+
|
234
|
+
Returns:
|
235
|
+
List of image data strings from all image content parts
|
236
|
+
"""
|
237
|
+
if isinstance(message, PromptMessage):
|
238
|
+
img_data = get_image_data(message.content)
|
239
|
+
return [img_data] if img_data is not None else []
|
240
|
+
|
241
|
+
result = []
|
242
|
+
for content in message.content:
|
243
|
+
img_data = get_image_data(content)
|
244
|
+
if img_data is not None:
|
245
|
+
result.append(img_data)
|
246
|
+
|
247
|
+
return result
|
248
|
+
|
249
|
+
@staticmethod
|
250
|
+
def get_first_image(message: Union[PromptMessage, PromptMessageMultipart]) -> Optional[str]:
|
251
|
+
"""
|
252
|
+
Get the first available image data from a message.
|
253
|
+
|
254
|
+
Args:
|
255
|
+
message: A PromptMessage or PromptMessageMultipart
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
First image data or None if no image content exists
|
259
|
+
"""
|
260
|
+
if isinstance(message, PromptMessage):
|
261
|
+
return get_image_data(message.content)
|
262
|
+
|
263
|
+
for content in message.content:
|
264
|
+
img_data = get_image_data(content)
|
265
|
+
if img_data is not None:
|
266
|
+
return img_data
|
267
|
+
|
268
|
+
return None
|
269
|
+
|
270
|
+
@staticmethod
|
271
|
+
def get_all_resources(
|
272
|
+
message: Union[PromptMessage, PromptMessageMultipart],
|
273
|
+
) -> List[EmbeddedResource]:
|
274
|
+
"""
|
275
|
+
Extract all embedded resources from a message.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
message: A PromptMessage or PromptMessageMultipart
|
279
|
+
|
280
|
+
Returns:
|
281
|
+
List of EmbeddedResource objects
|
282
|
+
"""
|
283
|
+
if isinstance(message, PromptMessage):
|
284
|
+
if isinstance(message.content, EmbeddedResource):
|
285
|
+
return [message.content]
|
286
|
+
return []
|
287
|
+
|
288
|
+
return [content for content in message.content if isinstance(content, EmbeddedResource)]
|
289
|
+
|
290
|
+
@staticmethod
|
291
|
+
def has_text(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
|
292
|
+
"""
|
293
|
+
Check if the message has any text content.
|
294
|
+
|
295
|
+
Args:
|
296
|
+
message: A PromptMessage or PromptMessageMultipart
|
297
|
+
|
298
|
+
Returns:
|
299
|
+
True if the message has text content, False otherwise
|
300
|
+
"""
|
301
|
+
return len(MessageContent.get_all_text(message)) > 0
|
302
|
+
|
303
|
+
@staticmethod
|
304
|
+
def has_images(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
|
305
|
+
"""
|
306
|
+
Check if the message has any image content.
|
307
|
+
|
308
|
+
Args:
|
309
|
+
message: A PromptMessage or PromptMessageMultipart
|
310
|
+
|
311
|
+
Returns:
|
312
|
+
True if the message has image content, False otherwise
|
313
|
+
"""
|
314
|
+
return len(MessageContent.get_all_images(message)) > 0
|
315
|
+
|
316
|
+
@staticmethod
|
317
|
+
def has_resources(message: Union[PromptMessage, PromptMessageMultipart]) -> bool:
|
318
|
+
"""
|
319
|
+
Check if the message has any embedded resources.
|
320
|
+
|
321
|
+
Args:
|
322
|
+
message: A PromptMessage or PromptMessageMultipart
|
323
|
+
|
324
|
+
Returns:
|
325
|
+
True if the message has embedded resources, False otherwise
|
326
|
+
"""
|
327
|
+
return len(MessageContent.get_all_resources(message)) > 0
|
@@ -31,7 +31,9 @@ def cast_message_role(role: str) -> MessageRole:
|
|
31
31
|
return "user"
|
32
32
|
|
33
33
|
|
34
|
-
def create_messages_with_resources(
|
34
|
+
def create_messages_with_resources(
|
35
|
+
content_sections: List[PromptContent], prompt_files: List[Path]
|
36
|
+
) -> List[PromptMessage]:
|
35
37
|
"""
|
36
38
|
Create a list of messages from content sections, with resources properly handled.
|
37
39
|
|
@@ -60,10 +62,14 @@ def create_messages_with_resources(content_sections: List[PromptContent], prompt
|
|
60
62
|
for resource_path in section.resources:
|
61
63
|
try:
|
62
64
|
# Load resource with information about its type
|
63
|
-
resource_content, mime_type, is_binary = resource_utils.load_resource_content(
|
65
|
+
resource_content, mime_type, is_binary = resource_utils.load_resource_content(
|
66
|
+
resource_path, prompt_files
|
67
|
+
)
|
64
68
|
|
65
69
|
# Create and add the resource message
|
66
|
-
resource_message = create_resource_message(
|
70
|
+
resource_message = create_resource_message(
|
71
|
+
resource_path, resource_content, mime_type, is_binary, role
|
72
|
+
)
|
67
73
|
messages.append(resource_message)
|
68
74
|
except Exception as e:
|
69
75
|
logger.error(f"Error loading resource {resource_path}: {e}")
|
@@ -76,7 +82,9 @@ def create_content_message(text: str, role: MessageRole) -> PromptMessage:
|
|
76
82
|
return PromptMessage(role=role, content=TextContent(type="text", text=text))
|
77
83
|
|
78
84
|
|
79
|
-
def create_resource_message(
|
85
|
+
def create_resource_message(
|
86
|
+
resource_path: str, content: str, mime_type: str, is_binary: bool, role: MessageRole
|
87
|
+
) -> Message:
|
80
88
|
"""Create a resource message with the specified content and role"""
|
81
89
|
message_class = UserMessage if role == "user" else AssistantMessage
|
82
90
|
|
@@ -86,7 +94,9 @@ def create_resource_message(resource_path: str, content: str, mime_type: str, is
|
|
86
94
|
return message_class(content=image_content)
|
87
95
|
else:
|
88
96
|
# For other resources, create an EmbeddedResource
|
89
|
-
embedded_resource = resource_utils.create_embedded_resource(
|
97
|
+
embedded_resource = resource_utils.create_embedded_resource(
|
98
|
+
resource_path, content, mime_type, is_binary
|
99
|
+
)
|
90
100
|
return message_class(content=embedded_resource)
|
91
101
|
|
92
102
|
|