tiny-agent-os 0.0.1__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.
- tiny_agent_os-0.0.1.dist-info/METADATA +377 -0
- tiny_agent_os-0.0.1.dist-info/RECORD +64 -0
- tiny_agent_os-0.0.1.dist-info/WHEEL +5 -0
- tiny_agent_os-0.0.1.dist-info/entry_points.txt +2 -0
- tiny_agent_os-0.0.1.dist-info/licenses/LICENSE +53 -0
- tiny_agent_os-0.0.1.dist-info/top_level.txt +1 -0
- tinyagent/__init__.py +75 -0
- tinyagent/_version.py +21 -0
- tinyagent/agent.py +957 -0
- tinyagent/chat/__init__.py +12 -0
- tinyagent/chat/chat_mode.py +291 -0
- tinyagent/cli/__init__.py +16 -0
- tinyagent/cli/colors.py +104 -0
- tinyagent/cli/main.py +664 -0
- tinyagent/cli/spinner.py +94 -0
- tinyagent/cli.py +47 -0
- tinyagent/config/__init__.py +14 -0
- tinyagent/config/config.py +258 -0
- tinyagent/decorators.py +187 -0
- tinyagent/exceptions.py +85 -0
- tinyagent/factory/__init__.py +18 -0
- tinyagent/factory/agent_factory.py +439 -0
- tinyagent/factory/dynamic_agent_factory.py +561 -0
- tinyagent/factory/orchestrator.py +1514 -0
- tinyagent/factory/tiny_chain.py +552 -0
- tinyagent/logging.py +97 -0
- tinyagent/mcp/__init__.py +14 -0
- tinyagent/mcp/manager.py +321 -0
- tinyagent/prompts/README.md +133 -0
- tinyagent/prompts/default.md +14 -0
- tinyagent/prompts/prompt_manager.py +206 -0
- tinyagent/prompts/system/agent.md +50 -0
- tinyagent/prompts/system/retry.md +55 -0
- tinyagent/prompts/system/strict_json.md +54 -0
- tinyagent/prompts/system.md +10 -0
- tinyagent/prompts/tools/calculator.md +13 -0
- tinyagent/prompts/tools/weather.md +7 -0
- tinyagent/prompts/workflows/riv_reflect.md +62 -0
- tinyagent/prompts/workflows/riv_verify.md +47 -0
- tinyagent/prompts/workflows/triage.md +129 -0
- tinyagent/tool.py +185 -0
- tinyagent/tools/README.md +391 -0
- tinyagent/tools/__init__.py +39 -0
- tinyagent/tools/aider.py +122 -0
- tinyagent/tools/anon_coder.py +296 -0
- tinyagent/tools/boilerplate_tool.py +147 -0
- tinyagent/tools/brave_search.py +104 -0
- tinyagent/tools/codeagent_tool.py +217 -0
- tinyagent/tools/content_processor.py +285 -0
- tinyagent/tools/custom_text_browser.py +965 -0
- tinyagent/tools/duckduckgo_search.py +153 -0
- tinyagent/tools/external.py +303 -0
- tinyagent/tools/file_manipulator.py +274 -0
- tinyagent/tools/final_extractor_tool.py +249 -0
- tinyagent/tools/llm_serializer.py +124 -0
- tinyagent/tools/markdown_gen.py +300 -0
- tinyagent/tools/ripgrep.py +136 -0
- tinyagent/utils/__init__.py +13 -0
- tinyagent/utils/json_parser.py +231 -0
- tinyagent/utils/logging_utils.py +78 -0
- tinyagent/utils/openrouter_request.py +123 -0
- tinyagent/utils/serialization.py +185 -0
- tinyagent/utils/structured_outputs.py +131 -0
- tinyagent/utils/type_converter.py +134 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Chat functionality for the tinyAgent framework.
|
|
3
|
+
|
|
4
|
+
This package provides chat-related functionality for the tinyAgent framework,
|
|
5
|
+
including direct conversation with the language model without using tools.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .chat_mode import run_chat_mode
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
'run_chat_mode',
|
|
12
|
+
]
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Chat mode functionality for the tinyAgent framework.
|
|
3
|
+
|
|
4
|
+
This module provides a direct conversation interface with language models without
|
|
5
|
+
requiring tool selection. It handles conversation history, API communication,
|
|
6
|
+
and provides a simple CLI interface.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import os
|
|
13
|
+
import time
|
|
14
|
+
import threading
|
|
15
|
+
import itertools
|
|
16
|
+
from typing import Optional, Final, Dict, Any, List
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
|
|
19
|
+
from openai import OpenAI
|
|
20
|
+
|
|
21
|
+
from ..logging import get_logger
|
|
22
|
+
from ..config import load_config, get_config_value
|
|
23
|
+
from ..cli.colors import Colors
|
|
24
|
+
from ..exceptions import ConfigurationError
|
|
25
|
+
|
|
26
|
+
# Set up logger
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
# Constants
|
|
30
|
+
API_URL: Final[str] = "https://openrouter.ai/api/v1/chat/completions"
|
|
31
|
+
ENV_API_KEY: Final[str] = "OPENROUTER_API_KEY"
|
|
32
|
+
DEFAULT_MODEL: Final[str] = "anthropic/claude-3.5-sonnet"
|
|
33
|
+
DEFAULT_SYSTEM_PROMPT: Final[str] = "You are a helpful AI assistant. Respond concisely and accurately to questions."
|
|
34
|
+
|
|
35
|
+
class ChatSession:
|
|
36
|
+
"""
|
|
37
|
+
Manages a conversation session with a language model.
|
|
38
|
+
|
|
39
|
+
This class handles the conversation history, API communication,
|
|
40
|
+
and message formatting for a chat session.
|
|
41
|
+
|
|
42
|
+
Attributes:
|
|
43
|
+
model: Name of the language model to use
|
|
44
|
+
api_key: API key for authentication
|
|
45
|
+
conversation: List of conversation messages with timestamps
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
model: Optional[str] = None,
|
|
51
|
+
api_key: Optional[str] = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Initialize a chat session with the specified model.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
model: Name of the language model to use
|
|
58
|
+
api_key: API key for authentication (if None, uses environment)
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
ConfigurationError: If the API key is not set
|
|
62
|
+
"""
|
|
63
|
+
# Try to load from config if available
|
|
64
|
+
config_model = None
|
|
65
|
+
try:
|
|
66
|
+
config = load_config()
|
|
67
|
+
if config:
|
|
68
|
+
config_model = get_config_value(config, "model.default")
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.warning(f"Error loading config: {e}")
|
|
71
|
+
|
|
72
|
+
# Priority: 1. Explicitly provided model, 2. Config model, 3. Default
|
|
73
|
+
self.model = model or config_model or DEFAULT_MODEL
|
|
74
|
+
self.api_key = api_key or os.getenv(ENV_API_KEY)
|
|
75
|
+
|
|
76
|
+
if not self.api_key:
|
|
77
|
+
raise ConfigurationError(f"{ENV_API_KEY} must be set in .env")
|
|
78
|
+
|
|
79
|
+
self.conversation: list[dict[str, str]] = [] # Store conversation history
|
|
80
|
+
logger.debug(f"Initialized chat session with model: {self.model}")
|
|
81
|
+
|
|
82
|
+
def add_message(self, role: str, content: str) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Add a message to the conversation history.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
role: Message role ("system", "user", or "assistant")
|
|
88
|
+
content: Message content
|
|
89
|
+
"""
|
|
90
|
+
self.conversation.append({
|
|
91
|
+
"role": role,
|
|
92
|
+
"content": content,
|
|
93
|
+
"timestamp": datetime.now().isoformat(),
|
|
94
|
+
})
|
|
95
|
+
logger.debug(f"Added {role} message: {content[:50]}...")
|
|
96
|
+
|
|
97
|
+
def get_response(self, prompt: str) -> str:
|
|
98
|
+
"""
|
|
99
|
+
Get a response from the language model for the given prompt.
|
|
100
|
+
|
|
101
|
+
This method sends the conversation history and the new prompt to the
|
|
102
|
+
language model and retrieves a response.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
prompt: User prompt to send to the model
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
The model's response
|
|
109
|
+
|
|
110
|
+
Raises:
|
|
111
|
+
Exception: If there's an error communicating with the API
|
|
112
|
+
"""
|
|
113
|
+
# Add user message to conversation
|
|
114
|
+
self.add_message("user", prompt)
|
|
115
|
+
|
|
116
|
+
# Log debug info about the model and conversation length
|
|
117
|
+
logger.debug(
|
|
118
|
+
f"Using model: {self.model} | History: {len(self.conversation)} messages"
|
|
119
|
+
)
|
|
120
|
+
print(
|
|
121
|
+
f"\r{Colors.OFF_WHITE}Using model: {self.model} | "
|
|
122
|
+
f"History: {len(self.conversation)} messages{Colors.RESET}",
|
|
123
|
+
flush=True,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Initialize spinner for loading feedback
|
|
127
|
+
spinner = itertools.cycle(["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"])
|
|
128
|
+
|
|
129
|
+
# Create an event for stopping the spinner thread
|
|
130
|
+
stop_event = threading.Event()
|
|
131
|
+
|
|
132
|
+
def spin_animation() -> None:
|
|
133
|
+
"""Display a spinning animation while waiting for response."""
|
|
134
|
+
while not stop_event.is_set():
|
|
135
|
+
for frame in spinner:
|
|
136
|
+
sys.stdout.write(
|
|
137
|
+
f"\r{Colors.LIGHT_RED}{frame}{Colors.OFF_WHITE} "
|
|
138
|
+
f"Thinking...{Colors.RESET}"
|
|
139
|
+
)
|
|
140
|
+
sys.stdout.flush()
|
|
141
|
+
# Short sleep with frequent checks for the stop event
|
|
142
|
+
for _ in range(10): # 10 * 0.01 = 0.1 seconds per frame
|
|
143
|
+
if stop_event.is_set():
|
|
144
|
+
break
|
|
145
|
+
time.sleep(0.01)
|
|
146
|
+
if stop_event.is_set():
|
|
147
|
+
break
|
|
148
|
+
# Clear the line when stopped
|
|
149
|
+
sys.stdout.write("\r" + " " * 50 + "\r")
|
|
150
|
+
sys.stdout.flush()
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
# Initialize OpenAI client with OpenRouter configuration
|
|
154
|
+
client = OpenAI(
|
|
155
|
+
base_url="https://openrouter.ai/api/v1",
|
|
156
|
+
api_key=self.api_key,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# Start spinner thread
|
|
160
|
+
spinner_thread = threading.Thread(target=spin_animation)
|
|
161
|
+
spinner_thread.daemon = True
|
|
162
|
+
spinner_thread.start()
|
|
163
|
+
|
|
164
|
+
try:
|
|
165
|
+
# Make the API request with explicit timeout
|
|
166
|
+
logger.debug(f"Sending request to {API_URL}")
|
|
167
|
+
|
|
168
|
+
completion = client.chat.completions.create(
|
|
169
|
+
extra_headers={
|
|
170
|
+
"HTTP-Referer": "https://tinyagent.dev",
|
|
171
|
+
},
|
|
172
|
+
model=self.model,
|
|
173
|
+
messages=self.conversation,
|
|
174
|
+
temperature=0.7,
|
|
175
|
+
max_tokens=2000,
|
|
176
|
+
timeout=60,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
logger.debug("Received response from API")
|
|
180
|
+
|
|
181
|
+
# Stop the spinner
|
|
182
|
+
stop_event.set()
|
|
183
|
+
spinner_thread.join(timeout=0.5) # Wait for spinner to clean up
|
|
184
|
+
|
|
185
|
+
# Extract assistant's response
|
|
186
|
+
if completion.choices and len(completion.choices) > 0:
|
|
187
|
+
assistant_message = completion.choices[0].message.content
|
|
188
|
+
|
|
189
|
+
# Check for empty response and provide fallback
|
|
190
|
+
if not assistant_message or assistant_message.strip() == "":
|
|
191
|
+
fallback_msg = (
|
|
192
|
+
"Sorry, I couldn't generate a response. "
|
|
193
|
+
"Let's try again with a different question."
|
|
194
|
+
)
|
|
195
|
+
logger.warning("Empty response received - using fallback")
|
|
196
|
+
# Add fallback message to conversation history
|
|
197
|
+
self.add_message("assistant", fallback_msg)
|
|
198
|
+
return fallback_msg
|
|
199
|
+
|
|
200
|
+
# Add assistant response to conversation history
|
|
201
|
+
self.add_message("assistant", assistant_message)
|
|
202
|
+
return assistant_message or ""
|
|
203
|
+
else:
|
|
204
|
+
# Extended debug output for troubleshooting
|
|
205
|
+
debug_msg = "Unexpected API response format: no valid choices found"
|
|
206
|
+
logger.warning(debug_msg)
|
|
207
|
+
# Create a fallback response that will be more useful than blank
|
|
208
|
+
fallback = "I'm having trouble processing your request. Please try asking a different question."
|
|
209
|
+
self.add_message("assistant", fallback)
|
|
210
|
+
return fallback
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
# Make sure to stop the spinner on error
|
|
214
|
+
stop_event.set()
|
|
215
|
+
spinner_thread.join(timeout=0.5)
|
|
216
|
+
raise e
|
|
217
|
+
|
|
218
|
+
except Exception as e:
|
|
219
|
+
# Enhanced error handling with more details and fallback response
|
|
220
|
+
logger.error(f"Error in get_response: {type(e).__name__}: {str(e)}")
|
|
221
|
+
if hasattr(e, "response") and hasattr(e.response, "text"):
|
|
222
|
+
logger.error(f"API response: {e.response.text[:500]}...")
|
|
223
|
+
|
|
224
|
+
# Provide a useful fallback response for the user
|
|
225
|
+
fallback = "I'm experiencing technical difficulties. Please try again in a moment."
|
|
226
|
+
# Add fallback to conversation history
|
|
227
|
+
self.add_message("assistant", fallback)
|
|
228
|
+
return fallback
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def run_chat_mode(
|
|
232
|
+
model: Optional[str] = None,
|
|
233
|
+
system_prompt: Optional[str] = None,
|
|
234
|
+
) -> None:
|
|
235
|
+
"""
|
|
236
|
+
Run the chat mode interface with the specified model.
|
|
237
|
+
|
|
238
|
+
This function provides a simple CLI interface for chatting directly with
|
|
239
|
+
a language model without using tools.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
model: Name of the language model to use
|
|
243
|
+
system_prompt: Optional system prompt to set the behavior of the model
|
|
244
|
+
"""
|
|
245
|
+
# Print welcome message
|
|
246
|
+
print(f"\n{Colors.OFF_WHITE}Welcome to tinyAgent Chat Mode!{Colors.RESET}")
|
|
247
|
+
print(
|
|
248
|
+
f"{Colors.OFF_WHITE}Type 'exit' or 'quit' to return to the main interface."
|
|
249
|
+
f"{Colors.RESET}"
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
try:
|
|
253
|
+
# Create chat session
|
|
254
|
+
session = ChatSession(model=model)
|
|
255
|
+
|
|
256
|
+
# Print the model being used (which could be from config)
|
|
257
|
+
print(
|
|
258
|
+
f"{Colors.OFF_WHITE}Using model: {session.model} "
|
|
259
|
+
f"(from config.yml or default){Colors.RESET}"
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# Add system prompt if provided
|
|
263
|
+
if system_prompt:
|
|
264
|
+
session.add_message("system", system_prompt)
|
|
265
|
+
else:
|
|
266
|
+
# Default system prompt
|
|
267
|
+
session.add_message("system", DEFAULT_SYSTEM_PROMPT)
|
|
268
|
+
|
|
269
|
+
# Main chat loop
|
|
270
|
+
while True:
|
|
271
|
+
# Get user input
|
|
272
|
+
user_input = input(f"\n{Colors.LIGHT_RED}❯{Colors.OFF_WHITE} ")
|
|
273
|
+
|
|
274
|
+
# Check for exit command
|
|
275
|
+
if user_input.lower() in ["exit", "quit"]:
|
|
276
|
+
print(f"\n{Colors.LIGHT_RED}Exiting chat mode.{Colors.RESET}")
|
|
277
|
+
break
|
|
278
|
+
|
|
279
|
+
# Get response from LLM
|
|
280
|
+
response = session.get_response(user_input)
|
|
281
|
+
|
|
282
|
+
# Print response
|
|
283
|
+
print(f"\n{Colors.OFF_WHITE}{response}{Colors.RESET}")
|
|
284
|
+
|
|
285
|
+
except KeyboardInterrupt:
|
|
286
|
+
print(f"\n{Colors.LIGHT_RED}Chat mode interrupted. Exiting.{Colors.RESET}")
|
|
287
|
+
logger.info("Chat mode interrupted by user")
|
|
288
|
+
except Exception as e:
|
|
289
|
+
error_msg = f"Error in chat mode: {str(e)}"
|
|
290
|
+
print(f"\n{Colors.error(error_msg)}")
|
|
291
|
+
logger.error(error_msg)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line interface for the tinyAgent framework.
|
|
3
|
+
|
|
4
|
+
This package provides the CLI components for the tinyAgent framework,
|
|
5
|
+
including command parsing, interactive mode, and specific command handlers.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .main import main
|
|
9
|
+
from .spinner import Spinner
|
|
10
|
+
from .colors import Colors
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
'main',
|
|
14
|
+
'Spinner',
|
|
15
|
+
'Colors',
|
|
16
|
+
]
|
tinyagent/cli/colors.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Color definitions for the tinyAgent CLI.
|
|
3
|
+
|
|
4
|
+
This module provides ANSI color codes for consistent color usage throughout
|
|
5
|
+
the tinyAgent CLI, making the interface more intuitive and user-friendly.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Colors:
|
|
10
|
+
"""
|
|
11
|
+
ANSI color codes for CLI output.
|
|
12
|
+
|
|
13
|
+
This class defines constants for various colors and styles used in the
|
|
14
|
+
tinyAgent CLI output. These provide visual cues for different types of
|
|
15
|
+
information, such as errors, warnings, and success messages.
|
|
16
|
+
|
|
17
|
+
Attributes:
|
|
18
|
+
LIGHT_RED: Red color for errors and important alerts
|
|
19
|
+
OFF_WHITE: Light grey color for normal text
|
|
20
|
+
DARK_RED: Darker red for backgrounds and borders
|
|
21
|
+
RESET: Code to reset to default text color and style
|
|
22
|
+
BOLD: Code to make text bold
|
|
23
|
+
GREEN: Green color for success messages
|
|
24
|
+
YELLOW: Yellow color for warnings
|
|
25
|
+
BLUE: Blue color for information messages
|
|
26
|
+
CYAN: Cyan color for process steps
|
|
27
|
+
MAGENTA: Magenta color for user inputs
|
|
28
|
+
"""
|
|
29
|
+
LIGHT_RED = "\033[38;2;255;107;107m"
|
|
30
|
+
OFF_WHITE = "\033[38;2;248;249;250m"
|
|
31
|
+
DARK_RED = "\033[38;2;230;69;69m"
|
|
32
|
+
RESET = "\033[0m"
|
|
33
|
+
BOLD = "\033[1m"
|
|
34
|
+
GREEN = "\033[38;2;114;225;158m"
|
|
35
|
+
YELLOW = "\033[38;2;255;214;107m"
|
|
36
|
+
BLUE = "\033[38;2;118;180;255m"
|
|
37
|
+
CYAN = "\033[38;2;100;223;223m"
|
|
38
|
+
MAGENTA = "\033[38;2;219;112;219m"
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def colorize(text: str, color: str) -> str:
|
|
42
|
+
"""
|
|
43
|
+
Apply a color to text.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
text: The text to colorize
|
|
47
|
+
color: The color code to apply
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
The colorized text
|
|
51
|
+
"""
|
|
52
|
+
return f"{color}{text}{Colors.RESET}"
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def error(text: str) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Format text as an error message.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
text: The error message
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Formatted error message
|
|
64
|
+
"""
|
|
65
|
+
return f"{Colors.LIGHT_RED}{Colors.BOLD}Error: {text}{Colors.RESET}"
|
|
66
|
+
|
|
67
|
+
@staticmethod
|
|
68
|
+
def warning(text: str) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Format text as a warning message.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
text: The warning message
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Formatted warning message
|
|
77
|
+
"""
|
|
78
|
+
return f"{Colors.YELLOW}{Colors.BOLD}Warning: {text}{Colors.RESET}"
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def success(text: str) -> str:
|
|
82
|
+
"""
|
|
83
|
+
Format text as a success message.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
text: The success message
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Formatted success message
|
|
90
|
+
"""
|
|
91
|
+
return f"{Colors.GREEN}{Colors.BOLD}Success: {text}{Colors.RESET}"
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def info(text: str) -> str:
|
|
95
|
+
"""
|
|
96
|
+
Format text as an information message.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
text: The information message
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Formatted information message
|
|
103
|
+
"""
|
|
104
|
+
return f"{Colors.BLUE}Info: {text}{Colors.RESET}"
|