-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT]: send email & summary as email using slash command. #13
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
[FEAT]: send email & summary as email using slash command. #13
Conversation
… multiple languages
…ing and user notifications
…modal integration
…message retrieval and formatting
…N formatting in email content
@VipinDevelops PTAL |
…ality, add message configuration constants, and improve prompt formatting
// Retrieve stored email data | ||
const emailData = await this.getStoredEmailData(room.id); | ||
|
||
if (!emailData) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User should get a error message when these error's occur that explain what went wrong.
throw new Error('Email data not found'); | ||
} | ||
|
||
if (!triggerId) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for this too
} | ||
} | ||
|
||
public async ProcessNaturalLanguageQuery(query: string): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To many thing happening in this method refactor it to smaller chunks
src/handlers/Handler.ts
Outdated
|
||
fixedArguments = fixedArguments.replace(/("content"\s*:\s*")([^"]*)\n([^"]*?)(")/g, (match, start, content1, content2, end) => { | ||
const fixedContent = (content1 + content2).replace(/\n/g, '\\n').replace(/\r/g, '\\r'); | ||
return start + fixedContent + end; | ||
}); | ||
|
||
fixedArguments = fixedArguments.replace(/("content"\s*:\s*")([^"]*"[^"]*?)(")/g, (match, start, content, end) => { | ||
const fixedContent = content.replace(/"/g, '\\"'); | ||
return start + fixedContent + end; | ||
}); | ||
|
||
try { | ||
args = JSON.parse(fixedArguments); | ||
} catch (secondParseError) { | ||
resultMessageBuilder.setText(t(Translations.LLM_PARSING_ERROR, this.language)); | ||
return this.read.getNotifier().notifyUser(this.sender, resultMessageBuilder.getMessage()); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is this piece of code doing to many regex no explanation try to give me some example in comment its hard to understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have improved the prompt, now we dont need this regex in this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why is it still in code ?
src/handlers/Handler.ts
Outdated
} | ||
|
||
// Handle send-email and summarize-and-send-email tools with buttons instead of immediate modal | ||
if (toolCall.function.name === 'send-email' || toolCall.function.name === 'summarize-and-send-email') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use string use enums or type
src/handlers/Handler.ts
Outdated
if (toolCall.function.name === 'send-email' || toolCall.function.name === 'summarize-and-send-email') { | ||
let emailData: ISendEmailData; | ||
|
||
if (toolCall.function.name === 'send-email') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again no strings
src/handlers/Handler.ts
Outdated
} | ||
|
||
// Format messages for summarization | ||
const formattedMessages = messageService.formatMessagesForSummary(messages); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put all the formatted message thing in different file.
src/handlers/Handler.ts
Outdated
// Show simplified email ready message with buttons | ||
const block = this.modify.getCreator().getBlockBuilder(); | ||
|
||
const messageText = toolCall.function.name === 'summarize-and-send-email' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again no string
src/handlers/Handler.ts
Outdated
); | ||
|
||
// Create formatted message showing the tool execution result | ||
const block = this.modify.getCreator().getBlockBuilder(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this whole method is TOO long it should be a lot smaller divide this in different files and handlers
@priyanshuharshbodhi1 make the requested changes. |
…essage formatting, and additional translation constants for recipient display
…er and MessageFormatter classes
…rmatting interfaces, and enhance translation constants for improved user feedback
Hey @VipinDevelops PTAL! Screencast.from.2025-07-19.02-12-42.webm |
…andling with username extraction for display, and improve message formatting with avatars in SendEmailModal
I have updated the PR with changes you mentioned. |
We can improve the messages you show for AI thinking it should be just "thinking" Remove " AI response" from second message How you are handling cases when there would be alot of email and images ? There should be a threshold Like above 3 we only show images Current modal image UI might break in case of multiple mails |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR is improved but still needs some changes
@priyanshuharshbodhi1
src/constants/prompts.ts
Outdated
@@ -0,0 +1,157 @@ | |||
export const LlmPrompts = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really long prompt divided this into seperate parts to make it easy to use
Like one constant name response example so on after that spread it in here.
src/constants/prompts.ts
Outdated
|
||
--- | ||
|
||
CRITICAL JSON REQUIREMENTS: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be common in all AI prompt make a constant for this
src/handlers/Handler.ts
Outdated
messageBuilder.setText( | ||
t(Translations.ERROR_PROCESSING_LOGIN, this.language, { error: error.message }) | ||
); | ||
this.app.getLogger().error('Login processing error:', error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create a common error handlerand use that in all the places
src/handlers/Handler.ts
Outdated
this.app.getLogger().error('Logout preparation error:', error); | ||
|
||
// Provide user-friendly error message | ||
let userMessage: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Common error handler
src/handlers/Handler.ts
Outdated
@@ -351,7 +387,17 @@ export class Handler implements IHandler { | |||
.setRoom(this.room) | |||
.setGroupable(false); | |||
|
|||
messageBuilder.setText(t(Translations.CONFIG_ERROR, this.language, { error: error.message })); | |||
// Categorize error and provide user-friendly message |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same error handler
src/handlers/Handler.ts
Outdated
t(Translations.REPORT_ERROR, this.language, { error: error.message }) | ||
|
||
// Provide user-friendly error message based on error type | ||
let userMessage: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here as well
src/handlers/Handler.ts
Outdated
.setGroupable(false); | ||
|
||
// Provide specific error message based on error type | ||
let userMessage: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error thing
@VipinDevelops, PTAL, I have made all the changes. I will raise the "Change LLM" PR once you merge this one. Or make it draft one. |
… put comma in between
You can raise that PR right now and the branch of that can be from this branch similar to how we did previously |
Don't wait for Merges to make PR or stop working because of that PR will only get merged when its complete and tested. |
@@ -469,6 +469,7 @@ | |||
"version": "3.0.0-beta2", | |||
"resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.0.0-beta2.tgz", | |||
"integrity": "sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw==", | |||
"deprecated": "too old", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you installed new package or what why we have this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope. the authers of the package may have marked this version of package "too old" and thus it shows it here.
text: string; | ||
} | ||
|
||
export interface ISummarizeParams { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add comments why we have all things optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because, the query from user may or may not those fields:
- if it contains start and end date for conversation then LLM responds with those. in that case days will be optional
- if user mentioned
conversation from last 5 days
then LLM responds with 5 in days field. - if user didn't mentioned any date in the query then all three( days, start date, end date) would be empty and in that case app will just summarise last 25 messages in the channel or thread.
- for person, if user mentioned any person(s) in the query then app will only summarise messages of that person(s).
- if user mentioned like he wants the summary in bullet format then summary will be in bullett format. If nothing is mentioned then the summary will be generic
format?: 'bullet' | 'paragraph' | 'detailed' | 'brief'; | ||
} | ||
|
||
export interface ISummarizeAndSendEmailData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same for here
}; | ||
} | ||
|
||
export interface ILLMResponse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LLM response from different providers would be different right? you have to define for all the different provider you been using
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, this interface structure will be same for all LLMs.
// Get user's preferred email provider from their personal settings | ||
const data = await this.read.getPersistenceReader().readByAssociation(association); | ||
|
||
// Handle both array and single object responses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good are we handling any case in which LLM provide a response that don't fit any of the type swe defined because of hallucination
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its explicitely mentioned in the prompt that it should respond with only tool mentioned in the prompt and if no tool fits for the query enterd by user then app gives messsage: I can't understand your request. Please rewrite your query with more details.
If LLM halicunates and dont responds with plain text instead of json or incorrect json then it shows: LLM parse error
in message
Yes its done 90%. |
all the changes and comments resolved ? |
Description
This PR enables user to do following things:
send an email to any email address or any user(s) present on the workspace by tagging them in the slash commmand.
Ex:
/email send an congratulatory email to priyanshu@gmail.com
--> sends email to priyanshu@gmail.com/email send an congratulatory email to @priyanshu.harshbodhi and @sing.li
--> sends email to sing and priyanshu on their registered emails in RC(in case of more than 1 emails are verified of a user then mail will be send to all of those emails)User can summarise conversations in channel OR thread send it as email. User can also mention date range and which user's messages to summarise by tagging them)
Ex:
/email summarise the conversation between @sing.li and @priyanshu.harshbodhi in the last week and send it to @vipin.chaudhary
--> summarises the conversation between ONLY sing and priyanshu in last 7 days by extracting messages between only them and sends it email address of vipinUser can edit emails before sending it to recipient(s)
If user types anything which our app cant do or understand then iut shows error response:
Ex:
/email fhsd foo baar sdhsd
---> app replies: "I can't understand your request. Could you please rephrase it with more details?"Videos:
Screencast.from.2025-07-13.01-08-05.webm
Screencast.from.2025-07-13.01-06-10.webm
Screencast.from.2025-07-13.02-02-17.webm