Skip to content

Commit 6dbb6c5

Browse files
authored
Merge pull request #45 from stenwire/dev
Dev
2 parents 0351c9f + c473c29 commit 6dbb6c5

8 files changed

Lines changed: 96 additions & 10 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""added_is_active_column
2+
3+
Revision ID: 2ca6c95dd95b
4+
Revises: bcb063b582c0
5+
Create Date: 2026-01-04 21:00:58.319341
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
from sqlalchemy.dialects import postgresql
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = '2ca6c95dd95b'
16+
down_revision: Union[str, Sequence[str], None] = 'bcb063b582c0'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
"""Upgrade schema."""
23+
# ### commands auto generated by Alembic - please adjust! ###
24+
with op.batch_alter_table('widget_settings', schema=None) as batch_op:
25+
batch_op.add_column(sa.Column('is_active', sa.Boolean(), nullable=True))
26+
27+
# ### end Alembic commands ###
28+
29+
30+
def downgrade() -> None:
31+
"""Downgrade schema."""
32+
# ### commands auto generated by Alembic - please adjust! ###
33+
with op.batch_alter_table('widget_settings', schema=None) as batch_op:
34+
batch_op.drop_column('is_active')
35+
36+
# ### end Alembic commands ###

backend/app/api/widget.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class WidgetUpdate(BaseModel):
4343
whatsapp_number: Optional[str] = None
4444
max_messages_per_session: Optional[int] = None
4545
max_sessions_per_day: Optional[int] = None
46+
max_sessions_per_day: Optional[int] = None
4647
whitelisted_domains: Optional[List[str]] = None
48+
is_active: Optional[bool] = None
4749

4850

4951
def normalize_url(url: str) -> str:
@@ -174,6 +176,9 @@ def update_my_widget_settings(
174176
if settings.whitelisted_domains is not None:
175177
widget.whitelisted_domains = settings.whitelisted_domains
176178

179+
if settings.is_active is not None:
180+
widget.is_active = settings.is_active
181+
177182
db.commit()
178183
db.refresh(widget)
179184
db.commit()
@@ -586,6 +591,7 @@ async def process_chat_message(db: Session, widget: WidgetSettings, guest: Guest
586591

587592

588593
try:
594+
print(f"Widget: Calling run_conversation with user_id={widget.user_id} (Type: {type(widget.user_id)})")
589595
ai_response_text = await run_conversation(
590596
message=message_text,
591597
user_id=widget.user_id,

backend/app/models/widget.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class WidgetSettings(Base):
2626
whatsapp_enabled = Column(Boolean, default=False)
2727
whatsapp_number = Column(String, nullable=True)
2828

29+
# Feature Flags
30+
is_active = Column(Boolean, default=True) # Master toggle to enable/disable widget
31+
2932
# Denormalized Business Fields (for easier widget access)
3033
logo_url = Column(String, nullable=True)
3134

backend/app/schemas/widget.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class WidgetConfigResponse(BaseModel):
6868
max_sessions_per_day: Optional[int] = 5
6969
whitelisted_domains: Optional[List[str]] = None
7070
logo_url: Optional[str] = None
71+
is_active: Optional[bool] = True
7172

7273
class Config:
7374
from_attributes = True

backend/app/services/agent_system/tools.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def get_context(user_input: str, tool_context: ToolContext) -> str:
4141

4242
# Retrieve context with user_id and api_key
4343
context_chunks = rag_service.query(text=user_input, user_id=user_id, api_key=api_key)
44+
print(f"--- Tool: RAG Service returned {len(context_chunks)} chunks ---")
4445
context_text = "\n\n".join(context_chunks)
4546
return context_text
4647

backend/app/services/rag_service.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,27 @@ def query(self, text: str, user_id: str, api_key: Optional[str] = None, db: Sess
167167
return []
168168

169169
try:
170-
query_embedding = self._get_query_embedding(text, api_key)
171-
# Query with user_id filter and query_embedding
172-
# Wrap in list as vector_db expects list of embeddings
173-
results = self.vector_db.query(query_embeddings=[query_embedding], where={"user_id": user_id})
174-
175-
if results and results['documents']:
176-
return results['documents'][0]
177-
return []
170+
print(f"RAG Service: Querying for user_id={user_id}")
171+
query_embedding = self._get_query_embedding(text, api_key)
172+
# Query with user_id filter and query_embedding
173+
# Wrap in list as vector_db expects list of embeddings
174+
175+
where_clause = {"user_id": user_id}
176+
print(f"RAG Service: Executing vector_db.query with where={where_clause}")
177+
178+
results = self.vector_db.query(query_embeddings=[query_embedding], where=where_clause)
179+
180+
print(f"RAG Service: Raw results keys: {results.keys() if results else 'None'}")
181+
if results and results.get('documents'):
182+
doc_count = len(results['documents'][0])
183+
print(f"RAG Service: Found {doc_count} documents.")
184+
# console log first few chars of first doc if exists
185+
if doc_count > 0:
186+
print(f"RAG Service: First doc snippet: {results['documents'][0][0][:50]}...")
187+
return results['documents'][0]
188+
189+
print("RAG Service: No documents found.")
190+
return []
178191
except Exception as e:
179192
print(f"Error querying RAG: {e}")
180193
return []

frontend/src/app/dashboard/widget-settings/page.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ interface WidgetSettings {
2828
max_messages_per_session?: number;
2929
max_sessions_per_day?: number;
3030
whitelisted_domains?: string[];
31+
is_active?: boolean;
3132
}
3233

3334
type Tab = 'business' | 'appearance' | 'installation';
@@ -98,7 +99,8 @@ export default function WidgetSettingsPage() {
9899
whatsapp_number: settings.whatsapp_number,
99100
max_messages_per_session: settings.max_messages_per_session,
100101
max_sessions_per_day: settings.max_sessions_per_day,
101-
whitelisted_domains: settings.whitelisted_domains
102+
whitelisted_domains: settings.whitelisted_domains,
103+
is_active: settings.is_active
102104
}),
103105
});
104106
if (res.ok) {
@@ -279,6 +281,24 @@ export default function WidgetSettingsPage() {
279281
</div>
280282

281283
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
284+
<div className="md:col-span-2 bg-[var(--bg-secondary)] p-6 rounded-[var(--radius-md)] border border-[var(--border-subtle)] flex items-center justify-between">
285+
<div>
286+
<h3 className="text-sm font-bold text-[var(--text-primary)]">Widget Status</h3>
287+
<p className="text-sm text-[var(--text-secondary)] mt-1">
288+
{settings?.is_active ? 'Widget is currently active and visible on your site.' : 'Widget is disabled and hidden from your site.'}
289+
</p>
290+
</div>
291+
<label className="relative inline-flex items-center cursor-pointer">
292+
<input
293+
type="checkbox"
294+
className="sr-only peer"
295+
checked={settings?.is_active ?? true}
296+
onChange={(e) => settings && setSettings({ ...settings, is_active: e.target.checked })}
297+
/>
298+
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-green-300 dark:peer-focus:ring-green-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-[var(--brand-primary)]"></div>
299+
</label>
300+
</div>
301+
282302
<div>
283303
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">Primary Brand Color</label>
284304
<div className="flex gap-3 items-center">

frontend/src/app/widget.js/route.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ export async function GET() {
3939
if (!res.ok) throw new Error("Failed to load widget config");
4040
return res.json();
4141
})
42-
.then(config => initWidget(config))
42+
.then(config => {
43+
if (config.is_active === false) {
44+
console.log("Taimako.AI Widget: Widget is currently disabled.");
45+
return;
46+
}
47+
initWidget(config);
48+
})
4349
.catch(err => console.error("Taimako.AI Widget Error:", err));
4450
4551
function initWidget(config) {

0 commit comments

Comments
 (0)