Commit Graph

620 Commits

Author SHA1 Message Date
Abhinav Raut 29847f955f keep campaign visitor sessions identified 2026-09-18 16:38:24 +05:30
Abhinav Raut b28f57674f fix quick reply character limits 2026-09-18 16:38:03 +05:30
Abhinav Raut 7d77754b52 improve live chat widget flows
Expand widget conversations with audience-specific forms, AI handoffs, message previews, and help article translations. Keep existing inbox settings compatible and reject invalid live chat configuration.
2026-09-18 16:09:15 +05:30
Abhinav Raut 3843f1e7e9 Merge branch 'main' into libredesk-widget-improvements 2026-09-18 02:55:49 +05:30
Abhinav Raut ccba084d4b Merge remote-tracking branch 'origin/main' into libredesk-widget-improvements 2026-09-18 02:54:09 +05:30
Abhinav Raut ab44d64068 add cursor pagination and search sorting 2026-09-18 02:21:05 +05:30
Abhinav Raut 3d09ad1a2e preserve existing search API responses 2026-09-18 01:20:44 +05:30
Abhinav Raut 9c1e14704f fix campaign reply and poll edge cases, enlarge mobile launcher 2026-09-18 01:05:21 +05:30
Abhinav Raut 9391b50b80 fix search results and pagination 2026-09-17 02:29:30 +05:30
Abhinav Raut 608eefb76d Merge remote-tracking branch 'origin/main' into search-improvements 2026-09-17 02:25:17 +05:30
Abhinav Raut f600e7e9b7 add filters, pagination and richer results to conversation search 2026-09-16 13:01:35 +05:30
Abhinav Raut 89f58904d2 wip: add widget campaigns, help center in widget and transcript download 2026-09-16 02:11:44 +05:30
Abhinav Raut 6655a9fcb0 fix reply alerts and browser push subscriptions
Send every reply alert while batching email for five minutes. Keep shared browser subscriptions tied to the signed-in agent.
2026-09-16 00:16:12 +05:30
Abhinav Raut ced1a8bee5 add per-agent notification preferences and browser push 2026-09-15 12:31:27 +05:30
Abhinav Raut 2b3b9a4ce4 Merge pull request #602 from anvme/fix/csat-error-leak
fix: don't render raw driver errors on CSAT submit
2026-09-14 18:49:46 +05:30
Abhinav Raut 6487b6b242 remove over-explanatory CSAT comments 2026-09-14 18:47:46 +05:30
Stanislaw cdfe81155f fix: don't render raw driver errors on CSAT submit
handleUpdateCSATResponse rendered err.Error() directly, so submitting a form
to a malformed UUID leaked the raw Postgres error to the page. Show a generic
message and only surface known envelope.Error messages.
2026-09-14 15:02:59 +02:00
Stanislaw 852dbfe7e1 fix: truncate CSAT feedback by runes to preserve valid UTF-8
Feedback was sliced by bytes at maxCsatFeedbackLength, which could split a
multibyte character and produce invalid UTF-8. Postgres then rejects the row
and the entire submission fails, losing the rating too. Truncate by runes.
2026-09-14 15:02:59 +02:00
Abhinav Raut 93df6c8bf3 Merge pull request #492 from pat-s/agent/sso-only-auth
feat(auth): add SSO-only login mode
2026-09-09 01:32:18 +05:30
Abhinav Raut 32f814757f drop the rationale comment on isLocalLoginEnabled 2026-09-09 01:16:53 +05:30
Abhinav Raut bde1f06ec6 skip the OIDC lookup on login unless local login is disabled and translate the error 2026-09-09 01:14:42 +05:30
Abhinav Raut 34d2a64895 keep prompt content out of the agent prompt list and load it on edit behind ai:manage 2026-09-09 00:45:43 +05:30
Abhinav Raut 30b5d94627 add editor prompts admin page to create, edit and delete AI reply box prompts 2026-09-09 00:33:02 +05:30
Abhinav Raut 52b6658e74 reject duplicate emails when creating a contact and reuse shared i18n keys 2026-09-08 01:44:16 +05:30
Abhinav Raut e8007b67fd Merge remote-tracking branch 'origin/main' into pr-312
# Conflicts:
#	frontend/apps/main/src/components/sidebar/Sidebar.vue
#	frontend/apps/main/src/features/contact/ContactsList.vue
#	internal/user/contact.go
#	internal/user/user.go
2026-09-08 01:29:04 +05:30
Abhinav Raut 8109d1b1d6 filter conversation and message search by read permissions in sql 2026-09-03 00:51:13 +05:30
Abhinav Raut afeb120a5f apply the search limit after the read-permission filter 2026-09-03 00:10:44 +05:30
Abhinav Raut c47e8e0c5b let search callers pass a result limit and show the palette spinner while typing 2026-09-02 23:48:44 +05:30
Abhinav Raut 9c0d242549 rebuild the command palette and add keyboard shortcuts for conversation actions 2026-09-02 15:44:27 +05:30
Abhinav Raut b136346b95 fetch only the edited view's count after saving a view 2026-09-02 01:19:50 +05:30
Abhinav Raut 2ba716cb58 Merge remote-tracking branch 'origin/main' into pr/sidebar-counts
# Conflicts:
#	frontend/apps/main/src/stores/conversation.js
#	internal/conversation/conversation.go
2026-09-02 00:45:50 +05:30
Abhinav Raut 5e22ed3f56 keep the thumbnail name when its upload fails 2026-09-02 00:01:46 +05:30
Abhinav Raut 12bb634b0f Merge remote-tracking branch 'origin/main' into shrink-macro-payloads
# Conflicts:
#	frontend/apps/main/src/features/conversation/ReplyBox.vue
#	frontend/apps/main/src/stores/macro.js
#	frontend/apps/main/src/stores/macro.test.js
#	internal/image/image.go
2026-09-02 00:01:42 +05:30
Abhinav Raut 4aacd20261 keep the upload when the thumbnail fails 2026-09-01 23:07:36 +05:30
Abhinav Raut c934758ca8 cap sidebar view counts and move the count badge into a component 2026-09-01 21:18:48 +05:30
Abhinav Raut c1d613c942 Merge pull request #548 from malpou/fix/oidc-redirect-live-lookup
oidc: resolve redirect URL live so Root URL changes without a restart (preferred option)
2026-08-30 23:48:47 +05:30
Abhinav Raut 60cb85494c Merge pull request #544 from malpou/api/source-id
api: accept source_id on conversation and message endpoints
2026-08-30 23:47:26 +05:30
Abhinav Raut baeade99a6 oidc: always read the redirect URL from settings, drop the session copy 2026-08-30 23:26:34 +05:30
Abhinav Raut 9a64fe3303 move canCreateConversationMessage below the handlers 2026-08-30 22:52:48 +05:30
Abhinav Raut c0471ae230 gate message delete on messages:write_private & drop doc str 2026-08-30 22:50:45 +05:30
Marc Vila 08a12801d9 feat: add separate permission for private conversation notes 2026-08-30 10:22:09 +02:00
malpou 1811e89c5f oidc: reject a missing redirect URI from the session in the callback
The callback retrieved oidc_redirect_uri from the session and silently
fell back to an empty string when it was missing, unreadable, or not a
string, then passed that empty value to ExchangeOIDCToken, which would
send no redirect_uri and have the exchange rejected by the IdP. Treat
a missing or unreadable value as a stale session and route it through
the existing session-expired error path, the same way a state mismatch
is handled.
2026-08-29 12:06:57 +02:00
malpou 8eeea388d6 oidc: resolve redirect URI once per login and propagate errors
Address CodeRabbit review on the live-lookup change:

