Files

73 lines
2.9 KiB
Python

# -*- coding: utf-8 -*-
"""Unified result object returned by all channel adapters."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
@dataclass
class UnifiedResult:
"""A platform-agnostic representation of a fetch outcome.
``status`` semantics:
success - data fetched, ``data`` is populated
cache_hit - served from local LRU cache
rate_limited - tenant or platform quota exhausted
breaker_open - circuit breaker tripped
error - platform errored, ``error`` populated
timeout - exceeded per-call timeout
no_creds - tenant has not authorised this channel
"""
status: str
data: dict | list | None = None
error: str | None = None
latency_ms: int = 0
channel: str = ""
raw: dict | None = field(default=None, repr=False)
@property
def ok(self) -> bool:
return self.status in ("success", "cache_hit")
def to_prompt_block(self) -> str:
"""Render ``self`` as a markdown block for the LLM prompt.
Returns a short failure hint on platform errors so the LLM does not
hallucinate prices/stock. Returns empty on ``no_creds`` (silent skip).
"""
if self.status == "no_creds":
return ""
if not self.ok or not self.data:
if self.status == "rate_limited":
return "📦 实时商品数据: 触发限流,请稍后重试"
if self.status == "breaker_open":
return "📦 实时商品数据: 平台服务暂时不可用(熔断)"
if self.status == "timeout":
return "📦 实时商品数据: 请求超时,已跳过"
return "📦 实时商品数据: 平台 API 暂不可用,请基于现有知识谨慎回答(不要编造价格/库存)"
lines = ["📦 实时商品信息:"]
# data shape (per channel): {"title": ..., "price": ..., "currency": ..., "url": ..., "in_stock": ...}
d = self.data
if isinstance(d, dict):
if d.get("title"):
lines.append(f" - 商品: {d['title']}")
if d.get("price") is not None:
cur = d.get("currency", "")
lines.append(f" - 价格: {cur} {d['price']}".strip())
if d.get("in_stock") is not None:
lines.append(f" - 库存: {'有' if d['in_stock'] else '无'}")
if d.get("url"):
lines.append(f" - 链接: {d['url']}")
elif isinstance(d, list):
for i, item in enumerate(d[:3], 1):
if not isinstance(item, dict):
continue
title = item.get("title", "(无标题)")
price = item.get("price")
cur = item.get("currency", "")
lines.append(f" {i}. {title}{cur} {price}".strip())
return "\n".join(lines)