Add language/location support: setup wizard, LLM matching, localization#651
Add language/location support: setup wizard, LLM matching, localization#651
Conversation
ASPDMA Schema Fix: - Remove tool_parameters from ASPDMALLMResult (only tool_name needed) - Remove tool_parameters from TSASPDMAInputs (extracted by TSASPDMA) - ASPDMA selects tool name; TSASPDMA extracts parameters from context HA Adapter Fixes: - Add missing parameter extraction (volume_level, temperature, hvac_mode, percentage) - Fix misleading "Entity not found" error when media_play has no effect - Error now explains media_play only resumes paused content - Error now directs users to Music Assistant tools for playing new music Documentation Updates: - Clarify media_play ONLY resumes paused content - Add critical gotcha: use ma_search/ma_play for new music playback - Update quick_start and dma_guidance to direct to Music Assistant 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The mobile app's audit trail was showing limited details for TOOL and
PONDER entries because the API only extracted a subset of fields from
the parameters JSON.
Now extracts:
- TOOL: tool_name (also from "name" key), tool_parameters
- PONDER: ponder_questions (questions list)
- SPEAK: content
- DEFER: defer_reason, defer_until
- TASK_COMPLETE: completion_reason
- REJECT: reject_reason
This enables the mobile audit trail to show full details like:
- "Questions: What should I consider?; How do I proceed?"
- "Tool: ha_device_control → parameters: {entity_id: ..., action: ...}"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, if ANY SQLite entries existed, graph entries were skipped entirely. This was wrong because: - Handler actions (tool, ponder, speak) are stored in graph via log_action - System events (agent_configured) go to SQLite - Both sources are needed for a complete audit trail Now both sources are always merged, giving the mobile app access to all audit entries with their full metadata (ponder_questions, tool_name, tool_parameters, tool_result, etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added detailed logging to trace audit data flow: - ActionDispatcher: Logs extracted params and full audit details - Audit API: Logs graph entry conversion with metadata keys This makes it clear what's being captured and returned: - TOOL: tool_name, tool_parameters, tool_adapter, tool_result - PONDER: ponder_questions, question_count 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…r enhancements ## Audit Trail - Fix audit API to merge graph and SQLite sources (handler actions stored in graph) - Extract all action-specific metadata: ponder_questions, tool_parameters, tool_result - Add comprehensive audit logging for debugging data flow ## ASPDMA Schema - Remove tool_parameters from ASPDMALLMResult (ASPDMA only selects tool name) - TSASPDMA now extracts parameters from context with full tool documentation ## Home Assistant Adapter - Add missing parameter extraction (volume_level, temperature, hvac_mode) - Fix misleading "Entity not found" error for media_play actions - Clarify media_play only resumes paused content; use Music Assistant for new music - Update tool documentation and gotchas 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add full ToolDocumentation (detailed_instructions, examples, gotchas) for: - ma_browse: Library browsing with media_type filtering - ma_queue: Queue viewing with player_id requirement - ma_players: Player discovery with entity_id patterns - Previously added docs for: ha_device_control, ha_automation_trigger, ha_sensor_query, ha_list_entities, ha_notification, ha_camera_analyze, ma_search, ma_play - Fix mypy: Remove invalid tool_parameters from ASPDMALLMResult (ASPDMA only selects tool name, TSASPDMA handles parameters) - Fix audit tests: Update test expectations to match correct multi-source merge behavior (entries show all sources, dedup by timestamp+action) - Add context enrichment logging for tool prompt debugging 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When an event is first seen in graph memory, seen_timestamps is populated but dedup_to_entry is not (only SQLite populates dedup_to_entry). This caused JSONL records matching by timestamp+action to not have "jsonl" added to storage_sources. Fix: When dedup_to_entry lookup fails, search merged entries by matching the dedup_key (timestamp+action) to find and update the correct entry. Added test: test_jsonl_source_added_when_graph_entry_exists 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The when_to_use field was extracted but not displayed in the tool highlight section. Now it's included to help the LLM understand when to use the highlighted tool. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ma_get_players(): Add detection for mass_player_type attribute and app_id == "music_assistant" to correctly identify MA-controlled players (e.g., bedroom_nabu_media_player_2 vs bedroom_nabu_media_player) - ma_play(): Remove config_entry_id parameter which causes HTTP 400 when invalid/unavailable - it's not required for play_media service 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1: Per-user email for public API services - Add publicApiEmail and publicApiServicesEnabled to SetupState - Add setters in SetupViewModel - Add Navigation & Weather card to OptionalFeaturesStep with: - Feature explanation (OSM, NOAA public APIs) - Enable/disable toggle - Email input field (shown when enabled) - Update weather/navigation services to use PUBLIC_API_CONTACT_EMAIL env var from wizard, falling back to legacy env vars - Pass email to adapter_config in setup completion request This enables users to use navigation:geocode to convert location names to coordinates for weather tools, all powered by free public APIs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…zard support ## Cross-Platform CIRIS_HOME Setup - Add ensure_ciris_home_env() in path_resolution.py for centralized env var setup - Update main.py to call ensure_ciris_home_env() early before ciris_engine imports - Update mobile_main.py (Android) to use centralized function - Update ios_main.py (iOS) to use centralized function - Fix Android path fallback bug (Path.home() / "ciris" not "files/ciris") ## Desktop App QA Infrastructure - Add testable tags to all navigation menu items in CIRISApp.kt: - Category buttons: btn_adapters_menu, btn_config_menu, btn_data_menu, btn_governance_menu - Menu items: menu_tools, menu_settings, menu_config, menu_billing - Data menu: menu_memory, menu_sessions, menu_consent, menu_audit, menu_data_management - Governance: menu_wise_authority, menu_users - Advanced: menu_telemetry, menu_services, menu_logs, menu_system, menu_runtime, menu_tickets, menu_scheduler ## SetupScreen Test Automation - Add TestAutomation.textInputRequests observer for programmatic text input - Support automated input for: input_public_api_email, input_username, input_password, input_api_key, input_llm_model_text ## Adapter Wizard Integration - Add adapter wizard state fields to SetupFormState for wizard-in-wizard support - Add SetupViewModel methods for adapter configuration during setup - Enable adapter configuration flow within the setup wizard 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract 11 helper functions from _process_graph_entries and _process_sqlite_entries to reduce cognitive complexity from 56 to approximately 15. Add 53 unit tests for comprehensive coverage. Helper functions added: - _entry_has_additional_metadata() - _merge_graph_metadata_into_entry() - _find_sqlite_entry_for_dedup_key() - _infer_outcome_from_event() - _extract_handler_metadata() - _parse_event_payload_metadata() - _extract_sqlite_entry_info() - _track_sqlite_dedup_key() - _handle_duplicate_graph_entry() - _add_new_graph_entry() - _add_new_sqlite_entry() 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The agent was always responding in English even when users wrote in other languages. Two changes fix this: 1. Action selection PDMA now instructs the LLM to match the user's language 2. User profile formatter now surfaces preferred_language to LLM context https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
|
|
|
|
…uide WalletAdapter: - Generic money tools: send_money, request_money, get_statement - x402 provider for USDC on Base L2 (Ed25519 -> secp256k1 derivation) - Chapa provider for Ethiopian Birr via Telebirr/CBE Birr - Context enrichment for get_statement (balance awareness) - DMA guidance with requires_approval for financial ops - Provider-agnostic design for future providers (M-Pesa, etc.) Documentation: - FSD/WALLET_ADAPTER.md - Full functional specification - FSD/ADAPTER_DEVELOPMENT_GUIDE.md - Guide for building adapters - CLAUDE.md updated with adapter development quick reference Design for global access: Ethiopian philosophers pay in ETB, developers pay in USDC - same service, same dignity. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Setup wizard changes (all platforms): - New "Preferences" step (Step 2) for language and location selection - Users choose location granularity: country only, +region, +city, or none - 15 languages in picker, auto-detect timezone on Android - Preferences saved to .env and graph memory for LLM context - Backend SetupCompleteRequest gains preferred_language, location_*, timezone fields Android (4-step wizard: Welcome > Preferences > AI Config > Confirm): - New SetupPreferencesFragment with language spinner and location radio group - Dynamic location fields appear based on chosen granularity - SetupViewModel extended with language/location state - Layout updated with 4-step indicator Localization folder (/localization/): - manifest.json tracking origin (auto-generated), dates, review status - 15 language files: en, am, ar, de, es, fr, hi, it, ja, ko, pt, ru, sw, tr, zh - Covers setup wizard strings, common agent messages, and status labels - All marked as draft/needs_native_review except English base https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
Key security improvement: - Wallet address derived from Ed25519 PUBLIC key (not seed) - Private key NEVER leaves CIRISVerify secure element - Signing delegated via callback to CIRISVerify - Every CIRIS agent has a wallet address from birth Changes: - x402_provider.py: Accept public_key + signing_callback - adapter.py: Auto-load from CIRISVerify singleton - Address derivation via HKDF from public key - Receive-only mode if no signing callback For receiving funds: Only need public key (immediate) For sending funds: Need signing callback to CIRISVerify 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The en.json base file now includes every string the LLM receives: - DMA prompts: PDMA ethical principles, CSDMA common sense, IDMA coherence analysis, DSDMA domain norms, ASPDMA action selection, TSASPDMA tool selection - System formatters: snapshot headers, continuity awareness, resource usage, context enrichment, identity fields, user profile context - Handler messages: speak/observe/defer/reject/forget/memorize/ponder follow-up thoughts injected into LLM context - Escalation stages: early/mid/late/exhausted guidance - Crisis resources: guidance text and disclaimers - Error messages: all API and service errors shown to users - Discord: embed field labels, deferral messages - Engine overview template Manifest updated to v2.0 with string category documentation. Non-English files have setup/agent/status coverage; remaining sections noted as pending in manifest. https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
Read values from the attributes dict instead of the setup object to avoid CodeQL taint tracking through SetupCompleteRequest password fields. https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
| add_graph_node(node, time_service, None) | ||
| lang = attributes.get("preferred_language", "not set") | ||
| loc = attributes.get("location", "not set") | ||
| logger.info(f"Stored user preferences for {user_id}: lang={lang}, location={loc}") |
Check failure
Code scanning / CodeQL
Clear-text logging of sensitive information High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 20 days ago
To fix the problem, avoid logging the tainted user_id (derived from canonical_user_id) and instead either (a) remove the log line, or (b) log only non-sensitive metadata such as the fact that preferences were stored and possibly the language/location, without any stable identifier. This preserves observability while preventing sensitive or potentially sensitive identifiers from reaching the logs.
The minimal-change, best fix here is to adjust the log message in _store_user_preferences (lines 305–310) so it no longer includes user_id. The function’s behavior—storing preferences via add_graph_node—remains unchanged; we only change what is logged. Concretely, in ciris_engine/logic/adapters/api/routes/setup/complete.py, replace:
logger.info(f"Stored user preferences for {user_id}: lang={lang}, location={loc}")with something like:
logger.info(f"Stored user preferences: lang={lang}, location={loc}")This removes the tainted user_id from the log sink, which resolves all CodeQL variants tied to that flow. No new methods or imports are needed; only this single line is updated.
| @@ -306,7 +306,7 @@ | ||
| add_graph_node(node, time_service, None) | ||
| lang = attributes.get("preferred_language", "not set") | ||
| loc = attributes.get("location", "not set") | ||
| logger.info(f"Stored user preferences for {user_id}: lang={lang}, location={loc}") | ||
| logger.info(f"Stored user preferences: lang={lang}, location={loc}") | ||
|
|
||
|
|
||
| async def _log_wa_list(auth_service: Any, phase: str) -> None: |
All 14 non-English files now have the complete key structure matching en.json (290-303 entries each). Untranslated strings are prefixed with [EN] for easy identification and batch translation. Coverage per file: - setup/agent/status sections: fully translated (existing) - prompts/handlers/errors/discord: [EN] fallback (pending) The [EN] prefix convention allows: - grep -r "\[EN\]" localization/ to find all pending translations - Batch translation tools to target only [EN]-prefixed values - Runtime fallback to English for untranslated strings https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
…-language-support-F5j4O
Merged release/2.3 and added all new user-facing strings: New adapter sections: - adapters.wallet: send_money, request_money, get_statement tool docs, currency/provider mapping, spending limits, error messages (Chapa ETB, x402 USDC, M-Pesa/Flutterwave future) - adapters.navigation: geocode, reverse geocode, route calculation tool docs, OpenStreetMap rate limit notes, error messages - adapters.weather: current/forecast/alerts tool docs, NOAA/OWM data sources, US-only gotchas, safety disclaimers New mobile section: - Setup wizard: agent registration, portal connect, node auth flow, validation errors, setup state labels - Interact screen: action type labels, outcome labels, hallucination warning, welcome text, sender labels, field names en.json: ~511 entries (up from ~298) All 14 translations updated with [EN] fallbacks for new keys. Manifest bumped to v2.1.0. https://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ
|
|
||
| import json | ||
| from datetime import datetime, timezone | ||
| from typing import Any, Dict |
| from typing import Any, Dict | ||
| from unittest.mock import MagicMock | ||
|
|
||
| import pytest |
| import uuid | ||
| from datetime import datetime, timezone | ||
| from decimal import Decimal | ||
| from typing import Any, Callable, Dict, List, Optional |
| # ============================================================================= | ||
| from ciris_engine.logic.utils.path_resolution import ensure_ciris_home_env | ||
|
|
||
| _ciris_home = ensure_ciris_home_env() |
|
|
||
| Examples: 'x402', 'chapa', 'mpesa', 'flutterwave' | ||
| """ | ||
| ... |
| - Chapa: ['ETB'] | ||
| - M-Pesa: ['KES'] | ||
| """ | ||
| ... |
| Returns: | ||
| True if initialization successful, False otherwise. | ||
| """ | ||
| ... |
| Called during adapter shutdown. Should close connections, | ||
| flush pending operations, etc. | ||
| """ | ||
| ... |
| Raises: | ||
| ValueError: If currency not supported or parameters invalid | ||
| """ | ||
| ... |
| Returns: | ||
| PaymentRequest with request ID, checkout URL, etc. | ||
| """ | ||
| ... |



Summary
preferred_languagefrom user profiles to LLM context/localization/folder with auto-generated translations for 15 languagesChanges
LLM Language Matching (commit 1)
action_selection_pdma.yml— LANGUAGE MATCHING instruction inclosing_reminderuser_profiles.py— Includepreferred_languagein profile formatter outputSetup Wizard - Preferences Step (commit 2)
SetupCompleteRequestgainspreferred_language,location_country,location_region,location_city,timezonefieldscomplete.pysaves preferences to.envand stores in graph memory as a CONCEPT nodeprompt_language_and_location()with 15-language picker and granularity-selectable locationSetupPreferencesFragment.kt— Language spinner + location radio group with dynamic fieldsSetupViewModel.kt— Language/location state managementfragment_setup_preferences.xml— Layout with granularity-based visibilityactivity_setup_wizard.xml— 4-step indicatorstrings.xml— New preference string resourcesLocalization Folder (
/localization/)manifest.json— Tracks origin (auto-generated), addition dates, review status per languageneeds_native_reviewLocation Granularity
Users choose their own level of detail:
Test plan
SetupCompleteRequestaccepts new fields correctlyhttps://claude.ai/code/session_01Kk7Kjgu8YRuZzB6X5RTgdQ