[Customer Portal][BE] Refactor chat endpoints to conversations, update ID validation, and enhance conversation search - #224
Conversation
📝 WalkthroughWalkthroughRenames chat→conversation across models and APIs, standardizes many ID fields to Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client
participant API as Service (service.bal)
participant Entity as Entity Module (entity.bal)
participant DB as Database/Store
Client->>API: POST /projects/[id]/conversations/search (ConversationSearchPayload)
API->>Entity: searchConversations(idToken, payload)
Entity->>DB: query conversations (filters, pagination, sort)
DB-->>Entity: conversations + totalRecords
Entity-->>API: ConversationResponse
API->>API: mapConversationSearchResponse(entityResponse)
API-->>Client: 200 OK (types:ConversationResponse)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/customer-portal/backend/service.bal (1)
871-907:⚠️ Potential issue | 🟡 MinorMissing
http:Forbiddenincases/searchreturn type and error handlerThe return union at line 873 omits
http:Forbidden, and the error-handling block has nohttp:STATUS_FORBIDDENcheck. The underlyingsearchCasescall invokes an HTTP endpoint that can propagate a403from the entity layer. If this occurs, it silently falls through to thehttp:InternalServerErrorhandler — returning a misleading 500 to the caller. The siblingconversations/searchendpoint (line 996) correctly declares and handleshttp:Forbidden.🛡️ Proposed fix
- returns http:Ok|http:BadRequest|http:Unauthorized|http:InternalServerError { + returns http:Ok|http:BadRequest|http:Unauthorized|http:Forbidden|http:InternalServerError {if getStatusCode(casesResponse) == http:STATUS_UNAUTHORIZED { log:printWarn(string `User: ${userInfo.userId} is not authorized to access the customer portal!`); return <http:Unauthorized>{ body: { message: ERR_MSG_UNAUTHORIZED_ACCESS } }; } + + if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN { + log:printWarn(string `User: ${userInfo.userId} is forbidden to search cases for project: ${id}`); + return <http:Forbidden>{ + body: { + message: ERR_MSG_PROJECT_ACCESS_FORBIDDEN + } + }; + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 871 - 907, The resource function post projects/[entity:IdString id]/cases/search currently omits http:Forbidden from its return union and does not handle http:STATUS_FORBIDDEN from the searchCases call; update the function signature to include http:Forbidden and add a branch in the casesResponse is error block that checks if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN and returns <http:Forbidden> with an appropriate message (mirroring the pattern used for http:STATUS_UNAUTHORIZED), so that searchCases errors propagating a 403 are returned correctly instead of as an InternalServerError.
🧹 Nitpick comments (5)
apps/customer-portal/backend/modules/entity/types.bal (1)
447-455:ProjectConversationStatsResponseis a closed record withoutjson...;.Unlike most other response types in this file (e.g.,
ProjectCaseStatsResponse,ProjectDeploymentStatsResponse), this record doesn't includejson...;. If the upstream API ever returns additional fields, deserialization will fail. This might be intentional to enforce a strict contract, but it deviates from the pattern used elsewhere.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 - 455, The ProjectConversationStatsResponse record is defined as a closed record (no json...;) which will break deserialization if upstream returns extra fields; update the ProjectConversationStatsResponse record definition to be an open record by adding the json...; filler (i.e., include "json...;") so it matches the pattern used by other response types like ProjectCaseStatsResponse and ProjectDeploymentStatsResponse and safely accepts unexpected additional fields.apps/customer-portal/backend/modules/ai_chat_agent/types.bal (1)
100-102:isFirstMessageis a required field with no default — confirm this is intentional.Unlike other boolean fields in this module (e.g.,
isCompleteinSlotStatedefaults tofalse),isFirstMessagehas no default. Callers must always supply it explicitly. If it's expected to befalsemost of the time, aboolean isFirstMessage = false;default would reduce boilerplate.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal` around lines 100 - 102, The field isFirstMessage in the message type is currently required with no default, forcing callers to always provide it; change it to have a default value (e.g., boolean isFirstMessage = false) if the common case is false to reduce caller boilerplate, or explicitly document/validate its presence if it must remain required—update the declaration for isFirstMessage accordingly in the message type definition (and adjust any constructors/initializers that build these types to rely on the default where appropriate).apps/customer-portal/backend/modules/entity/constants.bal (1)
26-33: Potential confusion:RESOLVEDandCLOSEDboth have value3in different state domains.
CLOSED(case state, line 27) andRESOLVED(chat state, line 32) share the integer value3. While this compiles fine since they are distinct named constants, it can lead to subtle bugs if someone accidentally uses the wrong constant (e.g.,RESOLVEDwhereCLOSEDwas intended). Consider adding a comment clarifying the domain distinction, or use a naming convention that encodes the domain (e.g.,CHAT_RESOLVED,CASE_CLOSED).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/constants.bal` around lines 26 - 33, CLOSED and RESOLVED both use the integer 3 in different domains which can cause accidental misuse; update the constants to make their domains explicit (for example rename CLOSED -> CASE_CLOSED and RESOLVED -> CHAT_RESOLVED or at minimum add a clear comment above each group like "// Case state values" and "// Chat state values"), then update all references/usages to the renamed symbols (or rely on the comment if you choose not to rename) so callers use the domain-prefixed constants (e.g., CASE_CLOSED, CHAT_RESOLVED) to avoid ambiguity.apps/customer-portal/backend/modules/entity/enums.bal (1)
44-48:ChatSortFieldnaming is inconsistent with the chat→conversation rename.Throughout this PR, terminology is being migrated from "chat" to "conversation." This enum is still named
ChatSortFieldwithCHAT_CREATED_ON/CHAT_UPDATED_ONmembers. Consider renaming toConversationSortFieldwithCONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ONfor consistency.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/enums.bal` around lines 44 - 48, Rename the enum ChatSortField to ConversationSortField and update its members from CHAT_CREATED_ON/CHAT_UPDATED_ON to CONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ON while preserving their string values ("createdOn"/"updatedOn"); then update all references/usages/imports across the codebase (including any switch/case, type annotations, serializers, and tests) to use ConversationSortField and the new member names so the rename is consistent with the chat→conversation migration.apps/customer-portal/backend/service.bal (1)
1051-1055: Inconsistent path parameter nameId(capital I)Line 1055 uses
Idwhile every other endpoint in this file uses lowercaseid. The docstring at line 1052 perpetuates the inconsistency (# + Id - ID of the project). Since this function was touched in this PR, it's a good opportunity to align the naming.♻️ Proposed fix
- # + Id - ID of the project + # + id - ID of the project # + conversationId - ID of the conversation # + return - Chat history response or error - resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx) + resource function get projects/[string id]/conversations/[string conversationId](http:RequestContext ctx) returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError { ... - ai_chat_agent:ChatHistoryResponse|error chatHistoryResponse = - ai_chat_agent:getChatHistory(Id, conversationId); + ai_chat_agent:ChatHistoryResponse|error chatHistoryResponse = + ai_chat_agent:getChatHistory(id, conversationId);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 1051 - 1055, The route parameter name is inconsistent: the resource function is declared as get projects/[string Id]/conversations/[string conversationId] and the docstring uses `Id` (capital I) while the rest of the file uses lowercase `id`; rename the path parameter to use lowercase `id` everywhere to match conventions—update the resource signature to projects/[string id]/conversations/[string conversationId], update the docstring line that mentions `Id` to `id`, and search the function body for any references to `Id` (e.g., parameter variables or path extraction) and change them to `id` as well to keep identifiers consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/utils.bal`:
- Around line 28-29: The Message instances for user and assistant are created
with timestamp: "" which can break downstream consumers; when constructing
Message objects (Message user and Message assistant) replace the empty string
timestamp with a proper sentinel (e.g., current UTC timestamp) or a clearly
named constant indicating unused timestamp; update the creation site that sets
timestamp for the USER and ASSISTANT messages (using userMessage and
assistantMessage) to populate a real timestamp value or a documented sentinel.
In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 68-77: Rename the public function getConverstationStatsForProject
to getConversationStatsForProject and fix the doc comment ("converstaion" →
"conversation"); update the function signature and its doc block, then find and
update all internal and external callers to the new name (or add a short
compatibility wrapper named getConverstationStatsForProject that delegates to
getConversationStatsForProject if you must preserve the old API). Also ensure
any references in tests, imports, or API docs that mention
getConverstationStatsForProject are updated; the function interacts with
csEntityClient->/projects/[id]/conversations/stats.get(generateHeaders(idToken)),
so keep that call unchanged.
- Around line 336-340: The searchConversations function is calling the old
endpoint csEntityClient->/chats/search.post; update it to call
csEntityClient->/conversations/search.post so it matches the migrated entity API
and the other conversation methods (e.g., createConversation,
updateConversation, getConverstationStatsForProject); ensure you continue to
pass payload and generateHeaders(idToken) unchanged.
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 362-363: Fix the typo in the documentation comment above the
ChoiceListItem[] conversationStates field: change "converstaion" to
"conversation" (also apply the same correction where the same typo appears in
entity.bal) so the comment reads "List of available conversation states" and
matches the field name conversationStates.
- Around line 1091-1112: Update the stale doc comments in the Conversation
record: change references from "chat" to "conversation" in the type header and
field comments (e.g., the top-line comment for Conversation and the comments for
id, number, initialMessage, and createdBy). Edit the comment texts adjacent to
the Conversation declaration and its fields (including IdString id, string?
number, string? initialMessage, and string createdBy) so they consistently say
"conversation" instead of "chat".
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 763-770: The public record type ConversationResponse uses the
field name chats but should be conversations to match the entity layer
(entity:ConversationResponse) and the chat→conversation rename; update the type
definition in ConversationResponse to rename the chats field to conversations
and then update any usages (notably the mapper function
mapConversationSearchResponse in utils.bal) to populate and read conversations
instead of chats so names are consistent across the API and entity types.
- Around line 740-761: The doc comment for the createdBy field in the
Conversation record uses "User who created the chat" which is inconsistent;
update that comment to "User who created the conversation" (locate the public
type Conversation and edit the comment above the createdBy field) so terminology
matches the rest of the type.
In `@apps/customer-portal/backend/service.bal`:
- Line 994: The resource signature for the POST endpoint currently uses an
unconstrained path parameter "[string id]"—update the resource declaration
"resource function post projects/[string id]/conversations/search(...)" to use
the refactored type "[entity:IdString id]" so the endpoint matches other
project-scoped handlers and benefits from the built-in ID validation; ensure any
references to the path parameter inside the function keep the same name "id" and
compile against the entity:IdString type.
In `@apps/customer-portal/backend/utils.bal`:
- Around line 427-456: The doc comment and variable/field names still refer to
"Chat" and "chats": update the comment in mapConversationSearchResponse to say
"Conversation search response" and "Mapped conversation search response", rename
the local variable chats to conversations (and its comprehension target from
response.conversations if needed), and change the returned property key from
chats to conversations to match the renamed
types:ConversationResponse.conversations; ensure any references to
types:ConversationResponse.chats are updated to
types:ConversationResponse.conversations and adjust the select/return
accordingly.
---
Outside diff comments:
In `@apps/customer-portal/backend/service.bal`:
- Around line 871-907: The resource function post projects/[entity:IdString
id]/cases/search currently omits http:Forbidden from its return union and does
not handle http:STATUS_FORBIDDEN from the searchCases call; update the function
signature to include http:Forbidden and add a branch in the casesResponse is
error block that checks if getStatusCode(casesResponse) == http:STATUS_FORBIDDEN
and returns <http:Forbidden> with an appropriate message (mirroring the pattern
used for http:STATUS_UNAUTHORIZED), so that searchCases errors propagating a 403
are returned correctly instead of as an InternalServerError.
---
Nitpick comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal`:
- Around line 100-102: The field isFirstMessage in the message type is currently
required with no default, forcing callers to always provide it; change it to
have a default value (e.g., boolean isFirstMessage = false) if the common case
is false to reduce caller boilerplate, or explicitly document/validate its
presence if it must remain required—update the declaration for isFirstMessage
accordingly in the message type definition (and adjust any
constructors/initializers that build these types to rely on the default where
appropriate).
In `@apps/customer-portal/backend/modules/entity/constants.bal`:
- Around line 26-33: CLOSED and RESOLVED both use the integer 3 in different
domains which can cause accidental misuse; update the constants to make their
domains explicit (for example rename CLOSED -> CASE_CLOSED and RESOLVED ->
CHAT_RESOLVED or at minimum add a clear comment above each group like "// Case
state values" and "// Chat state values"), then update all references/usages to
the renamed symbols (or rely on the comment if you choose not to rename) so
callers use the domain-prefixed constants (e.g., CASE_CLOSED, CHAT_RESOLVED) to
avoid ambiguity.
In `@apps/customer-portal/backend/modules/entity/enums.bal`:
- Around line 44-48: Rename the enum ChatSortField to ConversationSortField and
update its members from CHAT_CREATED_ON/CHAT_UPDATED_ON to
CONVERSATION_CREATED_ON/CONVERSATION_UPDATED_ON while preserving their string
values ("createdOn"/"updatedOn"); then update all references/usages/imports
across the codebase (including any switch/case, type annotations, serializers,
and tests) to use ConversationSortField and the new member names so the rename
is consistent with the chat→conversation migration.
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: The ProjectConversationStatsResponse record is defined as
a closed record (no json...;) which will break deserialization if upstream
returns extra fields; update the ProjectConversationStatsResponse record
definition to be an open record by adding the json...; filler (i.e., include
"json...;") so it matches the pattern used by other response types like
ProjectCaseStatsResponse and ProjectDeploymentStatsResponse and safely accepts
unexpected additional fields.
In `@apps/customer-portal/backend/service.bal`:
- Around line 1051-1055: The route parameter name is inconsistent: the resource
function is declared as get projects/[string Id]/conversations/[string
conversationId] and the docstring uses `Id` (capital I) while the rest of the
file uses lowercase `id`; rename the path parameter to use lowercase `id`
everywhere to match conventions—update the resource signature to
projects/[string id]/conversations/[string conversationId], update the docstring
line that mentions `Id` to `id`, and search the function body for any references
to `Id` (e.g., parameter variables or path extraction) and change them to `id`
as well to keep identifiers consistent.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/customer-portal/backend/service.bal (1)
1050-1078:⚠️ Potential issue | 🟠 MajorChat history endpoint not updated to use
entity:IdStringand has naming inconsistencies.This endpoint has several issues relative to the rest of the PR:
- Path parameter
[string Id](line 1055) uses uppercase "I" — every other endpoint uses lowercaseid. This is also inconsistent with the PR-wide migration toentity:IdString.- Doc comment on line 1052 says
# + Idinstead of# + id.- Missing Unauthorized/Forbidden error handling — other project-scoped endpoints verify project access and return 401/403, but this one only returns
InternalServerError.Proposed fix for naming and ID type consistency
# Get chat history for a specific conversation. - # - # + Id - ID of the project + # + # + id - ID of the project # + conversationId - ID of the conversation # + return - Chat history response or error - resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx) + resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx) returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 1050 - 1078, Change the resource function signature and docs to use lowercase id of type entity:IdString (resource function get projects/[entity:IdString id]/conversations/[string conversationId]) and update the doc comment from "Id" to "id"; rename all uses of Id to id (including the ai_chat_agent:getChatHistory call). After extracting userInfo (authorization:UserInfoPayload|error userInfo = ctx.getWithType(authorization:HEADER_USER_INFO)), call the same project-access verification used by other project-scoped endpoints (the existing helper used elsewhere to return 401/403) and return http:Unauthorized or http:Forbidden as appropriate before calling ai_chat_agent:getChatHistory; keep the existing error logging (ERR_MSG_USER_INFO_HEADER_NOT_FOUND and log:printError) and preserve the InternalServerError path for getChatHistory failures.apps/customer-portal/backend/modules/entity/types.bal (1)
447-455:⚠️ Potential issue | 🟡 MinorStale "chat" in doc comment on line 449.
The type was renamed to
ProjectConversationStatsResponse, but line 449 still says "Active chat count". Should be "Active conversation count" (and similarly "Session count" and "Resolved count" are fine).Proposed fix
# Project conversation statistics response. public type ProjectConversationStatsResponse record {| - # Active chat count + # Active conversation count int activeCount;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 - 455, Update the stale doc comment for the ProjectConversationStatsResponse record: change the comment on the activeCount field that currently reads "Active chat count" to "Active conversation count" so it matches the renamed type; locate the ProjectConversationStatsResponse type and modify the comment above activeCount accordingly.
🧹 Nitpick comments (5)
apps/customer-portal/backend/modules/types/types.bal (2)
188-198: Stale "chats" terminology inProjectSupportStatsfields.The fields
activeChats,sessionChats, andresolvedChatsstill use "chats" terminology, which is inconsistent with the broader chat→conversation rename in this PR. If these field names are part of a public API contract, this is a breaking change concern either way — consider renaming them toactiveConversations,sessionConversations, andresolvedConversationsto stay consistent.Proposed fix
public type ProjectSupportStats record {| # Total cases count int totalCases?; - # Active chats count - int activeChats?; - # Session chats count - int sessionChats?; - # Resolved chats count - int resolvedChats?; + # Active conversations count + int activeConversations?; + # Session conversations count + int sessionConversations?; + # Resolved conversations count + int resolvedConversations?; |};Note: This would also require updating the corresponding return values in
service.bal(lines 681-689) where these fields are populated.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/types/types.bal` around lines 188 - 198, Rename the stale "chats" fields in the ProjectSupportStats record to use "Conversations" (change activeChats → activeConversations, sessionChats → sessionConversations, resolvedChats → resolvedConversations) and update every place that constructs or reads ProjectSupportStats (notably where the record is populated in service.bal) to use the new field names; ensure any serialization/exposed API mappings are updated to avoid mismatches and run tests to catch any remaining references to the old field names.
200-210: Same stale "chats" terminology inProjectStats.
ProjectStats.activeChats(line 205) should also be renamed for consistency with the chat→conversation migration.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/types/types.bal` around lines 200 - 210, ProjectStats still uses the old field name activeChats; rename that field to activeConversations in the ProjectStats record definition (replace activeChats? with activeConversations?) and update every usage site that references ProjectStats.activeChats — assignments, destructuring, JSON mapping, and tests — to use ProjectStats.activeConversations so the type and all consumers reflect the chat→conversation migration consistently.apps/customer-portal/backend/service.bal (3)
409-411:patch projects/[string projectId]/deployments/[string deploymentId]not migrated toentity:IdString.Other project and deployment endpoints (lines 267, 314, 353) use
entity:IdString, but this PATCH endpoint still usesstringfor both path parameters. This leaves an inconsistency where these IDs skip the hex validation that other endpoints enforce.Proposed fix
- resource function patch projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx, + resource function patch projects/[entity:IdString projectId]/deployments/[entity:IdString deploymentId](http:RequestContext ctx,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 409 - 411, The PATCH resource signature uses plain string path params which bypass hex validation; update the resource declaration resource function patch projects/[string projectId]/deployments/[string deploymentId](...) to use the validated type entity:IdString for both path params (e.g., projects/[entity:IdString projectId]/deployments/[entity:IdString deploymentId]) so it matches the other endpoints (see resource functions at lines with entity:IdString) and adjust any local parameter references if necessary to the same names; no other behavioral changes are required.
1391-1393:patch deployments/[string deploymentId]/products/[string productId]not migrated toentity:IdString.Same inconsistency — other deployment and product endpoints use
entity:IdStringbut this one still usesstringfor both path parameters.Proposed fix
- resource function patch deployments/[string deploymentId]/products/[string productId](http:RequestContext ctx, + resource function patch deployments/[entity:IdString deploymentId]/products/[entity:IdString productId](http:RequestContext ctx,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 1391 - 1393, The resource function signature for patch deployments/[string deploymentId]/products/[string productId] uses plain string path parameters; change both path parameter types to entity:IdString to match other endpoints by updating the resource function declaration (the symbol to edit is the resource function named "patch deployments/[string deploymentId]/products/[string productId]") so it reads deployments/[entity:IdString deploymentId]/products/[entity:IdString productId], and then update any uses of deploymentId or productId in the function body to the IdString type if necessary (e.g., any type assertions, validations, or function calls expecting entity:IdString).
2206-2208:patch cases/[string caseId]/call-requests/[string callRequestId]not migrated toentity:IdString.Same inconsistency as the other PATCH endpoints — the case ID and call request ID path parameters still use
string.Proposed fix
- resource function patch cases/[string caseId]/call\-requests/[string callRequestId](http:RequestContext ctx, + resource function patch cases/[entity:IdString caseId]/call\-requests/[entity:IdString callRequestId](http:RequestContext ctx,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 2206 - 2208, The PATCH resource signature patch cases/[string caseId]/call-requests/[string callRequestId] still uses plain string path params; update the route parameter types to entity:IdString (i.e., change [string caseId] and [string callRequestId] to [entity:IdString caseId] and [entity:IdString callRequestId] in the resource function declaration for patch cases/.../call-requests/...) and adjust any code inside the resource that assumes plain string (e.g., validations or conversions) to accept entity:IdString; ensure the resource continues to return entity:UpdatedCallRequest|http:BadRequest|http:Forbidden|http:NotFound|http:InternalServerError.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1069-1089: Update the doc comment for the searchQuery field inside
the ConversationSearchPayload type: change the phrase "Search query for chat
messages" to "Search query for conversation messages" (the field is filters ->
searchQuery on ConversationSearchPayload) so the comment matches the renamed
domain term; leave the rest of the record unchanged.
In `@apps/customer-portal/backend/service.bal`:
- Around line 673-678: The comments use stale "chat" terminology; update them to
accurately describe conversation/project statistics. Change the inline comment
before the call to entity:getConversationStatsForProject and the trailing
comment after the error handling around the conversationStats variable to refer
to "conversation" or "project conversation" stats (e.g., "Fetch project
conversation stats" and "To return other project stats even if conversation
stats retrieval fails, error will not be returned"), leaving the call to
entity:getConversationStatsForProject and the error logging via
ERR_MSG_CHATS_STATISTICS unchanged.
- Around line 518-524: Update stale "chat" wording to "conversation" in this
block and related symbols: change the inline comments around
entity:getConversationStatsForProject and the comment at the end of the error
branch to reference "conversation stats" instead of "chat stats", and rename the
constant ERR_MSG_CHATS_STATISTICS to ERR_MSG_CONVERSATIONS_STATISTICS (and
update all usages, e.g., the occurrences noted around lines 673, 677-678) so the
log call log:printError(ERR_MSG_CHATS_STATISTICS, conversationStats) uses the
new constant name; ensure all references and the constant definition are updated
for consistency.
---
Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: Update the stale doc comment for the
ProjectConversationStatsResponse record: change the comment on the activeCount
field that currently reads "Active chat count" to "Active conversation count" so
it matches the renamed type; locate the ProjectConversationStatsResponse type
and modify the comment above activeCount accordingly.
In `@apps/customer-portal/backend/service.bal`:
- Around line 1050-1078: Change the resource function signature and docs to use
lowercase id of type entity:IdString (resource function get
projects/[entity:IdString id]/conversations/[string conversationId]) and update
the doc comment from "Id" to "id"; rename all uses of Id to id (including the
ai_chat_agent:getChatHistory call). After extracting userInfo
(authorization:UserInfoPayload|error userInfo =
ctx.getWithType(authorization:HEADER_USER_INFO)), call the same project-access
verification used by other project-scoped endpoints (the existing helper used
elsewhere to return 401/403) and return http:Unauthorized or http:Forbidden as
appropriate before calling ai_chat_agent:getChatHistory; keep the existing error
logging (ERR_MSG_USER_INFO_HEADER_NOT_FOUND and log:printError) and preserve the
InternalServerError path for getChatHistory failures.
---
Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/entity.bal`:
- Around line 68-77: The function getConversationStatsForProject and its call to
csEntityClient->/projects/[id]/conversations/stats.get(generateHeaders(idToken))
are already correct and the documentation matches the behavior, so no code
changes are required—leave the function name, endpoint path, and return type
ProjectConversationStatsResponse|error as-is.
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1091-1112: The Conversation record's doc comments still refer to
"chat" rather than "conversation"; update the comments for the Conversation type
and its fields (e.g., the IdString id, string? number, string? initialMessage,
and string createdBy entries inside the Conversation record) to use
"conversation" (e.g., "ID of the conversation", "Conversation number", "Initial
message of the conversation", "User who created the conversation"); scan the
Conversation record for any other "chat" mentions and replace them to keep the
documentation consistent.
- Around line 362-363: The field name typo was corrected from
"converstaionStates" to "conversationStates" in the ChoiceListItem[]
declaration; update any references to the old symbol (e.g., code that accessed
converstaionStates, serializers, tests, and any JSON mapping) to use
conversationStates so compilation/serialization stays consistent and run tests
to verify no remaining references to the old name remain.
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 763-770: The ConversationResponse type has already been updated to
rename the field from chats to conversations; no code change is required—just
confirm that the new record type ConversationResponse contains Conversation[]
conversations and int totalRecords and that any references to the old chats
field are updated to use conversations (check usages of ConversationResponse and
any serializers/deserializers).
In `@apps/customer-portal/backend/service.bal`:
- Around line 989-1048: No changes needed: the resource function post
projects/[entity:IdString id]/conversations/search correctly injects the project
id into entity:searchConversations payload (projectIds: [id]) and handles error
cases (Unauthorized, Forbidden, InternalServerError) before returning
mapConversationSearchResponse(conversationResponse); leave these symbols and
logic as-is.
In `@apps/customer-portal/backend/utils.bal`:
- Around line 427-456: The loop variable name `chat` in
mapConversationSearchResponse (declared as `from entity:Conversation chat in
response.conversations`) is a minor readability issue; rename it to a clearer
identifier (e.g., `conversation` or `conv`) in the comprehension and update all
references inside the select block so the mapping logic remains identical but
more descriptive.
---
Nitpick comments:
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 188-198: Rename the stale "chats" fields in the
ProjectSupportStats record to use "Conversations" (change activeChats →
activeConversations, sessionChats → sessionConversations, resolvedChats →
resolvedConversations) and update every place that constructs or reads
ProjectSupportStats (notably where the record is populated in service.bal) to
use the new field names; ensure any serialization/exposed API mappings are
updated to avoid mismatches and run tests to catch any remaining references to
the old field names.
- Around line 200-210: ProjectStats still uses the old field name activeChats;
rename that field to activeConversations in the ProjectStats record definition
(replace activeChats? with activeConversations?) and update every usage site
that references ProjectStats.activeChats — assignments, destructuring, JSON
mapping, and tests — to use ProjectStats.activeConversations so the type and all
consumers reflect the chat→conversation migration consistently.
In `@apps/customer-portal/backend/service.bal`:
- Around line 409-411: The PATCH resource signature uses plain string path
params which bypass hex validation; update the resource declaration resource
function patch projects/[string projectId]/deployments/[string
deploymentId](...) to use the validated type entity:IdString for both path
params (e.g., projects/[entity:IdString projectId]/deployments/[entity:IdString
deploymentId]) so it matches the other endpoints (see resource functions at
lines with entity:IdString) and adjust any local parameter references if
necessary to the same names; no other behavioral changes are required.
- Around line 1391-1393: The resource function signature for patch
deployments/[string deploymentId]/products/[string productId] uses plain string
path parameters; change both path parameter types to entity:IdString to match
other endpoints by updating the resource function declaration (the symbol to
edit is the resource function named "patch deployments/[string
deploymentId]/products/[string productId]") so it reads
deployments/[entity:IdString deploymentId]/products/[entity:IdString productId],
and then update any uses of deploymentId or productId in the function body to
the IdString type if necessary (e.g., any type assertions, validations, or
function calls expecting entity:IdString).
- Around line 2206-2208: The PATCH resource signature patch cases/[string
caseId]/call-requests/[string callRequestId] still uses plain string path
params; update the route parameter types to entity:IdString (i.e., change
[string caseId] and [string callRequestId] to [entity:IdString caseId] and
[entity:IdString callRequestId] in the resource function declaration for patch
cases/.../call-requests/...) and adjust any code inside the resource that
assumes plain string (e.g., validations or conversions) to accept
entity:IdString; ensure the resource continues to return
entity:UpdatedCallRequest|http:BadRequest|http:Forbidden|http:NotFound|http:InternalServerError.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
apps/customer-portal/backend/modules/entity/types.bal (1)
447-455:⚠️ Potential issue | 🟡 MinorStale doc comment:
# Active chat countshould say# Active conversation count.🔧 Proposed fix
public type ProjectConversationStatsResponse record {| - # Active chat count + # Active conversation count int activeCount;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 - 455, The doc comment for the activeCount field in the ProjectConversationStatsResponse record is stale; change the comment from "# Active chat count" to "# Active conversation count" so the field documentation accurately describes activeCount in ProjectConversationStatsResponse.apps/customer-portal/backend/service.bal (1)
1114-1142:⚠️ Potential issue | 🟡 Minor
[string Id]and[string conversationId]are inconsistent with the PR-wide[entity:IdString id]refactor.This endpoint is the only conversation-scoped endpoint still using unconstrained
stringpath parameters. Additionally,Id(capital I) deviates from the lowercaseidconvention used everywhere else in the service.🔧 Proposed fix
- resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx) + resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx)Also update the doc comment parameter name to match:
- # + Id - ID of the project + # + id - ID of the project🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 1114 - 1142, The path params on the resource function get projects/[string Id]/conversations/[string conversationId] are inconsistent with the PR-wide refactor and casing: change both path parameters to use the constrained type and lowercase names (e.g., [entity:IdString id] and [entity:IdString conversationId]), update every use inside the function (replace Id and conversationId usages with the new lowercase id and conversationId variables), and update the doc comment parameter names to match the new lowercase identifiers.apps/customer-portal/backend/modules/types/types.bal (1)
188-210:⚠️ Potential issue | 🟡 Minor
activeChats/sessionChats/resolvedChatsin public stats types are inconsistent with the chat→conversation rename.
ProjectSupportStatsandProjectStatsstill expose fields namedactiveChats,sessionChats, andresolvedChats, but they are now populated fromentity:ProjectConversationStatsResponse(e.g.,conversationStats.activeCount). If this is intended as a deliberate backward-compat hold-out for the stats API surface, it should be documented; otherwise these should be renamed toactiveConversations,sessionConversations, andresolvedConversationsfor consistency.🔧 Proposed rename
public type ProjectSupportStats record {| int totalCases?; - int activeChats?; - int sessionChats?; - int resolvedChats?; + int activeConversations?; + int sessionConversations?; + int resolvedConversations?; |}; public type ProjectStats record {| int openCases?; - int activeChats?; + int activeConversations?; int deployments?; string slaStatus?; |};(Service layer references at lines 610, 748–753 of
service.balwould also need updating.)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/types/types.bal` around lines 188 - 210, The public record types ProjectSupportStats and ProjectStats expose fields named activeChats, sessionChats, and resolvedChats which are inconsistent with the internal rename from "chat" to "conversation"; rename those fields to activeConversations, sessionConversations, and resolvedConversations in the types (ProjectSupportStats and ProjectStats), update all code that populates them from entity:ProjectConversationStatsResponse (e.g., map conversationStats.activeCount → activeConversations, sessionCount → sessionConversations, resolvedCount → resolvedConversations), and update any service-layer references and serializers that read/write those fields; if this was intentionally kept for backward compatibility, instead add clear documentation and maintain aliasing mapping when serializing/deserializing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: The doc comment for the activeCount field in the
ProjectConversationStatsResponse record is stale; change the comment from "#
Active chat count" to "# Active conversation count" so the field documentation
accurately describes activeCount in ProjectConversationStatsResponse.
In `@apps/customer-portal/backend/modules/types/types.bal`:
- Around line 188-210: The public record types ProjectSupportStats and
ProjectStats expose fields named activeChats, sessionChats, and resolvedChats
which are inconsistent with the internal rename from "chat" to "conversation";
rename those fields to activeConversations, sessionConversations, and
resolvedConversations in the types (ProjectSupportStats and ProjectStats),
update all code that populates them from entity:ProjectConversationStatsResponse
(e.g., map conversationStats.activeCount → activeConversations, sessionCount →
sessionConversations, resolvedCount → resolvedConversations), and update any
service-layer references and serializers that read/write those fields; if this
was intentionally kept for backward compatibility, instead add clear
documentation and maintain aliasing mapping when serializing/deserializing.
In `@apps/customer-portal/backend/service.bal`:
- Around line 1114-1142: The path params on the resource function get
projects/[string Id]/conversations/[string conversationId] are inconsistent with
the PR-wide refactor and casing: change both path parameters to use the
constrained type and lowercase names (e.g., [entity:IdString id] and
[entity:IdString conversationId]), update every use inside the function (replace
Id and conversationId usages with the new lowercase id and conversationId
variables), and update the doc comment parameter names to match the new
lowercase identifiers.
---
Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1091-1112: Update the stale "chat" wording in the Conversation
type's field doc comments: replace "chat" with "conversation" for the IdString
id, string? number, string? initialMessage, and string createdBy fields in the
Conversation record so comments read e.g. "ID of the conversation",
"Conversation number", "Initial message of the conversation", and "User who
created the conversation"; edit the doc comment lines inside the public type
Conversation declaration to apply these exact wording changes.
b67bf89 to
9375b9c
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/customer-portal/backend/modules/entity/types.bal (1)
447-455:⚠️ Potential issue | 🟡 Minor
ProjectConversationStatsResponseis missingjson...;and has stale "chat" comment.Two issues:
- The doc comment on line 449 still says "Active chat count" — should be "Active conversation count".
- This is the only stats response type using a closed record without a
json...;rest field. BothProjectCaseStatsResponseandProjectDeploymentStatsResponseincludejson...;for forward compatibility. This should be consistent.Proposed fix
# Project conversation statistics response. public type ProjectConversationStatsResponse record {| - # Active chat count + # Active conversation count int activeCount; # Session count int sessionCount; # Resolved count int resolvedCount; + json...; |};🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/entity/types.bal` around lines 447 - 455, Update ProjectConversationStatsResponse: change the doc comment "Active chat count" to "Active conversation count" and make the record open for forward compatibility by adding the json...; rest field. Locate the declaration of the ProjectConversationStatsResponse type and replace the stale comment string and add the json...; rest field to match ProjectCaseStatsResponse and ProjectDeploymentStatsResponse.apps/customer-portal/backend/service.bal (1)
1114-1142:⚠️ Potential issue | 🟠 MajorChat history endpoint is inconsistent with the PR-wide
IdStringrefactor and naming conventions.Three issues with this endpoint:
- PascalCase
Id(line 1119): The path parameter is[string Id]while every other endpoint uses lowercase[... id].- Missing
entity:IdString: BothIdandconversationIdremain plainstring, skipping the validation that all other refactored endpoints now get.- Missing Unauthorized/Forbidden handling: Unlike the sibling conversation search endpoint (line 1058), this endpoint only handles
InternalServerError.Proposed fix
- resource function get projects/[string Id]/conversations/[string conversationId](http:RequestContext ctx) - returns ai_chat_agent:ChatHistoryResponse|http:InternalServerError { + resource function get projects/[entity:IdString id]/conversations/[entity:IdString conversationId](http:RequestContext ctx) + returns ai_chat_agent:ChatHistoryResponse|http:Unauthorized|http:Forbidden|http:InternalServerError {Also update the internal call on line 1131:
- ai_chat_agent:getChatHistory(Id, conversationId); + ai_chat_agent:getChatHistory(id, conversationId);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 1114 - 1142, Update the resource signature and error handling to match the PR-wide IdString refactor and sibling endpoints: change the route param `[string Id]` to lowercase `[string id]`, change both parameters' types from plain string to the validated type `entity:IdString` (i.e., resource function get projects/[string id]/conversations/[entity:IdString conversationId] or both as entity:IdString as per project convention), ensure you still obtain userInfo via ctx.getWithType(authorization:HEADER_USER_INFO) and add the same Unauthorized/Forbidden checks and responses used in the sibling conversation search endpoint, and update the internal call to ai_chat_agent:getChatHistory(...) to pass the renamed/typed variables (id and conversationId) accordingly while keeping existing InternalServerError handling for backend failures.
🧹 Nitpick comments (2)
apps/customer-portal/backend/service.bal (1)
409-411: Deployment update endpoint still uses[string projectId]and[string deploymentId].This
PATCH projects/{projectId}/deployments/{deploymentId}endpoint was not migrated toentity:IdString, while the siblingGET(line 314) andPOST(line 353) endpoints for the same resource were. This creates an inconsistency where some deployment routes validate IDs and others don't.Proposed fix
- resource function patch projects/[string projectId]/deployments/[string deploymentId](http:RequestContext ctx, + resource function patch projects/[entity:IdString projectId]/deployments/[entity:IdString deploymentId](http:RequestContext ctx,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/service.bal` around lines 409 - 411, The PATCH resource function declaration "resource function patch projects/[string projectId]/deployments/[string deploymentId]" should be changed to use the validated ID type used elsewhere: replace both "[string projectId]" and "[string deploymentId]" with "[entity:IdString projectId]" and "[entity:IdString deploymentId]" respectively so the signature matches the GET and POST endpoints; update any references inside the function body that assume plain strings (e.g., uses of projectId or deploymentId) if necessary to work with entity:IdString. Ensure the resource function name and return types (resource function patch ... returns ...) remain unchanged other than the parameter type adjustments.apps/customer-portal/backend/modules/ai_chat_agent/types.bal (1)
29-32: Minor: trailing semicolon after enum closing brace.The
Roleenum ends with};(line 32) while all enums inenums.balend with just}. This is syntactically valid but inconsistent within the PR.Proposed fix
public enum Role { USER = "user", ASSISTANT = "assistant" -}; +}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal` around lines 29 - 32, Trailing semicolon after the Role enum creates an inconsistency with other enums; open the enum declaration for Role in types.bal (the public enum Role { USER = "user", ASSISTANT = "assistant" }) and remove the trailing semicolon after the closing brace so it ends with just } to match the rest of enums in enums.bal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/customer-portal/backend/modules/entity/constants.bal`:
- Around line 30-32: The constants ACTIVE and RESOLVED in constants.bal
currently reuse numeric IDs that overlap case states (ACTIVE = 2, RESOLVED = 3)
and are unused; add or update conversation state validation and filtering so
conversation updates use type-based validation rather than relying on unique
numeric values. Specifically, implement a validateConversationUpdatePayload (or
extend existing validateCaseUpdatePayload) to check incoming updates against
conversationStates (not caseStates) and ensure any state comparisons in the
codebase reference the conversation type before interpreting numeric IDs; keep
ACTIVE and RESOLVED if they map to backend conversation IDs but ensure all state
checks use the conversationStates enum/lookup to avoid conflating cases and
conversations.
In `@apps/customer-portal/backend/modules/entity/enums.bal`:
- Around line 46-49: Rename the enum members in ConversationSortField from
CHAT_CREATED_ON and CHAT_UPDATED_ON to CREATED_ON and UPDATED_ON (keeping their
string values "createdOn" and "updatedOn") so the naming matches CaseSortField;
update any references/usages of ConversationSortField.CHAT_CREATED_ON and
ConversationSortField.CHAT_UPDATED_ON to ConversationSortField.CREATED_ON and
ConversationSortField.UPDATED_ON respectively to avoid breakages.
In `@apps/customer-portal/backend/service.bal`:
- Around line 746-754: Rename the response fields returned where
ProjectConversationStatsResponse is used: change activeChats →
activeConversations, sessionChats → sessionConversations, and resolvedChats →
resolvedConversations in the returned object; then update the
ProjectSupportStats type definition to use those same field names and update any
entity/type comments that currently read "Active chat count"/similar to "Active
conversation count" to keep naming consistent with
ProjectConversationStatsResponse. Locate the return object (the block that
references ProjectConversationStatsResponse) and the ProjectSupportStats type
and edit both field names and their comments accordingly so callers and types
align.
---
Outside diff comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 447-455: Update ProjectConversationStatsResponse: change the doc
comment "Active chat count" to "Active conversation count" and make the record
open for forward compatibility by adding the json...; rest field. Locate the
declaration of the ProjectConversationStatsResponse type and replace the stale
comment string and add the json...; rest field to match ProjectCaseStatsResponse
and ProjectDeploymentStatsResponse.
In `@apps/customer-portal/backend/service.bal`:
- Around line 1114-1142: Update the resource signature and error handling to
match the PR-wide IdString refactor and sibling endpoints: change the route
param `[string Id]` to lowercase `[string id]`, change both parameters' types
from plain string to the validated type `entity:IdString` (i.e., resource
function get projects/[string id]/conversations/[entity:IdString conversationId]
or both as entity:IdString as per project convention), ensure you still obtain
userInfo via ctx.getWithType(authorization:HEADER_USER_INFO) and add the same
Unauthorized/Forbidden checks and responses used in the sibling conversation
search endpoint, and update the internal call to
ai_chat_agent:getChatHistory(...) to pass the renamed/typed variables (id and
conversationId) accordingly while keeping existing InternalServerError handling
for backend failures.
---
Duplicate comments:
In `@apps/customer-portal/backend/modules/entity/types.bal`:
- Around line 1152-1173: Update the doc comments inside the Conversation record
type to replace stale "chat" wording with "conversation": edit the comment lines
for fields id, number, initialMessage and createdBy (the comments currently
saying "ID of the chat", "Chat number", "Initial message of the chat", and "User
who created the chat") to use "conversation" instead so the Conversation type's
field comments are consistent with the rename.
---
Nitpick comments:
In `@apps/customer-portal/backend/modules/ai_chat_agent/types.bal`:
- Around line 29-32: Trailing semicolon after the Role enum creates an
inconsistency with other enums; open the enum declaration for Role in types.bal
(the public enum Role { USER = "user", ASSISTANT = "assistant" }) and remove the
trailing semicolon after the closing brace so it ends with just } to match the
rest of enums in enums.bal.
In `@apps/customer-portal/backend/service.bal`:
- Around line 409-411: The PATCH resource function declaration "resource
function patch projects/[string projectId]/deployments/[string deploymentId]"
should be changed to use the validated ID type used elsewhere: replace both
"[string projectId]" and "[string deploymentId]" with "[entity:IdString
projectId]" and "[entity:IdString deploymentId]" respectively so the signature
matches the GET and POST endpoints; update any references inside the function
body that assume plain strings (e.g., uses of projectId or deploymentId) if
necessary to work with entity:IdString. Ensure the resource function name and
return types (resource function patch ... returns ...) remain unchanged other
than the parameter type adjustments.
444e9b1
into
wso2-open-operations:customer-portal-milestone-1
Description
This PR includes the following updates:
IdString idinstead ofstring idChanges
1️⃣ Rename Chat to Conversation
Reason:
Using "conversation" better reflects the domain model and improves API clarity.
2️⃣ Use
IdStringfor Validationstring idvalidation withIdString idvalidationReason:
Using IdString ensures proper user validation and aligns with authentication best practices.
3️⃣ Add Conversation Search Method
Reason:
Enables structured and scalable case retrieval instead of relying on simple listing logic.
4️⃣ Remove Conversations POST (Temporary)
5️⃣ Add endpoint to POST attachments to a deployment
Testing
IdStringvalidation logicImpact
⚠ Chat endpoints renamed (potential breaking change)
⚠ Conversation POST endpoint temporarily removed
Related PRs
Summary by CodeRabbit
New Features
Refactor