fast-agent-mcp 0.4.7__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.
Files changed (261) hide show
  1. fast_agent/__init__.py +183 -0
  2. fast_agent/acp/__init__.py +19 -0
  3. fast_agent/acp/acp_aware_mixin.py +304 -0
  4. fast_agent/acp/acp_context.py +437 -0
  5. fast_agent/acp/content_conversion.py +136 -0
  6. fast_agent/acp/filesystem_runtime.py +427 -0
  7. fast_agent/acp/permission_store.py +269 -0
  8. fast_agent/acp/server/__init__.py +5 -0
  9. fast_agent/acp/server/agent_acp_server.py +1472 -0
  10. fast_agent/acp/slash_commands.py +1050 -0
  11. fast_agent/acp/terminal_runtime.py +408 -0
  12. fast_agent/acp/tool_permission_adapter.py +125 -0
  13. fast_agent/acp/tool_permissions.py +474 -0
  14. fast_agent/acp/tool_progress.py +814 -0
  15. fast_agent/agents/__init__.py +85 -0
  16. fast_agent/agents/agent_types.py +64 -0
  17. fast_agent/agents/llm_agent.py +350 -0
  18. fast_agent/agents/llm_decorator.py +1139 -0
  19. fast_agent/agents/mcp_agent.py +1337 -0
  20. fast_agent/agents/tool_agent.py +271 -0
  21. fast_agent/agents/workflow/agents_as_tools_agent.py +849 -0
  22. fast_agent/agents/workflow/chain_agent.py +212 -0
  23. fast_agent/agents/workflow/evaluator_optimizer.py +380 -0
  24. fast_agent/agents/workflow/iterative_planner.py +652 -0
  25. fast_agent/agents/workflow/maker_agent.py +379 -0
  26. fast_agent/agents/workflow/orchestrator_models.py +218 -0
  27. fast_agent/agents/workflow/orchestrator_prompts.py +248 -0
  28. fast_agent/agents/workflow/parallel_agent.py +250 -0
  29. fast_agent/agents/workflow/router_agent.py +353 -0
  30. fast_agent/cli/__init__.py +0 -0
  31. fast_agent/cli/__main__.py +73 -0
  32. fast_agent/cli/commands/acp.py +159 -0
  33. fast_agent/cli/commands/auth.py +404 -0
  34. fast_agent/cli/commands/check_config.py +783 -0
  35. fast_agent/cli/commands/go.py +514 -0
  36. fast_agent/cli/commands/quickstart.py +557 -0
  37. fast_agent/cli/commands/serve.py +143 -0
  38. fast_agent/cli/commands/server_helpers.py +114 -0
  39. fast_agent/cli/commands/setup.py +174 -0
  40. fast_agent/cli/commands/url_parser.py +190 -0
  41. fast_agent/cli/constants.py +40 -0
  42. fast_agent/cli/main.py +115 -0
  43. fast_agent/cli/terminal.py +24 -0
  44. fast_agent/config.py +798 -0
  45. fast_agent/constants.py +41 -0
  46. fast_agent/context.py +279 -0
  47. fast_agent/context_dependent.py +50 -0
  48. fast_agent/core/__init__.py +92 -0
  49. fast_agent/core/agent_app.py +448 -0
  50. fast_agent/core/core_app.py +137 -0
  51. fast_agent/core/direct_decorators.py +784 -0
  52. fast_agent/core/direct_factory.py +620 -0
  53. fast_agent/core/error_handling.py +27 -0
  54. fast_agent/core/exceptions.py +90 -0
  55. fast_agent/core/executor/__init__.py +0 -0
  56. fast_agent/core/executor/executor.py +280 -0
  57. fast_agent/core/executor/task_registry.py +32 -0
  58. fast_agent/core/executor/workflow_signal.py +324 -0
  59. fast_agent/core/fastagent.py +1186 -0
  60. fast_agent/core/logging/__init__.py +5 -0
  61. fast_agent/core/logging/events.py +138 -0
  62. fast_agent/core/logging/json_serializer.py +164 -0
  63. fast_agent/core/logging/listeners.py +309 -0
  64. fast_agent/core/logging/logger.py +278 -0
  65. fast_agent/core/logging/transport.py +481 -0
  66. fast_agent/core/prompt.py +9 -0
  67. fast_agent/core/prompt_templates.py +183 -0
  68. fast_agent/core/validation.py +326 -0
  69. fast_agent/event_progress.py +62 -0
  70. fast_agent/history/history_exporter.py +49 -0
  71. fast_agent/human_input/__init__.py +47 -0
  72. fast_agent/human_input/elicitation_handler.py +123 -0
  73. fast_agent/human_input/elicitation_state.py +33 -0
  74. fast_agent/human_input/form_elements.py +59 -0
  75. fast_agent/human_input/form_fields.py +256 -0
  76. fast_agent/human_input/simple_form.py +113 -0
  77. fast_agent/human_input/types.py +40 -0
  78. fast_agent/interfaces.py +310 -0
  79. fast_agent/llm/__init__.py +9 -0
  80. fast_agent/llm/cancellation.py +22 -0
  81. fast_agent/llm/fastagent_llm.py +931 -0
  82. fast_agent/llm/internal/passthrough.py +161 -0
  83. fast_agent/llm/internal/playback.py +129 -0
  84. fast_agent/llm/internal/silent.py +41 -0
  85. fast_agent/llm/internal/slow.py +38 -0
  86. fast_agent/llm/memory.py +275 -0
  87. fast_agent/llm/model_database.py +490 -0
  88. fast_agent/llm/model_factory.py +388 -0
  89. fast_agent/llm/model_info.py +102 -0
  90. fast_agent/llm/prompt_utils.py +155 -0
  91. fast_agent/llm/provider/anthropic/anthropic_utils.py +84 -0
  92. fast_agent/llm/provider/anthropic/cache_planner.py +56 -0
  93. fast_agent/llm/provider/anthropic/llm_anthropic.py +796 -0
  94. fast_agent/llm/provider/anthropic/multipart_converter_anthropic.py +462 -0
  95. fast_agent/llm/provider/bedrock/bedrock_utils.py +218 -0
  96. fast_agent/llm/provider/bedrock/llm_bedrock.py +2207 -0
  97. fast_agent/llm/provider/bedrock/multipart_converter_bedrock.py +84 -0
  98. fast_agent/llm/provider/google/google_converter.py +466 -0
  99. fast_agent/llm/provider/google/llm_google_native.py +681 -0
  100. fast_agent/llm/provider/openai/llm_aliyun.py +31 -0
  101. fast_agent/llm/provider/openai/llm_azure.py +143 -0
  102. fast_agent/llm/provider/openai/llm_deepseek.py +76 -0
  103. fast_agent/llm/provider/openai/llm_generic.py +35 -0
  104. fast_agent/llm/provider/openai/llm_google_oai.py +32 -0
  105. fast_agent/llm/provider/openai/llm_groq.py +42 -0
  106. fast_agent/llm/provider/openai/llm_huggingface.py +85 -0
  107. fast_agent/llm/provider/openai/llm_openai.py +1195 -0
  108. fast_agent/llm/provider/openai/llm_openai_compatible.py +138 -0
  109. fast_agent/llm/provider/openai/llm_openrouter.py +45 -0
  110. fast_agent/llm/provider/openai/llm_tensorzero_openai.py +128 -0
  111. fast_agent/llm/provider/openai/llm_xai.py +38 -0
  112. fast_agent/llm/provider/openai/multipart_converter_openai.py +561 -0
  113. fast_agent/llm/provider/openai/openai_multipart.py +169 -0
  114. fast_agent/llm/provider/openai/openai_utils.py +67 -0
  115. fast_agent/llm/provider/openai/responses.py +133 -0
  116. fast_agent/llm/provider_key_manager.py +139 -0
  117. fast_agent/llm/provider_types.py +34 -0
  118. fast_agent/llm/request_params.py +61 -0
  119. fast_agent/llm/sampling_converter.py +98 -0
  120. fast_agent/llm/stream_types.py +9 -0
  121. fast_agent/llm/usage_tracking.py +445 -0
  122. fast_agent/mcp/__init__.py +56 -0
  123. fast_agent/mcp/common.py +26 -0
  124. fast_agent/mcp/elicitation_factory.py +84 -0
  125. fast_agent/mcp/elicitation_handlers.py +164 -0
  126. fast_agent/mcp/gen_client.py +83 -0
  127. fast_agent/mcp/helpers/__init__.py +36 -0
  128. fast_agent/mcp/helpers/content_helpers.py +352 -0
  129. fast_agent/mcp/helpers/server_config_helpers.py +25 -0
  130. fast_agent/mcp/hf_auth.py +147 -0
  131. fast_agent/mcp/interfaces.py +92 -0
  132. fast_agent/mcp/logger_textio.py +108 -0
  133. fast_agent/mcp/mcp_agent_client_session.py +411 -0
  134. fast_agent/mcp/mcp_aggregator.py +2175 -0
  135. fast_agent/mcp/mcp_connection_manager.py +723 -0
  136. fast_agent/mcp/mcp_content.py +262 -0
  137. fast_agent/mcp/mime_utils.py +108 -0
  138. fast_agent/mcp/oauth_client.py +509 -0
  139. fast_agent/mcp/prompt.py +159 -0
  140. fast_agent/mcp/prompt_message_extended.py +155 -0
  141. fast_agent/mcp/prompt_render.py +84 -0
  142. fast_agent/mcp/prompt_serialization.py +580 -0
  143. fast_agent/mcp/prompts/__init__.py +0 -0
  144. fast_agent/mcp/prompts/__main__.py +7 -0
  145. fast_agent/mcp/prompts/prompt_constants.py +18 -0
  146. fast_agent/mcp/prompts/prompt_helpers.py +238 -0
  147. fast_agent/mcp/prompts/prompt_load.py +186 -0
  148. fast_agent/mcp/prompts/prompt_server.py +552 -0
  149. fast_agent/mcp/prompts/prompt_template.py +438 -0
  150. fast_agent/mcp/resource_utils.py +215 -0
  151. fast_agent/mcp/sampling.py +200 -0
  152. fast_agent/mcp/server/__init__.py +4 -0
  153. fast_agent/mcp/server/agent_server.py +613 -0
  154. fast_agent/mcp/skybridge.py +44 -0
  155. fast_agent/mcp/sse_tracking.py +287 -0
  156. fast_agent/mcp/stdio_tracking_simple.py +59 -0
  157. fast_agent/mcp/streamable_http_tracking.py +309 -0
  158. fast_agent/mcp/tool_execution_handler.py +137 -0
  159. fast_agent/mcp/tool_permission_handler.py +88 -0
  160. fast_agent/mcp/transport_tracking.py +634 -0
  161. fast_agent/mcp/types.py +24 -0
  162. fast_agent/mcp/ui_agent.py +48 -0
  163. fast_agent/mcp/ui_mixin.py +209 -0
  164. fast_agent/mcp_server_registry.py +89 -0
  165. fast_agent/py.typed +0 -0
  166. fast_agent/resources/examples/data-analysis/analysis-campaign.py +189 -0
  167. fast_agent/resources/examples/data-analysis/analysis.py +68 -0
  168. fast_agent/resources/examples/data-analysis/fastagent.config.yaml +41 -0
  169. fast_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +1471 -0
  170. fast_agent/resources/examples/mcp/elicitations/elicitation_account_server.py +88 -0
  171. fast_agent/resources/examples/mcp/elicitations/elicitation_forms_server.py +297 -0
  172. fast_agent/resources/examples/mcp/elicitations/elicitation_game_server.py +164 -0
  173. fast_agent/resources/examples/mcp/elicitations/fastagent.config.yaml +35 -0
  174. fast_agent/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +17 -0
  175. fast_agent/resources/examples/mcp/elicitations/forms_demo.py +107 -0
  176. fast_agent/resources/examples/mcp/elicitations/game_character.py +65 -0
  177. fast_agent/resources/examples/mcp/elicitations/game_character_handler.py +256 -0
  178. fast_agent/resources/examples/mcp/elicitations/tool_call.py +21 -0
  179. fast_agent/resources/examples/mcp/state-transfer/agent_one.py +18 -0
  180. fast_agent/resources/examples/mcp/state-transfer/agent_two.py +18 -0
  181. fast_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +27 -0
  182. fast_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +15 -0
  183. fast_agent/resources/examples/researcher/fastagent.config.yaml +61 -0
  184. fast_agent/resources/examples/researcher/researcher-eval.py +53 -0
  185. fast_agent/resources/examples/researcher/researcher-imp.py +189 -0
  186. fast_agent/resources/examples/researcher/researcher.py +36 -0
  187. fast_agent/resources/examples/tensorzero/.env.sample +2 -0
  188. fast_agent/resources/examples/tensorzero/Makefile +31 -0
  189. fast_agent/resources/examples/tensorzero/README.md +56 -0
  190. fast_agent/resources/examples/tensorzero/agent.py +35 -0
  191. fast_agent/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
  192. fast_agent/resources/examples/tensorzero/demo_images/crab.png +0 -0
  193. fast_agent/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
  194. fast_agent/resources/examples/tensorzero/docker-compose.yml +105 -0
  195. fast_agent/resources/examples/tensorzero/fastagent.config.yaml +19 -0
  196. fast_agent/resources/examples/tensorzero/image_demo.py +67 -0
  197. fast_agent/resources/examples/tensorzero/mcp_server/Dockerfile +25 -0
  198. fast_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh +35 -0
  199. fast_agent/resources/examples/tensorzero/mcp_server/mcp_server.py +31 -0
  200. fast_agent/resources/examples/tensorzero/mcp_server/pyproject.toml +11 -0
  201. fast_agent/resources/examples/tensorzero/simple_agent.py +25 -0
  202. fast_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json +29 -0
  203. fast_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +11 -0
  204. fast_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +35 -0
  205. fast_agent/resources/examples/workflows/agents_as_tools_extended.py +73 -0
  206. fast_agent/resources/examples/workflows/agents_as_tools_simple.py +50 -0
  207. fast_agent/resources/examples/workflows/chaining.py +37 -0
  208. fast_agent/resources/examples/workflows/evaluator.py +77 -0
  209. fast_agent/resources/examples/workflows/fastagent.config.yaml +26 -0
  210. fast_agent/resources/examples/workflows/graded_report.md +89 -0
  211. fast_agent/resources/examples/workflows/human_input.py +28 -0
  212. fast_agent/resources/examples/workflows/maker.py +156 -0
  213. fast_agent/resources/examples/workflows/orchestrator.py +70 -0
  214. fast_agent/resources/examples/workflows/parallel.py +56 -0
  215. fast_agent/resources/examples/workflows/router.py +69 -0
  216. fast_agent/resources/examples/workflows/short_story.md +13 -0
  217. fast_agent/resources/examples/workflows/short_story.txt +19 -0
  218. fast_agent/resources/setup/.gitignore +30 -0
  219. fast_agent/resources/setup/agent.py +28 -0
  220. fast_agent/resources/setup/fastagent.config.yaml +65 -0
  221. fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
  222. fast_agent/resources/setup/pyproject.toml.tmpl +23 -0
  223. fast_agent/skills/__init__.py +9 -0
  224. fast_agent/skills/registry.py +235 -0
  225. fast_agent/tools/elicitation.py +369 -0
  226. fast_agent/tools/shell_runtime.py +402 -0
  227. fast_agent/types/__init__.py +59 -0
  228. fast_agent/types/conversation_summary.py +294 -0
  229. fast_agent/types/llm_stop_reason.py +78 -0
  230. fast_agent/types/message_search.py +249 -0
  231. fast_agent/ui/__init__.py +38 -0
  232. fast_agent/ui/console.py +59 -0
  233. fast_agent/ui/console_display.py +1080 -0
  234. fast_agent/ui/elicitation_form.py +946 -0
  235. fast_agent/ui/elicitation_style.py +59 -0
  236. fast_agent/ui/enhanced_prompt.py +1400 -0
  237. fast_agent/ui/history_display.py +734 -0
  238. fast_agent/ui/interactive_prompt.py +1199 -0
  239. fast_agent/ui/markdown_helpers.py +104 -0
  240. fast_agent/ui/markdown_truncator.py +1004 -0
  241. fast_agent/ui/mcp_display.py +857 -0
  242. fast_agent/ui/mcp_ui_utils.py +235 -0
  243. fast_agent/ui/mermaid_utils.py +169 -0
  244. fast_agent/ui/message_primitives.py +50 -0
  245. fast_agent/ui/notification_tracker.py +205 -0
  246. fast_agent/ui/plain_text_truncator.py +68 -0
  247. fast_agent/ui/progress_display.py +10 -0
  248. fast_agent/ui/rich_progress.py +195 -0
  249. fast_agent/ui/streaming.py +774 -0
  250. fast_agent/ui/streaming_buffer.py +449 -0
  251. fast_agent/ui/tool_display.py +422 -0
  252. fast_agent/ui/usage_display.py +204 -0
  253. fast_agent/utils/__init__.py +5 -0
  254. fast_agent/utils/reasoning_stream_parser.py +77 -0
  255. fast_agent/utils/time.py +22 -0
  256. fast_agent/workflow_telemetry.py +261 -0
  257. fast_agent_mcp-0.4.7.dist-info/METADATA +788 -0
  258. fast_agent_mcp-0.4.7.dist-info/RECORD +261 -0
  259. fast_agent_mcp-0.4.7.dist-info/WHEEL +4 -0
  260. fast_agent_mcp-0.4.7.dist-info/entry_points.txt +7 -0
  261. fast_agent_mcp-0.4.7.dist-info/licenses/LICENSE +201 -0