- Resolve the redirect URI live in LoginURL and return it so the caller
  persists it in the session; ExchangeOIDCToken reuses that stored value
  instead of resolving again. The token exchange redirect_uri must match
  the one in the auth request (RFC 6749 4.1.3); resolving twice would let
  a Root URL change between login and callback produce a mismatch the IdP
  rejects.
- Propagate the redirect URL resolution error out of LoginURL rather
  than discarding it, so a setting read failure fails the login loudly
  instead of sending an empty redirect_uri.
- Pass rootURL as a formatting argument in oidc.RedirectURL instead of
  concatenating it into the format string, so a root URL containing a
  %-sequence (e.g. %2F) is not interpreted as a verb.
2026-08-29 11:51:43 +02:00
malpou 02e9d1d3bf oidc: resolve redirect URL live so Root URL changes without a restart
Auth providers captured the redirect URL as a string at build time, so
changing app.root_url in General settings left OIDC providers sending
the old redirect_uri until the process restarted. The identity provider
then rejected login with "redirect_uri is missing in the client
configuration" even though the database and the IdP client both held the
right value.

Make auth.Provider.RedirectURL a closure and resolve it in LoginURL and
ExchangeOIDCToken from the current root URL, matching the media store's
existing rootURL closure. The redirect URL is computed by a new
oidc.Manager.RedirectURL(id) helper so the path format stays in one
place. Other provider fields (client ID, provider URL) remain snapshotted
and are refreshed by reloadAuth on OIDC changes, as before.

