Commit Graph

6661 Commits

Author SHA1 Message Date
Gabriel Jablonski
cc008951db
fix(sidebar): improve active child route matching logic (#13121) 2026-04-16 10:57:16 +05:30
Aakash Bakhle
97dae52841
fix: use committed model registry for RubyLLM (#14067)
RubyLLM bundles a static models.json that doesn't know about models
released after the gem was published. Self-hosted users configuring
newer models hit ModelNotFoundError.

Added a rake task that refreshes the registry from models.dev and saves
to disk. ~~Called during Docker image build so every deploy gets fresh
model data. Falls back silently to the bundled registry if models.dev is
unreachable.~~

Commit the models.json file to code so it is available across
deployments.

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2026-04-16 10:28:38 +05:30
Rodribm10
8ea87027d1 fix: move captain_unit_factory_spec out of factories/ (was breaking rails runner boot) 2026-04-15 22:19:48 -03:00
Rodribm10
2e9551a0f3 feat(lifecycle): rules tab with templates, wizard and variable autocomplete
Implements Task 15: Rules.vue (template grid + rules table), RuleWizardDialog.vue
(4-step wizard: Quando/Pra quem/O quê/Revisão) and MessageEditor.vue (textarea with
{{ variable }} autocomplete). Adds WIZARD.CANCEL, OFFSET_UNIT_LABEL, STEP_LABELS and
REVIEW i18n keys in en and pt_BR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 11:15:00 -03:00
Rodribm10
94fdb5c318 feat(lifecycle): settings tab with guards form and concierge per unit
Replaces stub Settings.vue with full implementation: anti-spam guard
form (quiet hours, interval, pause-on-reply, opt-out label) and a
collapsible ConciergeUnitCard per unit (inbox selector, persona name,
knowledge base, key-value variables). Adds CONCIERGE_CONFIGURED /
CONCIERGE_NOT_CONFIGURED i18n keys to en + pt_BR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 11:05:40 -03:00
Rodribm10
ae4647d1c2 feat(lifecycle): history tab with paginated list and preview modal
Implements Task 13 — replaces the stub History.vue with a real paginated
table filtered by status, and adds DeliveryPreviewModal to show rendered_body.
Also extends i18n keys (TOTAL, PAGINATION, MODAL labels) in en + pt_BR.
2026-04-15 10:57:56 -03:00
Rodribm10
ad2255aba4 feat(lifecycle): sidebar entry for Jornada do Cliente 2026-04-15 10:53:33 -03:00
Rodribm10
65a76ed59d feat(lifecycle): parent view with TabBar + 3 stub children routes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:51:09 -03:00
Rodribm10
bc85ec0a67 feat(lifecycle): Pinia/Vuex stores for rules/config/deliveries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:46:20 -03:00
Rodribm10
b69053ae62 feat(lifecycle): API clients for rules/config/deliveries + concierge update
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:42:51 -03:00
Rodribm10
1459655243 feat(lifecycle): i18n keys for Jornada do Cliente UI
Adds CAPTAIN_LIFECYCLE block (en + pt_BR) to captain.json with full
key set for Rules, Wizard, Settings, History and sidebar entry.

Also stages pre-existing uncommitted additions to captain.json from
prior work (KPI, PILLS, QUICK_DATE, CARD, ACTIONS extras for
CAPTAIN_RESERVATIONS) — those were already in the working tree and
belong to the same feature branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:39:50 -03:00
Rodribm10
fa1dd8b6cb feat(lifecycle): expose concierge config update on UnitsController
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:35:03 -03:00
Rodribm10
0b195781c5 feat(lifecycle): REST endpoint for lifecycle deliveries audit log 2026-04-15 10:29:24 -03:00
Rodribm10
8690a49971 feat(lifecycle): REST endpoint for lifecycle config singleton 2026-04-15 10:23:42 -03:00
Rodribm10
7c17a7cb96 feat(lifecycle): REST endpoint for lifecycle rules CRUD
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:17:59 -03:00
Rodribm10
cb67a1063d fix(lifecycle): move stub controllers from non-enterprise to enterprise path
Os stubs de lifecycle criados na task anterior estavam em app/controllers/
causando futura colisão de redefinição de classe quando os controllers reais
forem implementados em enterprise/app/controllers/ (tasks 4-6). Move os 3
stubs para o enterprise path onde vivem todos os controllers Captain.

Routing spec: 7 examples, 0 failures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:13:33 -03:00
Rodribm10
fbc91e2fa8 feat(lifecycle): add REST routes for rules, config, deliveries, concierge
Wires 3 new captain namespace resources (lifecycle_rules, lifecycle_config,
lifecycle_deliveries) and a member action `patch :concierge` on units.
Includes stub controllers (to be expanded in Tasks 4-7) and passing routing spec.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 10:11:39 -03:00
Rodribm10
7d21530bc7 feat(lifecycle): add Pundit policies for rule/config/delivery 2026-04-15 10:06:47 -03:00
Rodribm10
b29b35465b feat(lifecycle): add Account associations for lifecycle models 2026-04-15 10:03:01 -03:00
Rodribm10
7da16f7722 docs(lifecycle): add backend handoff with gotchas and next-session prompt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 09:41:52 -03:00
Rodribm10
325f05c3eb fix(spec): captain_unit factory now auto-creates brand in matching account
Replaced broken `association :brand, factory: :captain_brand, account: account`
(FactoryBot cannot evaluate `account` lazily that way) with a transient block
that does `Captain::Brand.find_by(account_id: account.id) || association(...)`,
ensuring the brand always belongs to the same account as the unit.
Adds factory spec (6 examples) confirming standalone create, account override,
and brand reuse all work correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:36:52 -03:00
Rodribm10
5639c3ae1d chore(lifecycle): add demo seed script for manual pipeline testing 2026-04-15 09:31:11 -03:00
Rodribm10
f302726d9b test(lifecycle): add end-to-end integration spec for scheduler→dispatch→send flow
Also fixes double-scheduling bug in scheduler_spec and delivery_spec caused by
after_create_commit hook firing while rules already exist — reservation is now
created before rules in setup so the hook finds nothing to schedule.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:29:52 -03:00
Aakash Bakhle
5264de24b0
feat: migrations for document auto-sync [AI-141] (#14041)
# Pull Request Template

## Description

Add migrations for document auto-sync

Fixes # (issue)

## Type of change

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

## How Has This Been Tested?
locally

## 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-04-15 17:56:10 +05:30
Rodribm10
7b009cf47f feat(lifecycle): inject concierge context into Captain orchestrator prompt
Adds concierge.* and reservation.* Liquid variables to agent_instructions
so Sofia's orchestrator_prompt receives unit persona/knowledge/variables
and reservation data resolved from conversation.custom_attributes.current_unit_id.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 09:25:16 -03:00
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
Sojan Jose
b96bf41234
chore: Enable Participating tab for conversations (#11714)
## Summary

This PR enables the **Participating** conversation view in the main
sidebar and keeps the behavior aligned with existing conversation views.

## What changed

- Added **Participating** under Conversations in the new sidebar.
- Added a guard in conversation realtime `addConversation` flow so
generic `conversation.created` events are not injected while the user is
on Participating view.
- Added participating route mapping in conversation-list redirect helper
so list redirects resolve correctly to `/participating/conversations`.

## Scope notes

- Kept changes minimal and consistent with current `develop` behavior.
- No additional update-event filtering was added beyond what existing
views already do.

---------


Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
2026-04-15 17:03:39 +05:30
Tanmay Deep Sharma
3f9f054c43
fix: drop WhatsApp incoming messages from blocked contacts (#14061)
## Linear ticket

https://linear.app/chatwoot/issue/CW-6839/blocked-contact-can-still-send-messages-to-whatsapp-inbox

## Description

Drop WhatsApp incoming messages  from blocked contacts

## Type of change

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

## How Has This Been Tested?

- Incoming messages for blocked contacts 

## 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

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2026-04-15 13:42:48 +07: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
23a17599c4 feat(wuzapi): dispatch interactive messages (buttons/list/url_button)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:30:31 -03:00
Rodribm10
7a203ccb6d feat(wuzapi): add send_buttons, send_list, send_url_button methods
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:28:00 -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
1c89ef73ff feat(lifecycle): add captain_lifecycle_* tables and concierge columns on captain_units
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 01:10:49 -03:00
Rodribm10
13070bd197 docs: add Jornada do Cliente backend (Fases A+C) implementation plan
Plano de 20 tasks em TDD cobrindo: migrations, models (Rule/Delivery/Config),
extensões em Captain::Unit, 3 métodos interativos em Wuzapi::Client,
EventResolver, Scheduler event-driven, hooks em Captain::Reservation,
ContextBuilder, 6 guards (Opção C quiet hours, max-5, opt-out, etc),
Dispatcher pipeline, DispatcherJob, injeção Liquid de concierge.* no
orchestrator prompt e spec de integração end-to-end.

Out of scope: UI (Fase B) será plano separado após backend validado.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 01:05:00 -03:00
Rodribm10
af5e2723aa docs: add Jornada do Cliente (lifecycle automation) design spec
Design para a feature de automação de mensagens WhatsApp baseada em
eventos do ciclo de vida de reserva — 4 componentes isolados (rules
engine, scheduler event-driven, dispatcher pipeline, concierge AI
Sofia), multi-tenant desde o dia 1, com guards anti-ban e injeção
dinâmica de knowledge por unidade via Liquid.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 00:53:08 -03:00
Rodribm10
69f0b124bb docs: plano Fase 5 - polish visual (hero, carrossel, skeletons, confetti) 2026-04-14 22:05:19 -03:00
Rodribm10
e55f793ffc docs: plano Fase 4 - multi-tenant SaaS + admin CRUD 2026-04-14 20:50:17 -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
a892e65300 fix(ui): dropdown Vincular Unidade Pix mostra unit vinculada em cascata
Existem 3 mecanismos de vinculo inbox-unit no fork:
  1. captain_inboxes.captain_unit_id (fluxo Captain)
  2. captain_unit_inboxes (tabela join pura, usada pela UI nova)
  3. captain_units.inbox_id (legado direto)

O serializer lia so o #1 e retornava null nas outras, fazendo a UI
mostrar 'Nenhuma unidade vinculada' mesmo quando havia vinculo via
#2 ou #3. Agora o jbuilder cai em cascata nas 3 fontes.
2026-04-14 20:07:33 -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