fix(chat): fix location clarification loop and test isolation bugs
- Add _COMMAND_VERBS guard to _is_likely_location_reply() so messages starting with imperative verbs (find, search, show, get, ...) are not mistakenly treated as user location replies. This prevented 'Find good places' from being used as a retry location, which was causing the clarification path to never fire and the tool loop to exhaust MAX_ALL_FAILURE_ROUNDS instead. - Extract city from comma-delimited fallback address strings when city/country FKs are absent, e.g. 'Little Turnstile 6, London' → 'London', so context-based location retry works for manually- entered itinerary stops without geocoded FK data. - Add attempted_location_retry flag: if retry was attempted but all retry attempts failed, convert result to an execution failure rather than emitting a clarification prompt (user already provided context via their itinerary). - Fix test assertion ordering in test_collection_context_retry_extracts_ city_from_fallback_address: streaming_content must be consumed before checking mock call counts since StreamingHttpResponse is lazy.
This commit is contained in:
@@ -74,6 +74,8 @@ Run in this order:
|
||||
- Chat providers: dynamic catalog from `GET /api/chat/providers/`; configured in `CHAT_PROVIDER_CONFIG`
|
||||
- Chat model override: dropdown selector fed by `GET /api/chat/providers/{provider}/models/`; persisted in `localStorage` key `voyage_chat_model_prefs`; backend accepts optional `model` param in `send_message`
|
||||
- Chat context: collection chats inject collection UUID + multi-stop itinerary context; system prompt guides `get_trip_details`-first reasoning and confirms only before first `add_to_itinerary`; `search_places` has a deterministic context-retry fallback — when the LLM omits `location`, the backend retries using the trip destination or first itinerary stop before asking the user for clarification; a dining-intent heuristic infers `category="food"` from user messages when the LLM omits category for restaurant/dining requests
|
||||
- `itinerary_stops` extraction: when `city`/`country` FK is null, city is extracted from the last non-numeric segment of a comma-separated address (e.g. `"Little Turnstile 6, London"` → `"London"`); ensures `trip_context_location` is always a geocodable city name, not a street address.
|
||||
- After itinerary context retries: if all retries fail, result is converted to an execution failure rather than triggering a clarification prompt — the user is never asked for a location they already implied via collection context.
|
||||
- Chat tool output: `role=tool` messages hidden from display; tool outputs render as concise summaries; persisted tool rows reconstructed on reload via `rebuildConversationMessages()`; tool results are deduplicated by `tool_call_id` at three layers — rebuild from persisted rows (discards server-side pre-populated `tool_results`), SSE ingestion (`appendToolResultDedup`), and render-time (`uniqueToolResultsByCallId`)
|
||||
- Chat error surfacing: `_safe_error_payload()` maps LiteLLM exceptions to sanitized user-safe categories (never forwards raw `exc.message`); `execute_tool()` catch-all returns a generic sanitized message (never raw `str(exc)`)
|
||||
- Invalid tool calls (missing required args) are detected and short-circuited with a user-visible error — not replayed into history
|
||||
|
||||
Reference in New Issue
Block a user