Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
b3f8239
make account approval configurable
Feb 27, 2026
412cc2e
make account approval configurable
Feb 27, 2026
7e61b69
improve: account approval configuration
anishghimire862 Feb 27, 2026
3ad0a69
chore: upgrade dependencies
anishghimire862 Feb 27, 2026
38e553e
change password
Feb 27, 2026
b7f7659
feat: change password
anishghimire862 Feb 27, 2026
df6d760
update ui for login and register pages
Feb 27, 2026
8fd5fab
improve: update ui for login and register pages
anishghimire862 Feb 27, 2026
eb473c8
feat: ai providers api + test
anishghimire862 Feb 28, 2026
8f85466
Merge pull request #83 from Sarva-Tech/feat/ai-providers-api
krrishg Mar 1, 2026
722267d
improve: refactor ai providers logic + add tests
anishghimire862 Mar 1, 2026
33aa8b2
improve: refactor ai providers logic + add tests
anishghimire862 Mar 1, 2026
80b651a
improve: refactor ai providers logic + add tests
anishghimire862 Mar 1, 2026
5bbdbcb
feat: list user owned and builtin ai providers
anishghimire862 Mar 1, 2026
e344ae1
feat: api for app ai provider configuration
anishghimire862 Mar 1, 2026
c126bd6
refactor: use uuid lookup for ai provider apis and fix tests
anishghimire862 Mar 1, 2026
5ee1c03
feat: configure app ai providers api
anishghimire862 Mar 3, 2026
e45cf86
improve: refactor and integrate AI Provider setting
anishghimire862 Mar 4, 2026
aac6c45
feat: validate ai providers
anishghimire862 Mar 4, 2026
0c77eeb
feat: make ai providers config dynamic and configurable
anishghimire862 Mar 4, 2026
5881430
feat: extract and merge additional fields to metadata
anishghimire862 Mar 4, 2026
1dc85f6
feat: integrate AI providers UI and refactored backend as needed
anishghimire862 Mar 5, 2026
1047986
chore: clean up and wrap up AI provider
anishghimire862 Mar 5, 2026
42bac3b
fix: use paginated response in ui stores
anishghimire862 Mar 6, 2026
2e6e60c
feat: load ai provider models and UI improvements
anishghimire862 Mar 7, 2026
cea7124
fix: ensure navigation items work consistently on click
dipakbadu01 Mar 10, 2026
4e39fc2
feat: allow configuring AI models (text, embedding) for an application
anishghimire862 Mar 10, 2026
5bf39e6
Merge pull request #87 from Sarva-Tech/fix-sidebar-navigation-click
dipakbadu Mar 10, 2026
3cea2cc
test: AI models configuration tests
anishghimire862 Mar 10, 2026
f50e643
Merge branch 'develop' of https://github.com/Sarva-Tech/ch8r into dev…
anishghimire862 Mar 10, 2026
2b7f0f4
ci: setup backend ci
anishghimire862 Mar 10, 2026
59edce8
ci: update env and fix qdrant version
anishghimire862 Mar 10, 2026
bc5a5cb
ci: debug env
anishghimire862 Mar 10, 2026
1ed598a
ci: prevent multiple tests run and read discord webhook from env prop…
anishghimire862 Mar 10, 2026
ef56ee8
ci: add inspect project step and refactor duplicate env
anishghimire862 Mar 10, 2026
d77401b
ci: remove coverage step
anishghimire862 Mar 10, 2026
32c3050
ci: add static root setting
anishghimire862 Mar 10, 2026
122d862
improve: chatroom ui
anishghimire862 Mar 11, 2026
de39a54
feat: use the new ai provider during text generation and conversation…
anishghimire862 Mar 14, 2026
49bfe50
feat(widget): add embeddable chat widget with multi-mode support
anishghimire862 Mar 14, 2026
d4a1372
fix: app name in widget
anishghimire862 Mar 14, 2026
58b5c12
ui: improve dashboard and widget chatroom ui
anishghimire862 Mar 15, 2026
015fd3d
feat: support embedding using new ai provider approach
anishghimire862 Mar 15, 2026
e3c0cc8
feat: new messages live updates on dashboard and widget
anishghimire862 Mar 15, 2026
4cf0910
feat: unread messages indicator and messages preview
anishghimire862 Mar 16, 2026
1d995fc
chore: remove .kiro directory
anishghimire862 Mar 16, 2026
6cfae20
refactor: messages in widget and dashboard
anishghimire862 Mar 17, 2026
5ad48cb
feat: new widget experience, unread messages indicator and message pr…
anishghimire862 Mar 17, 2026
ae18c5a
feat: replace chatroom-level mode with per-message platform/is_intern…
anishghimire862 Mar 20, 2026
6476086
feat: replace chatroom-level mode with per-message platform/is_intern…
anishghimire862 Mar 20, 2026
1353e08
feat: provide better messages with visibility and ai_mode selection
anishghimire862 Mar 22, 2026
a45d988
chore: cleanups
anishghimire862 Mar 22, 2026
41e40e7
feat: replace chatroom-level mode with per-message platform/is_intern…
anishghimire862 Mar 22, 2026
51ba318
feat: set chat mode (ai/human) based on the last sent message's mode
anishghimire862 Mar 22, 2026
c024012
feat: ctrl + enter to send message and ui cleanups
anishghimire862 Mar 22, 2026
380340f
feat: allow button's icon position to be configurable
anishghimire862 Mar 22, 2026
63527ef
feat: show ctrl + enter icon in send button
anishghimire862 Mar 22, 2026
175adcc
feat: (widget) configurable position
anishghimire862 Mar 22, 2026
5c55d19
feat: configure Gemini models to generate structured output
anishghimire862 Mar 22, 2026
7d82ec3
ingest github
Mar 23, 2026
999c739
feat: order messages by created at date
anishghimire862 Mar 23, 2026
95d8f1a
feat: enable ai_mode and internal mode for new conversations
anishghimire862 Mar 23, 2026
e8206e6
feat: delete api keys and api keys page ui improvements
anishghimire862 Mar 23, 2026
866c875
use graphql for github ingestion
Mar 24, 2026
692276e
Merge pull request #97 from Sarva-Tech/github-ingest
krrishg Mar 24, 2026
00f0de8
feat: generate agent's response in Markdown and render Markdown in bo…
anishghimire862 Mar 24, 2026
8cf09c3
Merge remote-tracking branch 'origin/develop' into develop
anishghimire862 Mar 24, 2026
a198a49
fix: make widget's header compact
anishghimire862 Mar 24, 2026
5806007
feat: auto scroll to bottom of messages initially and while a new mes…
anishghimire862 Mar 24, 2026
ff24128
fix: issue with conversation list allowing users to scroll on x-axis …
anishghimire862 Mar 24, 2026
1afdcfa
improve: show unread message badge on the right side of the conversat…
anishghimire862 Mar 24, 2026
74f4839
improve: highlight unread preview message in a light background
anishghimire862 Mar 24, 2026
c89d33d
fix: (widget) long message causing overflow on x
anishghimire862 Mar 24, 2026
6a4267a
improve: consistent text/bg color
anishghimire862 Mar 24, 2026
fe536c6
refactor
Mar 25, 2026
7a31ec4
Merge pull request #98 from Sarva-Tech/github-ingest
krrishg Mar 25, 2026
6b4a7ea
refactor
Mar 25, 2026
8ee9775
Merge pull request #99 from Sarva-Tech/github-ingest
krrishg Mar 25, 2026
4a8af6a
refactor
Mar 25, 2026
a707092
Merge pull request #101 from Sarva-Tech/github-ingest
krrishg Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
177 changes: 177 additions & 0 deletions .github/workflows/ci-backend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
name: Backend CI

on:
push:
branches: [ master, develop ]
pull_request:
branches: [ master, develop ]

jobs:
test:
runs-on: ubuntu-latest
environment: Test CI/CD
env:
APP_SECRET_KEY: 'test-secret-key-for-ci'
DB_NAME: ch8rtests
DB_USER: testuser
DB_PASSWORD: testpass
DB_HOST: localhost
PORT: 5432
TEST_DB_NAME: ch8rtests
TEST_DB_USER: testuser
TEST_DB_PASSWORD: testpass
TEST_DB_HOST: localhost
TEST_DB_PORT: 5432
DJANGO_SETTINGS_MODULE: config.test_settings
CONNECT_TO_LOCAL_VECTOR_DB: 'true'
QDRANT_LOCAL_HOST: localhost
QDRANT_LOCAL_PORT: 6333
SECRET_ENCRYPTION_KEY: 'r5kAsRtMlZuP0b6UeRXdI9QqL_0uTTvTkT7jXsmkGxk='
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY || 'test-key' }}
QDRANT_CLOUD_API_KEY: ${{ secrets.QDRANT_CLOUD_API_KEY || 'test-key' }}
MAILERSEND_API_KEY: ${{ secrets.MAILERSEND_API_KEY || 'test-key' }}
DISCORD_SIGNUP_WEBHOOK_URL: 'https://example.com'
WIDGET_URL: 'https://widget.ch8r.com'
API_BASE_URL: 'http://localhost:8000/api'
FRONTEND_URL: 'http://localhost:3000'
CLOSED_ALPHA_SIGN_UPS: '["test@example.com"]'
REQUIRE_ACCOUNT_APPROVAL: 'False'

