mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-04-25 16:56:22 +02:00
Merge pull request #756 from AnishSarkar22/fix/google-calendar-connectors
fix: google calendar issues (composio & non-composio)
This commit is contained in:
commit
4e04b4053a
8 changed files with 54 additions and 39 deletions
|
|
@ -246,15 +246,18 @@ class GoogleCalendarConnector:
|
||||||
dt_start = isoparse(start_date)
|
dt_start = isoparse(start_date)
|
||||||
dt_end = isoparse(end_date)
|
dt_end = isoparse(end_date)
|
||||||
|
|
||||||
|
# Set start to beginning of day (00:00:00) and end to end of day (23:59:59)
|
||||||
|
# This ensures same-date queries work (e.g., start=2026-01-23, end=2026-01-23)
|
||||||
|
# and matches the Composio connector behavior
|
||||||
if dt_start.tzinfo is None:
|
if dt_start.tzinfo is None:
|
||||||
dt_start = dt_start.replace(tzinfo=pytz.UTC)
|
dt_start = dt_start.replace(hour=0, minute=0, second=0, tzinfo=pytz.UTC)
|
||||||
else:
|
else:
|
||||||
dt_start = dt_start.astimezone(pytz.UTC)
|
dt_start = dt_start.astimezone(pytz.UTC).replace(hour=0, minute=0, second=0)
|
||||||
|
|
||||||
if dt_end.tzinfo is None:
|
if dt_end.tzinfo is None:
|
||||||
dt_end = dt_end.replace(tzinfo=pytz.UTC)
|
dt_end = dt_end.replace(hour=23, minute=59, second=59, tzinfo=pytz.UTC)
|
||||||
else:
|
else:
|
||||||
dt_end = dt_end.astimezone(pytz.UTC)
|
dt_end = dt_end.astimezone(pytz.UTC).replace(hour=23, minute=59, second=59)
|
||||||
|
|
||||||
if dt_start >= dt_end:
|
if dt_start >= dt_end:
|
||||||
return [], (
|
return [], (
|
||||||
|
|
|
||||||
|
|
@ -191,10 +191,10 @@ async def index_google_calendar_events(
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
calculated_start_date = datetime.now() - timedelta(
|
calculated_start_date = datetime.now() - timedelta(
|
||||||
days=30
|
days=365
|
||||||
) # Use 30 days as default for calendar events
|
) # Use 365 days as default for calendar events (matches frontend)
|
||||||
logger.info(
|
logger.info(
|
||||||
f"No last_indexed_at found, using {calculated_start_date.strftime('%Y-%m-%d')} (30 days ago) as start date"
|
f"No last_indexed_at found, using {calculated_start_date.strftime('%Y-%m-%d')} (365 days ago) as start date"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Use calculated dates if not provided
|
# Use calculated dates if not provided
|
||||||
|
|
@ -209,23 +209,6 @@ async def index_google_calendar_events(
|
||||||
start_date_str = start_date
|
start_date_str = start_date
|
||||||
end_date_str = end_date
|
end_date_str = end_date
|
||||||
|
|
||||||
# If start_date and end_date are the same, adjust end_date to be one day later
|
|
||||||
# to ensure valid date range (start_date must be strictly before end_date)
|
|
||||||
if start_date_str == end_date_str:
|
|
||||||
# Parse the date and add one day to ensure valid range
|
|
||||||
dt = isoparse(end_date_str)
|
|
||||||
if dt.tzinfo is None:
|
|
||||||
dt = dt.replace(tzinfo=pytz.UTC)
|
|
||||||
else:
|
|
||||||
dt = dt.astimezone(pytz.UTC)
|
|
||||||
# Add one day to end_date to make it strictly after start_date
|
|
||||||
dt_end = dt + timedelta(days=1)
|
|
||||||
end_date_str = dt_end.strftime("%Y-%m-%d")
|
|
||||||
logger.info(
|
|
||||||
f"Adjusted end_date from {end_date} to {end_date_str} "
|
|
||||||
f"to ensure valid date range (start_date must be strictly before end_date)"
|
|
||||||
)
|
|
||||||
|
|
||||||
await task_logger.log_task_progress(
|
await task_logger.log_task_progress(
|
||||||
log_entry,
|
log_entry,
|
||||||
f"Fetching Google Calendar events from {start_date_str} to {end_date_str}",
|
f"Fetching Google Calendar events from {start_date_str} to {end_date_str}",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,13 @@ def get_model_context_window(model_name: str) -> int:
|
||||||
"""Get the total context window size for a model (input + output tokens)."""
|
"""Get the total context window size for a model (input + output tokens)."""
|
||||||
try:
|
try:
|
||||||
model_info = get_model_info(model_name)
|
model_info = get_model_info(model_name)
|
||||||
context_window = model_info.get("max_input_tokens", 4096) # Default fallback
|
context_window = model_info.get("max_input_tokens")
|
||||||
|
# Handle case where key exists but value is None
|
||||||
|
if context_window is None:
|
||||||
|
print(
|
||||||
|
f"Warning: max_input_tokens is None for {model_name}, using default 4096 tokens."
|
||||||
|
)
|
||||||
|
return 4096 # Conservative fallback
|
||||||
return context_window
|
return context_window
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(
|
print(
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ interface DateRangeSelectorProps {
|
||||||
onStartDateChange: (date: Date | undefined) => void;
|
onStartDateChange: (date: Date | undefined) => void;
|
||||||
onEndDateChange: (date: Date | undefined) => void;
|
onEndDateChange: (date: Date | undefined) => void;
|
||||||
allowFutureDates?: boolean; // Allow future dates for calendar connectors
|
allowFutureDates?: boolean; // Allow future dates for calendar connectors
|
||||||
|
lastIndexedAt?: string | null; // Last sync timestamp to show in default placeholder
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DateRangeSelector: FC<DateRangeSelectorProps> = ({
|
export const DateRangeSelector: FC<DateRangeSelectorProps> = ({
|
||||||
|
|
@ -23,7 +24,21 @@ export const DateRangeSelector: FC<DateRangeSelectorProps> = ({
|
||||||
onStartDateChange,
|
onStartDateChange,
|
||||||
onEndDateChange,
|
onEndDateChange,
|
||||||
allowFutureDates = false,
|
allowFutureDates = false,
|
||||||
|
lastIndexedAt,
|
||||||
}) => {
|
}) => {
|
||||||
|
// Get the placeholder text for start date based on whether connector was previously indexed
|
||||||
|
const getStartDatePlaceholder = () => {
|
||||||
|
if (lastIndexedAt) {
|
||||||
|
const date = new Date(lastIndexedAt);
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
const indexedYear = date.getFullYear();
|
||||||
|
// Show year only if different from current year
|
||||||
|
const formatStr = indexedYear === currentYear ? "MMM d, HH:mm" : "MMM d, yyyy HH:mm";
|
||||||
|
const formattedDate = format(date, formatStr);
|
||||||
|
return `Since (${formattedDate})`;
|
||||||
|
}
|
||||||
|
return "Default (1 year ago)";
|
||||||
|
};
|
||||||
const handleLast30Days = () => {
|
const handleLast30Days = () => {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
onStartDateChange(subDays(today, 30));
|
onStartDateChange(subDays(today, 30));
|
||||||
|
|
@ -73,7 +88,7 @@ export const DateRangeSelector: FC<DateRangeSelectorProps> = ({
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
{startDate ? format(startDate, "PPP") : "Default (1 year ago)"}
|
{startDate ? format(startDate, "PPP") : getStartDatePlaceholder()}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-auto p-0 z-[100]" align="start">
|
<PopoverContent className="w-auto p-0 z-[100]" align="start">
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
||||||
connector.connector_type === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR" ||
|
connector.connector_type === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR" ||
|
||||||
connector.connector_type === "LUMA_CONNECTOR"
|
connector.connector_type === "LUMA_CONNECTOR"
|
||||||
}
|
}
|
||||||
|
lastIndexedAt={connector.last_indexed_at}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
|
||||||
config.connectorType === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR" ||
|
config.connectorType === "COMPOSIO_GOOGLE_CALENDAR_CONNECTOR" ||
|
||||||
config.connectorType === "LUMA_CONNECTOR"
|
config.connectorType === "LUMA_CONNECTOR"
|
||||||
}
|
}
|
||||||
|
lastIndexedAt={connector?.last_indexed_at}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ const DialogContent = React.forwardRef<
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0",
|
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 rounded-lg focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,12 @@ class ConnectorsApiService {
|
||||||
throw new ValidationError(`Invalid request: ${errorMessage}`);
|
throw new ValidationError(`Invalid request: ${errorMessage}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform query params to be string values
|
// Transform query params to be string values, filtering out undefined/null
|
||||||
const transformedQueryParams = parsedRequest.data.queryParams
|
const transformedQueryParams = parsedRequest.data.queryParams
|
||||||
? Object.fromEntries(
|
? Object.fromEntries(
|
||||||
Object.entries(parsedRequest.data.queryParams).map(([k, v]) => {
|
Object.entries(parsedRequest.data.queryParams)
|
||||||
|
.filter(([_, v]) => v !== undefined && v !== null)
|
||||||
|
.map(([k, v]) => {
|
||||||
return [k, String(v)];
|
return [k, String(v)];
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
@ -102,9 +104,11 @@ class ConnectorsApiService {
|
||||||
|
|
||||||
const { data, queryParams } = parsedRequest.data;
|
const { data, queryParams } = parsedRequest.data;
|
||||||
|
|
||||||
// Transform query params to be string values
|
// Transform query params to be string values, filtering out undefined/null
|
||||||
const transformedQueryParams = Object.fromEntries(
|
const transformedQueryParams = Object.fromEntries(
|
||||||
Object.entries(queryParams).map(([k, v]) => {
|
Object.entries(queryParams)
|
||||||
|
.filter(([_, v]) => v !== undefined && v !== null)
|
||||||
|
.map(([k, v]) => {
|
||||||
return [k, String(v)];
|
return [k, String(v)];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -174,9 +178,11 @@ class ConnectorsApiService {
|
||||||
|
|
||||||
const { connector_id, queryParams, body } = parsedRequest.data;
|
const { connector_id, queryParams, body } = parsedRequest.data;
|
||||||
|
|
||||||
// Transform query params to be string values
|
// Transform query params to be string values, filtering out undefined/null
|
||||||
const transformedQueryParams = Object.fromEntries(
|
const transformedQueryParams = Object.fromEntries(
|
||||||
Object.entries(queryParams).map(([k, v]) => {
|
Object.entries(queryParams)
|
||||||
|
.filter(([_, v]) => v !== undefined && v !== null)
|
||||||
|
.map(([k, v]) => {
|
||||||
return [k, String(v)];
|
return [k, String(v)];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue