Commit Graph

4199 Commits

Author SHA1 Message Date
Sojan Jose
cc86b8c7f1 fix: stream attachment handling in workers (#12870)
We’ve been watching Sidekiq workers climb from ~600 MB at boot to
1.4–1.5 GB after an hour whenever attachment-heavy jobs run. This PR is
an experiment to curb that growth by streaming attachments instead of
loading the whole blob into Ruby: reply-mailer inline attachments,
Telegram uploads, and audio transcriptions now read/write in chunks. If
this keeps RSS stable in production we’ll keep it; otherwise we’ll roll
it back and keep digging
2025-12-05 13:02:53 -08:00
Muhsin Keloth
efc3b5e7d4 fix: Handle Instagram API error codes properly in message processing (#13002)
### Problem

Instagram webhook processing was failing with:

> TypeError: no implicit conversion of String into Integer

This occurred when handling **echo messages** (outgoing messages) that:

* Contained `unsupported_type` attachments, and
* Were sent to a recipient user that could **not** be fetched via the
Instagram API.

In these cases, the webhook job crashed while trying to create or find
the contact for the recipient.

### Root Cause

The Instagram message service does not correctly handle Instagram API
error code **100**:

> "Object with ID does not exist, cannot be loaded due to missing
permissions, or does not support this operation"

When this error occurred during `fetch_instagram_user`:

1. The method fell through to exception tracking without an explicit
return.
2. `ChatwootExceptionTracker.capture_exception` returned `true`.
3. As a result, `fetch_instagram_user` effectively returned `true`
instead of a hash or empty hash.
4. `ensure_contact` then called `find_or_create_contact(true)` because
`true.present?` is `true`.
5. `find_or_create_contact` crashed when it tried to access
`true['id']`.

So the chain was:

```txt
fetch_instagram_user -> returns true
ensure_contact -> find_or_create_contact(true)
find_or_create_contact -> true['id'] -> TypeError
```

**Example Webhook Payload**

```
{
  "object": "instagram",
  "entry": [{
    "time": 1764822592663,
    "id": "17841454414819988",
    "messaging": [{
      "sender": { "id": "17841454414819988" },     // Business account
      "recipient": { "id": "1170166904857608" },   // User that can't be fetched
      "timestamp": 1764822591874,
      "message": {
        "attachments": [{
          "type": "unsupported_type",
          "payload": { "url": "https://..." }
        }],
        "is_echo": true
      }
    }]
  }]
}
```

**Corresponding Instagram API error:**

```
{
  "error": {
    "message": "The requested user cannot be found.",
    "type": "IGApiException",
    "code": 100,
    "error_subcode": 2534014
  }
}
```

**Debug Logs (Before Fix)**

```
[InstagramUserFetchError]: Unsupported get request. Object with ID '17841454414819988' does not exist... 100
[DEBUG] result: true
[DEBUG] result.present?: true
[DEBUG] find_or_create_contact called
[DEBUG] user: true
[DEBUG] Invalid user parameter - expected hash with id, got TrueClass: true
```

### Solution

### 1\. Handle Error Code 100 Explicitly

We now treat Instagram API error code **100** as a valid case for
creating an “unknown” contact, similar to how we already handle error
code `9010`:

```
# Handle error code 100: Object doesn't exist or missing permissions
# This typically occurs when trying to fetch a user that doesn't exist
# or has privacy restrictions. We can safely create an unknown contact.
return unknown_user(ig_scope_id) if error_code == 100
```

This ensures:

* `fetch_instagram_user` returns a valid hash for unknown users.
* `ensure_contact` can proceed safely without crashing.

### 2\. Prevent Exception Tracker Results from Leaking Through

For any **unhandled** error codes, we now explicitly return an empty
hash after logging the exception:

```
exception = StandardError.new(
  "#{error_message} (Code: #{error_code}, IG Scope ID: #{ig_scope_id})"
)
ChatwootExceptionTracker.new(exception, account: @inbox.account).capture_exception

# Explicitly return empty hash for any unhandled error codes
# This prevents the exception tracker result (true/false) from being returned.
{}
```

This guarantees that `fetch_instagram_user` always returns either:

* A valid user hash,
* An “unknown” user hash
* An empty hash
Fixes
https://linear.app/chatwoot/issue/CW-6068/typeerror-no-implicit-conversion-of-string-into-integer-typeerror
2025-12-04 18:53:50 +05:30
Muhsin Keloth
0a17976913 fix: Filter out unsupported ephemeral message attachments (#13003)
Fixes
https://linear.app/chatwoot/issue/CW-6070/argumenterror-ephemeral-is-not-a-valid-file-type-argumenterror

**Problem**
The instagram webhooks containing ephemeral (disappearing) message were
causing ArgumentError exceptions because this attachment type is not
supported and was not in the enum validation.

**Solution**
- Added ephemeral to the unsupported_file_type? filter
- Ephemeral attachments are now silently filtered out before processing,
following the same pattern as existing unsupported types (template,
unsupported_type)
2025-12-04 16:09:04 +05:30
Vishnu Narayanan
728a5a6710 fix: handle missing AccountUser in inbox_member API (#12993)
Fixes
https://linear.app/chatwoot/issue/CW-6065/actionviewtemplateerror-undefined-method-availability-status-for-nil
2025-12-04 13:32:51 +05:30
Muhsin Keloth
5c3b85334b feat: Add support for shared post and story attachment types in Instagram messages (#12997)
When users share Instagram posts or stories via DM, Instagram sends
webhooks with type `ig_post` and `ig_story` attachments. The system was
failing on these types because they weren't defined in the file_types.
This PR fixes the issue by handling all shared types and rendering them
on the front end.

**Shared post**

<img width="2154" height="1828" alt="CleanShot 2025-12-03 at 16 29
14@2x"
src="https://github.com/user-attachments/assets/7e731171-4904-43a6-abeb-b1db2c262742"
/>

**Shared status**
<img width="1702" height="1676" alt="CleanShot 2025-12-03 at 16 10
25@2x"
src="https://github.com/user-attachments/assets/6a151233-ce47-429d-b7c2-061514b20e05"
/>


Fixes
https://linear.app/chatwoot/issue/CW-5441/argumenterror-ig-story-is-not-a-valid-file-type-argumenterror
2025-12-04 05:20:47 +05:30
Muhsin Keloth
e6a7e836a0 fix: Add support for ig_post attachment type in Instagram messages (#12992)
Fixes
https://linear.app/chatwoot/issue/CW-6055/argumenterror-ig-post-is-not-a-valid-file-type-argumenterror

This PR fixes an issue where Instagram sends webhooks with both "type":
"share" and "type": "ig_post" attachments when users share Instagram
posts in direct messages. The system was failing on the ig_post type
because it wasn't defined, causing ArgumentError exceptions.


https://github.com/user-attachments/assets/577b8ebd-80e3-4c11-95f5-d8a8c3e16534
2025-12-03 10:27:16 +05:30
Tanmay Deep Sharma
b269cca0bf feat: Add AI credit topup flow for Stripe (#12988)
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-12-02 17:53:44 -08:00
Sivin Varghese
1df5fd513a fix: Reduce unnecessary label suggestion API calls (#12978) 2025-12-01 13:36:34 +05:30
Muhsin Keloth
4627aad56d fix: Enable reply editor for API channels with templates (#12973) 2025-12-01 10:13:38 +05:30
Sivin Varghese
f23d95e004 feat: Add Pinia support and relocate store factory (#12854)
Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-11-28 16:31:59 +05:30
Sivin Varghese
92fc286ecb fix: Resolve z-index issue in assistant switcher (#12969) 2025-11-27 10:35:42 +05:30
Sivin Varghese
dedb0426fb chore: Improve pagination with compact number formatting and pluralization (#12962) 2025-11-27 10:32:34 +05:30
Vinay Keerthi
eb0410af53 fix: handle string return values in MailPresenter#from method (#12966) 2025-11-27 10:31:56 +05:30
Vinay Keerthi
f1079574e3 fix: Disable SSL verification for LINE webhooks in development (#12960)
## Summary

- Fixes SSL certificate verification errors when testing LINE webhooks
in development environments
- Configures the LINE Bot API client to skip SSL verification only in
development mode

## Background

When testing LINE webhooks locally on macOS, the LINE Bot SDK was
failing with:
```
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get certificate CRL)
```

This occurs because the LINE Bot SDK tries to fetch user profiles via
HTTPS, and OpenSSL on macOS development environments may not have proper
access to Certificate Revocation Lists (CRLs).

## Changes

- Added `http_options` configuration to the LINE Bot client in
`Channel::Line#client`
- Sets `verify_mode: OpenSSL::SSL::VERIFY_NONE` only when
`Rails.env.development?` is true
- Production environments continue to use full SSL verification for
security

## Test Plan

- [x] Send a LINE message to trigger webhook in development
- [x] Verify webhook is processed without SSL errors
- [x] Confirm change only applies in development mode

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
2025-11-26 22:38:26 +05:30
Muhsin Keloth
73ad27e94c fix: Show WhatsApp templates only for inboxes with templates (#12965)
Fixed the logic to show WhatsApp templates option only for inboxes that have templates available.
2025-11-26 21:01:31 +05:30
Muhsin Keloth
6a83cad69d fix: Prevent WhatsApp campaign duplicate messages by updating status immediately (#12955)
Fixes
https://linear.app/chatwoot/issue/CW-5918/whatsapp-campaigns-running-in-parallel-and-duplicating-messages
2025-11-26 15:25:49 +05:30
Gabriel Jablonski
7e0507e3b5 fix: invalid language tag in heatmap component in reports page (#12952)
## Description

This PR fixes a `RangeError: Invalid language tag` that occurs in the
Heatmap report when using locales with underscores (e.g., `pt_BR`,
`zh_TW`).

The issue was caused by passing the raw locale string from `vue-i18n`
(which uses underscores for some regions) directly to
`Intl.DateTimeFormat`. The `Intl` API expects BCP 47 language tags which
use hyphens (e.g., `pt-BR`).

This change sanitizes the locale string by replacing underscores with
hyphens before creating the `DateTimeFormat` instance.

Fixes #12951
2025-11-26 13:24:29 +05:30
Shivam Mishra
7b20ecd27b chore: Revert pagination formatting and pluralization (#12954) 2025-11-25 21:36:13 +05:30
Gabriel Jablonski
e635122ff6 fix: add presence validation for account name (#12636)
## Description

When a user tries creating a new account through the Super Admin
dashboard, and they forget to fill in the account name, they're faced
with an ugly error (generic "Something went wrong" on production).

This PR simply adds the `validates :name, presence: true` model
validation on `Account` model, which is translated as a proper error
message on the Super Admin UI.
2025-11-25 20:11:15 +05:30
Sivin Varghese
46eb6f39f3 fix: Resolve z-index issue in assistant switcher (#12940) 2025-11-25 18:47:31 +05:30
Sivin Varghese
f0538b25ed fix: Reactive assistantId issue in Captain Inbox after route changes (#12939) 2025-11-25 18:47:18 +05:30
Shivam Mishra
389b864020 fix: click event for billing support (#12942) 2025-11-25 14:53:27 +05:30
Sivin Varghese
26778156dc chore: Improve pagination with compact number formatting and pluralization (#12921)
# Pull Request Template

## Description

This PR enhances the pagination component with standardized number
formatting and improved i18n handling.

**Includes:**

* Added `formatCompactNumber` and `formatFullNumber` helpers using
`Intl.NumberFormat`.
    * `< 1,000`: show exact value (e.g., `999`)
    * `1,000–999,999`: show compact format (`1k`, `1k+`)
    * `1,000,000+`: show in millions with one decimal (e.g., `1.2M`)
* Updated `PaginationFooter` to use the new formatters for all displayed
numbers.
  * Added proper pluralization to pagination i18n strings.

Fixes
https://linear.app/chatwoot/issue/CW-5999/better-display-of-numbers

## Type of change

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

## How Has This Been Tested?

### Screenshoots

**Before**
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/9fcf8baa-ae32-4a8a-85b0-24002fd863db"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/3d7138b7-133e-4ae6-b55f-67eff73ff1cc"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/1bbf7070-0681-492d-9308-a33874052d28"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/4e441672-26aa-4e66-965e-9edb807eaa72"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/11836702-1b74-4834-8932-31c20adc2db8"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/d37971bc-09af-4238-8601-ccc2ae69dbe7"
/>


**After**
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/8eaf2a23-beea-486b-b555-37f8b36ab904"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/f44f508a-e39d-45cb-afd8-98deb26920f8"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/d3b90711-bd7e-44ee-8bb3-48e45b799420"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/30dca6cd-f2be-4dcb-8596-924326ebf8c0"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/58896699-1f05-46c9-88cb-908318e71476"
/>
<img width="991" height="69" alt="image"
src="https://github.com/user-attachments/assets/ea0d91b0-077b-4d72-81a7-d38d17742da6"
/>




## 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
- [ ] Any dependent changes have been merged and published in downstream
modules
2025-11-24 17:49:24 -08:00
Sojan Jose
48627da0f9 feat: outbound voice call essentials (#12782)
- Enables outbound voice calls in voice channel . We are only caring
about wiring the logic to trigger outgoing calls to the call button
introduced in previous PRs. We will connect it to call component in
subsequent PRs

ref: #11602 

## Screens

<img width="2304" height="1202" alt="image"
src="https://github.com/user-attachments/assets/b91543a8-8d4e-4229-bd80-9727b42c7b0f"
/>

<img width="2304" height="1200" alt="image"
src="https://github.com/user-attachments/assets/1a1dad2a-8cb2-4aa2-9702-c062416556a7"
/>

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Vishnu Narayanan <vishnu@chatwoot.com>
2025-11-24 17:47:00 -08:00
Aakash Bakhle
e9c60aec04 feat: Add support for Langfuse LLM Tracing via OTEL (#12905)
This PR adds LLM instrumentation on langfuse for ai-editor feature

## Type of change
New feature (non-breaking change which adds functionality)

Needs langfuse account and env vars to be set

## How Has This Been Tested?

I configured personal langfuse credentials and instrumented the app,
traces can be seen in langfuse.
each conversation is one session. 
<img width="1683" height="714" alt="image"
src="https://github.com/user-attachments/assets/3fcba1c9-63cf-44b9-a355-fd6608691559"
/>
<img width="1446" height="172" alt="image"
src="https://github.com/user-attachments/assets/dfa6e98f-4741-4e04-9a9e-078d1f01e97b"
/>


## 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
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: aakashb95 <aakash@chatwoot.com>
Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com>
Co-authored-by: Pranav <pranav@chatwoot.com>
2025-11-21 16:31:45 -08:00
Sivin Varghese
45fa697885 chore: Hide pagination for empty company list (#12920) 2025-11-21 12:23:01 +05:30
Sivin Varghese
51fbf583b6 fix: Companies card pluralization issue (#12919) 2025-11-21 12:22:02 +05:30
Sivin Varghese
38d6ee6dd2 chore: Save company list sorting preferences in UI settings (#12916)
# Pull Request Template

## Description

This PR saves the company list sorting preferences (field and order) in
the user’s UI settings. The sort state is initialized from the stored
preferences when the component mounts, defaulting to `-created_at` if
none exist.

Fixes
https://linear.app/chatwoot/issue/CW-5992/save-sort-filter-to-ui-settings

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


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] 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
- [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
- [ ] Any dependent changes have been merged and published in downstream
modules
2025-11-20 16:51:27 -08:00
Rob Coenen
5608f5a1a2 fix: Widget shows 'away' on initial load despite agents being online (#12869)
## Description

Fixes #12868

This PR fixes a Vue 3 reactivity bug that causes the widget to display
"We are away at the moment" on initial page load, even when agents are
online and the API correctly returns their availability.

## Problem

The widget welcome screen shows "We are away" on first render, only
updating to show correct agent status after navigating to the
conversation view and back. This misleads visitors into thinking no
agents are available.

**Reproduction:** Open website with widget in fresh incognito window,
click bubble immediately → shows "away" despite agents being online.

## Root Cause

Vue 3 reactivity chain breaks in the `useAvailability` composable:

**Before (broken):**
```javascript
// AvailabilityContainer.vue
const { isOnline } = useAvailability(props.agents); // Passes VALUE

// useAvailability.js  
const availableAgents = toRef(agents); // Creates ref from VALUE, doesn't track changes
```

When the API responds and updates the Vuex store, the parent component's
computed `props.agents` updates correctly, but the composable's
`toRef()` doesn't know about the change because it was created from a
static value, not a reactive source.

## Solution

**After (fixed):**
```javascript
// AvailabilityContainer.vue
const { isOnline } = useAvailability(toRef(props, 'agents')); // Passes REACTIVE REF

// useAvailability.js
const availableAgents = computed(() => unref(agents)); // Unwraps ref and tracks changes
```

Now when `props.agents` updates after the API response, the `computed()`
re-evaluates and all downstream reactive properties (`hasOnlineAgents`,
`isOnline`) update correctly.

## Testing

-  Initial page load shows correct agent status immediately
-  Status changes via WebSocket update correctly  
-  No configuration changes or workarounds needed
-  Tested with network monitoring (Puppeteer) confirming API returns
correct data

## Files Changed

1.
`app/javascript/widget/components/Availability/AvailabilityContainer.vue`
   - Pass `toRef(props, 'agents')` instead of `props.agents`

2. `app/javascript/widget/composables/useAvailability.js`
   - Use `computed(() => unref(agents))` instead of `toRef(agents)`
   - Added explanatory comments

## Related Issues

- #5918 - Similar symptoms, closed with workaround (business hours
toggle) rather than fixing root cause
- #5763 - Different issue (mobile app presence)

This is a genuine Vue 3 reactivity bug affecting all widgets,
independent of business hours configuration.

Co-authored-by: rcoenen <rcoenen@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2025-11-20 20:27:44 +05:30
Shivam Mishra
da4110a495 feat: add retry loadWithRetry composable (#12873) 2025-11-20 19:40:20 +05:30
Vinay Keerthi
9a2136caf1 fix: Change messages.source_id to text column (#12908)
## Summary
Changes `messages.source_id` from `string` (255 char limit) to `text`
(20,000 char limit) to support long email Message-ID headers.

## Changes
- Migration to change column type from string to text
- Added spec tests for source_id length validation

## Related
Fixes
https://linear.app/chatwoot/issue/CW-5961/activerecordrecordinvalid-validation-failed-source-is-too-long-maximum
2025-11-20 11:41:41 +05:30
Sojan Jose
5f2b2f4221 feat: APIs to assign agents_bots as assignee in conversations (#12836)
## Summary
- add an assignee_agent_bot_id column as an initital step to prototype
this before fully switching to polymorphic assignee
- update assignment APIs and conversation list / show endpoints to
reflect assignee as agent bot
- ensure webhook payloads contains agent bot assignee


[Codex
Task](https://chatgpt.com/codex/tasks/task_e_6912833377e48326b6641b9eee32d50f)

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
2025-11-18 18:20:58 -08:00
Vishnu Narayanan
70c183ea6e feat: hide email forwarding address if INBOUND_EMAIL_DOMAIN is not configured (#12768)
#### Summary

- Improved email inbox setup flow to handle cases where inbound email
forwarding is not configured on the installation
- Added conditional display of email forwarding address based on
MAILER_INBOUND_EMAIL_DOMAIN environment variable availability
- Enhanced user messaging to guide users toward configuring SMTP/IMAP
settings when forwarding is unavailable

#### Changes

**Backend (app/views/api/v1/models/_inbox.json.jbuilder)**
- Added forwarding_enabled boolean flag to inbox API response based on
MAILER_INBOUND_EMAIL_DOMAIN presence
- Made forward_to_email conditional - only included when forwarding is
enabled

  **Frontend - Inbox Creation Flow**
- Created new EmailInboxFinish.vue component to handle email inbox setup
completion
  - Shows different messages based on whether forwarding is enabled:
- With forwarding: displays forwarding address and encourages SMTP/IMAP
configuration
- Without forwarding: warns that SMTP/IMAP configuration is required for
emails to be processed
- Added link to configuration page for easy access to SMTP/IMAP settings

<img width="988" height="312" alt="Screenshot 2025-11-18 at 3 27 27 PM"
src="https://github.com/user-attachments/assets/928aff78-df73-49fa-9a26-dbbd1297b26a"
/>

<img width="765" height="489" alt="Screenshot 2025-11-18 at 3 24 46 PM"
src="https://github.com/user-attachments/assets/6a182c7d-087f-4e88-92a5-30f147a567a7"
/>


Fixes
https://linear.app/chatwoot/issue/CW-5881/hide-forwaring-email-section-if-inbound-email-domain-is-not-configured


## Type of change

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

## How Has This Been Tested?

- Tested locally

## 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: Pranav <pranav@chatwoot.com>
2025-11-18 18:05:12 -08:00
Sivin Varghese
e33f28dc33 feat: Companies page (#12842)
# Pull Request Template

## Description

This PR introduces a new Companies section in the Chatwoot dashboard. It
lists all companies associated with the account and includes features
such as **search**, **sorting**, and **pagination** to enable easier
navigation and efficient management.

Fixes
https://linear.app/chatwoot/issue/CW-5928/add-companies-tab-to-dashboard

## Type of change

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

## How Has This Been Tested?

### Screenshot
<img width="1619" height="1200" alt="image"
src="https://github.com/user-attachments/assets/21f0a666-c3d6-4dec-bd02-1e38e0cd9542"
/>



## 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
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Vinay Keerthi <11478411+stonecharioteer@users.noreply.github.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2025-11-18 15:29:15 +05:30
Vinay Keerthi
58ca82c720 feat: Backend - Companies API endpoint with pagination and search (#12840)
## Description

Adds API endpoint to list companies with pagination, search, and
sorting.

Fixes
https://linear.app/chatwoot/issue/CW-5930/add-backend-routes-to-get-companies-result
Parent issue:
https://linear.app/chatwoot/issue/CW-5928/add-companies-tab-to-dashboard

## Type of change

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

## How Has This Been Tested?

Added comprehensive specs to
`spec/enterprise/controllers/api/v1/accounts/companies_controller_spec.rb`:
- Pagination (25 per page, multiple pages)
- Search by name and domain (case-insensitive)
- Counter cache for contacts_count
- Account scoping
- Authorization

To reproduce:
```bash
bundle exec rspec spec/enterprise/controllers/api/v1/accounts/companies_controller_spec.rb
bundle exec rubocop enterprise/app/controllers/api/v1/accounts/companies_controller.rb
```

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] 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
- [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
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
Co-authored-by: Sojan Jose <sojan@pepalo.com>
2025-11-18 14:28:56 +05:30
Chatwoot Bot
7acf3c8817 chore: Update translations (#12876) 2025-11-17 22:02:54 -08:00
Sojan Jose
77f492590e feat: Control the allowed login methods via Super Admin (#12892)
- Control the allowed authentication methods for a chatwoot installation
via super admin configs. [SAML, Google Auth etc]
------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_6917d503b6e48326a261672c1de91462)

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2025-11-17 21:55:12 -08:00
Sojan Jose
5b56f64838 feat: Customizable webhook timeout configuration (#12777)
## Summary
- Ability to configure the webhook timeout for Chatwoot self hosted
installations

fixes: https://github.com/chatwoot/chatwoot/issues/12754
2025-11-17 14:43:23 -08:00
Sojan Jose
bf806f0c28 feat: allow configuring attachment upload limit (#12835)
## Summary
- add a configurable MAXIMUM_FILE_UPLOAD_SIZE installation setting and
surface it through super admin and global config payloads
- apply the configurable limit to attachment validations and shared
upload helpers on dashboard and widget
- introduce a reusable helper with unit tests for parsing the limit and
extend attachment specs for configurability


------
[Codex
Task](https://chatgpt.com/codex/tasks/task_e_6912644786b08326bc8dee9401af6d0a)

---------

Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
2025-11-17 14:03:08 -08:00
Vinay Keerthi
93374f4327 fix: Change contact_inboxes.source_id to text column (#12882)
## Description

Fixes CW-5961 where IMAP email processing failed with
`ActiveRecord::RecordInvalid: Validation failed: Source is too long
(maximum is 255 characters)` error.

This changes the `contact_inboxes.source_id` column from `string` (255
character limit) to `text` (unlimited) to accommodate long email message
IDs that were causing validation failures.

Fixes CW-5961

## Type of change

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

## How Has This Been Tested?

- Added spec test validating `source_id` values longer than 255
characters (300 chars)
- All existing `contact_inbox_spec.rb` tests pass (7 examples, 0
failures)
- Migration applied successfully with reversible up/down methods
- Verified `source_id` column type changed to `text` with `null: false`
constraint preserved

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [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
2025-11-17 16:09:36 +05:30
Tanmay Deep Sharma
c9823d9409 feat: Assignment service (v2) (#12320)
## Linear Link

 
## Description

This PR introduces a new robust auto-assignment system for conversations
in Chatwoot. The system replaces the existing round-robin assignment
with a more sophisticated service-based architecture that supports
multiple assignment strategies, rate limiting, and Enterprise features
like capacity-based assignment and balanced distribution.

## Type of change

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

## How Has This Been Tested?

- Unit test cases
- Test conversations getting assigned on status change to open
- Test the job directly via rails console

## 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]
> Adds a new service-based auto-assignment system with scheduled jobs,
rate limiting, enterprise capacity/balanced selection, and wiring via
inbox/handler; includes Redis helpers and comprehensive tests.
> 
> - **Auto-assignment v2 (core services)**:
> - Add `AutoAssignment::AssignmentService` with bulk assignment,
configurable conversation priority, RR selection, and per-agent rate
limiting via `AutoAssignment::RateLimiter`.
>   - Add `AutoAssignment::RoundRobinSelector` for agent selection.
> - **Jobs & scheduling**:
> - Add `AutoAssignment::AssignmentJob` (per-inbox bulk assign;
env-based limit) and `AutoAssignment::PeriodicAssignmentJob` (batch over
accounts/inboxes).
> - Schedule periodic run in `config/schedule.yml`
(`periodic_assignment_job`).
> - **Model/concerns wiring**:
> - Include `InboxAgentAvailability` in `Inbox`; add
`Inbox#auto_assignment_v2_enabled?`.
> - Update `AutoAssignmentHandler` to trigger v2 job when
`auto_assignment_v2_enabled?`, else fallback to legacy.
> - **Enterprise extensions**:
> - Add `Enterprise::InboxAgentAvailability` (capacity-aware filtering)
and `Enterprise::Concerns::Inbox` association `inbox_capacity_limits`.
> - Extend service via `Enterprise::AutoAssignment::AssignmentService`
(policy-driven config, capacity filtering, exclusion rules) and add
selectors/services: `BalancedSelector`, `CapacityService`.
> - **Infrastructure**:
> - Enhance `Redis::Alfred` with `expire`, key scan/count, and extended
ZSET helpers (`zadd`, `zcount`, `zcard`, `zrangebyscore`).
> - **Tests**:
> - Add specs for jobs, core service, rate limiter, RR selector, and
enterprise features (capacity, balanced selection, exclusions).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
0ebe187c8aea73765b0122a44b18d6f465c2477f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2025-11-17 10:08:25 +05:30
Sivin Varghese
2c4e65d68e chore: Hide assistant switcher on paywall screen (#12875) 2025-11-17 09:58:59 +05:30
Chatwoot Bot
32da4eec27 chore: Update translations (#12818) 2025-11-14 15:24:38 +05:30
Sivin Varghese
eed1825d5a fix: Brand installation name not showing (#12861)
# Pull Request Template

## Description

Fixes
https://linear.app/chatwoot/issue/CW-5946/fix-brand-installation-name-issue-in-dyte

## Type of change

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


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] 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
- [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
- [ ] Any dependent changes have been merged and published in downstream
modules
2025-11-13 22:16:25 +05:30
Sivin Varghese
651645fbd2 chore: Update missing places with new colors (#12862)
# Pull Request Template

## Description

This PR updates the colors in places that were missed during the color
update migration.

## Type of change

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


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] 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
- [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
- [ ] Any dependent changes have been merged and published in downstream
modules
2025-11-13 22:16:13 +05:30
Gabriel Jablonski
bdcb1934c0 feat(webhooks): add name to webhook (#12641)
## Description

When working with webhooks, it's easy to lose track of which URL is
which. Adding a `name` (optional) column to the webhook model is a
straight-forward solution to make it significantly easier to identify
webhooks.

## Type of change

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

## How Has This Been Tested?

Model and controller specs, and also running in production over several
months without any issues.

| Before | After |
| --- | --- |
| <img width="949" height="990" alt="image copy 3"
src="https://github.com/user-attachments/assets/6b33c072-7d16-4a9c-a129-f9c0751299f5"
/> | <img width="806" height="941" alt="image"
src="https://github.com/user-attachments/assets/77f3cb3a-2eb0-41ac-95bf-d02915589690"
/> |
| <img width="1231" height="650" alt="image copy 2"
src="https://github.com/user-attachments/assets/583374af-96e0-4436-b026-4ce79b7f9321"
/> | <img width="1252" height="650" alt="image copy"
src="https://github.com/user-attachments/assets/aa81fb31-fd18-4e21-a40e-d8ab0dc76b4e"
/> |


## 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
- [x] 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
2025-11-13 13:28:15 +05:30
Shivam Mishra
4f09c2203c feat: allow querying reporting events via the API (#12832) 2025-11-13 12:46:55 +05:30
Vinay Keerthi
f455e7994e fix: respect status parameter when creating articles via API (#12846)
## Description

The Articles API was ignoring the `status` parameter when creating new
articles. All articles were forced to be drafts due to a hardcoded
`@article.draft!` call in the controller, even when users explicitly
sent `status: 1` (published) in their API request.

This PR removes the hardcoded draft enforcement and allows the status
parameter to be respected while maintaining backward compatibility.

Fixes #12063

## Type of change

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

## How Has This Been Tested?

**Before:**
- API POST with `status: 1` → Created as draft (ignored parameter)
- API POST without status → Created as draft

**After:**
- API POST with `status: 1` → Created as published 
- API POST without status → Created as draft (backward compatible) 
- UI creates articles → Still creates as draft (UI doesn't send status)


**Tests run:**
```bash
bundle exec rspec spec/controllers/api/v1/accounts/articles_controller_spec.rb
# 17 examples, 0 failures
```

Updated tests:
1. Changed 2 existing tests that were verifying the broken behavior
(expecting draft when published was sent)
2. Added new test to verify articles default to draft when status is not
provided
3. All existing tests pass, confirming backward compatibility

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [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

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2025-11-13 12:07:24 +05:30
Shivam Mishra
28e16f7ee0 feat: allow selecting month range in overview reports (#12701)
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
Co-authored-by: iamsivin <iamsivin@gmail.com>
2025-11-12 18:34:00 +05:30
Sivin Varghese
fb0be60ae2 chore: Improve captain layout (#12820) 2025-11-12 18:31:17 +05:30