Skip to content

Commit c297fcd

Browse files
aryanranderiyasankalpaacharyaDhruv-Maradiyaactions-userCopilot
authored
chore(release): v0.3.0 (#131)
* ci: replace --no-frozen-lockfile with --frozen-lockfile * perf: parallelize cloudinary upload and summary generation * ci: upgrade pnpm from v8 to v10.12.2 * feat: update privacy policy to include Google user data handling and protection measures * refactor: simplify onboarding process by removing country-related fields and validations * ci(auto-fix): Apply ESLint formatting * feat: enhance subscription management and webhook processing - Update subscription status checks to ensure only active subscriptions are considered. - Add cleanup tasks for abandoned subscriptions and reconciliation of payment statuses. - Implement webhook event tracking for idempotency and error handling. - Introduce new models for webhook events and enhance Razorpay client integration. - Improve user interface components to reflect accurate subscription states. * refactor: update datetime handling and remove unused apiService * Refactor payment handling and UI components - Replaced native button with custom Button component in BlogList and PricingPage for consistency. - Introduced PaymentSuccessPage to handle payment verification and success feedback. - Updated pricing API to streamline subscription creation and payment verification. - Removed Razorpay integration and replaced it with Dodo Payments for subscription handling. - Simplified error handling and state management in payment flow. - Enhanced SubscriptionSettings to disable cancellation option and guide users to contact support. - Cleaned up unused hooks and components related to Razorpay. * feat: add dodo_product_id to Plan model and update related components * feat: implement JWT authentication for Pub/Sub webhook requests * fix: filtered empty user messages in system generated chat when response is empty * feat: enhance logout functionality to redirect to logout URL from backend * feat: implement Dodo Payments webhook handling and processing logic * feat: enhance error handling for integration toasts to prevent duplicates * feat: update Navbar to display chat icon and link based on user authentication * Refactor Dodo Payments integration: - Simplified webhook handling in payments.py, removing signature verification and improving error handling. - Reorganized MongoDB collections in collections.py for clarity. - Updated indexes in indexes.py to optimize payment and subscription queries. - Enhanced webhook models in webhook_models.py for better structure and naming consistency. - Streamlined payment_service.py to focus on payment link generation without immediate database storage. - Consolidated payment webhook logic into payment_webhook_service.py, removing redundant code and improving event handling. - Deleted outdated webhook_service.py to eliminate duplication and maintain a single source of truth for webhook processing. * feat: enhance tool execution request message to include fallback for unavailable tools * feat: enhance Dodo Payments webhook handling with signature verification * feat: add auto redirect countdown to SubscriptionSuccessModal * ci(auto-fix): Apply ESLint formatting * feat: integrate Standard Webhooks library for Dodo Payments signature verification * feat: update Dodo Payments setup script and modify subscription plans descriptions * ci(auto-fix): Apply ESLint formatting * feat: refactor navigation components and enhance app configuration with new links and descriptions * feat: add ScrollToBottomButton component for improved chat navigation * feat: implement abort controller management for chat stream handling * feat: implement save functionality for incomplete conversations in chat stream * feat: refactor modal handling in ChatOptionsDropdown for improved state management * fix: shift + enter appends to end of composer * chore:lint * feat: enhance memory management with async client and export options in MemoryGraph * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/app/models/payment_models.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/scripts/dodo_setup.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update backend/scripts/dodo_setup.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * ci(auto-fix): Apply pre-commit hooks formatting * ci(auto-fix): Apply ESLint formatting * refactor: improve validation and sanitization in onboarding preferences * refactor: update OAuth integration comments and adjust dropdown positioning in chat components * refactor: streamline input clearing logic in Composer and useChatStream * ci(auto-fix): Apply pre-commit hooks formatting * feat: enhance OAuth integration handling with unified integrations support * feat: implement caching for integrations configuration to enhance performance * ci(auto-fix): Apply ESLint formatting * feat: refactor Google OAuth integration handling and improve scope management * feat: update integration icon handling to support multiple icons * chore: fix linting & type issues * ci(auto-fix): Apply ESLint formatting * chore: configure PostHog analytics * feat: add Sentry integration for error tracking and performance monitoring on backend * feat: integrate Sentry for error tracking and performance monitoring - Added Sentry configuration for edge features in `sentry.edge.config.ts` - Added Sentry configuration for server-side in `sentry.server.config.ts` - Implemented global error boundary in `global-error.tsx` to capture exceptions - Configured Sentry for client-side instrumentation in `instrumentation-client.ts` - Created `instrumentation.ts` to register Sentry based on runtime environment * ci(auto-fix): Apply pre-commit hooks formatting * Create CODE_OF_CONDUCT.md * feat: enhance calendar event handling with timezone support and updated models - Updated calendar event models to include timezone offset and processing logic. - Refactored calendar service to utilize processed times directly. - Improved chat API to handle conversation ID extraction from URL. - Enhanced CalendarEventSection to include calendar ID in event options. - Adjusted hooks to manage conversation ID more flexibly. * feat: update WorkOS client to AsyncWorkOSClient and enhance calendar event handling for batch processing * refactor: remove unused router import from useChatStream hook * Remove outdated documentation and OAuth integration icons from the project * Update frontend/src/features/chat/components/composer/ComposerRight.tsx * fix: "error in chat stream" error infinite * feat: implement support ticket system with creation and management tools * docs: update usage rules in support ticket tool documentation for clarity * feat: add Cerebras AI configuration and integrate ChatCerebras model in client * ci(auto-fix): Apply ESLint formatting * feat: removed unused nltk and replaced embeddings model with better embedding * fix: remove unnecessary max-height from description scroll shadow * ci(auto-fix): Apply pre-commit hooks formatting * chore(ci): add manual trigger for Release Please workflow * fix: update release token in workflow and import useRouter in useChatStream hook * ci(auto-fix): Apply ESLint formatting * chore(lint): Remove unused imports in PricingPage component * docs: Added Code of Conduct docs: Added Code of Conduct and appropriately replaced main with master in docs --------- Co-authored-by: Aryan <aryan.k.randeriya@gmail.com> --------- Co-authored-by: sankalpaacharya <sankalpaacharya01@gmail.com> Co-authored-by: Dhruv Maradiya <dhruvmaradiya0@gmail.com> Co-authored-by: GitHub Actions <actions@github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jigar Bhoye <84662430+jigarbhoye04@users.noreply.github.com>
1 parent aa2228b commit c297fcd

File tree

174 files changed

+20671
-15568
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+20671
-15568
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020

2121
- uses: pnpm/action-setup@v2
2222
with:
23-
version: 8
23+
version: 10.12.2
2424

2525
- name: Use Node.js
2626
uses: actions/setup-node@v3
@@ -31,8 +31,7 @@ jobs:
3131

3232
- name: Install dependencies
3333
run: |
34-
pnpm install --no-frozen-lockfile
35-
pnpm install
34+
pnpm install --frozen-lockfile
3635
3736
- name: Run ESLint with autofix
3837
run: pnpm lint:fix

CODE_OF_CONDUCT.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Commitment
4+
5+
We are committed to making participation in our community a welcoming, respectful, and productive experience for everyone.
6+
7+
## Standards
8+
9+
Positive examples of behavior include:
10+
11+
- Showing respect and kindness to others
12+
- Being open to different perspectives and experiences
13+
- Offering and accepting constructive feedback
14+
- Taking responsibility for mistakes and working to correct them
15+
16+
Unacceptable behavior includes:
17+
18+
- Harassment or discrimination of any kind
19+
- Offensive, derogatory, or inappropriate comments
20+
- Personal attacks or trolling
21+
- Sharing private information without consent
22+
- Any unprofessional or disruptive conduct
23+
24+
## Responsibilities
25+
26+
Community leaders will:
27+
28+
- Enforce this Code of Conduct consistently and fairly
29+
- Take appropriate action for violations, which may include warnings, temporary bans, or permanent bans
30+
- Provide clear reasons for moderation decisions when possible
31+
32+
## Scope
33+
34+
This Code of Conduct applies across all community spaces and when an individual is representing the community in public settings.
35+
36+
## Enforcement
37+
38+
If you experience or witness unacceptable behavior, please report it to the community leaders at **your-email@example.com**. Reports will be handled respectfully, promptly, and with confidentiality.
39+
40+
## Enforcement Guidelines
41+
42+
Community leaders will use the following guidelines when determining consequences for violations:
43+
44+
1. **Warning**
45+
- *Behavior*: Minor or first-time violation.
46+
- *Action*: Private warning with explanation. A public apology may be requested.
47+
48+
2. **Temporary Ban**
49+
- *Behavior*: More serious or repeated violations.
50+
- *Action*: Temporary restriction from community participation.
51+
52+
3. **Permanent Ban**
53+
- *Behavior*: Severe or ongoing violations.
54+
- *Action*: Permanent removal from the community.
55+
56+
## Attribution
57+
58+
This Code of Conduct is adapted from the [Contributor Covenant, version 2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html), with modifications for clarity and brevity.

backend/.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
# ============================================================================================
2+
# IMPORTANT: DO NOT DELETE THIS FILE
3+
# --------------------------------------------------------------------------------------------
4+
# This `.env.example` file is required for the repository. It serves as a reference template
5+
# showing the environment variables needed to run the project. Actual values must be provided
6+
# via Infisical or your own `.env` file, but this file should remain in version control.
7+
#
8+
# For setup instructions and details on configuring environment variables, see:
9+
# https://docs.heygaia.io/configuration/environment-variables
10+
# ============================================================================================
11+
112
# Environment Configuration
213
ENV=development # Environment type: development, staging, production
314
DISABLE_PROFILING=true # Disable performance profiling in non-production environments

backend/Dockerfile

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,8 @@
4949
uv pip install --system --no-cache-dir -r heavy-deps.txt && \
5050
rm -rf /root/.cache/pip
5151

52-
# Setup Playwright and NLTK
53-
RUN python -m playwright install --with-deps chromium
54-
RUN python -m nltk.downloader punkt stopwords punkt_tab && \
55-
rm -rf /root/.cache/nltk
52+
# Setup Playwright
53+
RUN python -m playwright install chromium
5654

5755
# ---- Default Dependencies Stage: Install default application dependencies ----
5856
FROM heavy-dependencies AS default-dependencies
@@ -82,8 +80,7 @@
8280

8381
# Setup non-root user and permissions
8482
RUN adduser --disabled-password --gecos '' appuser \
85-
&& mkdir -p /home/appuser/.cache/huggingface /home/appuser/nltk_data \
86-
&& cp -R /root/nltk_data/* /home/appuser/nltk_data/ \
83+
&& mkdir -p /home/appuser/.cache \
8784
&& chown -R appuser:appuser /home/appuser \
8885
&& cp -R /root/.cache/ms-playwright /home/appuser/.cache/ \
8986
&& chown -R appuser:appuser /home/appuser/.cache/ms-playwright \

backend/app/api/v1/dependencies/google_scope_dependencies.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
before allowing access to protected endpoints that require specific integrations.
66
"""
77

8-
from typing import Dict, List, Literal, Union
8+
from typing import List, Literal, Union
99

1010
import httpx
1111
from app.api.v1.dependencies.oauth_dependencies import get_current_user
1212
from app.config.loggers import auth_logger as logger
13+
from app.config.oauth_config import get_integration_scopes, get_short_name_mapping
1314
from app.config.token_repository import token_repository
1415
from fastapi import Depends, HTTPException, status
1516

@@ -40,10 +41,13 @@ async def wrapper(user: dict = Depends(get_current_user)):
4041
)
4142

4243
try:
43-
token = await token_repository.get_token(
44-
user_id, "google", renew_if_expired=True
45-
)
46-
authorized_scopes = str(token.get("scope", "")).split()
44+
try:
45+
token = await token_repository.get_token(
46+
user_id, "google", renew_if_expired=True
47+
)
48+
authorized_scopes = str(token.get("scope", "")).split()
49+
except HTTPException:
50+
authorized_scopes = []
4751

4852
# Handle both single scope and list of scopes
4953
required_scopes = [scope] if isinstance(scope, str) else scope
@@ -76,18 +80,6 @@ async def wrapper(user: dict = Depends(get_current_user)):
7680
return wrapper
7781

7882

79-
# Mapping of integration names to their required OAuth scope URLs
80-
GOOGLE_SCOPE_URLS: Dict[str, Union[str, List[str]]] = {
81-
"gmail": "https://www.googleapis.com/auth/gmail.modify",
82-
"calendar": [
83-
"https://www.googleapis.com/auth/calendar.events",
84-
"https://www.googleapis.com/auth/calendar.readonly",
85-
],
86-
"drive": "https://www.googleapis.com/auth/drive.file",
87-
"docs": "https://www.googleapis.com/auth/documents",
88-
}
89-
90-
9183
def require_google_integration(
9284
integration: Literal["gmail", "calendar", "drive", "docs"],
9385
):
@@ -101,24 +93,32 @@ def require_google_integration(
10193
def get_events(user = Depends(require_google_integration("calendar"))):
10294
# user has Calendar scope with both read and write permissions
10395
104-
# For Calendar readonly endpoints
105-
@app.get("/calendar/events/readonly")
106-
def get_events_readonly(user = Depends(require_google_integration("calendar_readonly"))):
107-
# user has Calendar readonly scope
96+
# For Gmail endpoints
97+
@app.get("/gmail/messages")
98+
def get_messages(user = Depends(require_google_integration("gmail"))):
99+
# user has Gmail scope with required permissions
108100
109101
Args:
110-
integration: The Google integration name
102+
integration: The Google integration short name
111103
112104
Returns:
113105
The corresponding scope dependency function
114106
115107
Raises:
116108
ValueError: If unknown integration name is provided
117109
"""
118-
if integration not in GOOGLE_SCOPE_URLS:
110+
# Get the short name mapping from oauth_config (single source of truth)
111+
short_name_mapping = get_short_name_mapping()
112+
113+
if integration not in short_name_mapping:
119114
raise ValueError(
120-
f"Unknown integration: {integration}. Available: {list(GOOGLE_SCOPE_URLS.keys())}"
115+
f"Unknown integration: {integration}. Available: {list(short_name_mapping.keys())}"
121116
)
122117

123-
scope_urls = GOOGLE_SCOPE_URLS[integration]
118+
integration_id = short_name_mapping[integration]
119+
scope_urls = get_integration_scopes(integration_id)
120+
121+
if not scope_urls:
122+
raise ValueError(f"No scopes found for integration: {integration_id}")
123+
124124
return require_google_scope(scope_urls)

backend/app/api/v1/router/chat.py

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from datetime import datetime
1+
from datetime import datetime, timezone
22

33
from fastapi import APIRouter, BackgroundTasks, Depends
44
from fastapi.responses import StreamingResponse
@@ -7,13 +7,23 @@
77
get_current_user,
88
get_user_timezone,
99
)
10-
from app.decorators import tiered_rate_limit
11-
from app.models.message_models import MessageRequestWithHistory
12-
from app.services.chat_service import chat_stream
10+
from app.decorators import profile_time, tiered_rate_limit
11+
from app.models.message_models import (
12+
MessageRequestWithHistory,
13+
SaveIncompleteConversationRequest,
14+
MessageDict,
15+
)
16+
from app.models.chat_models import MessageModel, UpdateMessagesRequest
17+
from app.services.chat_service import (
18+
chat_stream,
19+
)
20+
from app.services.conversation_service import update_messages
21+
from app.utils.chat_utils import create_conversation
1322

1423
router = APIRouter()
1524

1625

26+
@profile_time()
1727
@router.post("/chat-stream")
1828
@tiered_rate_limit("chat_messages")
1929
async def chat_stream_endpoint(
@@ -38,3 +48,61 @@ async def chat_stream_endpoint(
3848
"Access-Control-Allow-Origin": "*",
3949
},
4050
)
51+
52+
53+
@router.post("/save-incomplete-conversation")
54+
@tiered_rate_limit("chat_messages")
55+
async def save_incomplete_conversation(
56+
body: SaveIncompleteConversationRequest,
57+
background_tasks: BackgroundTasks,
58+
user: dict = Depends(get_current_user),
59+
) -> dict:
60+
"""
61+
Save incomplete conversation when stream is cancelled.
62+
"""
63+
conversation_id = body.conversation_id
64+
65+
# Only create new conversation if conversation_id is None
66+
if conversation_id is None:
67+
last_message: MessageDict = {"role": "user", "content": body.message}
68+
selectedTool = body.selectedTool
69+
conversation = await create_conversation(
70+
last_message, user=user, selectedTool=selectedTool
71+
)
72+
conversation_id = conversation.get("conversation_id", "")
73+
74+
# Save the incomplete conversation immediately (not as background task)
75+
# Since user expects to see it right away when they navigate/refresh
76+
77+
# Create user message
78+
user_message = MessageModel(
79+
type="user",
80+
response=body.message,
81+
date=datetime.now(timezone.utc).isoformat(),
82+
fileIds=body.fileIds,
83+
fileData=body.fileData,
84+
selectedTool=body.selectedTool,
85+
toolCategory=body.toolCategory,
86+
)
87+
88+
# Create bot message with incomplete response
89+
bot_message = MessageModel(
90+
type="bot",
91+
response=body.incomplete_response,
92+
date=datetime.now(timezone.utc).isoformat(),
93+
fileIds=body.fileIds,
94+
)
95+
96+
# Save immediately instead of background task
97+
await update_messages(
98+
UpdateMessagesRequest(
99+
conversation_id=conversation_id,
100+
messages=[user_message, bot_message],
101+
),
102+
user=user,
103+
)
104+
105+
return {
106+
"success": True,
107+
"conversation_id": conversation_id,
108+
}

backend/app/api/v1/router/mail_webhook.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import json
22

3-
from fastapi import APIRouter, HTTPException, Request
4-
from fastapi.encoders import jsonable_encoder
5-
from fastapi.exceptions import RequestValidationError
6-
from pydantic import ValidationError
7-
83
from app.config.loggers import mail_webhook_logger as logger
94
from app.models.mail_models import EmailWebhookRequest
105
from app.services.mail_webhook_service import queue_email_processing
6+
from app.utils.pubsub_auth import get_verified_pubsub_request
7+
from fastapi import APIRouter, Depends, HTTPException, Request
8+
from fastapi.encoders import jsonable_encoder
9+
from fastapi.exceptions import RequestValidationError
10+
from pydantic import ValidationError
1111

1212
router = APIRouter()
1313

@@ -16,13 +16,21 @@
1616
"/mail-webhook/receive",
1717
summary="Process Email Webhook",
1818
)
19-
async def receive_email(request: Request):
19+
async def receive_email(
20+
request: Request,
21+
jwt_payload: dict = Depends(
22+
get_verified_pubsub_request
23+
), # Ensure the request is verified
24+
):
2025
"""
2126
Process incoming email webhook notifications from Gmail.
2227
The webhook payload contains information about new emails.
2328
2429
This endpoint receives the webhook, validates the payload,
2530
and queues a background task for processing.
31+
32+
The request is authenticated using JWT tokens to ensure it
33+
comes from Google Cloud Pub/Sub and not unauthorized entities.
2634
"""
2735
try:
2836
# Log raw request body
@@ -44,8 +52,6 @@ async def receive_email(request: Request):
4452
detail="Email address and history ID must be provided.",
4553
)
4654

47-
logger.info(f"Parsed: email={email_address}, historyId={history_id}")
48-
4955
# Use service to queue email processing
5056
return await queue_email_processing(email_address, history_id)
5157

0 commit comments

Comments
 (0)