aigency 0.0.1rc238211992__py3-none-any.whl → 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
aigency/utils/logger.py CHANGED
@@ -1,3 +1,24 @@
1
+ """Singleton logger implementation for consistent application-wide logging.
2
+
3
+ This module provides a centralized logging system using the Singleton pattern to
4
+ ensure consistent logging behavior across the entire Aigency application. It supports
5
+ configurable log levels, multiple output handlers, and dynamic configuration updates.
6
+
7
+ The Logger class extends the Singleton base class to guarantee only one logger
8
+ instance exists throughout the application lifecycle, preventing configuration
9
+ conflicts and ensuring unified log formatting and output destinations.
10
+
11
+ Example:
12
+ Basic logger usage:
13
+
14
+ >>> logger = get_logger({"log_level": "DEBUG", "log_file": "app.log"})
15
+ >>> logger.info("Application started")
16
+ >>> logger.error("An error occurred", exc_info=True)
17
+
18
+ Attributes:
19
+ None: This module contains only class definitions and utility functions.
20
+ """
21
+
1
22
  import logging
2
23
  import sys
3
24
  from typing import Optional, Dict, Any
@@ -5,97 +26,165 @@ from aigency.utils.singleton import Singleton
5
26
 
6
27
 
7
28
  class Logger(Singleton):
29
+ """Singleton logger class for consistent logging across the application.
30
+
31
+ This class provides a centralized logging mechanism that ensures only one
32
+ logger instance exists throughout the application lifecycle.
33
+
34
+ Attributes:
35
+ config (Dict[str, Any]): Configuration dictionary for logger settings.
36
+ _logger (logging.Logger): Internal logger instance.
37
+ _initialized (bool): Flag to track initialization state.
38
+ """
39
+
8
40
  def __init__(self, config: Optional[Dict[str, Any]] = None):
9
- if hasattr(self, '_initialized'):
10
- # Si ya está inicializado y se pasa nueva config, actualizar
11
- if config and config != getattr(self, 'config', {}):
41
+ """Initialize the logger with optional configuration.
42
+
43
+ Args:
44
+ config (Dict[str, Any], optional): Dictionary containing logger
45
+ configuration. Defaults to None.
46
+ """
47
+ if hasattr(self, "_initialized"):
48
+ # If already initialized and new config is passed, update
49
+ if config and config != getattr(self, "config", {}):
12
50
  self.config.update(config)
13
51
  self._setup_logger()
14
52
  return
15
-
53
+
16
54
  self._initialized = True
17
55
  self.config = config or {}
18
56
  self._logger = None
19
57
  self._setup_logger()
20
-
58
+
21
59
  def _setup_logger(self):
22
- """Configura el logger con la configuración proporcionada"""
23
- # Obtener configuración del logger
24
- log_level = self.config.get('log_level', 'INFO').upper()
25
- log_format = self.config.get('log_format', '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
26
- log_file = self.config.get('log_file')
27
- logger_name = self.config.get('logger_name', 'aigency')
28
-
29
- # Crear logger
60
+ """Configure the logger with the provided configuration.
61
+
62
+ Sets up the internal logger instance with handlers, formatters, and
63
+ log levels based on the configuration dictionary.
64
+ """
65
+ # Get logger configuration
66
+ log_level = self.config.get("log_level", "INFO").upper()
67
+ log_format = self.config.get(
68
+ "log_format", "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
69
+ )
70
+ log_file = self.config.get("log_file")
71
+ logger_name = self.config.get("logger_name", "aigency")
72
+
73
+ # Create logger
30
74
  self._logger = logging.getLogger(logger_name)
31
75
  self._logger.setLevel(getattr(logging, log_level, logging.INFO))
32
-
33
- # Evitar duplicar handlers si ya existen
76
+
77
+ # Avoid duplicating handlers if they already exist
34
78
  if self._logger.handlers:
35
79
  return
36
-
37
- # Crear formatter
80
+
81
+ # Create formatter
38
82
  formatter = logging.Formatter(log_format)
39
-
40
- # Handler para consola
83
+
84
+ # Console handler
41
85
  console_handler = logging.StreamHandler(sys.stdout)
42
86
  console_handler.setLevel(getattr(logging, log_level, logging.INFO))
43
87
  console_handler.setFormatter(formatter)
44
88
  self._logger.addHandler(console_handler)
45
-
46
- # Handler para archivo si se especifica
89
+
90
+ # File handler if specified
47
91
  if log_file:
48
92
  file_handler = logging.FileHandler(log_file)
49
93
  file_handler.setLevel(getattr(logging, log_level, logging.INFO))
50
94
  file_handler.setFormatter(formatter)
51
95
  self._logger.addHandler(file_handler)
52
-
96
+
53
97
  def debug(self, message: str, *args, **kwargs):
54
- """Log a debug message"""
98
+ """Log a debug message.
99
+
100
+ Args:
101
+ message (str): The message to log.
102
+ *args: Variable length argument list.
103
+ **kwargs: Arbitrary keyword arguments.
104
+ """
55
105
  self._logger.debug(message, *args, **kwargs)
56
-
106
+
57
107
  def info(self, message: str, *args, **kwargs):
58
- """Log an info message"""
108
+ """Log an info message.
109
+
110
+ Args:
111
+ message (str): The message to log.
112
+ *args: Variable length argument list.
113
+ **kwargs: Arbitrary keyword arguments.
114
+ """
59
115
  self._logger.info(message, *args, **kwargs)
60
-
116
+
61
117
  def warning(self, message: str, *args, **kwargs):
62
- """Log a warning message"""
118
+ """Log a warning message.
119
+
120
+ Args:
121
+ message (str): The message to log.
122
+ *args: Variable length argument list.
123
+ **kwargs: Arbitrary keyword arguments.
124
+ """
63
125
  self._logger.warning(message, *args, **kwargs)
64
-
126
+
65
127
  def error(self, message: str, *args, **kwargs):
66
- """Log an error message"""
128
+ """Log an error message.
129
+
130
+ Args:
131
+ message (str): The message to log.
132
+ *args: Variable length argument list.
133
+ **kwargs: Arbitrary keyword arguments.
134
+ """
67
135
  self._logger.error(message, *args, **kwargs)
68
-
136
+
69
137
  def critical(self, message: str, *args, **kwargs):
70
- """Log a critical message"""
138
+ """Log a critical message.
139
+
140
+ Args:
141
+ message (str): The message to log.
142
+ *args: Variable length argument list.
143
+ **kwargs: Arbitrary keyword arguments.
144
+ """
71
145
  self._logger.critical(message, *args, **kwargs)
72
-
146
+
73
147
  def exception(self, message: str, *args, **kwargs):
74
- """Log an exception with traceback"""
148
+ """Log an exception with traceback.
149
+
150
+ Args:
151
+ message (str): The message to log.
152
+ *args: Variable length argument list.
153
+ **kwargs: Arbitrary keyword arguments.
154
+ """
75
155
  self._logger.exception(message, *args, **kwargs)
76
-
156
+
77
157
  def set_level(self, level: str):
78
- """Cambiar el nivel de logging dinámicamente"""
158
+ """Change the logging level dynamically.
159
+
160
+ Args:
161
+ level (str): The new logging level as a string.
162
+ """
79
163
  log_level = level.upper()
80
164
  self._logger.setLevel(getattr(logging, log_level, logging.INFO))
81
165
  for handler in self._logger.handlers:
82
166
  handler.setLevel(getattr(logging, log_level, logging.INFO))
83
-
167
+
84
168
  def get_logger(self):
85
- """Obtener la instancia del logger interno"""
169
+ """Get the internal logger instance.
170
+
171
+ Returns:
172
+ logging.Logger: The internal logging.Logger instance.
173
+ """
86
174
  return self._logger
87
175
 
88
176
 
89
- # Función de conveniencia para obtener la instancia del logger
177
+ # Convenience function to get the logger instance
90
178
  def get_logger(config: Optional[Dict[str, Any]] = None) -> Logger:
91
- """
92
- Obtiene la instancia singleton del logger.
93
- Si es la primera vez que se llama y se proporciona config, se usa esa configuración.
94
-
179
+ """Get the singleton logger instance.
180
+
181
+ If this is the first call and config is provided, that configuration is used.
182
+
95
183
  Args:
96
- config: Configuración opcional para el logger (solo se usa en la primera llamada)
97
-
184
+ config (Dict[str, Any], optional): Optional configuration for the logger
185
+ (only used on first call). Defaults to None.
186
+
98
187
  Returns:
99
- Instancia singleton del Logger
188
+ Logger: Singleton Logger instance.
100
189
  """
101
- return Logger(config)
190
+ return Logger(config)
@@ -1,7 +1,54 @@
1
+ """Singleton pattern implementation using metaclasses.
2
+
3
+ This module provides a robust implementation of the Singleton design pattern using
4
+ Python metaclasses. It ensures that classes inheriting from the Singleton base class
5
+ can have only one instance throughout the application lifecycle, which is useful
6
+ for shared resources like loggers, configuration managers, and database connections.
7
+
8
+ The implementation uses a metaclass approach to control instance creation at the
9
+ class level, providing thread-safe singleton behavior without requiring explicit
10
+ synchronization in the client code.
11
+
12
+ Example:
13
+ Creating singleton classes:
14
+
15
+ >>> class DatabaseManager(Singleton):
16
+ ... def __init__(self):
17
+ ... self.connection = "db_connection"
18
+ >>>
19
+ >>> db1 = DatabaseManager()
20
+ >>> db2 = DatabaseManager()
21
+ >>> db1 is db2
22
+ True
23
+
24
+ Attributes:
25
+ None: This module contains only class definitions.
26
+ """
27
+
28
+
1
29
  class SingletonMeta(type):
30
+ """Metaclass that implements the Singleton pattern.
31
+
32
+ This metaclass ensures that only one instance of a class can exist.
33
+ When a class uses this metaclass, subsequent instantiation attempts
34
+ will return the same instance.
35
+
36
+ Attributes:
37
+ _instances (dict): Dictionary storing singleton instances by class.
38
+ """
39
+
2
40
  _instances = {}
3
41
 
4
42
  def __call__(cls, *args, **kwargs):
43
+ """Control instance creation to ensure singleton behavior.
44
+
45
+ Args:
46
+ *args: Variable length argument list for class instantiation.
47
+ **kwargs: Arbitrary keyword arguments for class instantiation.
48
+
49
+ Returns:
50
+ object: The singleton instance of the class.
51
+ """
5
52
  if cls not in cls._instances:
6
53
  instance = super().__call__(*args, **kwargs)
7
54
  cls._instances[cls] = instance
@@ -9,4 +56,18 @@ class SingletonMeta(type):
9
56
 
10
57
 
11
58
  class Singleton(metaclass=SingletonMeta):
12
- pass
59
+ """Base class for implementing singleton pattern.
60
+
61
+ Classes that inherit from this base class will automatically
62
+ follow the singleton pattern, ensuring only one instance exists.
63
+
64
+ Example:
65
+ >>> class MyClass(Singleton):
66
+ ... pass
67
+ >>> obj1 = MyClass()
68
+ >>> obj2 = MyClass()
69
+ >>> obj1 is obj2
70
+ True
71
+ """
72
+
73
+ pass
aigency/utils/utils.py CHANGED
@@ -1,4 +1,23 @@
1
- """Utility functions for type conversions and environment variable handling."""
1
+ """Utility functions for type conversions and environment variable handling.
2
+
3
+ This module provides essential utility functions for the Aigency framework, including
4
+ type conversions between A2A and Google GenAI formats, environment variable expansion,
5
+ URL generation, and safe asynchronous execution helpers.
6
+
7
+ The utilities handle common operations needed across the framework, such as converting
8
+ message parts between different protocol formats, managing environment variables in
9
+ configurations, and safely running coroutines in various asyncio contexts.
10
+
11
+ Example:
12
+ Converting between A2A and GenAI formats:
13
+
14
+ >>> a2a_part = TextPart(text="Hello world")
15
+ >>> genai_part = convert_a2a_part_to_genai(a2a_part)
16
+ >>> back_to_a2a = convert_genai_part_to_a2a(genai_part)
17
+
18
+ Attributes:
19
+ logger: Module-level logger instance for utility operations.
20
+ """
2
21
 
3
22
  import asyncio
4
23
  import os
@@ -57,9 +76,17 @@ def convert_genai_part_to_a2a(part: types.Part) -> Part:
57
76
 
58
77
 
59
78
  def expand_env_vars(env_dict):
60
- """
61
- Expande los valores del diccionario usando variables de entorno solo si el valor es una clave de entorno existente.
62
- Si la variable no existe en el entorno, deja el valor literal.
79
+ """Expand dictionary values using environment variables.
80
+
81
+ Expands values in the dictionary using environment variables only if the value
82
+ is an existing environment variable key. If the variable doesn't exist in the
83
+ environment, leaves the literal value.
84
+
85
+ Args:
86
+ env_dict (dict): Dictionary with potential environment variable references.
87
+
88
+ Returns:
89
+ dict: Dictionary with expanded environment variable values.
63
90
  """
64
91
  result = {}
65
92
  for k, v in env_dict.items():
@@ -85,7 +112,20 @@ def generate_url(host: str, port: int, path: str = "") -> str:
85
112
 
86
113
 
87
114
  def safe_async_run(coro):
88
- """Simple wrapper to safely run async code."""
115
+ """Simple wrapper to safely run async code.
116
+
117
+ This function handles different asyncio event loop scenarios to safely
118
+ execute coroutines, including cases where a loop is already running.
119
+
120
+ Args:
121
+ coro: The coroutine to execute.
122
+
123
+ Returns:
124
+ Any: The result of the coroutine execution.
125
+
126
+ Raises:
127
+ Exception: Any exception raised by the coroutine.
128
+ """
89
129
  try:
90
130
  loop = asyncio.get_event_loop()
91
131
  if loop.is_running():
@@ -111,4 +151,3 @@ def safe_async_run(coro):
111
151
  return loop.run_until_complete(coro)
112
152
  except RuntimeError:
113
153
  return asyncio.run(coro)
114
-
@@ -0,0 +1,171 @@
1
+ Metadata-Version: 2.4
2
+ Name: aigency
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Requires-Python: >=3.12
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: google-adk>=1.11.0
8
+ Requires-Dist: a2a-sdk>=0.3.0
9
+ Requires-Dist: litellm<1.73.0,>=1.72.6
10
+ Requires-Dist: pyyaml==6.0.2
11
+ Requires-Dist: PyJWT==2.10.1
12
+
13
+ # Aigency
14
+
15
+ AI Agent Development Acceleration Kit — build, run, and orchestrate intelligent agents with a production‑ready Agent‑to‑Agent (A2A) runtime.
16
+
17
+ Aigency provides primitives and utilities to define agents via simple YAML, instantiate them programmatically, and serve them over HTTP using the A2A server. It is designed to be modular, observable, and extensible.
18
+
19
+ - Python: >= 3.12
20
+ - PyPI package: `aigency`
21
+ - Core deps: `a2a-sdk`, `pyyaml`, `litellm`, `PyJWT`, `google-adk`
22
+
23
+ ## Features
24
+ - Config‑first agents: define agent behavior, skills, tools, and model in YAML
25
+ - Agent generator: instantiate agents, build agent cards, and executors programmatically
26
+ - A2A integration: serve agents over HTTP with Starlette‑based A2A server
27
+ - MCP‑friendly: integrate external tools/services via Model Context Protocol (optional)
28
+ - Observability: compatible with Phoenix and A2A Inspector for tracing and debugging
29
+ - Docker‑friendly: used across example demos and containers
30
+
31
+ ## Installation
32
+ ```bash
33
+ pip install aigency
34
+ ```
35
+ Requires Python 3.12+.
36
+
37
+ ## Quickstart
38
+ Minimal example for a single agent (no MCP) that responds in the user’s language.
39
+
40
+ 1) Create an agent config file (e.g., `agent_config.yaml`):
41
+ ```yaml
42
+ metadata:
43
+ name: hello_agent
44
+ description: A simple example agent that greets and answers briefly.
45
+ version: 1.0.0
46
+
47
+ service:
48
+ url: http://hello-agent:8080
49
+ capabilities:
50
+ streaming: true
51
+ interface:
52
+ default_input_modes: [text, text/plain]
53
+ default_output_modes: [text, text/plain]
54
+
55
+ agent:
56
+ model:
57
+ name: gemini-2.0-flash
58
+
59
+ instruction: |
60
+ """
61
+ You are a friendly, concise assistant. Always reply in the same language as the user.
62
+ Keep responses short and helpful.
63
+ """
64
+
65
+ skills:
66
+ - id: greet
67
+ name: Greet
68
+ description: Greets users and offers help
69
+ examples:
70
+ - "Hello! How can I help you today?"
71
+ ```
72
+
73
+ 2) Run a tiny A2A app (e.g., `app.py`):
74
+ ```python
75
+ import os
76
+ import uvicorn
77
+ from a2a.server.apps import A2AStarletteApplication
78
+ from a2a.server.request_handlers import DefaultRequestHandler
79
+ from a2a.server.tasks import InMemoryTaskStore
80
+ from aigency.agents.generator import AgentA2AGenerator
81
+ from aigency.utils.config_service import ConfigService
82
+
83
+ CONFIG_PATH = os.path.join(os.path.dirname(__file__), "agent_config.yaml")
84
+
85
+ config_service = ConfigService(config_file=CONFIG_PATH)
86
+ agent_config = config_service.config
87
+
88
+ agent = AgentA2AGenerator.create_agent(agent_config=agent_config)
89
+ agent_card = AgentA2AGenerator.build_agent_card(agent_config=agent_config)
90
+ executor = AgentA2AGenerator.build_executor(agent=agent, agent_card=agent_card)
91
+
92
+ request_handler = DefaultRequestHandler(
93
+ agent_executor=executor,
94
+ task_store=InMemoryTaskStore(),
95
+ )
96
+ app = A2AStarletteApplication(
97
+ agent_card=agent_card,
98
+ http_handler=request_handler,
99
+ ).build()
100
+
101
+ if __name__ == "__main__":
102
+ uvicorn.run(app, host="0.0.0.0", port=8080)
103
+ ```
104
+
105
+ 3) Start the server:
106
+ ```bash
107
+ python app.py
108
+ ```
109
+ Then open http://localhost:8080 to interact via the A2A HTTP interface or connect a compatible client.
110
+
111
+ ## Using Models & Providers
112
+ Aigency integrates with LLM providers via its dependencies. For Google Gemini models:
113
+
114
+ - Use API key (Google AI Studio):
115
+ - `GEMINI_API_KEY=your_gemini_api_key`
116
+ - `GOOGLE_GENAI_USE_VERTEXAI=FALSE`
117
+ - Or use Vertex AI (requires additional env like project/region and credentials):
118
+ - `GOOGLE_GENAI_USE_VERTEXAI=TRUE`
119
+
120
+ Set these environment variables before running your app if you use Gemini‑based models.
121
+
122
+ ## Configuration Reference (YAML)
123
+ Common top‑level sections:
124
+
125
+ - `metadata`: name, description, version
126
+ - `service`: url, capabilities, interface defaults
127
+ - `agent`:
128
+ - `model`: model name (e.g., `gemini-2.0-flash`)
129
+ - `instruction`: system prompt/persona
130
+ - `skills`: list of skills with `id`, `name`, `description`, and `examples`
131
+ - `tools`: optional integrations (e.g., MCP tools)
132
+ - `observability`: optional Phoenix/A2A Inspector configuration
133
+
134
+ Example of adding an MCP tool:
135
+ ```yaml
136
+ tools:
137
+ - type: mcp
138
+ name: sample_mcp
139
+ description: Example MCP tool
140
+ mcp_config:
141
+ url: sample-mcp-service
142
+ port: 8080
143
+ path: /mcp/
144
+ ```
145
+
146
+ ## Examples & Demos
147
+ Explore ready‑to‑run demos built with Aigency:
148
+
149
+ - Reception Agent (single agent, no MCP):
150
+ https://aigency-project.github.io/get_started/demos/reception_aigent
151
+ - Gossip Agent (single agent + MCP tools):
152
+ https://aigency-project.github.io/get_started/demos/gossip_agent
153
+ - Detective Aigency (multi‑agent system):
154
+ https://aigency-project.github.io/get_started/demos/detective_aigency/
155
+
156
+ Documentation site:
157
+ - https://aigency-project.github.io/
158
+
159
+ ## Observability
160
+ Aigency‑based apps can be observed with:
161
+ - Phoenix dashboard (tracing/metrics)
162
+ - A2A Inspector (agent/task introspection)
163
+
164
+ Refer to the demo repositories for docker‑compose setups that launch these services.
165
+
166
+ ## Development
167
+ - Python 3.12+
168
+ - Install dev deps and run tests as usual; for versioning helpers, see `scripts/version_manager.py` in this repo.
169
+
170
+ ## License
171
+ This project’s license is provided in the `LICENSE` file.
@@ -0,0 +1,26 @@
1
+ aigency/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ aigency/agents/client.py,sha256=M2j6NpzjG4aeLmYY0NMsgjb6HQSLMVz9Cba7WJsEIQ8,2651
3
+ aigency/agents/communicator.py,sha256=qr77SolCIiNrp7nmuFfPOscmdPnCWmgQwPQcBwJIlt4,5712
4
+ aigency/agents/executor.py,sha256=0FdWQodUeTnYbMGe3CPOYxzhQ2uF0S7m2aJudTrdx20,7494
5
+ aigency/agents/generator.py,sha256=D1O0Vn96kyruv6yvuZUWhE5yGxDpoUrYiDQpOEcS6N8,7363
6
+ aigency/schemas/aigency_config.py,sha256=qbcHjmmMAG_-nWY689aS9wQ0gzbroQTpjPb9MlDBfmc,1817
7
+ aigency/schemas/agent/agent.py,sha256=NamGZsk9ajOmIJiLyoSdFZsbJ8av6-0d2mTgHNG5z64,1910
8
+ aigency/schemas/agent/model.py,sha256=FKLoXiPamrsFs1G8jFQkn0nvdp3rIlpMUg5BWmL1Klc,1381
9
+ aigency/schemas/agent/remote_agent.py,sha256=wfqirTisFGQFwOAU_oKLyiYw_61ZZVp7lIfe1g_11ZA,1244
10
+ aigency/schemas/agent/skills.py,sha256=LZntfTygAhuv09m5URbkygDhCD0-Sl2A9gEAJkgCncg,1287
11
+ aigency/schemas/agent/tools.py,sha256=ANyzJstAFn3dg5JjpiwTGmkOHSFJ4-Ry7Fw2nmj1XNk,3526
12
+ aigency/schemas/metadata/metadata.py,sha256=9mKSJgLfwjhRrKD3pvdNIuhk6b8c3pz1YaVIb5qOWMY,1108
13
+ aigency/schemas/observability/observability.py,sha256=DHY4zmFg_qy7U97YILRJ02Y0tWNgcNB9w7akZaNbyfo,1302
14
+ aigency/schemas/observability/phoenix.py,sha256=SpiStSw5xbXkEZH8HW56rCidMyjBi3OT3Y2i4D0tA_k,1018
15
+ aigency/schemas/service/capabilities.py,sha256=sMQtqCaXYVnDebdKhZ48iKDL1h9CoXWoxh7TFm1LO6E,898
16
+ aigency/schemas/service/interface.py,sha256=Jcp9Wy2sArhdeh_PiQNqcl0f2IMbipo3Muw5EWIoiiE,1140
17
+ aigency/schemas/service/service.py,sha256=E_KZNiM-7DJS4Ezd8xPfFq_W8HkzIFZvzGe4sreDfjY,1415
18
+ aigency/tools/generator.py,sha256=wMk5rt8wXSCci_K-vVyUMKvNuWlJcnpB7Y3SxRnfgG4,4355
19
+ aigency/utils/config_service.py,sha256=ZE7xptJ20zk9sAJMxcDa2QYWMPhzfiW95gHquSX8E3s,5852
20
+ aigency/utils/logger.py,sha256=kOIWbCTFiT4coz3cqcvD-YAu_EqIy4bqLBdaJ-sYOnk,6602
21
+ aigency/utils/singleton.py,sha256=zwIj5c-A3F6BhK16AnwwxUX_qr_AbPAab-477nSGf7w,2267
22
+ aigency/utils/utils.py,sha256=qjnzCV_5yOT0XG870_jU-xYnQeK1TUqVksU5Rnefxcs,4470
23
+ aigency-0.1.0.dist-info/METADATA,sha256=XNj8kLxh_5HpkN5xAJrNEeVD_DZa6-ktlfW7CqnNXgo,5400
24
+ aigency-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ aigency-0.1.0.dist-info/top_level.txt,sha256=nr33Htucgjs3wJFNugPV8w7b9ZgSnytxCtRiinR3eb8,8
26
+ aigency-0.1.0.dist-info/RECORD,,