Enable quote-first Leo Telegram research
This commit is contained in:
parent
19f5346118
commit
9b7feb4278
4 changed files with 66 additions and 2 deletions
|
|
@ -19,6 +19,11 @@ domain_expertise: >
|
|||
|
||||
# ─── Hosted Leo Runtime ──────────────────────────────────────────────────
|
||||
http_chat_proxy_url: "https://leo.livingip.xyz/api/agents/leo/chat"
|
||||
http_research_proxy_url: "https://leo.livingip.xyz/api/agents/leo/research"
|
||||
smart_research_command_prefixes:
|
||||
- "/smart_research"
|
||||
- "/paid_research"
|
||||
auto_smart_research_from_chat: true
|
||||
respond_to_private_chats: true
|
||||
|
||||
# ─── KB Scope ────────────────────────────────────────────────────────────
|
||||
|
|
@ -44,6 +49,10 @@ voice_definition: |
|
|||
answer from retained Living IP runtime evidence and current route state.
|
||||
Do not claim payment execution unless the HTTP route returns retained
|
||||
payment/readback evidence.
|
||||
When addressed or used in private chat, clear requests for fresh sourced
|
||||
research should go through Leo's hosted research route. First return a paid
|
||||
research quote and checkout link. Only resume paid execution after a
|
||||
work_order_id or payment receipt is present.
|
||||
|
||||
# ─── Learnings ───────────────────────────────────────────────────────────
|
||||
learnings_file: agents/leo/learnings.md
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ from http_chat_proxy import (
|
|||
extract_smart_research_goal,
|
||||
post_chat_proxy,
|
||||
should_attach_structured_market_context,
|
||||
smart_research_payment_fields_for_message,
|
||||
smart_research_command_names,
|
||||
)
|
||||
|
||||
|
|
@ -1128,6 +1129,10 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
if len(text) < MIN_MESSAGE_LENGTH:
|
||||
return
|
||||
|
||||
if AGENT_HTTP_RESEARCH_PROXY_URL and extract_paid_work_order_id(text):
|
||||
await handle_tagged(update, context)
|
||||
return
|
||||
|
||||
# Conversation window behavior depends on chat type (Rio: DMs vs groups)
|
||||
# DMs: auto-respond (always 1-on-1, no false positives)
|
||||
# Groups: silent context only (reply-to is the only follow-up trigger)
|
||||
|
|
@ -1207,7 +1212,10 @@ async def handle_tagged(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
tuple(AGENT_MENTION_ALIASES),
|
||||
)
|
||||
if AGENT_HTTP_RESEARCH_PROXY_URL and smart_research_goal:
|
||||
payment_gate = _smart_research_payment_gate(msg.chat_id)
|
||||
payment_gate = smart_research_payment_fields_for_message(
|
||||
paid_work_order_id=paid_work_order_id,
|
||||
configured_payment_gate=_smart_research_payment_gate(msg.chat_id),
|
||||
)
|
||||
proxy_research_goal = smart_research_goal
|
||||
if should_attach_structured_market_context(smart_research_goal):
|
||||
market_context, market_data_audit, market_duration, market_tokens = await _market_context_for_message(
|
||||
|
|
|
|||
|
|
@ -184,6 +184,19 @@ def should_attach_structured_market_context(message: str) -> bool:
|
|||
return bool(_MARKET_CONTEXT_RE.search(text))
|
||||
|
||||
|
||||
def smart_research_payment_fields_for_message(
|
||||
*,
|
||||
paid_work_order_id: str | None,
|
||||
configured_payment_gate: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Return paid-execution fields only for a settled work-order resume message."""
|
||||
if not paid_work_order_id:
|
||||
return {"allow_paid_execution": False}
|
||||
if configured_payment_gate.get("allow_paid_execution") is True:
|
||||
return configured_payment_gate
|
||||
return {"allow_paid_execution": False}
|
||||
|
||||
|
||||
def build_smart_research_proxy_payload(
|
||||
*,
|
||||
research_goal: str,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from http_chat_proxy import ( # noqa: E402
|
|||
extract_chat_proxy_reply,
|
||||
extract_smart_research_goal,
|
||||
should_attach_structured_market_context,
|
||||
smart_research_payment_fields_for_message,
|
||||
smart_research_command_names,
|
||||
)
|
||||
from market_data import extract_market_data_tokens, format_price_context # noqa: E402
|
||||
|
|
@ -31,6 +32,9 @@ def test_leo_config_opts_into_http_chat_proxy_without_changing_default_agents():
|
|||
|
||||
assert leo.name == "Leo"
|
||||
assert leo.http_chat_proxy_url == "https://leo.livingip.xyz/api/agents/leo/chat"
|
||||
assert leo.http_research_proxy_url == "https://leo.livingip.xyz/api/agents/leo/research"
|
||||
assert "/smart_research" in leo.smart_research_command_prefixes
|
||||
assert leo.auto_smart_research_from_chat is True
|
||||
assert leo.respond_to_private_chats is True
|
||||
assert "@teLEOhuman" in leo.mention_aliases
|
||||
assert leo_wallet_test.name == "Leo Wallet Test"
|
||||
|
|
@ -43,7 +47,6 @@ def test_leo_config_opts_into_http_chat_proxy_without_changing_default_agents():
|
|||
assert "@lipleowallet0622183538bot" in leo_wallet_test.mention_aliases
|
||||
assert rio.http_chat_proxy_url is None
|
||||
assert rio.respond_to_private_chats is False
|
||||
assert leo.auto_smart_research_from_chat is False
|
||||
|
||||
|
||||
def test_invalid_http_chat_proxy_url_fails_closed(tmp_path):
|
||||
|
|
@ -135,6 +138,37 @@ def test_smart_research_payload_can_resume_paid_work_order_without_secret_materi
|
|||
assert "secret" not in str(payload).lower()
|
||||
|
||||
|
||||
def test_smart_research_payment_fields_quote_first_even_when_gate_enabled():
|
||||
configured_gate = {
|
||||
"allow_paid_execution": True,
|
||||
"approval_ref": "approval_ref_livingip_x402_20260622",
|
||||
"max_amount_usd": 0.01,
|
||||
}
|
||||
|
||||
payment_fields = smart_research_payment_fields_for_message(
|
||||
paid_work_order_id=None,
|
||||
configured_payment_gate=configured_gate,
|
||||
)
|
||||
|
||||
assert payment_fields == {"allow_paid_execution": False}
|
||||
assert "approval_ref" not in payment_fields
|
||||
|
||||
|
||||
def test_smart_research_payment_fields_resume_uses_capped_gate():
|
||||
configured_gate = {
|
||||
"allow_paid_execution": True,
|
||||
"approval_ref": "approval_ref_livingip_x402_20260622",
|
||||
"max_amount_usd": 0.01,
|
||||
}
|
||||
|
||||
payment_fields = smart_research_payment_fields_for_message(
|
||||
paid_work_order_id="sponsored_work_orders:f951ccc6c7762ecba6f76cf6",
|
||||
configured_payment_gate=configured_gate,
|
||||
)
|
||||
|
||||
assert payment_fields == configured_gate
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("message", "expected"),
|
||||
[
|
||||
|
|
|
|||
Loading…
Reference in a new issue