feat: two-phase execution, think slugs, query enrichment (v1.6.0)
Build and Push / build (release) Successful in 1m14s
Build and Push / build (release) Successful in 1m14s
Two-Phase Tatlock Execution: - orchestrate_tool_calls() for Phase 1 coordination - synthesize_from_results() for Phase 2 butler-toned synthesis - Guarantees butler personality in all responses Automatic Think Slugs: - Deterministic butler-perspective messages during expert delegation - ActionType enum: RETRIEVE, RESEARCH, CREATE, CONTROL, RECORD - HOUSEHOLD_THINK_MESSAGES mapping for all experts - Streaming delegation wrappers with automatic think messages Steward Query Enrichment: - Auto-fill user context (location, timezone) when not specified - _build_enriched_query() with regex word boundary matching - enriched_query field in StewardRecommendation schema Documentation: - ORCHESTRATION_SCENARIOS.md rewritten with Mermaid diagrams - New Housekeeper and Biographer scenarios - TESTING_IMPROVEMENTS.md for future LLM testing patterns 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,10 @@ class StewardRecommendation(BaseModel):
|
||||
default_factory=dict,
|
||||
description="Pre-fetched user context from memory (profile, preferences)"
|
||||
)
|
||||
enriched_query: str = Field(
|
||||
default="",
|
||||
description="User query with auto-filled context (location, timezone) when not specified"
|
||||
)
|
||||
|
||||
def format_for_butler(self) -> str:
|
||||
"""
|
||||
|
||||
@@ -149,6 +149,68 @@ def _extract_missing_capabilities(text: str) -> Optional[str]:
|
||||
return None
|
||||
|
||||
|
||||
def _build_enriched_query(user_request: str, memory_context: dict[str, Any]) -> str:
|
||||
"""
|
||||
Build an enriched query by appending user context when not specified.
|
||||
|
||||
When the user asks location-dependent questions (weather, nearby, etc.)
|
||||
without specifying a location, this appends their known location.
|
||||
Similarly for timezone-dependent queries.
|
||||
|
||||
Args:
|
||||
user_request: The user's original request
|
||||
memory_context: Pre-fetched memory context with profile/preferences
|
||||
|
||||
Returns:
|
||||
str: Query with context appended, or original query if no enrichment needed
|
||||
|
||||
Example:
|
||||
>>> query = _build_enriched_query(
|
||||
... "What's the weather?",
|
||||
... {"profile": {"location": "Amsterdam", "timezone": "Europe/Amsterdam"}}
|
||||
... )
|
||||
>>> query
|
||||
"What's the weather?\n\n[User Context: location=Amsterdam, timezone=Europe/Amsterdam]"
|
||||
"""
|
||||
if not memory_context:
|
||||
return user_request
|
||||
|
||||
request_lower = user_request.lower()
|
||||
profile = memory_context.get("profile", {})
|
||||
preferences = memory_context.get("preferences", {})
|
||||
|
||||
context_parts = []
|
||||
|
||||
# Check if location is needed and not specified
|
||||
location_keywords = ["weather", "temperature", "forecast", "nearby", "local", "here"]
|
||||
# Use word boundary pattern to avoid false positives like "at" in "what"
|
||||
location_prepositions = [r'\bin\b', r'\bat\b', r'\bnear\b', r'\baround\b', r'\bfor\b']
|
||||
location_specified = any(re.search(p, request_lower) for p in location_prepositions)
|
||||
|
||||
if any(word in request_lower for word in location_keywords):
|
||||
if not location_specified and profile.get("location"):
|
||||
context_parts.append(f"location={profile['location']}")
|
||||
|
||||
# Check if timezone is needed and not specified
|
||||
time_keywords = ["time", "schedule", "meeting", "appointment", "when", "today", "tomorrow"]
|
||||
timezone_specified = any(word in request_lower for word in ["timezone", "tz", "utc", "gmt"])
|
||||
|
||||
if any(word in request_lower for word in time_keywords):
|
||||
if not timezone_specified and profile.get("timezone"):
|
||||
context_parts.append(f"timezone={profile['timezone']}")
|
||||
|
||||
# Add preferences if relevant
|
||||
if preferences.get("temperature_unit") and "weather" in request_lower:
|
||||
context_parts.append(f"temperature_unit={preferences['temperature_unit']}")
|
||||
|
||||
# Build enriched query
|
||||
if context_parts:
|
||||
context_str = ", ".join(context_parts)
|
||||
return f"{user_request}\n\n[User Context: {context_str}]"
|
||||
|
||||
return user_request
|
||||
|
||||
|
||||
async def _prefetch_memory_context(user_request: str) -> dict[str, Any]:
|
||||
"""
|
||||
Pre-fetch user context that might be needed for this request.
|
||||
@@ -277,6 +339,9 @@ async def analyze_request(
|
||||
context = _extract_conversation_context(analysis_text, conversation_history)
|
||||
missing = _extract_missing_capabilities(analysis_text)
|
||||
|
||||
# Build enriched query with auto-filled context
|
||||
enriched_query = _build_enriched_query(user_request, memory_context)
|
||||
|
||||
recommendation = StewardRecommendation(
|
||||
recommended_capabilities=capabilities,
|
||||
reasoning=analysis_text,
|
||||
@@ -284,6 +349,7 @@ async def analyze_request(
|
||||
conversation_context=context,
|
||||
missing_capabilities=missing,
|
||||
memory_context=memory_context,
|
||||
enriched_query=enriched_query,
|
||||
)
|
||||
|
||||
# Update log context with results
|
||||
|
||||
Reference in New Issue
Block a user