cc008951dbda26da25f61b35f8bb9b1d5e447f0a
6019
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cc008951db | fix(sidebar): improve active child route matching logic (#13121) | ||
|
|
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> |
||
|
|
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 |
||
|
|
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> |
||
|
|
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> |
||
|
|
8e5d4f4d23 |
chore(deps): bump axios from 1.13.6 to 1.15.0 (#14051)
Bumps [axios](https://github.com/axios/axios) from 1.13.6 to 1.15.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/axios/axios/releases">axios's releases</a>.</em></p> <blockquote> <h2>v1.15.0</h2> <p>This release delivers two critical security patches, adds runtime support for Deno and Bun, and includes significant CI hardening, documentation improvements, and routine dependency updates.</p> <h2>⚠️ Important Changes</h2> <ul> <li><strong>Deprecation:</strong> <code>url.parse()</code> usage has been replaced to address Node.js deprecation warnings. If you are on a recent version of Node.js, this resolves console warnings you may have been seeing. (<strong><a href="https://redirect.github.com/axios/axios/issues/10625">#10625</a></strong>)</li> </ul> <h2>🔒 Security Fixes</h2> <ul> <li><strong>Proxy Handling:</strong> Fixed a <code>no_proxy</code> hostname normalisation bypass that could lead to Server-Side Request Forgery (SSRF). (<strong><a href="https://redirect.github.com/axios/axios/issues/10661">#10661</a></strong>)</li> <li><strong>Header Injection:</strong> Fixed an unrestricted cloud metadata exfiltration vulnerability via a header injection chain. (<strong><a href="https://redirect.github.com/axios/axios/issues/10660">#10660</a></strong>)</li> </ul> <h2>🚀 New Features</h2> <ul> <li><strong>Runtime Support:</strong> Added compatibility checks and documentation for Deno and Bun environments. (<strong><a href="https://redirect.github.com/axios/axios/issues/10652">#10652</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10653">#10653</a></strong>)</li> </ul> <h2>🔧 Maintenance & Chores</h2> <ul> <li><strong>CI Security:</strong> Hardened workflow permissions to least privilege, added the <code>zizmor</code> security scanner, pinned action versions, and gated npm publishing with OIDC and environment protection. (<strong><a href="https://redirect.github.com/axios/axios/issues/10618">#10618</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10619">#10619</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10627">#10627</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10637">#10637</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10666">#10666</a></strong>)</li> <li><strong>Dependencies:</strong> Bumped <code>serialize-javascript</code>, <code>handlebars</code>, <code>picomatch</code>, <code>vite</code>, and <code>denoland/setup-deno</code> to latest versions. Added a 7-day Dependabot cooldown period. (<strong><a href="https://redirect.github.com/axios/axios/issues/10574">#10574</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10572">#10572</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10568">#10568</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10663">#10663</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10664">#10664</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10665">#10665</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10669">#10669</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10670">#10670</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10616">#10616</a></strong>)</li> <li><strong>Documentation:</strong> Unified docs, improved <code>beforeRedirect</code> credential leakage example, clarified <code>withCredentials</code>/<code>withXSRFToken</code> behaviour, HTTP/2 support notes, async/await timeout error handling, header case preservation, and various typo fixes. (<strong><a href="https://redirect.github.com/axios/axios/issues/10649">#10649</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10624">#10624</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/7452">#7452</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/7471">#7471</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10654">#10654</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10644">#10644</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10589">#10589</a></strong>)</li> <li><strong>Housekeeping:</strong> Removed stale files, regenerated lockfile, and updated sponsor scripts and blocks. (<strong><a href="https://redirect.github.com/axios/axios/issues/10584">#10584</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10650">#10650</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10582">#10582</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10640">#10640</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10659">#10659</a></strong>, <strong><a href="https://redirect.github.com/axios/axios/issues/10668">#10668</a></strong>)</li> <li><strong>Tests:</strong> Added regression coverage for urlencoded <code>Content-Type</code> casing. (<strong><a href="https://redirect.github.com/axios/axios/issues/10573">#10573</a></strong>)</li> </ul> <h2>🌟 New Contributors</h2> <p>We are thrilled to welcome our new contributors. Thank you for helping improve Axios:</p> <ul> <li><strong><a href="https://github.com/raashish1601"><code>@raashish1601</code></a></strong> (<strong><a href="https://redirect.github.com/axios/axios/issues/10573">#10573</a></strong>)</li> <li><strong><a href="https://github.com/Kilros0817"><code>@Kilros0817</code></a></strong> (<strong><a href="https://redirect.github.com/axios/axios/issues/10625">#10625</a></strong>)</li> <li><strong><a href="https://github.com/ashstrc"><code>@ashstrc</code></a></strong> (<strong><a href="https://redirect.github.com/axios/axios/issues/10624">#10624</a></strong>)</li> <li><strong><a href="https://github.com/Abhi3975"><code>@Abhi3975</code></a></strong> (<strong><a href="https://redirect.github.com/axios/axios/issues/10589">#10589</a></strong>)</li> <li><strong><a href="https://github.com/theamodhshetty"><code>@theamodhshetty</code></a></strong> (<strong><a href="https://redirect.github.com/axios/axios/issues/7452">#7452</a></strong>)</li> </ul> <h2>v1.14.0</h2> <p>This release focuses on compatibility fixes, adapter stability improvements, and test/tooling modernisation.</p> <h2>⚠️ Important Changes</h2> <ul> <li><strong>Breaking Changes:</strong> None identified in this release.</li> <li><strong>Action Required:</strong> If you rely on env-based proxy behaviour or CJS resolution edge-cases, validate your integration after upgrade (notably <code>proxy-from-env</code> v2 alignment and <code>main</code> entry compatibility fix).</li> </ul> <h2>🚀 New Features</h2> <ul> <li><strong>Runtime Features:</strong> No new end-user features were introduced in this release.</li> <li><strong>Test Coverage Expansion:</strong> Added broader smoke/module test coverage for CJS and ESM package usage. (<a href="https://redirect.github.com/axios/axios/pull/7510">#7510</a>)</li> </ul> <h2>🐛 Bug Fixes</h2> <ul> <li><strong>Headers:</strong> Trim trailing CRLF in normalised header values. (<a href="https://redirect.github.com/axios/axios/pull/7456">#7456</a>)</li> <li><strong>HTTP/2:</strong> Close detached HTTP/2 sessions on timeout to avoid lingering sessions. (<a href="https://redirect.github.com/axios/axios/pull/7457">#7457</a>)</li> <li><strong>Fetch Adapter:</strong> Cancel <code>ReadableStream</code> created during request-stream capability probing to prevent async resource leaks. (<a href="https://redirect.github.com/axios/axios/pull/7515">#7515</a>)</li> <li><strong>Proxy Handling:</strong> Fixed env proxy behavior with <code>proxy-from-env</code> v2 usage. (<a href="https://redirect.github.com/axios/axios/pull/7499">#7499</a>)</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2><a href="https://github.com/axios/axios/compare/v1.13.2...v1.13.3">1.13.3</a> (2026-01-20)</h2> <h3>Bug Fixes</h3> <ul> <li><strong>http2:</strong> Use port 443 for HTTPS connections by default. (<a href="https://redirect.github.com/axios/axios/issues/7256">#7256</a>) (<a href="https://github.com/axios/axios/commit/d7e60653460480ffacecf85383012ca1baa6263e">d7e6065</a>)</li> <li><strong>interceptor:</strong> handle the error in the same interceptor (<a href="https://redirect.github.com/axios/axios/issues/6269">#6269</a>) (<a href="https://github.com/axios/axios/commit/5945e40bb171d4ac4fc195df276cf952244f0f89">5945e40</a>)</li> <li>main field in package.json should correspond to cjs artifacts (<a href="https://redirect.github.com/axios/axios/issues/5756">#5756</a>) (<a href="https://github.com/axios/axios/commit/7373fbff24cd92ce650d99ff6f7fe08c2e2a0a04">7373fbf</a>)</li> <li><strong>package.json:</strong> add 'bun' package.json 'exports' condition. Load the Node.js build in Bun instead of the browser build (<a href="https://redirect.github.com/axios/axios/issues/5754">#5754</a>) (<a href="https://github.com/axios/axios/commit/b89217e3e91de17a3d55e2b8f39ceb0e9d8aeda8">b89217e</a>)</li> <li>silentJSONParsing=false should throw on invalid JSON (<a href="https://redirect.github.com/axios/axios/issues/7253">#7253</a>) (<a href="https://redirect.github.com/axios/axios/issues/7257">#7257</a>) (<a href="https://github.com/axios/axios/commit/7d19335e43d6754a1a9a66e424f7f7da259895bf">7d19335</a>)</li> <li>turn AxiosError into a native error (<a href="https://redirect.github.com/axios/axios/issues/5394">#5394</a>) (<a href="https://redirect.github.com/axios/axios/issues/5558">#5558</a>) (<a href="https://github.com/axios/axios/commit/1c6a86dd2c0623ee1af043a8491dbc96d40e883b">1c6a86d</a>)</li> <li><strong>types:</strong> add handlers to AxiosInterceptorManager interface (<a href="https://redirect.github.com/axios/axios/issues/5551">#5551</a>) (<a href="https://github.com/axios/axios/commit/8d1271b49fc226ed7defd07cd577bd69a55bb13a">8d1271b</a>)</li> <li><strong>types:</strong> restore AxiosError.cause type from unknown to Error (<a href="https://redirect.github.com/axios/axios/issues/7327">#7327</a>) (<a href="https://github.com/axios/axios/commit/d8233d9e8e9a64bfba9bbe01d475ba417510b82b">d8233d9</a>)</li> <li>unclear error message is thrown when specifying an empty proxy authorization (<a href="https://redirect.github.com/axios/axios/issues/6314">#6314</a>) (<a href="https://github.com/axios/axios/commit/6ef867e684adf7fb2343e3b29a79078a3c76dc29">6ef867e</a>)</li> </ul> <h3>Features</h3> <ul> <li>add <code>undefined</code> as a value in AxiosRequestConfig (<a href="https://redirect.github.com/axios/axios/issues/5560">#5560</a>) (<a href="https://github.com/axios/axios/commit/095033c626895ecdcda2288050b63dcf948db3bd">095033c</a>)</li> <li>add automatic minor and patch upgrades to dependabot (<a href="https://redirect.github.com/axios/axios/issues/6053">#6053</a>) (<a href="https://github.com/axios/axios/commit/65a7584eda6164980ddb8cf5372f0afa2a04c1ed">65a7584</a>)</li> <li>add Node.js coverage script using c8 (closes <a href="https://redirect.github.com/axios/axios/issues/7289">#7289</a>) (<a href="https://redirect.github.com/axios/axios/issues/7294">#7294</a>) (<a href="https://github.com/axios/axios/commit/ec9d94e9f88da13e9219acadf65061fb38ce080a">ec9d94e</a>)</li> <li>added copilot instructions (<a href="https://github.com/axios/axios/commit/3f83143bfe617eec17f9d7dcf8bafafeeae74c26">3f83143</a>)</li> <li>compatibility with frozen prototypes (<a href="https://redirect.github.com/axios/axios/issues/6265">#6265</a>) (<a href="https://github.com/axios/axios/commit/860e03396a536e9b926dacb6570732489c9d7012">860e033</a>)</li> <li>enhance pipeFileToResponse with error handling (<a href="https://redirect.github.com/axios/axios/issues/7169">#7169</a>) (<a href="https://github.com/axios/axios/commit/88d78842541610692a04282233933d078a8a2552">88d7884</a>)</li> <li><strong>types:</strong> Intellisense for string literals in a widened union (<a href="https://redirect.github.com/axios/axios/issues/6134">#6134</a>) (<a href="https://github.com/axios/axios/commit/f73474d02c5aa957b2daeecee65508557fd3c6e5">f73474d</a>), closes <a href="https://redirect.github.com//redirect.github.com/microsoft/TypeScript/issues/33471/issues/issuecomment-1376364329">microsoft/TypeScript#33471</a></li> </ul> <h3>Reverts</h3> <ul> <li>Revert "fix: silentJSONParsing=false should throw on invalid JSON (<a href="https://redirect.github.com/axios/axios/issues/7253">#7253</a>) (<a href="https://redirect.github.com/axios/axios/issues/7">#7</a>…" (<a href="https://redirect.github.com/axios/axios/issues/7298">#7298</a>) (<a href="https://github.com/axios/axios/commit/a4230f5581b3f58b6ff531b6dbac377a4fd7942a">a4230f5</a>), closes <a href="https://redirect.github.com/axios/axios/issues/7253">#7253</a> <a href="https://redirect.github.com/axios/axios/issues/7">#7</a> <a href="https://redirect.github.com/axios/axios/issues/7298">#7298</a></li> <li><strong>deps:</strong> bump peter-evans/create-pull-request from 7 to 8 in the github-actions group (<a href="https://redirect.github.com/axios/axios/issues/7334">#7334</a>) (<a href="https://github.com/axios/axios/commit/2d6ad5e48bd29b0b2b5e7e95fb473df98301543a">2d6ad5e</a>)</li> </ul> <h3>Contributors to this release</h3> <ul> <li><!-- raw HTML omitted --> <a href="https://github.com/ashvin2005" title="+1752/-4 ([#7218](https://github.com/axios/axios/issues/7218) [#7218](https://github.com/axios/axios/issues/7218) )">Ashvin Tiwari</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/mochinikunj" title="+940/-12 ([#7294](https://github.com/axios/axios/issues/7294) [#7294](https://github.com/axios/axios/issues/7294) )">Nikunj Mochi</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/imanchalsingh" title="+544/-102 ([#7169](https://github.com/axios/axios/issues/7169) [#7185](https://github.com/axios/axios/issues/7185) )">Anchal Singh</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/jasonsaayman" title="+317/-73 ([#7334](https://github.com/axios/axios/issues/7334) [#7298](https://github.com/axios/axios/issues/7298) )">jasonsaayman</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/brodo" title="+99/-120 ([#5558](https://github.com/axios/axios/issues/5558) )">Julian Dax</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/AKASHDHARDUBEY" title="+167/-0 ([#7287](https://github.com/axios/axios/issues/7287) [#7288](https://github.com/axios/axios/issues/7288) )">Akash Dhar Dubey</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/madhumitaaa" title="+20/-68 ([#7198](https://github.com/axios/axios/issues/7198) )">Madhumita</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/Tackoil" title="+80/-2 ([#6269](https://github.com/axios/axios/issues/6269) )">Tackoil</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/justindhillon" title="+41/-41 ([#6324](https://github.com/axios/axios/issues/6324) [#6315](https://github.com/axios/axios/issues/6315) )">Justin Dhillon</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/Rudrxxx" title="+71/-2 ([#7257](https://github.com/axios/axios/issues/7257) )">Rudransh</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/WuMingDao" title="+36/-36 ([#7215](https://github.com/axios/axios/issues/7215) )">WuMingDao</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/codenomnom" title="+70/-0 ([#7201](https://github.com/axios/axios/issues/7201) [#7201](https://github.com/axios/axios/issues/7201) )">codenomnom</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/Nandann018-ux" title="+60/-10 ([#7272](https://github.com/axios/axios/issues/7272) )">Nandan Acharya</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/KernelDeimos" title="+22/-40 ([#7042](https://github.com/axios/axios/issues/7042) )">Eric Dubé</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/tiborpilz" title="+40/-4 ([#5551](https://github.com/axios/axios/issues/5551) )">Tibor Pilz</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/joaoGabriel55" title="+31/-4 ([#6314](https://github.com/axios/axios/issues/6314) )">Gabriel Quaresma</a></li> <li><!-- raw HTML omitted --> <a href="https://github.com/turadg" title="+23/-6 ([#6265](https://github.com/axios/axios/issues/6265) )">Turadg Aleahmad</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/axios/axios/commit/772a4e54ecc4cc2421e2b746daff0aca10f359d7"><code>772a4e5</code></a> chore(release): prepare release 1.15.0 (<a href="https://redirect.github.com/axios/axios/issues/10671">#10671</a>)</li> <li><a href="https://github.com/axios/axios/commit/4b071371be2f810b4bc7797a13838e0f806ebb22"><code>4b07137</code></a> chore(deps-dev): bump vite from 8.0.0 to 8.0.5 in /tests/smoke/esm (<a href="https://redirect.github.com/axios/axios/issues/10663">#10663</a>)</li> <li><a href="https://github.com/axios/axios/commit/51e57b39db251bfe3d34af5c943dfea18e06c8b6"><code>51e57b3</code></a> chore(deps-dev): bump vite from 8.0.2 to 8.0.5 (<a href="https://redirect.github.com/axios/axios/issues/10664">#10664</a>)</li> <li><a href="https://github.com/axios/axios/commit/fba1a77930f0c459677b729161627234b88c90aa"><code>fba1a77</code></a> chore(deps-dev): bump vite from 8.0.2 to 8.0.5 in /tests/module/esm (<a href="https://redirect.github.com/axios/axios/issues/10665">#10665</a>)</li> <li><a href="https://github.com/axios/axios/commit/0bf6e28eac86e87da2b60bbf5ea4237910e1a08e"><code>0bf6e28</code></a> chore(deps): bump denoland/setup-deno in the github-actions group (<a href="https://redirect.github.com/axios/axios/issues/10669">#10669</a>)</li> <li><a href="https://github.com/axios/axios/commit/8107157c572ee4a54cb28c01ab7f7f3d895ba661"><code>8107157</code></a> chore(deps-dev): bump the development_dependencies group with 4 updates (<a href="https://redirect.github.com/axios/axios/issues/10670">#10670</a>)</li> <li><a href="https://github.com/axios/axios/commit/e66530e3302d56176befd0778155dafea2487542"><code>e66530e</code></a> ci: require npm-publish environment for releases (<a href="https://redirect.github.com/axios/axios/issues/10666">#10666</a>)</li> <li><a href="https://github.com/axios/axios/commit/49f23cbfe4d308a075281c5f798d4c68f648cbe2"><code>49f23cb</code></a> chore(sponsor): update sponsor block (<a href="https://redirect.github.com/axios/axios/issues/10668">#10668</a>)</li> <li><a href="https://github.com/axios/axios/commit/363185461b90b1b78845dc8a99a1f103d9b122a1"><code>3631854</code></a> fix: unrestricted cloud metadata exfiltration via header injection chain (<a href="https://redirect.github.com/axios/axios/issues/10">#10</a>...</li> <li><a href="https://github.com/axios/axios/commit/fb3befb6daac6cad26b2e54094d0f2d9e47f24df"><code>fb3befb</code></a> fix: no_proxy hostname normalization bypass leads to ssrf (<a href="https://redirect.github.com/axios/axios/issues/10661">#10661</a>)</li> <li>Additional commits viewable in <a href="https://github.com/axios/axios/compare/v1.13.6...v1.15.0">compare view</a></li> </ul> </details> <details> <summary>Install script changes</summary> <p>This version modifies <code>prepare</code> script that runs during installation. Review the package contents before updating.</p> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/chatwoot/chatwoot/network/alerts). </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> |
||
|
|
64f6bfc811 |
feat: Inline edit support for contact info (#13976)
# Pull Request Template ## Description This PR adds inline editing support for contact name, phone number, email, and company fields in the conversation contact sidebar ## Type of change - [x] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? **Screencast** https://github.com/user-attachments/assets/e9f8e37d-145b-4736-b27a-eb9ea66847bd ## 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 --------- Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
72c9e1775b |
fix: Prevent article editor from resetting content while typing (#14014)
# Pull Request Template ## Description ### Description This PR fixes an issue where the editor would reset content and move the cursor while typing. The issue was caused by a dual debounce setup (400ms + 2500ms) that saved content and then overwrote local state with stale API responses while the user was still typing. ### What changed * Editor now uses local state (`localTitle`, `localContent`) as the source of truth while editing * Vuex store is only used on initial load or navigation * Replaced dual debounce with a single 500ms debounce (fewer API calls) * `UPDATE_ARTICLE` now merges updates instead of replacing the article * Prevents status changes from wiping unsaved content * Removed `updateAsync` for a simpler update flow ### How it works User types → local ref updates immediately (editor reads from this) → 500ms debounce triggers → dispatches `articles/update` → API persists the change → on success: store merges the response (used by other components) → editor remains unaffected (continues using local state) Fixes https://linear.app/chatwoot/issue/CW-6727/better-syncing-of-content-the-editor-randomly-updates-the-content ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? 1. Open any Help Center article for editing 2. Type continuously for a few seconds — content should not reset or jump 3. Change article status (publish/archive/draft) while editing — content should remain intact 4. Test on a slow network (use DevTools throttling) — typing should remain smooth ## 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: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
b7b6e67df7 |
fix(captain): localize AI summary to account language (#13790)
AI-generated summaries now respect the account's language setting. Previously, summaries were always returned in English regardless of the user's configured language, making section headings like "Customer Intent" and "Action Items" appear in English even for non-English accounts. Previous behavior: <img width="1336" height="790" alt="image" src="https://github.com/user-attachments/assets/5df8b78b-1218-438d-9578-a806b5cb94ac" /> Current Behavior: <img width="1253" height="372" alt="image" src="https://github.com/user-attachments/assets/ae932c97-06da-4baf-9f77-9719bc9162e8" /> ## What changed - Added explicit account locale to the AI system prompt in `Captain::SummaryService` - Updated the summary prompt template to instruct the model to translate section headings ## How to test 1. Configure an account with a non-English language (e.g., Portuguese) 2. Open a conversation with messages 3. Use the Copilot "Summarize" feature 4. Verify that section headings ("Customer Intent", "Conversation Summary", etc.) appear in the account's language --------- Co-authored-by: Aakash Bakhle <48802744+aakashb95@users.noreply.github.com> |
||
|
|
288c1cb757 | fix: Respect app direction for incoming email content (#14011) | ||
|
|
a8c8b38f51 | fix: create article on title blur instead of debounce (#14037) | ||
|
|
f422c83c26 |
feat: Add unified Call model for voice calling (#14026)
Adds a Call model to track voice call state across providers (Twilio, WhatsApp). This replaces storing call data in conversation.additional_attributes and provides a foundation for call analytics multi-call-per-conversation support, and future voice providers. --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> |
||
|
|
722e68eecb |
fix: validate support_email format and handle parse errors in mailer (#13958)
## Description ConversationReplyMailer#parse_email calls Mail::Address.new(email_string).address without error handling. When an account's support_email contains a non-email string (e.g., "Smith Smith"), the mail gem raises Mail::Field::IncompleteParseError, crashing conversation transcript emails. This has caused 1,056 errors on Sentry (EXTERNAL-CHATINC-JX) since Feb 25, all from a single account that has a name stored in the support_email field instead of a valid email address. Closes https://linear.app/chatwoot/issue/CW-6687/mailfieldincompleteparseerror-mailaddresslist-can-not-parse-orsmith ## Type of change Please delete options that are not relevant. - [ ] 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 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Vishnu Narayanan <iamwishnu@gmail.com> |
||
|
|
0592cccca9 |
fix: prevent lost custom_attributes updates from concurrent jsonb writes (#14040)
## Linear ticket https://linear.app/chatwoot/issue/CW-6834/billing-upgrade-didnt-work ## Description A `customer.subscription.updated` Stripe webhook for account 76162 returned 200 OK but did not persist the new `subscribed_quantity`. Root cause: a race condition between the webhook handler and `increment_response_usage` (Captain usage counter), both doing read-modify-write on the `custom_attributes` JSONB column. The webhook wrote `quantity: 6`, then a concurrent `save` from `increment_response_usage` overwrote the entire hash with stale data — restoring `quantity: 5`. Fix: use atomic `jsonb_set` so usage counter updates only touch the single key they care about, instead of rewriting the whole `custom_attributes` hash. `increment_custom_attribute` also performs the increment in SQL, making concurrent increments correct as well. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - New regression spec in `handle_stripe_event_service_spec.rb` that simulates concurrent webhook + `increment_response_usage` and asserts both `subscribed_quantity` and `captain_responses_usage` survive - Existing account, billing, captain, and topup specs all pass 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 - [ ] Any dependent changes have been merged and published in downstream modules |
||
|
|
45b6ea6b3f |
feat: add automation condition to filter private notes (#12102)
## Summary Adds a new automation condition to filter private notes. This allows automation rules to explicitly include or exclude private notes instead of relying on implicit behavior. Fixes: #11208 ## Preview https://github.com/user-attachments/assets/c40f6910-7bbf-4e59-aae5-ad408602927a |
||
|
|
de0bd8e71b |
fix(perf): disable tags counter cache to prevent label deadlocks (#14021)
Label attach/detach against a shared label no longer deadlocks under parallel load. During high-concurrency label writes (for example, a broadcast script attaching a campaign label to many conversations at once), Chatwoot previously hit periodic `ActiveRecord::Deadlocked` errors and tail-latency spikes on the tags table. This PR removes the contention by disabling the `acts-as-taggable-on` counter cache, which Chatwoot never reads. ## Closes Fixes [INF-68](https://linear.app/chatwoot/issue/INF-68) (event 2) ## How to reproduce 1. Seed an account with ~20 conversations and 5 labels. 2. Spawn 20 parallel threads, each calling `conversation.update!(label_list: shared_labels.shuffle)` against different conversations. 3. Observe `ActiveRecord::Deadlocked` exceptions and p99 label-write latency well above 1s. With the counter cache disabled, the deadlock cycle cannot form. ## How this was tested - Ran a 20-thread synthetic load test locally, each thread attaching 5 shared labels (shuffled per request) to different conversations. With the counter cache enabled: 8 deadlocks across 300 attempts, p99 ~2.2s. With the counter cache disabled: zero deadlocks, p99 ~306ms (roughly 85% tail-latency reduction). The `UPDATE tags SET taggings_count = ...` statement disappears from the SQL log entirely. - Verified at boot via `rails runner` that `ActsAsTaggableOn::Tagging.reflect_on_association(:tag).options[:counter_cache]` returns `false` after the initializer runs. The gem wires `belongs_to :tag, counter_cache: ActsAsTaggableOn.tags_counter` at class-load time, so the initializer must sit ahead of the `Tagging` autoload path; this confirms it does. |
||
|
|
224b1f98b0 |
fix: handle ioerror in imap fetch (#13960)
## Description The IMAP email fetch job (Inboxes::FetchImapEmailsJob) crashes with an unhandled IOError: closed stream when the mail server's SSL socket is closed mid-write during Net::IMAP#fetch. This error was being reported to Sentry because the rescue clause only caught EOFError, not its parent class IOError. Fixes [CW-6689](https://linear.app/chatwoot/issue/CW-6689/ioerror-closed-stream-ioerror) Widened the rescue in fetch_imap_emails_job.rb from EOFError to IOError. In Ruby's exception hierarchy, EOFError is a subclass of IOError: ``` StandardError └── IOError └── EOFError ``` The Sentry stacktrace shows a plain IOError: closed stream raised from OpenSSL::Buffering#do_write → Net::IMAP#put_string → Net::IMAP#fetch. Since this is an IOError (not EOFError), it bypassed the existing rescue and fell through to the StandardError catch-all, which reported it to Sentry as an unhandled exception. Rescuing IOError now catches both: IOError: closed stream — the reported crash (parent class) EOFError — the previously handled case (still caught as a subclass) ## 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 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
3190b29fe9 |
fix(revert): "fix: Ignore RoutingError in New Relic error reporting (#14030)" (#14038)
This reverts commit
|
||
|
|
42163946eb |
fix: Ignore RoutingError in New Relic error reporting (#14030)
Routing errors (404s) are expected in production and don't represent actionable issues. Reporting them to New Relic creates noise and makes it harder to spot real errors. Adds ActionController::RoutingError to the New Relic error_collector.ignore_errors list so these are no longer tracked as exceptions. |
||
|
|
f13f3ba446 |
fix: log only on system api key failures (#13968)
Removes sentry flooding of unnecessary rubyllm logs of wrong API key. Logs only system api key error since it would be P0. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
f1da7b8afa |
feat: enable assignment v2 by default for new accounts (#14031)
## Description Enable assignment v2 by default for new accounts ## Type of change - [ ] New feature (non-breaking change which adds functionality) ## 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 |
||
|
|
bd14e96ed9 | chore: allow article to create without content (#14007) | ||
|
|
00837019b5 |
fix(captain): display handoff message to customer in V2 flow (#13885)
HandoffTool changes conversation status but only posts a private note.
ResponseBuilderJob now detects the tool flag and creates the public
handoff message that was previously only shown in V1.
# Pull Request Template
## Description
Captain V2 was silently forwarding conversations to humans without
showing a handoff message to the customer. The conversation appeared to
just stop
responding.
Root cause: In V2, HandoffTool calls bot_handoff! during agent
execution, which changes conversation status from pending to open. By
the time control returns
to ResponseBuilderJob#process_response, the conversation_pending? guard
returns early - skipping create_handoff_message entirely. The V1 flow
didn't have this
problem because AssistantChatService just returns a string token
(conversation_handoff) and lets ResponseBuilderJob handle everything.
What changed:
1. AgentRunnerService now surfaces the handoff_tool_called flag (already
tracked internally for usage metadata) in its response hash.
2. ResponseBuilderJob#handoff_requested? detects handoffs from both V1
(response token) and V2 (tool flag).
3. ResponseBuilderJob#process_response checks handoff_requested? before
the conversation_pending? guard, so V2 handoffs are processed even when
the status has
already changed.
4. ResponseBuilderJob#process_action('handoff') captures
conversation_pending? before calling bot_handoff! and uses that snapshot
to guard both bot_handoff!
and the OOO message - preventing double-execution when V2's HandoffTool
already ran them.
New V2 handoff flow:
AgentRunnerService
→ agent calls HandoffTool (creates private note, calls bot_handoff!)
→ returns response with handoff_tool_called: true
ResponseBuilderJob#process_response
→ handoff_requested? detects the flag
→ process_action('handoff')
→ create_handoff_message (public message for customer)
→ bot_handoff! skipped (conversation_pending? is false)
→ OOO skipped (conversation_pending? is false)
Fixes #13881
## Type of change
Please delete options that are not relevant.
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality not to work as expected)
- [ ] This change requires a documentation update
## How Has This Been Tested?
- Update existing response_builder_job_spec.rb covering the V2 handoff
path, V2 normal response path, and V1 regression
- Updated existing agent_runner_service_spec.rb expectations for the new
handoff_tool_called key and added a context for when the flag is true
## 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
- [x] Any dependent changes have been merged and published in downstream
modules
---------
Co-authored-by: Aakash Bakhle <48802744+aakashb95@users.noreply.github.com>
Co-authored-by: aakashb95 <aakashbakhle@gmail.com>
|
||
|
|
45124c3b41 |
fix(i18n): improve zh-TW translation coverage and quality (#14004)
Comprehensive update to Traditional Chinese (Taiwan) translations. As a native zh-TW speaker and active user based in Taiwan, I found the existing translations were quite incomplete (~54% overall) with many strings still in English. Some existing translations also used Simplified Chinese terms or unnatural phrasing. I chose to submit this as a direct PR rather than going through Crowdin because working through all the files at once is much faster and lets me ensure consistent terminology across the entire locale. Closes #14003 ## What changed **Backend (`config/locales/zh_TW.yml`)** - Translated all ~259 previously untranslated strings (was ~19% complete, now 100%) - Covers: error messages, notifications, activity logs, integration descriptions, Captain AI, public portal, reports **Frontend (42 JSON files under `dashboard/i18n/locale/zh_TW/`)** - Translated ~2,627 previously untranslated strings (was ~50% complete, now ~100%) - Most impacted files: `inboxMgmt.json`, `integrations.json`, `settings.json`, `conversation.json`, `contact.json`, `report.json` **Quality fixes across all files** - Replaced Simplified Chinese terms mixed into zh-TW: 账→帳, 获→取得, 模板→範本, 收件箱→收件匣, 重置→重設, 自定義→自訂 - Standardized terminology for consistency: 客服人員 (agent), 延後 (snooze), 稽核 (audit), 巨集 (macro) - Fixed incorrect translations (e.g., audit log table headers were swapped, availability label was wrong) ## How to test 1. Set account/user language to 中文(台灣) 2. Navigate through the dashboard — settings, inbox management, integrations, reports, conversations 3. Verify strings display in natural Traditional Chinese with no remaining English gaps 4. Check that all placeholders (names, counts, dates) render correctly |
||
|
|
699b12b1d3 |
fix: Block inline images in message signatures (#13772)
# Pull Request Template ## Description This PR includes, block inline images in message signatures and prevent auto signature insertion when editor is disabled. - Strip inline base64 images from signature on save and show warning message - Add `INLINE_IMAGE_WARNING` translation key for signature inline image removal notification - Add disabled check to `addSignature()` to prevent signature insertion when editor is disabled - Add `isEditorDisabled` checks to signature toggle logic in `toggleSignatureForDraft()`, `replaceText()`, and `clearMessage()` - Remove unused `replaceText` from the codebase, which belongs to old `textarea` editor Fixes https://linear.app/chatwoot/issue/CW-6588/the-browser-hangs-when-the-message-signature-contains-inline-image ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/fb556b46a12a4308a737eed732d5ed73 ## 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 --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
e5107604a0 |
feat: account enrichment using context.dev [UPM-27] (#13978)
## Account branding enrichment during signup This PR does the following ### Replace Firecrawl with Context.dev Switches the enterprise brand lookup from Firecrawl to Context.dev for better data quality, built-in caching, and automatic filtering of free/disposable email providers. The service interface changes from URL to email input to match Context.dev's email endpoint. OSS still falls back to basic HTML scraping with a normalized output shape across both paths. The enterprise path intentionally does not fall back to HTML scraping on failure — speed matters more than completeness. We want the user on the editable onboarding form fast, and a slow fallback scrape is worse than letting them fill it in. Requires `CONTEXT_DEV_API_KEY` in Super Admin → App Config. Without it, falls back to OSS HTML scraping. ### Add job to enrich account details After account creation, `Account::BrandingEnrichmentJob` looks up the signup email and pre-fills the account name, colors, logos, social links, and industry into `custom_attributes['brand_info']`. The job signals completion via a short-lived Redis key (30s TTL) + an ActionCable broadcast (`account.enrichment_completed`). The Redis key lets the frontend distinguish "still running" from "finished with no results." |
||
|
|
871f2f4d56 | fix: harden fetching on upload endpoint (#14012) | ||
|
|
4f94ad4a75 |
feat: ensure signup verification [UPM-14] (#13858)
Previously, signing up gave immediate access to the app. Now, unconfirmed users are redirected to a verification page where they can resend the confirmation email. - After signup, the user is routed to `/auth/verify-email` instead of the dashboard - After login, unconfirmed users are redirected to the verification page - The dashboard route guard catches unconfirmed users and redirects them - `active_for_authentication?` is removed from the sessions controller so unconfirmed users can authenticate — the frontend gates access instead - If the user visits the verification page after already confirming, they're automatically redirected to the dashboard - No session is issued until the user is verified <details><summary>Demo</summary> <p> #### Fresh Signup https://github.com/user-attachments/assets/abb735e5-7c8e-44a2-801c-96d9e4823e51 #### Google Fresh Signup https://github.com/user-attachments/assets/ab9e389a-a604-4a9d-b492-219e6d94ee3f #### Create new account from Dashboard https://github.com/user-attachments/assets/c456690d-1946-4e0b-834b-ad8efcea8369 </p> </details> --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com> |
||
|
|
fbe3560b7a |
feat(captain): Add paywall and expose Custom Tools (#13977)
# Pull Request Template ## Description Custom tools is now discoverable on all plans ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? Before: <img width="390" height="446" alt="CleanShot 2026-04-02 at 13 40 11@2x" src="https://github.com/user-attachments/assets/0a751954-f3ad-47d6-85b8-1e2f1476a646" /> After: <img width="392" height="522" alt="CleanShot 2026-04-02 at 13 40 47@2x" src="https://github.com/user-attachments/assets/62a252f6-2551-47a9-b50c-be949f08c456" /> <img width="1826" height="638" alt="CleanShot 2026-04-02 at 13 37 39@2x" src="https://github.com/user-attachments/assets/77dc2a75-3d76-44cf-8579-8d3457879bd0" /> ## 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 --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
118270d2e8 |
fix(agent-bot): Update listener spec to match signed webhook arguments (#14006)
Fixes failing `agent_bot_listener_spec.rb` tests for `conversation_status_changed` events. After #13892 added webhook signing, `process_webhook_bot_event` passes `:agent_bot_webhook` and `secret:`/`delivery_id:` kwargs to `AgentBots::WebhookJob.perform_later`, but two spec expectations were not updated to match the new call signature. ## What changed - Updated `perform_later` expectations in `conversation_status_changed` specs to include the `:agent_bot_webhook` type and `secret` keyword arguments. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
8c0c0fd32c |
chore: Update translations (#13990)
Co-authored-by: Sojan Jose <sojan.official@gmail.com> Co-authored-by: Sojan Jose <sojan@pepalo.com> |
||
|
|
50d6ebaaca |
fix(agent-bot): Dispatch conversation_status_changed event to agent bots (#14002)
Agent bots assigned to a conversation were not receiving `conversation_status_changed` webhook events. This meant bots could not react to status transitions like moving a conversation to **pending**. The deprecated `conversation_opened` and `conversation_resolved` events were still being delivered, but the newer unified `conversation_status_changed` event was silently dropped because `AgentBotListener` had no handler for it. ## What changed - Added `conversation_status_changed` handler to `AgentBotListener`, matching the pattern already used by `WebhookListener`. The payload includes `changed_attributes` so bots know which status transition occurred. ## How to test 1. Configure an agent bot with an `outgoing_url` (e.g. a webhook.site endpoint). 2. Assign the bot to an inbox or conversation. 3. Change a conversation's status to **pending** (or any other status). 4. Verify the bot receives a `conversation_status_changed` event with the correct `changed_attributes`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
95463230cb |
feat: sign webhooks for API channel and agentbots (#13892)
Account webhooks sign outgoing payloads with HMAC-SHA256, but agent bot and API inbox webhooks were delivered unsigned. This PR adds the same signing to both. Each model gets a dedicated `secret` column rather than reusing the agent bot's `access_token` (for API auth back into Chatwoot) or the API inbox's `hmac_token` (for inbound contact identity verification). These serve different trust boundaries and shouldn't be coupled — rotating a signing secret shouldn't invalidate API access or contact verification. The existing `Webhooks::Trigger` already signs when a secret is present, so the backend change is just passing `secret:` through to the jobs. Shared token logic is extracted into a `WebhookSecretable` concern included by `Webhook`, `AgentBot`, and `Channel::Api`. The frontend reuses the existing `AccessToken` component for secret display. Secrets are admin-only and excluded from enterprise audit logs. ### How to test Point an agent bot or API inbox webhook URL at a request inspector. Send a message and verify `X-Chatwoot-Signature` and `X-Chatwoot-Timestamp` headers are present. Reset the secret from settings and confirm subsequent deliveries use the new value. --------- Co-authored-by: Sojan Jose <sojan@pepalo.com> |
||
|
|
f4d66566d0 |
fix(agent-bot): Include changed_attributes in conversation_updated webhook (#14001)
The `conversation_updated` webhook sent to AgentBots did not include
`changed_attributes`, making it impossible for bots to distinguish
between different types of conversation updates (e.g. bot assignment vs
label change vs status change).
This aligns the AgentBot webhook payload with the existing
`WebhookListener` behavior, which already includes `changed_attributes`.
## How to reproduce
1. Assign an AgentBot to a conversation
2. Then update the conversation (e.g. add a label)
3. **Before fix:** Both events arrive with identical payload structure —
bot cannot tell them apart
4. **After fix:** Each event includes `changed_attributes` showing
exactly what changed
## What changed
- **`AgentBotListener#conversation_updated`**: Added
`changed_attributes` to the webhook payload using
`extract_changed_attributes` (same pattern as `WebhookListener`)
## How to test
1. Assign an AgentBot to a conversation via API
2. Check the webhook payload — should include:
```json
"changed_attributes": [
{ "assignee_agent_bot_id": { "previous_value": null, "current_value": 7
} }
]
```
3. Update the conversation (e.g. add a label)
4. Check the webhook payload — `changed_attributes` should reflect the
label change, not bot assignment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
5fd3d5e036 |
feat: allow zero conversation limit capacity policy (#13964)
## Description Two improvements to Agent Capacity Policy: **1. Support exclusion via zero conversation limit** Allow `conversation_limit` to be `0` on inbox capacity limits. Agents with a zero limit are excluded from auto-assignment for that inbox while remaining members for manual assignment. **2. Fix exclusion rules duration input** - Default changed from `10` to `null` so time-based exclusion isn't applied unless explicitly set. - Minimum lowered from 10 to 1 minute. - `DurationInput` updated to handle `null` values correctly. ## Type of change Please delete options that are not relevant. - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Added model and capacity service specs for zero-limit exclusion behavior. - Tested manually via UI flows ## 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> |
||
|
|
6f5ad8f372 |
fix: strip manually_managed_features from params in super admin account create (#13983)
## Summary When a Super Admin creates a new account via the Administrate dashboard, the `manually_managed_features` field (a virtual attribute stored in `internal_attributes` JSON) is passed to `Account.new(...)`, raising `ActiveModel::UnknownAttributeError`. The existing `update` action already strips this param — this fix adds the same handling to `create`. Closes -> https://linear.app/chatwoot/issue/INF-66 Related Sentry -> https://chatwoot-p3.sentry.io/issues/7168237533/?project=6382945&referrer=Linear ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How to reproduce 1. Log in as Super Admin 2. Navigate to Accounts → New 3. Fill in the form (with or without manually managed features selected) 4. Submit → `ActiveModel::UnknownAttributeError: unknown attribute 'manually_managed_features' for Account` ## What changed - Added a `create` override in `Enterprise::SuperAdmin::AccountsController` that strips `manually_managed_features` from params before calling `super`, then persists them via `InternalAttributesService` after the account is saved. |
||
|
|
441fe4db11 |
fix: scope external_url override to Instagram DM conversations only (#13982)
Previously, all incoming messages from Facebook channel with instagram_id had their attachment data_url and thumb_url overridden with external_url. This caused issues for non-Instagram conversations originating from Facebook Message where the file URL should be used instead. Narrows the override to only apply when the conversation type is instagram_direct_message, which is the only case where Instagram's CDN URLs need to be used directly. Fixes https://linear.app/chatwoot/issue/CW-6722/videos-are-missing-in-facebook-conversation --------- Co-authored-by: Muhsin <12408980+muhsin-k@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
b9b5a18767 |
revert: html background for widget (#13981)
Reverts chatwoot/chatwoot#13955 |
||
|
|
b815eb9ce0 |
fix(agent-bot): Dispatch webhook event on agent bot assignment (#13975)
When an AgentBot is assigned to a conversation after the first message
has already been received, the bot does not respond because it never
receives any event. The `message_created` event fires before the bot is
assigned, and the bot has no way to know it was assigned.
Chatwoot already dispatches a `CONVERSATION_UPDATED` event when
`assignee_agent_bot_id` changes, but `AgentBotListener` wasn't listening
for it. This fix adds a `conversation_updated` handler so the bot
receives a webhook with the conversation context when assigned.
## How to reproduce
1. Customer sends a message → conversation created, `message_created`
fires
2. System processes the message (adds labels, custom attributes)
3. System assigns an AgentBot to the conversation via API
4. **Before fix:** Bot receives no event and never responds
5. **After fix:** Bot receives `conversation_updated` event with
conversation payload
## What changed
- **`AgentBotListener`**: Added `conversation_updated` handler that
sends the conversation webhook payload to the assigned bot when the
conversation is updated
## How to test
1. Create an AgentBot with an `outgoing_url` pointing to a webhook
inspector (e.g. webhook.site)
2. Send a message to create a conversation
3. Assign the AgentBot to the conversation via API:
```
POST /api/v1/accounts/{id}/conversations/{id}/assignments
{ "assignee_id": <bot_id>, "assignee_type": "AgentBot" }
```
4. Verify the bot receives a `conversation_updated` event at its webhook
URL
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
b3d0af84c4 |
fix(widget): Queue SDK-set conversation attributes and labels for first message (#13912)
### Description
When integrating the web widget via the JS SDK, customers call
setConversationCustomAttributes and setLabel on chatwoot:ready — before
any conversation exists. These API calls silently fail because the
backend endpoints require an existing conversation. When the visitor
sends their first message, the conversation is created without those
attributes/labels, so the message_created webhook payload is missing the
expected metadata.
This change queues SDK-set conversation custom attributes and labels in
the widget store when no conversation exists yet, and includes them in
the API request when the first message (or attachment) creates the
conversation. The backend now permits and applies these params during
conversation creation — before the message is saved and webhooks fire.
### How to test
1. Configure a web widget without a pre-chat form.
2. Open the widget on a test page and run the following in the browser
console after chatwoot:ready:
`window.$chatwoot.setConversationCustomAttributes({ plan: 'enterprise'
});`
`window.$chatwoot.setLabel('vip');` // must be a label that exists in
the account
3. Send the first message from the widget.
4. Verify in the Chatwoot dashboard that the conversation has plan:
enterprise in custom attributes and the vip label applied.
5. Set up a webhook subscriber for `message_created` confirm the first
payload includes the conversation metadata.
6. Verify that calling `setConversationCustomAttributes` / `setLabel` on
an existing conversation still works as before (direct API path, no
regression).
7. Verify the pre-chat form flow still works as expected.
|
||
|
|
d83beb2148 |
fix: Populate extension and include content_type in attachment webhook payload (#13945)
Attachment webhook event payloads (`message_created`) were missing the
file extension and content type. The `extension` column existed but was
never populated, and `content_type` was not included in the payload at
all.
## What changed
- Added `before_save :set_extension` callback to extract file extension
from the filename when saving an attachment.
- Added `content_type` (from ActiveStorage) to the `file_metadata` used
in `push_event_data`.
### Before
```json
{
"extension": null,
"data_url": "...",
"file_size": 11960
}
```
### After
```json
{
"extension": "pdf",
"content_type": "application/pdf",
"data_url": "...",
"file_size": 11960
}
```
## How to reproduce
1. Send a message with a file attachment (e.g., PDF) via any channel
2. Inspect the `message_created` webhook payload
3. Observe `extension` is `null` and `content_type` is missing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
8daf6cf6cb |
feat: captain custom tools v1 (#13890)
# Pull Request Template ## Description Adds custom tool support to v1 ## 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. <img width="1816" height="958" alt="CleanShot 2026-03-24 at 11 37 33@2x" src="https://github.com/user-attachments/assets/2777a953-8b65-4a2d-88ec-39f395b3fb47" /> <img width="378" height="488" alt="CleanShot 2026-03-24 at 11 38 18@2x" src="https://github.com/user-attachments/assets/f6973c99-efd0-40e4-90fe-4472a2f63cea" /> <img width="1884" height="1452" alt="CleanShot 2026-03-24 at 11 38 32@2x" src="https://github.com/user-attachments/assets/9fba4fc4-0c33-46da-888a-52ec6bad6130" /> ## Checklist: - [x] 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: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> |
||
|
|
211fb1102d |
chore: rotate oauth password if unconfirmed (#13878)
When a user signs up with an email they don't own and sets a password, that password remains valid even after the real owner later signs in via OAuth. This means the original registrant — who never proved ownership of the email — retains working credentials on the account. This change closes that gap by rotating the password to a random value whenever an unconfirmed user completes an OAuth sign-in. The check (`oauth_user_needs_password_reset?`) is evaluated before `skip_confirmation!` runs, since confirmation would flip `confirmed_at` and mask the condition. If the user was unconfirmed, the stored password is replaced with a secure random string that satisfies the password policy. This applies to both the web and mobile OAuth callback paths, as well as the sign-up path where the password is rotated before the reset token is generated. Users who lose access to password-based login as a side effect can recover through the standard "Forgot password" flow at any time. Since they've already proven email ownership via OAuth, this is a low-friction recovery path |
||
|
|
7b09b033ef |
fix: Markdown tables don't render properly in help centre (#13971)
# Pull Request Template ## Description This PR fixes an issue where markdown tables were not rendering correctly in the Help Center. The issue was caused by a backslash `(\)` being appended after table row separators `(|)`, which breaks the markdown table parsing. The issue was introduced after recent editor changes made to preserve new lines, which unintentionally affected how table markdown is parsed and displayed. ### https://github.com/chatwoot/prosemirror-schema/pull/44 Fixes https://linear.app/chatwoot/issue/CW-6714/markdown-tables-dont-render-properly-in-help-centre-preview ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? **Before** ``` | Type | What you provide |\ |--------------|-------------------------------|\ | None | No authentication |\ | Bearer Token | A token string |\ | Basic Auth | Username and password |\ | API Key | A custom header name and value| ``` **After** ``` | Type | What you provide | |--------------|-------------------------------| | None | No authentication | | Bearer Token | A token string | | Basic Auth | Username and password | | API Key | A custom header name and value| ``` ## 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 |
||
|
|
65867b8b36 |
fix: exclude MutexApplicationJob::LockAcquisitionError from Sentry (#13965)
## Summary - Add `MutexApplicationJob::LockAcquisitionError` to Sentry's `excluded_exceptions` - This error is expected control flow (mutex lock contention during webhook processing), not a bug - Generated ~131K Sentry events in March 2026, 100% from `InstagramEventsJob` Fixes https://linear.app/chatwoot/issue/INF-58 |
||
|
|
4cce7f6ad8 |
fix(line): Use non-expiring URLs for image and video messages (#13949)
Images and videos sent from Chatwoot to LINE inboxes fail to display on the LINE mobile app — users see expired markers, broken thumbnails, or missing images. This happens because LINE mobile lazy-loads images rather than downloading them immediately, and the ActiveStorage signed URLs expire after 5 minutes. Closes https://linear.app/chatwoot/issue/CW-6696/line-messaging-with-image-or-video-may-not-show-when-client-inactive ## How to reproduce 1. Create a LINE inbox and start a chat from the LINE mobile app 2. Close the LINE mobile app 3. Send an image from Chatwoot to that chat 4. Wait 7-8 minutes (past the 5-minute URL expiration) 5. Open the LINE mobile app — the image is broken/expired ## What changed - **`originalContentUrl`**: switched from `download_url` (signed, 5-min expiry) to `file_url` (permanent redirect-based URL) - **`previewImageUrl`**: switched to `thumb_url` (250px resized thumbnail meeting LINE's 1MB/240x240 recommendation), with fallback to `file_url` for non-image attachments like video 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Sojan Jose <sojan@pepalo.com> |
||
|
|
f2cb23d6e9 |
fix: handle Socket::ResolutionError in browser push notifications (#13957)
## Linear Ticket https://linear.app/chatwoot/issue/CW-6707/socketresolutionerror-failed-to-open-tcp-connection-to-permanently https://linear.app/chatwoot/issue/CW-6707/socketresolutionerror-failed-to-open-tcp-connection-to-permanently#comment-14e0f9ff ## Description Browser push notifications fail with Socket::ResolutionError when the push subscription endpoint's domain can't be resolved via DNS (e.g., defunct push service, transient DNS failure). This error wasn't handled in handle_browser_push_error, so it fell through to the catch-all else branch and got reported to Sentry on every notification attempt — 1,637 times in the last 7 days. The dead subscription was never cleaned up or the error suppressed, so every subsequent notification for the affected user triggered the same Sentry alert. Added Socket::ResolutionError to the existing transient network error handler alongside Errno::ECONNRESET, Net::OpenTimeout, and Net::ReadTimeout. The error is logged but not reported to Sentry, and the subscription is kept intact in case it's a temporary DNS blip. ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - Verified that Socket::ResolutionError is a subclass of StandardError and matches the when clause ## 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: Vishnu Narayanan <iamwishnu@gmail.com> |
||
|
|
8824efe0e1 | fix(sentry): syntaxError: No error message (#13954) | ||
|
|
5de7ae492c |
fix: html/body background not applied in appearance mode (#13955)
# Pull Request Template ## Description This PR fixes the white background bleed visible in the widget, widget article viewer and help center when dark mode is active. **What was happening** While scrolling, the `<body>` element retained a white background in dark mode. This occurred because dark mode classes were only applied to inner container elements, not the root. **What changed** * **Widget:** Updated the `useDarkMode` composable to sync the `dark` class to `<html>` using `watchEffect`, allowing `<body>` to inherit dark theme variables. Also added background styles to `html`, `body`, and `#app` in `woot.scss`. * **Help center portal:** Moved `bg-white dark:bg-slate-900` from `<main>` to `<body>` in the portal layout so the entire page background responds correctly to dark mode, including within the widget iframe. * **ArticleViewer:** Replaced hardcoded `bg-white` with `bg-n-solid-1` to ensure better theming. Fixes https://linear.app/chatwoot/issue/CW-6704/widget-body-colour-not-implemented ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Screencasts ### Before **Widget** https://github.com/user-attachments/assets/e0224ad1-81a6-440a-a824-e115fb806728 **Help center** https://github.com/user-attachments/assets/40a8ded5-5360-474d-9ec5-fd23e037c845 ### After **Widget** https://github.com/user-attachments/assets/dd37cc68-99fc-4d60-b2ae-cf41f9d4d38c **Help center** https://github.com/user-attachments/assets/bc998c4e-ef77-46fa-ac7f-4ea16d912ce3 ## 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 |
||
|
|
b4b5de9b46 |
fix: conservative hand_off prompt on auto-resolution (#13953)
# Pull Request Template ## Description The initial version of prompt deciding to resolve or hand-off to human agents was too conservative especially in cases where a link or an action was told to customer. If the customer didn't respond, Captain was told to hand it off to the agent, but customer may actually have solved the issue. If not, they can come back and continue the conversation. Removed two lines about the same and now we should not see needless handoffs. ## 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 ## 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 |