Commit Graph

336 Commits

Author SHA1 Message Date
Rodribm10
d0d08ed662 feat(lifecycle): implement DispatcherJob
Replace no-op stub with full perform body: find delivery by id, skip if
blank, delegate to Captain::Lifecycle::Dispatcher#call. Add retry_on
with polynomially_longer backoff (3 attempts). Spec covers dispatcher
delegation and graceful skip for missing records.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:20:32 -03:00
Rodribm10
0d4583a21a feat(lifecycle): add Dispatcher service with guards→render→send pipeline
Orchestrates guards → render (Liquid) → send pipeline for one delivery.
Handles skip, reschedule, sent, failed states and re-enqueues on reschedule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:53:01 -03:00
Rodribm10
6d84a7586b feat(lifecycle): add MinInterval and CustomerReplied guards
Implement guards following the same pass/reschedule/too_stale pattern as QuietHours.
Also fix belongs_to :conversation on Delivery to use class_name: '::Conversation' to avoid namespace resolution failure inside Captain::Lifecycle module.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:49:22 -03:00
Rodribm10
fcdc2054b5 feat(lifecycle): add QuietHours guard with 2h staleness limit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:44:39 -03:00
Rodribm10
823008a1cd feat(lifecycle): add Guards::Base e 3 guards simples (ReservationActive, OptOutLabel, MaxPerReservation)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:42:10 -03:00
Rodribm10
f6aa39921a feat(lifecycle): add ContextBuilder for Liquid render variables
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:39:35 -03:00
Rodribm10
8e0a06246b feat(lifecycle): wire Captain::Reservation lifecycle hooks
Add after_commit callbacks to call Captain::Lifecycle::Scheduler on
create, status change (cancelled/no_show), and check_in_at change.
Each handler wraps in rescue StandardError to preserve existing behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:37:23 -03:00
Rodribm10
bb4631f427 feat(lifecycle): add Scheduler service and DispatcherJob stub
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:35:31 -03:00
Rodribm10
4a88f7f517 feat(lifecycle): add EventResolver service
Pure function mapping reservation events to timestamps; used by Scheduler (T9) to compute fire_at.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:31:47 -03:00
Rodribm10
a4472b80b9 feat(lifecycle): add concierge_* accessors to Captain::Unit 2026-04-15 01:23:40 -03:00
Rodribm10
41bbf14d57 feat(lifecycle): add Captain::Lifecycle::Delivery model with state helpers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:21:11 -03:00
Rodribm10
ffc5ac7fb8 feat(lifecycle): add Captain::Lifecycle::Rule model with filter matching
TDD: 16 examples passing. Adds EVENTS constant, active/for_event scopes,
and matches_reservation? with unit_ids/categorias/permanencias filters.
Also adds captain_reservation factory used by the spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:18:17 -03:00
Rodribm10
6ee3fcd4ef feat(lifecycle): add Captain::Lifecycle::Config model 2026-04-15 01:14:19 -03:00
Rodribm10
ea8ff83034 feat: Captain::PixCharge posta nota interna quando PIX eh gerado
Antes so existiam 2 notas automaticas:
  1. 'Nova reserva criada' (from Captain::Reservation after_create_commit)
  2. 'Pagamento confirmado' (from Captain::Payments::ConfirmationService)

Adiciona uma terceira entre elas: 'PIX enviado, aguardando pagamento'
(from Captain::PixCharge after_create_commit). A atendente ve no
timeline: reserva -> pix enviado -> pix pago.
2026-04-14 20:09:20 -03:00
Rodribm10
996704350b feat: Captain::Reservation callback cria nota interna automaticamente
Cobre ambos os caminhos (generate_pix_tool e PublicReservationsController):
toda reserva criada recebe um after_create_commit que posta uma mensagem
privada na conversa com os detalhes (suite, check-in, valores, ID).

Remove a criacao duplicada do PublicReservationsController.
2026-04-14 19:53:21 -03:00
Rodribm10
f8d64b6992 feat: link enviado como mensagem direta + email extraction + contact metadata auto-persist
- GeneratePixTool: envia payment_link como mensagem outgoing direta (bypassa
  hallucination de [Link do Pix] placeholder pela LLM)
- GeneratePixTool: extrai email das mensagens recentes via regex e persiste
  em contact.email
- GenerateReservationLinkTool: mesmo padrao de envio direto do link
- Captain::Reservation: after_create_commit callback atualiza
  ultima_suite/permanencia/reserva_em/total_reservas em contact.custom_attributes
  (aparece no painel lateral)
