Add LocalChatClientWithAgents sample (Apple Intelligence + Agent Framework)#744
Add LocalChatClientWithAgents sample (Apple Intelligence + Agent Framework)#744mattleibow wants to merge 16 commits intodotnet:mainfrom
Conversation
AI Travel Planner using on-device Apple Intelligence with the Microsoft Agent Framework, Microsoft.Extensions.AI, and .NET MAUI. Features a 4-agent workflow pipeline: - Travel Planner: NLP intent extraction - Researcher: RAG-based destination matching with NL embeddings - Itinerary Planner: Streaming itinerary generation with tool calling - Translator: Conditional translation for non-English requests Only supported on iOS and macCatalyst (Apple Intelligence). Other platforms throw PlatformNotSupportedException at startup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move ChatOverlayView, ChatBubbleTemplateSelector, MarkdownConverter to Views/Chat/ - Update namespaces to LocalChatClientWithAgents.Views.Chat - Pin Microsoft.Agents.AI packages to 1.0.0-rc3 (Hosting: 1.0.0-preview.260304.1) - Pin Microsoft.Extensions.AI to 10.3.0 - Pin Microsoft.Extensions.* to 10.0.0 - Fix Microsoft.Maui.Essentials.AI version glob to 10.0.*-* Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace manual AddSingleton<IChatClient> with MEAI's AddChatClient() - Replace AddKeyedSingleton<IChatClient> with AddKeyedChatClient() - Use .Build(sp) to pass IServiceProvider to middleware pipeline - Remove Arabic from SetLanguage tool description (not in SupportedLanguages) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Split TripPlanningPage into landmark detail page (TripPlanningPage) and itinerary generation page (ItineraryPage) - ItineraryPage starts generating immediately on navigation - PlanTrip chat tool navigates directly to ItineraryPage with day count - Add day counter stepper (1-7) on landmark detail page - Remove chat overlay from inner pages (FAB only on LandmarksPage) - Remove LandmarkTripView wrapper (inlined into pages) - Fix NullReferenceException in ItineraryViewModel.CreateDays() - Change Itinerary.Days constraint from [Length(3,3)] to [Length(1,7)] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eferenceService - Remove LanguagePreferenceService singleton and DI registration - Add language picker directly to TripPlanningPage - Pass language as parameter through navigation and service calls - Remove SetLanguage chat tool (chat specifies language via PlanTrip tool) - Remove floating language button from LandmarksPage - Clean up LandmarksViewModel language properties Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Replace bottom panel with floating card: rounded corners, shadow, max-width 400px - Vertical layout with uppercase DURATION/LANGUAGE section headers - Fix redundant day counter (single '3 days' label instead of big number + caption) - Full-width language picker with globe icon in bordered field - Full-width generate button with drop shadow - Card centers on wide screens, fills on narrow screens - Add system prompt instruction to use default values for unspecified params Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix duplicate ChatService DI registration - Fix CancellationTokenSource leak in ItineraryPageViewModel and TripPlanningViewModel - Refactor ChatViewModel to use [RelayCommand] for consistency - Replace hardcoded colors with StaticResource/AppThemeBinding (Primary, tool borders, error text) - Migrate BackgroundColor to Background across all XAML files - Add SafeAreaEdges=None on root Grid layouts for edge-to-edge content - Wrap back buttons in Grid with SafeAreaEdges=Container for status bar clearance - Add negative margin + padding on horizontal scroll lists for edge-to-edge scrolling - Update README: expand Run section, add ItineraryPage to architecture docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new .NET MAUI AI sample (10.0/AI/LocalChatClientWithAgents/) demonstrating an on-device Apple Intelligence travel planner that combines Microsoft.Extensions.AI (IChatClient) with a multi-agent Microsoft Agent Framework workflow (RAG + streaming itinerary + conditional translation), plus a chat overlay with tool calling.
Changes:
- Introduces a 4-agent itinerary workflow (Travel Planner → Researcher/RAG → Itinerary Planner/tools+streaming → Translator/conditional) and associated streaming/merge utilities.
- Adds new MAUI pages/views/viewmodels for landmark browsing, trip planning, streaming itinerary rendering, and a chat overlay UI with markdown rendering.
- Adds sample resources (styles, icons, splash, embedded JSON datasets) and platform scaffolding (iOS/macCatalyst/Android/Windows).
Reviewed changes
Copilot reviewed 93 out of 141 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkListItemView.xaml.cs | Landmark list item control code-behind + tap event plumbing |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkListItemView.xaml | Landmark list item UI layout (thumbnail + title) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkHorizontalListView.xaml.cs | Horizontal list wrapper control code-behind + event forwarding |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkHorizontalListView.xaml | Horizontal scroll + BindableLayout templating for landmarks |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkFeaturedItemView.xaml.cs | Featured landmark control code-behind + tap event plumbing |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkFeaturedItemView.xaml | Featured landmark UI (background image + title overlay) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/MessageView.xaml.cs | Simple wrapper view code-behind for itinerary status/error display |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/MessageView.xaml | Status/error overlay UI for itinerary page |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/LandmarkDetailMapView.xaml.cs | Map view code-behind (pins + region positioning) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/LandmarkDetailMapView.xaml | Map view XAML with pin template |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/LandmarkDescriptionView.xaml.cs | Simple wrapper view code-behind for landmark details section |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/LandmarkDescriptionView.xaml | Landmark title/tags/description UI |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ItineraryView.xaml.cs | Simple wrapper view code-behind for itinerary content section |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ItineraryView.xaml | Itinerary header/rationale/day list UI |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ItineraryPlanningView.xaml.cs | Simple wrapper view code-behind for planning progress section |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ItineraryPlanningView.xaml | “planning” progress UI with fading status trail |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/DayView.xaml.cs | Simple wrapper view code-behind for a single day card |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/DayView.xaml | Day card UI (map + weather/title/subtitle + activities) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ActivityListView.xaml.cs | Simple wrapper view code-behind for day activities list |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Itinerary/ActivityListView.xaml | Activities list UI (bullet + title/description) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Chat/MarkdownConverter.cs | Markdig-based markdown → FormattedString converter for chat bubbles |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Chat/ChatOverlayView.xaml.cs | Chat overlay behavior (sizing, show/hide animation, autoscroll) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Chat/ChatOverlayView.xaml | Chat overlay UI templates (user/assistant/tool call/result) |
| 10.0/AI/LocalChatClientWithAgents/src/Views/Chat/ChatBubbleTemplateSelector.cs | Template selection based on bubble type |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/TripPlanningViewModel.cs | Trip configuration VM (day count, language, tag generation) |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/LandmarksViewModel.cs | Landmarks browsing VM + embedding progress UI state |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/ItineraryViewModel.cs | Itinerary VM wrapper + day VM creation |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/ItineraryPageViewModel.cs | Orchestrates streaming itinerary generation + weather enrichment |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/DayPlanViewModel.cs | Day plan VM (activities, weather) |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/ChatViewModel.cs | Chat UI VM (streaming updates, tool call/result bubbles) |
| 10.0/AI/LocalChatClientWithAgents/src/ViewModels/ChatBubbleViewModel.cs | Bubble VM + expand/collapse for tool details |
| 10.0/AI/LocalChatClientWithAgents/src/Services/WeatherService.cs | Open-Meteo integration for daily forecasts |
| 10.0/AI/LocalChatClientWithAgents/src/Services/TaggingService.cs | Tag extraction via IChatClient structured output |
| 10.0/AI/LocalChatClientWithAgents/src/Services/StreamingJsonDeserializer.cs | Streaming JSON reconstruction + incremental deserialization helper |
| 10.0/AI/LocalChatClientWithAgents/src/Services/JsonMerger.cs | Deep-merge utility for progressively overlaying translated JSON |
| 10.0/AI/LocalChatClientWithAgents/src/Services/ItineraryService.cs | Streams workflow output, incremental parsing, translation merge handling |
| 10.0/AI/LocalChatClientWithAgents/src/Services/DataService.cs | Loads datasets + generates embeddings + semantic search |
| 10.0/AI/LocalChatClientWithAgents/src/Services/ChatService.cs | Tool-enabled chat service + navigation tool callback |
| 10.0/AI/LocalChatClientWithAgents/src/Services/BufferedChatClient.cs | Delegating chat client that buffers streaming text updates |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Styles/Styles.xaml | App-wide control styles |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Styles/Colors.xaml | App-wide color palette + brushes |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Splash/splash.svg | Splash SVG asset |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Raw/pointsOfInterestData.json | Embedded points-of-interest dataset for the sample |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Raw/landmarkData.json | Embedded landmarks dataset for the sample |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/Raw/AboutAssets.txt | MAUI template raw-assets guidance file |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/AppIcon/appiconfg.svg | App icon foreground SVG |
| 10.0/AI/LocalChatClientWithAgents/src/Resources/AppIcon/appicon.svg | App icon background SVG |
| 10.0/AI/LocalChatClientWithAgents/src/Properties/launchSettings.json | Debug launch profile settings |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/iOS/Resources/PrivacyInfo.xcprivacy | iOS privacy manifest |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/iOS/Program.cs | iOS app entry point |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/iOS/Info.plist | iOS app metadata |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/iOS/AppDelegate.cs | iOS app delegate |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Windows/app.manifest | Windows manifest (template) |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Windows/Package.appxmanifest | Windows packaging manifest (template) |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Windows/App.xaml.cs | Windows app bootstrap |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Windows/App.xaml | Windows XAML app definition |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/MacCatalyst/Program.cs | MacCatalyst app entry point |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/MacCatalyst/Info.plist | MacCatalyst app metadata |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/MacCatalyst/Entitlements.plist | MacCatalyst entitlements (network client + sandbox) |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/MacCatalyst/AppDelegate.cs | MacCatalyst app delegate |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Android/Resources/values/colors.xml | Android color resources |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Android/MainApplication.cs | Android application bootstrap |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Android/MainActivity.cs | Android main activity |
| 10.0/AI/LocalChatClientWithAgents/src/Platforms/Android/AndroidManifest.xml | Android manifest + network permissions |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/TripPlanningPage.xaml.cs | Trip planning page navigation + lifecycle cancellation |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/TripPlanningPage.xaml | Trip planning UI (duration/language picker + generate CTA) |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/LandmarksPage.xaml.cs | Landmarks page interactions + chat overlay wiring |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/LandmarksPage.xaml | Landmarks browsing UI + embedding-generation blocker overlay |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/ItineraryPage.xaml.cs | Itinerary page lifecycle (generate/cancel) + back navigation |
| 10.0/AI/LocalChatClientWithAgents/src/Pages/ItineraryPage.xaml | Itinerary UI switching (planning/results/error) |
| 10.0/AI/LocalChatClientWithAgents/src/NuGet.config | Adds dotnet10 preview feed for Apple Intelligence package |
| 10.0/AI/LocalChatClientWithAgents/src/Models/Weather.cs | Weather forecast DTOs + weather code mapping helpers |
| 10.0/AI/LocalChatClientWithAgents/src/Models/PointOfInterest.cs | POI model + embeddings field |
| 10.0/AI/LocalChatClientWithAgents/src/Models/Landmark.cs | Landmark model + computed image names + location + embeddings field |
| 10.0/AI/LocalChatClientWithAgents/src/Models/Itinerary.cs | Itinerary schema + validation metadata + example generator |
| 10.0/AI/LocalChatClientWithAgents/src/MauiProgram.cs | DI registration + Apple Intelligence gating + workflow registration |
| 10.0/AI/LocalChatClientWithAgents/src/MauiAppBuilderExtensions.cs | Apple Intelligence + embeddings DI helpers |
| 10.0/AI/LocalChatClientWithAgents/src/LocalChatClientWithAgents.slnx | Solution entry for the new sample |
| 10.0/AI/LocalChatClientWithAgents/src/LocalChatClientWithAgents.csproj | Project definition + NuGet package references + assets |
| 10.0/AI/LocalChatClientWithAgents/src/Converters/IsNotNullOrEmptyConverter.cs | Converter used for conditional UI visibility |
| 10.0/AI/LocalChatClientWithAgents/src/Converters/IsNotNullConverter.cs | Converter used for null checks in XAML |
| 10.0/AI/LocalChatClientWithAgents/src/Converters/InvertedBoolConverter.cs | Converter used for boolean inversion in XAML |
| 10.0/AI/LocalChatClientWithAgents/src/AppShell.xaml.cs | Shell route registration |
| 10.0/AI/LocalChatClientWithAgents/src/AppShell.xaml | Shell structure (LandmarksPage as root) |
| 10.0/AI/LocalChatClientWithAgents/src/App.xaml.cs | Application bootstrap |
| 10.0/AI/LocalChatClientWithAgents/src/App.xaml | Resource dictionaries + converters registration |
| 10.0/AI/LocalChatClientWithAgents/src/AI/WorkflowModels.cs | Workflow model types exchanged between executors/agents |
| 10.0/AI/LocalChatClientWithAgents/src/AI/WorkflowEvents.cs | Custom workflow events for status + streaming text chunks |
| 10.0/AI/LocalChatClientWithAgents/src/AI/ItineraryWorkflowTools.cs | RAG provider + POI tool exposed to itinerary agent |
| 10.0/AI/LocalChatClientWithAgents/src/AI/ItineraryWorkflowExtensions.cs | Agent registrations + workflow graph + conditional translation routing |
| 10.0/AI/LocalChatClientWithAgents/src/AI/5_OutputExecutor.cs | Workflow output executor (final status event) |
| 10.0/AI/LocalChatClientWithAgents/src/AI/4_TranslatorExecutor.cs | Translator executor streaming translated JSON as workflow events |
| 10.0/AI/LocalChatClientWithAgents/src/AI/3_ItineraryPlannerExecutor.cs | Itinerary planner executor streaming itinerary JSON as workflow events |
| 10.0/AI/LocalChatClientWithAgents/src/AI/2_ResearcherExecutor.cs | Researcher executor using RAG context to pick best destination |
| 10.0/AI/LocalChatClientWithAgents/src/AI/1_TravelPlannerExecutor.cs | Travel planner executor extracting intent into a typed message |
| 10.0/AI/LocalChatClientWithAgents/README.md | Sample documentation (architecture, prerequisites, run instructions) |
10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkListItemView.xaml.cs
Show resolved
Hide resolved
10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkFeaturedItemView.xaml.cs
Show resolved
Hide resolved
10.0/AI/LocalChatClientWithAgents/src/Views/Landmarks/LandmarkHorizontalListView.xaml.cs
Show resolved
Hide resolved
…README - Fix chat overlay layout: edge-to-edge backdrop (SafeAreaEdges=None), safe area + keyboard-aware wrapper (SoftInput,Container), floating card with CascadeInputTransparent=False for proper touch handling - Remove iOS keyboard Done button on chat Entry (InputAccessoryView=null) - Use embedding cosine similarity for continent matching instead of string Contains — 'Oceania' now correctly matches 'Australia/Oceania' - Generate continent embeddings at startup in DataService - Add all 4 screenshots: landmarks, trip planning, itinerary, chat - Update README: add screenshot gallery, Key files, Sample prompts sections to match structure of ChatClient and ChatClientWithTools samples Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…review.1.26161.6 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change [Length(1, 7)] to [Length(3, 3)] on Itinerary.Days to match reference sample and produce consistent 3-day itineraries from Apple Intelligence - Pin Microsoft.Maui.Essentials.AI to 10.0.50-preview.1.26158.1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix TaggingService double deserialization: use ChatResponse<T>.TryGetResult() instead of ToString() + JsonSerializer.Deserialize round-trip - Fix Windows app.manifest assemblyIdentity to match project name - Remove unused dotnet_bot.png template asset - Add Microsoft.Maui.Controls with $(MauiVersion) for CI compatibility - Use $(MauiVersion) for Microsoft.Maui.Controls.Maps Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add GlobalXmlns.cs registering all app namespaces with the global URI. Enable MauiAllowImplicitXmlnsDeclaration and EnablePreviewFeatures. Remove redundant xmlns declarations and type prefixes from all 18 XAML files (50 lines removed). Maps xmlns kept where needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The [Length(3,3)] attribute on Itinerary.Days forced exactly 3 days regardless of user selection (2-7). Changed to [Length(1,7)] to match the UI range.
66534ed to
84dbd72
Compare
�� Multi-Model Code Review -- PR #744 (LocalChatClientWithAgents)CI Status: ✅ All checks passing Consensus Findings (flagged by 2+ of 5 models)🟡 MODERATE -- Race condition: embeddings never awaited (5/5 consensus)File:
Fix: // Replace ContinueWith with direct chaining:
_embeddingsTask = _initializationTask.ContinueWith(_ => Task.Run(GenerateEmbeddingsAsync)).Unwrap();🟡 MODERATE --
|
Summary
Adds a new AI sample under
10.0/AI/LocalChatClientWithAgents/— a .NET MAUI Travel Planner app powered entirely by on-device Apple Intelligence. No cloud API keys or endpoints required.What it demonstrates
IChatClient) backed by Apple Intelligence on iOS/macCatalystMicrosoft.Agents.AI) with a 4-agent pipeline:NLEmbeddingGeneratorfor semantic landmark and continent searchApp flow
Architecture
Platform support
PlatformNotSupportedExceptionat startup)Key packages
Microsoft.Maui.Essentials.AI(dotnet10 preview feed)Microsoft.Agents.AI/Microsoft.Agents.AI.Hosting/Microsoft.Agents.AI.WorkflowsMicrosoft.Extensions.AI10.3.0CommunityToolkit.Mvvm8.4.0Structure
Follows the same folder structure as the existing
10.0/AI/ChatClientand10.0/AI/ChatClientWithToolssamples with README (frontmatter, screenshots, key files, sample prompts), images directory, and NuGet.config.