This removes the reload requirement for Root URL entirely; the settings
handler no longer needs to know that auth depends on it.
2026-08-29 11:32:28 +02:00
malpou 3b0d3d4415 api: accept source_id on conversation and message endpoints
Add an optional source_id to createConversationRequest and messageReq and
store it on the created contact message, mirroring the IMAP ingestion path
which is the only place source_id is otherwise populated.

BuildEmailThreadingHeaders builds every outgoing reply's References and
In-Reply-To from prior messages' source_id. A desk fed over the API, as
ours is, therefore references only its own previous sends, so the customer's
mail client has nothing of theirs to thread on and every reply arrives
looking standalone. Letting the API set source_id fixes this for any API-fed
inbox without a direct database write.

The value is normalized (whitespace and angle brackets stripped) since
source_id is stored unbracketed and the brackets are re-added when composing
the threading headers. An empty value leaves the column NULL as before, so
existing callers are unaffected.
2026-08-29 10:59:03 +02:00
Abhinav Raut 387071117d cut memory spikes from uploads, i18n and the hourly time trigger
Heap profiles on a large install showed three hot spots: image uploads
decoded the full bitmap twice, every i18n request rebuilt the language
pack, and the hourly time trigger loaded all conversations from the
last 30 days into one slice.
2026-08-28 17:06:08 +05:30
Abhinav Raut 18514cd021 search and paginate agents, teams, tags and macros instead of loading them all at boot 2026-08-28 01:43:59 +05:30
Amberger Moritz 1d88ef13b1 fix: address CodeRabbit review on sidebar counts PR
Restore upstream conversation create/transcript and mobile sidebar behavior that was accidentally overwritten during cherry-pick. Import onMounted in Sidebar.vue and bound view-count queries with a 10s timeout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 15:57:55 +02:00
Amberger Moritz d12c4446a6 feat: show open conversation counts in the inbox sidebar
Adds badges with the number of open conversations next to My inbox,
Mentions, Unassigned, All and each personal or shared view. "Open" means
a conversation whose status category is open, so snoozed and resolved
conversations are not counted.

Backend:
- GET /api/v1/conversations/sidebar-counts returns the counts, gated by
  the conversations:read permission. Each individual count is additionally
  gated server-side by the permission for that list, so an agent never
  receives a number for a list they cannot open.
- View counts are unioned into a single statement, so the number of views
  does not drive the number of queries.
- The list-type conditions shared by the conversation list and count
  queries are extracted into appendListTypeConditions, so both stay in
  sync on what each list type means.
- An empty team list now renders as IN (NULL) instead of the invalid
  IN (), which an agent holding a team permission without a team hit.
- The feature can be turned off via app.sidebar_counts_enabled, which
  defaults to enabled when the setting is missing.

Frontend:
- Counts refresh when switching inboxes, after the agent's own status or
  assignee changes, and from new_conversation and status-carrying
  conversation_update websocket events.
- Refreshes are throttled and share a short TTL, so bursts of incoming
  conversations collapse into a single request. Re-enabling the feature
  bypasses the TTL, because being disabled leaves a zeroed result cached.

Refs #466

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 16:58:30 +02:00
Abhinav Raut c0c21bc56a raise the response body pool limit to 1mb 2026-08-22 12:51:47 +05:30