2026-04-14 13:44:13 -03:00
Rodribm10
7c9411a0b0 feat: persiste metadados do cliente em custom_attributes + tool blindada
- Controller grava cpf/ultima_suite/ultima_permanencia/ultima_reserva_em/total_reservas
  em contact.custom_attributes (aparece no painel lateral do Chatwoot)
- GenerateReservationLinkTool exige marca/unidade/categoria/permanencia/checkin_at;
  retorna erro se Jasmine chamar sem esses dados
2026-04-14 13:26:02 -03:00
Rodribm10
37480b1fc5 feat: GenerateReservationLinkTool le contato da conversa automaticamente
Mirrors CheckPixPaymentTool resolve_conversation helpers. No fallback,
Jasmine so precisa passar categoria/permanencia/checkin_at - a tool
preenche nome/telefone/cpf/email a partir do contato.
2026-04-14 12:33:40 -03:00
Rodribm10
8ec1b652fa feat: tool GenerateReservationLink para jasmine gerar links prefill
Cria Captain::Tools::GenerateReservationLinkTool que constrói URL
pré-preenchida do reserva-1001 com dados coletados em conversa.
Registra entrada generate_reservation_link em tools.yml e documenta
RESERVA_1001_BASE_URL no .env.example.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 10:35:43 -03:00
Rodrigo Borba
84fff38d94 refactor: move notification templates de units para inboxes
- Arquitetura corrigida: templates agora pertencem à inbox (WhatsApp),
  não à unidade PIX (que é uma config financeira, não de mensagens)
- Migration: troca FK captain_unit_id -> inbox_id (up/down explícito)
- Model: belongs_to :inbox; scope for_inbox
- Controller: escopo via account.inboxes.find(inbox_id)
- Rotas: move de captain/units/:id → inboxes/:id/notification_templates
- Scanner job: joins(:conversation).where(conversations: {inbox_id:})
- UI: página /captain/notifications com seletor de inbox no topo
  (chips clicáveis, templates carregam por watch no selectedInboxId)
- i18n PT/EN: novas keys INBOX_LABEL, SELECT_INBOX_HINT, EMPTY
2026-03-01 22:17:27 -03:00
Rodrigo Borba
44908f32d1 feat: sistema de notificações de reserva com templates configuráveis
- Adiciona check_in_at/duration_hours ao schema do tool CreateReservationIntent
  para que a IA capture o horário EXATO de chegada informado pelo cliente
- Cria captain_notification_templates: label, content, timing_minutes,
  timing_direction (before/after), active, position
- Implementa SendNotificationService com interpolação de variáveis
  (guest_name, check_in_time, check_out_time, suite_name, unit_name)
- Implementa NotificationScannerJob (Sidekiq-cron a cada 5min) com
  janela de tolerância de ±5min e idempotência via metadata JSONB
- API REST: /captain/units/:unit_id/notification_templates (CRUD)
- Store Vuex captainNotificationTemplates + API client
- UI: página de gestão de templates com editor inline e botão '+'
- Configura rota captain_settings_notifications
- i18n PT/EN para todas as strings novas
- Rubocop e ESLint: zero offenses
2026-03-01 21:53:11 -03:00
Rodrigo Borba
dc3d1bbcf7 Fix(Captain): Correção na geração de relatórios de IA e adição do status Confirmada nas Reservas 2026-03-01 15:40:10 -03:00
Rodrigo Borba
7108bb135e feat(captain): permite criacao manual de reserva via painel e conversa 2026-03-01 03:07:44 -03:00
Rodrigo Borba
96cf48d893 feat(ai): implement dynamic debounce with sidekiq and concurrency locking with redis 2026-03-01 02:04:55 -03:00
Rodrigo Borba
b546c75f97 fix: Resolve erros de linting e conclui as correções de prompt customizado 2026-02-27 13:02:44 -03:00
Rodrigo Borba
dfa6d58e98 refactor: Simplifica a declaração da classe SystemPromptLeakError e adiciona o comentário frozen_string_literal: true. 2026-02-27 11:59:45 -03:00
Rodrigo Borba
c1b8534ea7 feat: Adiciona prompt orquestrador configurável para assistentes Captain com editor UI. 2026-02-27 11:57:59 -03:00
Rodrigo Borba
58f348c98d feat: Implementa funcionalidade de Relatórios Captain, permitindo a geração de insights por caixa de entrada e unidade, com interface de usuário dedicada. 2026-02-27 10:16:53 -03:00
Rodrigo Borba
039b9e116d fix(captain): add send_suite_images rules to scenario.liquid template
The [Galeria de Fotos] rules previously added to assistant_response_generator
only apply to the legacy V1 chat service. In V2 (captain_integration_v2),
scenario agents use scenario.liquid as their system prompt template, not
assistant_response_generator.

