-
Notifications
You must be signed in to change notification settings - Fork 43
Introducing Playground notification handling in Perplexity agent #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
aubreyquinn
merged 8 commits into
main
from
users/aubreyquinn/perplexity-playground-notifications
Nov 13, 2025
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
66e9ff0
Introducing playground notification handling in Perplexity agent
9ec07e0
Introducing playground Teams messaging notification handling in Perpl…
7cea376
applying changes from code review
3fddabb
Apply suggestion from @Copilot
aubreyquinn 813ced4
applying changes from code review
d1636ea
Merge branch 'users/aubreyquinn/perplexity-playground-notifications' …
21c6e29
Add missing copyright header to playgroundActivityTypes.ts (#36)
Copilot 5b4a0f3
Add copyright header to playgroundActivityTypes.ts (#35)
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,36 +1,227 @@ | ||
| import { TurnState, AgentApplication, AttachmentDownloader, MemoryStorage, TurnContext } from '@microsoft/agents-hosting'; | ||
| import { ActivityTypes } from '@microsoft/agents-activity'; | ||
| import { AgentNotificationActivity } from '@microsoft/agents-a365-notifications'; | ||
| import { PerplexityAgent } from './perplexityAgent.js'; | ||
| // Copyright (c) Microsoft Corporation. | ||
| // Licensed under the MIT License. | ||
|
|
||
| import { | ||
| TurnState, | ||
| AgentApplication, | ||
| AttachmentDownloader, | ||
| MemoryStorage, | ||
| TurnContext, | ||
| } from "@microsoft/agents-hosting"; | ||
| import { Activity, ActivityTypes } from "@microsoft/agents-activity"; | ||
| import { AgentNotificationActivity } from "@microsoft/agents-a365-notifications"; | ||
| import { PerplexityAgent } from "./perplexityAgent.js"; | ||
| import { | ||
| MentionInWordValue, | ||
| PlaygroundActivityTypes, | ||
| SendEmailActivity, | ||
| SendTeamsMessageActivity, | ||
| } from "./playgroundActivityTypes.js"; | ||
|
|
||
| /** | ||
| * Conversation state interface for tracking message count. | ||
| */ | ||
| interface ConversationState { | ||
| count: number; | ||
| } | ||
| type ApplicationTurnState = TurnState<ConversationState> | ||
|
|
||
| const downloader = new AttachmentDownloader(); | ||
| const storage = new MemoryStorage(); | ||
| /** | ||
| * ApplicationTurnState combines TurnState with our ConversationState. | ||
| */ | ||
| type ApplicationTurnState = TurnState<ConversationState>; | ||
|
|
||
| /** | ||
| * Instantiate the AttachmentDownloader. | ||
| */ | ||
| const downloader: AttachmentDownloader = new AttachmentDownloader(); | ||
|
|
||
| /** | ||
| * Instantiate the MemoryStorage. | ||
| */ | ||
| const storage: MemoryStorage = new MemoryStorage(); | ||
|
|
||
| /** | ||
| * Create the Agent Application instance with typed state. | ||
| */ | ||
| export const agentApplication: AgentApplication<ApplicationTurnState> = | ||
| new AgentApplication<ApplicationTurnState>({ | ||
| storage, | ||
| fileDownloaders: [downloader], | ||
| }); | ||
|
|
||
| /** | ||
| * Instantiate the PerplexityAgent. | ||
| */ | ||
| const perplexityAgent: PerplexityAgent = new PerplexityAgent(undefined); | ||
|
|
||
| /* -------------------------------------------------------------------- | ||
| * ✅ Real Notification Events (Production) | ||
| * These handlers process structured AgentNotificationActivity objects | ||
| * sent by Microsoft 365 workloads (Word, Outlook, etc.) in production. | ||
| * -------------------------------------------------------------------- */ | ||
|
|
||
| /** | ||
| * Handles ALL real notification events from any workload. | ||
| * Fires when an AgentNotificationActivity is received. | ||
| * Use this for generic notification handling logic. | ||
| */ | ||
| agentApplication.onAgentNotification( | ||
| "*", | ||
| async ( | ||
| context: TurnContext, | ||
| state: ApplicationTurnState, | ||
| activity: AgentNotificationActivity | ||
| ): Promise<void> => { | ||
| await perplexityAgent.handleAgentNotificationActivity( | ||
| context, | ||
| state, | ||
| activity | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * Handles Word-specific notifications (e.g., comments, mentions in Word). | ||
| * Fires only for AgentNotificationActivity originating from Word. | ||
| */ | ||
| agentApplication.onAgenticWordNotification( | ||
| async ( | ||
| context: TurnContext, | ||
| state: ApplicationTurnState, | ||
| activity: AgentNotificationActivity | ||
| ): Promise<void> => { | ||
| await perplexityAgent.handleAgentNotificationActivity( | ||
| context, | ||
| state, | ||
| activity | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * Handles Email-specific notifications (e.g., new mail, flagged items). | ||
| * Fires only for AgentNotificationActivity originating from Outlook/Email. | ||
| */ | ||
| agentApplication.onAgenticEmailNotification( | ||
| async ( | ||
| context: TurnContext, | ||
| state: ApplicationTurnState, | ||
| activity: AgentNotificationActivity | ||
| ): Promise<void> => { | ||
| await perplexityAgent.handleAgentNotificationActivity( | ||
| context, | ||
| state, | ||
| activity | ||
| ); | ||
| } | ||
| ); | ||
|
|
||
| /* -------------------------------------------------------------------- | ||
| * ✅ Playground Events (Simulated for Testing) | ||
| * These handlers process custom activityType strings sent via sendActivity() | ||
| * from the Playground UI. They DO NOT trigger real notification handlers. | ||
| * -------------------------------------------------------------------- */ | ||
|
|
||
| /** | ||
| * Handles simulated Word mention notifications. | ||
| * activityType: "mentionInWord" | ||
| * Useful for testing Word-related scenarios without real notifications. | ||
| */ | ||
| agentApplication.onActivity( | ||
| PlaygroundActivityTypes.MentionInWord, | ||
| async (context: TurnContext, _state: ApplicationTurnState): Promise<void> => { | ||
| const value: MentionInWordValue = context.activity | ||
| .value as MentionInWordValue; | ||
| const docName: string = value.mention.displayName; | ||
| const docUrl: string = value.docUrl; | ||
| const userName: string = value.mention.userPrincipalName; | ||
| const contextSnippet: string = value.context | ||
| ? `Context: ${value.context}` | ||
| : ""; | ||
| const message: string = `✅ You were mentioned in **${docName}** by ${userName}\n📄 ${docUrl}\n${contextSnippet}`; | ||
|
aubreyquinn marked this conversation as resolved.
|
||
| await context.sendActivity(message); | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * Handles simulated Email notifications. | ||
| * activityType: "sendEmail" | ||
| * Useful for testing email scenarios without real notifications. | ||
| */ | ||
| agentApplication.onActivity( | ||
| PlaygroundActivityTypes.SendEmail, | ||
| async (context: TurnContext, _state: ApplicationTurnState): Promise<void> => { | ||
| const activity: SendEmailActivity = context.activity as SendEmailActivity; | ||
| const email = activity.value; | ||
|
|
||
| const message: string = `📧 Email Notification: | ||
| From: ${email.from} | ||
| To: ${email.to.join(", ")} | ||
| Subject: ${email.subject} | ||
| Body: ${email.body}`; | ||
|
|
||
| await context.sendActivity(message); | ||
| } | ||
| ); | ||
|
|
||
| /** | ||
| * Handles simulated Teams message notifications. | ||
| * activityType: "sendTeamsMessage" | ||
| * Useful for testing Teams messaging scenarios without real notifications. | ||
| */ | ||
| agentApplication.onActivity( | ||
| PlaygroundActivityTypes.SendTeamsMessage, | ||
| async (context: TurnContext, _state: ApplicationTurnState): Promise<void> => { | ||
| const activity = context.activity as SendTeamsMessageActivity; | ||
| const message = `💬 Teams Message: ${activity.value.text} (Scope: ${activity.value.destination.scope})`; | ||
| await context.sendActivity(message); | ||
| } | ||
| ); | ||
|
|
||
| export const agentApplication = new AgentApplication<ApplicationTurnState>({ | ||
| storage, | ||
| fileDownloaders: [downloader] | ||
| }); | ||
| /** | ||
| * Handles a generic custom notification. | ||
| * Custom activityType: "custom" | ||
| * ✅ To add more custom activities: | ||
| * - Define a new handler using agentApplication.onActivity("<yourType>", ...) | ||
| * - Implement logic similar to this block. | ||
| */ | ||
| agentApplication.onActivity( | ||
| PlaygroundActivityTypes.Custom, | ||
| async (context: TurnContext, _state: ApplicationTurnState): Promise<void> => { | ||
| await context.sendActivity("this is a custom activity handler"); | ||
| } | ||
| ); | ||
|
|
||
| const perplexityAgent = new PerplexityAgent(undefined); | ||
| /* -------------------------------------------------------------------- | ||
| * ✅ Generic Activity Handlers | ||
| * These handle standard activity types like messages or installation updates. | ||
| * -------------------------------------------------------------------- */ | ||
|
|
||
| // Route agent notifications | ||
| agentApplication.onAgentNotification("*", async (context: TurnContext, state: ApplicationTurnState, activity: AgentNotificationActivity) => { | ||
| await perplexityAgent.handleAgentNotificationActivity(context, state, activity); | ||
| }); | ||
| /** | ||
| * Handles standard message activities (ActivityTypes.Message). | ||
| * Increments conversation count and delegates to PerplexityAgent. | ||
| */ | ||
| agentApplication.onActivity( | ||
| ActivityTypes.Message, | ||
| async (context: TurnContext, state: ApplicationTurnState): Promise<void> => { | ||
| let count: number = state.conversation.count ?? 0; | ||
| state.conversation.count = ++count; | ||
|
|
||
| agentApplication.onActivity(ActivityTypes.Message, async (context: TurnContext, state: ApplicationTurnState) => { | ||
| // Increment count state | ||
| let count = state.conversation.count ?? 0; | ||
| state.conversation.count = ++count; | ||
| await context.sendActivity( | ||
| Activity.fromObject({ type: ActivityTypes.Typing }) | ||
| ); | ||
|
|
||
| await perplexityAgent.handleAgentMessageActivity(context, state); | ||
| }); | ||
| await perplexityAgent.handleAgentMessageActivity(context, state); | ||
| } | ||
| ); | ||
|
|
||
| agentApplication.onActivity(ActivityTypes.InstallationUpdate, async (context: TurnContext, state: ApplicationTurnState) => { | ||
| await perplexityAgent.handleInstallationUpdateActivity(context, state); | ||
| }); | ||
| /** | ||
| * Handles installation update activities (ActivityTypes.InstallationUpdate). | ||
| * Useful for responding to app installation or update events. | ||
| */ | ||
| agentApplication.onActivity( | ||
| ActivityTypes.InstallationUpdate, | ||
| async (context: TurnContext, state: ApplicationTurnState): Promise<void> => { | ||
| await perplexityAgent.handleInstallationUpdateActivity(context, state); | ||
| } | ||
| ); | ||
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
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.