services:
postgres:
image: postgres:15
env:
POSTGRES_DB: ch8rtests
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

qdrant:
image: qdrant/qdrant:v1.11.0
ports:
- 6333:6333
- 6334:6334

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install Python dependencies
run: |
cd backend
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Run Django system checks
run: |
cd backend
python manage.py check

- name: Collect static files
run: |
cd backend
python manage.py collectstatic --noinput

- name: Run Django migrations
run: |
cd backend
python manage.py migrate --settings=config.test_settings

- name: Run backend tests
run: |
cd backend
pytest --cov=core --cov-report=term-missing --cov-fail-under=60 --json-report --json-report-file=test-results.json

- name: Discord notification on success
if: success()
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');

// Read test results from JSON file
let testResults = 'Tests completed successfully';
try {
const testData = JSON.parse(fs.readFileSync('backend/test-results.json', 'utf8'));
const passed = testData.summary.passed || 0;
const failed = testData.summary.failed || 0;
testResults = `Tests passed: ${passed}, Failed: ${failed}`;
} catch (error) {
console.log('Could not read test results:', error.message);
testResults = 'Tests completed successfully';
}

const payload = {
embeds: [{
title: 'Backend CI - Tests Passed',
description: `Branch: **${process.env.GITHUB_REF_NAME}**\nCommit: [${process.env.GITHUB_SHA.substring(0, 7)}](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA})\n${testResults}`,
color: 3066993,
timestamp: new Date().toISOString()
}]
};

const webhookUrl = process.env.DISCORD_TEST_WEBHOOK_URL;
console.log('Discord webhook URL available:', !!webhookUrl);
if (webhookUrl) {
console.log('Sending Discord notification...');
const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
console.log('Discord response status:', response.status);
if (!response.ok) {
console.error('Failed to send Discord notification:', response.status, response.statusText);
} else {
console.log('Discord notification sent successfully');
}
} else {
console.log('Discord webhook URL not found');
}
env:
DISCORD_TEST_WEBHOOK_URL: ${{ secrets.DISCORD_TEST_WEBHOOK_URL }}

- name: Discord notification on failure
if: failure()
uses: actions/github-script@v6
with:
script: |
const payload = {
embeds: [{
title: 'Backend CI - Tests Failed',
description: `Branch: **${process.env.GITHUB_REF_NAME}**\nCommit: [${process.env.GITHUB_SHA.substring(0, 7)}](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${process.env.GITHUB_SHA})\nTests failed. Check the logs for details.`,
color: 15158332,
timestamp: new Date().toISOString()
}]
};