This adds conditional rules to scenario.liquid (matching the existing pattern
for faq_lookup and check_pix_payment) that activate for any scenario that
has the send_suite_images tool:
- Infer suite_category vs suite_number from context, no confirmation needed
- Never announce photo sending before the tool confirms images were found

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 10:14:12 -03:00
Rodrigo Borba
d13656e499 fix: bloqueio de vazamento de system prompt nas conversas publicas
- Adiciona SYSTEM_PROMPT_LEAK_PATTERNS no ResponseBuilderJob para detectar quando o LLM retornou o system prompt em vez de uma resposta ao cliente
- Filtra mensagens contaminadas do historico de conversas antes de enviar ao LLM (evita contaminacao em espiral)
- Adiciona guardrail no validate_message_content! que redireciona para handoff humano em caso de vazamento detectado
- Cria Captain::Errors::SystemPromptLeakError para tipagem do erro
- Atualiza assistant.liquid com tags INSTRUCOES_INTERNAS e REGRA CRITICA para instruir o LLM a nao reproduzir o system prompt como resposta
2026-02-27 09:50:02 -03:00
Rodrigo Borba
87bff8126c feat(captain): add AI reports page with insights generation
Implementa a página Relatórios IA com geração de análises semanais
por IA baseadas nas conversas de cada unidade/caixa de entrada.

Funcionalidades:
- Página /settings/captain/reports com dois tabs (Insights IA / Operacional)
- Botão "Gerar Análise" que enfileira job Sidekiq
- Filtro por unidade ou caixa de entrada
- Exibe insights com status (pendente/processando/concluído/falhou)
- Mostra top_topics, ai_failures e period_summary
- Estado vazio com CTA para gerar primeiro relatório

Backend:
- InsightsController com endpoints index/show/generate
- GenerateInsightsJob que processa conversas com LLM
- ConversationInsightService com chunking e merge inteligente
- Migração para adicionar inbox_id à tabela captain_conversation_insights
- Link sidebar "Relatórios IA" em /settings/captain/reports

Frontend:
- Vuex store captainReports com actions/mutations/getters
- API client CaptainReportsAPI (getInsights, generateInsight)
- i18n en e pt_BR para CAPTAIN_REPORTS.*

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 07:05:58 -03:00
Rodrigo Borba
972fc5c67b feat(captain): improve suite photo search accuracy with AI guidance
Melhorias na ferramenta send_suite_images para resolver confusão entre
categoria e número de suíte:

1. **Descrições de parâmetros mais claras**
   - suite_category: exemplos específicos (Hidromassagem, ALEXA, STILO)
   - suite_number: apenas números (101, 102, 103) - remove exemplos confusos

2. **Instruções explícitas no system prompt**
   - Seção [Galeria de Fotos] com regras claras
   - Prioriza suite_category quando ambíguo
   - Evita confirmações desnecessárias com cliente

3. **Mensagens de erro melhoradas**
   - Sugere buscar por categoria quando busca por número falha
   - Feedback mais útil para a IA

