code-puppy 0.0.154__tar.gz → 0.0.155__tar.gz
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.
- {code_puppy-0.0.154 → code_puppy-0.0.155}/PKG-INFO +2 -2
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agent.py +4 -3
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/agent_creator_agent.py +9 -2
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/runtime_manager.py +12 -4
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/install_command.py +50 -1
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/wizard_utils.py +88 -17
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/config.py +8 -2
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/main.py +17 -4
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/__init__.py +2 -2
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/config_wizard.py +1 -1
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/spinner/console_spinner.py +1 -1
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/model_factory.py +13 -12
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/models.json +26 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/round_robin_model.py +35 -18
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/summarization_agent.py +1 -3
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/agent_tools.py +41 -138
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/file_operations.py +116 -96
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/app.py +1 -1
- {code_puppy-0.0.154 → code_puppy-0.0.155}/pyproject.toml +2 -2
- code_puppy-0.0.154/code_puppy/token_utils.py +0 -67
- code_puppy-0.0.154/code_puppy/tools/token_check.py +0 -32
- code_puppy-0.0.154/code_puppy/tui/tests/__init__.py +0 -1
- code_puppy-0.0.154/code_puppy/tui/tests/test_agent_command.py +0 -79
- code_puppy-0.0.154/code_puppy/tui/tests/test_chat_message.py +0 -28
- code_puppy-0.0.154/code_puppy/tui/tests/test_chat_view.py +0 -88
- code_puppy-0.0.154/code_puppy/tui/tests/test_command_history.py +0 -89
- code_puppy-0.0.154/code_puppy/tui/tests/test_copy_button.py +0 -191
- code_puppy-0.0.154/code_puppy/tui/tests/test_custom_widgets.py +0 -27
- code_puppy-0.0.154/code_puppy/tui/tests/test_disclaimer.py +0 -27
- code_puppy-0.0.154/code_puppy/tui/tests/test_enums.py +0 -15
- code_puppy-0.0.154/code_puppy/tui/tests/test_file_browser.py +0 -60
- code_puppy-0.0.154/code_puppy/tui/tests/test_help.py +0 -38
- code_puppy-0.0.154/code_puppy/tui/tests/test_history_file_reader.py +0 -107
- code_puppy-0.0.154/code_puppy/tui/tests/test_input_area.py +0 -33
- code_puppy-0.0.154/code_puppy/tui/tests/test_settings.py +0 -44
- code_puppy-0.0.154/code_puppy/tui/tests/test_sidebar.py +0 -33
- code_puppy-0.0.154/code_puppy/tui/tests/test_sidebar_history.py +0 -153
- code_puppy-0.0.154/code_puppy/tui/tests/test_sidebar_history_navigation.py +0 -132
- code_puppy-0.0.154/code_puppy/tui/tests/test_status_bar.py +0 -54
- code_puppy-0.0.154/code_puppy/tui/tests/test_timestamped_history.py +0 -52
- code_puppy-0.0.154/code_puppy/tui/tests/test_tools.py +0 -82
- {code_puppy-0.0.154 → code_puppy-0.0.155}/.gitignore +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/LICENSE +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/README.md +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/agent_orchestrator.json +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/meta_command_handler.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/async_lifecycle.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/blocking_startup.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/captured_stdio_server.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/circuit_breaker.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/dashboard.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/error_isolation.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/examples/retry_example.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/health_monitor.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/managed_server.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/manager.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/registry.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/retry_manager.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/server_registry_catalog.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/status_tracker.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/mcp/system_tools.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/message_history_processor.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/messaging/spinner/textual_spinner.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/state_management.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/chat_view.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/command_history_modal.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/copy_button.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/custom_widgets.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/human_input_modal.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/input_area.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/sidebar.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/components/status_bar.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/messages.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/models/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/models/chat_message.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/models/command_history.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/models/enums.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/screens/__init__.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/screens/help.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/screens/mcp_install_wizard.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/screens/settings.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/tui/screens/tools.py +0 -0
- {code_puppy-0.0.154 → code_puppy-0.0.155}/code_puppy/version_checker.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.155
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
|
|
6
6
|
Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
|
|
@@ -13,7 +13,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Topic :: Software Development :: Code Generators
|
|
16
|
-
Requires-Python: >=3.
|
|
16
|
+
Requires-Python: >=3.11
|
|
17
17
|
Requires-Dist: bs4>=0.0.2
|
|
18
18
|
Requires-Dist: fastapi>=0.110.0
|
|
19
19
|
Requires-Dist: httpx-limiter>=0.3.0
|
|
@@ -24,17 +24,17 @@ from code_puppy.tools.common import console
|
|
|
24
24
|
|
|
25
25
|
def load_puppy_rules():
|
|
26
26
|
global PUPPY_RULES
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
# Check for all 4 combinations of the rules file
|
|
29
29
|
possible_paths = ["AGENTS.md", "AGENT.md", "agents.md", "agent.md"]
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
for path_str in possible_paths:
|
|
32
32
|
puppy_rules_path = Path(path_str)
|
|
33
33
|
if puppy_rules_path.exists():
|
|
34
34
|
with open(puppy_rules_path, "r") as f:
|
|
35
35
|
puppy_rules = f.read()
|
|
36
36
|
return puppy_rules
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
# If none of the files exist, return None
|
|
39
39
|
return None
|
|
40
40
|
|
|
@@ -206,4 +206,5 @@ def get_custom_usage_limits():
|
|
|
206
206
|
Default pydantic-ai limit is 50, this increases it to the configured value (default 100).
|
|
207
207
|
"""
|
|
208
208
|
from code_puppy.config import get_message_limit
|
|
209
|
+
|
|
209
210
|
return UsageLimits(request_limit=get_message_limit())
|
|
@@ -390,7 +390,14 @@ Your goal is to take users from idea to working agent in one smooth conversation
|
|
|
390
390
|
|
|
391
391
|
def get_available_tools(self) -> List[str]:
|
|
392
392
|
"""Get all tools needed for agent creation."""
|
|
393
|
-
return [
|
|
393
|
+
return [
|
|
394
|
+
"list_files",
|
|
395
|
+
"read_file",
|
|
396
|
+
"edit_file",
|
|
397
|
+
"agent_share_your_reasoning",
|
|
398
|
+
"list_agents",
|
|
399
|
+
"invoke_agent",
|
|
400
|
+
]
|
|
394
401
|
|
|
395
402
|
def validate_agent_json(self, agent_config: Dict) -> List[str]:
|
|
396
403
|
"""Validate a JSON agent configuration.
|
|
@@ -485,4 +492,4 @@ Your goal is to take users from idea to working agent in one smooth conversation
|
|
|
485
492
|
|
|
486
493
|
def get_user_prompt(self) -> Optional[str]:
|
|
487
494
|
"""Get the initial user prompt."""
|
|
488
|
-
return "Hi! I'm the Agent Creator 🏗️ Let's build an awesome agent together!"
|
|
495
|
+
return "Hi! I'm the Agent Creator 🏗️ Let's build an awesome agent together!"
|
|
@@ -27,7 +27,7 @@ from pydantic_ai import Agent
|
|
|
27
27
|
from pydantic_ai.exceptions import UsageLimitExceeded
|
|
28
28
|
from pydantic_ai.usage import UsageLimits
|
|
29
29
|
|
|
30
|
-
from code_puppy.messaging.message_queue import emit_info
|
|
30
|
+
from code_puppy.messaging.message_queue import emit_info
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class RuntimeAgentManager:
|
|
@@ -113,7 +113,10 @@ class RuntimeAgentManager:
|
|
|
113
113
|
return await agent.run(prompt, usage_limits=usage_limits, **kwargs)
|
|
114
114
|
except* UsageLimitExceeded as ule:
|
|
115
115
|
emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
|
|
116
|
-
emit_info(
|
|
116
|
+
emit_info(
|
|
117
|
+
"The agent has reached its usage limit. You can ask it to continue by saying 'please continue' or similar.",
|
|
118
|
+
group_id=group_id,
|
|
119
|
+
)
|
|
117
120
|
except* mcp.shared.exceptions.McpError as mcp_error:
|
|
118
121
|
emit_info(f"MCP server error: {str(mcp_error)}", group_id=group_id)
|
|
119
122
|
emit_info(f"{str(mcp_error)}", group_id=group_id)
|
|
@@ -132,7 +135,9 @@ class RuntimeAgentManager:
|
|
|
132
135
|
if isinstance(exc, ExceptionGroup):
|
|
133
136
|
for sub_exc in exc.exceptions:
|
|
134
137
|
collect_non_cancelled_exceptions(sub_exc)
|
|
135
|
-
elif not isinstance(
|
|
138
|
+
elif not isinstance(
|
|
139
|
+
exc, (asyncio.CancelledError, UsageLimitExceeded)
|
|
140
|
+
):
|
|
136
141
|
remaining_exceptions.append(exc)
|
|
137
142
|
emit_info(f"Unexpected error: {str(exc)}", group_id=group_id)
|
|
138
143
|
emit_info(f"{str(exc.args)}", group_id=group_id)
|
|
@@ -226,7 +231,10 @@ class RuntimeAgentManager:
|
|
|
226
231
|
except UsageLimitExceeded as ule:
|
|
227
232
|
group_id = str(uuid.uuid4())
|
|
228
233
|
emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
|
|
229
|
-
emit_info(
|
|
234
|
+
emit_info(
|
|
235
|
+
"The agent has reached its usage limit. You can ask it to continue by saying 'please continue' or similar.",
|
|
236
|
+
group_id=group_id,
|
|
237
|
+
)
|
|
230
238
|
# Return None or some default value to indicate the limit was reached
|
|
231
239
|
return None
|
|
232
240
|
|
|
@@ -158,10 +158,59 @@ class InstallCommand(MCPCommandBase):
|
|
|
158
158
|
emit_info("Installation cancelled", message_group=group_id)
|
|
159
159
|
return False
|
|
160
160
|
|
|
161
|
-
#
|
|
161
|
+
# Collect environment variables and command line arguments
|
|
162
162
|
env_vars = {}
|
|
163
163
|
cmd_args = {}
|
|
164
164
|
|
|
165
|
+
# Get environment variables
|
|
166
|
+
required_env_vars = selected_server.get_environment_vars()
|
|
167
|
+
if required_env_vars:
|
|
168
|
+
emit_info(
|
|
169
|
+
"\n[yellow]Required Environment Variables:[/yellow]",
|
|
170
|
+
message_group=group_id,
|
|
171
|
+
)
|
|
172
|
+
for var in required_env_vars:
|
|
173
|
+
# Check if already set in environment
|
|
174
|
+
import os
|
|
175
|
+
|
|
176
|
+
current_value = os.environ.get(var, "")
|
|
177
|
+
if current_value:
|
|
178
|
+
emit_info(
|
|
179
|
+
f" {var}: [green]Already set[/green]",
|
|
180
|
+
message_group=group_id,
|
|
181
|
+
)
|
|
182
|
+
env_vars[var] = current_value
|
|
183
|
+
else:
|
|
184
|
+
value = emit_prompt(f" Enter value for {var}: ").strip()
|
|
185
|
+
if value:
|
|
186
|
+
env_vars[var] = value
|
|
187
|
+
|
|
188
|
+
# Get command line arguments
|
|
189
|
+
required_cmd_args = selected_server.get_command_line_args()
|
|
190
|
+
if required_cmd_args:
|
|
191
|
+
emit_info(
|
|
192
|
+
"\n[yellow]Command Line Arguments:[/yellow]", message_group=group_id
|
|
193
|
+
)
|
|
194
|
+
for arg_config in required_cmd_args:
|
|
195
|
+
name = arg_config.get("name", "")
|
|
196
|
+
prompt = arg_config.get("prompt", name)
|
|
197
|
+
default = arg_config.get("default", "")
|
|
198
|
+
required = arg_config.get("required", True)
|
|
199
|
+
|
|
200
|
+
# If required or has default, prompt user
|
|
201
|
+
if required or default:
|
|
202
|
+
arg_prompt = f" {prompt}"
|
|
203
|
+
if default:
|
|
204
|
+
arg_prompt += f" [{default}]"
|
|
205
|
+
if not required:
|
|
206
|
+
arg_prompt += " (optional)"
|
|
207
|
+
|
|
208
|
+
value = emit_prompt(f"{arg_prompt}: ").strip()
|
|
209
|
+
if value:
|
|
210
|
+
cmd_args[name] = value
|
|
211
|
+
elif default:
|
|
212
|
+
cmd_args[name] = default
|
|
213
|
+
|
|
165
214
|
# Install the server
|
|
166
215
|
return install_server_from_catalog(
|
|
167
216
|
self.manager, selected_server, server_name, env_vars, cmd_args, group_id
|
|
@@ -43,9 +43,61 @@ def run_interactive_install_wizard(manager, group_id: str) -> bool:
|
|
|
43
43
|
if not server_name:
|
|
44
44
|
return False
|
|
45
45
|
|
|
46
|
+
# Collect environment variables and command line arguments
|
|
47
|
+
env_vars = {}
|
|
48
|
+
cmd_args = {}
|
|
49
|
+
|
|
50
|
+
# Get environment variables
|
|
51
|
+
required_env_vars = selected_server.get_environment_vars()
|
|
52
|
+
if required_env_vars:
|
|
53
|
+
emit_info(
|
|
54
|
+
"\n[yellow]Required Environment Variables:[/yellow]",
|
|
55
|
+
message_group=group_id,
|
|
56
|
+
)
|
|
57
|
+
for var in required_env_vars:
|
|
58
|
+
# Check if already set in environment
|
|
59
|
+
import os
|
|
60
|
+
|
|
61
|
+
current_value = os.environ.get(var, "")
|
|
62
|
+
if current_value:
|
|
63
|
+
emit_info(
|
|
64
|
+
f" {var}: [green]Already set[/green]", message_group=group_id
|
|
65
|
+
)
|
|
66
|
+
env_vars[var] = current_value
|
|
67
|
+
else:
|
|
68
|
+
value = emit_prompt(f" Enter value for {var}: ").strip()
|
|
69
|
+
if value:
|
|
70
|
+
env_vars[var] = value
|
|
71
|
+
|
|
72
|
+
# Get command line arguments
|
|
73
|
+
required_cmd_args = selected_server.get_command_line_args()
|
|
74
|
+
if required_cmd_args:
|
|
75
|
+
emit_info(
|
|
76
|
+
"\n[yellow]Command Line Arguments:[/yellow]", message_group=group_id
|
|
77
|
+
)
|
|
78
|
+
for arg_config in required_cmd_args:
|
|
79
|
+
name = arg_config.get("name", "")
|
|
80
|
+
prompt = arg_config.get("prompt", name)
|
|
81
|
+
default = arg_config.get("default", "")
|
|
82
|
+
required = arg_config.get("required", True)
|
|
83
|
+
|
|
84
|
+
# If required or has default, prompt user
|
|
85
|
+
if required or default:
|
|
86
|
+
arg_prompt = f" {prompt}"
|
|
87
|
+
if default:
|
|
88
|
+
arg_prompt += f" [{default}]"
|
|
89
|
+
if not required:
|
|
90
|
+
arg_prompt += " (optional)"
|
|
91
|
+
|
|
92
|
+
value = emit_prompt(f"{arg_prompt}: ").strip()
|
|
93
|
+
if value:
|
|
94
|
+
cmd_args[name] = value
|
|
95
|
+
elif default:
|
|
96
|
+
cmd_args[name] = default
|
|
97
|
+
|
|
46
98
|
# Configure the server
|
|
47
99
|
return interactive_configure_server(
|
|
48
|
-
manager, selected_server, server_name, group_id
|
|
100
|
+
manager, selected_server, server_name, group_id, env_vars, cmd_args
|
|
49
101
|
)
|
|
50
102
|
|
|
51
103
|
except ImportError:
|
|
@@ -131,7 +183,12 @@ def interactive_get_server_name(selected_server, group_id: str) -> Optional[str]
|
|
|
131
183
|
|
|
132
184
|
|
|
133
185
|
def interactive_configure_server(
|
|
134
|
-
manager,
|
|
186
|
+
manager,
|
|
187
|
+
selected_server,
|
|
188
|
+
server_name: str,
|
|
189
|
+
group_id: str,
|
|
190
|
+
env_vars: Dict[str, Any],
|
|
191
|
+
cmd_args: Dict[str, Any],
|
|
135
192
|
) -> bool:
|
|
136
193
|
"""
|
|
137
194
|
Configure and install the selected server.
|
|
@@ -151,15 +208,20 @@ def interactive_configure_server(
|
|
|
151
208
|
emit_info("Installation cancelled", message_group=group_id)
|
|
152
209
|
return False
|
|
153
210
|
|
|
154
|
-
# For now, use defaults - a full implementation would collect env vars, etc.
|
|
155
|
-
# requirements = selected_server.get_requirements() # TODO: Use for validation
|
|
156
|
-
env_vars = {}
|
|
157
|
-
cmd_args = {}
|
|
158
|
-
|
|
159
211
|
# Show confirmation
|
|
160
212
|
emit_info(f"Installing: {selected_server.display_name}", message_group=group_id)
|
|
161
213
|
emit_info(f"Name: {server_name}", message_group=group_id)
|
|
162
214
|
|
|
215
|
+
if env_vars:
|
|
216
|
+
emit_info("Environment Variables:", message_group=group_id)
|
|
217
|
+
for var, value in env_vars.items():
|
|
218
|
+
emit_info(f" {var}: [hidden]{value}[/hidden]", message_group=group_id)
|
|
219
|
+
|
|
220
|
+
if cmd_args:
|
|
221
|
+
emit_info("Command Line Arguments:", message_group=group_id)
|
|
222
|
+
for arg, value in cmd_args.items():
|
|
223
|
+
emit_info(f" {arg}: {value}", message_group=group_id)
|
|
224
|
+
|
|
163
225
|
confirm = emit_prompt("Proceed with installation? [Y/n]: ")
|
|
164
226
|
if confirm.lower().startswith("n"):
|
|
165
227
|
emit_info("Installation cancelled", message_group=group_id)
|
|
@@ -196,18 +258,25 @@ def install_server_from_catalog(
|
|
|
196
258
|
from code_puppy.config import MCP_SERVERS_FILE
|
|
197
259
|
from code_puppy.mcp.managed_server import ServerConfig
|
|
198
260
|
|
|
199
|
-
#
|
|
200
|
-
|
|
261
|
+
# Set environment variables in the current environment
|
|
262
|
+
for var, value in env_vars.items():
|
|
263
|
+
os.environ[var] = value
|
|
201
264
|
|
|
202
|
-
#
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
265
|
+
# Get server config with command line argument overrides
|
|
266
|
+
config_dict = selected_server.to_server_config(server_name, **cmd_args)
|
|
267
|
+
|
|
268
|
+
# Update the config with actual environment variable values
|
|
269
|
+
if "env" in config_dict:
|
|
270
|
+
for env_key, env_value in config_dict["env"].items():
|
|
271
|
+
# If it's a placeholder like $GITHUB_TOKEN, replace with actual value
|
|
272
|
+
if env_value.startswith("$"):
|
|
273
|
+
var_name = env_value[1:] # Remove the $
|
|
274
|
+
if var_name in env_vars:
|
|
275
|
+
config_dict["env"][env_key] = env_vars[var_name]
|
|
207
276
|
|
|
208
277
|
# Create ServerConfig
|
|
209
278
|
server_config = ServerConfig(
|
|
210
|
-
id=
|
|
279
|
+
id=server_name,
|
|
211
280
|
name=server_name,
|
|
212
281
|
type=selected_server.type,
|
|
213
282
|
enabled=True,
|
|
@@ -234,8 +303,10 @@ def install_server_from_catalog(
|
|
|
234
303
|
data = {"mcp_servers": servers}
|
|
235
304
|
|
|
236
305
|
# Add new server
|
|
237
|
-
|
|
238
|
-
|
|
306
|
+
# Copy the config dict and add type before saving
|
|
307
|
+
save_config = config_dict.copy()
|
|
308
|
+
save_config["type"] = selected_server.type
|
|
309
|
+
servers[server_name] = save_config
|
|
239
310
|
|
|
240
311
|
# Save back
|
|
241
312
|
os.makedirs(os.path.dirname(MCP_SERVERS_FILE), exist_ok=True)
|
|
@@ -106,7 +106,13 @@ def get_config_keys():
|
|
|
106
106
|
Returns the list of all config keys currently in puppy.cfg,
|
|
107
107
|
plus certain preset expected keys (e.g. "yolo_mode", "model", "compaction_strategy", "message_limit", "allow_recursion").
|
|
108
108
|
"""
|
|
109
|
-
default_keys = [
|
|
109
|
+
default_keys = [
|
|
110
|
+
"yolo_mode",
|
|
111
|
+
"model",
|
|
112
|
+
"compaction_strategy",
|
|
113
|
+
"message_limit",
|
|
114
|
+
"allow_recursion",
|
|
115
|
+
]
|
|
110
116
|
config = configparser.ConfigParser()
|
|
111
117
|
config.read(CONFIG_FILE)
|
|
112
118
|
keys = set(config[DEFAULT_SECTION].keys()) if DEFAULT_SECTION in config else set()
|
|
@@ -173,7 +179,7 @@ def _default_model_from_models_json():
|
|
|
173
179
|
first_key = next(iter(models_config)) # Raises StopIteration if empty
|
|
174
180
|
_default_model_cache = first_key
|
|
175
181
|
return first_key
|
|
176
|
-
except Exception
|
|
182
|
+
except Exception:
|
|
177
183
|
# Any problem (network, file missing, empty dict, etc.) => fall back
|
|
178
184
|
_default_model_cache = "gpt-5"
|
|
179
185
|
return "gpt-5"
|
|
@@ -290,7 +290,9 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
290
290
|
if awaiting_input:
|
|
291
291
|
# No spinner - use agent_manager's run_with_mcp method
|
|
292
292
|
response = await agent_manager.run_with_mcp(
|
|
293
|
-
initial_command,
|
|
293
|
+
initial_command,
|
|
294
|
+
message_history=get_message_history(),
|
|
295
|
+
usage_limits=get_custom_usage_limits(),
|
|
294
296
|
)
|
|
295
297
|
else:
|
|
296
298
|
# Use our custom spinner for better compatibility with user input
|
|
@@ -299,7 +301,11 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
299
301
|
with ConsoleSpinner(console=display_console):
|
|
300
302
|
# Use agent_manager's run_with_mcp method
|
|
301
303
|
response = await agent_manager.run_with_mcp(
|
|
302
|
-
initial_command,
|
|
304
|
+
initial_command,
|
|
305
|
+
message_history=prune_interrupted_tool_calls(
|
|
306
|
+
get_message_history()
|
|
307
|
+
),
|
|
308
|
+
usage_limits=get_custom_usage_limits(),
|
|
303
309
|
)
|
|
304
310
|
set_message_history(
|
|
305
311
|
prune_interrupted_tool_calls(get_message_history())
|
|
@@ -426,7 +432,13 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
426
432
|
|
|
427
433
|
runtime_manager = get_runtime_agent_manager()
|
|
428
434
|
with ConsoleSpinner(console=message_renderer.console):
|
|
429
|
-
result = await runtime_manager.run_with_mcp(
|
|
435
|
+
result = await runtime_manager.run_with_mcp(
|
|
436
|
+
task,
|
|
437
|
+
get_custom_usage_limits(),
|
|
438
|
+
message_history=prune_interrupted_tool_calls(
|
|
439
|
+
get_message_history()
|
|
440
|
+
),
|
|
441
|
+
)
|
|
430
442
|
# Check if the task was cancelled (but don't show message if we just killed processes)
|
|
431
443
|
if result is None:
|
|
432
444
|
continue
|
|
@@ -495,7 +507,8 @@ async def execute_single_prompt(prompt: str, message_renderer) -> None:
|
|
|
495
507
|
|
|
496
508
|
with ConsoleSpinner(console=message_renderer.console):
|
|
497
509
|
response = await agent_manager.run_with_mcp(
|
|
498
|
-
prompt,
|
|
510
|
+
prompt,
|
|
511
|
+
usage_limits=get_custom_usage_limits(),
|
|
499
512
|
)
|
|
500
513
|
|
|
501
514
|
agent_response = response.output
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""MCP (Model Context Protocol) management system for Code Puppy.
|
|
2
2
|
|
|
3
|
-
Note: Be careful not to create circular imports with config_wizard.py.
|
|
4
|
-
config_wizard.py imports ServerConfig and get_mcp_manager directly from
|
|
3
|
+
Note: Be careful not to create circular imports with config_wizard.py.
|
|
4
|
+
config_wizard.py imports ServerConfig and get_mcp_manager directly from
|
|
5
5
|
.manager to avoid circular dependencies with this package __init__.py
|
|
6
6
|
"""
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
MCP Configuration Wizard - Interactive setup for MCP servers.
|
|
3
3
|
|
|
4
|
-
Note: This module imports ServerConfig and get_mcp_manager directly from
|
|
4
|
+
Note: This module imports ServerConfig and get_mcp_manager directly from
|
|
5
5
|
.code_puppy.mcp.manager to avoid circular imports with the package __init__.py
|
|
6
6
|
"""
|
|
7
7
|
|
|
@@ -6,9 +6,8 @@ from typing import Any, Dict
|
|
|
6
6
|
|
|
7
7
|
import httpx
|
|
8
8
|
from anthropic import AsyncAnthropic
|
|
9
|
-
from openai import AsyncAzureOpenAI
|
|
9
|
+
from openai import AsyncAzureOpenAI
|
|
10
10
|
from pydantic_ai.models.anthropic import AnthropicModel
|
|
11
|
-
from pydantic_ai.models.fallback import infer_model
|
|
12
11
|
from pydantic_ai.models.gemini import GeminiModel
|
|
13
12
|
from pydantic_ai.models.openai import OpenAIChatModel
|
|
14
13
|
from pydantic_ai.providers.anthropic import AnthropicProvider
|
|
@@ -87,13 +86,13 @@ class ModelFactory:
|
|
|
87
86
|
else:
|
|
88
87
|
from code_puppy.config import MODELS_FILE
|
|
89
88
|
|
|
90
|
-
|
|
91
|
-
with open(pathlib.Path(
|
|
92
|
-
|
|
93
|
-
target.write(src.read())
|
|
89
|
+
with open(pathlib.Path(__file__).parent / "models.json", "r") as src:
|
|
90
|
+
with open(pathlib.Path(MODELS_FILE), "w") as target:
|
|
91
|
+
target.write(src.read())
|
|
94
92
|
|
|
95
93
|
with open(MODELS_FILE, "r") as f:
|
|
96
94
|
config = json.load(f)
|
|
95
|
+
|
|
97
96
|
if pathlib.Path(EXTRA_MODELS_FILE).exists():
|
|
98
97
|
with open(EXTRA_MODELS_FILE, "r") as f:
|
|
99
98
|
extra_config = json.load(f)
|
|
@@ -248,25 +247,27 @@ class ModelFactory:
|
|
|
248
247
|
model = OpenAIChatModel(model_name=model_config["name"], provider=provider)
|
|
249
248
|
setattr(model, "provider", provider)
|
|
250
249
|
return model
|
|
251
|
-
|
|
250
|
+
|
|
252
251
|
elif model_type == "round_robin":
|
|
253
252
|
# Get the list of model names to use in the round-robin
|
|
254
253
|
model_names = model_config.get("models")
|
|
255
254
|
if not model_names or not isinstance(model_names, list):
|
|
256
|
-
raise ValueError(
|
|
257
|
-
|
|
255
|
+
raise ValueError(
|
|
256
|
+
f"Round-robin model '{model_name}' requires a 'models' list in its configuration."
|
|
257
|
+
)
|
|
258
|
+
|
|
258
259
|
# Get the rotate_every parameter (default: 1)
|
|
259
260
|
rotate_every = model_config.get("rotate_every", 1)
|
|
260
|
-
|
|
261
|
+
|
|
261
262
|
# Resolve each model name to an actual model instance
|
|
262
263
|
models = []
|
|
263
264
|
for name in model_names:
|
|
264
265
|
# Recursively get each model using the factory
|
|
265
266
|
model = ModelFactory.get_model(name, config)
|
|
266
267
|
models.append(model)
|
|
267
|
-
|
|
268
|
+
|
|
268
269
|
# Create and return the round-robin model
|
|
269
270
|
return RoundRobinModel(*models, rotate_every=rotate_every)
|
|
270
|
-
|
|
271
|
+
|
|
271
272
|
else:
|
|
272
273
|
raise ValueError(f"Unsupported model type: {model_type}")
|
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
{
|
|
2
|
+
"openrouter-sonoma-dusk-alpha": {
|
|
3
|
+
"type": "custom_openai",
|
|
4
|
+
"name": "openrouter/sonoma-dusk-alpha",
|
|
5
|
+
"custom_endpoint": {
|
|
6
|
+
"url": "https://openrouter.ai/api/v1",
|
|
7
|
+
"api_key": "$OPENROUTER_API_KEY",
|
|
8
|
+
"headers": {
|
|
9
|
+
"HTTP-Referer": "https://github.com/mpfaffenberger/code_puppy",
|
|
10
|
+
"X-Title": "Code Puppy"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"context_length": 2000000
|
|
14
|
+
},
|
|
15
|
+
"openrouter-sonoma-sky-alpha": {
|
|
16
|
+
"type": "custom_openai",
|
|
17
|
+
"name": "openrouter/sonoma-sky-alpha",
|
|
18
|
+
"custom_endpoint": {
|
|
19
|
+
"url": "https://openrouter.ai/api/v1",
|
|
20
|
+
"api_key": "$OPENROUTER_API_KEY",
|
|
21
|
+
"headers": {
|
|
22
|
+
"HTTP-Referer": "https://github.com/mpfaffenberger/code_puppy",
|
|
23
|
+
"X-Title": "Code Puppy"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"context_length": 2000000
|
|
27
|
+
},
|
|
2
28
|
"gpt-5": {
|
|
3
29
|
"type": "openai",
|
|
4
30
|
"name": "gpt-5",
|
|
@@ -1,10 +1,18 @@
|
|
|
1
|
-
|
|
2
1
|
from contextlib import asynccontextmanager, suppress
|
|
3
2
|
from dataclasses import dataclass, field
|
|
4
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, AsyncIterator, List
|
|
5
4
|
|
|
6
|
-
from pydantic_ai.models import
|
|
7
|
-
|
|
5
|
+
from pydantic_ai.models import (
|
|
6
|
+
Model,
|
|
7
|
+
ModelMessage,
|
|
8
|
+
ModelSettings,
|
|
9
|
+
ModelRequestParameters,
|
|
10
|
+
ModelResponse,
|
|
11
|
+
StreamedResponse,
|
|
12
|
+
)
|
|
13
|
+
from pydantic_ai.models.fallback import (
|
|
14
|
+
merge_model_settings,
|
|
15
|
+
)
|
|
8
16
|
from pydantic_ai.result import RunContext
|
|
9
17
|
|
|
10
18
|
try:
|
|
@@ -15,18 +23,21 @@ except ImportError:
|
|
|
15
23
|
class DummySpan:
|
|
16
24
|
def is_recording(self):
|
|
17
25
|
return False
|
|
26
|
+
|
|
18
27
|
def set_attributes(self, attributes):
|
|
19
28
|
pass
|
|
29
|
+
|
|
20
30
|
return DummySpan()
|
|
21
31
|
|
|
32
|
+
|
|
22
33
|
@dataclass(init=False)
|
|
23
34
|
class RoundRobinModel(Model):
|
|
24
35
|
"""A model that cycles through multiple models in a round-robin fashion.
|
|
25
|
-
|
|
36
|
+
|
|
26
37
|
This model distributes requests across multiple candidate models to help
|
|
27
38
|
overcome rate limits or distribute load.
|
|
28
39
|
"""
|
|
29
|
-
|
|
40
|
+
|
|
30
41
|
models: List[Model]
|
|
31
42
|
_current_index: int = field(default=0, repr=False)
|
|
32
43
|
_model_name: str = field(repr=False)
|
|
@@ -37,10 +48,10 @@ class RoundRobinModel(Model):
|
|
|
37
48
|
self,
|
|
38
49
|
*models: Model,
|
|
39
50
|
rotate_every: int = 1,
|
|
40
|
-
settings: ModelSettings | None = None
|
|
51
|
+
settings: ModelSettings | None = None,
|
|
41
52
|
):
|
|
42
53
|
"""Initialize a round-robin model instance.
|
|
43
|
-
|
|
54
|
+
|
|
44
55
|
Args:
|
|
45
56
|
models: The model instances to cycle through.
|
|
46
57
|
rotate_every: Number of requests before rotating to the next model (default: 1).
|
|
@@ -59,9 +70,9 @@ class RoundRobinModel(Model):
|
|
|
59
70
|
@property
|
|
60
71
|
def model_name(self) -> str:
|
|
61
72
|
"""The model name showing this is a round-robin model with its candidates."""
|
|
62
|
-
base_name = f
|
|
73
|
+
base_name = f"round_robin:{','.join(model.model_name for model in self.models)}"
|
|
63
74
|
if self._rotate_every != 1:
|
|
64
|
-
return f
|
|
75
|
+
return f"{base_name}:rotate_every={self._rotate_every}"
|
|
65
76
|
return base_name
|
|
66
77
|
|
|
67
78
|
@property
|
|
@@ -93,10 +104,14 @@ class RoundRobinModel(Model):
|
|
|
93
104
|
current_model = self._get_next_model()
|
|
94
105
|
# Use the current model's settings as base, then merge with provided settings
|
|
95
106
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
96
|
-
customized_model_request_parameters =
|
|
97
|
-
|
|
107
|
+
customized_model_request_parameters = (
|
|
108
|
+
current_model.customize_request_parameters(model_request_parameters)
|
|
109
|
+
)
|
|
110
|
+
|
|
98
111
|
try:
|
|
99
|
-
response = await current_model.request(
|
|
112
|
+
response = await current_model.request(
|
|
113
|
+
messages, merged_settings, customized_model_request_parameters
|
|
114
|
+
)
|
|
100
115
|
self._set_span_attributes(current_model)
|
|
101
116
|
return response
|
|
102
117
|
except Exception as exc:
|
|
@@ -116,8 +131,10 @@ class RoundRobinModel(Model):
|
|
|
116
131
|
current_model = self._get_next_model()
|
|
117
132
|
# Use the current model's settings as base, then merge with provided settings
|
|
118
133
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
119
|
-
customized_model_request_parameters =
|
|
120
|
-
|
|
134
|
+
customized_model_request_parameters = (
|
|
135
|
+
current_model.customize_request_parameters(model_request_parameters)
|
|
136
|
+
)
|
|
137
|
+
|
|
121
138
|
async with current_model.request_stream(
|
|
122
139
|
messages, merged_settings, customized_model_request_parameters, run_context
|
|
123
140
|
) as response:
|
|
@@ -129,6 +146,6 @@ class RoundRobinModel(Model):
|
|
|
129
146
|
with suppress(Exception):
|
|
130
147
|
span = get_current_span()
|
|
131
148
|
if span.is_recording():
|
|
132
|
-
attributes = getattr(span,
|
|
133
|
-
if attributes.get(
|
|
134
|
-
span.set_attributes(model.model_attributes(model))
|
|
149
|
+
attributes = getattr(span, "attributes", {})
|
|
150
|
+
if attributes.get("gen_ai.request.model") == self.model_name:
|
|
151
|
+
span.set_attributes(model.model_attributes(model))
|
|
@@ -53,9 +53,7 @@ def run_summarization_sync(prompt: str, message_history: List) -> List:
|
|
|
53
53
|
def reload_summarization_agent():
|
|
54
54
|
"""Create a specialized agent for summarizing messages when context limit is reached."""
|
|
55
55
|
models_config = ModelFactory.load_config()
|
|
56
|
-
model_name =
|
|
57
|
-
if model_name not in models_config:
|
|
58
|
-
model_name = get_model_name()
|
|
56
|
+
model_name = get_model_name()
|
|
59
57
|
model = ModelFactory.get_model(model_name, models_config)
|
|
60
58
|
|
|
61
59
|
# Specialized instructions for summarization
|