From 153b788134b13b157516b257ccc1dcfbbcb47cc1 Mon Sep 17 00:00:00 2001 From: pewdiepie-archdaemon Date: Thu, 11 Jun 2026 08:56:42 +0900 Subject: [PATCH] Tool retrieval: surface manage_contact for 'save X for ' patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user dumps a postal address or phone number alongside a person's name and says 'save this for X', the vector retriever was missing manage_contact because its description only mentioned the literal word 'contact'. The model defaulted to manage_memory (which is in ALWAYS_AVAILABLE), so the saved fact ended up as un-named memory that wouldn't surface on a later 'what's X's address?' search. - Rewrite manage_contact's index description to anchor on the semantics: 'save info about another person', including postal/ mailing address, ZIP, phone, etc. Now it embeds close to address- paste queries. - Extend the keyword intent-map with 'save this for', 'save it for', 'mailing address', 'postal code', 'their address', etc. — common ways users say 'this belongs to a contact' without the literal word 'contact'. --- src/tool_index.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tool_index.py b/src/tool_index.py index b6c196add..ea6bd323a 100644 --- a/src/tool_index.py +++ b/src/tool_index.py @@ -114,7 +114,7 @@ BUILTIN_TOOL_DESCRIPTIONS: Dict[str, str] = { "mark_email_read": "Mark an email as read or unread by toggling the \\Seen flag.", "bulk_email": "Perform one action on many emails at once. Use for delete all those, archive these, mark all read, move spam to junk. Takes explicit UIDs from list_emails or all_unread=true. Always pass account for Gmail/work/custom mailbox results.", "resolve_contact": "Look up a contact's email address by name. Searches CardDAV address book and sent email history. Use when the user says 'message [name]', 'email [name]', or 'send to [name]' without an email address.", - "manage_contact": "Create, update, delete, or list CardDAV contacts. Use to save a new contact, change an existing one's email/phone, or remove one. Action=list returns uids needed for update/delete. Use when the user says 'save this contact', 'add [name] to contacts', 'update [name]'s email', 'delete [name] from contacts'. Do not use for user identity facts like 'my name is '; those are memory.", + "manage_contact": "Save / update / delete / list address-book contacts (CardDAV). This is the right tool whenever the user is storing info about a specific OTHER person — their email, phone number, postal/mailing/street address, birthday, role at a company. Examples of phrasings that should land here: 'save this for ', 'save it for ', 'remember 's address / phone / email', 'add to contacts', 'update 's email', 'delete from contacts'. If the message contains a postal address, street, city, ZIP/postal code, or phone number alongside a person's name, use manage_contact — NOT manage_memory. Action=list returns the uid needed for update/delete. Do NOT use for facts about the USER themselves ('my name is X', 'I live at Y'); those are manage_memory.", "manage_notes": "Create and manage notes and checklists (Google Keep-style). ALWAYS use this for note/todo/checklist/reminder creation — NEVER hit /api/notes via app_api. Accepts natural-language `due_date` like 'tomorrow at 9am' or '11pm today' (parsed in the USER'S timezone). The due_date IS the reminder — it fires a notification at that time, so do NOT also create a calendar event for the same reminder. Set colors, labels, pin, archive. Do NOT use manage_memory for note content.", "manage_calendar": "Calendar event management: list, create, update, delete. Each event can carry a tag/category (event_type — work/personal/health/travel/meal/social/admin/other) and importance (low/normal/high/critical). Resolve today/tomorrow using the Current date and time context, then use ISO datetimes in the user's local wall time; supports all-day events. For event reminders/alarms, pass reminder_minutes; this creates the Notes reminder, so do not also call manage_notes for the same reminder.", "download_model": "Download a HuggingFace model to a local or remote server. Specify repo_id (e.g. 'Qwen/Qwen3-8B'), optional server host, and optional include filter for specific files.", @@ -371,7 +371,15 @@ class ToolIndex: {"resolve_contact", "manage_contact"}, frozenset({"save contact", "add contact", "new contact", "update contact", "edit contact", "delete contact", "remove contact", - "save this person", "add to contacts", "save to contacts"}): + "save this person", "add to contacts", "save to contacts", + # "save this for " / "save it for " — the user + # is storing info on a known person without using the literal + # word 'contact'. Catches the address/phone-paste pattern. + "save this for", "save it for", "save for", + "save this one for", "save that for", + # Postal-address-like signals + "postal code", "zip code", "street address", + "mailing address", "their address"}): {"manage_contact"}, # "Ask another model" intent → chat_with_model relays to a # different model and returns its answer. ask_teacher escalates