jaf-py 2.4.2__tar.gz → 2.4.4__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.
Files changed (128) hide show
  1. {jaf_py-2.4.2 → jaf_py-2.4.4}/PKG-INFO +1 -1
  2. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/engine.py +6 -4
  3. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/tracing.py +51 -7
  4. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/types.py +1 -0
  5. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/providers/postgres.py +10 -4
  6. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/PKG-INFO +1 -1
  7. {jaf_py-2.4.2 → jaf_py-2.4.4}/pyproject.toml +1 -1
  8. {jaf_py-2.4.2 → jaf_py-2.4.4}/LICENSE +0 -0
  9. {jaf_py-2.4.2 → jaf_py-2.4.4}/README.md +0 -0
  10. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/__init__.py +0 -0
  11. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/__init__.py +0 -0
  12. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/agent.py +0 -0
  13. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/agent_card.py +0 -0
  14. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/client.py +0 -0
  15. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/__init__.py +0 -0
  16. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/client_example.py +0 -0
  17. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/integration_example.py +0 -0
  18. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/rag_demo/__init__.py +0 -0
  19. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/server_demo/__init__.py +0 -0
  20. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/examples/server_example.py +0 -0
  21. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/__init__.py +0 -0
  22. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/cleanup.py +0 -0
  23. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/factory.py +0 -0
  24. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/providers/__init__.py +0 -0
  25. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/providers/composite.py +0 -0
  26. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/providers/in_memory.py +0 -0
  27. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/providers/postgres.py +0 -0
  28. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/providers/redis.py +0 -0
  29. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/serialization.py +0 -0
  30. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/__init__.py +0 -0
  31. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/run_comprehensive_tests.py +0 -0
  32. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/test_cleanup.py +0 -0
  33. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/test_serialization.py +0 -0
  34. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/test_stress_concurrency.py +0 -0
  35. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/tests/test_task_lifecycle.py +0 -0
  36. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/memory/types.py +0 -0
  37. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/protocol.py +0 -0
  38. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/server.py +0 -0
  39. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/standalone_client.py +0 -0
  40. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/__init__.py +0 -0
  41. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/run_tests.py +0 -0
  42. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/test_agent.py +0 -0
  43. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/test_client.py +0 -0
  44. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/test_integration.py +0 -0
  45. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/test_protocol.py +0 -0
  46. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/tests/test_types.py +0 -0
  47. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/a2a/types.py +0 -0
  48. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/cli.py +0 -0
  49. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/__init__.py +0 -0
  50. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/agent_tool.py +0 -0
  51. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/analytics.py +0 -0
  52. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/composition.py +0 -0
  53. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/errors.py +0 -0
  54. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/performance.py +0 -0
  55. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/proxy.py +0 -0
  56. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/proxy_helpers.py +0 -0
  57. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/state.py +0 -0
  58. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/streaming.py +0 -0
  59. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/tool_results.py +0 -0
  60. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/tools.py +0 -0
  61. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/core/workflows.py +0 -0
  62. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/exceptions.py +0 -0
  63. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/__init__.py +0 -0
  64. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/approval_storage.py +0 -0
  65. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/factory.py +0 -0
  66. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/providers/__init__.py +0 -0
  67. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/providers/in_memory.py +0 -0
  68. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/providers/redis.py +0 -0
  69. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/types.py +0 -0
  70. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/memory/utils.py +0 -0
  71. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/plugins/__init__.py +0 -0
  72. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/plugins/base.py +0 -0
  73. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/policies/__init__.py +0 -0
  74. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/policies/handoff.py +0 -0
  75. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/policies/validation.py +0 -0
  76. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/providers/__init__.py +0 -0
  77. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/providers/mcp.py +0 -0
  78. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/providers/model.py +0 -0
  79. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/server/__init__.py +0 -0
  80. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/server/main.py +0 -0
  81. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/server/server.py +0 -0
  82. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/server/types.py +0 -0
  83. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/utils/__init__.py +0 -0
  84. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/utils/attachments.py +0 -0
  85. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/utils/document_processor.py +0 -0
  86. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/__init__.py +0 -0
  87. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/example.py +0 -0
  88. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/functional_core.py +0 -0
  89. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/graphviz.py +0 -0
  90. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/imperative_shell.py +0 -0
  91. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf/visualization/types.py +0 -0
  92. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/SOURCES.txt +0 -0
  93. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/dependency_links.txt +0 -0
  94. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/entry_points.txt +0 -0
  95. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/requires.txt +0 -0
  96. {jaf_py-2.4.2 → jaf_py-2.4.4}/jaf_py.egg-info/top_level.txt +0 -0
  97. {jaf_py-2.4.2 → jaf_py-2.4.4}/setup.cfg +0 -0
  98. {jaf_py-2.4.2 → jaf_py-2.4.4}/setup.py +0 -0
  99. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_a2a_deep.py +0 -0
  100. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_a2a_examples.py +0 -0
  101. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_api_reference_examples.py +0 -0
  102. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_attachments.py +0 -0
  103. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_callback_system_examples.py +0 -0
  104. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_coffee_tool.py +0 -0
  105. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_conversation_id_fix.py +0 -0
  106. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_deployment_examples.py +0 -0
  107. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_docs_code_examples.py +0 -0
  108. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_engine.py +0 -0
  109. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_engine_manual.py +0 -0
  110. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_error_handling_examples.py +0 -0
  111. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_getting_started_examples.py +0 -0
  112. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_math_tool.py +0 -0
  113. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_mcp_comprehensive.py +0 -0
  114. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_mcp_docs.py +0 -0
  115. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_mcp_real_functionality.py +0 -0
  116. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_mcp_transports.py +0 -0
  117. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_memory_system_examples.py +0 -0
  118. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_model_providers_examples.py +0 -0
  119. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_property_based.py +0 -0
  120. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_proxy_simple.py +0 -0
  121. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_redis_fixes.py +0 -0
  122. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_redis_memory.py +0 -0
  123. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_server_api_examples.py +0 -0
  124. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_session_continuity.py +0 -0
  125. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_streamable_http_mcp_example.py +0 -0
  126. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_timeout_functionality.py +0 -0
  127. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_tool_integration.py +0 -0
  128. {jaf_py-2.4.2 → jaf_py-2.4.4}/tests/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jaf-py
