From 82636ec15b0118e2fa96e50d332bfe5d3cf28f1d Mon Sep 17 00:00:00 2001 From: "cristiano.hoshikawa" Date: Tue, 8 Sep 2026 10:13:03 -0300 Subject: [PATCH] bugfix: extractor cases 8 and 16 --- .../__pycache__/agent_runtime.cpython-313.pyc | Bin 200597 -> 198228 bytes .../transaction_parameters.cpython-313.pyc | Bin 14476 -> 19573 bytes .../agent_framework/runtime/agent_runtime.py | 118 ++++-------------- .../runtime/transaction_parameters.py | 96 +++++++++++--- 4 files changed, 109 insertions(+), 105 deletions(-) diff --git a/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc b/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index 7be129632969730dc1a4c132323536093b0e7c4c..23e52040f9fbf575b364daff0b9504c416890c46 100644 GIT binary patch delta 23987 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 dHFC>}sghPFrWWGJALBxG+aua0Q|1bQ}J)r;q delta 25858 zcmb_^34D~*)%V;xOZJeJ?8$_zlZ320H5yFrJ2qcsEOu~{@)7IAZv)YQI zUi8(1+A6eGp=lkftp&vvmzKn!Nk`GxTD7P(Aigeb?RWm?nGK}h_x1OF`TcU{K6g3y zZ1>!Am*+WsbL<@lV&gxGi;FhU->Yp0cKFU8jo%kp{FSN>S9euQ)iV2%rWIP}j@IUG zch$}c_$ELD0bgWG>sDt^d$(J=vHy1!Cr#o;&#g68rQB>k zDnvJLce-4y?M-bhHj8#W8dd=m0Nm35PR;M-xLZ&$qP3%~yQ!^NJK%X{Qhv-mD1Qjx z0Z+n|lzwCV`y&5-dbXJ~t{=(uU7gebwGIRPn5w=k9`W2<_wfYn%aylj?Uz)}@}y5I zvh<_vBmMKIT@WiDpmgJE?T5&!1NadEoAkwR>2bHYTHWrZ)?Fk-Ce0?aT_`o{6q!Jg zR)R(sla%tnJu}RUe}aM#TNgjtqO?ksF9To!xhUl`clUI)w=zzjxvjgk!>zeJZ_Qn1 zI!>jY`#Mtlmo{`76E4Q3J?MGvimbWc1uE3@nRd84T|RS5Pe+$qr|)KzJxPFcQiCcM zt<_Cx)T}7D4d9vn!UYe=1~*Dmny7EBsl(aT)#lpPw9DDv)9Thhq4paBHmTJk{VV~u zBw)2_lacW<0ngDHsr@;NPn*Q4{_|HI6nV(hUIbuKy^hpI03Dy_XydBby?8zi;4!FU z$He&lqU9wf%LsB#c~;qHWe2g4J^U5fX8}F{_*?%^?56^i`@gooYt9>lXFBMOn7kOLYHX7u*OM#90 zBDOo-&hBna%k$K?7xxtaH%6*2+TGgi_ke5xKBLpMmz{#o*xu^$MFlu@Yt?8}L%=87 zT6|`AbEig1ASAYQ9)kMN6R0Ht*q;B0PLed|wx%$Zd3^0TwtJ~W7ikh|rvvzqcM466 zt$Ug^W-Q-h?Wj*ILvbYlt0GFM+(=Q_e^bZ(7I9<$#O@^~vDdSEPmU!Sby7Tc?X2($Z|gEnztoB@fBt`Vu_0ARvra%$V$KCx4K z6HigiPFJU^t=ZW>cdywbUi2)yZgn<%gwNdGxtk1j0~&4ws6>x1_CI#r45QfNIsdf@ z;+Fo@uP2$W+D!%IP+_*(Ow@#~v|gmx+Mf?n?oV0R-99we-5@(f!$dEW>?33-{oQUgBzL-LpW`IyG%4GA!+#+qSi8 zzKGpU%|#yHXKHh8?bN{hL_qp5?YS_)UR?;^h*)xM8HbBD9LdAr86FG7Z; zgQA)3ZtY=y=%S`w-I^N@M$NgK=UZPyb7!m8OrC{xkw?g^*8aEe`q)fH|Js4f{E$?i zr-n44U`o{3V42|O`qK{fN~(O@{Z8?c=feH%YeP-`Kuxq$0BmJ1AO+__1{gxavH&h$ zWRtTUhTP(dXwq7pG%@?#Mf28e+JMj}yFWazC|>vEw|laFcBNS6+4i$4%Y&fml;@tG z^_DShe?nJp0i2=|Uos|#RyTRjrjY%MI@{WtI=fn3T9jw7e`W($1s^_3S7&=$^Il&>N1K~sqHVSaT~;A_*kzBQ zZY0GG9c?aWI}zUab1gg6A&RvW2+FLzf%Kc6*M2^KHVpFLAViUN0Ra3S7CPI}uGT%> zP3~@*3$)XojlZ~JU8oPHgPVN@wBs(F*FyowSAq6nh%vsYnKabY(cGoau*WD1jqE+1KM9^v zdlj{Lf&*ItL$spkV!C~@YnNu~|HJXWn9}xA)kZetg=B|R^$~#6p67qNPKa}Nqzju{=66B z&H89c@zf1WUdV)VJ$(jYxd8CA2EzSOu`VqT<%=R`LWa@2y;WCuiu5E-N$!7oKr;*J zseffsUj$WKsO1y2HlrTBG$nrx@16=xI{NY7YcXzvX zf^u}+KpQ;;u?9b}i* z+U2CBh_(tfgQRM!@p#g6--XOR@Z*bdw`vqjH@Tc0tsHKU2{A_Ib~9>&6mrhY+QT3d zO3)*>CZxcw&xBqt$Et2^h&Of19;DhF&gD?fC4%1obXPM@&($C2MsW~wiW;cVGqlLO z{o@UB4WNcrJGvf#brb6IQMVMpM&RN_6E*hL zQT&&pHb#nA^&uIjh*q;qVnQ00^1jH`%a>o(w5H*z03Fe4mq`>)3>io~;q)bL>v3u= z8Yb#3?VZg#Ng1rwLiC!eo->Iyv0l}gMWN*+i1w(BW>K!|^IG*iv&aghA2o|9am+DB zFiou;>LasQvJf5i#*u@yvhTCfawnj^Yatc(HyWjS$tY;FRnjo1L?xpxKVZ}H)i*3+ zULT|9R&e_ow@OCxEK_SAZ>ez6yYcDEzQ5T6gSC+i2nU3>sA`SA7Ug2w)axK*F=inM~FS%vIJp^=$nbYk^wLz_0`9Eq!88=qbjQi_5XTI>UKf)`+9HOLI1N zH)%cXv>U{;dMz-!(2%F98@#FMVzRL`NHEz2)5iosuNO^0KCe4Vd}0!RQ9G?-YvpZ( z=W{vT+Nfd8MKwq1$0yo+X0~>>ksdMi@mABHRCTpTSDPmYtD2H8R!sy~q>!%mw(fRp z+-Yrujxs3B=yvaJ>)x(!I=xHPG?#iTUs%Nn?{L0Y7Hh$#o-bRiOc&$T+)5EOlP%#> zuyqjXcnX*z$pNx!^F{Z#DB0P*i?qHU!{jtjFZF(_QdEivFheGTBkufZq$5G{=`g)C+J4@#p+#aG_pGEIhn}sSIE5jIk(OM_%^>E~;J&Ype^q1<3 z8c{7ys;XLIn4Jg51;6kvuN61P^nt}j?MJAu3j!$~2oE3yz3JF~ibvk6C`BHmc{m_V zkQUNq2+uF6jV)gHHkU}1#kkDSK`oyE=8%*xC&5@q=u2B4p)P*~6vqHA7K(Npc`S%u zP>SPS?;EqlP4TfI_I@ZsCZzqGs$Fb7)V1%5z|KN0b`|Qc_5v;VY}9^&Bnym%eu<5oP0K~zqRUA+%-qn| z(*Vx^oB((h;5P((k?Xb-8elZ=8@1;^ z^FGk|GEy(8o7RcD%fVB?bD6to+r*`BLg>CLd_QQeN_<`9s*d$y{YI7q+@rp<;ux3Z z$s_xD;GYY`{veM{hP!4b%#^Svz8xsog-7me-MhO}YoT3xZ{Y?pTVAPC2~uwfKWA-h0fa&%|Y^cni zv$4Ezb~K0)Zq2F2wu%)ATZvd-q^otClN?>Awq32*Cid9b!SfWyQf2FV3~av-gfKUX zs&%$#v!jLfGqitFCibJd=;VyJ{0l1bq_zd^T7~L6E600lwu|#7@lRFQAtuGJhd2h} z=cwimG0nox>jTfe_2a#dcZjzvX`?9ofWXBAR-d+-wu>nBa*s$;?{$k!Ja_3Dj?mJ` zROl4VNu<#lndY%v%HSzR%R}mfcUO;)CJVArJ2Ns`+7vs+&iS1auV{I4C;k*^Sq9Ic3Qm$`^^q44; z2Ub!PU8#NF5XGWgJ^l@GmH1qlZxD0F!{sg1coqK-Nbc_dpQ-gXi2s$%LGuJO-A{m~ zx;oH28DO^h*9~HNAGDw)p)gvjMt;caEs~@d+2? zsm~PLBRs8E1;P@kz?bN^fu>gP0S zoh0$59yf*OZJqi#2&?2Xm3FhpD^CUz#C$qmi-E#Fl&#>5$1}*Gso#0Cu*L8Kjuo7y z?k$$--k;tq@{IwNpZ>n6h~d&ow0YJWbF27Vj^q8e2zSpG8~|%pmEsXLJqTxXy#Hne z5o^(E20$u$|BUj;93039iJT2QD0dn%HK@zv&PUBqu*{2F#tGTFBdH!mY5b?D@1K=s z?{SZ4HHlkP$$n8PZc{7vi?ppgOhYQYc&yTHWDo7Q^VaVMkj(qP4Mbqa|LqF&3iA|-NDH94BAt@GY*MZA$EBe9~PfkW-%GN(D@VqCWyuTKFD|v zAQTpH)WS162QfcY*B=q}F}u-_Jx#KD>WIkiV{`$b_)jRgQZn=tiUk?nb!g4{NeCMV zx_(f^Ar0$i4<7ddu%>vn;dKtrq^!(apzLyvwGj{5lEVhjB?K{%`_=zCD(b`=>eoj_ zehlVtJ$gRw{p(Q?VHWGuxyQt&7(S#+L20sgy;oc-8;_x*iw6?TWv&)|&BLQ-BkD8t zH={DshjV-m@M$o8fHY5FCsf80Vvgl*V$C;8t-MoadG|gcOhSC1u76UDPeb%aQ3D6* z`@#QR0C#(T@}yX7nhU-f_4$EqU7wLqgUtzorvdkGb#hA89TRN@m}K;MDYA7}8=Y1+ zw`%Y#bSm5C?(Wp~YJJ|{924tJ;-JcWRuqYQ)!b)k`EV9ouzUZZ+Wf32NO^$z^Th^m zkkPueUaxvqJTJuO-Yvfqr^M_~UkU9_cX#+=iJbiXAU#;6QDY0`;emnTOI7=ZMQR@} zF8tFTa~wAJft6U8+J94u!lTe?g3anj=l~`Z*vzzohhUGqXmFb;Pxq#iQHm+gSJ8l* zJ*((2z0LEr(I{{1^J2`@&h&-GaLCMp16k_{vh*`bHER8MzU;is&WoMqOwrf;^#}=4 zd8nTdzvz*?qRZLk-rm{mwge<-)x4WtCcVcn+j@O9by#GJUwR$GVy{{JSe<%Jj2D~K z+pmedn4dy_yqR&EN;o67ZVc&kOFqawYM*OVMpg|ssXGH1<0qq;&5B6Xko`KTx;hWGTP za6}Y1n+t?SL7i%|)IUc>URohU9{Fcg{&9jpZfk7-0~6CjZ`CWQe>r`!s?zkQ)TTV^~d)`iRoXIRs+Q{)tm8w zs5UO(E|bxKHO;DHTF_Td8WlLLbmFTypLyt+2Rf~^rPbElhNC&%Uw@an)z+!+jfsye zy&&cm_3d-Cx6Ep}T^&6qGHQ8mLl0d+2=AHd?WnQOLKZ-~tP}@0x3spqH3)@w-n~iZ zMT04WSE5YTUMlggsb8h8)P3v3SBkVVlq5-vf(2gYBiQq6A+VNKv7d;Y#iOVh8QMtD ztq8+V-*C{^(CXe#M1Cp4?ZBGWzmNGGDniBjk>s1;*5!Ts6ERc9!wED7mbOo->d!@L zECO$zsmn>biu=7QKNqz!8$;SR4yV7g=4z^?TbCUj&R%0>?N;rl>cBrlZURrkXCTxa z=x(R?_x})s#?`!|f)%PSVr!eL1*aaNA@C84k?vwpFwFb7WCvKd;h?>v3m2j^rX@nJ z;?{T{;Pfxf%Tz%DUZj*)#3zOc7dIs|huWARYi(?Cr@*uo7-RI?qO2;i;(viqF8x$J zo*;89pCQAgUQLj*VmM;p8n>x}L|Iyhw9nk!Ni&i!%8ipECr#BFhC5y4;r-YS)tM+y zT1Sy3wsH({i7HVtU*!v#syZK)W_4|nbgjfzO|P6`$ZfNm({qN#?7xW{`SPmZ^w!UgIZ8dmg~3$pUm z^F=bxvIyx5>cb+rbSiHXuxeS;a7;c6-Lj<1O4@tq1wn6M<-{GNp>?skwpjYF92bM4 zMP6EEyDfc}?G`QAM-@r^>N;NCdvon`*2ap7fE*}aVe^U`)|~js;oXHl(!go*W{U?xL8u$Ssv)N5gPq+ z7`s}Y5J)b5^}sLa`0fAJO+Jde(J5t2nMY}sLf8%OTkBl{KFP*_P9?WmD2k@hfmZl(KEO#xfe_s8Oc z`7BNCkLZEts87&LXu7OI!m+A-vt-KjiO@jEZs|;-tEXGve_`Y1fqa?a>(2JPc~_qI zi&^q?jDusZ$t2!|VGGhLA#PrJ!d84{cBWbb=xRXGT!3^G(e+@u#!6S1wzqBVCRwvC zqgBaLS)#jS4(38pAV&(Jz=6ZR&(!Xv1vgCvq(!| zg|Xy0d^M;GOXUO$ucaGR_LZ{0qEqNyaHYJ?7_$#FH$q!y)bAT*hP=w=eYa8m(`1Zv zO7*T?{>T{Nd_>*4ni7UpIcl(2q~to{9f^){_MB;^B?i0LP894CcNiPZu?APNBgu2* z?^NcA*7lA#8EEzEVPZdpZJ zu*rtS@l-!`1DrblIa2G1NBpgj%SdN22CKm}-j(VwsIM;-DOQIdp2j

;;$MDb10_ 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 R+hRSbs{i{Y6gmE>@oyQPi;DmN delta 1312 zcmah|TW=dh6rS}h_Byt6aV|}$IxP|LHj$kw+-jssQL2h0)LbIdN&z{O-ATO3de+R0 zoyJ1Ag%(sO2sG;Dt*^Y6JRtQ?0O|u)ka$Pp;;1bMgb-&oT>63-?SA|1nRCAR=Irdl zTgJ6F()Uv-6T$e#y}fz*#GUk9_=(Gf8j}U5aCUj2@)GwqsVzleYt30JkPXUY#rByb zVs|V2`-oxfR>yxxhFfE%${ZeP7jbLAtP@UZR8n4H@DxRS#xnMLDH9D&D@53?+Zr6(psk^y{Gp_|b+8!mG zuL0*&gRSA523^Bv09xmjF+Z#_R$})L%QHsG5Zg1?Jt8Yj;x#DOa{QdSH1(Eo<+JH` zV=pHm@D4)8{mVceM;Kj4D+bVDlu_9zhsxn{q#P~B%00`*$@l_V4pqYlHI3`xQnVMb z_zJxJl^=g4s=gW?RL_O7svU}|FJ{g51d5~5edg`JtMI)hb+Ap~OE^SQkvGi}-NwAZq+6rd_Mu8t{f6h@hM>5(-e7id zl~d@o?RvB#Ibnj>>Zhqpdlhe2DZ{Qb8KsWEb`F>w{VLRz<1~(dT2i8(LprgN;LUQ~jF8PdF0|(}H;v;E6AA$m@?k>!>Kh)DfBRjJZSZQEz=YD<{v4sIB&S>^Tm@!P3oldest preservado na transação. - missing_after_current = self._missing_required_arguments(policy, arguments) - if missing_after_current: - required_fields = [str(name) for name in (policy.get("requires") or [])] - reconciliation = await self._reconcile_transaction_parameters( - state, - tool_name=tool_name, - 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 {})) - 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 []), - } - else: - state.pop("transaction_parameter_reconciliation", None) + state.pop("transaction_parameter_reconciliation", None) # Argumentos estruturados já presentes no contexto são aceitos de # forma genérica (não são parsing textual). Para required fields, @@ -3096,65 +3086,11 @@ class AgentRuntimeMixin: state, tool_name=tool_name, arguments=arguments, policy=policy, emit_events=emit_events ) if pre_validation_result is not None: - # A pre-validation é a fronteira autoritativa da coleta - # tradicional. Se ela rejeitar um candidato de forma recuperável - # (NEEDS_PARAMETER), ainda não repromptamos o usuário: fazemos UMA - # tentativa de reconciliação temporal com o histórico bounded e - # com a semântica declarada em tools.yaml. Isso cobre referências - # como "é a de R$ 19,99" sem tornar o reconciliador o caminho - # primário de COLLECTING_PARAMETERS. - pre_meta = state.get("transaction_pre_validation") - pre_meta = pre_meta if isinstance(pre_meta, dict) else {} - retry_parameter = str(pre_meta.get("parameter") or "").strip() - recoverable = ( - str(pre_meta.get("status") or "").upper() == "NEEDS_PARAMETER" - and bool(retry_parameter) - and state.get("transaction_status") == "COLLECTING_PARAMETERS" - ) - if recoverable: - recovered_selected = dict(self._active_transaction(state) or state.get("selected_tool_call") or {}) - recovered_arguments = dict(recovered_selected.get("arguments") or {}) - required_fields = [str(name) for name in (policy.get("requires") or [])] - reconciliation = await self._reconcile_transaction_parameters( - state, - tool_name=tool_name, - parameter_names=required_fields, - known_arguments=recovered_arguments, - ) - for field in reconciliation.get("clear_fields") or []: - recovered_arguments.pop(str(field), None) - recovered_arguments.update(dict(reconciliation.get("values") or {})) - state["transaction_parameter_reconciliation"] = { - "tool_name": tool_name, - "trigger": "prevalidation_needs_parameter", - "rejected_parameter": retry_parameter, - "decisions": dict(reconciliation.get("decisions") or {}), - "provenance": dict(reconciliation.get("provenance") or {}), - "clear_fields": list(reconciliation.get("clear_fields") or []), - } - retry_policy = self._resolve_tool_execution_policy(tool_name, recovered_arguments) - retry_missing = self._missing_required_arguments(retry_policy, recovered_arguments) - if retry_parameter not in retry_missing: - state["selected_tool_call"] = {"tool_name": tool_name, "arguments": recovered_arguments} - self._set_active_transaction( - state, tool_name=tool_name, arguments=recovered_arguments, status="COLLECTING_PARAMETERS" - ) - state["missing_parameters"] = retry_missing - pre_validation_retry = await self._run_transaction_pre_validation( - state, - tool_name=tool_name, - arguments=recovered_arguments, - policy=retry_policy, - emit_events=emit_events, - ) - if pre_validation_retry is None: - arguments = recovered_arguments - policy = retry_policy - pre_validation_result = None - else: - return [pre_validation_retry] - if pre_validation_result is not None: - return [pre_validation_result] + # A pre-validation é a fronteira autoritativa. Se pedir um + # parâmetro novamente, o estado produzido por ela é preservado + # e o próximo turno volta ao mesmo extractor. Não existe uma + # segunda tentativa escondida de reconciliação no mesmo turno. + return [pre_validation_result] tool_name, policy, force_confirmation = self._apply_prevalidated_transaction_decision( state, tool_name=tool_name, arguments=arguments, policy=policy diff --git a/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py b/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py index 88cfbeb6..4ba3b879 100644 --- a/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py +++ b/libs/agent_framework/src/agent_framework/runtime/transaction_parameters.py @@ -230,20 +230,88 @@ async def extract_transaction_parameters( tool_description: str | None = None, conversational_context: str | None = None, ) -> dict[str, Any]: - """Compatibility facade returning only resolved candidates. + """Extract transaction parameter values with one simple source of truth. - New runtime code should use :func:`reconcile_transaction_parameters` when it - needs preserve/clear/provenance decisions. Keeping this facade avoids - breaking routers and existing extensions that only need candidate extraction. + The current utterance is authoritative for new values/corrections. A bounded + conversation context may only be used to resolve references made by the + current utterance (for example, "the 14.99 one"). Known arguments are state + defaults: if a field is not returned it is preserved by the caller. + + The extractor does not decide preserve/clear/unresolved, routing, confirmation + or execution. Business validity remains the responsibility of pre-validation. """ - result = await reconcile_transaction_parameters( - llm, - text=text, - tool_name=tool_name, - parameter_names=missing_parameters, - known_arguments=known_arguments, - parameter_schema=parameter_schema, - tool_description=tool_description, - conversational_context=conversational_context, + names = [str(name) for name in (missing_parameters or []) if str(name).strip()] + message = str(text or "").strip() + if not names or not message or llm is None: + return {} + + schema = dict(parameter_schema or {}) + known = { + str(key): value + for key, value in dict(known_arguments or {}).items() + if value not in _EMPTY_VALUES + } + field_spec = { + name: { + "type": schema.get(name, "string") if not isinstance(schema.get(name), dict) else schema.get(name, {}).get("type", "string"), + "description": None if not isinstance(schema.get(name), dict) else schema.get(name, {}).get("description"), + } + for name in names + } + output_shape = {name: None for name in names} + prompt = ( + "Você extrai parâmetros de uma transação ativa. Não faça roteamento, confirmação, execução ou validação de negócio.\n\n" + "REGRAS:\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.\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.\n3. A fala atual é a fonte principal. Retorne um campo quando a fala atual o informa, corrige ou referencia de forma suficientemente clara.\n" + "4. conversational_context é apenas contexto recente para resolver referências da fala atual, como 'esse', 'a de 14,99', 'o primeiro'. Não trate texto do contexto como uma nova afirmação do cliente; use-o somente para interpretar a referência atual.\n" + "5. known_arguments contém valores já conhecidos. Não os repita por obrigação. Se a fala atual não os altera, omita o campo ou retorne null; o runtime os preservará.\n" + "6. Se a fala atual corrigir explicitamente um valor conhecido, retorne o novo valor. A fala atual tem precedência temporal para esse campo.\n" + "7. Você pode retornar mais de um campo quando a combinação da fala atual com o contexto recente determinar a relação de forma clara.\n" + "8. Não valide se o valor existe no backend nem se a combinação é permitida. Retorne o candidato textual; a pre-validation fará a validação autoritativa.\n" + "9. Em caso de dúvida razoável sobre a correspondência ou o valor, prefira null. Não invente associações.\n" + "10. Responda somente JSON válido, 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"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"user_message: {message}\n" + f"conversational_context: {str(conversational_context or '').strip()}\n" + f"Formato obrigatório: {json.dumps(output_shape, ensure_ascii=False)}" ) - return dict(result.get("values") or {}) + + try: + response = await llm.ainvoke( + [{"role": "user", "content": prompt}], + profile_name="transaction_parameter_extraction", + component_name="transaction_parameter_extraction", + generation_name="llm.transaction_parameter_extraction", + temperature=0.0, + ) + except TypeError: + response = await llm.ainvoke([{"role": "user", "content": prompt}]) + except Exception as exc: + logger.warning("transaction.parameter.extract_failed tool=%s fields=%s error=%s", tool_name, names, exc) + return {} + + raw = _response_text(response).strip() + try: + payload = parse_json_object(raw) + except (TypeError, ValueError): + logger.warning("transaction.parameter.extract_invalid_output tool=%s raw=%r", tool_name, raw[:240]) + return {} + if not isinstance(payload, dict): + return {} + + values: dict[str, Any] = {} + for name in names: + value = payload.get(name) + if value in _EMPTY_VALUES: + continue + declared = field_spec.get(name, {}).get("type", "string") + coerced = _coerce(value, declared) + if coerced not in _EMPTY_VALUES: + values[name] = coerced + return values