Resultado esperado:
- Cliente: "Me manda foto da suite Alexa"
- IA: busca por suite_category="Alexa" ✓ (sem pedir confirmação)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-26 23:04:28 -03:00
Rodrigo Borba
c022f4ce5d feat(units): allow one Pix unit to link to multiple inboxes (N:N) 2026-02-26 21:33:23 -03:00
Rodrigo Borba
8c456e7e98 fix(ai): add current date/time context and enforce strict suite photo filtering 2026-02-26 19:12:25 -03:00
Rodrigo Borba
f2fb40afaa ajuste galeria de imagens 2026-02-26 15:27:25 -03:00
Rodrigo Borba
f12e1d6545 fix(captain): integracao do delay do inbox com resposta humanizada e remocao de race conditions 2026-02-26 12:47:41 -03:00
Rodrigo Borba
ccc1bdf35f Fix Wuzapi webhook handling 2026-02-26 10:49:00 -03:00
Rodrigo Borba
389cbcbb61 feat: bypass user limit validation to allow unlimited agents 2026-02-25 21:40:18 -03:00
Rodrigo Borba
0e7dc282c4 chore(style): fix rubocop offenses and update typing indicators 2026-02-25 15:06:58 -03:00
gabrieljablonski
9a4c5058f3 Merge branch 'main' into chore/merge-upstream-4.11.0 2026-02-17 23:05:26 -03:00
Aakash Bakhle
dae4f3ee13
fix: move llm call of captain outside transaction (#13559)
# Pull Request Template

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes:

The LLM call was wrapped in a transaction. This is an anti-pattern and
caused idle-connections which PG eventually terminated with
`PQconsumeInput() FATAL: terminating connection due to
idle-in-transaction timeout`

This resulted in activity messages being missing in some conversations
on captain handoff, failures queueing up for retry and captain
responding long after conversation was marked open/snoozed.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.
locally and specs


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-02-17 18:12:14 +05:30
Aakash Bakhle
138840a23f
fix: typo in metadata key in captain v2 (#13558)
# Pull Request Template

## Description

## Type of change

typo fix

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
2026-02-17 15:40:50 +05:30
Aakash Bakhle
aa7e3c2d38
feat: langfuse logging improvements (#13534)
Langfuse logging improvements

## Description

Please include a summary of the change and issue(s) fixed. Also, mention
relevant motivation, context, and any dependencies that this change
requires.
Fixes # (issue)
For reply suggestion: the errors are being stored inside output field,
but observations should be marked as errors.
For assistant: add credit_used metadata to filter handoffs from
ai-replies
For langfuse tool call: add `observation_type=tool`

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)
## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

before:
<img width="1028" height="57" alt="image"
src="https://github.com/user-attachments/assets/70f6a36e-6c33-444c-a083-723c7c9e823a"
/>

after:
<img width="872" height="69" alt="image"
src="https://github.com/user-attachments/assets/1b6b6f5f-5384-4e9c-92ba-f56748fec6dd"
/>

`credit_used` to filter handoffs from AI replies that cause credit usage
<img width="1082" height="672" alt="image"
src="https://github.com/user-attachments/assets/90914227-553a-4c03-bc43-56b2018ac7c1"
/>


set `observation_type` to `tool`
<img width="726" height="1452" alt="image"
src="https://github.com/user-attachments/assets/e639cc9b-1c6c-4427-887e-23e5523bf64f"
/>


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
2026-02-17 13:30:04 +05:30
Aakash Bakhle
3874383698
feat: insrument captain v2 (#13439)
# Pull Request Template

## Description

Instruments captain v2

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

Local testing:
<img width="864" height="510" alt="image"
src="https://github.com/user-attachments/assets/855ebce5-e8b8-4d22-b0bb-0d413769a6ab"
/>



## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2026-02-17 13:28:26 +05:30
Sojan Jose
61eaa098ae
fix(messages): reduce audio transcription 400 retry noise (#13487)
## Summary
This PR reduces duplicate failure noise for audio transcription jobs
that fail with permanent HTTP 400 responses, and fixes a file-format
edge case causing intermittent 400s.

Sentry issue: [CHATWOOT-99E /
6660541334](https://chatwoot-p3.sentry.io/issues/6660541334/)

## Confirmed root cause
For some attachments, the stored filename had no extension (example:
`speech`, content type `audio/mpeg`).
When the temporary transcription upload file was created without an
extension, OpenAI returned:
`Unrecognized file format` (HTTP 400).

## Scope of changes
1. `Messages::AudioTranscriptionJob`
- Keeps `discard_on Faraday::BadRequestError` to avoid retry storms on
permanent request errors.
- Adds explicit Rails warning logs for discarded jobs with
attachment/job/status context.

2. `Messages::AudioTranscriptionService`
- Keeps guaranteed temp file cleanup via `ensure`.
- Ensures temp upload files include an extension when the original
filename has none, derived from blob `content_type`.
- This addresses intermittent failures like extensionless `audio/mpeg`
files.

## Reproduction
Enable audio transcription for an account and process an audio
attachment whose stored filename has no extension (for example `speech`)
but valid audio content type (`audio/mpeg`).
Before this fix, OpenAI transcription could return HTTP 400
`Unrecognized file format` for that attachment while similar attachments
with extensions succeeded.

## Testing
Ran:
`bundle exec rubocop
enterprise/app/jobs/messages/audio_transcription_job.rb
enterprise/app/services/messages/audio_transcription_service.rb`

Result: both modified files pass lint with no offenses.
2026-02-17 13:25:13 +05:30
Tanmay Deep Sharma
f4538ae2c5
fix: Enforce team boundaries to prevent cross-team assignments (#13353)
## Description

Fixes a critical bug where conversations assigned to a team could be
auto-assigned to agents outside that team when all team members were at
capacity.

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core assignment selection for both legacy and v2 flows;
misconfiguration of `allow_auto_assign` or team membership could cause
conversations to remain unassigned.
> 
> **Overview**
> Prevents auto-assignment from crossing team boundaries by filtering
eligible agents to the conversation’s `team` members (and requiring
`team.allow_auto_assign`) in both the legacy `AutoAssignmentHandler`
path and the v2 `AutoAssignment::AssignmentService` (including the
Enterprise override).
> 
> Adds test coverage to ensure team-scoped conversations only assign to
team members, and are skipped when team auto-assign is disabled or no
team members are available; also updates the conversations controller
spec setup to include team membership.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
67ed2bda0cd8ffd56c7e0253b86369dead2e6155. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2026-02-16 14:39:20 +05:30
Shivam Mishra
2c2f0547f7
fix: Captain not responding to campaign conversations (#13489)
Co-authored-by: Aakash Bakhle <48802744+aakashb95@users.noreply.github.com>
2026-02-12 10:07:56 +05:30
Vishnu Narayanan
00ed074d72
fix: disable email transcript for free plans (#13509)
- Block email transcript functionality for accounts without a paid plan
to prevent SES abuse.
2026-02-11 21:21:36 +05:30
Tanmay Deep Sharma
7b512bd00e
fix: V2 Assignment service enhancements (#13036)
## Linear Ticket:
https://linear.app/chatwoot/issue/CW-6081/review-feedback

## Description

Assignment V2 Service Enhancements

- Enable Assignment V2 on plan upgrade
- Fix UI issue with fair distribution policy display
- Add advanced assignment feature flag and enhance Assignment V2
capabilities

## Type of change

- [ ] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

This has been tested using the UI.

## Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes auto-assignment execution paths, rate limiting defaults, and
feature-flag gating (including premium plan behavior), which could
affect which conversations get assigned and when. UI rewires inbox
settings and policy flows, so regressions are possible around
navigation/linking and feature visibility.
> 
> **Overview**
> **Adds a new premium `advanced_assignment` feature flag** and uses it
to gate capacity/balanced assignment features in the UI (sidebar entry,
settings routes, assignment-policy landing cards) and backend
(Enterprise balanced selector + capacity filtering).
`advanced_assignment` is marked premium, included in Business plan
entitlements, and auto-synced in Enterprise accounts when
`assignment_v2` is toggled.
> 
> **Improves Assignment V2 policy UX** by adding an inbox-level
“Conversation Assignment” section (behind `assignment_v2`) that can
link/unlink an assignment policy, navigate to create/edit policy flows
with `inboxId` query context, and show an inbox-link prompt after
creating a policy. The policy form now defaults to enabled, disables the
`balanced` option with a premium badge/message when unavailable, and
inbox lists support click-to-navigate.
> 
> **Tightens/adjusts auto-assignment behavior**: bulk assignment now
requires `inbox.enable_auto_assignment?`, conversation ordering uses the
attached `assignment_policy` priority, and rate limiting uses
`assignment_policy` config with an infinite default limit while still
tracking assignments. Tests and i18n strings are updated accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
23bc03bf75ee4376071e4d7fc7cd564c601d33d7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2026-02-11 12:24:45 +05:30
Aakash Bakhle
bd732f1fa9
fix: search faqs in account language (#13428)
# Pull Request Template

## Description

Reply suggestions uses `search_documentation`. While this is useful,
there is a subtle bug, a user's message may be in a different language
(say spanish) than the FAQs present (english).
This results in embedding search in spanish and compared against english
vectors, which results in poor retrieval and poor suggestions.


Fixes # (issue)
This PR fixes the above behaviour by making a small llm call translate
the query before searching in the search documentation tool


## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration.

before:
<img width="894" height="157" alt="image"
src="https://github.com/user-attachments/assets/83871ee5-511e-4432-8b99-39e803759f63"
/>

after:
<img width="1149" height="294" alt="image"
src="https://github.com/user-attachments/assets/f9617d7a-6d48-4ca1-ad1c-2181e16c1f3d"
/>


test on rails console:
<img width="2094" height="380" alt="image"
src="https://github.com/user-attachments/assets/159fdaa5-8808-49d2-be5d-304d69fa97f7"
/>


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream
modules
2026-02-09 17:25:11 +05:30