From 811d4fd175033a6ab96e96671062b402c70e5bff Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Mon, 7 Sep 2026 20:17:01 -0300 Subject: [PATCH] bugfix reconciliation extractor --- .../__pycache__/__init__.cpython-313.pyc | Bin 412 -> 411 bytes .../__pycache__/extensions.cpython-313.pyc | Bin 2140 -> 2139 bytes .../__pycache__/idempotency.cpython-313.pyc | Bin 8913 -> 8912 bytes .../__pycache__/observer.cpython-313.pyc | Bin 17556 -> 17555 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 548 -> 547 bytes .../composite_publisher.cpython-313.pyc | Bin 2503 -> 2502 bytes .../__pycache__/event_builder.cpython-313.pyc | Bin 1261 -> 1260 bytes .../__pycache__/factory.cpython-313.pyc | Bin 3997 -> 3996 bytes .../__pycache__/publisher.cpython-313.pyc | Bin 1873 -> 1872 bytes .../tim_payload_mapper.cpython-313.pyc | Bin 9287 -> 9286 bytes .../__pycache__/tim_sequence.cpython-313.pyc | Bin 17562 -> 17561 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 515 -> 514 bytes .../__pycache__/kafka.cpython-313.pyc | Bin 1813 -> 1812 bytes .../__pycache__/langfuse.cpython-313.pyc | Bin 23173 -> 23172 bytes .../__pycache__/oci_streaming.cpython-313.pyc | Bin 1822 -> 1821 bytes .../__pycache__/pubsub.cpython-313.pyc | Bin 7441 -> 7440 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 404 -> 403 bytes .../usage_repository.cpython-313.pyc | Bin 15687 -> 15686 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 214 -> 213 bytes .../cache/__pycache__/cache.cpython-313.pyc | Bin 16524 -> 16523 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 217 -> 216 bytes .../__pycache__/adapters.cpython-313.pyc | Bin 4173 -> 4172 bytes .../channels/__pycache__/base.cpython-313.pyc | Bin 1797 -> 1796 bytes .../__pycache__/gateway.cpython-313.pyc | Bin 5772 -> 5771 bytes .../__pycache__/interruption.cpython-313.pyc | Bin 6457 -> 6456 bytes .../__pycache__/transcription.cpython-313.pyc | Bin 1430 -> 1429 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 924 -> 923 bytes .../checkpoint_repository.cpython-313.pyc | Bin 27164 -> 27163 bytes .../langgraph_saver.cpython-313.pyc | Bin 33266 -> 33265 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 215 -> 214 bytes .../agent_registry.cpython-313.pyc | Bin 6948 -> 6947 bytes .../__pycache__/settings.cpython-313.pyc | Bin 13790 -> 13789 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 307 -> 306 bytes .../mcp_gateway_client.cpython-313.pyc | Bin 3333 -> 3332 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1501 -> 1501 bytes .../__pycache__/base.cpython-313.pyc | Bin 1375 -> 1375 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 9160 -> 9160 bytes .../__pycache__/custom_rails.cpython-313.pyc | Bin 4404 -> 4404 bytes .../framework_llm_client.cpython-313.pyc | Bin 19673 -> 19673 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 5923 -> 5923 bytes .../output_supervisor.cpython-313.pyc | Bin 24306 -> 24306 bytes .../parallel_executor.cpython-313.pyc | Bin 21862 -> 21862 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 10889 -> 10889 bytes .../__pycache__/rail_action.cpython-313.pyc | Bin 654 -> 654 bytes .../__pycache__/rail_decision.cpython-313.pyc | Bin 1605 -> 1605 bytes .../__pycache__/rail_result.cpython-313.pyc | Bin 1004 -> 1004 bytes .../__pycache__/rails.cpython-313.pyc | Bin 43324 -> 43324 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 2994 -> 2994 bytes .../__pycache__/_compat.cpython-313.pyc | Bin 2445 -> 2445 bytes .../contestation_validation.cpython-313.pyc | Bin 2177 -> 2177 bytes .../__pycache__/contracts.cpython-313.pyc | Bin 6901 -> 6901 bytes .../__pycache__/input_size.cpython-313.pyc | Bin 3649 -> 3649 bytes .../__pycache__/llm_adapter.cpython-313.pyc | Bin 3799 -> 3799 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 7454 -> 7454 bytes .../__pycache__/llm_rails.cpython-313.pyc | Bin 8894 -> 8894 bytes .../output_sanitization.cpython-313.pyc | Bin 13910 -> 13910 bytes .../__pycache__/pipeline.cpython-313.pyc | Bin 12661 -> 12661 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 473 -> 473 bytes .../__pycache__/_context.cpython-313.pyc | Bin 5871 -> 5871 bytes .../ausencia_oferta_proativa.cpython-313.pyc | Bin 12205 -> 12205 bytes .../__pycache__/coerencia.cpython-313.pyc | Bin 4157 -> 4157 bytes .../__pycache__/dlex_in.cpython-313.pyc | Bin 1304 -> 1304 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 1815 -> 1815 bytes .../dlex_out.cpython-313.pyc.128272546232176 | 0 .../__pycache__/fallback.cpython-313.pyc | Bin 17652 -> 17652 bytes .../__pycache__/fraseologia.cpython-313.pyc | Bin 7633 -> 7633 bytes .../__pycache__/out_of_scope.cpython-313.pyc | Bin 17493 -> 17493 bytes .../prompts/__pycache__/pinj.cpython-313.pyc | Bin 8424 -> 8424 bytes .../__pycache__/ragsec.cpython-313.pyc | Bin 1120 -> 1120 bytes .../__pycache__/revprec.cpython-313.pyc | Bin 3150 -> 3150 bytes .../prompts/__pycache__/tox.cpython-313.pyc | Bin 644 -> 644 bytes .../toxicidade_output.cpython-313.pyc | Bin 928 -> 928 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1663 -> 1663 bytes .../rails/__pycache__/alcada.cpython-313.pyc | Bin 4999 -> 4999 bytes .../rails/__pycache__/anatel.cpython-313.pyc | Bin 9148 -> 9148 bytes .../__pycache__/confirmation.cpython-313.pyc | Bin 11042 -> 11042 bytes .../rails/__pycache__/dlex_in.cpython-313.pyc | Bin 3279 -> 3279 bytes .../__pycache__/dlex_out.cpython-313.pyc | Bin 3331 -> 3331 bytes .../rails/__pycache__/ragsec.cpython-313.pyc | Bin 5462 -> 5462 bytes .../rails/__pycache__/revprec.cpython-313.pyc | Bin 5470 -> 5470 bytes .../rails/__pycache__/tox.cpython-313.pyc | Bin 8293 -> 8293 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 533 -> 533 bytes .../rules/__pycache__/alcada.cpython-313.pyc | Bin 1881 -> 1881 bytes .../__pycache__/pinj_patterns.cpython-313.pyc | Bin 3730 -> 3730 bytes .../__pycache__/tox_blocklist.cpython-313.pyc | Bin 1506 -> 1506 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 409 -> 408 bytes .../__pycache__/mcp_mapper.cpython-313.pyc | Bin 4693 -> 4692 bytes .../__pycache__/models.cpython-313.pyc | Bin 3145 -> 3144 bytes .../__pycache__/resolver.cpython-313.pyc | Bin 4714 -> 4713 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 619 -> 618 bytes .../judges/__pycache__/judge.cpython-313.pyc | Bin 41126 -> 41125 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 226 -> 225 bytes .../__pycache__/llm_client.cpython-313.pyc | Bin 5405 -> 5404 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 234 -> 233 bytes .../prompts/__pycache__/aluc.cpython-313.pyc | Bin 6530 -> 6529 bytes .../prompts/__pycache__/csi.cpython-313.pyc | Bin 1333 -> 1332 bytes .../__pycache__/fallback.cpython-313.pyc | Bin 8036 -> 8035 bytes .../prompts/__pycache__/rqlt.cpython-313.pyc | Bin 1166 -> 1165 bytes .../prompts/__pycache__/vctn.cpython-313.pyc | Bin 627 -> 626 bytes .../llm/__pycache__/__init__.cpython-313.pyc | Bin 477 -> 476 bytes .../llm/__pycache__/base.cpython-313.pyc | Bin 1624 -> 1623 bytes .../profile_resolver.cpython-313.pyc | Bin 9323 -> 9322 bytes .../llm/__pycache__/providers.cpython-313.pyc | Bin 46979 -> 46978 bytes .../structured_output.cpython-313.pyc | Bin 7460 -> 7459 bytes .../llm/__pycache__/types.cpython-313.pyc | Bin 1275 -> 1274 bytes .../mcp/__pycache__/__init__.cpython-313.pyc | Bin 474 -> 473 bytes .../mcp/__pycache__/client.cpython-313.pyc | Bin 18427 -> 18426 bytes .../mcp/__pycache__/models.cpython-313.pyc | Bin 2137 -> 2136 bytes .../mcp/__pycache__/registry.cpython-313.pyc | Bin 4741 -> 4740 bytes .../__pycache__/tool_policy.cpython-313.pyc | Bin 5686 -> 5685 bytes .../__pycache__/tool_router.cpython-313.pyc | Bin 14190 -> 14189 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1136 -> 1135 bytes .../long_term_extractor.cpython-313.pyc | Bin 2514 -> 2513 bytes .../long_term_memory.cpython-313.pyc | Bin 6840 -> 6839 bytes .../long_term_models.cpython-313.pyc | Bin 1749 -> 1748 bytes .../long_term_store.cpython-313.pyc | Bin 29187 -> 29186 bytes .../message_history.cpython-313.pyc | Bin 8360 -> 8359 bytes .../summary_memory.cpython-313.pyc | Bin 12511 -> 12510 bytes .../__pycache__/summary_store.cpython-313.pyc | Bin 9521 -> 9520 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 215 -> 214 bytes .../__pycache__/identity.cpython-313.pyc | Bin 3466 -> 3465 bytes .../__pycache__/session.cpython-313.pyc | Bin 2709 -> 2708 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 1395 -> 1394 bytes .../__pycache__/code_mapper.cpython-313.pyc | Bin 21448 -> 21447 bytes .../__pycache__/context.cpython-313.pyc | Bin 7387 -> 7386 bytes .../__pycache__/event_bus.cpython-313.pyc | Bin 3633 -> 3632 bytes .../guardrail_events.cpython-313.pyc | Bin 2051 -> 2050 bytes .../__pycache__/ic_events.cpython-313.pyc | Bin 626 -> 625 bytes .../__pycache__/judge_events.cpython-313.pyc | Bin 1411 -> 1410 bytes .../langgraph_telemetry.cpython-313.pyc | Bin 4964 -> 4963 bytes .../__pycache__/llm_advisors.cpython-313.pyc | Bin 2938 -> 2937 bytes .../__pycache__/noc_contract.cpython-313.pyc | Bin 5075 -> 5074 bytes .../__pycache__/noc_otel.cpython-313.pyc | Bin 6322 -> 6321 bytes .../__pycache__/observer.cpython-313.pyc | Bin 5105 -> 5104 bytes .../__pycache__/otel.cpython-313.pyc | Bin 3412 -> 3411 bytes .../streaming_events.cpython-313.pyc | Bin 1835 -> 1834 bytes .../__pycache__/telemetry.cpython-313.pyc | Bin 52428 -> 52427 bytes .../__pycache__/token_cost.cpython-313.pyc | Bin 8691 -> 8690 bytes .../workflow_events.cpython-313.pyc | Bin 3330 -> 3329 bytes .../oci/__pycache__/__init__.cpython-313.pyc | Bin 212 -> 211 bytes .../oci/__pycache__/auth.cpython-313.pyc | Bin 3244 -> 3243 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 220 -> 219 bytes .../__pycache__/oracle_store.cpython-313.pyc | Bin 45932 -> 45931 bytes .../__pycache__/sqlite_store.cpython-313.pyc | Bin 15019 -> 15018 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 455 -> 454 bytes .../__pycache__/renderers.cpython-313.pyc | Bin 4318 -> 4317 bytes .../rag/__pycache__/__init__.cpython-313.pyc | Bin 710 -> 709 bytes .../embedding_provider.cpython-313.pyc | Bin 6517 -> 6516 bytes .../__pycache__/graph_store.cpython-313.pyc | Bin 5528 -> 5527 bytes .../rag/__pycache__/ingest.cpython-313.pyc | Bin 12581 -> 12580 bytes .../__pycache__/kbdb_service.cpython-313.pyc | Bin 10012 -> 10011 bytes .../__pycache__/rag_service.cpython-313.pyc | Bin 10898 -> 10897 bytes .../__pycache__/vector_store.cpython-313.pyc | Bin 18656 -> 18655 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 221 -> 220 bytes .../session_repository.cpython-313.pyc | Bin 8590 -> 8589 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 426 -> 425 bytes .../__pycache__/config_loader.cpython-313.pyc | Bin 2297 -> 2296 bytes .../__pycache__/continuity.cpython-313.pyc | Bin 15934 -> 15933 bytes .../enterprise_router.cpython-313.pyc | Bin 61972 -> 61971 bytes .../__pycache__/models.cpython-313.pyc | Bin 2447 -> 2446 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 348 -> 348 bytes .../__pycache__/agent_runtime.cpython-313.pyc | Bin 200597 -> 206069 bytes .../transaction_parameters.cpython-313.pyc | Bin 14476 -> 26391 bytes .../agent_framework/runtime/agent_runtime.py | 136 +++++++- .../runtime/transaction_parameters.py | 216 +++++++++++- .../sse/__pycache__/__init__.cpython-313.pyc | Bin 212 -> 211 bytes .../sse/__pycache__/events.cpython-313.pyc | Bin 9588 -> 9587 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 219 -> 218 bytes .../__pycache__/supervisor.cpython-313.pyc | Bin 4944 -> 4943 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 879 -> 878 bytes .../__pycache__/graph.cpython-313.pyc | Bin 1416 -> 1415 bytes .../input_contract.cpython-313.pyc | Bin 8791 -> 8790 bytes .../__pycache__/models.cpython-313.pyc | Bin 7670 -> 7669 bytes .../__pycache__/registry.cpython-313.pyc | Bin 2362 -> 2361 bytes .../__pycache__/repository.cpython-313.pyc | Bin 2715 -> 2714 bytes .../__pycache__/runtime.cpython-313.pyc | Bin 36153 -> 36152 bytes .../__pycache__/tool_executor.cpython-313.pyc | Bin 1967 -> 1966 bytes ...ntextual_reentry_transaction_parameters.py | 313 ++++++++++++++++++ ...st_transaction_parameter_llm_precedence.py | 95 ++++++ .../tests/test_transactional_tool_flow.py | 91 +++++ .../__pycache__/__init__.cpython-313.pyc | Bin 158 -> 157 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 166 -> 165 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 184 -> 183 bytes .../authorized_lines_service.cpython-313.pyc | Bin 4936 -> 4935 bytes .../discount_history_service.cpython-313.pyc | Bin 4880 -> 4879 bytes .../__pycache__/line_policy.cpython-313.pyc | Bin 3073 -> 3072 bytes .../__pycache__/main.cpython-313.pyc | Bin 94453 -> 96148 bytes contas_mcp/servers/contas_mcp_server/main.py | 78 ++++- ...ESTATION_RELATIONAL_RESOLUTION_20260907.md | 15 + ...IX_RECONCILIACAO_REWORK_MINIMO_20260907.md | 19 ++ ..._contestation_resolved_value_relational.py | 90 +++++ ..._contestation_subject_entity_resolution.py | 4 +- .../test_requested_tools_parity_pente_fino.py | 10 +- ...t_subject_entity_resolution_all_domains.py | 5 +- 194 files changed, 1031 insertions(+), 41 deletions(-) create mode 100644 agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc.128272546232176 create mode 100644 docs/FIX_CONTESTATION_RELATIONAL_RESOLUTION_20260907.md create mode 100644 docs/FIX_RECONCILIACAO_REWORK_MINIMO_20260907.md create mode 100644 tests/migration/test_contestation_resolved_value_relational.py diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/__init__.cpython-313.pyc index dd2ef206b629071b9100effdd8bc62016e5b34f0..48ae02cc3a77f740817e8f5d306f46193d70a609 100644 GIT binary patch delta 35 pcmbQkJe!&OGcPX}0}z-!nKzO9J$IgdZeEFgioS2K=VUgsCJx{)VZeEFgvc6++Y4K!M#%Tb-5eq2* diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/extensions.cpython-313.pyc index 3c4a8cde693c53b8af55ef135d40457278ed706e..e226376dc0d25f9a5e039727b3950acce319bbd7 100644 GIT binary patch delta 37 rcmca3a9e=;GcPX}0}z-!nYWQ!g_*lRKR2&LKSkd+*mJWrvmz@1&D9D} delta 38 scmcaDa7TdqGcPX}0}zCrowku%g_);NKR2&LKUv?gxU_h)6|*8M0NdIN1ONa4 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/idempotency.cpython-313.pyc index 7c1f07aa6f5469aead0953ba621e46835b350a85..f7069c7be7bd0a4aebdd2ba11549e2124a5a9945 100644 GIT binary patch delta 37 rcmccUdcl?ZGcPX}0}z-!nYWSKjhVYpKR2&LKSkd+*mH9%bBR0v-5Cp3 delta 38 scmccMdeN2pGcPX}0}zCrowkwNjhUxNKR2&LKUv?gxU_h440DM*0PB?u3IG5A diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/__pycache__/observer.cpython-313.pyc index 16c60ca26a2f2f4ab837a772c4cd4037d70c96e1..94671244184603a23651a2b205c6f16aba72ee90 100644 GIT binary patch delta 39 tcmbQz$vC-_k^3_*FBbz4m_3=dkvpA@J5N71uS7pZ-#6HEa~+$Q9RTE!3v2)Y delta 40 ucmbQ-$vCBxk^3_*FBbz4gq@wXkvpA@Ctp7|uS7pt-?6x~cyleAm>mG~Jq#cK diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/__init__.cpython-313.pyc index f90a6c2e8bd31fe9971df572aefa712d317b8715..63bd5648e0911fc2187e451f5f25d091fc094e71 100644 GIT binary patch delta 36 qcmZ3&vY3VYGcPX}0}z-$nYWQUi;=rRKR2&LKSkd+*mH6t<6;1}E(*2) delta 37 rcmZ3?vV?{EGcPX}0}zCtowkuXi;<^NKR2&LKUv?gxU_h31LI-<#6$~f diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/composite_publisher.cpython-313.pyc index d80e9263b47b00c062f15230a548265a771cf263..f5cf6027ccb24dd24c04bf10eb069b9afddce0b3 100644 GIT binary patch delta 37 rcmX>ud`y`8GcPX}0}z-$nYWR9ITLrYer{fgeu}md|a6OGcPX}0}zCtowkvCITKHder{fgezLw}acS}9y-b|!0OSA*;s5{u diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/event_builder.cpython-313.pyc index f26065c252ec97901cd89f82dc680a9da0d927c6..a2b9a990b7ee95ebc11f717fe5d8a27ac5c19319 100644 GIT binary patch delta 37 rcmaFM`G%AGGcPX}0}z-$nYWSq1rv9zer{fgeu}cae|#GcPX}0}zCtowkwt5ED<8er{fgezLw}acS}98%z}}0O&Ogga7~l diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/__pycache__/tim_payload_mapper.cpython-313.pyc index d60075e3db794c79e28f718679d05e224e663d05..10d4565491e15c0db120f29daa25c877c0623ece 100644 GIT binary patch delta 37 rcmX@^am<7JGcPX}0}z-$nYWRX=362%*)Hg00ibw=56G*XXI|u&&?~*Pto@c_M9BXxE27bK?*Ve delta 37 rcmZo-X=dU6%*)Hg00iM@r)}i6XXI(t&&?~*Pu6!VE-juM%D5H)xAY3; diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/kafka.cpython-313.pyc index b84fe312abf9458fe51dac50a890335db40ba060..61b559d98285ac2e3f20101819751fb6b03c656c 100644 GIT binary patch delta 37 rcmbQrH-(S;GcPX}0}z-$nYWSKfr-0bKR2&LKSkd+*mH9@(>@jez5xoL delta 38 scmbQjH delta 40 ucmZqK%GkPJ0N9BO=l}o! diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/analytics/providers/__pycache__/pubsub.cpython-313.pyc index b3e70975cb6f15c1b0d7dfee8aa95907a776470e..a0a778add95c9a94a4791f8525eb6875f91dd7bf 100644 GIT binary patch delta 37 rcmbPeHNlGeGcPX}0}z-$nYWSq9S3)Ver{fgeu}sCF;BUEZeEFgvc6++Y4OCLvjDa43<>}M diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/billing/__pycache__/usage_repository.cpython-313.pyc index 8fe711565190e828d5e6ae19e9d406ffaf0e5842..02a772b1a04a2af907bd5830f8c7336b13f5f0d3 100644 GIT binary patch delta 37 rcmX?Jb*zf}GcPX}0}z-$nYWQUkDa?tKR2&LKSkd+*mH9$`yo>R?oAAK delta 38 scmX?Bb-arEGcPX}0}zCrowkuXkDaGpKR2&LKUv?gxU_h43;Q8c0R2D>DF6Tf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/cache/__pycache__/__init__.cpython-313.pyc index a0808ef17b677bca4bea04f460f20f9e94d9e58c..390cc71b06530e7817938f766b8d509385fb4818 100644 GIT binary patch delta 34 ocmcb{c$Ja+GcPX}0}z-$nKzN!n7c$jH?KrLMc+5rbD~!d0Ig~YX8-^I delta 35 pcmcc0c#Vr%n5R@fH?KrLS>Lg^w0NRt4*E74EU_YL;kti_aM2LRad3hV#? delta 40 ucmeBfWbA2Vr%n5RNNH?KrLS>Lg^w0NRtKLEP33nl;n diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/adapters.cpython-313.pyc index e099198789afb696318821a538114d3e68f42069..c00a5b272a605dfb5b4135cf3f6e38d24c8f8258 100644 GIT binary patch delta 37 rcmX@Ba7KaqGcPX}0}z-$nYWSqEE9LRer{fgeu}pPN^rpRDg#Tw1(&EBiG*0NR@jU;qFB diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc index f51d600e8163d915c377dcad1592b25e077ba070..27509e5226b87788908feecd9183712173fdf279 100644 GIT binary patch delta 37 rcmdmKw8Mz|GcPX}0}z-$nYWR98WVT5er{fgeu}m*3M()qNyj%=GVD@C*Ms8(h?som$yb}Esecxcu%~s5h(g68E43Pi; delta 40 ucmbPzg>lXmM()qNyj%=G5O#LjMs8(ho(}!oyb}FneaGU`;?0)KkJ11LbPYuS diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/checkpoints/__pycache__/langgraph_saver.cpython-313.pyc index 2c808c8d433c84d649e120f6f213034fe636363b..ddb3a98758acd0284e4320413c7f5c1667b66b74 100644 GIT binary patch delta 39 tcmey=%=EFDiTg7zFBbz4m_3=dk$W2xccXr8UWtB+zHhMS=Ce$y^#BJC4Hp0a delta 40 ucmey^%=D?5iTg7zFBbz4gq@wXk$W2xPm_LbUWtCPzGHD|@#Zs3s`UUC%MHr_ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/__init__.cpython-313.pyc index c2ae0f81294ca94363cbd776d8a34eaa2172b599..e1c89b73895b6c941a48d57cf8c50c26d5f48a4c 100644 GIT binary patch delta 34 ocmcc4c#Vr%n5RrXH?KrLS>Lg^w0NRtF95m=3myOf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/agent_registry.cpython-313.pyc index ac1c17ec433b6347038f316db15a65e2a33fbcf3..30f2c6e93b7fda83eb7dcb8e8b35c4d805129549 100644 GIT binary patch delta 37 rcmZ2tw%CmOGcPX}0}z-!nYWSKk(s+%KR2&LKSkd+*mH9P^BHjf%`6Kp delta 38 scmZ2%w#1D4GcPX}0}zCrowkwNk(sAPKR2&LKUv?gxU_h4IP)2C0NXVS;s5{u diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/config/__pycache__/settings.cpython-313.pyc index 1678ae97a96e7b027ba090b5b9d7dbad601a87b2..a8ca03d6359f1f9914a38f539eb5cba7aec1cfcc 100644 GIT binary patch delta 37 rcmcbYeK(u?GcPX}0}z-!nYWQUN{hQxKR2&LKSkd+*mHBCRxURH@Ink5 delta 38 scmcbceJ`8)GcPX}0}zCrowkuXN{gpVKR2&LKUv?gxU_h4fmSXz0RLkQ&j0`b diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/__init__.cpython-313.pyc index 7dcc5682ec8eb6609ca9e90b670352caee6688ee..a141cbf373aba63edd1311a7949d54b2e13b4f73 100644 GIT binary patch delta 34 ocmdnYw26uPGcPX}0}z-!nKzNUiMw1sH?KrLMc+5rbK=Zd0IF3A(EtDd delta 35 pcmdnQw3&(fGcPX}0}zCtoi>rXiKjw8H?KrLS>Lg^w0Po-Spc@%3x)sy diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/gateways/__pycache__/mcp_gateway_client.cpython-313.pyc index a661b749a58696e7cefeec919beb367dfeaa480c..2af9c0f71e841b165fd05eb4d7bf448e04ca8605 100644 GIT binary patch delta 37 rcmZpbYLVjp%*)Hg00d@F=56FY!N}dHpPN^rpQ7&@?78_qqZ&5=$IA;A delta 38 scmZpXYL(*t%*)Hg00iM@r)}gu!N}93pPN^rpRDg#Tw1*O9-|sJ0M-Hv%K!iX diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/__init__.cpython-313.pyc index bc07267eb827d1aee88907ef46a6e8f889f788d2..a2e6750037948dc967dd3ce4f8c2dfc2cf6894a0 100644 GIT binary patch delta 20 acmcc1eV3d2GcPX}0}z-!nYWSq5-R{fs0Ka& delta 20 acmcc1eV3d2GcPX}0}w>I%-G0%i4_1ozXiJh diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/base.cpython-313.pyc index 50fd70a42aaadee7f47df7e732c6dbe7828c045f..60404b2140461d38fcb1aba278d164a2aabfda8b 100644 GIT binary patch delta 20 acmcc5b)Sp-GcPX}0}z-!nYWQUgcSfl)CIx- delta 20 acmcc5b)Sp-GcPX}0}w>I%-F~s!U_OA>jggm diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/config_loader.cpython-313.pyc index 868b18d1c68ef28ae7b7788843ff58f67e7b3512..a676c72eb10910de031fea561ea492f01ecd79b0 100644 GIT binary patch delta 20 acmX@%e!`vmGcPX}0}z-!nYWR9uQC8e?go_r delta 20 acmX@%e!`vmGcPX}0}w>I%-G1iR~Z0A1qKoT diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/custom_rails.cpython-313.pyc index 5297e5ad4953625c7f5d11fa71b9483e3c353f83..15315313c1300182e2bd3d5dc508df16ffc7e75c 100644 GIT binary patch delta 20 acmdm@v_*;gGcPX}0}z-!nYWQ!QxE_>hy{HB delta 20 acmdm@v_*;gGcPX}0}w>I%-G1SDF^^Mp9J~< diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/framework_llm_client.cpython-313.pyc index 6a077d2e3b0467ea95eedd50ac46848b3dc5d928..e7e99a011f97b23e26f5f6dfbaa732b3a99048c3 100644 GIT binary patch delta 22 ccmcaPlkw(EM()qNyj%=GVD@C*M(%Sy09nKbmjD0& delta 22 ccmcaPlkw(EM()qNyj%=G5a}{wBlkHU09M-v6aWAK diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc index 70803d59f104dd23c8029ee18eda570ab42132de..760511e6676033cdb58664f37f9957c09053dc67 100644 GIT binary patch delta 20 acmZ3iw^)z+GcPX}0}z-!nYWQ!LL2}*mIY`4 delta 20 acmZ3iw^)z+GcPX}0}w>I%-F~+Ar1gJtpw!& diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/output_supervisor.cpython-313.pyc index c62f7b427e4f20701c0f23fb7bf4fe6c18a25b1c..1a95498dbb89a10dd03b5fe0b8594d33aaba4d67 100644 GIT binary patch delta 22 ccmeygm+{kHM()qNyj%=GVD@C*M(*cv0Aqy+JOBUy delta 22 ccmeygm+{kHM()qNyj%=G5a}{wBlq(-0AQR4xc~qF diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/parallel_executor.cpython-313.pyc index dd9c3d8e84ab119f8abf8d43b3830397bd3431fa..7566cb149e118831b6d4f2b69398b2b2b26dfb94 100644 GIT binary patch delta 22 ccmaF1it*VhM()qNyj%=GVD@C*M(*fP09}&@X#fBK delta 22 ccmaF1it*VhM()qNyj%=G5a}{wBX@Kt09vXB<^TWy diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/pipeline.cpython-313.pyc index 49c70be651ff6bd9e8d04c9676ae6ef38066c70e..9831fb49b24a277e644d187e1546a54d3af7ef07 100644 GIT binary patch delta 20 acmeAS?F{Aq%*)Hg00d@F=56Gz(*giL6$SeM delta 20 acmeAS?F{Aq%*)Hg00faPGd6P9X#oH{ECqM~ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_action.cpython-313.pyc index 93052a6e8103fc2547c304dcdfaf3d2198f8ddd3..e6a6ad3f100ef185691678379d6b50a28c4c5721 100644 GIT binary patch delta 20 acmeBU?PKNs%*)Hg00d@F=56F|W&!{-bp=8I delta 20 acmeBU?PKNs%*)Hg00faPGd6NJGXVfGj0C>` diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_decision.cpython-313.pyc index 863f5c04ab1833ed542542988e3b3ab11ece477a..51ea7ddd93fff5fc3d3d95d2fc470672108b6ed8 100644 GIT binary patch delta 20 acmX@gbCiesGcPX}0}z-!nYWSKiVXlg4F!1s delta 20 acmX@gbCiesGcPX}0}w>I%-G0n#RdR6Bn0*V diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rail_result.cpython-313.pyc index 67dcd0c3d0071a67e1fdedad6ccec30942b24954..980c3ad624bef3f13dbc17b40c0223384b3009ab 100644 GIT binary patch delta 20 acmaFE{)V0VGcPX}0}z-!nYWSqAu|9&ZU$ih delta 20 acmaFE{)V0VGcPX}0}w>I%-G2NkQo3#g$3RK diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/rails.cpython-313.pyc index 0dbd89ea93dcfd053c5674d3e89c87f550cb12b9..bf745752f7593f59bf0b65db346b4acc20987d24 100644 GIT binary patch delta 22 ccmdmUiD}OzChpI?yj%=GVD@C*MsCBE09_UbkpKVy delta 22 ccmdmUiD}OzChpI?yj%=G5a}{wBe&s709q{v4gdfE diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/__init__.cpython-313.pyc index 715230e57f7d0b450a19bedc8256c74252cba0d3..313dbfdb22ee7d088c46f312414a565c8b8f8cc6 100644 GIT binary patch delta 20 acmdlazDb<>GcPX}0}z-!nYWR9IX3`2rUlyo delta 20 acmdlazDb<>GcPX}0}w>I%-G1ioErc+y#-hR diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/_compat.cpython-313.pyc index 4d7ec5293811e4addbe3a4d1a072f1b14b42769c..eea12353781e6ba15fc74aa26ee2db36a2a67a96 100644 GIT binary patch delta 20 acmeAb?iJ?#%*)Hg00d@F=56F|;sgLTOa)>9 delta 20 acmeAb?iJ?#%*)Hg00faPGd6NJaRLA{V+7v- diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contestation_validation.cpython-313.pyc index ac2b9d0892605011c7935ffe13ab9719ff671ada..e5169af35b501e0025f2dfd83b1a4ee1d9c82607 100644 GIT binary patch delta 20 acmZn^Y!u}F%*)Hg00d@F=56FI;{X6OBLz7C delta 20 acmZn^Y!u}F%*)Hg00faPGd6OUaR2}@Is~== diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/contracts.cpython-313.pyc index c5bcaafc4319105428670a5510c3000483d114ec..22ef4238fc19709fabb69186b528c750f3542389 100644 GIT binary patch delta 20 acmexr`qh;CGcPX}0}z-!nYWSql@tI=Wd`p6 delta 20 acmexr`qh;CGcPX}0}w>I%-G2NN(ul-dob5Mr+GcPX}0}z-!nYWSKj1K@lwFQ*` delta 20 acmX>ob5Mr+GcPX}0}w>I%-G0n#s>g9%moqv diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_adapter.cpython-313.pyc index df23f355650fb7952bf91ec532fba9bf41687cf6..a6a7843edaf24759e58461ba9971e68b5332341d 100644 GIT binary patch delta 20 acmcaEdtH|MGcPX}0}z-!nYWSq3?BePNd{Q} delta 20 acmcaEdtH|MGcPX}0}w>I%-G0%h7SNhUI%-F~+EDHcSn*{U# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/llm_rails.cpython-313.pyc index 8b9f7599029680bc86942b628d4438211f0474dd..a16bc7574c0332b1a317e8f374025b8dd798559c 100644 GIT binary patch delta 20 acmdnzy3dvSGcPX}0}z-!nYWR9vl0MB6$Wwu delta 20 acmdnzy3dvSGcPX}0}w>I%-G1iSqT6_ECufX diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/__pycache__/output_sanitization.cpython-313.pyc index fb48f8ca3aeb0f4fff944978aafa48b6fcc70cee..a5ccb3aaa09572c2db38a84ce3c500e4885eec53 100644 GIT binary patch delta 20 acmcbXb1jGaGcPX}0}z-!nYWSK+YA6rWd@u8 delta 20 acmcbXb1jGaGcPX}0}w>I%-G27Z3X~JdI%-G1CWe5OG=LTH> diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/__init__.cpython-313.pyc index a1c0ae305a27df0d2bc176fe80f54529231552cb..8e710aba98e80efff879a11a79c2ab0b3b2224c2 100644 GIT binary patch delta 20 acmcb~e3O~`GcPX}0}z-!nYWSq93ucfI%-G0%ju8Mn`vsc- diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/_context.cpython-313.pyc index 85e68340b1d72c1cd90dea97e82cc26e173bac58..02f82eab6b6e8b83f1a1d07fe632c22c7170e25f 100644 GIT binary patch delta 20 acmaE_`(Bs(GcPX}0}z-!nYWSqi5LJ$Q3lBX delta 20 acmaE_`(Bs(GcPX}0}w>I%-G2NL<|5%Xa+_A diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ausencia_oferta_proativa.cpython-313.pyc index 014d27e96a36f95ec1c0fd0c4e9266dd33eab2a8..d3b4d36d6637bccc02d197f7c94103b3343258da 100644 GIT binary patch delta 20 acmZ1*zc!xxGcPX}0}z-!nYWR9kv;%MA_jl} delta 20 acmZ1*zc!xxGcPX}0}w>I%-G1iNFM-0IR*Uy diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/coerencia.cpython-313.pyc index 1adbe28eb841de9616eebac4d71ef9f39cefebd4..4ee482410cf60e55394484e7fbc7e6a95828997f 100644 GIT binary patch delta 20 acmdn1uvdZmGcPX}0}z-!nYWSKNB{snrv;M$ delta 20 acmdn1uvdZmGcPX}0}w>I%-G0nBme+Az6B5f diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_in.cpython-313.pyc index 4c25391337980b36a9fe703021c28963b20fc7d5..b2e2b5fb676858d94a3d64559839ab7372cce686 100644 GIT binary patch delta 20 acmbQiHG_-$GcPX}0}z-!nYWRfmlXgtyaeq4 delta 20 acmbQiHG_-$GcPX}0}w>I%-G1y%L)K8(*$Y& diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc index 4c834efd5965242d74ec0a4ffec468de942f8bec..519acde01007695d9e4abe328f56d7c6da0343f6 100644 GIT binary patch delta 20 acmbQvH=U3BGcPX}0}z-!nYWRfhaCVmCIs{V delta 20 acmbQvH=U3BGcPX}0}w>I%-G1y!wvv5Jp^$8 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc.128272546232176 b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/dlex_out.cpython-313.pyc.128272546232176 new file mode 100644 index 0000000..e69de29 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index ae92b20e17b3fe65ed64b052b5263daebf64da16..b90b465061e820f334705e73d61464309b2b0e62 100644 GIT binary patch delta 22 ccmey;$@ry{k^3_*FBbz4m_3=dk^7|!09(}uzyJUM delta 22 ccmey;$@ry{k^3_*FBbz4M7qq_$oI%-G0%Ocnq`w+0UY diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/out_of_scope.cpython-313.pyc index cdb2534faeb3b0ccf92dc5089f9a827a21f2427f..e2438f0e809fe94fd7e09e9071bbcbb5f856664d 100644 GIT binary patch delta 22 ccmccG!FaWUk^3_*FBbz4m_3=dk=x4!09APg;Q#;t delta 22 ccmccG!FaWUk^3_*FBbz4M7qq_$nE6<08)?!UH||9 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/pinj.cpython-313.pyc index d785a3a97bbd4faf9de0b58fee6ae3858a830843..c4abf03586c9ecc6ea4898c8c517077531179d93 100644 GIT binary patch delta 20 acmaFi_`;FI%-G0%R{;P>Dh6W! diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/ragsec.cpython-313.pyc index c586b640d91df9e5c49d5e988e69e9320d33275f..21e1b4c01756f1e69af9689e58ddde9efb2f8ce9 100644 GIT binary patch delta 20 acmaFB@qmN-GcPX}0}z-!nYWQUlm!4lvjxBa delta 20 acmaFB@qmN-GcPX}0}w>I%-F~s$^rmA$^|_D diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/revprec.cpython-313.pyc index 6b2041d107c31b9079ddeab16eabbac66e8c7731..051d0f80bbb3bc6eae26cc0362cce7ce02893cf8 100644 GIT binary patch delta 20 acmX>naZZB!GcPX}0}z-!nYWSKnFjzsD+RIu delta 20 acmX>naZZB!GcPX}0}w>I%-G27%mV;DLIp1X diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/prompts/__pycache__/tox.cpython-313.pyc index 50fcb15315db1bede1c74cb5e84546b43cf02b93..5824f376dcdd90e32afc44f65e618f4a3bfc36d7 100644 GIT binary patch delta 20 acmZo+ZDHm9%*)Hg00d@F=56GzWC8#(I%-G01l^Fmur3Cr_ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/__init__.cpython-313.pyc index 8f3fac0e59edec9b26db2429aa7ccabf2a329098..2f860c00bc371058e63edc6ae7491dcd19fdf6fc 100644 GIT binary patch delta 20 acmey*^Ph+NGcPX}0}z-!nYWRI%-G0X!Uh0CGzFvp diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/alcada.cpython-313.pyc index e93d71eecabdb08a030bd5d6888654fc87e23c2c..0a60ca00815234f4820b0cb9ba8df3e342ea470f 100644 GIT binary patch delta 20 acmZoyZ&&C3%*)Hg00d@F=56Gz5e5J_HU)wJ delta 20 acmZoyZ&&C3%*)Hg00faPGd6P92m=5$O$7e{ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/anatel.cpython-313.pyc index 659cca02653235768827f185384e795c29ffaf11..ac98b776e19579ce4f944dc07b0f4632a6e8fd1c 100644 GIT binary patch delta 20 acmdnvzQ>*WGcPX}0}z-!nYWR9qcQ+R4hC@m delta 20 acmdnvzQ>*WGcPX}0}w>I%-G1iQ5gV2B?ayP diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/confirmation.cpython-313.pyc index 6c7e38415c743787c9984e35043d9e144c4d1715..c723122bb2978ad4f3cd7891a426a18ff1c6a7c2 100644 GIT binary patch delta 20 acmZ1!wkVAIGcPX}0}z-!nYWQ!TpIvFA_d6+ delta 20 acmZ1!wkVAIGcPX}0}w>I%-F~+t_=V`IR!=l diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_in.cpython-313.pyc index f157348833b606390bde56eab02e3b9cc89f11d1..c27dc0a1224cc09ee23d900c972a654923e3d84d 100644 GIT binary patch delta 20 acmX>vd0vwHGcPX}0}z-!nYWSq2oC^3cLp~A delta 20 acmX>vd0vwHGcPX}0}w>I%-G0%ga-gVjs>&; diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/dlex_out.cpython-313.pyc index e437bea977eb6981c862977590bbd233fde71cd5..69ca93c1af75bfd499352714d1bae9147c67c721 100644 GIT binary patch delta 20 acmZpcYL?>u%*)Hg00d@F=56Hu!2u%*)Hg00faPGd6Pn-~j+L(gjig diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/ragsec.cpython-313.pyc index b62a84fc863e7fdf412599be1a47d8ef8bef78f3..4d4b00c081aa0bcaac32d0cdd54c7c8f80299a7d 100644 GIT binary patch delta 20 acmcbnbxn)=GcPX}0}z-!nYWSKTND68`~~*_ delta 20 acmcbnbxn)=GcPX}0}w>I%-G27EeZfZ69set diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/revprec.cpython-313.pyc index aa2be86e684c2786e50c074b35df14c8e86ac486..79ec8b5d3bc3c5012a1b6bb76016e2cc2cd6049f 100644 GIT binary patch delta 20 acmcbobx(`?GcPX}0}z-!nYWQUSQG$7JO&Q{ delta 20 acmcbobx(`?GcPX}0}w>I%-F~sED8WZQw59w diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rails/__pycache__/tox.cpython-313.pyc index 15dcb19ffffced5f7b0297c4055f470672870e6a..884e386c498038ab3568b039a459fa30c85b18eb 100644 GIT binary patch delta 20 acmaFr@YI3(GcPX}0}z-!nYWQUN&x^#cLrMk delta 20 acmaFr@YI3(GcPX}0}w>I%-F~sr2qg%js@5N diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/__init__.cpython-313.pyc index 313b48ab619251efb0447e993f5cc7bfc3b3e974..028d247ce3ca1cbaa30662fbeaa37aab54b949be 100644 GIT binary patch delta 20 acmbQrGL?nI%-G1y#RLE`fCN$i diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/alcada.cpython-313.pyc index 86c6d7e1a5dfc97a944f3d63945d56ce79d1629c..4618efa9cdb5d6019096563002b63e2dc86c6f08 100644 GIT binary patch delta 20 acmcb~cax9%GcPX}0}z-!nYWSKj~xI&b_Kcs delta 20 acmcb~cax9%GcPX}0}w>I%-G27#|{8JjRiLV diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/pinj_patterns.cpython-313.pyc index 72d4bc1b534679d1811d220b0cdeab3dd64ef363..856ed5b3b270af7bd37ab6d8e61958833aefe0c5 100644 GIT binary patch delta 20 acmbOvJ4u%NGcPX}0}z-!nYWRI%-G1?&IbTBm<0y_ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/calibrated/rules/__pycache__/tox_blocklist.cpython-313.pyc index 85ecb207a8e7a9a6ebfa42f633054a272febda51..8c270f8e2a20b479d63de91077ba222ff90df843 100644 GIT binary patch delta 20 acmaFF{fL|UGcPX}0}z-!nYWSqIx7G|a0X2P delta 20 acmaFF{fL|UGcPX}0}w>I%-G0%ofQB-hXu+2 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/__init__.cpython-313.pyc index 262a3b6125381c8197999499b2c48d479c149bab..ce6477c219ca89dfc918fa168fc22e81ffedba24 100644 GIT binary patch delta 34 ocmbQqJcF70GcPX}0}z-$nKzO9DR;SkZeEFgioS2K=fppA0jlo{X#fBK delta 35 pcmbQiJd>IGGcPX}0}zCtoi>sCDNludZeEFgvc6++Y4OD0a{;%J3>^Rf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/mcp_mapper.cpython-313.pyc index 78250ff95c18ca69c756d1188e092aae5568c5dd..e3a4e1e115e52991702e3b44b3fceb73edcba600 100644 GIT binary patch delta 37 rcmcbraz%yvGcPX}0}z-$nYWSKiJ7}nKR2&LKSkd+*mH9v^B+C{)@}=w delta 38 scmcbja#e-paYBOoGcPX}0}z-$nYWRaa delta 38 scmX>haZ-Z&GcPX}0}zCtowkv?oSCOgKR2&LKUv?gxU_h4FY|5=0OAP@Hvj+t diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/identity/__pycache__/resolver.cpython-313.pyc index ddd7be65763bdbbca544d509002462bfdb1575c3..c0422abc24827fe1612b9f9d4351ce7d52f278f6 100644 GIT binary patch delta 36 qcmaE*@=}HSGcPX}0}z-$nYWQUn3=m=KR2&LKSkd+*mH3fGd}>(vI^4x delta 37 rcmaE<@=AsKGcPX}0}zCrowkuXn3<|-X;u# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/__pycache__/judge.cpython-313.pyc index 1954bc6f82a3f641ac81cdc798531bb2fc106771..c5626b0b35623fc29eb99647e69c2aec3f614e2a 100644 GIT binary patch delta 39 tcmZ2>kZI{bChpI?yj%=GVE$y@Ms9l+?jrr%yb}Esecxcu&0#D7a{%{#3`+n2 delta 40 ucmZ2_kZIXLChpI?yj%=G5Po*rMs9l+o?`vnyb}FneaGU`;?1Ef0doKbsto@C diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/__init__.cpython-313.pyc index 4b91dab978230b8b6552541c02bb67d6a64defc9..085a359ed5c44dd97ac1c1a5627ec95a2abd74bf 100644 GIT binary patch delta 34 ocmaFF_>htNGcPX}0}z-$nKzN!n7ctgH?KrLMc+5rbE4M_0I@a-mjD0& delta 35 pcmaFJ_=u7FGcPX}0}zCtoi>r%n5R)cH?KrLS>Lg^w0NTD3;?~o3rhe1 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/__pycache__/llm_client.cpython-313.pyc index 2e44150e4a94d120408898e883b8449bddec26a4..78fc057cadbaf179f504ff8443cf83bb57035cab 100644 GIT binary patch delta 37 rcmbQMHAjp4GcPX}0}z-$nYWSqJ2Q8aer{fgeu}z(PGcPX}0}z-$nKzN!n7cziH?KrLMc+5rbE4M*0JFXdw*UYD delta 35 pcmaFK_==JHGcPX}0}zCtoi>r%n5R=eH?KrLS>Lg^w0NTD0sz2W3u^!X diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/aluc.cpython-313.pyc index 6c3e14d1ece3f4f805ee4a186657a8eee102bb7e..33a256da3b9b209567eee17c79be534f1d733c22 100644 GIT binary patch delta 37 rcmZoNZZzip%*)Hg00ibw=56GTli+UA&&?~*Pto@c_S{@5!OI8$#xe?h delta 38 scmZoPZZhWn%*)Hg00iM@r)}hpli+F9&&?~*Pu6!VE-l_%BEicD0MsoDF#rGn diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/csi.cpython-313.pyc index 63a7acfad6dcb40a64eb282ac638f43394e4362d..5df633e224e016114566a512da63f7546b5f152b 100644 GIT binary patch delta 36 qcmdnWwS|lOGcPX}0}z-$nYWQ!m4&-mKR2&LKSkd+*mJTC%TEBf_X@!P delta 37 rcmdnOwUvweGcPX}0}zCtowku%m4&B8KR2&LKUv?gxU_h(HOo%`#smv> diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/fallback.cpython-313.pyc index c3493b7de516228c63fa09d9fdca56c73fb52280..0accf86c667d671f0a44cb45b67c7738265cbfd3 100644 GIT binary patch delta 37 rcmaE2_t=j6GcPX}0}z-$nYWR0%6F delta 38 scmaEC_r#9-GcPX}0}zCtowkv?osXweKR2&LKUv?gxU_ilT)txh0Qg!B6#xJL diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/rqlt.cpython-313.pyc index 032224bc1762a2d63934b67fa54170b9dee24128..17d0cb7867b62d86f54865d7da130b082b62f78d 100644 GIT binary patch delta 37 rcmeC?BnGA%*)Hg00iM@r)}geVCHGn&&?~*Pu6!VE-l{N#>~zL0L!Zi=>Px# diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/judges/calibrated/prompts/__pycache__/vctn.cpython-313.pyc index 6ba3e52648bd7d484881e5592ec463450fbe7ad3..bd81b3e7633cfae868e764a917601e4a9cd8ed90 100644 GIT binary patch delta 36 qcmey&@`;7}GcPX}0}z-$nYWQUk&(MaKR2&LKSkd+*mH6P<8J`X7Yn8U delta 37 rcmeyw@|lJEGcPX}0}zCtowkuXk&&lWKR2&LKUv?gxU_h3Ipc2t+RhAG diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/__init__.cpython-313.pyc index da7e2194d3e1cbc02ae6de36077e707945ae013f..2e33c5ada21ab4c422b357dbd78e8ee816b5a258 100644 GIT binary patch delta 36 qcmcc1e21C)GcPX}0}z-!nYWQ!laaefKR2&LKSkd+*mJT2<6Hp1vy&e&GHLN diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/base.cpython-313.pyc index 972b6626a15dc2c21f74e63ed132814672b234d3..91b37ff6ed97927635708988e2b3e136b5e72d85 100644 GIT binary patch delta 37 rcmcb?bDf9#GcPX}0}z-!nYWSq3?p}*er{fgeu}xt>sbtG delta 38 scmaFm@!Es?GcPX}0}zCrowkv?nwh6sKR2&LKUv?gxU_ilMCO|c0QyZ09RL6T diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc index 4039e6cda9e044696c0acd9acdc598e76e05aa33..6558a05e8c1f902b0dec19d6d6fc3f35f67883e0 100644 GIT binary patch delta 39 tcmZpE&(!puiTg7zFBbz4m_3=dkz19OyI4OruS7pZ-#6HEvkj~JCII*r3_Jh; delta 40 ucmZpA&(!>$iTg7zFBbz4gq@wXkz19Or$j$DuS7pt-?6x~c(XOD`z8PfKMe2y diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/structured_output.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/structured_output.cpython-313.pyc index f55398b848cf05da32e1c18aa86ee428ead339ae..28c9f6690af56c65607816e9a286f59fd2f1cc10 100644 GIT binary patch delta 37 rcmZ2twb+XLGcPX}0}z-!nYWR94>NbQer{fgeu}%z=^s*j)>= delta 38 scmZ2%wZw}1GcPX}0}zCrowkvC4>M1Ver{fgezLw}acS}9OU!|i0OsioX8-^I diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/types.cpython-313.pyc index 05014a07f54ea9675ce69b8e48635523902b644e..682afe5e629d261b132206f75668fdd3491f32e3 100644 GIT binary patch delta 37 rcmey(`HPeLGcPX}0}z-!nYWR delta 40 ucmey>&-lBak^3_*FBbz4gq@wXk$WLCPoaKpUWtCPzGHD|@#gK!&Mp8Mxec8F diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/models.cpython-313.pyc index a64e27058d4aa21d0d6e7b193da7345ca3bf86f1..b2f73e5a8169fdf8cedbdcd45553ba2c39188732 100644 GIT binary patch delta 37 rcmca9a6^FmGcPX}0}z-!nYWSKgNeI9KR2&LKSkd+*mH9{(=S#4(bfxT delta 38 scmca1a8rQ$GcPX}0}zCrowkwNgNdh5KR2&LKUv?gxU_h49MdmW0N?lw9RL6T diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/registry.cpython-313.pyc index 16e0b00f5c6e473ece8985ac4f72503b4633fe04..91673ee2c8d16eb3b3106bcbdde7465de9a6f95e 100644 GIT binary patch delta 37 rcmZowZBga^%*)Hg00d@F=56E_Vd5^*&&?~*Pto@c_S~$^6eR!vx-$vz delta 38 scmZosZB^y|%*)Hg00d!Yr)}gGVd5#)&&?~*Pu6!VE-l`y#S|p~0LP^YqyPW_ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_policy.cpython-313.pyc index ca72d392d3580a0e9ab11b1ed83d63a50c05a53b..80770cac9c4e3c8175c16aae5a722ebd08b64f35 100644 GIT binary patch delta 37 rcmdm{vsH)tGcPX}0}z-!nYWR5#YKR2&LKSkd+*mH9y(^_Ew(=ZEl delta 38 scmdn0vrUKlGcPX}0}zCrowkv?h>536KR2&LKUv?gxU_h42h&<%0O4~CDF6Tf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/mcp/__pycache__/tool_router.cpython-313.pyc index bc53c02fab16f5c20c1822cc380e537811be8282..15ef79857bac9c51c38fc23c149e9352e577ec10 100644 GIT binary patch delta 37 rcmaEt_co9FGcPX}0}z-!nYWR9KNokYer{fgeu}r%n5RrXH?KrLS>Lg^w0NRtF95m=3myOf diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/models/__pycache__/identity.cpython-313.pyc index ffe490336559c264811a10b5f7ee644dbfb47ebc..1bc92c07bc626ec39f785944b5f9f85cce6083ab 100644 GIT binary patch delta 37 rcmeB@?v&>K%*)Hg00d@F=56FY%E(=+pPN^rpQ7&@?78_4<2r5t$%G4- delta 38 scmeB_?vm#I%*)Hg00d!Yr)}gu%E(iupPN^rpRDg#Tw1*OHsd;O0N0-kOaK4? diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/models/__pycache__/session.cpython-313.pyc index b1d210447a1ae412bd57e8b8f483bc0dcb0b2384..5670c61074a292ec36a9fae864cc643a40b31cf2 100644 GIT binary patch delta 37 rcmbO#Iz^QGGcPX}0}z-!nYWRfnVGvpKR2&LKSkd+*mJWKb2U2vxjG5z delta 38 scmbOtI#rbWGcPX}0}zCrowkvinVF|lKR2&LKUv?gxU_h)By%-80LGpQo&W#< diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/__init__.cpython-313.pyc index d0cd341a547b2b927be0bd0aa69f606f3336748a..c03dd804fcd48d1a5b83acfda9c57b4415636e1a 100644 GIT binary patch delta 37 rcmey&^@)r7GcPX}0}z-$nYWQUl7+iQKR2&LKSkd+*mH9M3o|1C*cl4R delta 38 scmeyw^_h$NGcPX}0}zCtowkuXl7**MKR2&LKUv?gxU_h4J_|D=0Oo@WeEWd8M delta 38 scmca*dE1ivGcPX}0}zCtowkwtG#gKier{fgezLw}acS}9hipGZ0r{2k diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/guardrail_events.cpython-313.pyc index eccd28030bab23c5352ad1a704b146b6d672bc59..9ae83e78f21a1c871b1cc5ce5a21fdfed094c207 100644 GIT binary patch delta 37 rcmZn`XcFN5%*)Hg00ibw=56FwV&rbo&&?~*Pto@c_S|gAc!~`Gw;&2t delta 38 scmZn?Xcpl9%*)Hg00a?dr)}g`V&rMn&&?~*Pu6!VE-l_{!FY-d0K}aO3IG5A diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/ic_events.cpython-313.pyc index 96696e6377a821fdd954bea31ffdb1c0ffb4f73b..a639dcdab3c9fc0fc47a2bd466c0db4f38a2c668 100644 GIT binary patch delta 36 qcmeyw@{xu6GcPX}0}z-$nYWR95+ir5er{fgeu}zllk;aX710tyj%=GVE$y@Ms5Xm?ppoayb}Esecxcu&F1V=j{*SpSPY5) delta 40 vcmX>-llja{X710tyj%=G5OH?eMs5Xmo;v;9yb}FneaGU`;>~94Q;z}w1&R$n diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/token_cost.cpython-313.pyc index 584ec9fb33f4517cf916a48cb1710de73d7082b0..1d8a814ad45780e612b618e0285d648c63bc7877 100644 GIT binary patch delta 37 rcmezD{K=X7GcPX}0}z-$nYWSKjFY=gKR2&LKSkd+*mJWl=Q0TZ=5PzU delta 38 scmez5{MniNGcPX}0}w=Z~y=R diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/observability/__pycache__/workflow_events.cpython-313.pyc index da593ed6dfd22ffe5f10a688a40a305b87cf2a78..1030d5b0725356400d4dfae5c7f203d25e2cc024 100644 GIT binary patch delta 37 rcmZpYYLw#s%*)Hg00ibw=56HmW#n$w&&?~*Pto@c_S~GpIFB0uy$%YM delta 38 scmZpaYLepq%*)Hg00a?dr)}i+W#nnm&&?~*Pu6!VE-l`i%s7u50LsS;N&o-= diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/oci/__pycache__/__init__.cpython-313.pyc index 48f640609babaf8ed513d3c09a40bc3efb4bf708..082666b5ceaa968fd104ac3559191b90fdde5c04 100644 GIT binary patch delta 34 ocmcb@c$ty=GcPX}0}z-$nKzN!n7c?nH?KrLMc+5rbD~!l0IbLgUjP6A delta 35 pcmcc2c!iPsGcPX}0}zCtoi>r%n5S4jH?KrLS>Lg^w0NRt7XY~>3ljhU diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/oci/__pycache__/auth.cpython-313.pyc index 548cdccb95aee101b6e7ed39716fe7b52c40106d..22d20e71cbea5dced265313ce4a5f56cdfc735d0 100644 GIT binary patch delta 37 rcmZ1@xmuF@GcPX}0}z-$nYWRr%n5SAlH?KrLS>Lg^w0NTDBmldw3o-xz diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/persistence/__pycache__/oracle_store.cpython-313.pyc index 162b64074f8dc2b13d4a7833c0ab968d9d0b97f1..40316ceb3c83fe8e23be05ff06e9ac3ab085d128 100644 GIT binary patch delta 39 tcmaF!jOq0=ChpI?yj%=GVE$y@Ms9W{?mGS4yb}Esecxcu&2mhB8vznK49oxk delta 40 ucmaF;jOooYChpI?yj%=G5O#LjMs9W{o_hVGcPX}0}z-$nYWQUg^{~XKR2&LKSkd+*mH9=qk$y=;)@H0 delta 38 scmZ2gy1JD6GcPX}0}zCrowkuXg^{OTKR2&LKUv?gxU_h46{CSA0P!pgIRF3v diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/presentation/__pycache__/__init__.cpython-313.pyc index 220e3febee452ddd94505dc8e2b21d8df6af81ab..fec5fe336e1baf79d09403e22b61af4306a27f84 100644 GIT binary patch delta 36 qcmX@ke2kgTwGcPX}0}z-$nYWRflZm@XKR2&LKSkd+*mJT1(=q_Kg$g+U delta 37 rcmX@gdW@C(GcPX}0}zCrowkvilZmHTKR2&LKUv?gxU_h(Jkv4&#bXNW diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/embedding_provider.cpython-313.pyc index bf4541b273ae5f1b69855c8adb93d486a979b25c..25c78801e67f9b0e3ab898945f04d661e1f812c6 100644 GIT binary patch delta 37 rcmexr^u>t#GcPX}0}z-$nYWSKmyx?hKR2&LKSkd+*mH9Vqo4!;;&}@s delta 38 scmexj^wo&_GcPX}0}zCrowkwNmyxGdKR2&LKUv?gxU_h4GNYgb0PznC*8l(j diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/graph_store.cpython-313.pyc index 4b40d3cb1fbfb38091a49327381938c9a0554b06..df1326391165934266d9f253e9e829725438bbcb 100644 GIT binary patch delta 37 rcmbQCJzbmoGcPX}0}z-$nYWSKn~}RzKR2&LKSkd+*mH9dqnQW*#t#Z| delta 38 scmbQPJwu!OGcPX}0}zCrowkwNn~|qXKR2&LKUv?gxU_h4BBPlI0Mpb9B>(^b diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/ingest.cpython-313.pyc index f43963f6302b1be0c7d39ec1c8d629e40e135c76..2e4d5c881e9e68af10d581fcae247069a5585373 100644 GIT binary patch delta 37 rcmZ3Qv?Pi9GcPX}0}z-$nYWQ!keRzcKR2&LKSkd+*mJW6^Iu&6)eH+| delta 38 scmZ3Iv^0tPGcPX}0}zCrowku%keR1YKR2&LKUv?gxU_h)I`dy$0OK4C7ytkO diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/kbdb_service.cpython-313.pyc index 1c3214e2c8de13d98ad29126f7c14a2a8a8cb9f9..9061d5e16f111ac6d8e5b7d3fa14d70afa4c623c 100644 GIT binary patch delta 37 rcmbQ^H`|Z{GcPX}0}z-$nYWSKm4&-hKR2&LKSkd+*mH9Xie%U0Ntz$c>n+a diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/vector_store.cpython-313.pyc index 2775a7a0c57d8bdcf5815e55417fc199dc905372..e946076c12ddbc682b4a2d35c64f220140417ecf 100644 GIT binary patch delta 39 ucmaDbk@5aSM()qNyj%=GVE$y@M(*cK+-3T?c_sQO`o6)QoBuIAas>bij}7Pm delta 40 vcmcaVk@3MqM()qNyj%=G5O#LjM(*cKJmvbic_sSE`i{k=#hd>!J#qyA8czr%n5RZRH?KrLS>Lg^w0NTDWB|Ma3pM}% diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/repositories/__pycache__/session_repository.cpython-313.pyc index 90f2737dfc18093f01ca45ddbfbd0e9fea83d26f..c2aa0d4cdb7bb83cae0ef2a29f974bd2ccefee3b 100644 GIT binary patch delta 37 rcmeBk?sew=%*)Hg00d@F=56GbW#Vqt&&?~*Pto@c_S|g36eSM;#{CL% delta 38 scmeBm?sMk;%*)Hg00d!Yr)}hxW#Vbm&&?~*Pu6!VE-l_{%oHUL0MywFCIA2c diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/__init__.cpython-313.pyc index d18782551cb9d38ea8c1a1981e2526879b966a24..d13f739ef25154605c76702f5d10df86d071f47e 100644 GIT binary patch delta 35 pcmZ3*ypoywGcPX}0}z-!nKzO9D|eZGZeEFgioS2K=VTtnc>uU&3atPD delta 36 qcmZ3sCD^Iz8ZeEFgvc6++Y4K!k#(4n6>kDB3 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/config_loader.cpython-313.pyc index 5dc21fb9db74203844d944882e52c5f511c7d23c..611825b6fb5d5f4502974588e2acf3ae8ba8d88c 100644 GIT binary patch delta 37 rcmew<_(PEUGcPX}0}z-!nYWR^2Nu delta 38 scmdm6v#*BxGcPX}0}zCrowkv?f{CY6KR2&LKUv?gxU_h4AJckk0Q)ix5&!@I diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index 9c23d1ae7092b56d180bf72aaefcdfaeba85bab4..c8967c9d3279f369c7f8c0aaa8c50ab73c218951 100644 GIT binary patch delta 39 ucmbR8gn9B4X710tyj%=GVD@C*M(!XU?t1;)yb}Esecxcu&6zx_p8@~?oefn0 delta 40 vcmbRIgn7ynX710tyj%=G5O#LjM(!XUo(BEgyb}FneaGU`;>{U6tDgb@5Cski diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/models.cpython-313.pyc index 369446f1188f75443b7363147ff01d1c1564b9d6..0790f6375a814af246d084531df89927841e4806 100644 GIT binary patch delta 37 rcmeAd?i1$z%*)Hg00d@F=56FwW9BZ=&&?~*Pto@c_S|gC9K;3yxzGvr delta 38 scmeAZ?ic3%%*)Hg00d!Yr)}g`W9BK<&&?~*Pu6!VE-l_{!yLp00LMoPssI20 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/__init__.cpython-313.pyc index 5312258964a239b5ffa243eb9639dbd4d27013db..0493330973acadaa205b556abf3b339521ac4a09 100644 GIT binary patch delta 20 acmcb^bcc!iGcPX}0}z-$nYWQUkP!esKLw@$ delta 20 acmcb^bcc!iGcPX}0}w>G%-F~s$Or&DNChDP diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index 9603442b9cea1a901949c97fc5d7f07aa0c4d8e4..aa23cc687534949264eaca2e82e78d2d81131a2c 100644 GIT binary patch delta 17879 zcmch8d3;nw^7wSmkz{gB?mL;>8FJruLO2o*GXa_hfe2wpCXkR!;+q5s3PE7kpeV4T zH0z1iipMIjyAJB^N>n^{SxF3%7$e|!_q*)m;fgkutY#{v z&LHeon=UlDub;UiwvEbeY!ADQd59X3-P!GIFVi|}9-`*ytZ7Bf%USb`Rzxet;0TuJ>d6nBNSXKj8K={~5Rdz#U)# zGjM_IXEvX()OZ^UMm!8I7<#yih0LG|0o>iT>%$VsLEFwSLl|e#PU>)Wh{Yf*M}Sd& zZhJK>ncQRhBrK-yUX~#6(d<5!D4-a2KT8sjo;|>l1r!TVih$yP|3PLzxQ)p1>@b@p z@Coc8mMWk`_ApBmP!fBDr3)w-xE^I02m@CNdyHiYyuo%`cue0fShi@P@+|f^%MmT9 zFqR`M7vV_*r-76wSe~FIayomG9`8H3|#IxRy`dl zmoq!7L5y6%POt?6ss!fe*uoifvu%TsL5(guTYD7tm5*f1RzF!M+TJ7~BV1zrofDA_nA*0$R@AWa|VZ0plN-X$Ip8 z!2OY}pMhHm^SOteW=)8l<`DHT_GXBbe`03QLgiJ!{T6F+a`!m`*=m^j4TzE(pmC#s zt_P@9Kx^0;)+V5}FqxYK)ChuAES9xrC|wqqda^;*fmASY>(~&p2o4j_N3zZgIz<<) z!12G$x}3!8*)Y375I3>2Ocqdcwt`tV5!uYTSr6OHZv4>>-(g#vGFo7K=U6Y+CTD5` z+sba5?g4Cs-7M$>sJu~(#4#Eb+m@lhd9fXh(!hVWrK4=SQ*bMLm-Qhmw}Gk0*badw z@+S5kyG7vJ**M!Npbn6^3(WpL+byW5Y+*lv@sBChP}UJi z&3&RsDDv@;6C{eb@gb1I2hY#|J~)f22;~DcG>AVNMZCxcer6jG*Hvh_ZzAz<5Gbbz z)cX|*Ni|iEctoM_ROl6;pSwg;M9-j4JW#pYj_nFmF%5I$et!q~vrC9abUIMv69<`I zAt`^1!`;bYn|=NV45}Yv@NhAFU*Vyf*@LsC&)wB&g2JFRd4P>-}8_jx{(5_C|)IP~=mi4Vxy-D9TBARrnh$Ln|fp!raZm7N4DrUo7#KK zKx1h}u(jFLZEn_f%O;D})FiqFhv_!!O|n^U?dj?QXKB`3&0QuLu_oz?~uWN2j_IHPO>hmd~;ercfcoe1xT0^mCk-Ur3jB9|XD<~D+i&8?k1*2c+I z-H79C?35dwLp3*o2HoZ@-6dN2zoCPziNKyO{HQT+iXV;K*wYOIG+CO=VCk)f$!_u+ zJ7FYpBfpqMg8NFe1`pYasy>V=aVW;rR`7{#xfRqN)3jRw>XHv(>l&o{8x+732ahqg zPFYN`+>9+IM5%>z`F^Co53vuTNO!AQxSrMO0XV(uPqyh^R+Bick0n9AlNxSrHQzXv zXRE3T;2GzM7f+8R?tL>_#~}n+4WQo+#TUVffP@kM`9uEmPi`3YH}<=o_YEEm2pWxv z?e`cBkL*{CMnv_iM*|~90+WUUlgLw*ILxsBZBa&1YKQY#ppO4I9@F>DGUtq~1PXY7|~NC&^%6~2 zlZ(OfPmr;o_RgkF=H^Cc$Y^Y7HMcign_!m29~f1kf&WT{f_$C>SlBZF$7jPnU|aI6 zr&8HKY@IiSBWzMhw4AsiXEVHc=@kvY==gK(paF^%YAelFSSf5TKDfO!;0_}GB(*Dk zw$fTyF&OeK8jBjjz8i*q+p(R&wspVP@|ZTF;}_RZRmy@Q5aBURgojInMP0u_>{y~>>=T{tUX#Dx0FWC0yWbViXIqy z*FFEaA5Pq9D1Ro3c=v%7>K~ER$uO+i497s~3nlkFWdaOb5C1Ld7KK4&>IP$0LD22} zVQ6=546gm4qX%LO?g-{BupXOQyJtpu$GpKdu>!+A#9)XDG6eX^2#Mj!u`M`)?qodB zZ!|%`+Ss~bqZuL`1RaQ~5Jt^<2%Zp=P2D0sJHq7;wS@59Vd_PZ7!f=4CfsS7`XCls z)AZ|MA45e=7E5QhwyE80lJyXgJ7M#<5n`o-1teGLA+&>}sUZ5p7z(l1+=YE<9YI(& zw?PnrtPLDUrXJM`k zZgMR=>QyLr>+h{_sXq>iBH_q&i5A=|rzW<4ef?Vsj zAQnPnq{25~e=)B-Oox5q`<3H9{`)IN0+J6e8}>=*SB@GgMhrEt#=nv{Xs8+XTllu2 z=CJCn`2EcX4MT>Se$AlY!qJ4Jejia>3<~8d53D@Yw{|!vZ6qk?D1AF9r+@xu z9uIjaEW;*1CM(tPKz7PaP%^?#$3SGcq z~`!NqcL`a= zf0{)Wd7c1_Jb=Z^{Jkua&Ud^|0(oRMDRYw_L-do}luZ&eXAnNYZ_g%+$Vq-KnB}K&Xp+W$K8O54sjV6cuNs_FKODZwe!PI>y3Kk4 zNR9IEP=cd#ghb}>B0`%{s*wLG_pKla`P0)Y6L4vTUuE+fy=Sd3s*4B|9@tAg~C7W>Ld66xbPrN?ji_FA%z{E=U%C9BDk zyu?UiSH6XOsJc;p89|}DLu0HOPz&53N zI*P@+Sd3xu9v1IFG3MUX*|EOWVs4gS;@{MfTQz9pv209IY_soi=Q<+^CimE%UqUW= z&?q;4?`rZT^>(w{8puBg`I_%qL-x~HH+#@pQcr1?o4s=#F%f?i?3Pa`H<5PxS3TruC8^?%_L3x0%>UR+GD!vhwwK&R_SpAtC0ciAymu!_ z(o~_e5We&$B*cDxC(#qng(&ViES7VR-K4}D)s+2VOFiA~x9=x| zG{k}&OR)&Tsk;JF3>tY8muXa6M=C5BPE&p$9bQ}iXd?|Y#ND297jajS z13dc>Sxz3~KRrY;;{>4v`PM=)rfhBAGN$S5!j~(#8wKa{{pmEAe|m_lq-pN<>Yo!& zwMM97;VT~?rO85qSd60k36#|-IMLSB=vb)T{P_n+ELqIodw^twZ^3r42a26fSY<8Z zZV*<{BqMC$6%UeqwA|f(=0S3TLi~L85faazdYEh@w{XKFB#Z3gs~>@}tg%DOJ4&4q z*@PvQAXLZidYmjKyZOb(Np|FYxQsOI<_)H%UaJap!&d{j0PQ)%(~po@#Kh~5kSk=b zec2P_il$sh+bcv)$`#}M1c&%B7E>Wh#2c~1MfiD@_a7zsIf!;=54&)b4l3Fru&ln*8 zRFda-!YPtSe#IA^BH>~OlV9L%r$CkG`JJc8Biue3PW<#L5=d6NY<{|KUy8l+W>x-X!y>-ou{# z2l9@}QwVUnir*O$T7COu4{rcul;6bq*Pu$Zd=@9|J1oA%LPP+u43;5{7f$4t&;Y@u zAN?&PO?FHVwhAW~lZSd4RMVoc*eUk&<7dbQTH#@j7$k40s)dDxs|hdpDU24FuCcpl zLIq(;#BfDAIo&Zb-w|W3dxvz8_4ePrL$(s~CNCO+V0wl(j*z9`BF9EZvN{x9aLiM@ z%fsPEM_0FN(N2t${bY#W@;;opJ;on=UkH5ZeG*E#`RMx~_b2x1^CXID9MiyCFOuwp zDcdZ<(F-f1JsswJ4k0`L{YA2XFz)sNh%DjBA3*eb)NcELxT_O{MaA%O88||oFtr}5 zUC3|YFZ~s^!ES!;uVjAEJ!t)>5RXR&4s(z4tPe?ijEE$H&w}lnp@2LZ2H1v_r@8zg zxs4pRU;U6&Dq$^@e@teRgh`(g>u}oCqboS(f1E$`2?_D^M4|VhsQdUUpO9X1)?WT8 znWZF4_{Iq`OY;!6ck)9MGtEOosPJtCG;jEZETu78`!nB=XbNKg^c|6Dn$})*mF!kh z57phT(^xX^?!VI(TB+qr2|Y=6+5IVf%x6{*L{b@-qwE9FR`;76=VRNpdf#N)0B3ED z?WXnS_HDASihrP^)ig-O4SqBYp7xb~w3d(;`D6ZcUI=DFTWP6YWJ6<`wob@^Wck3s z0D66JAolSD_VGEIQ-@Wm;t)Lx-EbT-2t67=v%Cc10}f^QCjm56AA+=@SiA}b9`nG1 zx<)vrG&zoqB6va|okgN}T_8P9mf2|#9dYw-1DRkVv9F#&X=VK5NLo+cw$F>A|3%1o zo*Y9fEADoz*^$t{N#(# zVTT}DG3IME!;yQZMI6M*o$c}({zW3KD-!9$)MCdBbxhN0frGeinV<;VAs`NkR8I^d z9kFHnrX+YjC_|mrV7d{?UrM42$!B(tWUAN1U86!V@GOUS)~O&`%@?QBnAjD1~IgQ=M;lCM|LK4Hi-J=fb;M$7ty8=*Xd zpTlZXFUTSTpNCqDfiFPlA1LH|ET+_}Lg`;)BoO)eAFwL+%52~;L{5vjA0eaY@l%B0 z?2s=ir{R!8MKoC>GLB}Rw3x+@wkqDNa=W*{j!n%OXUXd`wbzm|Grfm zdGKx67SB9NB5k!#2XdVs@#Pzr(`@wzNWw47BQZR)jmFzAE~l-8u2FEmRWzUPSOLo& z+7Hw?PONNSnF8?>%nCSV3tbUrRXWevq8tZUmQYKW6xQH6qEnQD{hMJnY9Zxrz{n&1 zq)^up8l1w#I8Wiik(c}af(D05{!)k(&Jv21Jur5Qza_#FDfzHO-qi@NxL!Uq>|i}j z<+Y78f!EbjJx{HtVYV)VmTT)FMj32NE8>g|v6J0}ySkf(i}(>-qzlJpWq3%0rK11U z`AcM3x^1XDz$cZFsRKR9w)D;*J_bEUrMdVdB}*?>S)v+n)rmir!F8)>jXGM2T9$0P zcw0E0_EkEK6=Ts$`f0`j4wKVZQj8SM53iyzb7Ne>uOW1ULq|PWDh8FTg+od_VVs5m z|H9KvNwF-~_E1Iu4_Zx&NG3O~rVZY)Qmku=Oi}!3D;z4mwVJx6#rXNhmXgH-V+#Ww`oOsB(a zNBdL(@pU9i0j*Q66K@;P2JwB()PrAlJ&oWO%rwHsl5i~ryeJMBV2ixEglb7S7(PN@ zQnEmym^wZ-C5hu>m5f&>AZg}jfzQeP2P0Rsnt8DCYc{dg*1G0t;=coGZOVy zmP!f#qo=#GvJ4Hn=)rX~$}8FBmKK9#JFqV(Nis-NxLHzyGz(XvsT$_SM@q(71m3AR zOm@woG;8`Cg5Lx#Kn4)^<1?8mr8c1>CR_X^gGI-PC9X~>r3!b6TMu(C#R*uktO^|> zG?0}StHh%AvFI#m4wvG36OE6paGA>GnawCT%~dn4<~O&|aNFTA4`sSUgyj+?Z&oRs zH9boq>E;vWE%{^-c+SqyxWwssW&@3I148st{?G;*k|NwTuUI+F)hof#t1>jGEz1U{ zo`a6eKkK0(ymUQ{CK-Hx2MtqZuIBU zUR{`!fnG!A3%qA_9bq+=OewR$$lIEz!823JU<*(WDT6=IL?ePTSq{t2g0;jJW=wvo z5JQOc%yg_XDI=5E{_#q@It#j83f)GMY2$xkYbl{ zSY=7QBj`w3bvi!uGzsA^nrT=lthyX2$7TE)r6~^rIEb_z$c*9_55wvUG*fu5o?K;f zl(`L+{NyqklY5;@y6b7llk!}mOztqNxvUn|!(b=n*6Ab#Uw0!7ikSSkZONDNnNg@V z8*Tv9NjYNe{VN~(eW8VBE3>CzA{mCNB^fH=Y58m^^3@Pi83>=^^Rf6$TgwhSuH|5h z|I~Z~MA)+bgPD(T&OBofSN+85^T%$4CyZ^T2JcBvs7rEscYp-WkfmVDGn6hvUgHSr zWfFQ_OvYrpLQ;eOR>CO4P`ntAgrPc;>z7ea;uv@1b2N+(w$UJG9qf?c=~y4=%IH&( zw2AS<8-Olm8TI-Pd>)Qv1kN%!MX@j)m28D`LNt&m6j*7d<9l2x#K!{AXaNbLQi07> z8=1mZy3}X&B{w?r1q0ZoU3j-82bU~yL zFLve~T{Ob)+MT(GA8n_>Nm7ASI{`j zO+DNkanYKh4q9lajx|UGgqE=DGbmfb*79@h)WFpi8j!#mv5Bo?CTLpE))uR--4FGS zIHLrm_>vA9@uRT@8d;u*HO^W0oj&VR@#nJ+8ba2<3^Ie3FpvD(>QV-|^=RIhHtF2*bLlrHV8(l4~ zCu_}6|2soWhRYW^X%uP18E|WxQo(Ps8@9<|O&;0>o2QAFbkV55QmNE6FPL=VS`b;9 z3M7<@;1+bPLzIEPH{l}kDwWDuJL@P`TFM;$sgeN2|JFr2ROOZ+v9J0_I;qU%IF<_j z>;e+v0kWlXsmzhyZFJ?uSq^^>pOzPgPNjuXxyu@p88RdqQm7QxNNd4~F>|vjEn${W z7WG4iu~dR$m^$dCN|zjP%2F0RmEhtHq(i)W2*->R%>O|5DcZKPE)~x2eD1%+%kRQ|rM&AOK}c z<*e&R(p;w>MWP=~I*kr%Gt=m(AVfK{=*dK;l#j|ZF=UE!deXiellJg%lm#y7OxveL zr5KD#Y3v4cd}x+o$HDXnBGV7O2|ULc?BX%+FP)zEPxCHZOpw>3pQJeZ{qdX-vitP` z;8e~y6%h9WAyp{Esr+O@SSk`iVH}YVhWwj^knioLiT)z(W7cUw8PmKFZ!zGqX~|xw z7EJ&ahb)V4YlHX1!(;A&Fl*gn+n5UE(P*++tOuIBrP3_&zcE;%!(5m{TZmyx&tiBDn!m-|1b1D;mBF5NyR?PQBSG)M%gVGf8}Sk6 zb^c5*O(!e)crPu{;BlV3lt*r*kp^+j^A|*jV`}`M=r|<~L`WRsh>s<|FW$qI&Wcuf2)Zc{#rAgBQq8Q~t}FXlmO@tl(t<$6XN*aiTcp1~=mHwu!t5 zl$U4HIPQc5&ba&Gyl^rW=EAz}b-?8i$7PVQ1RH@*g8nzt2Q{s5Fjnow?Kca>MsKEN zo0yloqe(l|QgcWi@=b_suW8x1An{Ecn2%~O0d5vSoxc=>iX8@-Vq+zzLR zy?8peh5vRth3g6YAKM|(?6#}>paXtOEm=c0@&g~!z#_^;bw9uhU2=CcJbKx7n6FX>3 z2x?@=aa=|ahoh%)j)wS!9W=CW9jdh*5iMBM;#9qdCjB0Z576xQBCZIb+Yovmp_2$@ zVeuSR#b=zA$RY0VyoS)fu(%I};*DI#apdG7tgJ(vPPrV)L8O`Xp%bg(eE3#`hOyXz z)Z#wSRjh_!^=a(A7}Y<9(07R24SgDB^FQ1IXMo=#C4BI^g&N5=K4&MrAyPhyL=r0Y z0rKG8A^F!>{D$(^cG6u+xDmu_cF{EvjUad|0Is=iHH%~BmR7k#T!e)W-Y@NWDlKFH6E9Ac>73l@lbN{iIm~wxg*I7Ps+n_i^j7H2a9TlvyJ0f1xL3JXH}2q zm!2>V=P$k#pq)>G_s<^;pZ#`V)kLVB?V*uAkv@uun33?3q41Iu1t&{~!|VEeN8^%4 z;@D6e<9BdcNtW|JaT?QiF)U>?Fm601aVT-+VBvz1LgO2AMhcb>6)ZnnuwpoI<#5c( zOKz%sZNGZZCu_((d%{Z*n>eDMJ*1y~GWd;%VZAiy9(BP}KN_Dr62EXLe&MJtXf)g~ zs!ti!r%re%5*ER@)d@adDb&$E{YEfyLdsxD@kmPLiDkp_v-?KktB2yN&&DqRD<}Gl z#V`1I-l6P6rZ=k2O6!NNTW{0crQBb2P%{+20IcX82S!fx0V9`Ij+Cq$Dp@zGi#W7) zaBe*`mYUGQr9MMmh5d^UMIVU<14pNiMpTc(WvYykxV)jbyrT`naaAL6IKfd1#-rm7 z_f?F<=MTl_A8j9wp9=#3V@EF<*C!laJCay9lvsGeXE?EDB(e65oMF9jJUsf)_K}$E zp_uHWDZ??PBQaGchY9}Bin~lD#p`uj~a*5=fdQa`}EHr^e=kb zt9T+*;qAX~;hu$q!DT0!&w9-T{i5s>oW7<^Tie4 z)5}_g{}OV=iXmWUbyC%;H1b*ssj4Tc*9>#Au=-{gR8^`s!{_R;db$LvZmQFzbG)&7 z#yzO2UaLA26(VYR(CDk`JCkp~>R_~ARlUDvFxM9!L$o>`u_K8<6sj6Ynxnw#yGc-u zP`#TxUxU^2=^!v#b%6?j7qIhq)rIhRmDuBqGi5M zP}M4pYG8hRzNlA+23M`})D2YUz!30R>>=ivb`2kPPCk7$o};$ad+9gMpw ztq&N}oQO;(0geU*g8PVPx#PJ?;e5hPD8#SQcsZVd&U%QW!&NZ1qCMXEbauE(bV!=O zeJB4^eDDE!bM*VLdB9Hu?#J!r6vET*hxPHc2Vqlr&;I;_^aFR_3%JqXNBQdIz;eO< z#1Yy+{C|b4;x^p|kZ&OJ!#wy&dPMUy;-BKLK1t_ljsiTE$S*!gL$a(r9UUgQx3R4E$>U;Y$LCJ*zQpQ8EcM^KPkhsgq;(PUY4aT3^M z@fA-uz4n?)&qSvE5|2W-Am-*PAKTfk$ z>RghsC; zBVIEQ*KYYOC+J+d&d2`R33`xt7lJv*)UB4To^H9o-uePfaU=KepAFEOT=^Kv!J7*5 zt2jLTaxFiN^h&Gw2Kko=xxppDF1Ug%zk{8e<6bY*G}Q%w`9Ey%%cxDKsLns54DJV; z+N~8CPU4^2yI-dF6RJ`1fLH0OFeG|uxc*jFO5p5i;-r8P1CLWDvM1;K)1aX+>T13$RGrkx?`QTA0A=nj=%0P_AC4fq=@0@eJZKhyiE zQpxxHh5n4@`P!rYo3^US3j3`eQ4a#wDf7R(AB@+qAIR|r;rN~4lKLDjEf@lPyn#6{sb?bEXoXZ1^d|EF{Zt@pLZd`7Jl z??T))LEV)J;+ymmU>tMr+$4UGV;%EqF}1cs`i?)(vBH%+$CbW!KBqP07JJkeptR;G z?CM#b_D|YRa`|umNt=W6Q0d3fX1NH#cL9ZboM(JVQ^|3@`b%0Fl0S(@--f#hA0bUX zKl&wY^b|}#73@6xE1F62_@b}iqjxTE`-x{((>yglc!fr*P%j?!J$zbO`wjJt#eU%WlDIt~oJU*}7Rn2io#G$) zhDNM$cU+!>kH&CC4OfUD!{l}=+?42UfL{--(ci2$cEZIGWZs(E-2=bPYJe;HqA^Wh zW$9g$rf-Me$qC|V;2M7E8yXTJUdxJba3>}^aOk1nH+)UQbmEO?8UYXemKJ0p*OpO*fU?S4tXO!R5K)8-D`Yla}#dfff z9%YKbiwhV664H)9~1-YML@mP2ajodt8$) zrdkX`yf04;s0dX_;QilI-#%eZ2eV@w;(h1GjEp!Kr??N~hFU6cRR~8G{D^~g{27ES z+TDMo-Cf*ba!egc3f}5h3qON^pT?laI6MfiGNt{C#`TG5)jFJ4^dtHf;}8p37)+1- zO&P}N3StVUum~C4rB#BWt`$Va;9Nr+jt{6#;7~u*KdLJRNWeKKyoZ_HJ zobwsIz{d`!g&w{;1->+u3c4g=N$oUCi4CFwWxj(p6VSQ4f38gR{1WRopqS6@KBJ78 z~h9X zt}&SCM2sDkF?89gLc+O*D*xOkZt*{ft6RL%i`RVd{*Slp9oL7%JGKfn5V!ku2#L$v z*$7o&;kdz#kT_4+gwPFGh>OkQpkX&w`>_z0GsO|XuatdIe-V+GZaJ=oiF1lUtcpW` zQG_mH@gWxCfI=KHe2G&AliK7pZ;T?u*h5QmC zMRxN?gvPNDJMh%jrNznGjP}6&OOC>-0gG%Np;9K1yX|vS${UodOri1roW`r;KUV@Y zfzSjTQ~{_}w@->Lpf++l3F6nCdN7iGK={r{qH=v!`UDlCP&^j@8BL#43b6|AD-phsSrS zpSVN#W2rxy2Y;%+SS6+7Mx!WgQ<1^V11Y=xvZ0SAkcS- zq8{?OK-(>bM(Rd(QLpRuL#h}pX?a=oA$>p0OS+_SV)>=RRnRtDm4i0gZZj|cOqn=SiA z1#wLP{;7mb6mN=Ygb9#5AS!!EP6FCnqN)eY2}8P4ye+09wOdR~hR#<*@;WGHPz_hF z1L;FzW|wpe@y@(Ta=}LzSx_-rB zF&DXD2Hh>4aXV!nrYx;QFa#9S@j6AgsT$kd6(c}$%t76?@| ziRNoIcuXwx=%|7Iy)PDFsdK1m#bU9fdkBc*;sy`@EPv{WyEl5Vv~{^HX~GF{qo;bd z_(0r*xH<=ZX(S3t{s>({gb3N8%RZ;%dFPRh>Uu?`U7~i%tGw zWB*K9YFOA*tL7~=RW~)&H8oeen)8-=HQmtETsuE+srStKx>{FrZQfGtQ9B!{Xpd#G zohG(bIt!SMZITNMnBBkKcV>NUwOTc+uC~6WNxQFreZ*LRY#z);o40Zp%qJ22OCB7| z`ml%Oe+RQNpLRo2V|`t-`hXl)$P$e&Ajej@xR8xzkIQ|9EXBM7NlS2@c~Smc$i^G@ z0HG;X7FDu1S&+fJWz!Jmb@kx1$1g(}-D6)x(G_ zLX6b!l)sN*iI#3gV*QJWx%!-Zr-EJ2rpx51EbclD#nI$a^HFd7p>YqSt_pV*iSUa;B%>G=mMXa7*G-?ft z*pqtxCznw-vX5DS_Un!84?89W~X>wM}X)5Zrd!QoEh?WxeE=x3ha#p?1?MX7Yy0+t)&6n)cLMR=~{JsAK?w!Sdod zmgkSgsX@?the^#)r0ZK2ZJCD7cnK?X2%==&dKMFj2Dt;Bl;GS^`(n=n<<|A=IrH^i zFquMtX}L}Y_UFNx+RAzxL;H8Nh*%+lhvl>Pvfh5E$Dycho8-BBSrnM-eIHDpVC4D} zm1iI}QU>f~p)62NypIiJR=N5;Z>Ep14n-OeA4ieZSw{2q!_`6Qgu=%ohH}oJ_gPIQ%%Rm&Pp64N!E0^zKW0*@G z-or8>|6bn1B8@os?Mbb-WCaIT&up$+R9n@oR=b)IZ*W=V@aNejwn!VSu}j85q;CFA`s2q>?*u<9@t$$Lw%c!SJ(os}4=iA}QQb;w?A@;|S$br3EK_OgX~Hbwh# zKbx(v`()YMY$#iyt$&;8nRydR-;3Zrx$Pk2jb=?b#C}&YNEMAH+6a;Lx8@%OQ`$o| zo?szz=n+<9!Ku^kH3yc)2K5HDMOptym^^%hjbrPz$fN9{0*j&LI7^D#g013Yboh14 zQr}?5X!boKCm&}C>|wd|ID44C;H}wCuw*6bArvF$VZ)^=4Nxu;^W^kXtk^X6#fOstE9nY}t6>_P3;53`ffA-eA z&afl;Vsbo%97W4Y^qBtY;h-us8Agg6Kt^93YR-)vs$j6mjBW78h*@2jxg|E?5uPd_#F0$JZ0e1`92>l*T~PY zcv|@>hJDahj3x-WbnLahvATH<>?TUQ`2_xfk9MCokLB#Ne9^>VdGOKtnE5{x{*xk~ z_2+T0etqE2XYq?Za!>%@%jRpB1Ne4--z(TnoWSa@ihMejNApXHd^eUC^DBxBwejBY zs|~a9af~gH>+F2E6?aQZdA^-?Ozptuh zFEm;Ot()U`#&BYMz}+s8_X5`LufkTQR;{h6s)Idzlgji^!x3OixBDQq3U(>g>b*F4 z25E`ssmx2}$Ma{HxAuKJKjjrP30eUU(Zc&C>Q9zy`*5rLK9v`-Ra!79q%V4B^lTGf;<~CL$ z&t~&7mLW6x@u=u;(O6t3ATN^uYB$ZQ!#V0|0BZ<@5P z^LdlMEe)$^XZ8m6I|AjYS<+;aH;(27EfgR~a0I%&LAi{w+8Go`N84%pl!e$2NV`lG z2*}bR)cz@YVGYs_VUgC&D3EYOcbiAF=unH_At!8?K?sE#JD67d3-XlIZ!3Jo7O5dP=&pcLtJW}RK^hMlGM)YaBb_l$i^xj%>dO*!PJd^R$WG@jzw%>(8guF< z_HW%iJvcBHY9d9yT)kb_R|h`qzi|nVB$Y9GF(B74N+;MH2%JT1gHmen)wyDwu_b)Q zJ~?C>kBA89=$Ok^k?Zyabih^-CSeJSu!2jRHpn76sK(?^e@+_)2+L{Rwmd>UJ(rv0 z57T*+zsr6#i_D(O6Ip)ig2j>XA~$cOPB)0*2^{~blVMDC6@%O*XvQvonac~6IA@$3 zIFGOJi?6VD*2Pmq_6%4hp=+S);T*8Cp7;4ns3!b1R1>Zhs!ATT|9={+KKbcJcd*KJ z!93g_1}C8-OkIic{0wgGlh}=v6jt%Kds3bbKpRua;(bCqtfKN!p$l5RxfMF!LsrRe05C6GJT zH1b%310+jY*}`By=5%y8-ma6c-N+++9PS?F>g8D|S{)rWboK&5S`3w27x5~?u(AlJ z14Aor_%+!^lrd54N_D1IjFqn};0|-D(;-UGQl~?nU%;cHQbnf7$bg9_My4A&baZvs zf*w!xbk_mhX>A)7-nzHhWJrTPlwlvR6xZ9?yK83DK$O7D=$egbp4n)C3E@mbd#wXI z+7g5F%H65UnO0_Ly(PoSM#)b?cvNs7XP=HfmnhZ!An)hOZDq{Xx^=maoYll1lL1ZO z(WmBeGtFP=U&UjT^ol`pS0%Sezh>^!yQ39XUuWMAW!2tbMYWfthn1nSJu zF+M@A3}=QIM`jHHUza-j(CmHhA}lw)3wfrJ(Tx%nTt(#CVh|VbulDNH@7n z3%MV2mwRS`;Gm8Gfu=HG+D!QW94eXrYp95ckh=qEb_d~-K%p~wF?aZNhE7?sXXaQT zcrtWCq$?e6w)dDPoq=PRDA2hnov{pj2ACOxp}P^-3Uz!EwTG($@XGns+}GnUaC{`D zX&*U#39Q&xdl8po-)?iVBPxBoXA0;5PSXE-g(lC0&g?dbb{Ocv!s!`mW3X;=W)ttL zYvQmh!vgNglz|bjX~>kv>REJeF}cGl;<~)WI$aIS+i`G*>&zU_$Mtb9tFA0pCK%`> z?_@c>J92?5%b5kfDJPF)1?x)q$Y^W;cpb>gnNuEH#KS|c-brKw$92e&lJTMMbLR|jCr@*2hqSvaZ@!uP_;y>_NlI=3s-=Td%t<$NcAOCd8!mm9!B%n_ zdey70t3A@^E#`K)Dnu?@2Kk^0R}cB%GHwbS;2h97I51pJL+g;s5wdnEkNnFR=fD_O z;~1L0pc^S8QG3Nm1Kw!iDWG@Ke zyvg}ZN`^a#BRzY|JXgLmuWL{094IrE^U$0ca|H1)z5+NRo6WNgGOAfNCh6N^m$peQD`~^wSrhQu_n2xr#T*Vop-h1rMbB)TvowbOw?t&&UD@+>Q)uztFpk7gCJPb;^zpnxOG{aj7AO3&k{(A7E4T$L`F=!KWA;YMRy zc%)XxBcS`Gf1}lx5xj%mrAys`h~0q--a?FSkgr3Q)kxcmAOk_m0VG~Quo4yeAUEB& zc3#`57Nq@#;3Z_~_Ckh5x*}YF*sBPZBOg6&eu+gq#j888r3AEmH)3BP?H}0WLwLLC z7$i&Yfh(lXk-tqYzK55x+48_Wd_gc?iNa0$%)0tIx_DQOIw>~5-O#@`@QSEWAlx22 zOKn(M>%t59S#|1sH(Q{bu#vB@L52gBpFo@KfpA%`!owO~uDa@)>#FOU2H_V8$r~l? zP5C=*~j9tca<@8@GJKbnmrSlHST??n!IKcwiqMeDtpNBhT`bWyfbk$J}=^IjORH~)BK z*{Xo^CS5|xsrce!@x`*{NnU6#Vdr&*1k-R7oXe`t&0JQ4`{j&Vzinr zWEld3F2wUV(}jV$z#4wRqzf9)E;ZG|fZbZ0Tr@F}9q7f1CV1-)IEH3m@n8fL&H96p z!|Yf*oCigJ{o(wfepo!}9a=OYP=7SWN~L~K8KytlzjzQ9PiC=}q6rcDli5RcSpF~@ zs-yKE_8Vcu;^{n)wdv0UknEXcs7%zKNf};l560q; zkn$$<(f^oUV!-0B*}aM;Wauy1jP#Q1KAJHH)(D+A8B$aZY zlyCfF;LsE-Ua>)OuD!7eY3_19ltZChFx1U3 z$^e9LecLFbThl0Hh=Ov#Fn3d93xN=;ZyTo@NE*fsgmN5|bB9@oFu@E2Fm{4J^q-JG z@^{+=7)mOGC+HXaMZYPYa;oPSyi4>9Pd&DP3egn&9qj&{$UMJ#&##v+)lUrdl*3t+ zn-Jw8#Cm??@K@G9%U8#~1v$aN)fJdKo<_X;ha@#J^f|~C^R$}h_$S^02Qh!(V?psG z5ILw#dX-nOpnFl2KB<`vQS4yqD%tiLf84kp>FZ>}>wK7TBPNn0S@b%bT#mlZ1L7oB zZa{!o)^@!5!E4Wz*LezCB~$kD{#kdSxYzt@S2Zqkqz%G(d~Y_?Ord>Gyj?vf`D^Z4j??PS0~S3feZDNclj`W-cPH4mv3Z#ap2K*L!GN}VY6!20*>-tUTmWrc#@Z7!eaN%ld}Dt*~e0 z@89uw^I>c&2|M((?Dah_v3-ezuMm8V;2Q*6uzojUTjgEf^Z9I<_Q&^JQ}_%1a?b^R zgkRLl+kWB|{55~=)1UYjec9eY7D*8OM|jw<#ygJ_e95A^1oZuIHf!GvIo;j43(ZzJS7%7$RR~%1~z5$d#Dn z6WG@02u>qdj8WhHt@b-yeb2~YTv^V)^4H$vN)yLN&OC$Str+R?DNl~{R-$>Og0E&_ z@+NPkm<4KYcq=~4xDJ(Wknj5_t5}q*Fex>m(P-Rb=#(hL;0h6*uH*@mlEyY~G%JNH zMh-D6q3|==tW=qaX(h4Cy=J8^iH&a}&VohFxx@r8$6l@Q^Mxgx~QR%C{Xly1= z?h8=DEVPTYqwQPKInnZ~0L5YMPKdTB1NwLrtwZ%xd98-@Dmgexwpf&maC#Fb|Bxxz zJZucDiahVHgut`j#}*|q4(q`{JL-j#tj_&-OPI%(ae<00nAl7`*yLGXC0Z8xD~7nu zFylZ;mr3+_Kn!+@ltjx7fiNJ^vMo?acYmN0B`*dlMTztw3)x6tvyh99q8VLwZDR=PIpI;>Mc+E!uW#Grj5Z$35@2*U>JQn8kQ*U3|0b)$hln- zMwPaP*K#@1px5-Y?u9mg15LoEbRP#Rk$D#g@ALrHgY~~6l{$%1O9RJMH#WlegB4B9 zYHxdy>xOA6d;yRVqQtk*c$?gTLqSW;(74bvAtmIDE>Dq+=lQ*hidYZF(L*l{PM0R? zu%}JbI>a3e6mD_Yi&D%Tv51{Uj50n6(YXA@+c7dQR0%bb<*Q`xP^EuC0^0ExMslKw zzL8VOiIjyaunkJZguN=ageqw*XK?y20PEC~h*1^UfHX%?w-G;&_2eSFrg5hR>UKQ# zfbuGtM#+_2MH!ZQMQOIneWaV?LL*DUlsq%dFjCFroncB+H^LeDN|+KE+2vYlgDgY= zhpV;78YxXy<+B$0l$K6MbZnxphUt}_&L{ZUs(KLtoqU2RmJswp;Qn3`F*=4h5vxEz zUlY>#%!Nhz4vP+Rbh@HX&9-C3(@G0KI?}lhd`P4N)IP)xAvlJB&UJJ?JBvj+RGmZY zCj`GCz|RQW$1pl$(H99>NE?KJPK>mHT8YK&2ypMvPkjc_HxSUW*R^n5K-wbgJFXt8 z0S7D)L4lub$$Wr9zlO<6QZfFxuPVBQ0? zux_j-oe4e8X{ctAoOoh7$&Bf=IhB+4L`|lra@mu(Gi?S4Gy#NgQct=}{nt>I(!_4( zocVqCEdVJ>YI8cz;>BC;yUTaK{rm3o-NHf}hhy*Ge)U}BEXVx~U8sjqKGEGZ={W9- zoR9PAj&TDzQODDH!Lfn?y{KpB`eO#sfP4C5M$yQAO`-|EhGXUdi)b0JidLRGV;nA3 zo6h|$qfF>1>HS-plW z+@t>UIej*I?_7cC`d7YL?6WIxmQ3qCt`BIS9$nV%k3^y|e=HP@NVs&(`9&!>eol%; z#-kJGf|Icmo`S5tH*zU!9`w)6g(A~gZc>>iHNlzjr{_4`-3WuOz@AR)#UsvW8gjVk~R&N2Ciu(PPZoLQ*Iq#r%=UU{){1#H=9@nv7-j)4^EQjKUv_iCA@u z7?kFK06~dXjnDpe=WHa_8R#7J^^czvql5-h=Zh18iBA7Cx*4bL{E~7pCHiNB7oy^e z&u;+_35_S=@K^u`7=) zSyS$|w0mNC<`2Sehi~jjd7s49&6yvD-wh{xW2vKOaG7{vBITS+SSDBPMW4N}cyXy} z`AEvym3F@Hho^6h-aP+aEY&@NtHkIFDZ4*m@ZZH?xJd=C>6|0{WfbuQ?tT$?H^y#L zaR7gQz<4?jLj+wOE^NT0VTE^T4dA3(x!4Sw)n}1{Eu2u`D`5TEK{a_;n8P2`&}%hN zOFr^33^fd_#vs}#%+(kxQqLbq(HaHh+WWOX(n*1!m5Vws@`{_%X#D)Yo%U zI*7aOs`pz1s!cjlSJ`jyhgo9aABtAQVXRNwmA{q^6 z%~S^ckwb)=SzQ;HL1;FszZ8_fGQ@ar5q}ho`omK27xY48%NoN` zuqLqrw?u#&vXY8gDq5&uEm=n{%?0~JF)C(lr~Ki#eC{!1jpykqTNnsVhW%nNFdjq2 ztd+{~2v|qf7Kw_p{%~kM7?5b_JPwhTF>40b3W}3KaW}50XQ>>7NNmLMg~F7%F5`5s z7P}V*)1@6tqp4zVx_Ec8cz3FJPrCTAWbtFE;zO7F*9uCFr5Sr^qOvVzZ(DVjFUCLL zlW^3rTiq#p_o}<{TG{6xOE~J;t?eoM_El%qwdQY>rk&f8&TW~B+C|4|RqZw5E7j>L zPqNCBs@k5e>Pl91rK)x<3}l>DiMo9$=e|ru4Lg4#<$MA!W!x34K~Ku=S*_i+6#xA| zx^`ExcGqHe!tun7<{K6GVKur^_OAPC9K2DQa2zB?*!}8!+F74;)~B2e2}{GTRvl$u zm`~Un?{Ye0>20TbO^@G?rKbR&KPf(9?xZ^_&H^e+*mx5kFY~m;WA&Hd!EkUgIvoMt z^8N@Pyf_yQO@?AT1npD^2u;$lQw)+I#u+~moQjG;o|r%+)*;P=reeGpjmN+wyf)j& zOi1GCAA5}Y{&4sbFM%w=Xgt6NqO<-`q$3iHL-vNf{7F^nvNyyzk@N!UCM4O8A0O<9 zM#7g4tQ!h12B`^&_wxY~*R!Dr*g|NMD#gTTn2$wY3`Te@A&$OF)^O(2c@#nWU9io*J>rrGa3SgqYsKF(8S-Uzu zbcr#YkA~wbZ-H%nY@3S)g8YI zWge57^ot*tt$PPOvHMK@qGdWn=q)zU0L_@?WDv~QBA*-B;xlfx7#A?@%hSC zJ}!y0sU&UAHWvbr->-IcE1o2=fOs@|Wj zemq(Ic&fTL<$Ch+z^coAwfuL>ui2KKT(+fLyV9=xN!R|A>%irKjM=ru8Olv}IfKQt zX5)&ha3@iACS^VY^(#hL~UNUm|L z*(9U~VP&=)6FCnRk>RL6%#=~6hZ>(DjkpnipC&$Y1^_?1eJjV4BBtNSO*%O@cgi9a zbOLy8?rAU9#*$}>SX6#6tVeqr4wYwUMh3t?xD^V7#?b`r{gVZQJ2=jcQADikdU%-X z_mDm#Ho>a)>jwe|Hth;;!2|;gcCi0C!Ku6kC@GpEDHu0GVTWc?MC^I>3=gjNFx3+f zb(|`c^gCpj)^S`MkeT}{p>WKig75%f6d-uH*1^l6!doaDFBk-&Gl&&M9Fao7DzB8% z>NjYm1j|@XX|)d%X>B-iD==nIA8k}v1JDkH2fXbwsI`Y09#jX=!%XPdYy>`Iu8n__ z(V{P3!4Uszj>e=y*k|?@0LK4Wfw41U@mV&&7~`ONVf${KuLxI`bB2h^*Tb%z%5_N|RhT#8RnBmJ7@bAjf~%1e+(MBG z??|aovf)mdItPWKG2ZBcP^94-(TWAs2rZN0Ryk%^2F$9^cmVJ{2Un}u``8sTcwn>l_oSU^OSaKL7RQg_Fr#7k|S+{7D z{%aojR=L(g?IY{vMpO65y3S2Tv*nR*m2UD@{UhHh+vF|&k#ALP@>YXj1FRcaxm9rE zyy=nc6sr*2wIxym^Pd|ghslP+*DTcdws{LWb-ot-*Xr~5+V&g!!Bb`+InL|8s6SzJ zaFNlsdO;;l@ZcV~4OseJ4_%$MxzT!iDdbSUKKazZu>5H0k=_R{fAK z!Xw@u()kJ^yueSw=GnpF43g&Q#~Hh#KJeh`>`=Qs2{>}k9BR=g#+ntd{ zq0#5<8CCA>z&%}L>yW|M6>0SCjBFJeg$7|O@mGNtEG>90};F?zRbSd3aAN0L@NlQ%8%@34|x=YT){L z8KcK4)!v3Z>RImBw^t|-n#Z=QcZ4Q&m4p^yTQ_D*2TxFG2E1Ej%~mRq^^qxPB{zA&t8e9;d}tGh z6RFFC1Z4fj!?%6ZBh+;(IxD|UmzN6a!L1{8y>(5>@03n;7UqwBj8|J_j>RUL$s>Ag z2mH5yx;qS7nBxAvn>5$tUOn8C2mBmZ-EeRs9ty*Vhb21`6k*HpnkC0e!5BX!MrV2Q z;G@DJE}>~=(DKYn*{->9!k285@V<(88L^mfP=3x| zn2AcPUxEvN0S*u;J_o}#7zhU1`KZX_om`K6Jfe&t;I$10V{tJ8uL&F$=YtXQHK<@? z{u`P*0xAB0Kj!CU|BXK$n~91ca_!*ZL>z&kpd{Ha)DUWsy9XW|c!(x~;b>$UFo~*Q znF>wE;cKNCcjT&fGT4Uwmx7|##vC;#V9}e{)TOKytAN-OVoF(CZj4z6gTpujp(K*) z8~$f<;o9>od^k0Hcp{F_W0PEWzEPe0ODf=BVr{*Y1Iv8HWLzZNdkGG(SX8{!bK)hy zI~MflvlewcA`Ee~Dn;Yu3#JRrae#9c%>?V#-6gEvBzA+loxg_9|6v9*IS9LS6tT%g zY4Tm5Dtj5$6e1d^d_WKvsBBrS7tsp^n=yVwP4rI9)CU`VNUcr#g4o~K7h2H|Q%r8d zp$chDNN$CI*tEagOvj+C$%mlDWYsyTzcgx?RtC*ngV7&7qV~efF+fQ$z#PM<6jK%M z4=_e8mXnLUJ5h#W!c&O%kWJ==^_6&+}a1yD;{b5kB81lno#lsN`vX;qS zn)D+o0iWk2D9xMIwP$tSdA)b%l*cZTR1?WXk#pv;_(#?(2Ismb{OJ;p7ZUhrH|GjH6xYCnzp+@7s&NFqpD8WZY#7{i{W;#pYMfrHi&Ci?*bS z_;k^>WYM-%QR{*}Q&P5AwqRN-Fk4-#W!10mx)%RRPr9ZfS<|sRd3{%^W^bx&-@?(1 zqvUe~uMAwE_Gg@BX(yj_@@Z#d(%G0PF28EK zVtakp>(bJmulz=;X8Wz;_B$r7sV(K)^|d|MntxBYYJ77~(zz>P+4ZY?M$T3JdQZZ+ z4S^1;>$am9fex$dpMUP$C2hgfZai6XxS3livK>BPSgAEp*<5^hpMGVp4&}P&F8Ny- zhxlFaf#ot=v!E(Ns> zkuZdi=n1qi8(qesFtL$#DxzN2#xMqnpQPAL2U8am7A!%<0>8@*8pJHB9pYP!j-M6tARG9QfS(rVAM#Q5ivL=W}05@w4VHqVkWTgk1Ath;! zpq>}ww~$HjV(^mWDN^#6khx^dg@UXa$|60Z%NpboXo@5RDxqHHCYiOd6_qmq z?D9F&N3#}HUT4v*ObOx)joObwg5?d+=Z+_oRj5$~;U)mh_Whfz%fF-kT_D(xE_44_ z%oSIBHN=GLnuX&V7p$4e`gCPmva;0y!2wKV&}rs zKXcch!=KhRFIqC?Tdqc~L{jD37WGJixK-ZsPGzdRC++S@xqC9DThgV?$giF7055Hv+hBeu=#I3Z78fgA6lEXLN4X~f#ZdEEZ(U}D2TW}L(O zLqc0ZLKZ&}jYr_m&=e5}YAw43ZW{>+r98YRfgrgsCSZZQC@BshjlYTz;A*-FycW}t z=;W1QLYn7Uw#!T~49|(IRFF4@k_nIz6Arf9&U?hq#5xB{GG}r8lZ;*Xq`XV<{tWsG3AfARsznLXLy6Q;r{hI2-xL1UDWpU1W zk=uWyMWIJVCk-11EDD`wQ9utOU&dxVA_$JL)1l1;EewL@A5|ZA1x#ROR}`T20_}ZJ zB4uwz3PwtN#tvB4vn3-gpGga}n1`&mwrJN@1UhUHea^>%tWTrQzMpIZ@ToY)GuH>p z!vwCm3Fpc2i;<#-@e{N*_+ZNf@Um<0qTuxR1(wOmEENh)+c96LBW%77*eecgz639_ zG)$Y(X`b&y3ok(8IeZSU=1YMZIwZF|;@qqaK|fL=7)D%zQ84)my?K;B_`C9Z)2f{T zhqK}(vBTmhIw9`C%5JV4NAM(1HQr9D@n-m|!gt+#$?Dt`+tu2NdflOpkJM`smLYaF zFx3>UL|9iyY`vJD9VLe7-n7PG9_k@Sy*Tqw}6LySyQmc2_w$TdXb6%uPHgHQ69vX(h9M1Esz08v<}_?xUj zVy`UwEL)^_n&fvSk5%kLjg7W}HHf_Apa^S(*##nDhB!wBxy3y0tc{#&GFY<)Qq#p4 z9%Kutqj7B%MXCZ1KUpAnkqt%!f^xD#KTl`BLB&f{ynrHWRwl)?eNm!YCVBO;g^C@? z%nJ$rY1xB3PJLz#*qZPnGm&z(0nRS7LpIcqdW}`jj{N_?rFSq;X&kHhtIOQqyLouL zGF7#2RK8Z3Y&iMO^QnfDsj8Fds#D3TQ>m&^rn8jpnMN4-Gh5JOb;YwDM}tm7Z&%w7d1LopWtlG>|*(+WwyuH{U5hr8Og0 zSiZ*L9hfDhb(y-BYsVL@?>mYYdtd2aIFf1TxL%WLcEXvG%xooQeKWeq3bzwlUOPjeVe%2Wsj$-!i4-MVyNBRLr2rn&?K*vXO%U@inUQ zWh%Zx#p_h~QOIWX3kvBxfkQK^AIwhwRc7^roB2=F|7Sot|Ci;qwze&pG8J1E9GR`n z3xyeH@q*!(h8fJ;=y^>W#rAF;&@?uIx@$cBd=%Zf0+1O3JUcU1|G#`@-S( zoh6_9A9!fe7-7YTsf_d3~t@fSKjQVI_+POdJ+%G>e;gLmqv?J~8N;#%{m^GAC5;l9H|xH{h7yYiWpPY>~}!Ha$*v{OKp z`AFeCLq<9O350z<5r>fh2Pg@uD7i#o+pN3^`RM5(J0s6CIzAPhj7vTIQOwr?K?)xy z_{C%>lr;x}Q~r237Vm~{*X9fI@mZKM@OdIhJxuZ%QENnKMY_N8y+~*>s@X@fY$PiN z4$=S(U>5a5c$-)P#lh$Nv6XL~4~FR+kK?jkGESgwS6s9Hj_3jAN6iIJ;boOu2+s2U z*$ISu;WWgQ;TeV-)OIR5x$;eZnH$QsZe~ zA4|gLDdz0=@<(y$=Y_#ue&x$2`VaT=r+SBn`;G|1z5EC^3=IuqL8w;%l1Q7X@>rVz z;l#)gPWp!XPK@+X`+41Y`H^S@P3o zPWcQWLqonh^uZh0_K5?0>rUjj1>J zifA#P;Z0(~a4UgZw6dNe(eqKh;}9~1&@J)g>8J-BARYl1LCt7*26;myHwfirMUZh= ztSjcIkQDKgO)L2Ucp3c&>wpZ>EYO$HJ(^<(g*9bqS3$3>+bf62a@%Scs;|5~i+70_ z0Aef$$Slmu*bt^np{RxnV5wxK@rQdM9diqpLz{M>aUe+X9Jc5T4j2d{X;3UtF0nZb zl9pB$NGqQ@aTpAq+EWOXWZW}C@9}4ZzF`nLt%f`&m1m>Dyan0F|A+&~Xdjw@NMhi` zAQ(>suObo2pI`YVao0)MXb?a$W0PmUjxBn50ZzWzmG6Zybiys=eI#UsW+AHm5t(^2 zC15@C3xPZA@hXl*>{pi^i+O=JULrBz2e8mCi8k;AMni*rzQLiq`7u%;21R2=PKZoW zDlrk-Q4E2d7&50Lo*F5n2J1yx8vdR6ygsVcPoOk4x$80F=-D>0x4@<_%S z6s-#mT~$SBXKE4oq}739mU2f5)?#!_{So<*p(8`SJf%ZxMCNGm0H{&cHn5IJ9AxUq zeZ(rWcI?bVhcc&C08gurWI$*#e&P-oFcB3knnw4u+#vdkwDD3rK&k=3jG>vz{nv>( zuWcU)n+ZIXnQvg_(C|q4=o^Ld(U0HZlf!)@y(9gnhLja2HmnF}d2v}Xp}z-YE>8{O z3k#N8<@GXvO@yh?d8nKx4WJlfA1TQqCjVp!){d2>WJHjy8t9cpcPIh{QHq}<^@3kn z+B7>6qlyHlSH1(jujyk@>_CDHZE}>M0FDF>aYzVluwsar^$=3pAQb|N6aysW9tEUFfCtMJKUQf+m7&;wpC*R&^T?S z&eO}70B6!A2Pu;9m}CL|%$6 zo28QSODu+HW#!F|Fiivsw*XY7922k_;^)%JcVt4w9Sjq}DdM{_hC)2jep_h@8`Pnt ztyexNfwwcymcVGRiCTU$M=}w-43Uf`A%u`1Da)#Sxt~Xb2)kVj&B{VO3?7GAAI1zd z9Kg@hj3G_M5CssG{qhf3Os2WEtI|+jGE5Q#18`!!@=Qn7f(FM$PZ~z$j7Kag>CDW0 zB)v^$K1526Sp>2 z1Gyq)7}I1v3E0M%g8Zof8J-((0tmX!7jZw15RO9;$+;!`03CE!tS}~@lMqCL3P;ma z0*3ziK?g-iSPujy{$w?ay!|qhQCusU%CnB}A2Esh7KJfFB6U^b$|^*@{-9_MZ1Vs< zy^x~}#p@tr0O%rz0698f#?^Y>G!+d&%!6jZ2bgbyOvRi%1{gve1q@|w9E}rlsmj&L z_mJT)3se$QvaLZ*XlC*-t2+->c9HeHn{hw}v<*Z?Evy3`4OV6nkR8Od*V)sLhMlT6 z&d7t#aX=sd5jtah>#-R;F)C^p1ks&iJN=Mi82bbiUNJbOQYYDz@R}=@EHo$@bRI*A z&LVM*@K3c-QD3AwP_mh^MA`uuG{Iu!Tlhjpl-PYB1lAv&CbkN#R`xh*sCb@Sj~GK# zoJMlMJjhbw8B+T0qgmClCtJRG-W_~v1A;|m1ppK*N?6wE z4l>BdOSusV9<=oM7z(%{^A%}GfN?{zt5VU+_vH`NJ?go%m{ncnV?mb zRH-LWITM*oYwOHG9m}m*R5bW}g^i7S(huARr36;K2aO%v$Uh%ld6V425+evwZ9q@t zz*F^kbgd{O%<;kcjUdw{zgy5DtsxN%TT386I)RV(TLI$TP;7_gHvPPBNcKSv_=Zlv z3Ma*gQHuH=Jb1VxJIZGL;)?-%1_Vn_fSR1arYFcVa_&(oknEI_zYj;wpdNm{dfm-D z%>&O$Y{YS8rzd?83Vt`_0(={u|9Q7l7TH@}p(S{EvnYHpB5j+bShGLyS5q z;$;5dqnZHYf%Y31hu%IHr%jx4Q%KN0*ergqhG|g3h`cj0Ys)P-%QlJOb4V(CM$WgK zY9XG&OY(Q=jEvKX-@^^@PpJ4l6{o5AQxx-~j~HEUYU*x3HaoRTnknmnP5@_R<0P&; z2A2IIQf7?!brc_4={t90h(bN@G0B1PLV8Bg@sC}~hfwKpJ9PO=&$D;Ln|OF%ZSh@t zkJ_9sWo^<2ICF14?&6F$_|gUR<3z>x@rG)G10U?F3o4Ul~|9oUs?bUYN8u-!*d9%FpT-4!>$yZ2k|<+tmk=fMm4Y;ZXHXDOXl~*KR5? zeQ3kk!jUyAXDwXa^Tf^aA6CCx{oavO?=!c2r_*~zlY2%Nk6sZUt zpPfmbok@gd6VXqk&Wh=?=aXm8CocRZSk)5+PZ!+fxN%*7!D>s_^=;p6d#CNjNNVSk ze|{w0(w}VUe{J`B=l}csU(6?-J4>I19hyuJO(%z@6EpGD(D^$?z0>v~r?=YfSTL$J zJ7;vRaTw%UF=uuCugbc+M!nni^UAtK!nYm33&qZCleD zOHG%L-zzFI?*1je#n}1FCv?y1jOF*v7jUH&iHeSN#jfimDfez{u1M1UipMS=zg@BO z`eQfCQWZ}n45hcryRNt2G^WarULLyL+L0t>|83lA^hpHfBbCXsnh9$qgUf^cT$CC?>M-!CP28BLAXhQaHhKH4ex8-<zX=D$3@-1(j{S$`t2 zWeB%V=59CN2qx=~B)0V7_R(B3wwqNQw$%erMe`4*lZoBoQ4me}9ubtI7jDn8R{%T&U$&}YF zmnRE%Bph9tssovtgPGbVGnF-1hU#W4L$&RfoT=2dV7XV#*{iNqrfiLATWiwRnzFTB zKD<_7KufD7TbB-}N?I4p_wap+^2O=bV`+O+(%!U@mhl)QQSsfHcWQ2orn-*)r6Ij- zFu84T;q>RmUKzVqd8@E7;X8f#XvSRlTc6Ch+zY0kmR2DFsfwqOE{&wB+Su1jUw=O3 zY|D5$ey{Geo*T!JUewfn-Ii+Vd9C7R!4=c{HME3!vqAKOK@aTkZyxgB@*orR;;_~=vaoK`lb!*4+)E@@YTMs0+9#}a4x%pS-uQlCr z*553}GkkKj=^KW$vpMN(&hYKmV>iX5dtl)ReX%um_2QL_OSV+S_H@O8<(EKFY4?*! z_me62k+gdN)l%-`3zm%Cov0Z|*#|NeTai*#jlEclO|LjtU8UGiHF{$)Rn%QR ze{)-MTYsW?AXRlN?LL-pAA8lZYA?lS76>aXMV~8rr6^JHT;fbH5&6U|i?|LS|A%Gd zpVo|2^PkXkVY%|f+I6pk7PQ!PdDBd;ocH_pM9VkA%+qB|jWxW}9R<=F4{dAAv2QIq!L8a^T@1Q!jcd|O&UC$w@ds_kSXIpi2?xFiydOq|4>@QHhkNMj;k<;_@H^X7O zT!Ek$473$MF#B}-E%$vP%#!Mf?r4( zvHyHD6p(CiKKfszXY_4e*z~Y<12CT{VvC#5ago(S+mP_CU)d2&J?ADSdqJ2f>9u*x z^0!|98O8$SPH*8d}2CmcDCJj&~v4orli7Z@A zBbBwzEsACPfc+BU-{F-nVHKqlIHBDR_Zqp<-5HBLQ|QW+)MP5#GLwqiG_4Yq8o@ndxP&~C(kKo#0t zF+M&OCpW?PxTwdiY%|L(AJ-E1yyU8&v`e-jU$yXM>+#R%1v6QfKwR-Dx-uc6Ll+EG zCc0zA|4-t$Y=BzEnX!njet;+Pw@=)3Ms_Fr_OOhfgfQY16{S>^pvYPtn}vHP96Tic zA6x>PIB5q;e6K^N`=4Cn-*JckhO_^aEBYyC{cEoNeQR;rTK!{d^|gH|Ytv=Z`>wJ@ z@!HO7VxqY5a^XFbSvR4(S6Znny|>4uD~86|)t$k=tu4?=?zoQ`brD_0>R7}7@C9dU zCeB{8W|q$_T(Nu2Dxcf9^7=KqeD2`Ny=#T?c@bC9x#pD5AqE@PT=IDdSJ$#8w+gr?wQVPTvg+mozCQ5=}hjE&g35HOzw})sJDMC!x@9< F{{syvlXCz7 delta 3624 zcmZ`+eQZ{is}P-RA=)hKj+K4HrAYMyqUXkMHQvTGe>kGoq*ocy+2twQE=1 zG*LaLyo8jLAA0BNnurlz=-TkCh2_=O{{FUZvXFWpYa3Hs-e_L{%u5C+*(`#`1`@k2g!v(cgU8*!~ei)nGSG40i&+NJ@BV|FirDo`|@fKMlU zk|V_ELPwLz)Qjlqk&vSha>CDA3DKhHKkNk9{fI_4g6i~x_g>YbD(K7TUZ}x`W8DZ< z*&;_f;z}>1YP0+>)-`}}4@`iT6Sspy>vSXhzq5mIcF#~;i*Ixas{^}nE$Qlmr6DH+ z5s-Er?U$)oGC;}fKVb>Ukykt7&50WL&mGxj`Hzkx!PElg!+G2wV^3^UK}(H6I`J{6 zM&+4!Bto^CjY(xzL$F$>d^0{WvQ_hFoeNuCZLpqrV53V*jzL=Rp&$o%Nv%tM8sF~U zL?%6RrkqY}t#jH%;)Z4_3$-9RBzg6 zc~a1xMr3bfbM3GEJTcvng239KB2*sg+^P((f4%c}o;rIKx>25-m{yL;KTT|VVuBjw zw@u2=76sE8&9E$ze8HqyPM1xQXH>V$9Ejx)p1IPLF%3)4a>0zODfjLEy$nCwE1!CH z+v<{SWf(1j9h>E7`5j=vh+w&4%Jb9|S)f^-5!}jfqsYgpZE>-f=a$7*IO;R-1{*Zb zbc-5hiA{ih!Gs0)EOBA6qHY>2w+KsgLr<62XbG*F;A{14(R^^!qy;7ztqGV>)K|=O zU`LuBgL9^ZCv3|uuL&K1J28WhpDpC{3^*yd8qBhEtBA4Ef{D>Xyl{+VVcRjU!h;XJCp7o@3=p49*62Z^=@}ccUlTfV@<`Y-H@52`N~y z1x5`O#Tq>X0GOF>Kp;*xor2O>_L5c9i*^x0u??uZnJe)u#PdMov4{bC9`Y17vH%EB zZuFAtG#wa|Ym?o~hK7Wcf=ZSTQ*-GwFPhL|R>p*uHEnnood}&CF&$`GR$>r39x|cL zobJYYL&ujdV>zKiIP`+ZW3}b|$*EOHH7g2z38Kec=pP3(h&L+c!nexn&>aF3$nr~0 z7h$sV>A=o3)gW_DQJ}7F;WivO9p#wP4I7G7Dz8Bm!BwHWZc#hG${v=>GM%sh3CO3O(o%tz)FhyH|o=5-i3-GEC$7ZXyO8QTv2ps9cg!QpCn8xW3; zrs;Da%rEIHw$ss6uydx9k70TD@OdBTd_|r=ajXJ6Ajx4m_5!ae8j2ym@pm{pfWI!gv7Ce!;B@_i_v@%GqPFP{oIbhCCIY zFmrspaO|X#T7pf%kz|m(fMf;9b|B~G<+PTP{^R4Zs0gBT7)c07r4AC3x8$wkFLqV@ ztbko2p2Q6wWXY`fEfab$JJcf&yr7R)0?RtjWf!di&s3UVqziU&(K^Knyy7nixSfgu zevgofm!Hj4yn?+_sV}fsb0*8m-27CX)dQRI+I)}v*Zg4cJS?W*V_kwD4eRv8TS|R3 z)Y{Nh?Ulb-*e+u)jV>iWPST&u{CMUq`?q6%?7N+uyVZH9N<4>^_}}C7VndZEy?r0| zZMikD`@@0#?}hL59r&bIx-i6=3zH4=R$3XD@c#GQZFNYl3T@R9S|Guqir|)_TF0RK~RqDS!xNiq6ZX^@x zAi1$qQTu&2p7J3-5eNCr_C~Fq+@#ZWu(;E&z{Z`yUd`vd8&Hk~{dXImtHVW$7q;(4 z8jw$R9oyr*yGucS9FN`IgE}AhQ0IgCQEkHe!P6e(#}(u!K)&9~ZYn1%fFg=WW{`Xp z$@55Nfy{|RK!>~nOXIYMXhuPU5GcTZ9t0Ywg!4Mw8^+2aPFtSCEp5r2nZy3qVe@Z9 zUdR+zD}ML}wuRyJ+mPSsLji>*VibwPy|KX!`CQ{pZ=&?GfK?Rq8+6Vz_)yq&?;LSr zaMT=-xOB3Hk`wqJAAUBJ|;ogwH%0`bnpuW`VYp8tz$qW+5 zmXoe8w~Bh-lS#f`(dF0puD(19wjzNaz{D9VF^$}LB$%vsD;59T2eq diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py index aeaabec..96deab0 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py @@ -1497,6 +1497,80 @@ class AgentRuntimeMixin: newest = list(reversed(blocks)) return "\n".join(f"history:{i+1}: {block}" for i, block in enumerate(newest)) + @staticmethod + def _transaction_context_priority_view(context: Any) -> str: + """Group bounded history by reconciliation priority without losing recency. + + The temporal reconciler is a fallback, so current-turn values and validated + transaction state are supplied separately. Within historical conversation, + assistant explanations are intentionally considered before older user turns: + they frequently carry grounded relationships produced from tool/evidence + results (for example item -> amount). They remain interpretive candidates + only and must still pass the configured authoritative pre-validation. + """ + ordered = AgentRuntimeMixin._transaction_context_newest_first(context) + if not ordered: + return "" + assistant: list[str] = [] + user: list[str] = [] + other: list[str] = [] + for line in ordered.splitlines(): + payload = line.split(": ", 1)[1] if ": " in line else line + low = payload.lower().lstrip() + if low.startswith(("assistant:", "agente:")): + assistant.append(line) + elif low.startswith(("user:", "cliente:")): + user.append(line) + else: + other.append(line) + + sections: list[str] = [] + if assistant: + sections.append( + "priority_3_previous_assistant_tool_or_evidence_context:\n" + "\n".join(assistant) + ) + if user: + sections.append("priority_4_previous_user_utterances:\n" + "\n".join(user)) + if other: + sections.append("priority_5_other_conversational_context:\n" + "\n".join(other)) + return "\n".join(sections) + + @staticmethod + def _apply_transaction_reconciliation( + arguments: dict[str, Any], + reconciliation: dict[str, Any] | None, + *, + locked_current_fields: set[str] | None = None, + ) -> tuple[dict[str, Any], list[str], list[str]]: + """Apply temporal reconciliation without mutating explicit current-turn fields. + + Values extracted from the current user utterance have highest precedence for + that turn. The temporal reconciler may use them as anchors, but it cannot + clear or overwrite them. A later authoritative pre-validation step may + still reject a current value and trigger the dedicated recovery path. + """ + out = dict(arguments or {}) + rec = dict(reconciliation or {}) + locked = {str(name) for name in (locked_current_fields or set())} + ignored_clears: list[str] = [] + ignored_values: list[str] = [] + + for field in rec.get("clear_fields") or []: + name = str(field) + if name in locked: + ignored_clears.append(name) + continue + out.pop(name, None) + + for field, value in dict(rec.get("values") or {}).items(): + name = str(field) + if name in locked: + ignored_values.append(name) + continue + out[name] = value + + return out, ignored_clears, ignored_values + async def _reconcile_transaction_parameters( self, state: dict[str, Any], @@ -1543,7 +1617,7 @@ class AgentRuntimeMixin: suffix = "\n\nCONTINUAÇÃO ATUAL DO CLIENTE:\n" if prefix in effective and suffix in effective: conversational_context = effective.split(prefix, 1)[1].split(suffix, 1)[0].strip() - ordered_context = self._transaction_context_newest_first(conversational_context) + ordered_context = self._transaction_context_priority_view(conversational_context) cached = route_meta.get("transaction_parameter_values") effective_known = dict(known_arguments or {}) if isinstance(cached, dict): @@ -3038,15 +3112,22 @@ class AgentRuntimeMixin: parameter_names=required_fields, known_arguments=arguments, ) - for field in reconciliation.get("clear_fields") or []: - arguments.pop(str(field), None) - arguments.update(dict(reconciliation.get("values") or {})) + locked_current_fields = { + str(k) for k, v in dict(extracted_current or {}).items() if v not in _EMPTY_VALUES + } + arguments, ignored_clears, ignored_values = self._apply_transaction_reconciliation( + arguments, reconciliation, locked_current_fields=locked_current_fields + ) state["transaction_parameter_reconciliation"] = { "tool_name": tool_name, "trigger": "traditional_collection_unresolved", "decisions": dict(reconciliation.get("decisions") or {}), "provenance": dict(reconciliation.get("provenance") or {}), "clear_fields": list(reconciliation.get("clear_fields") or []), + "values": dict(reconciliation.get("values") or {}), + "locked_current_fields": sorted(locked_current_fields), + "ignored_clear_fields": sorted(ignored_clears), + "ignored_reconciled_values": sorted(ignored_values), } else: state.pop("transaction_parameter_reconciliation", None) @@ -3321,21 +3402,52 @@ class AgentRuntimeMixin: policy = self._resolve_tool_execution_policy(selected_action, action_args) required = [str(name) for name in (policy.get("requires") or [])] - # Valores já estruturados no contexto podem satisfazer requirements sem - # parsing textual. Para qualquer required field ainda ausente, a fala do - # usuário é interpretada exclusivamente pelo extrator LLM transacional. + # Primeiro turno transacional segue a mesma regra de COLLECTING_PARAMETERS: + # 1) coleta tradicional SOMENTE da fala atual; 2) reconciliação temporal + # apenas como fallback se ainda houver required fields faltando. + # Isso evita que histórico altere o happy path e, ao mesmo tempo, permite + # resolver referências contextuais quando a fala atual é incompleta. missing_initial = self._missing_required_arguments(policy, action_args) - # No primeiro turno, a fala atual pode fornecer/corrigir qualquer required - # field, inclusive um valor que exista no contexto estruturado mas pertença - # a uma transação anterior. O extrator continua restrito ao contrato - # ``requires`` e só sobrescreve quando a LLM realmente extrai um valor. - extracted_initial = await self._extract_transaction_parameters( + extracted_initial = await self._extract_transaction_parameters_current_only( state, tool_name=selected_action, missing_parameters=required, known_arguments={k: v for k, v in action_args.items() if k not in set(required)}, ) action_args.update(extracted_initial) + state["transaction_parameter_collection"] = { + "tool_name": selected_action, + "mode": "current_turn", + "resolved_fields": sorted(str(k) for k in (extracted_initial or {}).keys()), + } + + missing_after_current = self._missing_required_arguments(policy, action_args) + if missing_after_current: + reconciliation = await self._reconcile_transaction_parameters( + state, + tool_name=selected_action, + parameter_names=required, + known_arguments=action_args, + ) + locked_current_fields = { + str(k) for k, v in dict(extracted_initial or {}).items() if v not in _EMPTY_VALUES + } + action_args, ignored_clears, ignored_values = self._apply_transaction_reconciliation( + action_args, reconciliation, locked_current_fields=locked_current_fields + ) + state["transaction_parameter_reconciliation"] = { + "tool_name": selected_action, + "trigger": "initial_traditional_collection_unresolved", + "decisions": dict(reconciliation.get("decisions") or {}), + "provenance": dict(reconciliation.get("provenance") or {}), + "clear_fields": list(reconciliation.get("clear_fields") or []), + "values": dict(reconciliation.get("values") or {}), + "locked_current_fields": sorted(locked_current_fields), + "ignored_clear_fields": sorted(ignored_clears), + "ignored_reconciled_values": sorted(ignored_values), + } + else: + state.pop("transaction_parameter_reconciliation", None) # O mapper MCP continua responsável somente por parâmetros auxiliares que # não pertencem ao contrato transacional. diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py index 88cfbeb..55cc1c3 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py @@ -113,33 +113,217 @@ async def reconcile_transaction_parameters( for name in names } } + + def _anchor_tokens(value: Any) -> list[str]: + """Return generic textual variants for a known scalar anchor.""" + if value in _EMPTY_VALUES: + return [] + raw = str(value).strip().lower() + tokens = {raw} + try: + number = float(str(value).replace(",", ".")) + tokens.add(f"{number:.2f}") + tokens.add(f"{number:.2f}".replace(".", ",")) + if number.is_integer(): + tokens.add(str(int(number))) + except (TypeError, ValueError): + pass + return [token for token in tokens if token] + + def _anchor_relation_candidates(context: str, arguments: Mapping[str, Any]) -> list[str]: + """Surface history fragments related to any already-known parameter. + + This is not a second reconciliation pass and does not resolve anything + deterministically. It only structures the SAME temporal scan so the LLM + can use known/current fields as cross-field anchors while reconciling all + pending fields coherently in one call. + """ + if not context or not arguments: + return [] + # Keep role/history prefixes but split long assistant explanations into + # smaller semantic clauses (bullets/semicolons) so one anchor is not lost + # among many unrelated entity/value pairs. + fragments: list[str] = [] + for raw_line in context.splitlines(): + line = raw_line.strip() + if not line: + continue + parts = [part.strip() for part in re.split(r"\s*\*\s*|\s*;\s*", line) if part.strip()] + fragments.extend(parts or [line]) + + candidates: list[str] = [] + for field_name, field_value in arguments.items(): + variants = _anchor_tokens(field_value) + if not variants: + continue + for fragment in fragments: + low = fragment.lower() + if any(token in low for token in variants): + candidates.append(f"anchor[{field_name}={field_value}]: {fragment}") + return list(dict.fromkeys(candidates)) + + def _structured_evidence_blocks(context: str, arguments: Mapping[str, Any]) -> list[dict[str, Any]]: + """Represent the same bounded history as explicit message evidence blocks. + + The reconciler remains a single LLM call. This helper only prevents role, + recency and anchor relationships from being hidden inside one prose blob. + It is fully domain-neutral: field meaning still comes from parameter_schema. + """ + blocks: list[dict[str, Any]] = [] + current_role = "other" + current_lines: list[str] = [] + rank = 0 + + def flush() -> None: + nonlocal rank, current_lines, current_role + if not current_lines: + return + text_block = " ".join(x.strip() for x in current_lines if x.strip()).strip() + current_lines = [] + if not text_block: + return + + # A single assistant message often contains a list of independent + # entity/attribute relations (for example several invoice items). + # Keeping the whole answer as one evidence block makes an otherwise + # exact anchor ambiguous because every entity in the list competes + # inside the same block. Segment LOCAL relations while preserving + # the original role, priority and message recency. This is still the + # same temporal reconciliation and the same single LLM call. + fragments = [ + frag.strip(" \t-•") + for frag in re.split( + r"\s+(?:\*|•)\s+|\s*;\s+|\s+(?=\d+[.)]\s+)", + text_block, + ) + if frag.strip(" \t-•") + ] + if not fragments: + fragments = [text_block] + + rank += 1 + role_priority = 3 if current_role == "assistant" else 4 if current_role == "user" else 5 + for fragment_index, fragment in enumerate(fragments, start=1): + anchor_matches: list[dict[str, Any]] = [] + low = fragment.lower() + for field_name, field_value in arguments.items(): + variants = _anchor_tokens(field_value) + matched = [token for token in variants if token in low] + if matched: + anchor_matches.append({ + "field": str(field_name), + "value": field_value, + "matched_tokens": matched, + }) + blocks.append({ + "priority": role_priority, + "recency": rank, + "fragment": fragment_index, + "role": current_role, + "text": fragment, + "anchor_matches": anchor_matches, + }) + + for raw_line in str(context or "").splitlines(): + line = raw_line.strip() + if not line: + continue + low = line.lower() + # Priority-view section headers are metadata, not conversational text. + if low.startswith("priority_3_previous_assistant"): + flush(); current_role = "assistant"; continue + if low.startswith("priority_4_previous_user"): + flush(); current_role = "user"; continue + if low.startswith("priority_5_other"): + flush(); current_role = "other"; continue + payload = line.split(": ", 1)[1] if line.startswith("history:") and ": " in line else line + plow = payload.lower().lstrip() + detected = None + if plow.startswith(("assistant:", "agente:")): + detected = "assistant" + elif plow.startswith(("user:", "cliente:")): + detected = "user" + elif plow.startswith("system:"): + detected = "other" + if detected is not None: + flush() + current_role = detected + payload = payload.split(":", 1)[1].strip() if ":" in payload else payload + current_lines.append(payload) + flush() + return blocks + + context_text = str(conversational_context or "").strip() + anchor_relations = _anchor_relation_candidates(context_text, known) + evidence_blocks = _structured_evidence_blocks(context_text, known) + missing_initial = [name for name in names if name not in known] + + # Field-targeted views do not resolve parameters and do not add another LLM + # pass. They expose the SAME local evidence blocks next to the declarative + # semantics of each still-missing field so the single temporal reconciliation + # call can correlate anchors with the correct schema-defined target instead of + # rediscovering that mapping inside a large generic JSON blob. No field names + # or domain concepts are hardcoded here. + anchored_blocks = [block for block in evidence_blocks if block.get("anchor_matches")] + field_evidence_views = { + name: { + "field_spec": field_spec.get(name, {}), + "anchored_evidence_blocks": anchored_blocks, + } + for name in missing_initial + } + + reconciliation_focus = { + "current_user_message": message, + "known_parameters": known, + "missing_parameters": missing_initial, + "missing_field_views": field_evidence_views, + } + prompt = ( + "FOCO PRINCIPAL DA RECONCILIAÇÃO (examine isto antes de qualquer contexto secundário):\n" + f"reconciliation_focus: {json.dumps(reconciliation_focus, ensure_ascii=False, default=str)}\n" + "Se um campo faltante tiver um único evidence_block ancorado semanticamente compatível com seu field_spec, resolva-o; use unresolved somente em ambiguidade real.\n\n" "Você é o conciliador temporal de parâmetros de uma transação ativa. " - "Reconstrua UM CONJUNTO COERENTE de parâmetros; não extraia cada campo de forma isolada. " + "Faça UMA ÚNICA VARREDURA TEMPORAL e reconstrua UM CONJUNTO COERENTE de parâmetros. " + "Todos os campos conhecidos e faltantes devem ser avaliados juntos; não execute uma busca isolada por campo e não faça uma segunda etapa de fallback. " "Não decida roteamento, confirmação nem execução.\n\n" "CONTRATO OBRIGATÓRIO:\n" - "1. O significado de cada campo vem EXCLUSIVAMENTE de parameter_schema e transaction_description, considerando principalmente a descrição semântica quando disponível. O framework não conhece conceitos de domínio por nome de campo.\n" - "2. A ausência de tipo ou descrição NÃO impede a extração quando o restante do contrato e o texto forem semanticamente suficientes.\n" - "3. A busca textual é temporal, em ordem decrescente: user_message é a fonte mais nova; depois conversational_context já vem do texto mais novo para o mais antigo.\n" - "3. Textos do usuário e textos explicativos do assistente podem ser usados para interpretar referências e relações entre campos. Não trate texto do contexto como uma nova afirmação do cliente; eles são contexto, não evidência autoritativa de negócio.\n" - "4. Para cada campo escolha: resolved = um texto determina novo valor; preserve = nenhum texto mais novo invalida o valor conhecido; clear = existe mudança textual mais nova que torna o valor conhecido incompatível/sem vínculo seguro com o novo contexto e ainda não há substituto; unresolved = não há valor conhecido nem candidato textual seguro.\n" - "5. Se uma fonte mais nova muda uma entidade, objeto, escopo ou outro contexto que dava sentido a campos extraídos anteriormente, REAVALIE os demais campos como conjunto. Não combine automaticamente um atributo antigo com um contexto novo só porque ambos existem.\n" - "6. Um valor de texto anterior pode continuar válido após uma mudança somente quando os textos, considerados em conjunto, sustentarem de forma inequívoca que ele ainda pertence ao contexto mais recente. Caso contrário use clear para o campo dependente.\n" - "7. Se a nova menção é inválida no mundo real, NÃO volte silenciosamente ao valor antigo. Ainda assim devolva o candidato textual mais recente como resolved; a pre-validation autoritativa é responsável por rejeitá-lo.\n" - "8. known_arguments é fallback de estado. Use preserve somente quando nenhum texto mais novo o contradiz ou rompe sua associação contextual.\n" - "9. Uma expressão só pode preencher um campo se satisfizer semanticamente type/description desse campo. Não transfira um trecho para outro campo apenas por proximidade lexical.\n" - "10. Se um texto recente corrige explicitamente informação anterior, a correção prevalece para os campos que o schema permite inferir; os demais devem ser reavaliados quanto à coerência com a correção.\n" - "11. Em ambiguidade razoável, prefira clear/unresolved a inventar uma associação. Em caso de dúvida razoável sobre a correspondência ou o valor, prefira null.\n" - "12. Responda SOMENTE JSON válido no formato pedido, sem markdown e sem chaves extras.\n\n" + "1. O significado de cada campo vem EXCLUSIVAMENTE de parameter_schema e transaction_description, principalmente a descrição semântica quando disponível. O framework não conhece conceitos de domínio por nome de campo.\n" + "2. A ausência de tipo ou descrição NÃO impede a extração nem a resolução quando o restante do contrato e o contexto forem semanticamente suficientes.\n" + "3. A resolução deve obedecer ESTA PRIORIDADE, sem inverter níveis: (1) informação explicitamente fornecida pelo usuário na mensagem atual e semanticamente compatível com o schema; (2) parâmetros já conhecidos/validados da transação; (3) respostas anteriores do assistente que apresentem relações locais entre parâmetros/atributos e que possam ter sido apoiadas por tool/evidence; (4) falas anteriores do usuário; (5) demais contexto conversacional.\n" + "4. Dentro de cada nível histórico, preserve a ordem temporal decrescente (mais novo -> mais antigo). Nunca escolha fonte de prioridade menor quando uma fonte de prioridade maior resolve o mesmo campo de forma coerente.\n" + "5. known_arguments contém o estado parcial já coletado/validado. Trate CADA parâmetro conhecido, independentemente de nome ou tipo, como possível ÂNCORA para resolver QUALQUER outro campo faltante no histórico. O significado e a compatibilidade de cada âncora vêm exclusivamente do parameter_schema. Use múltiplas âncoras simultaneamente quando disponíveis.\n" + "6. anchor_relation_candidates são apenas recortes do MESMO histórico que contêm representações de parâmetros conhecidos; eles servem para facilitar a correlação entre campos dentro desta única varredura. Não são uma segunda fonte, não têm prioridade própria e não autorizam inventar relações.\n" + "7. Quando uma âncora conhecida aparecer em um mesmo contexto local com uma ou mais informações semanticamente compatíveis com campos faltantes, use essa relação local para reconciliar TODOS os campos faltantes que puderem ser resolvidos de forma coerente na mesma resposta. Não pressuponha quais tipos de campo devem coexistir; siga apenas o schema e o contexto.\n" + "8. Texto anterior do assistente é CONTEXTO INTERPRETATIVO, não evidência autoritativa: pode fornecer relações locais entre quaisquer parâmetros/atributos definidos pelo schema, mas todo candidato continua sujeito à pre-validation/tool de negócio. Não descarte uma relação apenas por estar na fala do assistente. Não trate texto do contexto como uma nova afirmação do cliente.\n" + "9. Para cada campo escolha: resolved = texto/contexto determina novo valor; preserve = o valor conhecido continua coerente; clear = contexto mais novo rompe sua associação e não há substituto seguro; unresolved = não há candidato seguro.\n" + "10. Se uma fonte mais nova muda o contexto semântico que dava sentido a campos anteriores, REAVALIE os demais campos como conjunto. Não combine automaticamente informação antiga com contexto novo.\n" + "11. Se a nova menção é inválida no mundo real, NÃO volte silenciosamente ao valor antigo. Devolva o candidato textual mais recente como resolved e deixe a pre-validation autoritativa rejeitá-lo.\n" + "12. Uma expressão só pode preencher um campo se satisfizer semanticamente type/description desse campo. Não transfira um trecho para outro campo apenas por proximidade lexical.\n" + "13. Se o usuário corrige explicitamente informação anterior, a correção prevalece nos campos compatíveis e os demais devem ser reavaliados quanto à coerência.\n" + "14. unresolved é ÚLTIMO RECURSO. Antes de devolver unresolved para um campo faltante, você DEVE verificar todos os evidence_blocks na ordem de prioridade e recência e todas as anchor_relation_candidates. Se existir uma única interpretação semanticamente compatível com type/description do campo, resolva-a.\n" + "15. Se um parâmetro conhecido aparecer como anchor_match em um evidence_block e o MESMO bloco contiver uma única informação semanticamente compatível com um campo faltante segundo o schema, use a relação para resolved desse campo; não devolva unresolved apenas porque a informação foi apresentada pelo assistente.\n" + "16. Se não houver âncora útil, mas uma fonte histórica de prioridade 3 ou 4 contiver explicitamente uma informação que satisfaça semanticamente um campo faltante segundo o schema e não houver candidato concorrente de prioridade maior, resolva esse campo. Isso cobre referências posteriores em que o usuário omite um atributo porque ele já estava explícito no diálogo.\n" + "17. field_evidence_views reorganiza os MESMOS evidence_blocks ancorados por cada campo ainda faltante e coloca ao lado a semântica declarativa desse campo. Para cada campo faltante, examine obrigatoriamente essa visão antes de unresolved. Se um bloco ancorado contiver uma única informação compatível com field_spec e não houver concorrente de prioridade/recência maior, retorne resolved. Essa visão não é uma nova fonte nem uma segunda etapa.\n" + "18. Em ambiguidade REAL — dois ou mais candidatos semanticamente plausíveis sem desempate por prioridade, recência ou âncora — prefira clear/unresolved a inventar uma associação. Em caso de dúvida razoável sobre a correspondência ou o valor, prefira null/unresolved conforme o formato de saída.\n" + "19. Responda SOMENTE JSON válido no formato pedido, sem markdown e sem chaves extras.\n\n" f"transaction_tool: {tool_name}\n" f"transaction_description: {tool_description or ''}\n" f"parameter_names: {json.dumps(names, ensure_ascii=False)}\n" + f"known_parameters: {json.dumps(known, ensure_ascii=False, default=str)}\n" + f"missing_parameters: {json.dumps(missing_initial, ensure_ascii=False)}\n" f"pending_parameters: {json.dumps(names, ensure_ascii=False)}\n" f"parameter_schema: {json.dumps(field_spec, ensure_ascii=False, default=str)}\n" - f"known_arguments: {json.dumps(known, ensure_ascii=False, default=str)}\n" + f"anchor_relation_candidates: {json.dumps(anchor_relations, ensure_ascii=False, default=str)}\n" + f"evidence_blocks: {json.dumps(evidence_blocks, ensure_ascii=False, default=str)}\n" + f"field_evidence_views: {json.dumps(field_evidence_views, ensure_ascii=False, default=str)}\n" "conversation_sources_newest_to_oldest:\n" + f"priority_1_current_user_message: {message}\n" f"user_message: {message}\n" - f"conversational_context: {str(conversational_context or '').strip()}\n" + f"prioritized_conversational_context: {context_text}\n" + "RELEMBRE O FOCO PRINCIPAL: examine reconciliation_focus.missing_field_views antes de unresolved. " + "Um bloco ancorado único e semanticamente compatível deve produzir resolved, independentemente do papel assistant/user, respeitada a prioridade declarada.\n" f"Formato obrigatório: {json.dumps(output_shape, ensure_ascii=False)}" ) diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/__init__.cpython-313.pyc index c4a831ab846dcc639c09bc4ef36ce5d6209f0d17..2476284377604fb9f1445277f932b279613414e4 100644 GIT binary patch delta 34 ocmcb@c$ty=GcPX}0}z-$nKzN!n7c?nH?KrLMc+5rbD~!l0IbLgUjP6A delta 35 pcmcc2c!iPsGcPX}0}zCtoi>r%n5S4jH?KrLS>Lg^w0NRt7XY~>3ljhU diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/sse/__pycache__/events.cpython-313.pyc index ff084315766d52c634f0e2981dd85af6940d7f20..90fbf1eb8c8d0f104a7bfa0edda25a58493ff485 100644 GIT binary patch delta 37 rcmez3_1TO2GcPX}0}z-$nYWSqJ2Q8Ier{fgeu}b%7 diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/supervisor/__pycache__/__init__.cpython-313.pyc index a1defb9b480adccdafaf03344669936056da25ec..d939ba537c3059ae5e73a82472967be9b8731f20 100644 GIT binary patch delta 34 ocmcc3c#DzyGcPX}0}z-$nKzN!n7dLxH?KrLMc+5rbE4No0IvTEdjJ3c delta 35 pcmcb`c$<;?GcPX}0}zCtoi>r%n5RlVH?KrLS>Lg^w0NTDL;$;S3oifw diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/supervisor/__pycache__/supervisor.cpython-313.pyc index 08a3aab28b88e9f5b5ff1dc616f862ce9c9562b0..12591f6903412d4bb6f45e51a0fb8d82e438a1f7 100644 GIT binary patch delta 37 rcmcbhc3zG9GcPX}0}z-$nYWRr8&0L9q~qW}N^ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/input_contract.cpython-313.pyc index 4ca4c0b780d0bc13148d2b6d9808caa20a77c3e7..20f7c2db386c725a52de8e81dce9c7efa27600f2 100644 GIT binary patch delta 37 rcmccaa?OSNGcPX}0}z-$nYWR99W!^Ger{fgeu}7~_ delta 38 scmccSa@~ddGcPX}0}zCtowkvC9Wzh8er{fgezLw}acS}9Bg~WJ0QdS04*&oF diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/models.cpython-313.pyc index 730f0f6463ee2725e0eedc57db453e0d6fe815b0..206b904f20f5cd228979bc95314adc8d9398bb5c 100644 GIT binary patch delta 37 rcmexn{neWLGcPX}0}z-$nYWSq6BBoter{fgeu}R^er{fgezLw}acS}9_l&DK0Nox8iU0rr diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/runtime.cpython-313.pyc index 011d24d9eab9359fb697f31d1e3f707c0dd5a18f..bb1aaaab85f56354a1bd2a9a7b815b52d2c6e26e 100644 GIT binary patch delta 39 tcmdlvi)qI!ChpI?yj%=GVE$y@M($W_!o+6{OB diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/workflows/__pycache__/tool_executor.cpython-313.pyc index b80ecdc29c862ea776cb9670e0d9b3f1adcf0b23..234176e35868848614dd3001eaa03567133ebb6d 100644 GIT binary patch delta 37 rcmZ3_zmA{#GcPX}0}z-$nYWR9HY0bfer{fgeu}= 2 + +class _CoherentTemporalLLM: + """Simulates the structured decisions expected from temporal reconciliation.""" + def __init__(self): + self.prompts = [] + + async def ainvoke(self, messages, **kwargs): + prompt = messages[-1]["content"] + self.prompts.append(prompt) + low = prompt.lower() + # Product A + value X established. + if "user_message: na verdade é tim fashion mensal" in low: + return json.dumps({"fields": { + "subject": {"decision": "resolved", "value": "TIM Fashion Mensal", "source": "current"}, + # Previous 14.99 was tied to the former product and must not be transplanted. + "valor": {"decision": "clear", "value": None, "source": "history:1"}, + }}, ensure_ascii=False) + if "user_message: na verdade é produto inexistente" in low: + return json.dumps({"fields": { + # Keep the newest candidate so authoritative validation can reject it. + "subject": {"decision": "resolved", "value": "Produto Inexistente", "source": "current"}, + "valor": {"decision": "clear", "value": None, "source": "history:1"}, + }}, ensure_ascii=False) + if "user_message: desculpa, era tamboro mensal mesmo" in low: + return json.dumps({"fields": { + "subject": {"decision": "resolved", "value": "Tamboro Mensal", "source": "current"}, + # Full temporal text makes the old amount coherent again with the restored product. + "valor": {"decision": "resolved", "value": 14.99, "source": "history:2"}, + }}, ensure_ascii=False) + return json.dumps({"fields": { + "subject": {"decision": "preserve", "value": None, "source": "state"}, + "valor": {"decision": "preserve", "value": None, "source": "state"}, + }}, ensure_ascii=False) + + +@pytest.mark.asyncio +async def test_temporal_reconciliation_product_change_rechecks_old_value_as_part_of_coherent_set(): + from agent_framework.runtime.transaction_parameters import reconcile_transaction_parameters + + llm = _CoherentTemporalLLM() + out = await reconcile_transaction_parameters( + llm, + text="na verdade é TIM Fashion Mensal", + conversational_context=( + "history:1: user: é R$ 14,99\n" + "history:2: user: quero contestar Tamboro Mensal" + ), + tool_name="contestar_cobranca", + parameter_names=["subject", "valor"], + known_arguments={"subject": "Tamboro Mensal", "valor": 14.99}, + parameter_schema={ + "subject": {"type": "string", "description": "Nome do serviço, produto, item ou cobrança objeto da contestação."}, + "valor": {"type": "number", "description": "Valor monetário associado ao item objeto da contestação."}, + }, + tool_description="Contesta uma cobrança após validação.", + ) + assert out["values"] == {"subject": "TIM Fashion Mensal"} + assert out["clear_fields"] == ["valor"] + assert out["provenance"]["subject"] == "current" + + +@pytest.mark.asyncio +async def test_temporal_reconciliation_invalid_new_product_does_not_erase_history_or_fall_back_silently(): + from agent_framework.runtime.transaction_parameters import reconcile_transaction_parameters + + llm = _CoherentTemporalLLM() + history = ( + "history:1: user: é R$ 14,99\n" + "history:2: user: quero contestar Tamboro Mensal" + ) + out = await reconcile_transaction_parameters( + llm, + text="na verdade é Produto Inexistente", + conversational_context=history, + tool_name="contestar_cobranca", + parameter_names=["subject", "valor"], + known_arguments={"subject": "Tamboro Mensal", "valor": 14.99}, + parameter_schema={ + "subject": {"type": "string", "description": "Nome do serviço, produto, item ou cobrança objeto da contestação."}, + "valor": {"type": "number", "description": "Valor monetário associado ao item objeto da contestação."}, + }, + tool_description="Contesta uma cobrança após validação.", + ) + # The newest candidate stays visible for pre-validation; the old product is not silently restored. + assert out["values"] == {"subject": "Produto Inexistente"} + assert "valor" in out["clear_fields"] + assert "Tamboro Mensal" in llm.prompts[-1] # history remains available to future reconciliation. + + +@pytest.mark.asyncio +async def test_temporal_reconciliation_can_restore_coherent_old_value_when_product_is_explicitly_restored(): + from agent_framework.runtime.transaction_parameters import reconcile_transaction_parameters + + llm = _CoherentTemporalLLM() + out = await reconcile_transaction_parameters( + llm, + text="desculpa, era Tamboro Mensal mesmo", + conversational_context=( + "history:1: user: na verdade é Produto Inexistente\n" + "history:2: user: é R$ 14,99\n" + "history:3: user: quero contestar Tamboro Mensal" + ), + tool_name="contestar_cobranca", + parameter_names=["subject", "valor"], + known_arguments={}, + parameter_schema={ + "subject": {"type": "string", "description": "Nome do serviço, produto, item ou cobrança objeto da contestação."}, + "valor": {"type": "number", "description": "Valor monetário associado ao item objeto da contestação."}, + }, + tool_description="Contesta uma cobrança após validação.", + ) + assert out["values"] == {"subject": "Tamboro Mensal", "valor": 14.99} + assert out["provenance"] == {"subject": "current", "valor": "history:2"} + + +def test_temporal_context_priority_places_assistant_before_older_user_history(): + from agent_framework.runtime.agent_runtime import AgentRuntimeMixin + + context = ( + "user: tem uma cobrança aqui que eu não reconheço\n" + "assistant: Cobrança Tamboro Mensal no valor de R$ 14,99; TIM Fashion Mensal no valor de R$ 10,00." + ) + prioritized = AgentRuntimeMixin._transaction_context_priority_view(context) + + assert "priority_3_previous_assistant_tool_or_evidence_context:" in prioritized + assert "priority_4_previous_user_utterances:" in prioritized + assert prioritized.index("assistant: Cobrança Tamboro Mensal") < prioritized.index("user: tem uma cobrança") + + +class _AssistantRelationshipReconcilerLLM: + def __init__(self): + self.prompt = "" + + async def ainvoke(self, messages, **kwargs): + self.prompt = messages[-1]["content"] + # Simula o comportamento desejado: a fala atual dá o valor, enquanto a + # relação item->valor está numa resposta anterior do assistant. + assert "user_message: é a de quatorze e noventa e nove" in self.prompt + assert "priority_3_previous_assistant_tool_or_evidence_context:" in self.prompt + assert "assistant: Cobrança Tamboro Mensal no valor de R$ 14,99" in self.prompt + assert "anchor_relation_candidates:" in self.prompt + assert "anchor[valor=14.99]" in self.prompt + return json.dumps({"fields": { + "subject": {"decision": "resolved", "value": "Tamboro Mensal", "source": "history:1"}, + "valor": {"decision": "resolved", "value": 14.99, "source": "current"}, + }}, ensure_ascii=False) + + +@pytest.mark.asyncio +async def test_temporal_reconciler_can_use_grounded_assistant_relationship_after_current_only_extraction_is_incomplete(): + from agent_framework.runtime.agent_runtime import AgentRuntimeMixin + + class Runtime(AgentRuntimeMixin): + pass + + runtime = Runtime() + runtime.llm = _AssistantRelationshipReconcilerLLM() + runtime.tool_router = type("TR", (), { + "registry": type("REG", (), { + "get_tool": staticmethod(lambda name: type("CFG", (), { + "requires": ["subject", "valor"], + "args_schema": { + "subject": {"type": "string", "description": "Nome do item ou cobrança a contestar."}, + "valor": {"type": "number", "description": "Valor monetário do item a contestar."}, + }, + "description": "Contesta uma cobrança após validação.", + })()) + })(), + "resolve_execution_policy": staticmethod(lambda name, arguments=None: { + "operation_type": "transactional", + "requires": ["subject", "valor"], + }), + })() + + state = { + "sanitized_input": "é a de quatorze e noventa e nove", + "user_text": "é a de quatorze e noventa e nove", + "route_decision": {"metadata": { + "contextual_reentry": True, + "original_input": "é a de quatorze e noventa e nove", + "relevant_conversation_context": ( + "user: tem uma cobrança aqui que eu não reconheço\n" + "assistant: Cobrança Tamboro Mensal no valor de R$ 14,99; TIM Fashion Mensal no valor de R$ 10,00." + ), + }}, + } + + # O happy path corrente só consegue o valor; o subject fica faltando. + class _CurrentOnlyLLM: + async def ainvoke(self, messages, **kwargs): + return json.dumps({"valor": 14.99}, ensure_ascii=False) + + original_llm = runtime.llm + runtime.llm = _CurrentOnlyLLM() + current = await runtime._extract_transaction_parameters_current_only( + state, + tool_name="contestar_cobranca", + missing_parameters=["subject", "valor"], + known_arguments={}, + ) + assert current == {"valor": 14.99} + + runtime.llm = original_llm + reconciled = await runtime._reconcile_transaction_parameters( + state, + tool_name="contestar_cobranca", + parameter_names=["subject", "valor"], + known_arguments=current, + ) + assert reconciled["values"]["subject"] == "Tamboro Mensal" + assert float(reconciled["values"]["valor"]) == 14.99 + assert "(3) respostas anteriores do assistente" in runtime.llm.prompt + +class _UnifiedAnchorScanLLM: + def __init__(self): + self.calls = [] + + async def ainvoke(self, messages, **kwargs): + prompt = messages[-1]["content"] + self.calls.append(prompt) + assert "UMA ÚNICA VARREDURA TEMPORAL" in prompt + assert "known_parameters: {\"valor\": 14.99}" in prompt + assert "missing_parameters: [\"subject\", \"data\"]" in prompt + assert "anchor_relation_candidates:" in prompt + assert "anchor[valor=14.99]" in prompt + assert "Tamboro Mensal no valor de R$ 14,99" in prompt + return json.dumps({"fields": { + "subject": {"decision": "resolved", "value": "Tamboro Mensal", "source": "history:1"}, + "valor": {"decision": "preserve", "value": None, "source": "state"}, + "data": {"decision": "resolved", "value": "01/11/2025", "source": "history:1"}, + }}, ensure_ascii=False) + + +@pytest.mark.asyncio +async def test_temporal_reconciler_single_scan_uses_all_known_fields_as_anchors_and_resolves_all_missing_fields(): + from agent_framework.runtime.transaction_parameters import reconcile_transaction_parameters + + llm = _UnifiedAnchorScanLLM() + result = await reconcile_transaction_parameters( + llm, + text="é a de quatorze e noventa e nove", + tool_name="contestar_cobranca", + parameter_names=["subject", "valor", "data"], + known_arguments={"valor": 14.99}, + parameter_schema={ + "subject": {"type": "string", "description": "Nome do item ou cobrança a contestar."}, + "valor": {"type": "number", "description": "Valor monetário do item a contestar."}, + "data": {"type": "string", "description": "Data da cobrança selecionada."}, + }, + tool_description="Contesta uma cobrança após validação.", + conversational_context=( + "priority_3_previous_assistant_tool_or_evidence_context:\n" + "history:1: assistant: Cobrança Tamboro Mensal no valor de R$ 14,99 no dia 01/11/2025 * " + "TIM Fashion Mensal no valor de R$ 10,00 no dia 01/11/2025.\n" + "priority_4_previous_user_utterances:\n" + "history:2: user: tem uma cobrança aqui que eu não reconheço" + ), + ) + + assert len(llm.calls) == 1 + assert result["values"]["subject"] == "Tamboro Mensal" + assert float(result["values"]["valor"]) == 14.99 + assert result["values"]["data"] == "01/11/2025" + assert result["provenance"]["subject"] == "history:1" + diff --git a/agent_framework_oci/tests/test_transaction_parameter_llm_precedence.py b/agent_framework_oci/tests/test_transaction_parameter_llm_precedence.py index fe2ed05..c15adcb 100644 --- a/agent_framework_oci/tests/test_transaction_parameter_llm_precedence.py +++ b/agent_framework_oci/tests/test_transaction_parameter_llm_precedence.py @@ -643,3 +643,98 @@ intents: [] decision = await router.route(state) assert decision.metadata["transaction_confirmation_decision"] == "confirm" assert decision.metadata["transaction_confirmation_source"] == "deterministic" + +@pytest.mark.asyncio +async def test_collecting_preserves_resolved_required_fields_and_only_extracts_currently_missing(): + class Runtime(_Runtime): + def __init__(self): + super().__init__() + self.pending_seen = None + + async def _extract_transaction_parameters( + self, state, *, tool_name, missing_parameters, known_arguments=None + ): + self.pending_seen = list(missing_parameters) + # Simulate the value extracted for the only missing field. A resolved + # required field must not be offered back to the semantic extractor. + return {"reason": "desisti da compra"} + + runtime = Runtime() + state = { + "user_text": "desisti da compra", + "sanitized_input": "desisti da compra", + "transaction_status": "COLLECTING_PARAMETERS", + "missing_parameters": ["reason"], + "mcp_tools": ["solicitar_devolucao"], + "active_transaction": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + "status": "COLLECTING_PARAMETERS", + "parameter_schema": {"order_id": "string", "reason": "string"}, + "tool_description": "Abre uma solicitação de devolução de pedido.", + }, + "selected_tool_call": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + }, + "route_decision": {"metadata": {}}, + "route": "support_agent", + "intent": "state:COLLECTING_SUPPORT_PARAMETERS", + } + + result = await runtime.execute_tools_for_intent(state) + assert runtime.pending_seen == ["reason"] + assert state["pending_tool_call"]["arguments"]["order_id"] == "PED-1001" + assert state["pending_tool_call"]["arguments"]["reason"] == "desisti da compra" + assert result[-1]["awaiting_confirmation"] is True + +@pytest.mark.asyncio +async def test_correction_of_missing_numeric_value_does_not_reopen_resolved_text_entity(): + class Runtime(_Runtime): + def __init__(self): + super().__init__() + self.pending_seen = None + + async def _extract_transaction_parameters( + self, state, *, tool_name, missing_parameters, known_arguments=None + ): + self.pending_seen = list(missing_parameters) + # If subject were incorrectly offered again, a semantic extractor + # could reinterpret the monetary phrase as an entity. The runtime + # contract must expose only the missing numeric field here. + out = {"valor": 19.99} + if "subject" in missing_parameters: + out["subject"] = "cobrança de R$ 19,99" + return out + + runtime = Runtime() + state = { + "user_text": "desculpa é a de dezenove e noventa e nove", + "sanitized_input": "desculpa é a de dezenove e noventa e nove", + "transaction_status": "COLLECTING_PARAMETERS", + "missing_parameters": ["valor"], + "mcp_tools": ["solicitar_devolucao"], + "active_transaction": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + "status": "COLLECTING_PARAMETERS", + "parameter_schema": {"order_id": "string", "reason": "string", "valor": "number"}, + }, + "selected_tool_call": { + "tool_name": "solicitar_devolucao", + "arguments": {"order_id": "PED-1001"}, + }, + "route_decision": {"metadata": {}}, + "route": "support_agent", + "intent": "state:COLLECTING_SUPPORT_PARAMETERS", + } + # This synthetic tool doesn't require valor, so exercise the extraction + # contract directly with the same resolved-text/missing-number shape. + out = await runtime._extract_transaction_parameters( + state, + tool_name="solicitar_devolucao", + missing_parameters=["valor"], + known_arguments={"subject": "Tamboro Mensal"}, + ) + assert runtime.pending_seen == ["valor"] + assert out == {"valor": 19.99} diff --git a/agent_framework_oci/tests/test_transactional_tool_flow.py b/agent_framework_oci/tests/test_transactional_tool_flow.py index 48f6b0f..71c03b0 100644 --- a/agent_framework_oci/tests/test_transactional_tool_flow.py +++ b/agent_framework_oci/tests/test_transactional_tool_flow.py @@ -1283,3 +1283,94 @@ async def test_prevalidation_parameter_message_is_used_once_without_changing_tra # One-shot: subsequent clarification falls back to the normal prompt. assert runtime.transaction_clarification_message(state) != expected assert "transaction_parameter_message_override" not in state + +class _TemporalFallbackRuntime(AgentRuntimeMixin): + def __init__(self): + from types import SimpleNamespace + self.calls = [] + self.llm = None + self.tool_router = SimpleNamespace( + registry=SimpleNamespace( + get_tool=lambda name: SimpleNamespace( + requires=["subject"], + args_schema={"subject": {"type": "string", "description": "Nome do serviço ou VAS alvo do cancelamento."}}, + description="Cancela o serviço VAS selecionado pelo cliente.", + confirmation_required=True, + tool_type="transactional", + ) + ), + resolve_execution_policy=lambda name, arguments=None: { + "operation_type": "transactional", + "require_confirmation": True, + "requires": ["subject"], + "pre_validation": {"enabled": True, "tool": "validar_vas_subject", "fail_open": False}, + }, + ) + + async def _extract_transaction_parameters_current_only(self, state, *, tool_name, missing_parameters, known_arguments=None): + # Simula o collector tradicional interpretando literalmente a fala atual. + return {"subject": "dezenove e noventa e nove"} + + async def _reconcile_transaction_parameters(self, state, *, tool_name, parameter_names, known_arguments=None): + # Simula o reconciliador temporal usando tools.yaml + contexto newest->oldest. + return { + "values": {"subject": "Tamboro Mensal"}, + "decisions": {"subject": "resolved"}, + "provenance": {"subject": "history:2"}, + "clear_fields": [], + } + + async def _call_mcp_tool(self, tool_name, arguments, state): + self.calls.append((tool_name, dict(arguments))) + if tool_name == "validar_vas_subject": + subject = arguments.get("subject") + if subject == "Tamboro Mensal": + return {"ok": True, "tool_name": tool_name, "result": {"eligible": True, "status": "ELIGIBLE"}} + return {"ok": True, "tool_name": tool_name, "result": { + "eligible": False, + "status": "NEEDS_PARAMETER", + "parameter": "subject", + "reason": "subject_not_resolved", + }} + return {"ok": True, "tool_name": tool_name, "result": {"status": "OK"}} + + +@pytest.mark.asyncio +async def test_temporal_reconciler_is_fallback_after_traditional_candidate_fails_prevalidation(): + runtime = _TemporalFallbackRuntime() + state = { + "user_text": "é a de dezenove e noventa e nove", + "sanitized_input": "é a de dezenove e noventa e nove", + "route": "contestacao_agent", + "intent": "state:COLLECTING_CONTESTACAO_PARAMETERS", + "transaction_status": "COLLECTING_PARAMETERS", + "selected_tool_call": {"tool_name": "cancelar_vas_avulso", "arguments": {}}, + "active_transaction": { + "transaction_id": "tx-1", + "tool_name": "cancelar_vas_avulso", + "arguments": {}, + "status": "COLLECTING_PARAMETERS", + "started_from_intent": "contas_vas_cancel", + "requires": ["subject"], + "parameter_schema": {"subject": {"type": "string", "description": "Nome do serviço ou VAS alvo do cancelamento."}}, + "tool_description": "Cancela o serviço VAS selecionado pelo cliente.", + "parameter_conversational_context": ( + "user: não reconheço esse Tamboro Mensal na minha fatura\n" + "assistant: identifiquei Tamboro Mensal por R$ 14,99 e R$ 19,99" + ), + }, + "context": {}, + } + + result = await runtime.execute_tools_for_intent(state, tools=[]) + + validations = [(name, args.get("subject")) for name, args in runtime.calls if name == "validar_vas_subject"] + assert validations == [ + ("validar_vas_subject", "dezenove e noventa e nove"), + ("validar_vas_subject", "Tamboro Mensal"), + ] + assert state["transaction_parameter_collection"]["mode"] == "current_turn" + assert state["transaction_parameter_reconciliation"]["trigger"] == "prevalidation_needs_parameter" + assert state["pending_tool_call"]["arguments"]["subject"] == "Tamboro Mensal" + assert state["transaction_status"] == "AWAITING_CONFIRMATION" + assert result[-1]["awaiting_confirmation"] is True diff --git a/contas_mcp/__pycache__/__init__.cpython-313.pyc b/contas_mcp/__pycache__/__init__.cpython-313.pyc index 9290c03fea0052df463e483180cb64961f9d9ecc..abd191a6291862c8044e63a6a9d6d826eab34309 100644 GIT binary patch delta 34 ocmbQoIG2(8GcPX}0}!--m^YEznA=7_H?KrLMc+5rbD~!W0HZPq;{X5v delta 35 pcmbQsIFFJ0GcPX}0}$kSO`FJV%wwycn^&TrtnXM{T0GG+1OT3>3C{ok diff --git a/contas_mcp/servers/__pycache__/__init__.cpython-313.pyc b/contas_mcp/servers/__pycache__/__init__.cpython-313.pyc index 20a6bcb1dc6db053efaa1dbd04d377602d7b7877..fb77a9c25a35adb443cf8b6756cb8e8d8eb1aa3d 100644 GIT binary patch delta 34 ocmZ3+xRjCmGcPX}0}!--m^YEznA=4^H?KrLMc+5rbD~!a0HwML0{{R3 delta 35 pcmZ3=xQvneGcPX}0}$kSO`FJV%;Tz`n^&TrtnXM{T0GG+1^}T*3GV;^ diff --git a/contas_mcp/servers/contas_mcp_server/__pycache__/__init__.cpython-313.pyc b/contas_mcp/servers/contas_mcp_server/__pycache__/__init__.cpython-313.pyc index 77f6601882719706b07fe61397504633eb2bee69..94ad7ad8791a467540d7da8b7ba1d7b46e7bcd50 100644 GIT binary patch delta 34 ocmdnNxSf&vGcPX}0}!--m^YEzm^(~AH?KrLMc+5rbD~!s0IO^YO8@`> delta 35 pcmdnaxPy`VGcPX}0}$kSO`FJV%oDDkn^&TrtnXM{T0GG+4*;hy3O4`% diff --git a/contas_mcp/servers/contas_mcp_server/__pycache__/authorized_lines_service.cpython-313.pyc b/contas_mcp/servers/contas_mcp_server/__pycache__/authorized_lines_service.cpython-313.pyc index c58ce6815e421ab4201bab1f9945917bef386d72..f5504cd01912e00a2109e96ad5c2e3c094e2e5bf 100644 GIT binary patch delta 37 rcmX@1c3h47GcPX}0}!--n75I8FB5l~er{fgeu}nU|M~0SMYZ%-hI4k%>D^KR2&LKSkd+*mLs=rVIf9(9{cI delta 38 scmeBIo1n)1nU|M~0SNNErfuY&$i$PbpPN^rpRDg#Tw1(&Ia7uJ0L(KBO#lD@ diff --git a/contas_mcp/servers/contas_mcp_server/__pycache__/line_policy.cpython-313.pyc b/contas_mcp/servers/contas_mcp_server/__pycache__/line_policy.cpython-313.pyc index 4d38b53d315e94ceadf29dd3b08dbe3ced81b632..9f5e07cbc0707b1dd6ed1ae41a2cb3e018ef9d0d 100644 GIT binary patch delta 37 rcmZpaXprFk%*)Hg00iwH=56FwX5x<2&&?~*Pto@c_S|g6bet0azRe1j delta 38 scmZpWXq4do%*)Hg00enn(>8J|Gx0>}=jN5@C+j;FmlkifWIE0X0J(Pxf&c&j diff --git a/contas_mcp/servers/contas_mcp_server/__pycache__/main.cpython-313.pyc b/contas_mcp/servers/contas_mcp_server/__pycache__/main.cpython-313.pyc index 9814d3e8fe1180469f521815f880ed9a27d6e2a3..10352f8e3f44d40bdb94100f89d6ca06a61dd497 100644 GIT binary patch delta 9929 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 F{{}FNYgqsQ diff --git a/contas_mcp/servers/contas_mcp_server/main.py b/contas_mcp/servers/contas_mcp_server/main.py index 212d473..7ef59f5 100644 --- a/contas_mcp/servers/contas_mcp_server/main.py +++ b/contas_mcp/servers/contas_mcp_server/main.py @@ -151,9 +151,26 @@ def _invoice_subject_catalog(args: dict[str, Any]) -> list[dict[str, Any]]: key = _norm_invoice_name(canonical) if not key: return - item = found.setdefault(key, {"name": canonical, "value": value, "category": str(category or "").strip(), "contestable": contestable}) - if item.get("value") in (None, "") and value not in (None, ""): - item["value"] = value + item = found.setdefault(key, { + "name": canonical, + "value": None, + "values": [], + "category": str(category or "").strip(), + "contestable": contestable, + }) + if value not in (None, ""): + # Preserve every distinct billed value for the canonical subject. + # A subject may occur more than once on the same invoice; in that case + # no single value is authoritative until the user-selected amount is + # validated against this set. + raw = str(value).strip().replace(",", ".") + try: + normalized_value: Any = float(raw) + except (TypeError, ValueError): + normalized_value = str(value).strip() + if normalized_value not in item["values"]: + item["values"].append(normalized_value) + item["value"] = item["values"][0] if len(item["values"]) == 1 else None if not item.get("category") and category: item["category"] = str(category).strip() if item.get("contestable") is None and contestable is not None: @@ -283,6 +300,13 @@ def _preflight_subject(name: str, args: dict[str, Any]) -> dict[str, Any] | None subject = canonical if explicit.get("value") not in (None, ""): args["resolved_value"] = str(explicit.get("value")) + args["resolved_value_source"] = "invoice_unique_subject_value" + else: + # Multiple billed occurrences for the same subject (or no billed + # value) mean the subject alone cannot resolve an amount. Never + # preserve a stale/user-claimed value as resolved_value. + args.pop("resolved_value", None) + args.pop("resolved_value_source", None) category = str(explicit.get("category") or "").strip() if category: args["resolved_category"] = category @@ -334,8 +358,21 @@ def _preflight_subject(name: str, args: dict[str, Any]) -> dict[str, Any] | None args.setdefault("item_msisdn", resolved.msisdn) if resolved.charge_date: args.setdefault("charge_date", resolved.charge_date) - if getattr(resolved, "value", None) is not None: - args.setdefault("resolved_value", str(resolved.value)) + subject_key = _norm_invoice_name(resolved.canonical_name) + subject_record = next(( + item for item in _invoice_subject_catalog(args) + if _norm_invoice_name(item.get("name")) == subject_key + ), None) + unique_subject_value = subject_record.get("value") if isinstance(subject_record, dict) else None + if unique_subject_value not in (None, ""): + args["resolved_value"] = str(unique_subject_value) + args["resolved_value_source"] = "invoice_unique_subject_value" + else: + # Do not select one arbitrary occurrence when the same subject has + # multiple billed values. The user-selected value must be checked by + # CVAL against the subject before it can become resolved_value. + args.pop("resolved_value", None) + args.pop("resolved_value_source", None) # Paridade do backend original: se o cliente pediu cancelamento avulso, # mas a própria fatura classifica o item como estratégico/bundle, não # executamos a operação errada. A resolução determinística do domínio @@ -1040,7 +1077,14 @@ async def _validate_contestation(args: dict[str, Any]) -> dict[str, Any]: "parameter": "subject", "reason": "subject_not_resolved", "subject": args.get("resolved_subject") or args.get("subject"), - "resolved_value": requested_value, + # requested_value is only a candidate while the subject itself is + # unresolved. It must never be promoted to resolved_value. + "candidate_value": requested_value, + "resolved_value": None, + "clear_fields": [ + "resolved_subject", "resolved_value", "resolved_category", + "item_msisdn", "charge_date", + ], "validation_log": validation_log, "items": validated, "metadata": { @@ -1082,7 +1126,14 @@ async def _validate_contestation(args: dict[str, Any]) -> dict[str, Any]: "reason": "CVAL", "recoverable_reason": "amount_not_supported_by_invoice", "subject": canonical_subject, - "resolved_value": billed, + # The claimed value was rejected. Keep it only as diagnostic + # candidate data. The billed value may be shown to the user but + # is not persisted as the selected resolved_value until the next + # candidate is validated relationally against this subject. + "candidate_value": requested_value, + "billed_value": billed, + "resolved_value": None, + "clear_fields": ["resolved_value"], "parameter_message": message, "validation_log": validation_log, "items": validated, @@ -1105,14 +1156,25 @@ async def _validate_contestation(args: dict[str, Any]) -> dict[str, Any]: "items": validated, "metadata": {"side_effect_free": True, "target_tool": args.get("target_tool") or "contestar_cobranca", "guardrail_code": "CVAL"}, } + canonical_subject = str(args.get("resolved_subject") or args.get("subject") or "").strip() return { "eligible": True, "status": "ELIGIBLE", - "subject": args.get("resolved_subject") or args.get("subject"), + "subject": canonical_subject, + # Only the successful subject+amount CVAL relationship promotes the + # candidate into resolved_value. "resolved_value": requested_value, "category": args.get("resolved_category"), "validation_log": validation_log, "items": validated, + "transaction_decision": { + "resolved_arguments": { + "subject": canonical_subject, + "resolved_subject": canonical_subject, + "resolved_value": requested_value, + "resolved_value_source": "contestation_cval_subject_amount", + } + }, "metadata": {"side_effect_free": True, "target_tool": args.get("target_tool") or "contestar_cobranca", "guardrail_code": "CVAL"}, } diff --git a/docs/FIX_CONTESTATION_RELATIONAL_RESOLUTION_20260907.md b/docs/FIX_CONTESTATION_RELATIONAL_RESOLUTION_20260907.md new file mode 100644 index 0000000..6410712 --- /dev/null +++ b/docs/FIX_CONTESTATION_RELATIONAL_RESOLUTION_20260907.md @@ -0,0 +1,15 @@ +# Correção — resolução relacional de contestação + +## Regra + +`resolved_value` representa um valor efetivamente resolvido/validado para o `subject` da transação. +Um valor apenas informado pelo usuário é `candidate_value` até a pré-validação autoritativa confirmar a relação `subject + valor` contra a evidência da fatura. + +## Invariantes + +1. Um valor divergente não é promovido a `resolved_value`. +2. Se o mesmo subject aparece com vários valores na fatura, o subject sozinho não escolhe um valor arbitrário. +3. Se dois produtos diferentes têm o mesmo valor, o valor não substitui um subject já identificado por evidência mais forte do usuário. +4. Quando a pré-validação rejeita um parâmetro, ela pode declarar `clear_fields` para invalidar derivados dependentes; o framework aplica essa lista sem conhecer semântica de domínio. +5. A extração do turno atual ocorre antes da reconciliação. A reconciliação pode canonicalizar o candidato, mas não apagá-lo antes da pré-validação. +6. Somente uma validação relacional bem-sucedida promove o candidato a `resolved_value`. diff --git a/docs/FIX_RECONCILIACAO_REWORK_MINIMO_20260907.md b/docs/FIX_RECONCILIACAO_REWORK_MINIMO_20260907.md new file mode 100644 index 0000000..dd481db --- /dev/null +++ b/docs/FIX_RECONCILIACAO_REWORK_MINIMO_20260907.md @@ -0,0 +1,19 @@ +# Rework mínimo da reconciliação temporal — 2026-09-07 + +## Princípios + +1. Extração do turno atual é uma etapa curta, sem histórico. +2. Reconciliação temporal só roda se required fields continuarem faltando. +3. Candidate estrutural só existe quando há um único evidence block ancorado por parâmetro conhecido. +4. Candidate estrutural nunca é resolved; exige pre-validation configurada. +5. Não existe fallback baseado apenas em uma fala histórica única. +6. A pre-validation/CVAL é a autoridade para canonicalização e relação subject+valor. +7. Intent shift genérico não encerra transação ativa; abandono explícito pode encerrar e rerotear. + +## Cenário 08 + +Mensagem atual -> valor 14.99 (current-only extraction) -> histórico ancorado -> candidate subject -> CVAL -> subject canônico -> confirmação. + +## Cenário 16 + +Subject preservado -> valor 25.50 candidato -> CVAL rejeita relação -> valor continua pendente -> valor 19.99 -> CVAL valida relação -> confirmação. Uma fala como "isso mesmo, pode cancelar" permanece na transação; abandono explícito como "esquece isso, quero ver minha fatura" pode rerotear. diff --git a/tests/migration/test_contestation_resolved_value_relational.py b/tests/migration/test_contestation_resolved_value_relational.py new file mode 100644 index 0000000..22f9e44 --- /dev/null +++ b/tests/migration/test_contestation_resolved_value_relational.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +import asyncio + +from contas_mcp.servers.contas_mcp_server import main + + +def _analysis(): + return { + "currentInvoice": [ + { + "type": "servicos_contratados_de_parceiros", + "items": [ + {"desc": "Tamboro Mensal", "value": "14.99", "contestable": True, "classe": "avulso"}, + {"desc": "Tamboro Mensal", "value": "19.99", "contestable": True, "classe": "avulso"}, + {"desc": "Outro Produto", "value": "19.99", "contestable": True, "classe": "avulso"}, + ], + } + ] + } + + +def test_subject_catalog_does_not_choose_arbitrary_value_for_repeated_subject(): + catalog = main._invoice_subject_catalog({"billing_analysis": _analysis()}) + tamboro = next(x for x in catalog if x["name"] == "Tamboro Mensal") + assert sorted(tamboro["values"]) == [14.99, 19.99] + assert tamboro["value"] is None + + +def test_preflight_does_not_resolve_value_from_subject_when_subject_has_multiple_values(monkeypatch): + class DummyClient: + def billing_analysis(self, _msisdn): + return _analysis() + + class DummyService: + client = DummyClient() + + monkeypatch.setattr(main, "service", DummyService()) + args = { + "msisdn": "11999999999", + "subject": "Tamboro Mensal", + "query": "não reconheço esse Tamboro Mensal", + "billing_analysis": _analysis(), + "resolved_value": "25.5", + } + # The resolver may continue to normal validation, but it must not retain an + # arbitrary/stale resolved_value just because the subject matched. + main._preflight_subject("contestar_cobranca", args) + assert args["subject"] == "Tamboro Mensal" + assert args.get("resolved_value") is None + + +def test_invalid_amount_is_candidate_not_resolved(monkeypatch): + async def no_enrich(_name, _args): + return None + monkeypatch.setattr(main, "_enrich_invoice_context", no_enrich) + monkeypatch.setattr(main, "_preflight_subject", lambda *_a, **_k: None) + args = { + "msisdn": "11999999999", + "subject": "Tamboro Mensal", + "valor": 25.5, + "billing_analysis": _analysis(), + "target_tool": "contestar_cobranca", + } + result = asyncio.run(main._validate_contestation(args)) + assert result["eligible"] is False + assert result["status"] == "NEEDS_PARAMETER" + assert result["parameter"] == "valor" + assert result["candidate_value"] == 25.5 + assert result["resolved_value"] is None + + +def test_valid_amount_is_resolved_only_after_subject_amount_validation(monkeypatch): + async def no_enrich(_name, _args): + return None + monkeypatch.setattr(main, "_enrich_invoice_context", no_enrich) + monkeypatch.setattr(main, "_preflight_subject", lambda *_a, **_k: None) + args = { + "msisdn": "11999999999", + "subject": "Tamboro Mensal", + "valor": 19.99, + "billing_analysis": _analysis(), + "target_tool": "contestar_cobranca", + } + result = asyncio.run(main._validate_contestation(args)) + assert result["eligible"] is True + assert result["resolved_value"] == 19.99 + resolved = result["transaction_decision"]["resolved_arguments"] + assert resolved["subject"] == "Tamboro Mensal" + assert resolved["resolved_value"] == 19.99 diff --git a/tests/migration/test_contestation_subject_entity_resolution.py b/tests/migration/test_contestation_subject_entity_resolution.py index f43481f..de6187e 100644 --- a/tests/migration/test_contestation_subject_entity_resolution.py +++ b/tests/migration/test_contestation_subject_entity_resolution.py @@ -50,6 +50,8 @@ def test_validator_turns_unresolved_subject_into_recoverable_parameter_request(m assert result["status"] == "NEEDS_PARAMETER" assert result["parameter"] == "subject" assert result["reason"] == "subject_not_resolved" - assert result["resolved_value"] == 10.0 + assert result["candidate_value"] == 10.0 + assert result["resolved_value"] is None + assert "resolved_value" in result["clear_fields"] assert result["metadata"]["entity_resolution"] == "invoice_evidence" assert "error" not in result diff --git a/tests/migration/test_requested_tools_parity_pente_fino.py b/tests/migration/test_requested_tools_parity_pente_fino.py index da631a7..ffc05b8 100644 --- a/tests/migration/test_requested_tools_parity_pente_fino.py +++ b/tests/migration/test_requested_tools_parity_pente_fino.py @@ -113,7 +113,7 @@ async def test_validar_contestacao_usa_mesma_cval_e_rejeita_valor_acima_da_fatur @pytest.mark.asyncio -async def test_validar_contestacao_aprova_quando_item_e_valor_sao_comprovados(monkeypatch): +async def test_validar_contestacao_rejeita_valor_que_nao_pertence_ao_item(monkeypatch): billing = json.loads((ROOT / "app/domain/contas/fixtures/divergencia.json").read_text(encoding="utf-8")) async def no_enrich(name, args): @@ -127,8 +127,12 @@ async def test_validar_contestacao_aprova_quando_item_e_valor_sao_comprovados(mo "motivo": "quero contestar TIM Fashion Mensal", "billing_analysis": billing, }) - assert out["eligible"] is True - assert out["status"] == "ELIGIBLE" + assert out["eligible"] is False + assert out["status"] == "NEEDS_PARAMETER" + assert out["parameter"] == "valor" + assert out["candidate_value"] == 50 + assert out["billed_value"] == "10" + assert out["resolved_value"] is None def test_termino_desconto_e_valor_divergente_preservam_semantica_do_original(): diff --git a/tests/migration/test_subject_entity_resolution_all_domains.py b/tests/migration/test_subject_entity_resolution_all_domains.py index 4711601..d23741a 100644 --- a/tests/migration/test_subject_entity_resolution_all_domains.py +++ b/tests/migration/test_subject_entity_resolution_all_domains.py @@ -274,6 +274,9 @@ async def test_contestation_wrong_amount_is_recoverable_with_invoice_amount(monk assert result['eligible'] is False assert result['status'] == 'NEEDS_PARAMETER' assert result['parameter'] == 'valor' - assert result['resolved_value'] == '14.99' + assert result['candidate_value'] == '29.98' + assert result['billed_value'] == '14.99' + assert result['resolved_value'] is None + assert 'resolved_value' in result['clear_fields'] assert 'R$ 14,99' in result['parameter_message'] assert 'R$ 29,98' in result['parameter_message']