3
- Version: 2.4.2
3
+ Version: 2.4.4
4
4
  Summary: A purely functional agent framework with immutable state and composable tools - Python implementation
5
5
  Author: JAF Contributors
6
6
  Maintainer: JAF Contributors
@@ -174,16 +174,18 @@ async def run(
174
174
  from .agent_tool import set_current_run_config
175
175
  set_current_run_config(config)
176
176
 
177
+ state_with_memory = await _load_conversation_history(initial_state, config)
178
+
179
+ # Emit RunStartEvent AFTER loading conversation history so we have complete context
177
180
  if config.on_event:
178
181
  config.on_event(RunStartEvent(data=to_event_data(RunStartEventData(
179
182
  run_id=initial_state.run_id,
180
183
  trace_id=initial_state.trace_id,
181
184
  session_id=config.conversation_id,
182
- context=initial_state.context,
183
- messages=initial_state.messages
185
+ context=state_with_memory.context,
186
+ messages=state_with_memory.messages, # Now includes full conversation history
187
+ agent_name=state_with_memory.current_agent_name
184
188
  ))))
185
-
186
- state_with_memory = await _load_conversation_history(initial_state, config)
187
189
 
188
190
  # Load approvals from storage if configured
189
191
  if config.approval_storage:
@@ -419,11 +419,24 @@ class LangfuseTraceCollector:
419
419
  for i in range(len(messages) - 1, -1, -1):
420
420
  msg = messages[i]
421
421
 
422
+ # Extract message data comprehensively
423
+ msg_data = {}
424
+
422
425
  if isinstance(msg, dict):
423
426
  role = msg.get("role")
424
427
  content = msg.get("content", "")
428
+ # Capture all additional fields from dict messages
429
+ msg_data = {
430
+ "role": role,
431
+ "content": content,
432
+ "tool_calls": msg.get("tool_calls"),
433
+ "tool_call_id": msg.get("tool_call_id"),
434
+ "name": msg.get("name"),
435
+ "function_call": msg.get("function_call"),
436
+ "timestamp": msg.get("timestamp", datetime.now().isoformat())
437
+ }
425
438
  elif hasattr(msg, 'role'):
426
- role = msg.role
439
+ role = getattr(msg, 'role', None)
427
440
  content = getattr(msg, 'content', "")
428
441
  # Handle both string content and complex content structures
429
442
  if not isinstance(content, str):
@@ -436,9 +449,25 @@ class LangfuseTraceCollector:
436
449
  content = str(content)
437
450
  else:
438
451
  content = str(content)
452
+
453
+ # Capture all additional fields from object messages
454
+ msg_data = {
455
+ "role": role,
456
+ "content": content,
457
+ "tool_calls": getattr(msg, 'tool_calls', None),
458
+ "tool_call_id": getattr(msg, 'tool_call_id', None),
459
+ "name": getattr(msg, 'name', None),
460
+ "function_call": getattr(msg, 'function_call', None),
461
+ "timestamp": getattr(msg, 'timestamp', datetime.now().isoformat())
462
+ }
439
463
  else:
464
+ # Handle messages that don't have expected structure
465
+ print(f"[LANGFUSE DEBUG] Skipping message with unexpected structure: {type(msg)}")
440
466
  continue
441
467
 
468
+ # Clean up None values from msg_data
469
+ msg_data = {k: v for k, v in msg_data.items() if v is not None}
470
+
442
471
  # If we haven't found the current user message yet and this is a user message
443
472
  if not current_user_message_found and (role == "user" or role == 'user'):
444
473
  user_query = content
@@ -446,15 +475,29 @@ class LangfuseTraceCollector:
446
475
  print(f"[LANGFUSE DEBUG] Found current user query: {user_query}")
447
476
  elif current_user_message_found:
448
477
  # Add to conversation history (excluding the current user message)
449
- conversation_history.insert(0, {
450
- "role": role,
451
- "content": content,
452
- "timestamp": datetime.now().isoformat() if not hasattr(msg, 'timestamp') else getattr(msg, 'timestamp', datetime.now().isoformat())
453
- })
478
+ # Include ALL message types: assistant, tool, system, function, etc.
479
+ conversation_history.insert(0, msg_data)
480
+ print(f"[LANGFUSE DEBUG] Added to conversation history: role={role}, content_length={len(str(content))}, has_tool_calls={bool(msg_data.get('tool_calls'))}")
454
481
 
455
482
  print(f"[LANGFUSE DEBUG] Final extracted - user_query: {user_query}, user_id: {user_id}")
456
483
  print(f"[LANGFUSE DEBUG] Conversation history length: {len(conversation_history)}")
457
484
 
485
+ # Debug: Log the roles and types captured in conversation history
486
+ if conversation_history:
487
+ roles_summary = {}
488
+ for msg in conversation_history:
489
+ role = msg.get("role", "unknown")
490
+ roles_summary[role] = roles_summary.get(role, 0) + 1
491
+ print(f"[LANGFUSE DEBUG] Conversation history roles breakdown: {roles_summary}")
492
+
493
+ # Log first few messages for verification
494
+ for i, msg in enumerate(conversation_history[:3]):
495
+ role = msg.get("role", "unknown")
496
+ content_preview = str(msg.get("content", ""))[:100]
497
+ has_tool_calls = bool(msg.get("tool_calls"))
498
+ has_tool_call_id = bool(msg.get("tool_call_id"))
499
+ print(f"[LANGFUSE DEBUG] History msg {i}: role={role}, content='{content_preview}...', tool_calls={has_tool_calls}, tool_call_id={has_tool_call_id}")
500
+
458
501
  # Create comprehensive input data for the trace
459
502
  trace_input = {
460
503
  "user_query": user_query,
@@ -495,6 +538,7 @@ class LangfuseTraceCollector:
495
538
  print(f"[LANGFUSE] Ending trace for run: {trace_id}")
496
539
 
497
540
  # Update the trace metadata with final tool calls and results
541
+ conversation_history = getattr(self.trace_spans[trace_id], '_conversation_history', [])
498
542
  final_metadata = {
499
543
  "framework": "jaf",
500
544
  "event_type": "run_end",
@@ -502,7 +546,7 @@ class LangfuseTraceCollector:
502
546
  "user_query": getattr(self.trace_spans[trace_id], '_user_query', None),
503
547
  "user_id": getattr(self.trace_spans[trace_id], '_user_id', None),
504
548
  "agent_name": event.data.get("agent_name", "analytics_agent_jaf"),
505
- "conversation_history": getattr(self.trace_spans[trace_id], '_conversation_history', []),
549
+ "conversation_history": conversation_history,
506
550
  "tool_calls": self.trace_tool_calls.get(trace_id, []),
507
551
  "tool_results": self.trace_tool_results.get(trace_id, [])
508
552
  }
@@ -490,6 +490,7 @@ class RunStartEventData:
490
490
  session_id: Optional[str] = None
491
491
  context: Optional[Any] = None
492
492
  messages: Optional[List[Message]] = None
493
+ agent_name: Optional[str] = None
493
494
 
494
495
  @dataclass(frozen=True)
495
496
  class RunStartEvent:
@@ -261,16 +261,22 @@ async def create_postgres_provider(config: PostgresConfig) -> Result[PostgresPro
261
261
  # but we can continue and hope the database already exists.
262
262
  print(f"Could not ensure database exists: {e}")
263
263
 
264
- # Now connect to the target database
264
+ # Now connect to the target database using connection pool with max_connections
265
265
  if config.connection_string:
266
- client = await asyncpg.connect(dsn=config.connection_string)
266
+ client = await asyncpg.create_pool(
267
+ dsn=config.connection_string,
268
+ min_size=1,
269
+ max_size=config.max_connections
270
+ )
267
271
  else:
268
- client = await asyncpg.connect(
272
+ client = await asyncpg.create_pool(
269
273
  host=config.host,
270
274
  port=config.port,
271
275
  user=config.username,
272
276
  password=config.password,
273
- database=config.database
277
+ database=config.database,
278
+ min_size=1,
279
+ max_size=config.max_connections
274
280
  )
275
281
 
276
282
  table_name = config.table_name or "conversations"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jaf-py
3
- Version: 2.4.2
3
+ Version: 2.4.4
4
4
  Summary: A purely functional agent framework with immutable state and composable tools - Python implementation
5
5
  Author: JAF Contributors
6
6
  Maintainer: JAF Contributors
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jaf-py"
7
- version = "2.4.2"
7
+ version = "2.4.4"
8
8
  description = "A purely functional agent framework with immutable state and composable tools - Python implementation"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes