Previously start.bas was prevented from re-running via a Redis flag
(set for 24h). This prevented switchers from being re-sent when
users reloaded the page. Now start.bas executes unconditionally
on every WebSocket connection and every first message.
The switchers were stored in Redis with the DB session ID (session.id)
but retrieved using the WebSocket session ID, causing switchers to
never be found. Fix by saving session.id before the move into
spawn_blocking closure.
- Fix DriveMonitor skipping .bas files that exist but have indexed=false
and same ETag (needs_reindex was computed but not used for bas sync)
- Mark bas files as indexed after successful sync to work dir
- Update INFRA.md: MinIO connection setup (port 9100, creds from drive.service)
- Remove erroneously created bottemplates start.bas (bots live in MinIO)
- Add start.bas with ADD SWITCHER keywords (tables, list, cards)
- Remove /opt/gbo/data references from AGENTS.md and INFRA.md
- Bots are stored in MinIO drive, not in /opt/gbo/data
- Update infrastructure paths documentation
- Fixed KB indexing logic that skipped re-index when DB showed docs but Qdrant was empty
- Added Qdrant collection validation before skipping indexing
- Updated AGENTS.md with correct log locations for staging/production
- Deployed to staging, awaiting CI completion
- Next: monitor chat.stage for KB search functionality
Continuation instructions:
1. Check CI status on ALM (action_run table in PROD-ALM DB)
2. Verify botserver binary updated on staging system container
3. Test KB search: ask question about PDF content in bot
4. Check /opt/gbo/logs/out.log for DriveMonitor indexing activity
5. Verify Qdrant collection has indexed_vectors_count > 0
Root cause: handle_gbkb_change() only checked DB document_count, not Qdrant state
Fix: Added get_collection_info() call to validate Qdrant has points before skipping
- Check Qdrant collection exists and has points before skipping re-index
- Previously only checked database document_count, causing issues when:
* Qdrant collection was deleted but DB still showed docs
* Vectors were not properly indexed (indexed_vectors_count = 0)
* New PDFs added to existing KB folder
- Now validates both DB and Qdrant state before deciding to skip indexing
- Logs warning when DB and Qdrant are out of sync
Fixes issue where KB from PDF files in drive were not being indexed to Qdrant
- Remove 'ADD SWITCHER' → 'ADD_SWITCHER' early replacement in preprocess_basic
which prevented convert_multiword_keywords from properly handling the AS keyword
- Add ADD_SWITCHER (underscore) pattern alongside ADD SWITCHER (space) pattern
so both forms are correctly converted to Rhai custom syntax
- Fix skip condition: only skip ADD_SWITCHER lines when 'as' is lowercase
(already properly converted), not when AS is uppercase (needs conversion)
- Fix ADD\s+MEMBER double-escaped regex → ADD_MEMBER + ADD\s+MEMBER patterns
- Add CLEAR SWITCHERS pattern to convert_multiword_keywords
- Add CLEAR_SWITCHERS() skip condition
Closes#495
- Add is_public column to bots table (migration 6.3.2-01)
- Add user_organizations to Diesel schema for org membership lookup
- Implement check_bot_access(): public bots allow all users, private bots
require user membership in the bot's organization via user_organizations
- Wire access check into websocket_handler before WS upgrade
- Read is_public from bots table instead of bot_configuration
- Add database_name field to Bot model
- Added SWITCHER_TOGGLE message type (8) for reprocessing last user message with active switchers
- Backend: Handler fetches last user question from DB, mutates message in-place, injects switcher prompts into system_prompt
- Backend: Switcher replays skip message_history save to avoid duplication
- Frontend: toggleSwitcher() sends SWITCHER_TOGGLE when input empty, sendMessage() when text present
- Frontend: Added TOOL_EXEC and SWITCHER_TOGGLE to MessageType constants
- Fixed session_id shadowing bug in DB query (used session_id_for_query)
- Preserves conversation history for LLM context when reprocessing with switchers
The compiler outputs ADD_SWITCHER "x" as "y" format but the keyword
was registered as a plain Rhai function expecting add_switcher(x, y).
Changed to register_custom_syntax matching the output format, consistent
with ADD_SUGGESTION and CLEAR SWITCHERS patterns.
Fixes#495
- Split partials/chat.html (1513→70 lines) into 8 JS modules:
chat-state.js, chat-switchers.js, chat-mentions.js,
chat-messages.js, chat-suggestions.js, chat-theme.js,
chat-websocket.js, chat-init.js
- Centralized state in ChatState global object
- Switcher chips auto-activate on switch_context suggestion action
- active_switchers sent in every WS message payload
- Removed old chat-main.js (merged into modules)
- Split vibe.html into vibe/ module directory with CSS extraction
- Updated standalone chat/chat.html to use same modules
The ADD_SWITCHER keyword was generating comma-separated params (ADD_SWITCHER(id, label))
instead of the expected Rhai custom syntax (ADD_SWITCHER id as label).
This fix adds special handling in the multiword processor to output the correct
format when processing ADD_SWITCHER with 2 parameters.
Fixes#495
- ADD_SWITCHER "tables" now works (label defaults to switcher ID)
- ADD_SWITCHER "tables" AS "Tabelas" still works (custom label)
- Follows same pattern as ADD_SUGGESTION simple/AS forms
- Fixes#495
- Event listeners were lost when renderSwitchers() re-created DOM
- Now using event delegation on parent container
- Listener attached once, persists across re-renders
- Added logging to verify active_switchers payload
Fixes switcher toggle not persisting and LLM modifier not being sent.
- chat.html reduced from 1623 lines to 59 lines
- Created chat-switchers.js for switcher state management
- Created chat-messages.js for message rendering
- Created chat-main.js for initialization and coordination
- Added console logging to debug switcher toggle functionality
- Follows AGENTS.md 450-line limit rule
- AppConfig::default() and from_env() now read PORT from environment
- DriveConfig loads from Vault first, falls back to env vars for development
- DATABASE_URL must be set (from Vault via .env in production)
- No more hardcoded 8080 - reads from PORT env var
- Removed hardcoded paths like /opt/gbo/data, now from env or reasonable defaults
- Development still works with defaults, production requires Vault via .env
- Changed AppConfig::from_env() to read PORT from std::env
- Falls back to 8080 if PORT not set
- Also reads HOST, SITE_PATH, DATA_DIR from environment
- Fixes issue where botserver ignored .env PORT=5858 setting