空运「货交」只记提货地址,不再当成起运地。舱位旧说法「释放」先问航线是否取消,陆运通关口岸示例改为友谊关。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-11 20:45:53 +08:00
co-authored by Cursor
parent b070a9b7a7
commit 185abbf45e
16 changed files with 533 additions and 49 deletions
@@ -53,6 +53,8 @@ from agent.routing.air_group_intent import (
INTENT_PICK_OPTION,
INTENT_QUOTE,
INTENT_RELEASE,
INTENT_RELEASE_ASK,
cabin_confirm_answer,
classify_air_group_text,
)
@@ -167,6 +169,9 @@ def handle_air_group(
return "duplicate_inbound"
mark_air_text(chat_id=chat_id, sender_id=message.sender_id, text=text)
wo = copy.extract_work_order_no(text)
answered = _answer_pending_cabin_cancel(engine, message, text)
if answered:
return answered
# 句中有多段工单号,或本群已经激活过多段单:跟这张单,不必每句再带工单号。
followed = _follow_activated_multi(
engine,
@@ -200,7 +205,7 @@ def handle_air_group(
intent,
wo or "-",
)
if intent in {INTENT_LOCK, INTENT_RELEASE}:
if intent in {INTENT_LOCK, INTENT_RELEASE, INTENT_RELEASE_ASK}:
return _handle_cabin(
engine,
message,
@@ -309,6 +314,92 @@ def _should_speak_activate(intent: str) -> bool:
return intent in {INTENT_ACTIVATE, INTENT_OTHER}
def _answer_pending_cabin_cancel(engine, message: InboundMessage, text: str) -> str:
"""
上一句已经问过是否取消舱位。
航线回是/需要/确认/取消舱位才执行。回否/不用/不需要就停。
销售回这些词不算。说了别的业务就清掉询问,按那句话继续办。
没有待确认时返回空串。
"""
from agent.policy.air_group_ops import is_airline
from agent.redis_coord.pending_cabin_cancel import (
clear_pending_cabin_cancel,
load_pending_cabin_cancel,
)
chat_id = (message.chat_id or "").strip()
pending_wo = load_pending_cabin_cancel(chat_id)
if not pending_wo:
return ""
kind = cabin_confirm_answer(text)
if not kind:
clear_pending_cabin_cancel(chat_id)
logger.info("cabin.ask dropped chat=%s wo=%s", chat_id, pending_wo)
return ""
if not is_airline(engine, message.sender_id):
send_group_text(group_client_of(engine), chat_id, copy.air_airline_only_cabin())
return "not_airline"
clear_pending_cabin_cancel(chat_id)
if kind == "no":
send_group_text(group_client_of(engine), chat_id, copy.air_release_ask_dropped())
return "release_ask_dropped"
ticket, phase = resolve_cabin_ticket(
flow=engine,
chat_id=chat_id,
work_order_no=pending_wo,
allow_terminal=True,
)
if ticket is None:
return phase
return apply_air_release(
flow=engine,
ticket=ticket,
sender_id=message.sender_id,
chat_id=chat_id,
instruction=text,
)
def _ask_cabin_cancel(
engine,
message: InboundMessage,
*,
work_order_no: str,
) -> str:
"""航线说了释放舱位:只提问,不打 TMS。"""
from agent.policy.air_group_ops import is_airline
from agent.redis_coord.pending_cabin_cancel import save_pending_cabin_cancel
chat_id = message.chat_id
if not is_airline(engine, message.sender_id):
send_group_text(group_client_of(engine), chat_id, copy.air_airline_only_cabin())
return "not_airline"
no = (work_order_no or "").strip()
if not no:
bound = current_ticket(engine, chat_id)
if bound is not None and is_air_ticket(bound):
from agent.policy.sea_group_ops import ticket_no
no = ticket_no(bound)
if not no:
send_group_text(group_client_of(engine), chat_id, copy.air_lock_need_work_order())
return "cabin_need_work_order"
ticket, phase = resolve_cabin_ticket(
flow=engine,
chat_id=chat_id,
work_order_no=no,
allow_terminal=True,
)
if ticket is None:
return phase
from agent.policy.sea_group_ops import ticket_no
save_pending_cabin_cancel(chat_id, ticket_no(ticket))
send_group_text(group_client_of(engine), chat_id, copy.air_release_ask())
return "release_ask"
def _handle_cabin(
engine,
message: InboundMessage,
@@ -319,6 +410,12 @@ def _handle_cabin(
) -> str:
_ = injected_quote
chat_id = message.chat_id
if intent == INTENT_RELEASE_ASK:
return _ask_cabin_cancel(
engine,
message,
work_order_no=work_order_no,
)
if not work_order_no:
# 本群已经在锁这张单时,补舱位不用再报工单号。
bound = current_ticket(engine, chat_id)