const webhookUrl = process.env.DISCORD_TEST_WEBHOOK_URL;
console.log('Discord webhook URL available:', !!webhookUrl);
if (webhookUrl) {
console.log('Sending Discord notification...');
const response = await fetch(webhookUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
console.log('Discord response status:', response.status);
if (!response.ok) {
console.error('Failed to send Discord notification:', response.status, response.statusText);
} else {
console.log('Discord notification sent successfully');
}
} else {
console.log('Discord webhook URL not found');
}
env:
DISCORD_TEST_WEBHOOK_URL: ${{ secrets.DISCORD_TEST_WEBHOOK_URL }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ __pycache__/
.vscode/
.DS_Store
qdrant_storage
.env
.env
.kiro/
backend/.hypothesis
.hypothesis
9 changes: 9 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
APP_SECRET_KEY='app_secret_key'
DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1
GEMINI_API_KEY=GEMINI_KEY
DB_NAME=chatterbox
DB_USER=postgres
Expand Down Expand Up @@ -29,3 +31,10 @@ API_BASE_URL=http://localhost:8000/api
FRONTEND_URL=http://localhost:3000

CLOSED_ALPHA_SIGN_UPS='["test@example.com"]'
REQUIRE_ACCOUNT_APPROVAL=False

TEST_DB_NAME=ch8rtests
TEST_DB_USER=anish
TEST_DB_PASSWORD=Anish@1996
TEST_DB_HOST=localhost
TEST_DB_PORT=5432
1 change: 1 addition & 0 deletions backend/config/celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@

app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
app.autodiscover_tasks(['core.tasks.github_tasks'])
18 changes: 15 additions & 3 deletions backend/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
SECRET_KEY = os.environ.get('APP_SECRET_KEY')
CLOSED_ALPHA_SIGN_UPS = os.environ.get('CLOSED_ALPHA_SIGN_UPS')

DEBUG = True
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'

ALLOWED_HOSTS = []
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',') if os.environ.get('ALLOWED_HOSTS') else []

ASGI_APPLICATION = "config.asgi.application"

Expand All @@ -26,6 +26,7 @@
'rest_framework.authtoken',
'channels',
'core',
'github_data',
'corsheaders',
'rest_framework_api_key',
]
Expand Down Expand Up @@ -71,6 +72,13 @@
'PASSWORD': os.getenv('PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('PORT'),
'TEST': {
'NAME': os.getenv('TEST_DB_NAME', 'test_db'),
'USER': os.getenv('TEST_DB_USER'),
'PASSWORD': os.getenv('TEST_DB_PASSWORD'),
'HOST': os.getenv('TEST_DB_HOST', 'localhost'),
'PORT': os.getenv('TEST_DB_PORT', '5432'),
}
}
}

Expand Down Expand Up @@ -106,7 +114,9 @@
'rest_framework.parsers.MultiPartParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.JSONParser',
]
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
}

CORS_ALLOWED_ORIGINS = [
Expand Down Expand Up @@ -164,3 +174,5 @@
API_BASE_URL = os.getenv("API_BASE_URL")
FRONTEND_URL = os.getenv("FRONTEND_URL")
DISCORD_SIGNUP_WEBHOOK_URL = os.getenv("DISCORD_SIGNUP_WEBHOOK_URL")

REQUIRE_ACCOUNT_APPROVAL = os.getenv("REQUIRE_ACCOUNT_APPROVAL", "False").lower() == "true"
30 changes: 30 additions & 0 deletions backend/config/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os
from .settings import *

DEBUG = False

CONNECT_TO_LOCAL_VECTOR_DB = False

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('TEST_DB_NAME', 'test_db'),
'USER': os.getenv('TEST_DB_USER'),
'PASSWORD': os.getenv('TEST_DB_PASSWORD'),
'HOST': os.getenv('TEST_DB_HOST', 'localhost'),
'PORT': os.getenv('TEST_DB_PORT', '5432'),
}
}

EMAIL_BACKEND = 'django.core.mail.backends.locmem.LocMemBackend'

CELERY_TASK_ALWAYS_EAGER = True
CELERY_TASK_EAGER_PROPAGATES = True

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
3 changes: 0 additions & 3 deletions backend/core/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
from django.contrib import admin

# Register your models here.
1 change: 1 addition & 0 deletions backend/core/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .github_admin import *
Loading
Loading