fciannella's picture
Working with service run on 7860
53ea588
raw
history blame
6.83 kB
import os
import sys
import json
from typing import Any, Dict
from langchain_core.tools import tool
# Robust logic import to avoid crossing into other agent modules during hot reloads
try:
from . import logic as wt_logic # type: ignore
except Exception:
import importlib.util as _ilu
_dir = os.path.dirname(__file__)
_logic_path = os.path.join(_dir, "logic.py")
_spec = _ilu.spec_from_file_location("wire_transfer_agent_logic", _logic_path)
wt_logic = _ilu.module_from_spec(_spec) # type: ignore
assert _spec and _spec.loader
_spec.loader.exec_module(wt_logic) # type: ignore
get_accounts = wt_logic.get_accounts
get_profile = wt_logic.get_profile
find_customer_by_name = wt_logic.find_customer_by_name
find_customer_by_full_name = getattr(wt_logic, "find_customer_by_full_name", wt_logic.find_customer_by_name)
get_account_balance = wt_logic.get_account_balance
get_exchange_rate = wt_logic.get_exchange_rate
calculate_wire_fee = wt_logic.calculate_wire_fee
check_wire_limits = wt_logic.check_wire_limits
get_cutoff_and_eta = wt_logic.get_cutoff_and_eta
get_country_requirements = wt_logic.get_country_requirements
validate_beneficiary = wt_logic.validate_beneficiary
save_beneficiary = wt_logic.save_beneficiary
generate_otp = wt_logic.generate_otp
verify_otp = wt_logic.verify_otp
authenticate_user_wire = wt_logic.authenticate_user_wire
quote_wire = wt_logic.quote_wire
wire_transfer_domestic_logic = wt_logic.wire_transfer_domestic
wire_transfer_international_logic = wt_logic.wire_transfer_international
@tool
def list_accounts(customer_id: str) -> str:
"""List customer's accounts with masked numbers, balances, currency, and wire eligibility. Returns JSON string."""
return json.dumps(get_accounts(customer_id))
@tool
def get_customer_profile(customer_id: str) -> str:
"""Fetch basic customer profile (full_name, dob, ssn_last4, secret question). Returns JSON string."""
return json.dumps(get_profile(customer_id))
@tool
def find_customer(first_name: str | None = None, last_name: str | None = None, full_name: str | None = None) -> str:
"""Find a customer_id by name. Prefer full_name; otherwise use first and last name. Returns JSON with customer_id or {}."""
if isinstance(full_name, str) and full_name.strip():
return json.dumps(find_customer_by_full_name(full_name))
return json.dumps(find_customer_by_name(first_name or "", last_name or ""))
@tool
def find_account_by_last4(customer_id: str, last4: str) -> str:
"""Find a customer's account by last 4 digits. Returns JSON with account or {} if not found."""
accts = get_accounts(customer_id)
for a in accts:
num = str(a.get("account_number") or "")
if num.endswith(str(last4)):
return json.dumps(a)
return json.dumps({})
@tool
def verify_identity(session_id: str, customer_id: str | None = None, full_name: str | None = None, dob_yyyy_mm_dd: str | None = None, ssn_last4: str | None = None, secret_answer: str | None = None) -> str:
"""Verify user identity before wires. Provide any of: full_name, dob (YYYY-MM-DD), ssn_last4, secret_answer. Returns JSON with verified flag, needed fields, and optional secret question."""
res = authenticate_user_wire(session_id, customer_id, full_name, dob_yyyy_mm_dd, ssn_last4, secret_answer)
return json.dumps(res)
@tool
def get_account_balance_tool(account_id: str) -> str:
"""Get balance, currency, and wire limits for an account. Returns JSON."""
return json.dumps(get_account_balance(account_id))
@tool
def get_exchange_rate_tool(from_currency: str, to_currency: str, amount: float) -> str:
"""Get exchange rate and converted amount for a given amount. Returns JSON."""
return json.dumps(get_exchange_rate(from_currency, to_currency, amount))
@tool
def calculate_wire_fee_tool(kind: str, amount: float, from_currency: str, to_currency: str, payer: str) -> str:
"""Calculate wire fee breakdown and who pays (OUR/SHA/BEN). Returns JSON."""
return json.dumps(calculate_wire_fee(kind, amount, from_currency, to_currency, payer))
@tool
def check_wire_limits_tool(account_id: str, amount: float) -> str:
"""Check sufficient funds and daily wire limit on an account. Returns JSON."""
return json.dumps(check_wire_limits(account_id, amount))
@tool
def get_cutoff_and_eta_tool(kind: str, country: str) -> str:
"""Get cutoff time and estimated arrival window by type and country. Returns JSON."""
return json.dumps(get_cutoff_and_eta(kind, country))
@tool
def get_country_requirements_tool(country_code: str) -> str:
"""Get required beneficiary fields for a country. Returns JSON array."""
return json.dumps(get_country_requirements(country_code))
@tool
def validate_beneficiary_tool(country_code: str, beneficiary_json: str) -> str:
"""Validate beneficiary fields for a given country. Input is JSON dict string; returns {ok, missing}."""
try:
beneficiary = json.loads(beneficiary_json)
except Exception:
beneficiary = {}
return json.dumps(validate_beneficiary(country_code, beneficiary))
@tool
def save_beneficiary_tool(customer_id: str, beneficiary_json: str) -> str:
"""Save a beneficiary for future use. Input is JSON dict string; returns {beneficiary_id}."""
try:
beneficiary = json.loads(beneficiary_json)
except Exception:
beneficiary = {}
return json.dumps(save_beneficiary(customer_id, beneficiary))
@tool
def quote_wire_tool(kind: str, from_account_id: str, beneficiary_json: str, amount: float, from_currency: str, to_currency: str, payer: str) -> str:
"""Create a wire quote including FX, fees, limits, sanctions, eta; returns JSON with quote_id and totals."""
try:
beneficiary = json.loads(beneficiary_json)
except Exception:
beneficiary = {}
return json.dumps(quote_wire(kind, from_account_id, beneficiary, amount, from_currency, to_currency, payer))
@tool
def generate_otp_tool(customer_id: str) -> str:
"""Generate a one-time passcode for wire authorization. Returns masked destination info."""
return json.dumps(generate_otp(customer_id))
@tool
def verify_otp_tool(customer_id: str, otp: str) -> str:
"""Verify the one-time passcode for wire authorization. Returns {verified}."""
return json.dumps(verify_otp(customer_id, otp))
@tool
def wire_transfer_domestic(quote_id: str, otp: str) -> str:
"""Execute a domestic wire with a valid quote_id and OTP. Returns confirmation."""
return json.dumps(wire_transfer_domestic_logic(quote_id, otp))
@tool
def wire_transfer_international(quote_id: str, otp: str) -> str:
"""Execute an international wire with a valid quote_id and OTP. Returns confirmation."""
return json.dumps(wire_transfer_international_logic(quote_id, otp))