Skip to content

Phase 1: Add AppChat sessions powered by on-device SLM#204

Draft
mattleibow wants to merge 13 commits intomainfrom
feature/phase1-appchat
Draft

Phase 1: Add AppChat sessions powered by on-device SLM#204
mattleibow wants to merge 13 commits intomainfrom
feature/phase1-appchat

Conversation

@mattleibow
Copy link
Collaborator

@mattleibow mattleibow commented Feb 24, 2026

Implement local AI-powered chat sessions using Microsoft.Extensions.AI and Microsoft Agent Framework. AppChat sessions appear alongside Copilot sessions in the sidebar with distinct visual treatment.

New files:

Key changes:

  • SessionState.Session is now nullable (CopilotSession?)
  • AgentSessionInfo gains Kind property (defaults to Copilot)
  • CopilotService routes SendPromptAsync by SessionKind
  • MauiProgram registers keyed 'local' IChatClient pipeline
  • ExpandedSessionView hides Copilot-only controls for AppChat (Fiesta, ReflectionCycle, Plan/Autopilot, model selector)
  • Sidebar gets '✨ App Chat' button in both desktop and flyout

Found a bug: dotnet/maui#34124

@mattleibow mattleibow force-pushed the feature/phase1-appchat branch from 843eb87 to 939eff9 Compare February 24, 2026 16:25
- Revert SessionKind enum, nullable CopilotSession, and routing changes
- Revert ExpandedSessionView/SessionSidebar AppChat integration
- Create AppChatPopover.razor — floating overlay with ChatMessageList reuse
- Add ✨ FAB toggle in MainLayout
- Keep AI services: DirectLocalChatService, AppChatTools, NonFunctionInvokingChatClient
- Remove Kind reference from AppChatTools (SessionKind deleted)
- 610 tests passing, build clean

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mattleibow mattleibow force-pushed the feature/phase1-appchat branch from 939eff9 to 1d7995b Compare February 24, 2026 18:21
mattleibow and others added 12 commits February 24, 2026 20:26
…Dashboard sync

The tool was calling SetActiveSession which only sets the name, but the
Dashboard's expandedSession local state wasn't updating. Now uses
SwitchSession + SaveUiState (matching sidebar's SelectSession pattern)
so the Dashboard picks up the expanded session correctly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The RefreshState else-if guard required expandedSession != null, which
meant switching from grid view (expandedSession == null) never expanded
the target session. Removed the null guard so the active session always
expands when changed programmatically (matching sidebar behavior).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add switchKeepAliveSlot JS call in RefreshState sync path so the
  main pane actually switches when active session changes programmatically
- Remove collapsible header from AppChatPopover (toggle via header button)
- Remove close button and OnClose callback (header button toggles)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… programmatic switch

Two bugs fixed:

1. NonFunctionInvokingChatClient: Apple Intelligence crashes on
   FunctionCallContent in conversation history from previous turns.
   Added StripToolContent() to filter these from input messages before
   they reach the Apple Intelligence client.

2. Dashboard RefreshState: the sessionSwitched path didn't call
   switchKeepAliveSlot JS because it assumed the capture-phase click
   handler already did it. Programmatic switches (from tools) have no
   click event, so the main pane slot never toggled. Added the JS call
   to both the sessionSwitched and sync paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add onToolStart/onToolEnd callbacks to DirectLocalChatService
- Track ToolActivity list and CurrentToolName in AppChatPopover
- Pass ToolActivities and CurrentToolName to ChatMessageList
- Tool calls now show the same expandable activity indicators as main chat

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Tool calls now appear as expandable messages in the chat history
  (ToolCallMessage on start, marked complete with result on end)
- Fix horizontal scroll: overflow-x hidden on body, pre-wrap on code
  blocks, word-break on message text

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- onToolStart now passes arguments JSON (3rd param)
- ToolCallMessage created with args so tapping shows input
- Tool result stored as full Content (no truncation) for expandable view
- ToolActivity.Input populated for activity display

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Compact=true was rendering tool calls as simple one-liners without
expandable args/output. Set Compact=false to use the same action-box
rendering as the main chat with clickable headers, args, and output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve conflicts keeping both AppChat and Statistics/info-popover features.
Update Microsoft.Maui.Essentials.AI to 10.0.50-ci.main.26153.3.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MEAI now handles Apple Intelligence tool calls natively without the
double-invocation workaround (dotnet/extensions#7204 resolved).
Matches the updated MAUI AI sample which also removed this class.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Switch ChatMessageList to Compact=true for condensed message rendering
  suitable for large tool call messages in the small popover
- Increase popover width from 380px to 520px
- Switch max-height from fixed 560px to 72vh (viewport-relative)
- Update appchat-body max-height to match (calc(72vh - 100px))

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant