机器人显示名与站点标题可配;多段联运列表投影;协同群监听对账;工单附件落存;模板与工单后台补强
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
意图:询价卡片按钮(复制工单号 / 拉产品进群 / 跳过协同 / 采用 / 不采用 / 成交)。
|
||||
|
||||
本文件职责:校验当前会话允许的动作后交给流程执行。
|
||||
本文件职责:校验当前会话允许的动作后交给流程执行;卡片按钮集中防抖入口。
|
||||
禁止:不校验 wait/允许集合就改主账;禁止一个函数处理未声明的新按钮。
|
||||
"""
|
||||
|
||||
@@ -15,6 +15,7 @@ from agent.policy import inquiry_copy as copy
|
||||
from agent.policy.air_text_flow import get_air_text_flow
|
||||
from agent.policy.land_text_flow import get_land_text_flow
|
||||
from agent.policy.sea_text_flow import get_sea_text_flow
|
||||
from agent.redis_coord.card_debounce import debounce_key, try_acquire as try_card_debounce
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -57,6 +58,7 @@ def handle_card_action(
|
||||
|
||||
wait_version:会话书签版本;错版本丢弃,不重放副作用。
|
||||
payload 须带 task_id / event_key,才能找回点卡当时的工单。
|
||||
连点:同一 task_id+按钮在防抖 TTL 内只跑一次业务,避免多条智能体提示。
|
||||
"""
|
||||
_ = thread_id
|
||||
if not (sender_id or "").strip():
|
||||
@@ -68,6 +70,41 @@ def handle_card_action(
|
||||
return "card_discard"
|
||||
|
||||
msg_store = store or get_message_store()
|
||||
wo_hint = ""
|
||||
if sess is not None:
|
||||
wo_hint = (sess.work_order_no or "").strip()
|
||||
if not wo_hint:
|
||||
wo_hint = copy.work_order_from_card_meta(payload)
|
||||
# 集中防抖:键用 task_id+动作,不用 ResponseCode(企微每次点击换新码)
|
||||
dkey = debounce_key(
|
||||
action=action,
|
||||
task_id=str((payload or {}).get("task_id") or ""),
|
||||
work_order_no=wo_hint,
|
||||
sender_id=sender_id,
|
||||
event_key=str((payload or {}).get("event_key") or ""),
|
||||
)
|
||||
if not try_card_debounce(dkey):
|
||||
logger.info(
|
||||
"card 防抖丢弃 sender=%s action=%s key=%s",
|
||||
sender_id,
|
||||
action,
|
||||
dkey,
|
||||
)
|
||||
# 仍用新 ResponseCode 置灰,避免企微按钮一直可点;不发业务 ack
|
||||
code = str((payload or {}).get("response_code") or "").strip()
|
||||
if code:
|
||||
msg_store.enqueue_outbound(
|
||||
touser=sender_id,
|
||||
content=copy.BTN_SKIP_COLLAB_DONE,
|
||||
dedupe_key=f"card-grey:{sender_id}:{wo_hint}:{code}",
|
||||
payload=copy.skip_collab_card_update(
|
||||
response_code=code,
|
||||
replace_name=action if action in {
|
||||
copy.BTN_DEAL, copy.BTN_LOST, copy.BTN_NEGOTIATE
|
||||
} else "",
|
||||
),
|
||||
)
|
||||
return "card_debounced"
|
||||
|
||||
def reply(text: str, extra: dict | None = None) -> str:
|
||||
# 销售询价正文不加 [test];[test] 只给运维告警
|
||||
@@ -79,13 +116,16 @@ def handle_card_action(
|
||||
if not wo:
|
||||
wo = copy.work_order_from_card_meta(payload)
|
||||
code = str((payload or {}).get("response_code") or extra.get("response_code") or "")[:24]
|
||||
msgtype = str(extra.get("msgtype") or "text")
|
||||
# 文本 ack 按工单+动作去重;置灰更新仍带 code(每次 ResponseCode 只能用一次)
|
||||
if msgtype == "update_template_card":
|
||||
dedupe_key = f"card-grey:{sender_id}:{wo}:{code}:{action}"
|
||||
else:
|
||||
dedupe_key = f"card-ack:{sender_id}:{wo}:{action}:{body[:24]}"
|
||||
ok, info = msg_store.enqueue_outbound(
|
||||
touser=sender_id,
|
||||
content=body,
|
||||
dedupe_key=(
|
||||
f"card:{sender_id}:{wo}:{code}:"
|
||||
f"{sess.wait_version if sess else 0}:{action}:{body[:20]}"
|
||||
),
|
||||
dedupe_key=dedupe_key,
|
||||
payload=extra,
|
||||
)
|
||||
if not ok:
|
||||
|
||||
Reference in New Issue
Block a user