Allow drivers to publish trips in their own style; add reply_instruction for no-match results; improve privacy prompts
Browse files- Update driver_message handling: use when driver provides a custom ad (not just >2 emojis)
- Add reply_instruction to about_falzh, search_trips, create_driver_account, add_trip_by_driver tools for better AI response control
- Add _no_trip_reply_instruction helper to prevent narrow retries or false promises
- Update Arabic prompts: driver style flexibility, phone number privacy, FAQ improvements
- Update system prompts to direct unsure feature queries to about_falzh
- Add/update tests for new behaviors
- app/ai/tool_schemas.py +6 -4
- app/services/conversation_service.py +4 -0
- app/tools/handlers.py +35 -2
- prompts/falzh_info.md +5 -4
- prompts/system.md +4 -1
- prompts/system_driver.md +7 -1
- prompts/system_new_user.md +1 -1
- prompts/system_passenger.md +1 -0
- tests/test_conversation_service.py +2 -1
- tests/test_tools.py +69 -0
app/ai/tool_schemas.py
CHANGED
|
@@ -7,7 +7,8 @@ _ABOUT_FALZH = {
|
|
| 7 |
"function": {
|
| 8 |
"name": "about_falzh",
|
| 9 |
"description": (
|
| 10 |
-
"Retrieve official FALZH company, FAQ, policy, or
|
|
|
|
| 11 |
),
|
| 12 |
"parameters": {
|
| 13 |
"type": "object",
|
|
@@ -246,9 +247,10 @@ _ADD_TRIP_BY_DRIVER = {
|
|
| 246 |
"driver_message": {
|
| 247 |
"type": "string",
|
| 248 |
"description": (
|
| 249 |
-
"Optional cleaned version of the driver's original
|
| 250 |
-
"
|
| 251 |
-
"
|
|
|
|
| 252 |
),
|
| 253 |
},
|
| 254 |
},
|
|
|
|
| 7 |
"function": {
|
| 8 |
"name": "about_falzh",
|
| 9 |
"description": (
|
| 10 |
+
"Retrieve official FALZH company, FAQ, policy, pricing, or feature information. "
|
| 11 |
+
"Use before answering any FALZH capability/request you are unsure about."
|
| 12 |
),
|
| 13 |
"parameters": {
|
| 14 |
"type": "object",
|
|
|
|
| 247 |
"driver_message": {
|
| 248 |
"type": "string",
|
| 249 |
"description": (
|
| 250 |
+
"Optional cleaned version of the driver's original trip ad when the "
|
| 251 |
+
"driver wrote it in a style likely meant for passengers. Remove phone "
|
| 252 |
+
"numbers, personal info, and driver name. Keep route info, dates, "
|
| 253 |
+
"times, emojis, and decorations."
|
| 254 |
),
|
| 255 |
},
|
| 256 |
},
|
app/services/conversation_service.py
CHANGED
|
@@ -205,6 +205,10 @@ class ConversationService:
|
|
| 205 |
"in the groups and we are impressed. Explain that we have registered them in "
|
| 206 |
"FALZH so they can now send trips directly here instead of posting in groups. "
|
| 207 |
"Show them how: just send the trip details (route, date, time) in chat. "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
"Explain the benefits: passengers find their trips via AI search, they get "
|
| 209 |
"notified immediately when a passenger selects their trip, and registered "
|
| 210 |
"drivers get priority visibility in search results. Tell them we will no "
|
|
|
|
| 205 |
"in the groups and we are impressed. Explain that we have registered them in "
|
| 206 |
"FALZH so they can now send trips directly here instead of posting in groups. "
|
| 207 |
"Show them how: just send the trip details (route, date, time) in chat. "
|
| 208 |
+
"Tell them they may write each trip ad in their own preferred style/format, "
|
| 209 |
+
"and FALZH will extract the trip details automatically. Tell them personal "
|
| 210 |
+
"data such as phone numbers will be removed from public trip ads/cards and "
|
| 211 |
+
"shared only after a passenger selects the trip and wants to contact them. "
|
| 212 |
"Explain the benefits: passengers find their trips via AI search, they get "
|
| 213 |
"notified immediately when a passenger selects their trip, and registered "
|
| 214 |
"drivers get priority visibility in search results. Tell them we will no "
|
app/tools/handlers.py
CHANGED
|
@@ -76,6 +76,9 @@ class FalzhToolHandlers:
|
|
| 76 |
data={
|
| 77 |
"answer": "No matching FALZH policy or FAQ content was found.",
|
| 78 |
"sources": [],
|
|
|
|
|
|
|
|
|
|
| 79 |
},
|
| 80 |
)
|
| 81 |
|
|
@@ -91,6 +94,10 @@ class FalzhToolHandlers:
|
|
| 91 |
}
|
| 92 |
for match in matches
|
| 93 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
},
|
| 95 |
)
|
| 96 |
|
|
@@ -228,6 +235,7 @@ class FalzhToolHandlers:
|
|
| 228 |
"alternate_alert": alternate_alert,
|
| 229 |
"sent_as_messages": False,
|
| 230 |
"note": "No active matching trips were found.",
|
|
|
|
| 231 |
},
|
| 232 |
)
|
| 233 |
|
|
@@ -338,6 +346,13 @@ class FalzhToolHandlers:
|
|
| 338 |
"name": self.customer.get("name"),
|
| 339 |
"remoteJid": self.customer.get("remoteJid"),
|
| 340 |
"message": "Driver account created successfully.",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
},
|
| 342 |
)
|
| 343 |
|
|
@@ -592,8 +607,8 @@ class FalzhToolHandlers:
|
|
| 592 |
use_driver_message = False
|
| 593 |
if self.current_message:
|
| 594 |
raw_msg = self.current_message.get("message") or ""
|
| 595 |
-
|
| 596 |
-
|
| 597 |
driver_message = llm_message or raw_msg
|
| 598 |
use_driver_message = True
|
| 599 |
|
|
@@ -1063,6 +1078,24 @@ def _alternate_time_alert(trips: list[dict[str, Any]]) -> str | None:
|
|
| 1063 |
)
|
| 1064 |
|
| 1065 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1066 |
def _trip_search_note(alternate_alert: str | None) -> str:
|
| 1067 |
if alternate_alert:
|
| 1068 |
return alternate_alert
|
|
|
|
| 76 |
data={
|
| 77 |
"answer": "No matching FALZH policy or FAQ content was found.",
|
| 78 |
"sources": [],
|
| 79 |
+
"reply_instruction": (
|
| 80 |
+
"Apologize briefly. Do not guess or invent an answer."
|
| 81 |
+
),
|
| 82 |
},
|
| 83 |
)
|
| 84 |
|
|
|
|
| 94 |
}
|
| 95 |
for match in matches
|
| 96 |
],
|
| 97 |
+
"reply_instruction": (
|
| 98 |
+
"Answer only from this context. If it does not clearly answer the user's "
|
| 99 |
+
"question, apologize briefly and say there is no confirmed information."
|
| 100 |
+
),
|
| 101 |
},
|
| 102 |
)
|
| 103 |
|
|
|
|
| 235 |
"alternate_alert": alternate_alert,
|
| 236 |
"sent_as_messages": False,
|
| 237 |
"note": "No active matching trips were found.",
|
| 238 |
+
"reply_instruction": _no_trip_reply_instruction(departure_request),
|
| 239 |
},
|
| 240 |
)
|
| 241 |
|
|
|
|
| 346 |
"name": self.customer.get("name"),
|
| 347 |
"remoteJid": self.customer.get("remoteJid"),
|
| 348 |
"message": "Driver account created successfully.",
|
| 349 |
+
"reply_instruction": (
|
| 350 |
+
"Tell the driver in Arabic that they can publish each trip in their own "
|
| 351 |
+
"format/style and FALZH will extract the trip details automatically. Also "
|
| 352 |
+
"tell them personal data such as phone numbers will be removed from trip "
|
| 353 |
+
"ads/cards and shared with passengers only after a passenger selects the "
|
| 354 |
+
"trip and wants to contact them."
|
| 355 |
+
),
|
| 356 |
},
|
| 357 |
)
|
| 358 |
|
|
|
|
| 607 |
use_driver_message = False
|
| 608 |
if self.current_message:
|
| 609 |
raw_msg = self.current_message.get("message") or ""
|
| 610 |
+
llm_message = _optional_string(arguments.get("driver_message"))
|
| 611 |
+
if llm_message or count_emojis(raw_msg) > 2:
|
| 612 |
driver_message = llm_message or raw_msg
|
| 613 |
use_driver_message = True
|
| 614 |
|
|
|
|
| 1078 |
)
|
| 1079 |
|
| 1080 |
|
| 1081 |
+
def _no_trip_reply_instruction(departure_request: Any) -> str:
|
| 1082 |
+
instruction = (
|
| 1083 |
+
"Tell the passenger briefly that no active matching trip is currently available. "
|
| 1084 |
+
"Do not promise to notify them when a future matching trip is added."
|
| 1085 |
+
)
|
| 1086 |
+
if departure_request.departure_date or departure_request.departure_time:
|
| 1087 |
+
instruction += (
|
| 1088 |
+
" Do not call search_trips again with a narrower/specific time for the same "
|
| 1089 |
+
"route unless the passenger provides new route/date information."
|
| 1090 |
+
)
|
| 1091 |
+
else:
|
| 1092 |
+
instruction += (
|
| 1093 |
+
" This was already a general search for the provided trip details; do not call "
|
| 1094 |
+
"search_trips again only to add a specific time for the same trip."
|
| 1095 |
+
)
|
| 1096 |
+
return instruction
|
| 1097 |
+
|
| 1098 |
+
|
| 1099 |
def _trip_search_note(alternate_alert: str | None) -> str:
|
| 1100 |
if alternate_alert:
|
| 1101 |
return alternate_alert
|
prompts/falzh_info.md
CHANGED
|
@@ -24,13 +24,13 @@
|
|
| 24 |
ุงูุณุนุฑ ุชุญุฏุฏู ุดุฑูุฉ ุงูุณุงุฆู ุฃู ุงูุณุงุฆู ููุณู. ููุฒุฉ ููุท ุชุนุฑุถ ุงูุณุนุฑ ุงููู ุฃุฏุฎูู ุงูุณุงุฆู ุนูุฏ ูุดุฑ ุงูุฑุญูุฉ. ููุฒุฉ ูุง ุชุญุฏุฏ ุงูุฃุณุนุงุฑ ููุง ุชุชุนุงู
ู ูู ุงูู
ุฏููุนุงุช. ุฅุฐุง ูุงู ุงูุณุนุฑ ู
ู ู
ุญุฏุฏ ูู ุงูุฑุญูุฉุ ุงุณุฃู ุงูุณุงุฆู ู
ุจุงุดุฑุฉ.
|
| 25 |
|
| 26 |
## ุฎุฏู
ุงุช ุงูุณุงุฆููู
|
| 27 |
-
ุชุณุฌูู ุญุณุงุจ ุณุงุฆู: ูุญุชุงุฌ ุงูุงุณู
ุงููุงู
ู. ุชุฑุจุท ููุฒุฉ ุญุณุงุจู ุจุฑูู
ูุงุชุณุงุจู. ุฅุถุงูุฉ ู
ุฑูุจุฉ: ุงุณู
ุงูู
ุฑูุจุฉ ู
ุทููุจุ ุฑูู
ุงูููุญุฉ ูุนุฏุฏ ุงูู
ูุงุนุฏ ุงุฎุชูุงุฑู. ูุดุฑ ุฑุญูุฉ: ููุฒู
ุงูู
ุฏููุฉ (ู
ู ูุฅูู)ุ ุงูุชุงุฑูุฎุ ุงููุชุฑุฉ (ุตุจุงุญ/ุธูุฑ/ููู). ุนุฏุฏ ุงูู
ูุงุนุฏ ูุงูุณุนุฑ ุชูู
ูุฃ ุชููุงุฆูุงู ู
ู ุขุฎุฑ ุฑุญูุฉ ุฃู ู
ุฑูุจุชู ุงูู
ุณุฌูุฉ. ุชุนุฏูู ุฑุญูุฉ: ุชูุฏุฑ ุชุบูุฑ ุงููุฌูุฉุ ุงูููุชุ ุงูุณูุงุฑุฉุ ุงูู
ูุงุนุฏุ ุฃู ุงูุณุนุฑ. ุชุงุฑูุฎ ุงูุฑุญูุฉ ูุง ูู
ูู ุชุบููุฑู โ ูุงุฒู
ุชูุดุฆ ุฑุญูุฉ ุฌุฏูุฏุฉ. ุญุฐู ุฑุญูุฉ: ุชูุบู ุงูุฑุญูุฉ ูุชุฑูุนูุง ู
ู ุงูุจุญุซ. ู
ู
ููุน ูููู ุนูุฏู ุฑุญูุชูู ูู ููุณ ุงูุชุงุฑูุฎ ูุงููุชุฑุฉ.
|
| 28 |
|
| 29 |
## ุงูุณูุงุณุงุช
|
| 30 |
ููุฒุฉ ูุง ุชุญุฌุฒ ุฑุญูุงุช ููุง ุชุคูุฏ ุญุฌูุฒุงุช. ุงุฎุชูุงุฑ ุงูุฑุญูุฉ ูุนูู ุชุณุฌูู ุงูุชู
ุงู
ููุท. ููุฒุฉ ูุง ุชุชุนุงู
ู ูู ุงูู
ุฏููุนุงุช ููุงุฆูุงู. ุงูู
ุณุงูุฑ ูุชุญู
ู ู
ุณุคูููุฉ ุชูุฏูู
ู
ุนููู
ุงุช ุตุญูุญุฉ ุนู ูุฌูุชู ูููุชู ูุนุฏุฏ ุงูู
ูุงุนุฏ. ููุฒุฉ ููุท ุชูุฏู
ู
ุนููู
ุงุช ุนู ุฎุฏู
ุงุชูุง โ ุชุฑูุถ ุงูุฅุฌุงุจุฉ ุนู ุฃู ู
ูุถูุน ุฎุงุฑุฌ ุงูุณูุฑ.
|
| 31 |
|
| 32 |
## ุงูุฎุตูุตูุฉ
|
| 33 |
-
ุฑูู
ูุงุชุณุงุจู ููุณุชุฎุฏู
ููุท ูุฑุจุท ุญุณุงุจู ูุฅุฑุณุงู ุงูุฅุดุนุงุฑุงุช. ุฑูู
ูุงุชูู ููุดุงุฑู ู
ุน ุงูุณุงุฆู ููุท ุนูุฏู
ุง
|
| 34 |
|
| 35 |
## ุงูุฃุณุฆูุฉ ุงูุดุงุฆุนุฉ
|
| 36 |
ุณ: ูุด ูู ููุฒุฉุ ุฌ: ุฎุฏู
ุฉ ุณูุฑ ุนูู ูุงุชุณุงุจ. ุชูุฏุฑ ุชุจุญุซ ุนู ุฑุญูุงุช ุณูุงุฑุงุช ูุจุงุตุงุช ูุชุฎุชุงุฑ ุฑุญูุฉ ูุชุชูุงุตู ู
ุน ุงูุณุงุฆู โ ูู ุดูุก ุฏุงุฎู ูุงุชุณุงุจ.
|
|
@@ -42,10 +42,11 @@
|
|
| 42 |
ุณ: ูู ุฃูุฏุฑ ุฃูุบู ุงุฎุชูุงุฑูุ ุฌ: ุงุฎุชูุงุฑ ุงูุฑุญูุฉ ูู ุฅุฑุณุงู ุงูุชู
ุงู
ููุท ููุง ููุฌุฏ ุฅูุบุงุก ู
ู ุงููุธุงู
. ุฅุฐุง ุชุบูุฑ ุฑุฃููุ ุชูุงุตู ู
ุน ุงูุณุงุฆู ู
ุจุงุดุฑุฉ.
|
| 43 |
ุณ: ููู ุฃุณุฌู ูุณุงุฆูุ ุฌ: ููู "ุฃุจู ุฃุณุฌู ูุณุงุฆู" ุฃู ุงุฎุชุฑ ูุถุน ุงูุณุงุฆู. ูุญุชุงุฌ ุงูุงุณู
ุงููุงู
ู.
|
| 44 |
ุณ: ููู ุฃุจุญุซ ุนู ุฑุญูุฉ ูุณุงุฆู ู
ุนููุ ุฌ: ููู "ุฃุจู ุฑุญูุงุช ุงูุณุงุฆู ุฃุญู
ุฏ" ุฃู "ุฏูุฑ ุฑุญูุฉ ู
ุน ุงูุณุงุฆู". ููุฒุฉ ุชุจุญุซ ูู ุงูุฑุญูุงุช ุงูู
ุชุงุญุฉ ููุงูุณุงุฆู ูุชุฑุณู ูู ุงููุชุงุฆุฌ.
|
| 45 |
-
ุณ:
|
|
|
|
| 46 |
ุณ: ููู ุฃุนุฏู ุฃู ุฃูุบู ุฑุญูุฉุ ุฌ: ููู "ุฃุจู ุฃุนุฏู ุฑุญูุฉ" ุฃู "ุฃุจู ุฃูุบู ุฑุญูุฉ". ููุฒุฉ ุชุฑุณู ูู ูุงุฆู
ุฉ ุฑุญูุงุชู โ ุชุฑุฏ ุนูู ุงููู ุชุจูู.
|
| 47 |
ุณ: ูู ููู ุฑุญูุงุช ุจูู ูู ุงูู
ุฏูุ ุฌ: ููุฒุฉ ุชุนุฑุถ ุงูุฑุญูุงุช ุงููู ููุดุฑูุง ุงูุณุงุฆููู. ุฅุฐุง ู
ุง ูููุช ุฑุญูุชูุ ุงุณุฃู ู
ุฑุฉ ุซุงููุฉ ุฃู ุชูุงุตู ู
ุน ุงูุฏุนู
.
|
| 48 |
ุณ: ูู ุงูุฎุฏู
ุฉ ู
ุฌุงููุฉุ ุฌ: ุงุณุชุฎุฏุงู
ููุฒุฉ ู
ุฌุงูู. ุงูุณุนุฑ ููุณูุฑ ุชุชูู ููู ู
ุน ุงูุณุงุฆู.
|
| 49 |
|
| 50 |
## ุงูุฏุนู
ุงูููู
|
| 51 |
-
ุฅุฐุง ู
ุง ููู ุงูู
ุณุงุนุฏ
|
|
|
|
| 24 |
ุงูุณุนุฑ ุชุญุฏุฏู ุดุฑูุฉ ุงูุณุงุฆู ุฃู ุงูุณุงุฆู ููุณู. ููุฒุฉ ููุท ุชุนุฑุถ ุงูุณุนุฑ ุงููู ุฃุฏุฎูู ุงูุณุงุฆู ุนูุฏ ูุดุฑ ุงูุฑุญูุฉ. ููุฒุฉ ูุง ุชุญุฏุฏ ุงูุฃุณุนุงุฑ ููุง ุชุชุนุงู
ู ูู ุงูู
ุฏููุนุงุช. ุฅุฐุง ูุงู ุงูุณุนุฑ ู
ู ู
ุญุฏุฏ ูู ุงูุฑุญูุฉุ ุงุณุฃู ุงูุณุงุฆู ู
ุจุงุดุฑุฉ.
|
| 25 |
|
| 26 |
## ุฎุฏู
ุงุช ุงูุณุงุฆููู
|
| 27 |
+
ุชุณุฌูู ุญุณุงุจ ุณุงุฆู: ูุญุชุงุฌ ุงูุงุณู
ุงููุงู
ู. ุชุฑุจุท ููุฒุฉ ุญุณุงุจู ุจุฑูู
ูุงุชุณุงุจู. ุฅุถุงูุฉ ู
ุฑูุจุฉ: ุงุณู
ุงูู
ุฑูุจุฉ ู
ุทููุจุ ุฑูู
ุงูููุญุฉ ูุนุฏุฏ ุงูู
ูุงุนุฏ ุงุฎุชูุงุฑู. ูุดุฑ ุฑุญูุฉ: ููุฒู
ุงูู
ุฏููุฉ (ู
ู ูุฅูู)ุ ุงูุชุงุฑูุฎุ ุงููุชุฑุฉ (ุตุจุงุญ/ุธูุฑ/ููู). ููุฏุฑ ุงูุณุงุฆู ููุชุจ ุฅุนูุงู ุงูุฑุญูุฉ ุจุตูุบุชู ุงูุฎุงุตุฉ ูุจุฃุณููุจู ุงูู
ุนุชุงุฏุ ูููุฒุฉ ุชุณุชุฎุฑุฌ ุชูุงุตูู ุงูุฑุญูุฉ ุชููุงุฆูุงู. ุนุฏุฏ ุงูู
ูุงุนุฏ ูุงูุณุนุฑ ุชูู
ูุฃ ุชููุงุฆูุงู ู
ู ุขุฎุฑ ุฑุญูุฉ ุฃู ู
ุฑูุจุชู ุงูู
ุณุฌูุฉ. ุชุนุฏูู ุฑุญูุฉ: ุชูุฏุฑ ุชุบูุฑ ุงููุฌูุฉุ ุงูููุชุ ุงูุณูุงุฑุฉุ ุงูู
ูุงุนุฏุ ุฃู ุงูุณุนุฑ. ุชุงุฑูุฎ ุงูุฑุญูุฉ ูุง ูู
ูู ุชุบููุฑู โ ูุงุฒู
ุชูุดุฆ ุฑุญูุฉ ุฌุฏูุฏุฉ. ุญุฐู ุฑุญูุฉ: ุชูุบู ุงูุฑุญูุฉ ูุชุฑูุนูุง ู
ู ุงูุจุญุซ. ู
ู
ููุน ูููู ุนูุฏู ุฑุญูุชูู ูู ููุณ ุงูุชุงุฑูุฎ ูุงููุชุฑุฉ.
|
| 28 |
|
| 29 |
## ุงูุณูุงุณุงุช
|
| 30 |
ููุฒุฉ ูุง ุชุญุฌุฒ ุฑุญูุงุช ููุง ุชุคูุฏ ุญุฌูุฒุงุช. ุงุฎุชูุงุฑ ุงูุฑุญูุฉ ูุนูู ุชุณุฌูู ุงูุชู
ุงู
ููุท. ููุฒุฉ ูุง ุชุชุนุงู
ู ูู ุงูู
ุฏููุนุงุช ููุงุฆูุงู. ุงูู
ุณุงูุฑ ูุชุญู
ู ู
ุณุคูููุฉ ุชูุฏูู
ู
ุนููู
ุงุช ุตุญูุญุฉ ุนู ูุฌูุชู ูููุชู ูุนุฏุฏ ุงูู
ูุงุนุฏ. ููุฒุฉ ููุท ุชูุฏู
ู
ุนููู
ุงุช ุนู ุฎุฏู
ุงุชูุง โ ุชุฑูุถ ุงูุฅุฌุงุจุฉ ุนู ุฃู ู
ูุถูุน ุฎุงุฑุฌ ุงูุณูุฑ.
|
| 31 |
|
| 32 |
## ุงูุฎุตูุตูุฉ
|
| 33 |
+
ุฑูู
ูุงุชุณุงุจู ููุณุชุฎุฏู
ููุท ูุฑุจุท ุญุณุงุจู ูุฅุฑุณุงู ุงูุฅุดุนุงุฑุงุช. ุฑูู
ูุงุชู ุงูุฑุงูุจ ููุดุงุฑู ู
ุน ุงูุณุงุฆู ููุท ุนูุฏู
ุง ูุฎุชุงุฑ ุฑุญูุฉุ ุนุดุงู ูุชูุงุตู ู
ุนู. ุจูุงูุงุช ุงูุณุงุฆู ุงูุดุฎุตูุฉ ู
ุซู ุฑูู
ุงููุงุชู ุชูุฒุงู ู
ู ุฅุนูุงู ุงูุฑุญูุฉ ูุจุทุงูุงุช ุงูุนุฑุถุ ููุง ุชุธูุฑ ููุฑุงูุจ ุฅูุง ุจุนุฏ ุฃู ูุฎุชุงุฑ ุงูุฑุญูุฉ ููุฑูุฏ ุงูุชูุงุตู ู
ุน ุงูุณุงุฆู. ููุฒุฉ ูุง ุชุดุงุฑู ู
ุนููู
ุงุชู ู
ุน ุฃู ุทุฑู ุขุฎุฑ.
|
| 34 |
|
| 35 |
## ุงูุฃุณุฆูุฉ ุงูุดุงุฆุนุฉ
|
| 36 |
ุณ: ูุด ูู ููุฒุฉุ ุฌ: ุฎุฏู
ุฉ ุณูุฑ ุนูู ูุงุชุณุงุจ. ุชูุฏุฑ ุชุจุญุซ ุนู ุฑุญูุงุช ุณูุงุฑุงุช ูุจุงุตุงุช ูุชุฎุชุงุฑ ุฑุญูุฉ ูุชุชูุงุตู ู
ุน ุงูุณุงุฆู โ ูู ุดูุก ุฏุงุฎู ูุงุชุณุงุจ.
|
|
|
|
| 42 |
ุณ: ูู ุฃูุฏุฑ ุฃูุบู ุงุฎุชูุงุฑูุ ุฌ: ุงุฎุชูุงุฑ ุงูุฑุญูุฉ ูู ุฅุฑุณุงู ุงูุชู
ุงู
ููุท ููุง ููุฌุฏ ุฅูุบุงุก ู
ู ุงููุธุงู
. ุฅุฐุง ุชุบูุฑ ุฑุฃููุ ุชูุงุตู ู
ุน ุงูุณุงุฆู ู
ุจุงุดุฑุฉ.
|
| 43 |
ุณ: ููู ุฃุณุฌู ูุณุงุฆูุ ุฌ: ููู "ุฃุจู ุฃุณุฌู ูุณุงุฆู" ุฃู ุงุฎุชุฑ ูุถุน ุงูุณุงุฆู. ูุญุชุงุฌ ุงูุงุณู
ุงููุงู
ู.
|
| 44 |
ุณ: ููู ุฃุจุญุซ ุนู ุฑุญูุฉ ูุณุงุฆู ู
ุนููุ ุฌ: ููู "ุฃุจู ุฑุญูุงุช ุงูุณุงุฆู ุฃุญู
ุฏ" ุฃู "ุฏูุฑ ุฑุญูุฉ ู
ุน ุงูุณุงุฆู". ููุฒุฉ ุชุจุญุซ ูู ุงูุฑุญูุงุช ุงูู
ุชุงุญุฉ ููุงูุณุงุฆู ูุชุฑุณู ูู ุงููุชุงุฆุฌ.
|
| 45 |
+
ุณ: ูู ุชูุจูููู ุฅุฐุง ุชููุฑุช ุฑุญูุฉ ุจุญุซุช ุนููุงุ ุฌ: ูุง ุชูุฌุฏ ุชูุจููุงุช ุชููุงุฆูุฉ ุนูุฏ ุฅุถุงูุฉ ุฑุญูุฉ ุฌุฏูุฏุฉ ุญุงููุงู. ุชูุฏุฑ ุชุจุญุซ ู
ุฑุฉ ุซุงููุฉ ูุงุญูุงู.
|
| 46 |
+
ุณ: ููู ุฃุถูู ุฑุญูุฉ ูุณุงุฆูุ ุฌ: ููู "ุฃุจู ุฃุถูู ุฑุญูุฉ ู
ู ุนุฏู ุฅูู ุงูุญุฏูุฏุฉ ุงูุฌู
ุนุฉ ุงูุตุจุงุญ" ุฃู ุงูุชุจ ุฅุนูุงูู ุจุชูุณููู ุงูุฎุงุต. ูู๏ฟฝ๏ฟฝุฉ ุชุณุชุฎุฑุฌ ุงูุชูุงุตูู ูุชุฒูู ุงูุฑูู
ูุงูุจูุงูุงุช ุงูุดุฎุตูุฉ ู
ู ุจุทุงูุฉ ุงูุนุฑุถ.
|
| 47 |
ุณ: ููู ุฃุนุฏู ุฃู ุฃูุบู ุฑุญูุฉุ ุฌ: ููู "ุฃุจู ุฃุนุฏู ุฑุญูุฉ" ุฃู "ุฃุจู ุฃูุบู ุฑุญูุฉ". ููุฒุฉ ุชุฑุณู ูู ูุงุฆู
ุฉ ุฑุญูุงุชู โ ุชุฑุฏ ุนูู ุงููู ุชุจูู.
|
| 48 |
ุณ: ูู ููู ุฑุญูุงุช ุจูู ูู ุงูู
ุฏูุ ุฌ: ููุฒุฉ ุชุนุฑุถ ุงูุฑุญูุงุช ุงููู ููุดุฑูุง ุงูุณุงุฆููู. ุฅุฐุง ู
ุง ูููุช ุฑุญูุชูุ ุงุณุฃู ู
ุฑุฉ ุซุงููุฉ ุฃู ุชูุงุตู ู
ุน ุงูุฏุนู
.
|
| 49 |
ุณ: ูู ุงูุฎุฏู
ุฉ ู
ุฌุงููุฉุ ุฌ: ุงุณุชุฎุฏุงู
ููุฒุฉ ู
ุฌุงูู. ุงูุณุนุฑ ููุณูุฑ ุชุชูู ููู ู
ุน ุงูุณุงุฆู.
|
| 50 |
|
| 51 |
## ุงูุฏุนู
ุงูููู
|
| 52 |
+
ุฅุฐุง ู
ุง ููู ุงูู
ุณุงุนุฏ ุฑุญูุฉ ู
ูุงุณุจุฉุ ููุถุญ ุฃูู ูุง ุชูุฌุฏ ุฑุญูุฉ ู
ุชุงุญุฉ ุญุงููุงู ููุง ูุนุฏ ุจุชูุจูู ุชููุงุฆู ุนูุฏ ุฅุถุงูุฉ ุฑุญูุฉ ูุงุญูุงู. ุฅุฐุง ุณูุฆู ุนู ู
ูุฒุฉ ุฃู ุทูุจ ููู
ูุฌุฏ ูู ุฅุฌุงุจุฉ ู
ูุซูุฉ ูู ู
ุนููู
ุงุช ููุฒุฉุ ูุนุชุฐุฑ ููุง ูุฎู
ู. ููุชูุงุตู ู
ุน ุงูุฏุนู
ุงูููู: ุฃุฑุณู ุงุณุชูุณุงุฑู ูุณูุฑุฏ ุนููู ูู ุฃูุฑุจ ููุช.
|
prompts/system.md
CHANGED
|
@@ -4,7 +4,10 @@ Rules:
|
|
| 4 |
- Reply in sender's language (Arabic/English). Be concise, warm, practical.
|
| 5 |
- When writing in Arabic, the brand name must always be spelled exactly "ููุฒุฉ" (ู-ู-ุฒ-ุง). Never use "ููุณุง", "ููุธ", "ููุธุฉ", "ููุฒ", or any other variant.
|
| 6 |
- For new users: be extra warm and welcoming. Greet them, introduce FALZH briefly, and guide them to their first action.
|
| 7 |
-
- Use `about_falzh` for company/FAQ/policy/pricing/support
|
|
|
|
|
|
|
|
|
|
| 8 |
- Tool args: Arabic for departure/destination/vehicle_type/time labels. English for digits/times.
|
| 9 |
- Never invent trips, prices, drivers, or bookings.
|
| 10 |
- Never pass phone_number; WhatsApp supplies it.
|
|
|
|
| 4 |
- Reply in sender's language (Arabic/English). Be concise, warm, practical.
|
| 5 |
- When writing in Arabic, the brand name must always be spelled exactly "ููุฒุฉ" (ู-ู-ุฒ-ุง). Never use "ููุณุง", "ููุธ", "ููุธุฉ", "ููุฒ", or any other variant.
|
| 6 |
- For new users: be extra warm and welcoming. Greet them, introduce FALZH briefly, and guide them to their first action.
|
| 7 |
+
- Use `about_falzh` for company/FAQ/policy/pricing/support, and for any feature,
|
| 8 |
+
capability, or FALZH request you are unsure about. Answer only from the returned
|
| 9 |
+
context. If it does not clearly answer the question, apologize briefly and say
|
| 10 |
+
you do not have confirmed information.
|
| 11 |
- Tool args: Arabic for departure/destination/vehicle_type/time labels. English for digits/times.
|
| 12 |
- Never invent trips, prices, drivers, or bookings.
|
| 13 |
- Never pass phone_number; WhatsApp supplies it.
|
prompts/system_driver.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
| 2 |
- check_driver_trips for upcoming trips.
|
| 3 |
- add_driver_car to register vehicle (name required).
|
| 4 |
- add_trip_by_driver(route, departure_date, departure_time). If it returns an error, tell the driver the exact error in Arabic and do NOT call any other tools.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
- Accept natural date expressions from the driver (ุงูููู
/ุจูุฑุฉ/ุบุฏุง/ููู
ุงูุฎู
ูุณ/ุจุนุฏ ููู
ูู etc.)
|
| 6 |
and convert them to YYYY-MM-DD using the current date in context. Never ask the driver
|
| 7 |
to rewrite the date in a specific format.
|
|
@@ -10,7 +14,9 @@
|
|
| 10 |
- To search/book as traveler: switch_to_passenger (name optional).
|
| 11 |
|
| 12 |
Driver message cleanup:
|
| 13 |
-
- When the driver's message
|
|
|
|
|
|
|
| 14 |
- Remove ALL phone numbers AND the surrounding text (e.g. "ููุชูุงุตู ุงูุงุชุตุงู ุนูู ุงูุฑูู
ุงูุขุชู๐:-770026665" โ remove entirely).
|
| 15 |
- Remove the driver's name wherever it appears in the message.
|
| 16 |
- Keep emojis, decorative elements, route info, dates, times, and seat info.
|
|
|
|
| 2 |
- check_driver_trips for upcoming trips.
|
| 3 |
- add_driver_car to register vehicle (name required).
|
| 4 |
- add_trip_by_driver(route, departure_date, departure_time). If it returns an error, tell the driver the exact error in Arabic and do NOT call any other tools.
|
| 5 |
+
- If the driver asks how to publish trips, tell them they can write the trip ad in
|
| 6 |
+
their own style/format. You extract the route, date, time, seats, price, and
|
| 7 |
+
vehicle automatically, and the cleaned ad can be shown to passengers in the
|
| 8 |
+
driver's preferred style.
|
| 9 |
- Accept natural date expressions from the driver (ุงูููู
/ุจูุฑุฉ/ุบุฏุง/ููู
ุงูุฎู
ูุณ/ุจุนุฏ ููู
ูู etc.)
|
| 10 |
and convert them to YYYY-MM-DD using the current date in context. Never ask the driver
|
| 11 |
to rewrite the date in a specific format.
|
|
|
|
| 14 |
- To search/book as traveler: switch_to_passenger (name optional).
|
| 15 |
|
| 16 |
Driver message cleanup:
|
| 17 |
+
- When the driver's message is a custom trip ad they likely want passengers to see,
|
| 18 |
+
set `driver_message` in add_trip_by_driver after cleaning it. For plain commands
|
| 19 |
+
like "add a trip from X to Y", omit `driver_message`.
|
| 20 |
- Remove ALL phone numbers AND the surrounding text (e.g. "ููุชูุงุตู ุงูุงุชุตุงู ุนูู ุงูุฑูู
ุงูุขุชู๐:-770026665" โ remove entirely).
|
| 21 |
- Remove the driver's name wherever it appears in the message.
|
| 22 |
- Keep emojis, decorative elements, route info, dates, times, and seat info.
|
prompts/system_new_user.md
CHANGED
|
@@ -4,7 +4,7 @@ It is the sender's first message. Welcome them warmly and introduce FALZH with a
|
|
| 4 |
2. Explain what FALZH is in 1 sentence: a WhatsApp travel service powered by AI โ no app to install.
|
| 5 |
3. Give a quick how-to guide showing both paths clearly:
|
| 6 |
- ุงูู
ุณุงูุฑ: ุงูุชุจ ูุฌูุชู (ู
ุซูุงู "ู
ู ุตูุนุงุก ุฅูู ุนุฏู ุจูุฑุฉ ุงูุตุจุงุญ") โ ููุฒุฉ ุชุจุญุซ โ ุฑุฏ ุนูู ุงูุจุทุงูุฉ โ ุชุชูุงุตู ู
ุน ุงูุณุงุฆู. Do NOT ask for name.
|
| 7 |
-
- ุงูุณุงุฆู: ุณุฌู ูุณุงุฆู โ ุฃ
|
| 8 |
4. Use emojis (๐, ๐, etc.) and friendly tone. Be warm, not robotic.
|
| 9 |
5. Keep it short โ 4-5 lines max. Do not over-explain.
|
| 10 |
6. Never ask for name of a passenger. Only ask for name if they want to become a driver.
|
|
|
|
| 4 |
2. Explain what FALZH is in 1 sentence: a WhatsApp travel service powered by AI โ no app to install.
|
| 5 |
3. Give a quick how-to guide showing both paths clearly:
|
| 6 |
- ุงูู
ุณุงูุฑ: ุงูุชุจ ูุฌูุชู (ู
ุซูุงู "ู
ู ุตูุนุงุก ุฅูู ุนุฏู ุจูุฑุฉ ุงูุตุจุงุญ") โ ููุฒุฉ ุชุจุญุซ โ ุฑุฏ ุนูู ุงูุจุทุงูุฉ โ ุชุชูุงุตู ู
ุน ุงูุณุงุฆู. Do NOT ask for name.
|
| 7 |
+
- ุงูุณุงุฆู: ุณุฌู ูุณุงุฆู โ ุฃุฑุณู ุฅุนูุงู ุฑุญูุชู ุจุชูุณููู ุงูุฎุงุต โ ููุฒุฉ ุชุณุชุฎุฑุฌ ุงูุชูุงุตูู ูุชุนุฑุถ ุงูุฅุนูุงู ุจุนุฏ ุฅุฒุงูุฉ ุงูุฑูู
ูุงูุจูุงูุงุช ุงูุดุฎุตูุฉ. Collect their full name, then create_driver_account(name) -> switch_to_driver.
|
| 8 |
4. Use emojis (๐, ๐, etc.) and friendly tone. Be warm, not robotic.
|
| 9 |
5. Keep it short โ 4-5 lines max. Do not over-explain.
|
| 10 |
6. Never ask for name of a passenger. Only ask for name if they want to become a driver.
|
prompts/system_passenger.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
- search_trips as soon as the user mentions a departure, destination, or driver name. You do not need all details โ the tool accepts partial info. Only ask a follow-up if neither departure, destination, nor driver name was mentioned.
|
| 2 |
- When search_trips finds matches, trip cards are sent to the user automatically along with a prompt to choose one. Do NOT add any text after calling search_trips โ the tool will handle the response.
|
|
|
|
| 3 |
- When the user replies to a trip card, immediately call select_trip โ trip_id is auto-detected and seats default to 1. Do not ask for seat count or other details.
|
| 4 |
- Selections are not reservations โ seats are not held.
|
| 5 |
- After successful select_trip, tell the passenger the driver's phone number from driver_phone so they can contact the driver directly to arrange the booking.
|
|
|
|
| 1 |
- search_trips as soon as the user mentions a departure, destination, or driver name. You do not need all details โ the tool accepts partial info. Only ask a follow-up if neither departure, destination, nor driver name was mentioned.
|
| 2 |
- When search_trips finds matches, trip cards are sent to the user automatically along with a prompt to choose one. Do NOT add any text after calling search_trips โ the tool will handle the response.
|
| 3 |
+
- When search_trips returns no matches, follow the tool's `reply_instruction`. Do not promise alerts or notifications when a future matching trip is added.
|
| 4 |
- When the user replies to a trip card, immediately call select_trip โ trip_id is auto-detected and seats default to 1. Do not ask for seat count or other details.
|
| 5 |
- Selections are not reservations โ seats are not held.
|
| 6 |
- After successful select_trip, tell the passenger the driver's phone number from driver_phone so they can contact the driver directly to arrange the booking.
|
tests/test_conversation_service.py
CHANGED
|
@@ -180,6 +180,8 @@ async def test_returning_driver_gets_welcome_and_upgraded_to_driver(settings):
|
|
| 180 |
system_contents = [m["content"] for m in ai_messages if m["role"] == "system"]
|
| 181 |
assert any("ููุฏ" in msg for msg in system_contents)
|
| 182 |
assert any("group" in msg.lower() or "ู
ุฌู
ูุนุงุช" in msg for msg in system_contents)
|
|
|
|
|
|
|
| 183 |
|
| 184 |
# user_mode should be upgraded to 'driver'
|
| 185 |
assert customer["user_mode"] == "driver"
|
|
@@ -225,4 +227,3 @@ async def test_conversation_uses_driver_tools_when_user_mode_is_driver(settings)
|
|
| 225 |
}
|
| 226 |
|
| 227 |
|
| 228 |
-
|
|
|
|
| 180 |
system_contents = [m["content"] for m in ai_messages if m["role"] == "system"]
|
| 181 |
assert any("ููุฏ" in msg for msg in system_contents)
|
| 182 |
assert any("group" in msg.lower() or "ู
ุฌู
ูุนุงุช" in msg for msg in system_contents)
|
| 183 |
+
assert any("own preferred style/format" in msg for msg in system_contents)
|
| 184 |
+
assert any("phone numbers will be removed" in msg for msg in system_contents)
|
| 185 |
|
| 186 |
# user_mode should be upgraded to 'driver'
|
| 187 |
assert customer["user_mode"] == "driver"
|
|
|
|
| 227 |
}
|
| 228 |
|
| 229 |
|
|
|
tests/test_tools.py
CHANGED
|
@@ -79,6 +79,17 @@ async def test_about_falzh_returns_retrieved_context():
|
|
| 79 |
assert embeddings.query_texts == ["What is FALZH?"]
|
| 80 |
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
@pytest.mark.asyncio
|
| 83 |
async def test_search_trips_uses_supabase_vector_matches_and_validates_business_rules():
|
| 84 |
repository = FakeRepository()
|
|
@@ -136,6 +147,26 @@ async def test_search_trips_reports_no_matches():
|
|
| 136 |
assert result.ok is True
|
| 137 |
assert result.data["matches"] == []
|
| 138 |
assert "No active" in result.data["note"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
|
| 141 |
@pytest.mark.asyncio
|
|
@@ -311,6 +342,8 @@ async def test_create_driver_account_uses_sender_phone():
|
|
| 311 |
assert result.ok is True
|
| 312 |
assert repository.created_drivers[0]["customers"]["remoteJid"] == "967700000010"
|
| 313 |
assert result.data["driver_id"] == "driver-1"
|
|
|
|
|
|
|
| 314 |
|
| 315 |
|
| 316 |
@pytest.mark.asyncio
|
|
@@ -662,6 +695,42 @@ async def test_add_trip_by_driver_uses_llm_cleaned_message():
|
|
| 662 |
assert created_trip["driver_message"] == cleaned_msg
|
| 663 |
|
| 664 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
@pytest.mark.asyncio
|
| 666 |
async def test_add_trip_by_driver_no_driver_message_with_few_emojis():
|
| 667 |
repository = FakeRepository()
|
|
|
|
| 79 |
assert embeddings.query_texts == ["What is FALZH?"]
|
| 80 |
|
| 81 |
|
| 82 |
+
@pytest.mark.asyncio
|
| 83 |
+
async def test_about_falzh_no_match_instructs_apology():
|
| 84 |
+
handlers = make_handlers()
|
| 85 |
+
|
| 86 |
+
result = await handlers.about_falzh({"query": "Do you support rewards?", "language": "en"})
|
| 87 |
+
|
| 88 |
+
assert result.ok is True
|
| 89 |
+
assert result.data["sources"] == []
|
| 90 |
+
assert "Do not guess" in result.data["reply_instruction"]
|
| 91 |
+
|
| 92 |
+
|
| 93 |
@pytest.mark.asyncio
|
| 94 |
async def test_search_trips_uses_supabase_vector_matches_and_validates_business_rules():
|
| 95 |
repository = FakeRepository()
|
|
|
|
| 147 |
assert result.ok is True
|
| 148 |
assert result.data["matches"] == []
|
| 149 |
assert "No active" in result.data["note"]
|
| 150 |
+
assert "Do not promise to notify" in result.data["reply_instruction"]
|
| 151 |
+
assert "already a general search" in result.data["reply_instruction"]
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
@pytest.mark.asyncio
|
| 155 |
+
async def test_search_trips_no_timed_match_instructs_no_narrow_retry():
|
| 156 |
+
handlers = make_handlers()
|
| 157 |
+
|
| 158 |
+
result = await handlers.search_trips(
|
| 159 |
+
{
|
| 160 |
+
"departure": "Aden",
|
| 161 |
+
"destination": "Sana'a",
|
| 162 |
+
"travel_date": "2026-12-01",
|
| 163 |
+
"travel_time": "morning",
|
| 164 |
+
}
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
assert result.ok is True
|
| 168 |
+
assert result.data["matches"] == []
|
| 169 |
+
assert "narrower/specific time" in result.data["reply_instruction"]
|
| 170 |
|
| 171 |
|
| 172 |
@pytest.mark.asyncio
|
|
|
|
| 342 |
assert result.ok is True
|
| 343 |
assert repository.created_drivers[0]["customers"]["remoteJid"] == "967700000010"
|
| 344 |
assert result.data["driver_id"] == "driver-1"
|
| 345 |
+
assert "own format/style" in result.data["reply_instruction"]
|
| 346 |
+
assert "phone numbers" in result.data["reply_instruction"]
|
| 347 |
|
| 348 |
|
| 349 |
@pytest.mark.asyncio
|
|
|
|
| 695 |
assert created_trip["driver_message"] == cleaned_msg
|
| 696 |
|
| 697 |
|
| 698 |
+
@pytest.mark.asyncio
|
| 699 |
+
async def test_add_trip_by_driver_uses_cleaned_message_without_many_emojis():
|
| 700 |
+
repository = FakeRepository()
|
| 701 |
+
repository.drivers_by_remote_jid["967700000010"] = {
|
| 702 |
+
"id": "driver-1",
|
| 703 |
+
"name": "Ali",
|
| 704 |
+
"remoteJid": "967700000010",
|
| 705 |
+
}
|
| 706 |
+
repository.driver_cars_by_driver["driver-1"] = [
|
| 707 |
+
{"id": "car-1", "car_type": "SUV", "seat_count": 4},
|
| 708 |
+
]
|
| 709 |
+
raw_msg = "ุฑุญูุฉ ููู
ูุฉ ู
ู ุนุฏู ุฅูู ุงูู
ููุง ููุชูุงุตู 770026665"
|
| 710 |
+
cleaned_msg = "ุฑุญูุฉ ููู
ูุฉ ู
ู ุนุฏู ุฅูู ุงูู
ููุง"
|
| 711 |
+
handlers = make_handlers(repository=repository, sender_phone="967700000010")
|
| 712 |
+
handlers.current_message = {"message": raw_msg}
|
| 713 |
+
|
| 714 |
+
result = await handlers.add_trip_by_driver(
|
| 715 |
+
{
|
| 716 |
+
"departure": "ุนุฏู",
|
| 717 |
+
"destination": "ุงูู
ููุง",
|
| 718 |
+
"departure_date": "2026-06-10",
|
| 719 |
+
"departure_time": "morning",
|
| 720 |
+
"vehicle_type": "SUV",
|
| 721 |
+
"available_seats": 2,
|
| 722 |
+
"total_seats": 4,
|
| 723 |
+
"price": 50,
|
| 724 |
+
"driver_message": cleaned_msg,
|
| 725 |
+
}
|
| 726 |
+
)
|
| 727 |
+
|
| 728 |
+
assert result.ok is True
|
| 729 |
+
created_trip = repository.created_trips[-1]
|
| 730 |
+
assert created_trip["use_driver_message"] is True
|
| 731 |
+
assert created_trip["driver_message"] == cleaned_msg
|
| 732 |
+
|
| 733 |
+
|
| 734 |
@pytest.mark.asyncio
|
| 735 |
async def test_add_trip_by_driver_no_driver_message_with_few_emojis():
|
| 736 |
repository = FakeRepository()
|