fast_agent/__init__.py ADDED
@@ -0,0 +1,183 @@
1
+ """fast-agent - An MCP native agent application framework"""
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ # Configuration and settings (safe - pure Pydantic models)
6
+ from fast_agent.config import (
7
+ AnthropicSettings,
8
+ AzureSettings,
9
+ BedrockSettings,
10
+ DeepSeekSettings,
11
+ GenericSettings,
12
+ GoogleSettings,
13
+ GroqSettings,
14
+ HuggingFaceSettings,
15
+ LoggerSettings,
16
+ MCPElicitationSettings,
17
+ MCPRootSettings,
18
+ MCPSamplingSettings,
19
+ MCPServerAuthSettings,
20
+ MCPServerSettings,
21
+ MCPSettings,
22
+ OpenAISettings,
23
+ OpenRouterSettings,
24
+ OpenTelemetrySettings,
25
+ Settings,
26
+ SkillsSettings,
27
+ TensorZeroSettings,
28
+ XAISettings,
29
+ )
30
+
31
+ # Type definitions and enums (safe - no dependencies)
32
+ from fast_agent.types import (
33
+ ConversationSummary,
34
+ LlmStopReason,
35
+ PromptMessageExtended,
36
+ RequestParams,
37
+ ResourceLink,
38
+ audio_link,
39
+ extract_first,
40
+ extract_last,
41
+ find_matches,
42
+ image_link,
43
+ resource_link,
44
+ search_messages,
45
+ text_content,
46
+ video_link,
47
+ )
48
+
49
+
50
+ def __getattr__(name: str):
51
+ """Lazy import heavy modules to avoid circular imports during package initialization."""
52
+ if name == "Core":
53
+ from fast_agent.core import Core
54
+
55
+ return Core
56
+ elif name == "Context":
57
+ from fast_agent.context import Context
58
+
59
+ return Context
60
+ elif name == "ContextDependent":
61
+ from fast_agent.context_dependent import ContextDependent
62
+
63
+ return ContextDependent
64
+ elif name == "ServerRegistry":
65
+ from fast_agent.mcp_server_registry import ServerRegistry
66
+
67
+ return ServerRegistry
68
+ elif name == "ProgressAction":
69
+ from fast_agent.event_progress import ProgressAction
70
+
71
+ return ProgressAction
72
+ elif name == "ProgressEvent":
73
+ from fast_agent.event_progress import ProgressEvent
74
+
75
+ return ProgressEvent
76
+ elif name == "ToolAgentSynchronous":
77
+ from fast_agent.agents.tool_agent import ToolAgent
78
+
79
+ return ToolAgent
80
+ elif name == "LlmAgent":
81
+ from fast_agent.agents.llm_agent import LlmAgent
82
+
83
+ return LlmAgent
84
+ elif name == "LlmDecorator":
85
+ from fast_agent.agents.llm_decorator import LlmDecorator
86
+
87
+ return LlmDecorator
88
+ elif name == "ToolAgent":
89
+ from fast_agent.agents.tool_agent import ToolAgent
90
+
91
+ return ToolAgent
92
+ elif name == "McpAgent":
93
+ # Import directly from submodule to avoid package re-import cycles
94
+ from fast_agent.agents.mcp_agent import McpAgent
95
+
96
+ return McpAgent
97
+ elif name == "FastAgent":
98
+ # Import from the canonical implementation to avoid recursive imports
99
+ from fast_agent.core.fastagent import FastAgent
100
+
101
+ return FastAgent
102
+ elif name == "Prompt":
103
+ # Prompt helper relies on MCP types; load lazily to speed up import time.
104
+ from fast_agent.mcp.prompt import Prompt
105
+
106
+ return Prompt
107
+ elif name == "load_prompt":
108
+ # Prompt loader also depends on MCP; defer import until explicitly requested.
109
+ from fast_agent.mcp.prompts.prompt_load import load_prompt
110
+
111
+ return load_prompt
112
+ else:
113
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
114
+
115
+
116
+ # Help static analyzers/IDEs resolve symbols and signatures without importing at runtime.
117
+ if TYPE_CHECKING: # pragma: no cover - typing aid only
118
+ # Provide a concrete import path for type checkers/IDEs
119
+ from fast_agent.core.fastagent import FastAgent as FastAgent # noqa: F401
120
+ from fast_agent.mcp.prompt import Prompt as Prompt # noqa: F401
121
+ from fast_agent.types import ConversationSummary as ConversationSummary # noqa: F401
122
+ from fast_agent.types import PromptMessageExtended as PromptMessageExtended # noqa: F401
123
+
124
+
125
+ __all__ = [
126
+ # Core fast-agent components (lazy loaded)
127
+ "Core",
128
+ "Context",
129
+ "ContextDependent",
130
+ "ServerRegistry",
131
+ # Configuration and settings (eagerly loaded)
132
+ "Settings",
133
+ "MCPSettings",
134
+ "MCPServerSettings",
135
+ "MCPServerAuthSettings",
136
+ "MCPSamplingSettings",
137
+ "MCPElicitationSettings",
138
+ "MCPRootSettings",
139
+ "AnthropicSettings",
140
+ "OpenAISettings",
141
+ "DeepSeekSettings",
142
+ "GoogleSettings",
143
+ "XAISettings",
144
+ "GenericSettings",
145
+ "OpenRouterSettings",
146
+ "AzureSettings",
147
+ "GroqSettings",
148
+ "OpenTelemetrySettings",
149
+ "TensorZeroSettings",
150
+ "BedrockSettings",
151
+ "HuggingFaceSettings",
152
+ "LoggerSettings",
153
+ "SkillsSettings",
154
+ # Progress and event tracking (lazy loaded)
155
+ "ProgressAction",
156
+ "ProgressEvent",
157
+ # Type definitions and enums (eagerly loaded)
158
+ "LlmStopReason",
159
+ "RequestParams",
160
+ "PromptMessageExtended",
161
+ "ResourceLink",
162
+ "ConversationSummary",
163
+ # Content helpers (eagerly loaded)
164
+ "text_content",
165
+ "resource_link",
166
+ "image_link",
167
+ "video_link",
168
+ "audio_link",
169
+ # Search utilities (eagerly loaded)
170
+ "search_messages",
171
+ "find_matches",
172
+ "extract_first",
173
+ "extract_last",
174
+ # Prompt helpers (eagerly loaded)
175
+ "Prompt",
176
+ "load_prompt",
177
+ # Agents (lazy loaded)
178
+ "LlmAgent",
179
+ "LlmDecorator",
180
+ "ToolAgent",
181
+ "McpAgent",
182
+ "FastAgent",
183
+ ]
@@ -0,0 +1,19 @@
1
+ """Agent Client Protocol (ACP) support for fast-agent."""
2
+
3
+ from fast_agent.acp.acp_aware_mixin import ACPAwareMixin, ACPCommand, ACPModeInfo
4
+ from fast_agent.acp.acp_context import ACPContext, ClientCapabilities, ClientInfo
5
+ from fast_agent.acp.filesystem_runtime import ACPFilesystemRuntime
6
+ from fast_agent.acp.server.agent_acp_server import AgentACPServer
7
+ from fast_agent.acp.terminal_runtime import ACPTerminalRuntime
8
+
9
+ __all__ = [
10
+ "ACPCommand",
11
+ "ACPModeInfo",
12
+ "ACPContext",
13
+ "ACPAwareMixin",
14
+ "ClientCapabilities",
15
+ "ClientInfo",
16
+ "AgentACPServer",
17
+ "ACPFilesystemRuntime",
18
+ "ACPTerminalRuntime",
19
+ ]
@@ -0,0 +1,304 @@
1
+ """
2
+ ACPAwareMixin - Mixin providing convenient ACP access for agents.
3
+
4
+ This mixin extends ContextDependent to provide easy access to ACP features
5
+ when running in ACP mode. Agents inheriting this mixin can:
6
+
7
+ - Check if they're running in ACP mode
8
+ - Access ACP capabilities (terminal, filesystem, etc.)
9
+ - Switch modes programmatically
10
+ - Define slash commands declaratively via acp_commands property
11
+ - Query client capabilities
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+ from typing import TYPE_CHECKING, Awaitable, Callable
18
+
19
+ from fast_agent.context_dependent import ContextDependent
20
+
21
+ if TYPE_CHECKING:
22
+ from fast_agent.acp.acp_context import ACPContext
23
+
24
+
25
+ # Type alias for slash command handlers
26
+ SlashCommandHandlerFunc = Callable[[str], Awaitable[str]]
27
+
28
+
29
+ @dataclass
30
+ class ACPCommand:
31
+ """
32
+ Defines a slash command that an agent can expose via ACP.
33
+
34
+ Agents declare their commands by overriding the `acp_commands` property
35
+ to return a dict mapping command names to ACPCommand instances.
36
+
37
+ Example:
38
+ @property
39
+ def acp_commands(self) -> dict[str, ACPCommand]:
40
+ return {
41
+ "analyze": ACPCommand(
42
+ description="Analyze the current context",
43
+ handler=self._handle_analyze,
44
+ ),
45
+ }
46
+ """
47
+
48
+ description: str
49
+ handler: SlashCommandHandlerFunc
50
+ input_hint: str | None = None
51
+
52
+
53
+ @dataclass
54
+ class ACPModeInfo:
55
+ """
56
+ Optional display metadata for ACP modes.
57
+
58
+ Agents can override `acp_mode_info()` to provide a custom name and/or
59
+ description that will be surfaced to ACP clients.
60
+ """
61
+
62
+ name: str | None = None
63
+ description: str | None = None
64
+
65
+
66
+ class ACPAwareMixin(ContextDependent):
67
+ """
68
+ Mixin providing convenient ACP access for agents.
69
+
70
+ This mixin builds on ContextDependent to provide easy access to ACP features.
71
+ It checks for the presence of an ACPContext in the application Context and
72
+ provides convenient properties and methods for ACP operations.
73
+
74
+ Usage:
75
+ class MyAgent(ACPAwareMixin, McpAgent):
76
+ async def initialize(self):
77
+ await super().initialize()
78
+
79
+ # Check if running in ACP mode
80
+ if self.is_acp_mode:
81
+ # Register a dynamic slash command
82
+ await self.acp_add_command(
83
+ name="analyze",
84
+ description="Run analysis",
85
+ handler=self._handle_analyze
86
+ )
87
+
88
+ async def generate_impl(self, request):
89
+ if self.is_acp_mode:
90
+ # Check client capabilities
91
+ if self.acp.supports_terminal:
92
+ ...
93
+
94
+ # Get current mode
95
+ print(f"Current mode: {self.acp_current_mode}")
96
+
97
+ # Maybe switch modes
98
+ if should_delegate:
99
+ await self.acp_switch_mode("specialist_agent")
100
+
101
+ return await super().generate_impl(request)
102
+
103
+ async def _handle_analyze(self, arguments: str) -> str:
104
+ return f"Analysis result for: {arguments}"
105
+ """
106
+
107
+ @property
108
+ def acp(self) -> "ACPContext | None":
109
+ """
110
+ Get the ACP context if available.
111
+
112
+ Returns:
113
+ ACPContext if running in ACP mode, None otherwise
114
+ """
115
+ try:
116
+ ctx = self.context
117
+ return getattr(ctx, "acp", None)
118
+ except RuntimeError:
119
+ # No context available
120
+ return None
121
+
122
+ @property
123
+ def is_acp_mode(self) -> bool:
124
+ """
125
+ Check if the agent is running in ACP mode.
126
+
127
+ Returns:
128
+ True if ACP context is available, False otherwise
129
+ """
130
+ return self.acp is not None
131
+
132
+ # =========================================================================
133
+ # Mode Management Shortcuts
134
+ # =========================================================================
135
+
136
+ @property
137
+ def acp_current_mode(self) -> str | None:
138
+ """
139
+ Get the current ACP mode (agent ID).
140
+
141
+ Returns:
142
+ Current mode ID, or None if not in ACP mode
143
+ """
144
+ acp = self.acp
145
+ return acp.current_mode if acp else None
146
+
147
+ @property
148
+ def acp_session_id(self) -> str | None:
149
+ """
150
+ Get the ACP session ID.
151
+
152
+ Returns:
153
+ Session ID, or None if not in ACP mode
154
+ """
155
+ acp = self.acp
156
+ return acp.session_id if acp else None
157
+
158
+ async def acp_switch_mode(self, mode_id: str) -> bool:
159
+ """
160
+ Switch to a different mode (agent).
161
+
162
+ This sends a CurrentModeUpdate notification to the ACP client,
163
+ telling it that the agent has autonomously switched modes.
164
+
165
+ Args:
166
+ mode_id: The mode ID to switch to
167
+
168
+ Returns:
169
+ True if switch was successful, False if not in ACP mode
170
+
171
+ Raises:
172
+ ValueError: If the mode_id is not in available modes
173
+ """
174
+ acp = self.acp
175
+ if not acp:
176
+ return False
177
+
178
+ await acp.switch_mode(mode_id)
179
+ return True
180
+
181
+ def acp_available_modes(self) -> list[str]:
182
+ """
183
+ Get list of available mode IDs.
184
+
185
+ Returns:
186
+ List of mode IDs, or empty list if not in ACP mode
187
+ """
188
+ acp = self.acp
189
+ return list(acp.available_modes.keys()) if acp else []
190
+
191
+ # =========================================================================
192
+ # Client Capability Shortcuts
193
+ # =========================================================================
194
+
195
+ @property
196
+ def acp_supports_terminal(self) -> bool:
197
+ """Check if ACP client supports terminal operations."""
198
+ acp = self.acp
199
+ return acp.supports_terminal if acp else False
200
+
201
+ @property
202
+ def acp_supports_fs_read(self) -> bool:
203
+ """Check if ACP client supports file reading."""
204
+ acp = self.acp
205
+ return acp.supports_fs_read if acp else False
206
+
207
+ @property
208
+ def acp_supports_fs_write(self) -> bool:
209
+ """Check if ACP client supports file writing."""
210
+ acp = self.acp
211
+ return acp.supports_fs_write if acp else False
212
+
213
+ @property
214
+ def acp_supports_filesystem(self) -> bool:
215
+ """Check if ACP client supports any filesystem operations."""
216
+ acp = self.acp
217
+ return acp.supports_filesystem if acp else False
218
+
219
+ # =========================================================================
220
+ # Slash Commands (Declarative)
221
+ # =========================================================================
222
+
223
+ @property
224
+ def acp_commands(self) -> dict[str, "ACPCommand"]:
225
+ """
226
+ Declare slash commands this agent exposes via ACP.
227
+
228
+ Override this property to provide agent-specific commands.
229
+ Commands are queried dynamically when the agent is the active mode.
230
+
231
+ Returns:
232
+ Dict mapping command names (without slash) to ACPCommand instances.
233
+
234
+ Example:
235
+ @property
236
+ def acp_commands(self) -> dict[str, ACPCommand]:
237
+ return {
238
+ "analyze": ACPCommand(
239
+ description="Analyze the current context",
240
+ handler=self._handle_analyze,
241
+ ),
242
+ "report": ACPCommand(
243
+ description="Generate a report",
244
+ handler=self._handle_report,
245
+ input_hint="<format>",
246
+ ),
247
+ }
248
+ """
249
+ return {}
250
+
251
+ def acp_mode_info(self) -> ACPModeInfo | None:
252
+ """
253
+ Optional ACP mode metadata (name/description) for display in clients.
254
+ Override to customize the label and description for this agent's mode.
255
+ """
256
+ return None
257
+
258
+ # =========================================================================
259
+ # Runtime Access Shortcuts
260
+ # =========================================================================
261
+
262
+ @property
263
+ def acp_terminal_runtime(self):
264
+ """
265
+ Get the ACP terminal runtime (if available).
266
+
267
+ Returns:
268
+ ACPTerminalRuntime or None
269
+ """
270
+ acp = self.acp
271
+ return acp.terminal_runtime if acp else None
272
+
273
+ @property
274
+ def acp_filesystem_runtime(self):
275
+ """
276
+ Get the ACP filesystem runtime (if available).
277
+
278
+ Returns:
279
+ ACPFilesystemRuntime or None
280
+ """
281
+ acp = self.acp
282
+ return acp.filesystem_runtime if acp else None
283
+
284
+ @property
285
+ def acp_permission_handler(self):
286
+ """
287
+ Get the ACP permission handler (if available).
288
+
289
+ Returns:
290
+ ACPToolPermissionAdapter or None
291
+ """
292
+ acp = self.acp
293
+ return acp.permission_handler if acp else None
294
+
295
+ @property
296
+ def acp_progress_manager(self):
297
+ """
298
+ Get the ACP progress manager (if available).
299
+
300
+ Returns:
301
+ ACPToolProgressManager or None
302
+ """
303
+ acp = self.acp
304
+ return acp.progress_manager if acp else None