From 123895103bd55dbb7140c98ed6f19a4bbc1eb7bf Mon Sep 17 00:00:00 2001 From: Martins Veiss Date: Wed, 8 Apr 2026 13:03:35 +0300 Subject: [PATCH 1/3] fix: fetch user/group names from API in ShareKnowledgeDialog (#3990) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(ansible): add sync-code-source.yml to push code from controller to SLM (#3604) Adds a new playbook that rsync's the dev machine's local checkout to /opt/autobot/code_source on the SLM manager. Integrated into deploy-slm-manager.yml as a no-op step when controller_repo_root is not set, and active when passed via -e: ansible-playbook ... -e "controller_repo_root=/path/to/AutoBot-AI" Closes the offline-deployment gap where the pre-flight GitHub pull silently falls back to stale code_source, causing fixes that exist in the local repo to never reach the SLM. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): replace fragile group-based SLM detection in Phase 4c with filesystem stat The _is_slm_manager check relied on inventory group membership (slm_server/slm) or node_roles values, both of which are absent in temp inventories generated by per-node provisioning from the SLM UI. This caused Phase 4c to skip the nginx co-location re-render entirely, leaving / → /slm/ redirect intact even when the user frontend was deployed on the same host. Replace with filesystem-based detection: 1. Stat /etc/nginx/sites-available/autobot-slm to identify the SLM manager 2. Stat autobot-frontend/package.json to confirm co-location Both stats work regardless of inventory shape (wizard, per-node, static). Also remove the role_path fallback in the template src — the playbook_dir relative path is always correct and avoids a None-based string. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): use set_fact to override slm_colocated_frontend — include_vars beats task vars include_vars has Ansible precedence 18 while task-level vars: has 17. Loading slm_manager/defaults/main.yml (which has slm_colocated_frontend: false) via include_vars was silently overriding vars: slm_colocated_frontend: true on the template task, so the template always rendered in non-co-located mode. Replace vars: on the template task with an explicit set_fact (precedence 19) that runs after include_vars, ensuring the template sees true. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): fix code_source ownership before git reset to unblock pre-flight sync Earlier sudo cp commands left provision-fleet-roles.yml owned by root:root in code_source, causing git reset --hard to fail with EPERM. Add a pre-flight chown (become: true) that runs before the git pull so force: yes can always overwrite any root-owned file regardless of how it got there. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): preserve wizard's slm_colocated_frontend in role set_fact; fix include_vars precedence in Phase 4c slm_manager role set_fact was unconditionally overwriting slm_colocated_frontend with the file-detection result, discarding the True value the wizard set in the inventory. Change to OR expression so a wizard-supplied True is preserved. Phase 4c had include_vars (precedence 18) loading defaults with false, then task vars: (precedence 17) trying to set true — always losing. Add an explicit set_fact after include_vars so the correct value wins. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): restart backend+celery when code is synced (#3608) Sync tasks lacked notify — service ran stale code after rsync, causing 502 on /api/health and login failures. All three sync tasks now notify handlers. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): correct systemd startup ordering for all core services (#3609) - autobot-backend: redis.service → redis-stack-server.service (was silently ignored by systemd); add Wants= + network-online.target - autobot-celery: same redis fix; keep After=autobot-backend.service - autobot-slm-backend: add redis-stack-server + postgresql dependencies (had none — could race both on every boot) Co-Authored-By: Claude Sonnet 4.6 * feat(rag): per-user annotation signals for personalized RAG retrieval (#3240) (#3610) * feat(rag): per-user annotation signals for personalized RAG retrieval (#3240) * fix(rag): export GLOBAL_USER publicly, fix query_text field, Literal validation, move imports (#3240) * fix(backend): replace naive datetime.now() with UTC-aware calls (#3613) (#3615) * fix(backend): replace naive datetime.now() with UTC-aware calls throughout (#3613) Co-Authored-By: Claude Sonnet 4.6 * fix(backend): fix aware/naive datetime comparisons in agent_client + auth_middleware (#3613) - agent_client.py: default sentinel for last_health_check was datetime.min (naive); cold-start subtraction from datetime.now(tz=utc) raised TypeError — use datetime.min.replace(tzinfo=timezone.utc) instead - auth_middleware.py: fromisoformat() of pre-migration Redis strings returns naive; normalize to UTC before comparing against now(tz=utc) Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat(memory-graph): consolidate into single autobot_memory_graph with semantic search (#3612) (#3616) * feat(memory-graph): add semantic search and hybrid scoring to autobot_memory_graph (#3612) Co-Authored-By: Claude Sonnet 4.6 * fix(memory-graph): fix _parse_ft_results, SECRET_USAGE pattern, ssot_config.get, asyncio.run (#3612) - _parse_ft_results now extracts keys and _redis_search calls _fetch_entities_by_keys - Add SECRET_USAGE to secret/credential pattern in _ENTITY_TYPE_PATTERNS - Replace ssot_config.get() with getattr() (Pydantic model, not dict) - Replace asyncio.get_event_loop().run_until_complete() with asyncio.run() in all 6 test sites Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * refactor(constants): add TTL_1_HOUR/TTL_5_MINUTES and replace raw cache TTL literals (#3614) (#3617) * refactor(constants): add TTL_1_HOUR/TTL_5_MINUTES and replace raw cache TTL literals (#3614) Co-Authored-By: Claude Sonnet 4.6 * fix(constants): fix orphan TTL import, residual literals, noqa suppressions in #3617 - router.py: replace raw 300 with TTL_5_MINUTES (resolves orphan import) - advanced_cache_manager.py: add TTL_1_HOUR import, replace all 8 raw 300/3600 literals - embedding_cache.py: remove incorrect # noqa: F401 comment - token_optimizer.py: remove incorrect # noqa: F401 comment Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * feat(slm): add admin password reset to user management UI (#3625) * feat(slm): add admin password reset to user management UI (#3625) - POST /slm-users/{id}/change-password and /autobot-users/{id}/change-password backend endpoints using UserService.change_password(require_current=False) - changeSlmUserPassword() + changeAutobotUserPassword() in useSlmUserApi.ts - PasswordChangeForm: apiEndpoint prop replaces hardcoded /api/users/ URL - UserManagementSettings: key (lock) icon in each user row opens reset modal; selectedUserType tracks slm/autobot/legacy to route to correct endpoint Co-Authored-By: Claude Sonnet 4.6 * fix(slm): remove unreachable InvalidCredentialsError handler; use getSlmApiBase() for password change URLs (#3625) - Drop except InvalidCredentialsError blocks — require_current=False means the service never raises it; dead code flagged in code review - passwordChangeApiEndpoint now uses getSlmApiBase() from ssot-config instead of hardcoded /api/ prefix, fixing co-located /slm/api deployments Co-Authored-By: Claude Sonnet 4.6 --------- Co-authored-by: Claude Sonnet 4.6 * chore(frontend): add getApiBase() to ssot-config for configurable API prefix (#3628) Co-authored-by: Claude Sonnet 4.6 * fix(backend): use local time in is_business_hours and is_weekend (#3619) Co-authored-by: Claude Sonnet 4.6 * fix(backend): normalize naive datetime from Redis in knowledge_manager (#3618) Co-authored-by: Claude Sonnet 4.6 * fix(backend): normalize naive datetimes from Redis in stats and analytics (#3620) Closes #3620 Pre-#3615 Redis data stores naive datetime strings. After fromisoformat() parsing, add UTC tzinfo when tzinfo is None to prevent TypeError when comparing with UTC-aware datetime.now(tz=timezone.utc). Co-authored-by: Claude Sonnet 4.6 * chore(slm-frontend): replace hardcoded /api/ with getSlmApiBase() in 3 remaining files (#3627) Co-authored-by: Claude Sonnet 4.6 * chore(frontend): adopt getApiBase() in composables (#3630) - Added getApiBase() to ssot-config.ts (prerequisite from #3628) - Replaced ~133 hardcoded '/api/' occurrences across 36 composable files - All replacements use template literals: `${getApiBase()}/path` - Imports added or extended in each modified file Co-authored-by: Claude Sonnet 4.6 * chore(frontend): adopt getApiBase() in service and utils layer (#3629) * chore(frontend): adopt getApiBase() in service and utils layer (#3629) Co-Authored-By: Claude Sonnet 4.6 * chore(frontend): remove duplicate getApiBase() — defined in #3632 (#3629) --------- Co-authored-by: Claude Sonnet 4.6 * chore(frontend): adopt getApiBase() in stores, models, and components (#3631) (#3641) - Added getApiBase() to ssot-config.ts (prerequisite from #3628) - Replaced 110 hardcoded /api/ occurrences across 8 files: - stores/useKnowledgeStore.ts (7 paths) - stores/usePermissionStore.ts (10 paths) - stores/useUserStore.ts (2 paths) - models/repositories/KnowledgeRepository.ts (36 paths) - models/repositories/ChatRepository.ts (12 paths) - models/repositories/SystemRepository.ts (37 paths) - models/repositories/ApiRepository.ts (5 paths incl. cache keys) - components/ChatInterface.ts (1 path) Co-authored-by: Claude Sonnet 4.6 * test: replace asyncio.get_event_loop() with asyncio.run() (#3605) Co-authored-by: Claude Sonnet 4.6 * refactor(helpers): add extra_data support to TaskResult (#3564) Co-authored-by: Claude Sonnet 4.6 * refactor(helpers): remove duplicate raise_not_found_error in catalog_http_exceptions (#3566) Co-authored-by: Claude Sonnet 4.6 * refactor(helpers): cap exponential backoff via TimingConstants (#3565) Co-authored-by: Claude Sonnet 4.6 * refactor(backend): remove dead AgentThresholds import and replace magic 0.8 in orchestrator.py (#3607) Co-authored-by: Claude Sonnet 4.6 * refactor(agents): declare _get_system_prompt @abstractmethod in StandardizedAgent (#3606) Co-authored-by: Claude Sonnet 4.6 * chore(ci): align isort line_length with Black at 120 in pyproject.toml (#3408) Align pyproject.toml isort line_length from 100 to 120 to match Black's line-length and the explicit --line-length=120 args in pre-commit and CI. Black and isort hooks were already present in both pre-commit-config.yaml and code-quality.yml; this fix resolves the config inconsistency that caused isort --settings-path=. to use a conflicting line_length value. Co-authored-by: Claude Sonnet 4.6 * fix(ansible): sync standalone autobot_shared on backend deploy (#3649) The backend role only synced code_source/autobot_shared/ into backend_install_dir/autobot_shared/ (the in-backend copy). The separate /opt/autobot/autobot_shared/ directory — resolved via PYTHONPATH by Celery workers and other services — was never updated, causing ModuleNotFoundError for newly added modules (pagination.py, task_result.py, error_boundaries.py, alert_cooldown.py). Add a synchronize task immediately after the existing backend sync that also pushes to the standalone path, plus a file ownership fix task. Introduce backend_shared_standalone_dir default (/opt/autobot/autobot_shared) so the path is a named variable, not a hardcoded literal. Co-authored-by: Claude Sonnet 4.6 * chore(frontend): remove duplicate getApiBase() declarations from ssot-config.ts (#3631) All target files (stores, model repositories, ChatInterface) already had getApiBase() imported and in use from prior development. Fixed the only remaining issue: three duplicate getApiBase() function declarations in ssot-config.ts (added by parallel PRs #3628-#3630) — reduced to a single canonical declaration. Co-authored-by: Claude Sonnet 4.6 * chore(tests): replace hardcoded localhost:8001 with get_test_backend_url() helper Co-authored-by: Claude Sonnet 4.6 * chore(slm-frontend): replace hardcoded /autobot-api/ with getBackendUrl() Co-authored-by: Claude Sonnet 4.6 * fix(backend): guard context_window_manager against list-format llm_models.yaml (#3647) PR #3588 changed models: to a list-based registry; ContextWindowManager still accessed it as a dict, crashing all workers on startup. Detect list format and fall back to default context-window config. Co-Authored-By: Claude Sonnet 4.6 * fix(slm): pass auth token to PasswordChangeForm — was always sending empty Bearer PasswordChangeForm read localStorage.getItem('authToken') which is never set; SLM auth store uses key 'slm_access_token' in sessionStorage. Added authToken prop; UserManagementSettings passes authStore.token. Co-Authored-By: Claude Sonnet 4.6 * fix(ansible): guard groups['database'] lookup in deploy-backend-local.yml (#3651) Wrap the hostvars lookup with an inline if-guard so AnsibleUndefinedVariable is never raised when the 'database' inventory group is absent or empty. Falls back to 127.0.0.1 in both cases. Co-authored-by: Claude Sonnet 4.6 * fix(backend): default SLM_URL to localhost and deduplicate startup warning (#3655) On co-located deployments SLM_URL is not set, so the backend now defaults to http://127.0.0.1:8000 instead of None, preventing silent SLM client failures. The startup warning is deferred to init_slm_client() and gated by a module-level flag, so it fires at most once per process instead of 3×. Co-authored-by: Claude Sonnet 4.6 * refactor(backend): give context_window_manager its own config YAML (#3650) Decouple ContextWindowManager from llm_models.yaml (which uses a list schema for the YAML-model-registry feature) by introducing a dedicated config/context_windows.yaml with the dict-keyed schema the manager has always expected. Covers all 40+ models from llm_models.yaml with realistic context_window_tokens, max_output_tokens, and message_budget values. Default config path updated from config/llm_models.yaml to config/context_windows.yaml. Co-authored-by: Claude Sonnet 4.6 * fix(backend): add TTL_24_HOURS to chat_workflow/manager.py import (#3646) PR #3617 added TTL_24_HOURS usage in manager.py but the import from constants.ttl_constants was never updated — NameError crashes all workers. Co-Authored-By: Claude Sonnet 4.6 * refactor(agents): cap exponential backoff in agent_client.py via exponential_backoff_delay (#3658) Co-authored-by: Claude Sonnet 4.6 * refactor(backend): remove dead doc_generation_threshold attribute (#3656) Co-authored-by: Claude Sonnet 4.6 * fix(backend): fix REDIS_HOST → AUTOBOT_REDIS_HOST in chat history modules Co-authored-by: Claude Sonnet 4.6 * chore(frontend): remove duplicate getApiBase() declarations from ssot-config.ts (#3628) Co-authored-by: Claude Sonnet 4.6 * chore(slm-frontend): replace hardcoded /api/ with getSlmApiBase() (#3627) (#3676) Co-authored-by: Claude Sonnet 4.6 * feat(ansible): add pre-flight code_source sync to deploy playbooks (#3604) Create shared pre-flight-code-sync.yml extracted from provision-fleet-roles.yml Play 0; import it at the top of deploy-full.yml, deploy-aiml.yml, deploy-backend-local.yml, and deploy-backend-remote.yml so standalone deployments always pull the latest code before roles run. GitHub sync uses ignore_errors so air-gapped SLMs fall back to existing code_source with a visible warning and staleness report. Co-authored-by: Claude Sonnet 4.6 * feat(slm): add component selector to File Drift Check UI (#3433) Add a