Add Microsoft.Maui.AI.Navigation library with route-aware deep navigation#134
Draft
mattleibow wants to merge 29 commits into
Draft
Add Microsoft.Maui.AI.Navigation library with route-aware deep navigation#134mattleibow wants to merge 29 commits into
mattleibow wants to merge 29 commits into
Conversation
mattleibow
added a commit
that referenced
this pull request
Apr 23, 2026
Removed Microsoft.Maui.AI.Navigation library (belongs in PR #134). Restored modal Shell routes for catalog, orders, and cart pages. Navigation tools back on MainViewModel (navigate_to_page, dismiss_page). All pages are now navigable via: - Buttons: catalog items have Details/Add to Cart, orders tap to detail, product detail has Write Review and Add to Cart, order detail has Reorder and product taps - AI tools: navigate_to_page('catalog'/'orders'/'cart'), dismiss_page() - Back buttons on every modal page Pages use relative Shell routes (product?sku=X, review?sku=X, order?orderId=X) so they push on top of their parent modal naturally. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bb2c6c5 to
022e4a1
Compare
95722c3 to
5f2c661
Compare
Rebased onto latest main as a single commit. Includes: - Microsoft.Maui.AI.Attributes runtime library + source generator - IncludeTools/ExcludeTools filtering on [AIToolSource] - Assembly-wide auto-generated tool context - Property getter/setter tool support - 91 runtime tests + 116 generator tests - Garden Shop sample with chat, catalog, orders, reviews, cart modes - Expandable tool call details in chat UI - CI workflow (ci-ai.yml) + AzDO official pipeline job - NuGet package includes generator DLL in analyzers/ folder - Unique CI version suffix (ci.YYYYMMDD.N) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…tributes Separate AI Attributes from the Essentials AI directory (src/AI/) so each product has its own top-level folder: - src/AIAttributes/ — AI Attributes library + source generator - tests/AIAttributes/ — runtime and generator tests - src/AI/ — reserved for Essentials AI Update all ProjectReferences, solution filter, CI workflow, AzDO pipeline, MauiLabs.slnx, and README paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename src/AIAttributes → src/AIExtensions and tests/AIAttributes → tests/AIExtensions to reflect the broader scope of AI extension packages (AI.Navigation will join AI.Attributes under src/AIExtensions/). Rename sample folders and csproj files from AIAttributes.Sample.* to AIExtensions.Sample.* and update all namespaces, project references, CI paths, and documentation links. Project/assembly names (Microsoft.Maui.AI.Attributes) are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…1 compat Microsoft.Extensions.AI.OpenAI 10.4.1 requires OpenAI >= 2.9.1. The EssentialsAI sample was pinned at 2.6.0, causing CS1705 on CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the reflection-based schema generation (GetMethod/GetProperty + CreateFunctionJsonSchema) with per-parameter CreateJsonSchema calls that use the source-generated JsonSerializerOptions. This eliminates all MethodInfo/PropertyInfo lookups from the generated code. Change AIToolMetadataServices to accept JsonTypeInfo<T> instead of JsonSerializerOptions, making all argument deserialization AOT-safe. The generator now emits the concrete JsonTypeInfo<T> expression for each parameter. Mark Microsoft.Maui.AI.Attributes with IsTrimmable=true and IsAotCompatible=true — trim and AOT analyzers report zero warnings. Key changes: - Generator: emit per-parameter schema via AIJsonUtilities.CreateJsonSchema with explicit s_jsonOptions instead of reflection-based CreateFunctionJsonSchema(MethodInfo) - Generator: emit s_jsonOptions field using AIJsonUtilities.DefaultOptions - Generator: emit JsonTypeInfo<T> expressions for GetRequiredArg/GetOptionalArg - AIToolMetadataServices: replace JsonSerializerOptions? parameter with JsonTypeInfo<T> for type-safe, trim-safe deserialization - Runtime lib csproj: add IsTrimmable=true, IsAotCompatible=true - Remove System.Reflection using from generated output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The IsNullable flag incorrectly included '|| p.Type.IsReferenceType', causing all reference-type parameters (e.g. 'string name') to be treated as nullable. This meant non-nullable string parameters were never added to the JSON schema 'required' array, making the schema tell the LLM the param is optional while the runtime throws on missing values. Fix: use only NullableAnnotation.Annotated to determine nullability, matching C# nullable reference type semantics. Add two new schema tests verifying required array contents for both non-nullable reference types and value types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…and conversions - Add EnumParamService and CollectionParamService with tool contexts - Add 9 schema tests (enum, collection, optional, no-params, void return, multi-param, DI exclusion, CancellationToken exclusion) - Add 10 conversion edge case tests (enum, list, dict, DTO, JsonNode, nullable) - Add EnumParameter and CollectionParameter generator inputs - Add 4 generator compilation tests for enum/collection scenarios - Add enum/collection to AllValidInputs_CompileCleanly theory Test count: 110 runtime (was 93) + 122 generator (was 116) = 232 total Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Split the 1268-line AIToolContextGenerator.cs into focused files: - Models.cs (88 lines) — pipeline value types (enums + records) - Diagnostics.cs (74 lines) — diagnostic descriptors and factories - SymbolAnalysis.cs (682 lines) — Roslyn symbol extraction + constants - CodeEmitter.cs (312 lines) — source code generation + string helpers - AIToolContextGenerator.cs (137 lines) — slim entry point with Initialize() Pure structural refactor — generated output is byte-identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Gate user secrets embedding on Debug configuration only - Dispose secrets.json stream with 'using' in MauiProgram.cs - Uncomment NSPrivacyAccessedAPICategoryUserDefaults in privacy manifest - Add pull_request types [opened, synchronize, reopened, edited] to ci-ai.yml - Fix DIParameters README garbled sentence - Use explicit SDK version in AzDO AI build job (not useGlobalJson) - Pass actual argument name in AIToolMetadataServices exception - Add clarifying comment on README Remove path in csproj Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5f2c661 to
f302f4a
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the fragile None Remove path — PackRepoRootReadme=false already prevents Arcade from including the repo-root README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update CI workflow name, AzDO pipeline display names, README headers, and sample descriptions to use 'AI Extensions' — reflecting the broader product area that will include AI Navigation alongside AI Attributes. Package/assembly names (Microsoft.Maui.AI.Attributes) unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
022e4a1 to
5b93a1b
Compare
Make src/AIExtensions/README.md a concise landing page with a Packages table that can grow as new packages join (e.g. AI.Navigation). Move the code sample and detailed docs to the per-package NuGet README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t README Restructure so future packages (e.g. AI Navigation) can be added as sibling sub-headings under the AI Extensions section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Skip Xcode version validation repo-wide in Directory.Build.props. Add warning comment on the embedded user-secrets target explaining this is only acceptable for local-only developer samples. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ample New library: Microsoft.Maui.AI.Navigation - ShellNavigationService: runtime Shell route discovery, template-aware URI parsing (ParseRoute), multi-step GoToAsync navigation, BuildRoute helper - Query parameter discovery via [QueryProperty] reflection on pages and VMs - Package README with API docs, usage examples, and integration guide - 44 xUnit tests covering query parameters, BuildRoute, ParseRoute, and back-navigation stack correctness Garden sample updates: - AINavigationService wrapper bridging ShellNavigationService to [ExportAIFunction] - Replace hardcoded navigate_to_page/dismiss_page with route-aware navigate tool - Dynamic system prompt with discovered route table and template-style examples - Update csproj, MauiProgram, AppShell, ChatViewModel, MainViewModel Infrastructure: - Add AI.Navigation to MauiLabs.slnx and AIExtensions.slnf - Add AI Navigation row to AIExtensions product README - Add AI Navigation section to root README - Update Garden sample README with navigation tools and features Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
5b93a1b to
1eb5968
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ate prompts - Remove unused Title/Icon on ShellContent (tab bar is hidden) - Add descriptive comments on routes in AppShell.xaml and .cs - Document each AIToolSource pattern in GardenShopTools XML doc - Replace generic suggestion prompts with more demonstrative ones Cherry-picked from PR #134 — sample improvements independent of navigation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mattleibow/garden-deep-navigation # Conflicts: # samples/AIExtensions.Sample.Garden/AppShell.xaml.cs # samples/AIExtensions.Sample.Garden/ViewModels/Chat/ChatViewModel.cs
Replace ▼/▶ (U+25BC/25B6) expand/collapse toggle and › (U+203A) list chevron with FluentIcons.ChevronDown/ChevronRight glyphs. Unicode geometric symbols may not render on iOS with custom fonts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…appings The previous codepoints (U+E76C, U+E70D) were Segoe Fluent Icons values, not FluentSystemIcons-Filled. In this font: - U+E76C = leaf_three (not chevron_right) - U+E70D = heart_circle (not chevron_down) Correct codepoints from the bundled font: - U+F2B0 = ic_fluent_chevron_right_20_filled - U+F2A3 = ic_fluent_chevron_down_20_filled Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mattleibow/garden-deep-navigation
Add Android handler mapping to set BackgroundTintList to transparent, matching the existing iOS/MacCatalyst border removal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…mattleibow/garden-deep-navigation
jfversluis
pushed a commit
that referenced
this pull request
May 15, 2026
* Add Microsoft.Maui.AI.Attributes — source-generated AI tool bindings Rebased onto latest main as a single commit. Includes: - Microsoft.Maui.AI.Attributes runtime library + source generator - IncludeTools/ExcludeTools filtering on [AIToolSource] - Assembly-wide auto-generated tool context - Property getter/setter tool support - 91 runtime tests + 116 generator tests - Garden Shop sample with chat, catalog, orders, reviews, cart modes - Expandable tool call details in chat UI - CI workflow (ci-ai.yml) + AzDO official pipeline job - NuGet package includes generator DLL in analyzers/ folder - Unique CI version suffix (ci.YYYYMMDD.N) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move AI Attributes source to src/AIAttributes and tests to tests/AIAttributes Separate AI Attributes from the Essentials AI directory (src/AI/) so each product has its own top-level folder: - src/AIAttributes/ — AI Attributes library + source generator - tests/AIAttributes/ — runtime and generator tests - src/AI/ — reserved for Essentials AI Update all ProjectReferences, solution filter, CI workflow, AzDO pipeline, MauiLabs.slnx, and README paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restore src/AI/README.md from main Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename AIAttributes to AIExtensions across folders and samples Rename src/AIAttributes → src/AIExtensions and tests/AIAttributes → tests/AIExtensions to reflect the broader scope of AI extension packages (AI.Navigation will join AI.Attributes under src/AIExtensions/). Rename sample folders and csproj files from AIAttributes.Sample.* to AIExtensions.Sample.* and update all namespaces, project references, CI paths, and documentation links. Project/assembly names (Microsoft.Maui.AI.Attributes) are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump OpenAI package to 2.9.1 for Microsoft.Extensions.AI.OpenAI 10.4.1 compat Microsoft.Extensions.AI.OpenAI 10.4.1 requires OpenAI >= 2.9.1. The EssentialsAI sample was pinned at 2.6.0, causing CS1705 on CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove runtime reflection from generated tools for AOT/trim safety Replace the reflection-based schema generation (GetMethod/GetProperty + CreateFunctionJsonSchema) with per-parameter CreateJsonSchema calls that use the source-generated JsonSerializerOptions. This eliminates all MethodInfo/PropertyInfo lookups from the generated code. Change AIToolMetadataServices to accept JsonTypeInfo<T> instead of JsonSerializerOptions, making all argument deserialization AOT-safe. The generator now emits the concrete JsonTypeInfo<T> expression for each parameter. Mark Microsoft.Maui.AI.Attributes with IsTrimmable=true and IsAotCompatible=true — trim and AOT analyzers report zero warnings. Key changes: - Generator: emit per-parameter schema via AIJsonUtilities.CreateJsonSchema with explicit s_jsonOptions instead of reflection-based CreateFunctionJsonSchema(MethodInfo) - Generator: emit s_jsonOptions field using AIJsonUtilities.DefaultOptions - Generator: emit JsonTypeInfo<T> expressions for GetRequiredArg/GetOptionalArg - AIToolMetadataServices: replace JsonSerializerOptions? parameter with JsonTypeInfo<T> for type-safe, trim-safe deserialization - Runtime lib csproj: add IsTrimmable=true, IsAotCompatible=true - Remove System.Reflection using from generated output Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix non-nullable reference params missing from schema required array The IsNullable flag incorrectly included '|| p.Type.IsReferenceType', causing all reference-type parameters (e.g. 'string name') to be treated as nullable. This meant non-nullable string parameters were never added to the JSON schema 'required' array, making the schema tell the LLM the param is optional while the runtime throws on missing values. Fix: use only NullableAnnotation.Annotated to determine nullability, matching C# nullable reference type semantics. Add two new schema tests verifying required array contents for both non-nullable reference types and value types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add missing AI Attributes test cases for enums, collections, schema, and conversions - Add EnumParamService and CollectionParamService with tool contexts - Add 9 schema tests (enum, collection, optional, no-params, void return, multi-param, DI exclusion, CancellationToken exclusion) - Add 10 conversion edge case tests (enum, list, dict, DTO, JsonNode, nullable) - Add EnumParameter and CollectionParameter generator inputs - Add 4 generator compilation tests for enum/collection scenarios - Add enum/collection to AllValidInputs_CompileCleanly theory Test count: 110 runtime (was 93) + 122 generator (was 116) = 232 total Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Refactor generator into separate files for maintainability Split the 1268-line AIToolContextGenerator.cs into focused files: - Models.cs (88 lines) — pipeline value types (enums + records) - Diagnostics.cs (74 lines) — diagnostic descriptors and factories - SymbolAnalysis.cs (682 lines) — Roslyn symbol extraction + constants - CodeEmitter.cs (312 lines) — source code generation + string helpers - AIToolContextGenerator.cs (137 lines) — slim entry point with Initialize() Pure structural refactor — generated output is byte-identical. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Apply dotnet format Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review comments - Gate user secrets embedding on Debug configuration only - Dispose secrets.json stream with 'using' in MauiProgram.cs - Uncomment NSPrivacyAccessedAPICategoryUserDefaults in privacy manifest - Add pull_request types [opened, synchronize, reopened, edited] to ci-ai.yml - Fix DIParameters README garbled sentence - Use explicit SDK version in AzDO AI build job (not useGlobalJson) - Pass actual argument name in AIToolMetadataServices exception - Add clarifying comment on README Remove path in csproj Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Revert Debug-only gate on user secrets — sample app only Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Simplify csproj README packing to match EssentialsAI pattern Remove the fragile None Remove path — PackRepoRootReadme=false already prevents Arcade from including the repo-root README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename AI Attributes branding to AI Extensions across display names Update CI workflow name, AzDO pipeline display names, README headers, and sample descriptions to use 'AI Extensions' — reflecting the broader product area that will include AI Navigation alongside AI Attributes. Package/assembly names (Microsoft.Maui.AI.Attributes) unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Restructure AIExtensions README as product-area landing page Make src/AIExtensions/README.md a concise landing page with a Packages table that can grow as new packages join (e.g. AI.Navigation). Move the code sample and detailed docs to the per-package NuGet README. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Make AI Extensions a heading with AI Attributes as sub-heading in root README Restructure so future packages (e.g. AI Navigation) can be added as sibling sub-headings under the AI Extensions section. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename publishAINuget to publishAIExtensionsNuget in AzDO pipeline Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix link text in AIExtensions README Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add ValidateXcodeVersion=false and secrets warning comment Skip Xcode version validation repo-wide in Directory.Build.props. Add warning comment on the embedded user-secrets target explaining this is only acceptable for local-only developer samples. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve Garden sample: clean up AppShell, document tool patterns, update prompts - Remove unused Title/Icon on ShellContent (tab bar is hidden) - Add descriptive comments on routes in AppShell.xaml and .cs - Document each AIToolSource pattern in GardenShopTools XML doc - Replace generic suggestion prompts with more demonstrative ones Cherry-picked from PR #134 — sample improvements independent of navigation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Replace Unicode arrows with Fluent icons in Garden sample Replace ▼/▶ (U+25BC/25B6) expand/collapse toggle and › (U+203A) list chevron with FluentIcons.ChevronDown/ChevronRight glyphs. Unicode geometric symbols may not render on iOS with custom fonts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix Fluent chevron codepoints — use actual FluentSystemIcons-Filled mappings The previous codepoints (U+E76C, U+E70D) were Segoe Fluent Icons values, not FluentSystemIcons-Filled. In this font: - U+E76C = leaf_three (not chevron_right) - U+E70D = heart_circle (not chevron_down) Correct codepoints from the bundled font: - U+F2B0 = ic_fluent_chevron_right_20_filled - U+F2A3 = ic_fluent_chevron_down_20_filled Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove Android Entry underline in Garden chat input Add Android handler mapping to set BackgroundTintList to transparent, matching the existing iOS/MacCatalyst border removal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Move Entry border removal into ConfigureMauiHandlers builder chain Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix review issues: HasDetails binding, Xcode scope, dead diagnostic - Fix ChatMessageViewModel: add [NotifyPropertyChangedFor(nameof(HasDetails))] to ToolResult so HasDetails updates when tool results arrive. Remove the incorrect OnPropertyChanged call on ChatViewModel that fired for a property it doesn't own. - Scope ValidateXcodeVersion=false to the Garden sample only (was global). - Remove dead MAUIAI005 diagnostic (IncludeAndExcludeBothSet) — by design, IncludeTools and ExcludeTools compose and are both allowed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
Microsoft.Maui.AI.Navigation— a new package under AI Extensions for runtime Shell route discovery and template-aware navigation. Integrates it into the Garden sample, replacing hardcoded navigation tools with route-aware AI tools.New package:
Microsoft.Maui.AI.NavigationA dependency-free MAUI library (no AI.Attributes dependency) that discovers Shell routes at runtime and provides template-style URI navigation.
ShellNavigationServiceGetRoutes()Routing.RegisterRouteentries to discover routes and[QueryProperty]parametersGetCurrentRoute()Shell.CurrentState.LocationNavigateAsync(route)//main/products/product/seed-tomato/review, splits into sequentialGoToAsynccalls with extracted query paramsBuildRoute(base, segments, params)ParseRoute(uri)Template-style URIs
The AI writes clean URIs with parameter values inline in the path:
ParseRoutematches path segments against known routes, treats unknown segments after parameterized routes as inline parameter values, and produces sequentialGoToAsyncsteps with proper query strings. The first step is absolute; subsequent steps are relative — so back-navigation (..) pops to the correct parent.Tests
44 xUnit tests covering: query parameter discovery,
BuildRoute,ParseRoute(hierarchy routes, inline params, nested routes, relative routes, explicit query strings, URL encoding, back-navigation stack correctness, parameter propagation, valid URI invariant).Garden sample integration
AINavigationService— thin wrapper adding[ExportAIFunction]toShellNavigationService, bridging AI.Attributes and the dependency-free library. Exposesget_routes,get_current_route,navigate.ChatViewModel.BuildSystemPrompt()callsGetRoutes()at session start and injects the discovered route table into the prompt. No hardcoded routes.MainViewModel— removednavigate_to_pageanddismiss_pageAI tools (replaced byAINavigationService).AppShell— route registration comments now document the URI structure.MauiProgram— registersShellNavigationServiceandAINavigationServiceas singletons.Infrastructure
Microsoft.Maui.AI.NavigationtoMauiLabs.slnxandAIExtensions.slnfsrc/AIExtensions/README.mdwith new package rowREADME.mdwith AI Navigation sectionREADME.mdwith navigation tools and featuresmattleibow/ai-annotationstoci-ai.ymltriggers for stacked PR CI