Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions server/ai/agentPrompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1208,16 +1208,16 @@ export const agentSearchQueryPrompt = (
- "Documents from last month" → sortDirection: null (no clear direction specified)
- "Find my budget documents" → sortDirection: null (no sorting direction implied)

6. Extract email addresses and main intent from the query:
6. Extract email addresses and main mailParticipants from the query:

**CRITICAL RULES for Email Intent Extraction:**
- DO NOT extract intent for queries like: "give me all emails", "show me emails", "list my emails", "get emails"
- EXTRACT intent for queries with person names OR email addresses OR organization names:
**CRITICAL RULES for Email MailParticipants Extraction:**
- DO NOT extract mailParticipants for queries like: "give me all emails", "show me emails", "list my emails", "get emails"
- EXTRACT mailParticipants for queries with person names OR email addresses OR organization names:
- Person names: "emails from John", "messages from Sarah", "emails from prateek"
- Email addresses: "emails from john@company.com", "messages from user@domain.com"
- Organization names: "emails from OpenAI", "messages from Linear", "emails from Google"
- Specific subjects: "emails with subject 'meeting'"
- If the query is asking for ALL items without specific criteria, return empty intent object: {}
- If the query is asking for ALL items without specific criteria, return empty mailParticipants object: {}

**Email Address, Name, and Organization Detection Rules:**
- DETECT and EXTRACT ALL valid email patterns, person names, AND organization names:
Expand All @@ -1243,8 +1243,8 @@ export const agentSearchQueryPrompt = (
- Extract ALL email addresses, person names, AND organization names - the system will resolve names to emails later while preserving existing email addresses

For other apps/entities:
- Currently no specific intent fields defined
- Return empty intent object: {}
- Currently no specific mailParticipants fields defined
- Return empty mailParticipants object: {}

**FILTERQUERY EXTRACTION RULES:**

Expand Down Expand Up @@ -1418,15 +1418,15 @@ export const agentSearchQueryPrompt = (
"startTime": "<start time in ${config.llmTimeFormat}, if applicable, or null>",
"endTime": "<end time in ${config.llmTimeFormat}, if applicable, or null>",
"sortDirection": "<'asc' | 'desc' | null>",
"intent": {}
"mailParticipants": {}
}
}
- "answer" should only contain a conversational response if it's a greeting, conversational statement, or basic calculation. Otherwise, "answer" must be null.
- "queryRewrite" should contain the fully resolved query only if there was ambiguity or lack of context. Otherwise, "queryRewrite" must be null.
- "temporalDirection" should be "next" if the query asks about upcoming calendar events/meetings, and "prev" if it refers to past calendar events/meetings. Use null for all non-calendar queries.
- "filterQuery" contains the main search keywords extracted from the user's query. Set to null if no specific content keywords remain after filtering.
- "type" and "filters" are used for routing and fetching data.
- "intent" is an object that contains specific intent fields based on the app/entity detected.
- "mailParticipants" is an object that contains specific mailParticipants fields based on the app/entity detected.
- "sortDirection" can be "asc", "desc", or null. Use null when no clear sorting direction is specified or implied in the query.
- "apps" and "entities" should always be arrays when values are present. For single app/entity, use single-element arrays like ["Gmail"]. Set to null if no apps/entities are detected.
- If the query references an entity whose data is not available, set all filter fields (app, entity, count, startTime, endTime) to null.
Expand Down
25 changes: 12 additions & 13 deletions server/ai/prompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1361,11 +1361,11 @@ export const searchQueryPrompt = (
- For Google Workspace queries (contacts), always set "temporalDirection" to null
- Only set "temporalDirection" to "next" or "prev" when the query is specifically about calendar events/meetings

11. **INTENT EXTRACTION (for specific app/entity queries):**
- Extract intent fields ONLY when the user specifies SPECIFIC CRITERIA in their query
- ONLY extract intent when there are EXPLICIT FILTERING CRITERIA mentioned
11. **MailParticipants EXTRACTION (for specific app/entity queries):**
- Extract mailParticipants fields ONLY when the user specifies SPECIFIC CRITERIA in their query
- ONLY extract mailParticipants when there are EXPLICIT FILTERING CRITERIA mentioned

**Intent field mapping by app/entity:**
**mailParticipants field mapping by app/entity:**

For ${Apps.Gmail} with ${MailEntity.Email}:
- **Email Address Extraction**: ONLY extract when specific EMAIL ADDRESSES are mentioned:
Expand All @@ -1376,14 +1376,14 @@ export const searchQueryPrompt = (
- **Subject/Title Extraction**: ONLY extract when specific subject/topic keywords are mentioned:
- "subject"/"title"/"about" queries with specific content (e.g., "emails about 'meeting notes'", "subject contains 'project update'") → extract the specific keywords to "subject" array

**CRITICAL RULES for Intent Extraction:**
- DO NOT extract intent for queries like: "give me all emails", "show me emails", "list my emails", "get emails"
- EXTRACT intent for queries with person names OR email addresses OR organization names:
**CRITICAL RULES for mailParticipants Extraction:**
- DO NOT extract mailParticipants for queries like: "give me all emails", "show me emails", "list my emails", "get emails"
- EXTRACT mailParticipants for queries with person names OR email addresses OR organization names:
- Person names: "emails from John", "messages from Sarah", "emails from prateek"
- Email addresses: "emails from john@company.com", "messages from user@domain.com"
- Organization names: "emails from OpenAI", "messages from Linear", "emails from Google"
- Specific subjects: "emails with subject 'meeting'"
- If the query is asking for ALL items without specific criteria, return empty intent object: {}
- If the query is asking for ALL items without specific criteria, return empty mailParticipants object: {}

**Email Address, Name, and Organization Detection Rules:**
- DETECT and EXTRACT ALL valid email patterns, person names, AND organization names:
Expand All @@ -1409,8 +1409,8 @@ export const searchQueryPrompt = (
- Extract ALL email addresses, person names, AND organization names - the system will resolve names to emails later while preserving existing email addresses

For other apps/entities:
- Currently no specific intent fields defined
- Return empty intent object: {}
- Currently no specific mailParticipants fields defined
- Return empty mailParticipants object: {}


12. Output JSON in the following structure:
Expand All @@ -1429,7 +1429,7 @@ export const searchQueryPrompt = (
"startTime": "<start time in ${config.llmTimeFormat}, if applicable, or null>",
"endTime": "<end time in ${config.llmTimeFormat}, if applicable, or null>",
"sortDirection": "<'asc' | 'desc' | null>",
"intent": {}
"mailParticipants": {}
}
}
- "answer" should only contain a conversational response if it's a greeting, conversational statement, or basic calculation. Otherwise, "answer" must be null.
Expand All @@ -1438,7 +1438,7 @@ export const searchQueryPrompt = (
- "filterQuery" contains the main search keywords extracted from the user's query. Set to null if no specific content keywords remain after filtering.
- "type" and "filters" are used for routing and fetching data.
- "sortDirection" can be "asc", "desc", or null. Use null when no clear sorting direction is specified or implied in the query.
- "intent" is an object that contains specific intent fields based on the app/entity detected.
- "mailParticipants" is an object that contains specific mailParticipants fields based on the app/entity detected.
- "apps" and "entities" should always be arrays when values are present. For single app/entity, use single-element arrays like ["Gmail"]. Set to null if no apps/entities are detected.
- If the query references an entity whose data is not available, set all filter fields (app, entity, count, startTime, endTime) to null.
- ONLY GIVE THE JSON OUTPUT, DO NOT EXPLAIN OR DISCUSS THE JSON STRUCTURE. MAKE SURE TO GIVE ALL THE FIELDS.
Expand Down Expand Up @@ -2434,4 +2434,3 @@ Without these connections, I can only provide general assistance and cannot acce

Ensure that any mention of dates or times is expressed in the user's local time zone. Always respect the user's time zone.
I'm still here to help with general questions, explanations, and tasks that don't require access to your personal workspace data. How can I assist you today?`

29 changes: 16 additions & 13 deletions server/ai/provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import type {
ChainBreakClassifications,
ConverseResponse,
Cost,
Intent,
MailParticipant,
LLMProvider,
ModelParams,
QueryRouterLLMResponse,
Expand Down Expand Up @@ -431,7 +431,6 @@ export const getAISDKProviderByModel = (modelId: Models): ProviderV2 => {
: VertexProjectId && VertexRegion
? AIProviders.VertexAI
: null

switch (providerType) {
case AIProviders.VertexAI: {
if (!VertexProjectId || !VertexRegion) {
Expand Down Expand Up @@ -855,7 +854,7 @@ export const generateTitleUsingQuery = async (

params.json = true
Logger.info("inside generateTitleUsingQuery")
if(assistantResponse === undefined){
if (assistantResponse === undefined) {
assistantResponse = ""
}

Expand Down Expand Up @@ -1204,7 +1203,7 @@ export const baselineRAGJson = async (
userCtx,
retrievedCtx,
parseAgentPrompt(params.agentPrompt),
dateForAI
dateForAI,
)
} else {
params.systemPrompt = baselinePromptJson(userCtx, retrievedCtx, dateForAI)
Expand Down Expand Up @@ -1386,10 +1385,14 @@ export const temporalPromptJsonStream = (
userCtx,
retrievedCtx,
parseAgentPrompt(params.agentPrompt),
dateForAI
dateForAI,
)
} else {
params.systemPrompt = temporalDirectionJsonPrompt(userCtx, retrievedCtx, dateForAI)
params.systemPrompt = temporalDirectionJsonPrompt(
userCtx,
retrievedCtx,
dateForAI,
)
}
params.json = true
const baseMessage = {
Expand Down Expand Up @@ -1597,7 +1600,7 @@ export async function generateToolSelectionOutput(
reasoning?: string | null
} | null> {
params.json = true
const dateForAI = getDateForAI({userTimeZone: "Asia/Kolkata"})
const dateForAI = getDateForAI({ userTimeZone: "Asia/Kolkata" })

let defaultReasoning = isReasoning
params.systemPrompt = SearchQueryToolContextPrompt(
Expand Down Expand Up @@ -1753,7 +1756,7 @@ export function generateSynthesisBasedOnToolOutput(
userCtx,
currentMessage,
gatheredFragments,
dateForAI
dateForAI,
)

const baseMessage = {
Expand Down Expand Up @@ -1873,16 +1876,16 @@ export const generateFallback = async (
}

export const extractEmailsFromContext = async (
names: Intent,
names: MailParticipant,
userCtx: string,
retrievedCtx: string,
params: ModelParams,
): Promise<{ emails: Intent }> => {
): Promise<{ emails: MailParticipant }> => {
if (!params.modelId) {
params.modelId = defaultFastModel
}

const intentNames =
const participants =
[
...(names.from?.length ? [`From: ${names.from.join(", ")}`] : []),
...(names.to?.length ? [`To: ${names.to.join(", ")}`] : []),
Expand All @@ -1893,7 +1896,7 @@ export const extractEmailsFromContext = async (
params.systemPrompt = nameToEmailResolutionPrompt(
userCtx,
retrievedCtx,
intentNames,
participants,
names,
)
params.json = false
Expand All @@ -1902,7 +1905,7 @@ export const extractEmailsFromContext = async (
role: ConversationRole.USER,
content: [
{
text: `Help me find emails for these names: ${intentNames}`,
text: `Help me find emails for these names: ${participants}`,
},
],
}
Expand Down
6 changes: 3 additions & 3 deletions server/ai/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,15 +382,15 @@ export const ToolAnswerResponse = z.object({
})

// Intent Schema - only includes fields with actual values (modular for different apps)
export const IntentSchema = z.object({
export const MailParticipantSchema = z.object({
from: z.array(z.string()).optional(),
to: z.array(z.string()).optional(),
cc: z.array(z.string()).optional(),
bcc: z.array(z.string()).optional(),
subject: z.array(z.string()).optional(),
})

export type Intent = z.infer<typeof IntentSchema>
export type MailParticipant = z.infer<typeof MailParticipantSchema>

// Zod schemas for filters
export const FiltersSchema = z.object({
Expand All @@ -401,7 +401,7 @@ export const FiltersSchema = z.object({
sortDirection: z.string().optional(),
count: z.preprocess((val) => (val == null ? 5 : val), z.number()),
offset: z.preprocess((val) => (val == null ? 0 : val), z.number()),
intent: IntentSchema.optional(),
mailParticipants: MailParticipantSchema.optional(),
})

const TemporalClassifierSchema = z.object({
Expand Down
Loading