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.
Files changed (64) hide show
  1. tiny_agent_os-0.0.1.dist-info/METADATA +377 -0
  2. tiny_agent_os-0.0.1.dist-info/RECORD +64 -0
  3. tiny_agent_os-0.0.1.dist-info/WHEEL +5 -0
  4. tiny_agent_os-0.0.1.dist-info/entry_points.txt +2 -0
  5. tiny_agent_os-0.0.1.dist-info/licenses/LICENSE +53 -0
  6. tiny_agent_os-0.0.1.dist-info/top_level.txt +1 -0
  7. tinyagent/__init__.py +75 -0
  8. tinyagent/_version.py +21 -0
  9. tinyagent/agent.py +957 -0
  10. tinyagent/chat/__init__.py +12 -0
  11. tinyagent/chat/chat_mode.py +291 -0
  12. tinyagent/cli/__init__.py +16 -0
  13. tinyagent/cli/colors.py +104 -0
  14. tinyagent/cli/main.py +664 -0
  15. tinyagent/cli/spinner.py +94 -0
  16. tinyagent/cli.py +47 -0
  17. tinyagent/config/__init__.py +14 -0
  18. tinyagent/config/config.py +258 -0
  19. tinyagent/decorators.py +187 -0
  20. tinyagent/exceptions.py +85 -0
  21. tinyagent/factory/__init__.py +18 -0
  22. tinyagent/factory/agent_factory.py +439 -0
  23. tinyagent/factory/dynamic_agent_factory.py +561 -0
  24. tinyagent/factory/orchestrator.py +1514 -0
  25. tinyagent/factory/tiny_chain.py +552 -0
  26. tinyagent/logging.py +97 -0
  27. tinyagent/mcp/__init__.py +14 -0
  28. tinyagent/mcp/manager.py +321 -0
  29. tinyagent/prompts/README.md +133 -0
  30. tinyagent/prompts/default.md +14 -0
  31. tinyagent/prompts/prompt_manager.py +206 -0
  32. tinyagent/prompts/system/agent.md +50 -0
  33. tinyagent/prompts/system/retry.md +55 -0
  34. tinyagent/prompts/system/strict_json.md +54 -0
  35. tinyagent/prompts/system.md +10 -0
  36. tinyagent/prompts/tools/calculator.md +13 -0
  37. tinyagent/prompts/tools/weather.md +7 -0
  38. tinyagent/prompts/workflows/riv_reflect.md +62 -0
  39. tinyagent/prompts/workflows/riv_verify.md +47 -0
  40. tinyagent/prompts/workflows/triage.md +129 -0
  41. tinyagent/tool.py +185 -0
  42. tinyagent/tools/README.md +391 -0
  43. tinyagent/tools/__init__.py +39 -0
  44. tinyagent/tools/aider.py +122 -0
  45. tinyagent/tools/anon_coder.py +296 -0
  46. tinyagent/tools/boilerplate_tool.py +147 -0
  47. tinyagent/tools/brave_search.py +104 -0
  48. tinyagent/tools/codeagent_tool.py +217 -0
  49. tinyagent/tools/content_processor.py +285 -0
  50. tinyagent/tools/custom_text_browser.py +965 -0
  51. tinyagent/tools/duckduckgo_search.py +153 -0
  52. tinyagent/tools/external.py +303 -0
  53. tinyagent/tools/file_manipulator.py +274 -0
  54. tinyagent/tools/final_extractor_tool.py +249 -0
  55. tinyagent/tools/llm_serializer.py +124 -0
  56. tinyagent/tools/markdown_gen.py +300 -0
  57. tinyagent/tools/ripgrep.py +136 -0
  58. tinyagent/utils/__init__.py +13 -0
  59. tinyagent/utils/json_parser.py +231 -0
  60. tinyagent/utils/logging_utils.py +78 -0
  61. tinyagent/utils/openrouter_request.py +123 -0
  62. tinyagent/utils/serialization.py +185 -0
  63. tinyagent/utils/structured_outputs.py +131 -0
  64. 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
+ ]
@@ -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}"