@cossistant/core 0.0.30 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai-sdk-utils.d.ts.map +1 -1
- package/client.d.ts +4 -1
- package/client.d.ts.map +1 -1
- package/client.js +10 -0
- package/client.js.map +1 -1
- package/package.json +1 -1
- package/rest-client.d.ts +4 -1
- package/rest-client.d.ts.map +1 -1
- package/rest-client.js +27 -1
- package/rest-client.js.map +1 -1
- package/store/conversations-store.d.ts.map +1 -1
- package/store/conversations-store.js +2 -1
- package/store/conversations-store.js.map +1 -1
- package/store/seen-store.d.ts.map +1 -1
- package/store/seen-store.js +5 -1
- package/store/seen-store.js.map +1 -1
- package/types/src/api/conversation.d.ts +26 -9
- package/types/src/api/conversation.d.ts.map +1 -1
- package/types/src/api/timeline-item.d.ts +4 -4
- package/types/src/realtime-events.d.ts +10 -6
- package/types/src/realtime-events.d.ts.map +1 -1
- package/types/src/schemas.d.ts +4 -2
- package/types/src/schemas.d.ts.map +1 -1
package/ai-sdk-utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-sdk-utils.d.ts","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":[],"mappings":";;;;;;;AA+GG,KAzFS,aAAA,GAyFT;EACA,IAAA,EAAA,MAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,CAAA,EAAA,WAAA,GAAA,MAAA;CAAa;AAEX,KAxFO,kBAAA,
|
|
1
|
+
{"version":3,"file":"ai-sdk-utils.d.ts","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":[],"mappings":";;;;;;;AA+GG,KAzFS,aAAA,GAyFT;EACA,IAAA,EAAA,MAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,CAAA,EAAA,WAAA,GAAA,MAAA;CAAa;AAEX,KAxFO,kBAAA,GAwFO;EA2FP,IAAA,EAAA,WAAA;EAaI,IAAA,EAAA,MAAA;EAsBA,KAAA,CAAA,EAAA,WAAY,GAAA,MAAQ;EAyHxB,gBAAA,CAAA,EA3UQ,MA2UY,CAAA,MAAA,EAAA,OAAA,CAAA;AAgBhC,CAAA;AACU,KAzVE,aAAA,GAyVF;EACA,IAAA,EAAA,QAAA,MAAA,EAAA;EACP,UAAA,EAAA,MAAA;EAAY,QAAA,EAAA,MAAA;EA0BC,KAAA,EAjXR,MAiXQ,CAAA,MAAc,EAAA,OAAA,CAAA;EACnB,MAAA,CAAA,EAAA,OAAA;EACD,KAAA,EAAA,SAAA,GAAA,QAAA,GAAA,OAAA;EACP,SAAA,CAAA,EAAA,MAAA;EAAY,gBAAA,CAAA,EAhXK,MAgXL,CAAA,MAAA,EAAA,OAAA,CAAA;AAkHf,CAAA;AAUgB,KAzeJ,kBAAA,GAyekB;EACtB,IAAA,EAAA,YAAA;EACJ,QAAA,EAAA,MAAA;EAAqB,GAAA,EAAA,MAAA;EAAuB,KAAA,CAAA,EAAA,MAAA;EAUhC,gBAAA,CAAA,EAhfI,MAgfY,CAAA,MAAQ,EAAA,OAAA,CAAA;AAUxC,CAAA;KAvfY,uBAAA;;;;;;qBAMQ;;KAGR,kBAAA;;;KAIA,aAAA;;;;;;;;;KAcA,yBAAA;;;;;;;;;;;;;;;KAgBA,sBAAA;;;;;KAUA,SAAA,GACT,gBACA,qBACA,gBACA,qBACA,0BACA,qBACA;KAEE,cAAA,GAAiB;;;;;;KA2FV,mBAAA;;;YAGD;SACH;;;;;;;;iBASQ,WAAA,OAAkB,eAAe;;;;iBAsBjC,YAAA,QAAoB,iBAAiB;;;;KAyHzC,oBAAA;;;;;;;;;;;;;;;iBAgBI,aAAA,UACN,8BACA,uBACP;;;;iBA0Ba,cAAA,WACL,gCACD,uBACP;;;;iBAkHa,qBAAA,OAA4B;;;;iBAU5B,cAAA,QACR,eACJ,qBAAqB;;;;iBAUT,gBAAA,QAAwB,cAAc;;;;iBAUtC,kBAAA,QAA0B"}
|
package/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./types/src/api/conversation.js";
|
|
1
|
+
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody, SubmitConversationRatingRequestBody, SubmitConversationRatingResponseBody } from "./types/src/api/conversation.js";
|
|
2
2
|
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse, TimelineItem as TimelineItem$1 } from "./types/src/api/timeline-item.js";
|
|
3
3
|
import { Conversation } from "./types/src/schemas.js";
|
|
4
4
|
import { types_d_exports } from "./types.js";
|
|
@@ -77,6 +77,9 @@ declare class CossistantClient {
|
|
|
77
77
|
visitorPreview?: string | null;
|
|
78
78
|
visitorId?: string;
|
|
79
79
|
}): Promise<SetConversationTypingResponseBody>;
|
|
80
|
+
submitConversationRating(params: {
|
|
81
|
+
conversationId: string;
|
|
82
|
+
} & SubmitConversationRatingRequestBody): Promise<SubmitConversationRatingResponseBody>;
|
|
80
83
|
getConversationTimelineItems(params: GetConversationTimelineItemsRequest & {
|
|
81
84
|
conversationId: string;
|
|
82
85
|
}): Promise<GetConversationTimelineItemsResponse>;
|
package/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":"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"}
|
package/client.js
CHANGED
|
@@ -133,6 +133,16 @@ var CossistantClient = class {
|
|
|
133
133
|
async setVisitorTyping(params) {
|
|
134
134
|
return this.restClient.setConversationTyping(params);
|
|
135
135
|
}
|
|
136
|
+
async submitConversationRating(params) {
|
|
137
|
+
const response = await this.restClient.submitConversationRating(params);
|
|
138
|
+
const existing = this.conversationsStore.getState().byId[response.conversationId];
|
|
139
|
+
if (existing) this.conversationsStore.ingestConversation({
|
|
140
|
+
...existing,
|
|
141
|
+
visitorRating: response.rating,
|
|
142
|
+
visitorRatingAt: response.ratedAt
|
|
143
|
+
});
|
|
144
|
+
return response;
|
|
145
|
+
}
|
|
136
146
|
async getConversationTimelineItems(params) {
|
|
137
147
|
const response = await this.restClient.getConversationTimelineItems(params);
|
|
138
148
|
this.timelineItemsStore.ingestPage(params.conversationId, {
|
package/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["current: WebsiteState","conversation: Conversation","optimisticTimelineItem: TimelineItem","payload: SendTimelineItemRequest","createdAt"],"sources":["../src/client.ts"],"sourcesContent":["import {\n\ttype AnyRealtimeEvent,\n\ttype DefaultMessage,\n\tgetEventPayload,\n\ttype IdentifyContactResponse,\n\ttype RealtimeEvent,\n} from \"@cossistant/types\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n\tTimelineItem,\n} from \"@cossistant/types/api/timeline-item\";\nimport {\n\tConversationStatus,\n\tConversationTimelineType,\n\tSenderType,\n\tTimelineItemVisibility,\n} from \"@cossistant/types/enums\";\nimport type { Conversation } from \"@cossistant/types/schemas\";\nimport { CossistantRestClient } from \"./rest-client\";\nimport {\n\ttype ConversationsStore,\n\tcreateConversationsStore,\n} from \"./store/conversations-store\";\nimport {\n\tcreateTimelineItemsStore,\n\ttype TimelineItemsStore,\n} from \"./store/timeline-items-store\";\nimport {\n\tcreateWebsiteStore,\n\ttype WebsiteState,\n\ttype WebsiteStore,\n} from \"./store/website-store\";\nimport type {\n\tCossistantConfig,\n\tPublicWebsiteResponse,\n\tVisitorMetadata,\n\tVisitorResponse,\n} from \"./types\";\nimport { generateConversationId, generateMessageId } from \"./utils\";\n\ntype PendingConversation = {\n\tconversation: Conversation;\n\tinitialTimelineItems: TimelineItem[];\n};\n\ntype InitiateConversationParams = {\n\tconversationId?: string;\n\tvisitorId?: string | null;\n\twebsiteId?: string | null;\n\ttitle?: string;\n\tstatus?: Conversation[\"status\"];\n\tdefaultTimelineItems?: Array<DefaultMessage | TimelineItem>;\n};\n\ntype InitiateConversationResult = {\n\tconversationId: string;\n\tconversation: Conversation;\n\tdefaultTimelineItems: TimelineItem[];\n};\n\nexport class CossistantClient {\n\tprivate restClient: CossistantRestClient;\n\tprivate config: CossistantConfig;\n\tprivate pendingConversations = new Map<string, PendingConversation>();\n\tprivate websiteRequest: Promise<PublicWebsiteResponse> | null = null;\n\treadonly conversationsStore: ConversationsStore;\n\treadonly timelineItemsStore: TimelineItemsStore;\n\treadonly websiteStore: WebsiteStore;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\t\tthis.restClient = new CossistantRestClient(config);\n\t\tthis.conversationsStore = createConversationsStore();\n\t\tthis.timelineItemsStore = createTimelineItemsStore();\n\t\tthis.websiteStore = createWebsiteStore();\n\t}\n\n\t// Configuration updates\n\tupdateConfiguration(config: Partial<CossistantConfig>): void {\n\t\tthis.config = { ...this.config, ...config };\n\t\tthis.restClient.updateConfiguration(config);\n\t}\n\n\t// Utility methods\n\tgetConfiguration(): CossistantConfig {\n\t\treturn { ...this.config };\n\t}\n\n\t// Website information\n\tasync fetchWebsite(\n\t\tparams: { force?: boolean } = {}\n\t): Promise<PublicWebsiteResponse> {\n\t\tconst { force = false } = params;\n\t\tconst current: WebsiteState = this.websiteStore.getState();\n\n\t\tif (!force) {\n\t\t\tif (current.status === \"success\" && current.website) {\n\t\t\t\treturn current.website;\n\t\t\t}\n\t\t\tif (this.websiteRequest) {\n\t\t\t\treturn this.websiteRequest;\n\t\t\t}\n\t\t}\n\n\t\tthis.websiteStore.setLoading();\n\n\t\tconst request = this.restClient\n\t\t\t.getWebsite()\n\t\t\t.then((website) => {\n\t\t\t\tthis.websiteStore.setWebsite(website);\n\t\t\t\treturn website;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.websiteStore.setError(error);\n\t\t\t\tthrow error;\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (this.websiteRequest === request) {\n\t\t\t\t\tthis.websiteRequest = null;\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.websiteRequest = request;\n\n\t\treturn request;\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\treturn this.fetchWebsite({ force: true });\n\t}\n\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.restClient.setWebsiteContext(websiteId, visitorId);\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.restClient.setVisitorBlocked(isBlocked);\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\treturn this.restClient.updateVisitorMetadata(metadata);\n\t}\n\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\treturn this.restClient.identify(params);\n\t}\n\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\treturn this.restClient.updateContactMetadata(metadata);\n\t}\n\n\t// Conversation management\n\tinitiateConversation(\n\t\tparams: InitiateConversationParams = {}\n\t): InitiateConversationResult {\n\t\tconst conversationId = params.conversationId ?? generateConversationId();\n\t\tconst now = typeof window !== \"undefined\" ? new Date().toISOString() : \"\";\n\t\tconst timelineItems = (params.defaultTimelineItems ?? []).map((item) =>\n\t\t\tnormalizeBootstrapTimelineItem(conversationId, item)\n\t\t);\n\t\tconst existing = this.conversationsStore.getState().byId[conversationId];\n\t\tconst baseVisitorId =\n\t\t\tparams.visitorId ?? this.restClient.getCurrentVisitorId() ?? \"\";\n\t\tconst baseWebsiteId =\n\t\t\tparams.websiteId ?? this.restClient.getCurrentWebsiteId() ?? \"\";\n\n\t\tconst conversation: Conversation = existing\n\t\t\t? {\n\t\t\t\t\t...existing,\n\t\t\t\t\ttitle: params.title ?? existing.title,\n\t\t\t\t\tstatus: params.status ?? existing.status,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tlastTimelineItem: timelineItems.at(-1) ?? existing.lastTimelineItem,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tid: conversationId,\n\t\t\t\t\ttitle: params.title,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tvisitorId: baseVisitorId,\n\t\t\t\t\twebsiteId: baseWebsiteId,\n\t\t\t\t\tstatus: params.status ?? ConversationStatus.OPEN,\n\t\t\t\t\tdeletedAt: null,\n\t\t\t\t\tlastTimelineItem: timelineItems.at(-1),\n\t\t\t\t};\n\n\t\tthis.conversationsStore.ingestConversation(conversation);\n\n\t\tif (timelineItems.length > 0) {\n\t\t\tthis.timelineItemsStore.ingestPage(conversationId, {\n\t\t\t\titems: timelineItems,\n\t\t\t\thasNextPage: false,\n\t\t\t\tnextCursor: undefined,\n\t\t\t});\n\t\t}\n\n\t\tif (!existing || this.pendingConversations.has(conversationId)) {\n\t\t\tthis.pendingConversations.set(conversationId, {\n\t\t\t\tconversation,\n\t\t\t\tinitialTimelineItems: timelineItems,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tconversationId,\n\t\t\tconversation,\n\t\t\tdefaultTimelineItems: timelineItems,\n\t\t};\n\t}\n\n\tasync createConversation(\n\t\tparams?: Partial<CreateConversationRequestBody>\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst response = await this.restClient.createConversation(params);\n\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\treturn response;\n\t}\n\n\tasync listConversations(\n\t\tparams?: Partial<ListConversationsRequest>\n\t): Promise<ListConversationsResponse> {\n\t\tconst response = await this.restClient.listConversations(params);\n\t\tthis.conversationsStore.ingestList(response);\n\t\treturn response;\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\tconst response = await this.restClient.getConversation(params);\n\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\treturn response;\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\treturn this.restClient.markConversationSeen(params);\n\t}\n\n\tasync getConversationSeenData(params: { conversationId: string }) {\n\t\treturn this.restClient.getConversationSeenData(params);\n\t}\n\n\tasync setVisitorTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\treturn this.restClient.setConversationTyping(params);\n\t}\n\n\t// Timeline items management\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\tconst response = await this.restClient.getConversationTimelineItems(params);\n\t\tthis.timelineItemsStore.ingestPage(params.conversationId, {\n\t\t\titems: response.items,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t\tnextCursor: response.nextCursor ?? undefined,\n\t\t});\n\t\treturn response;\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest & { createIfPending?: boolean }\n\t): Promise<\n\t\tSendTimelineItemResponse & {\n\t\t\tconversation?: Conversation;\n\t\t\tinitialTimelineItems?: TimelineItem[];\n\t\t\twasConversationCreated?: boolean;\n\t\t}\n\t> {\n\t\tconst { createIfPending, ...rest } = params;\n\t\tconst optimisticId = rest.item.id ?? generateMessageId();\n\t\tconst createdAt = rest.item.createdAt\n\t\t\t? rest.item.createdAt\n\t\t\t: typeof window !== \"undefined\"\n\t\t\t\t? new Date().toISOString()\n\t\t\t\t: \"\";\n\n\t\t// Add optimistic timeline item\n\t\tconst optimisticTimelineItem: TimelineItem = {\n\t\t\tid: optimisticId,\n\t\t\tconversationId: rest.conversationId,\n\t\t\torganizationId: \"\", // Not available yet\n\t\t\tvisibility: rest.item.visibility ?? TimelineItemVisibility.PUBLIC,\n\t\t\ttype: rest.item.type ?? ConversationTimelineType.MESSAGE,\n\t\t\ttext: rest.item.text,\n\t\t\ttool: rest.item.tool ?? null,\n\t\t\tparts:\n\t\t\t\trest.item.parts && rest.item.parts.length > 0\n\t\t\t\t\t? rest.item.parts\n\t\t\t\t\t: rest.item.text\n\t\t\t\t\t\t? [{ type: \"text\" as const, text: rest.item.text }]\n\t\t\t\t\t\t: [],\n\t\t\tuserId: rest.item.userId ?? null,\n\t\t\tvisitorId: rest.item.visitorId ?? null,\n\t\t\taiAgentId: rest.item.aiAgentId ?? null,\n\t\t\tcreatedAt,\n\t\t\tdeletedAt: null,\n\t\t};\n\n\t\tthis.timelineItemsStore.ingestTimelineItem(optimisticTimelineItem);\n\n\t\tconst pending = this.pendingConversations.get(rest.conversationId);\n\n\t\tif (pending && createIfPending !== false) {\n\t\t\ttry {\n\t\t\t\tconst response = await this.restClient.createConversation({\n\t\t\t\t\tconversationId: rest.conversationId,\n\t\t\t\t\tdefaultTimelineItems: [\n\t\t\t\t\t\t...pending.initialTimelineItems,\n\t\t\t\t\t\toptimisticTimelineItem,\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\t\trest.conversationId,\n\t\t\t\t\toptimisticId\n\t\t\t\t);\n\t\t\t\tthis.timelineItemsStore.clearConversation(rest.conversationId);\n\n\t\t\t\tthis.timelineItemsStore.ingestPage(rest.conversationId, {\n\t\t\t\t\titems: response.initialTimelineItems,\n\t\t\t\t\thasNextPage: false,\n\t\t\t\t\tnextCursor: undefined,\n\t\t\t\t});\n\n\t\t\t\tthis.pendingConversations.delete(rest.conversationId);\n\n\t\t\t\tconst item =\n\t\t\t\t\tresponse.initialTimelineItems.at(-1) ??\n\t\t\t\t\tresponse.initialTimelineItems[0];\n\n\t\t\t\treturn {\n\t\t\t\t\titem: item as TimelineItem,\n\t\t\t\t\tconversation: response.conversation,\n\t\t\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t\t\t\twasConversationCreated: true,\n\t\t\t\t} satisfies SendTimelineItemResponse & {\n\t\t\t\t\tconversation: Conversation;\n\t\t\t\t\tinitialTimelineItems: TimelineItem[];\n\t\t\t\t\twasConversationCreated: true;\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\t\trest.conversationId,\n\t\t\t\t\toptimisticId\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst { createdAt: _createdAt, ...restItem } = rest.item;\n\n\t\tconst payload: SendTimelineItemRequest = {\n\t\t\t...rest,\n\t\t\titem: {\n\t\t\t\t...restItem,\n\t\t\t\tid: optimisticId,\n\t\t\t},\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this.restClient.sendMessage(payload);\n\n\t\t\t// Finalize the timeline item\n\t\t\tthis.timelineItemsStore.finalizeTimelineItem(\n\t\t\t\trest.conversationId,\n\t\t\t\toptimisticId,\n\t\t\t\tresponse.item\n\t\t\t);\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\trest.conversationId,\n\t\t\t\toptimisticId\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\thandleRealtimeEvent(event: AnyRealtimeEvent): void {\n\t\tif (event.type === \"conversationCreated\") {\n\t\t\tconst { conversation, header } = event.payload;\n\n\t\t\tthis.conversationsStore.ingestConversation({\n\t\t\t\t...conversation,\n\t\t\t\tlastTimelineItem: conversation.lastTimelineItem ?? undefined,\n\t\t\t});\n\t\t} else if (event.type === \"timelineItemCreated\") {\n\t\t\t// Ingest timeline item into store\n\t\t\tconst timelineItem =\n\t\t\t\tthis.timelineItemsStore.ingestRealtimeTimelineItem(event);\n\n\t\t\t// Update conversation with last timeline item\n\t\t\tconst existingConversation =\n\t\t\t\tthis.conversationsStore.getState().byId[timelineItem.conversationId];\n\n\t\t\tif (existingConversation) {\n\t\t\t\t// Check if this is a status-changing event timeline item\n\t\t\t\tconst newStatus = this.extractStatusFromEventTimelineItem(timelineItem);\n\n\t\t\t\tconst nextConversation = {\n\t\t\t\t\t...existingConversation,\n\t\t\t\t\tupdatedAt: timelineItem.createdAt,\n\t\t\t\t\tlastTimelineItem: timelineItem,\n\t\t\t\t\t...(newStatus && { status: newStatus }),\n\t\t\t\t};\n\n\t\t\t\tthis.conversationsStore.ingestConversation(nextConversation);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Extract conversation status from an event timeline item.\n\t * Returns the new status if this is a status-changing event, otherwise null.\n\t */\n\tprivate extractStatusFromEventTimelineItem(\n\t\ttimelineItem: TimelineItem\n\t): ConversationStatus | null {\n\t\tif (timelineItem.type !== ConversationTimelineType.EVENT) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Find the event part in the timeline item\n\t\tconst eventPart = timelineItem.parts?.find(\n\t\t\t(part) =>\n\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\tpart !== null &&\n\t\t\t\t\"type\" in part &&\n\t\t\t\tpart.type === \"event\"\n\t\t);\n\n\t\tif (\n\t\t\t!eventPart ||\n\t\t\ttypeof eventPart !== \"object\" ||\n\t\t\t!(\"eventType\" in eventPart)\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst eventType = (eventPart as { eventType: string }).eventType;\n\n\t\t// Map event types to conversation status\n\t\tswitch (eventType) {\n\t\t\tcase \"resolved\":\n\t\t\t\treturn ConversationStatus.RESOLVED;\n\t\t\tcase \"reopened\":\n\t\t\t\treturn ConversationStatus.OPEN;\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Handle conversationUpdated event from realtime\n\t * Updates conversation with new title (sentiment and escalation are dashboard-only)\n\t */\n\thandleConversationUpdated(event: RealtimeEvent<\"conversationUpdated\">): void {\n\t\tconst { conversationId, updates } = event.payload;\n\n\t\tconst existingConversation =\n\t\t\tthis.conversationsStore.getState().byId[conversationId];\n\n\t\tif (!existingConversation) {\n\t\t\t// Conversation not in store, ignore update\n\t\t\treturn;\n\t\t}\n\n\t\t// Build the updated conversation with only the title field\n\t\t// (sentiment and escalation are dashboard-only fields)\n\t\tconst nextConversation = {\n\t\t\t...existingConversation,\n\t\t\t...(updates.title !== undefined && { title: updates.title ?? undefined }),\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\n\t\tthis.conversationsStore.ingestConversation(nextConversation);\n\t}\n\n\t// File upload methods\n\t/**\n\t * Generate a presigned URL for uploading a file to S3.\n\t */\n\tasync generateUploadUrl(\n\t\tparams: Omit<\n\t\t\tParameters<CossistantRestClient[\"generateUploadUrl\"]>[0],\n\t\t\t\"websiteId\"\n\t\t>\n\t) {\n\t\treturn this.restClient.generateUploadUrl(params);\n\t}\n\n\t/**\n\t * Upload a file to S3 using a presigned URL.\n\t */\n\tasync uploadFile(file: File, uploadUrl: string, contentType: string) {\n\t\treturn this.restClient.uploadFile(file, uploadUrl, contentType);\n\t}\n\n\t/**\n\t * Upload multiple files for a conversation message.\n\t */\n\tasync uploadFilesForMessage(files: File[], conversationId: string) {\n\t\treturn this.restClient.uploadFilesForMessage(files, conversationId);\n\t}\n\n\t// Cleanup method\n\tdestroy(): void {\n\t\t// No cleanup needed for REST client\n\t}\n}\n\nfunction normalizeBootstrapTimelineItem(\n\tconversationId: string,\n\titem: DefaultMessage | TimelineItem\n): TimelineItem {\n\tif (isDefaultMessage(item)) {\n\t\tconst createdAt =\n\t\t\ttypeof window !== \"undefined\" ? new Date().toISOString() : \"\";\n\n\t\treturn {\n\t\t\tid: generateMessageId(),\n\t\t\tconversationId,\n\t\t\torganizationId: \"\", // Not available at this point\n\t\t\ttype: ConversationTimelineType.MESSAGE,\n\t\t\ttext: item.content,\n\t\t\tparts: [{ type: \"text\" as const, text: item.content }],\n\t\t\tvisibility: TimelineItemVisibility.PUBLIC,\n\t\t\tuserId:\n\t\t\t\titem.senderType === SenderType.TEAM_MEMBER\n\t\t\t\t\t? (item.senderId ?? null)\n\t\t\t\t\t: null,\n\t\t\taiAgentId:\n\t\t\t\titem.senderType === SenderType.AI ? (item.senderId ?? null) : null,\n\t\t\tvisitorId:\n\t\t\t\titem.senderType === SenderType.VISITOR ? (item.senderId ?? null) : null,\n\t\t\tcreatedAt,\n\t\t\tdeletedAt: null,\n\t\t} satisfies TimelineItem;\n\t}\n\n\tconst createdAt = item.createdAt\n\t\t? item.createdAt\n\t\t: typeof window !== \"undefined\"\n\t\t\t? new Date().toISOString()\n\t\t\t: \"\";\n\n\treturn {\n\t\t...item,\n\t\tid: item.id ?? generateMessageId(),\n\t\tconversationId,\n\t\torganizationId: item.organizationId || \"\",\n\t\ttype: item.type ?? ConversationTimelineType.MESSAGE,\n\t\ttool: item.tool ?? null,\n\t\tcreatedAt,\n\t\tdeletedAt: item.deletedAt ?? null,\n\t\tuserId: item.userId ?? null,\n\t\taiAgentId: item.aiAgentId ?? null,\n\t\tvisitorId: item.visitorId ?? null,\n\t\tvisibility: item.visibility ?? TimelineItemVisibility.PUBLIC,\n\t} satisfies TimelineItem;\n}\n\nfunction isDefaultMessage(\n\titem: DefaultMessage | TimelineItem\n): item is DefaultMessage {\n\treturn (item as DefaultMessage).content !== undefined;\n}\n"],"mappings":";;;;;;;;AA0EA,IAAa,mBAAb,MAA8B;CAC7B,AAAQ;CACR,AAAQ;CACR,AAAQ,uCAAuB,IAAI,KAAkC;CACrE,AAAQ,iBAAwD;CAChE,AAAS;CACT,AAAS;CACT,AAAS;CAET,YAAY,QAA0B;AACrC,OAAK,SAAS;AACd,OAAK,aAAa,IAAI,qBAAqB,OAAO;AAClD,OAAK,qBAAqB,0BAA0B;AACpD,OAAK,qBAAqB,0BAA0B;AACpD,OAAK,eAAe,oBAAoB;;CAIzC,oBAAoB,QAAyC;AAC5D,OAAK,SAAS;GAAE,GAAG,KAAK;GAAQ,GAAG;GAAQ;AAC3C,OAAK,WAAW,oBAAoB,OAAO;;CAI5C,mBAAqC;AACpC,SAAO,EAAE,GAAG,KAAK,QAAQ;;CAI1B,MAAM,aACL,SAA8B,EAAE,EACC;EACjC,MAAM,EAAE,QAAQ,UAAU;EAC1B,MAAMA,UAAwB,KAAK,aAAa,UAAU;AAE1D,MAAI,CAAC,OAAO;AACX,OAAI,QAAQ,WAAW,aAAa,QAAQ,QAC3C,QAAO,QAAQ;AAEhB,OAAI,KAAK,eACR,QAAO,KAAK;;AAId,OAAK,aAAa,YAAY;EAE9B,MAAM,UAAU,KAAK,WACnB,YAAY,CACZ,MAAM,YAAY;AAClB,QAAK,aAAa,WAAW,QAAQ;AACrC,UAAO;IACN,CACD,OAAO,UAAU;AACjB,QAAK,aAAa,SAAS,MAAM;AACjC,SAAM;IACL,CACD,cAAc;AACd,OAAI,KAAK,mBAAmB,QAC3B,MAAK,iBAAiB;IAEtB;AAEH,OAAK,iBAAiB;AAEtB,SAAO;;CAGR,MAAM,aAA6C;AAClD,SAAO,KAAK,aAAa,EAAE,OAAO,MAAM,CAAC;;CAG1C,kBAAkB,WAAmB,WAA0B;AAC9D,OAAK,WAAW,kBAAkB,WAAW,UAAU;;CAGxD,kBAAkB,WAA0B;AAC3C,OAAK,WAAW,kBAAkB,UAAU;;CAG7C,MAAM,sBACL,UAC2B;AAC3B,SAAO,KAAK,WAAW,sBAAsB,SAAS;;CAGvD,MAAM,SAAS,QAOsB;AACpC,SAAO,KAAK,WAAW,SAAS,OAAO;;CAGxC,MAAM,sBACL,UAC2B;AAC3B,SAAO,KAAK,WAAW,sBAAsB,SAAS;;CAIvD,qBACC,SAAqC,EAAE,EACV;EAC7B,MAAM,iBAAiB,OAAO,kBAAkB,wBAAwB;EACxE,MAAM,MAAM,OAAO,WAAW,+BAAc,IAAI,MAAM,EAAC,aAAa,GAAG;EACvE,MAAM,iBAAiB,OAAO,wBAAwB,EAAE,EAAE,KAAK,SAC9D,+BAA+B,gBAAgB,KAAK,CACpD;EACD,MAAM,WAAW,KAAK,mBAAmB,UAAU,CAAC,KAAK;EACzD,MAAM,gBACL,OAAO,aAAa,KAAK,WAAW,qBAAqB,IAAI;EAC9D,MAAM,gBACL,OAAO,aAAa,KAAK,WAAW,qBAAqB,IAAI;EAE9D,MAAMC,eAA6B,WAChC;GACA,GAAG;GACH,OAAO,OAAO,SAAS,SAAS;GAChC,QAAQ,OAAO,UAAU,SAAS;GAClC,WAAW;GACX,kBAAkB,cAAc,GAAG,GAAG,IAAI,SAAS;GACnD,GACA;GACA,IAAI;GACJ,OAAO,OAAO;GACd,WAAW;GACX,WAAW;GACX,WAAW;GACX,WAAW;GACX,QAAQ,OAAO,UAAU,mBAAmB;GAC5C,WAAW;GACX,kBAAkB,cAAc,GAAG,GAAG;GACtC;AAEH,OAAK,mBAAmB,mBAAmB,aAAa;AAExD,MAAI,cAAc,SAAS,EAC1B,MAAK,mBAAmB,WAAW,gBAAgB;GAClD,OAAO;GACP,aAAa;GACb,YAAY;GACZ,CAAC;AAGH,MAAI,CAAC,YAAY,KAAK,qBAAqB,IAAI,eAAe,CAC7D,MAAK,qBAAqB,IAAI,gBAAgB;GAC7C;GACA,sBAAsB;GACtB,CAAC;AAGH,SAAO;GACN;GACA;GACA,sBAAsB;GACtB;;CAGF,MAAM,mBACL,QAC0C;EAC1C,MAAM,WAAW,MAAM,KAAK,WAAW,mBAAmB,OAAO;AACjE,OAAK,mBAAmB,mBAAmB,SAAS,aAAa;AACjE,SAAO;;CAGR,MAAM,kBACL,QACqC;EACrC,MAAM,WAAW,MAAM,KAAK,WAAW,kBAAkB,OAAO;AAChE,OAAK,mBAAmB,WAAW,SAAS;AAC5C,SAAO;;CAGR,MAAM,gBACL,QACmC;EACnC,MAAM,WAAW,MAAM,KAAK,WAAW,gBAAgB,OAAO;AAC9D,OAAK,mBAAmB,mBAAmB,SAAS,aAAa;AACjE,SAAO;;CAGR,MAAM,qBACL,QAG4C;AAC5C,SAAO,KAAK,WAAW,qBAAqB,OAAO;;CAGpD,MAAM,wBAAwB,QAAoC;AACjE,SAAO,KAAK,WAAW,wBAAwB,OAAO;;CAGvD,MAAM,iBAAiB,QAKwB;AAC9C,SAAO,KAAK,WAAW,sBAAsB,OAAO;;CAKrD,MAAM,6BACL,QACgD;EAChD,MAAM,WAAW,MAAM,KAAK,WAAW,6BAA6B,OAAO;AAC3E,OAAK,mBAAmB,WAAW,OAAO,gBAAgB;GACzD,OAAO,SAAS;GAChB,aAAa,SAAS;GACtB,YAAY,SAAS,cAAc;GACnC,CAAC;AACF,SAAO;;CAGR,MAAM,YACL,QAOC;EACD,MAAM,EAAE,iBAAiB,GAAG,SAAS;EACrC,MAAM,eAAe,KAAK,KAAK,MAAM,mBAAmB;EACxD,MAAM,YAAY,KAAK,KAAK,YACzB,KAAK,KAAK,YACV,OAAO,WAAW,+BACjB,IAAI,MAAM,EAAC,aAAa,GACxB;EAGJ,MAAMC,yBAAuC;GAC5C,IAAI;GACJ,gBAAgB,KAAK;GACrB,gBAAgB;GAChB,YAAY,KAAK,KAAK,cAAc,uBAAuB;GAC3D,MAAM,KAAK,KAAK,QAAQ,yBAAyB;GACjD,MAAM,KAAK,KAAK;GAChB,MAAM,KAAK,KAAK,QAAQ;GACxB,OACC,KAAK,KAAK,SAAS,KAAK,KAAK,MAAM,SAAS,IACzC,KAAK,KAAK,QACV,KAAK,KAAK,OACT,CAAC;IAAE,MAAM;IAAiB,MAAM,KAAK,KAAK;IAAM,CAAC,GACjD,EAAE;GACP,QAAQ,KAAK,KAAK,UAAU;GAC5B,WAAW,KAAK,KAAK,aAAa;GAClC,WAAW,KAAK,KAAK,aAAa;GAClC;GACA,WAAW;GACX;AAED,OAAK,mBAAmB,mBAAmB,uBAAuB;EAElE,MAAM,UAAU,KAAK,qBAAqB,IAAI,KAAK,eAAe;AAElE,MAAI,WAAW,oBAAoB,MAClC,KAAI;GACH,MAAM,WAAW,MAAM,KAAK,WAAW,mBAAmB;IACzD,gBAAgB,KAAK;IACrB,sBAAsB,CACrB,GAAG,QAAQ,sBACX,uBACA;IACD,CAAC;AAEF,QAAK,mBAAmB,mBAAmB,SAAS,aAAa;AACjE,QAAK,mBAAmB,mBACvB,KAAK,gBACL,aACA;AACD,QAAK,mBAAmB,kBAAkB,KAAK,eAAe;AAE9D,QAAK,mBAAmB,WAAW,KAAK,gBAAgB;IACvD,OAAO,SAAS;IAChB,aAAa;IACb,YAAY;IACZ,CAAC;AAEF,QAAK,qBAAqB,OAAO,KAAK,eAAe;AAMrD,UAAO;IACN,MAJA,SAAS,qBAAqB,GAAG,GAAG,IACpC,SAAS,qBAAqB;IAI9B,cAAc,SAAS;IACvB,sBAAsB,SAAS;IAC/B,wBAAwB;IACxB;WAKO,OAAO;AACf,QAAK,mBAAmB,mBACvB,KAAK,gBACL,aACA;AACD,SAAM;;EAIR,MAAM,EAAE,WAAW,YAAY,GAAG,aAAa,KAAK;EAEpD,MAAMC,UAAmC;GACxC,GAAG;GACH,MAAM;IACL,GAAG;IACH,IAAI;IACJ;GACD;AAED,MAAI;GACH,MAAM,WAAW,MAAM,KAAK,WAAW,YAAY,QAAQ;AAG3D,QAAK,mBAAmB,qBACvB,KAAK,gBACL,cACA,SAAS,KACT;AACD,UAAO;WACC,OAAO;AACf,QAAK,mBAAmB,mBACvB,KAAK,gBACL,aACA;AACD,SAAM;;;CAIR,oBAAoB,OAA+B;AAClD,MAAI,MAAM,SAAS,uBAAuB;GACzC,MAAM,EAAE,cAAc,WAAW,MAAM;AAEvC,QAAK,mBAAmB,mBAAmB;IAC1C,GAAG;IACH,kBAAkB,aAAa,oBAAoB;IACnD,CAAC;aACQ,MAAM,SAAS,uBAAuB;GAEhD,MAAM,eACL,KAAK,mBAAmB,2BAA2B,MAAM;GAG1D,MAAM,uBACL,KAAK,mBAAmB,UAAU,CAAC,KAAK,aAAa;AAEtD,OAAI,sBAAsB;IAEzB,MAAM,YAAY,KAAK,mCAAmC,aAAa;IAEvE,MAAM,mBAAmB;KACxB,GAAG;KACH,WAAW,aAAa;KACxB,kBAAkB;KAClB,GAAI,aAAa,EAAE,QAAQ,WAAW;KACtC;AAED,SAAK,mBAAmB,mBAAmB,iBAAiB;;;;;;;;CAS/D,AAAQ,mCACP,cAC4B;AAC5B,MAAI,aAAa,SAAS,yBAAyB,MAClD,QAAO;EAIR,MAAM,YAAY,aAAa,OAAO,MACpC,SACA,OAAO,SAAS,YAChB,SAAS,QACT,UAAU,QACV,KAAK,SAAS,QACf;AAED,MACC,CAAC,aACD,OAAO,cAAc,YACrB,EAAE,eAAe,WAEjB,QAAO;AAMR,UAHmB,UAAoC,WAGvD;GACC,KAAK,WACJ,QAAO,mBAAmB;GAC3B,KAAK,WACJ,QAAO,mBAAmB;GAC3B,QACC,QAAO;;;;;;;CAQV,0BAA0B,OAAmD;EAC5E,MAAM,EAAE,gBAAgB,YAAY,MAAM;EAE1C,MAAM,uBACL,KAAK,mBAAmB,UAAU,CAAC,KAAK;AAEzC,MAAI,CAAC,qBAEJ;EAKD,MAAM,mBAAmB;GACxB,GAAG;GACH,GAAI,QAAQ,UAAU,UAAa,EAAE,OAAO,QAAQ,SAAS,QAAW;GACxE,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC;AAED,OAAK,mBAAmB,mBAAmB,iBAAiB;;;;;CAO7D,MAAM,kBACL,QAIC;AACD,SAAO,KAAK,WAAW,kBAAkB,OAAO;;;;;CAMjD,MAAM,WAAW,MAAY,WAAmB,aAAqB;AACpE,SAAO,KAAK,WAAW,WAAW,MAAM,WAAW,YAAY;;;;;CAMhE,MAAM,sBAAsB,OAAe,gBAAwB;AAClE,SAAO,KAAK,WAAW,sBAAsB,OAAO,eAAe;;CAIpE,UAAgB;;AAKjB,SAAS,+BACR,gBACA,MACe;AACf,KAAI,iBAAiB,KAAK,EAAE;EAC3B,MAAMC,cACL,OAAO,WAAW,+BAAc,IAAI,MAAM,EAAC,aAAa,GAAG;AAE5D,SAAO;GACN,IAAI,mBAAmB;GACvB;GACA,gBAAgB;GAChB,MAAM,yBAAyB;GAC/B,MAAM,KAAK;GACX,OAAO,CAAC;IAAE,MAAM;IAAiB,MAAM,KAAK;IAAS,CAAC;GACtD,YAAY,uBAAuB;GACnC,QACC,KAAK,eAAe,WAAW,cAC3B,KAAK,YAAY,OAClB;GACJ,WACC,KAAK,eAAe,WAAW,KAAM,KAAK,YAAY,OAAQ;GAC/D,WACC,KAAK,eAAe,WAAW,UAAW,KAAK,YAAY,OAAQ;GACpE;GACA,WAAW;GACX;;CAGF,MAAM,YAAY,KAAK,YACpB,KAAK,YACL,OAAO,WAAW,+BACjB,IAAI,MAAM,EAAC,aAAa,GACxB;AAEJ,QAAO;EACN,GAAG;EACH,IAAI,KAAK,MAAM,mBAAmB;EAClC;EACA,gBAAgB,KAAK,kBAAkB;EACvC,MAAM,KAAK,QAAQ,yBAAyB;EAC5C,MAAM,KAAK,QAAQ;EACnB;EACA,WAAW,KAAK,aAAa;EAC7B,QAAQ,KAAK,UAAU;EACvB,WAAW,KAAK,aAAa;EAC7B,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc,uBAAuB;EACtD;;AAGF,SAAS,iBACR,MACyB;AACzB,QAAQ,KAAwB,YAAY"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["current: WebsiteState","conversation: Conversation","optimisticTimelineItem: TimelineItem","payload: SendTimelineItemRequest","createdAt"],"sources":["../src/client.ts"],"sourcesContent":["import {\n\ttype AnyRealtimeEvent,\n\ttype DefaultMessage,\n\tgetEventPayload,\n\ttype IdentifyContactResponse,\n\ttype RealtimeEvent,\n} from \"@cossistant/types\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingResponseBody,\n\tSubmitConversationRatingRequestBody,\n\tSubmitConversationRatingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n\tTimelineItem,\n} from \"@cossistant/types/api/timeline-item\";\nimport {\n\tConversationStatus,\n\tConversationTimelineType,\n\tSenderType,\n\tTimelineItemVisibility,\n} from \"@cossistant/types/enums\";\nimport type { Conversation } from \"@cossistant/types/schemas\";\nimport { CossistantRestClient } from \"./rest-client\";\nimport {\n\ttype ConversationsStore,\n\tcreateConversationsStore,\n} from \"./store/conversations-store\";\nimport {\n\tcreateTimelineItemsStore,\n\ttype TimelineItemsStore,\n} from \"./store/timeline-items-store\";\nimport {\n\tcreateWebsiteStore,\n\ttype WebsiteState,\n\ttype WebsiteStore,\n} from \"./store/website-store\";\nimport type {\n\tCossistantConfig,\n\tPublicWebsiteResponse,\n\tVisitorMetadata,\n\tVisitorResponse,\n} from \"./types\";\nimport { generateConversationId, generateMessageId } from \"./utils\";\n\ntype PendingConversation = {\n\tconversation: Conversation;\n\tinitialTimelineItems: TimelineItem[];\n};\n\ntype InitiateConversationParams = {\n\tconversationId?: string;\n\tvisitorId?: string | null;\n\twebsiteId?: string | null;\n\ttitle?: string;\n\tstatus?: Conversation[\"status\"];\n\tdefaultTimelineItems?: Array<DefaultMessage | TimelineItem>;\n};\n\ntype InitiateConversationResult = {\n\tconversationId: string;\n\tconversation: Conversation;\n\tdefaultTimelineItems: TimelineItem[];\n};\n\nexport class CossistantClient {\n\tprivate restClient: CossistantRestClient;\n\tprivate config: CossistantConfig;\n\tprivate pendingConversations = new Map<string, PendingConversation>();\n\tprivate websiteRequest: Promise<PublicWebsiteResponse> | null = null;\n\treadonly conversationsStore: ConversationsStore;\n\treadonly timelineItemsStore: TimelineItemsStore;\n\treadonly websiteStore: WebsiteStore;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\t\tthis.restClient = new CossistantRestClient(config);\n\t\tthis.conversationsStore = createConversationsStore();\n\t\tthis.timelineItemsStore = createTimelineItemsStore();\n\t\tthis.websiteStore = createWebsiteStore();\n\t}\n\n\t// Configuration updates\n\tupdateConfiguration(config: Partial<CossistantConfig>): void {\n\t\tthis.config = { ...this.config, ...config };\n\t\tthis.restClient.updateConfiguration(config);\n\t}\n\n\t// Utility methods\n\tgetConfiguration(): CossistantConfig {\n\t\treturn { ...this.config };\n\t}\n\n\t// Website information\n\tasync fetchWebsite(\n\t\tparams: { force?: boolean } = {}\n\t): Promise<PublicWebsiteResponse> {\n\t\tconst { force = false } = params;\n\t\tconst current: WebsiteState = this.websiteStore.getState();\n\n\t\tif (!force) {\n\t\t\tif (current.status === \"success\" && current.website) {\n\t\t\t\treturn current.website;\n\t\t\t}\n\t\t\tif (this.websiteRequest) {\n\t\t\t\treturn this.websiteRequest;\n\t\t\t}\n\t\t}\n\n\t\tthis.websiteStore.setLoading();\n\n\t\tconst request = this.restClient\n\t\t\t.getWebsite()\n\t\t\t.then((website) => {\n\t\t\t\tthis.websiteStore.setWebsite(website);\n\t\t\t\treturn website;\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tthis.websiteStore.setError(error);\n\t\t\t\tthrow error;\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (this.websiteRequest === request) {\n\t\t\t\t\tthis.websiteRequest = null;\n\t\t\t\t}\n\t\t\t});\n\n\t\tthis.websiteRequest = request;\n\n\t\treturn request;\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\treturn this.fetchWebsite({ force: true });\n\t}\n\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.restClient.setWebsiteContext(websiteId, visitorId);\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.restClient.setVisitorBlocked(isBlocked);\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\treturn this.restClient.updateVisitorMetadata(metadata);\n\t}\n\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\treturn this.restClient.identify(params);\n\t}\n\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\treturn this.restClient.updateContactMetadata(metadata);\n\t}\n\n\t// Conversation management\n\tinitiateConversation(\n\t\tparams: InitiateConversationParams = {}\n\t): InitiateConversationResult {\n\t\tconst conversationId = params.conversationId ?? generateConversationId();\n\t\tconst now = typeof window !== \"undefined\" ? new Date().toISOString() : \"\";\n\t\tconst timelineItems = (params.defaultTimelineItems ?? []).map((item) =>\n\t\t\tnormalizeBootstrapTimelineItem(conversationId, item)\n\t\t);\n\t\tconst existing = this.conversationsStore.getState().byId[conversationId];\n\t\tconst baseVisitorId =\n\t\t\tparams.visitorId ?? this.restClient.getCurrentVisitorId() ?? \"\";\n\t\tconst baseWebsiteId =\n\t\t\tparams.websiteId ?? this.restClient.getCurrentWebsiteId() ?? \"\";\n\n\t\tconst conversation: Conversation = existing\n\t\t\t? {\n\t\t\t\t\t...existing,\n\t\t\t\t\ttitle: params.title ?? existing.title,\n\t\t\t\t\tstatus: params.status ?? existing.status,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tlastTimelineItem: timelineItems.at(-1) ?? existing.lastTimelineItem,\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tid: conversationId,\n\t\t\t\t\ttitle: params.title,\n\t\t\t\t\tcreatedAt: now,\n\t\t\t\t\tupdatedAt: now,\n\t\t\t\t\tvisitorId: baseVisitorId,\n\t\t\t\t\twebsiteId: baseWebsiteId,\n\t\t\t\t\tstatus: params.status ?? ConversationStatus.OPEN,\n\t\t\t\t\tdeletedAt: null,\n\t\t\t\t\tlastTimelineItem: timelineItems.at(-1),\n\t\t\t\t};\n\n\t\tthis.conversationsStore.ingestConversation(conversation);\n\n\t\tif (timelineItems.length > 0) {\n\t\t\tthis.timelineItemsStore.ingestPage(conversationId, {\n\t\t\t\titems: timelineItems,\n\t\t\t\thasNextPage: false,\n\t\t\t\tnextCursor: undefined,\n\t\t\t});\n\t\t}\n\n\t\tif (!existing || this.pendingConversations.has(conversationId)) {\n\t\t\tthis.pendingConversations.set(conversationId, {\n\t\t\t\tconversation,\n\t\t\t\tinitialTimelineItems: timelineItems,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tconversationId,\n\t\t\tconversation,\n\t\t\tdefaultTimelineItems: timelineItems,\n\t\t};\n\t}\n\n\tasync createConversation(\n\t\tparams?: Partial<CreateConversationRequestBody>\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst response = await this.restClient.createConversation(params);\n\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\treturn response;\n\t}\n\n\tasync listConversations(\n\t\tparams?: Partial<ListConversationsRequest>\n\t): Promise<ListConversationsResponse> {\n\t\tconst response = await this.restClient.listConversations(params);\n\t\tthis.conversationsStore.ingestList(response);\n\t\treturn response;\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\tconst response = await this.restClient.getConversation(params);\n\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\treturn response;\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\treturn this.restClient.markConversationSeen(params);\n\t}\n\n\tasync getConversationSeenData(params: { conversationId: string }) {\n\t\treturn this.restClient.getConversationSeenData(params);\n\t}\n\n\tasync setVisitorTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\treturn this.restClient.setConversationTyping(params);\n\t}\n\n\tasync submitConversationRating(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & SubmitConversationRatingRequestBody\n\t): Promise<SubmitConversationRatingResponseBody> {\n\t\tconst response = await this.restClient.submitConversationRating(params);\n\n\t\tconst existing =\n\t\t\tthis.conversationsStore.getState().byId[response.conversationId];\n\n\t\tif (existing) {\n\t\t\tthis.conversationsStore.ingestConversation({\n\t\t\t\t...existing,\n\t\t\t\tvisitorRating: response.rating,\n\t\t\t\tvisitorRatingAt: response.ratedAt,\n\t\t\t});\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t// Timeline items management\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\tconst response = await this.restClient.getConversationTimelineItems(params);\n\t\tthis.timelineItemsStore.ingestPage(params.conversationId, {\n\t\t\titems: response.items,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t\tnextCursor: response.nextCursor ?? undefined,\n\t\t});\n\t\treturn response;\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest & { createIfPending?: boolean }\n\t): Promise<\n\t\tSendTimelineItemResponse & {\n\t\t\tconversation?: Conversation;\n\t\t\tinitialTimelineItems?: TimelineItem[];\n\t\t\twasConversationCreated?: boolean;\n\t\t}\n\t> {\n\t\tconst { createIfPending, ...rest } = params;\n\t\tconst optimisticId = rest.item.id ?? generateMessageId();\n\t\tconst createdAt = rest.item.createdAt\n\t\t\t? rest.item.createdAt\n\t\t\t: typeof window !== \"undefined\"\n\t\t\t\t? new Date().toISOString()\n\t\t\t\t: \"\";\n\n\t\t// Add optimistic timeline item\n\t\tconst optimisticTimelineItem: TimelineItem = {\n\t\t\tid: optimisticId,\n\t\t\tconversationId: rest.conversationId,\n\t\t\torganizationId: \"\", // Not available yet\n\t\t\tvisibility: rest.item.visibility ?? TimelineItemVisibility.PUBLIC,\n\t\t\ttype: rest.item.type ?? ConversationTimelineType.MESSAGE,\n\t\t\ttext: rest.item.text,\n\t\t\ttool: rest.item.tool ?? null,\n\t\t\tparts:\n\t\t\t\trest.item.parts && rest.item.parts.length > 0\n\t\t\t\t\t? rest.item.parts\n\t\t\t\t\t: rest.item.text\n\t\t\t\t\t\t? [{ type: \"text\" as const, text: rest.item.text }]\n\t\t\t\t\t\t: [],\n\t\t\tuserId: rest.item.userId ?? null,\n\t\t\tvisitorId: rest.item.visitorId ?? null,\n\t\t\taiAgentId: rest.item.aiAgentId ?? null,\n\t\t\tcreatedAt,\n\t\t\tdeletedAt: null,\n\t\t};\n\n\t\tthis.timelineItemsStore.ingestTimelineItem(optimisticTimelineItem);\n\n\t\tconst pending = this.pendingConversations.get(rest.conversationId);\n\n\t\tif (pending && createIfPending !== false) {\n\t\t\ttry {\n\t\t\t\tconst response = await this.restClient.createConversation({\n\t\t\t\t\tconversationId: rest.conversationId,\n\t\t\t\t\tdefaultTimelineItems: [\n\t\t\t\t\t\t...pending.initialTimelineItems,\n\t\t\t\t\t\toptimisticTimelineItem,\n\t\t\t\t\t],\n\t\t\t\t});\n\n\t\t\t\tthis.conversationsStore.ingestConversation(response.conversation);\n\t\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\t\trest.conversationId,\n\t\t\t\t\toptimisticId\n\t\t\t\t);\n\t\t\t\tthis.timelineItemsStore.clearConversation(rest.conversationId);\n\n\t\t\t\tthis.timelineItemsStore.ingestPage(rest.conversationId, {\n\t\t\t\t\titems: response.initialTimelineItems,\n\t\t\t\t\thasNextPage: false,\n\t\t\t\t\tnextCursor: undefined,\n\t\t\t\t});\n\n\t\t\t\tthis.pendingConversations.delete(rest.conversationId);\n\n\t\t\t\tconst item =\n\t\t\t\t\tresponse.initialTimelineItems.at(-1) ??\n\t\t\t\t\tresponse.initialTimelineItems[0];\n\n\t\t\t\treturn {\n\t\t\t\t\titem: item as TimelineItem,\n\t\t\t\t\tconversation: response.conversation,\n\t\t\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t\t\t\twasConversationCreated: true,\n\t\t\t\t} satisfies SendTimelineItemResponse & {\n\t\t\t\t\tconversation: Conversation;\n\t\t\t\t\tinitialTimelineItems: TimelineItem[];\n\t\t\t\t\twasConversationCreated: true;\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\t\trest.conversationId,\n\t\t\t\t\toptimisticId\n\t\t\t\t);\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\tconst { createdAt: _createdAt, ...restItem } = rest.item;\n\n\t\tconst payload: SendTimelineItemRequest = {\n\t\t\t...rest,\n\t\t\titem: {\n\t\t\t\t...restItem,\n\t\t\t\tid: optimisticId,\n\t\t\t},\n\t\t};\n\n\t\ttry {\n\t\t\tconst response = await this.restClient.sendMessage(payload);\n\n\t\t\t// Finalize the timeline item\n\t\t\tthis.timelineItemsStore.finalizeTimelineItem(\n\t\t\t\trest.conversationId,\n\t\t\t\toptimisticId,\n\t\t\t\tresponse.item\n\t\t\t);\n\t\t\treturn response;\n\t\t} catch (error) {\n\t\t\tthis.timelineItemsStore.removeTimelineItem(\n\t\t\t\trest.conversationId,\n\t\t\t\toptimisticId\n\t\t\t);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\thandleRealtimeEvent(event: AnyRealtimeEvent): void {\n\t\tif (event.type === \"conversationCreated\") {\n\t\t\tconst { conversation, header } = event.payload;\n\n\t\t\tthis.conversationsStore.ingestConversation({\n\t\t\t\t...conversation,\n\t\t\t\tlastTimelineItem: conversation.lastTimelineItem ?? undefined,\n\t\t\t});\n\t\t} else if (event.type === \"timelineItemCreated\") {\n\t\t\t// Ingest timeline item into store\n\t\t\tconst timelineItem =\n\t\t\t\tthis.timelineItemsStore.ingestRealtimeTimelineItem(event);\n\n\t\t\t// Update conversation with last timeline item\n\t\t\tconst existingConversation =\n\t\t\t\tthis.conversationsStore.getState().byId[timelineItem.conversationId];\n\n\t\t\tif (existingConversation) {\n\t\t\t\t// Check if this is a status-changing event timeline item\n\t\t\t\tconst newStatus = this.extractStatusFromEventTimelineItem(timelineItem);\n\n\t\t\t\tconst nextConversation = {\n\t\t\t\t\t...existingConversation,\n\t\t\t\t\tupdatedAt: timelineItem.createdAt,\n\t\t\t\t\tlastTimelineItem: timelineItem,\n\t\t\t\t\t...(newStatus && { status: newStatus }),\n\t\t\t\t};\n\n\t\t\t\tthis.conversationsStore.ingestConversation(nextConversation);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Extract conversation status from an event timeline item.\n\t * Returns the new status if this is a status-changing event, otherwise null.\n\t */\n\tprivate extractStatusFromEventTimelineItem(\n\t\ttimelineItem: TimelineItem\n\t): ConversationStatus | null {\n\t\tif (timelineItem.type !== ConversationTimelineType.EVENT) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// Find the event part in the timeline item\n\t\tconst eventPart = timelineItem.parts?.find(\n\t\t\t(part) =>\n\t\t\t\ttypeof part === \"object\" &&\n\t\t\t\tpart !== null &&\n\t\t\t\t\"type\" in part &&\n\t\t\t\tpart.type === \"event\"\n\t\t);\n\n\t\tif (\n\t\t\t!eventPart ||\n\t\t\ttypeof eventPart !== \"object\" ||\n\t\t\t!(\"eventType\" in eventPart)\n\t\t) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst eventType = (eventPart as { eventType: string }).eventType;\n\n\t\t// Map event types to conversation status\n\t\tswitch (eventType) {\n\t\t\tcase \"resolved\":\n\t\t\t\treturn ConversationStatus.RESOLVED;\n\t\t\tcase \"reopened\":\n\t\t\t\treturn ConversationStatus.OPEN;\n\t\t\tdefault:\n\t\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Handle conversationUpdated event from realtime\n\t * Updates conversation with new title (sentiment and escalation are dashboard-only)\n\t */\n\thandleConversationUpdated(event: RealtimeEvent<\"conversationUpdated\">): void {\n\t\tconst { conversationId, updates } = event.payload;\n\n\t\tconst existingConversation =\n\t\t\tthis.conversationsStore.getState().byId[conversationId];\n\n\t\tif (!existingConversation) {\n\t\t\t// Conversation not in store, ignore update\n\t\t\treturn;\n\t\t}\n\n\t\t// Build the updated conversation with only the title field\n\t\t// (sentiment and escalation are dashboard-only fields)\n\t\tconst nextConversation = {\n\t\t\t...existingConversation,\n\t\t\t...(updates.title !== undefined && { title: updates.title ?? undefined }),\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t};\n\n\t\tthis.conversationsStore.ingestConversation(nextConversation);\n\t}\n\n\t// File upload methods\n\t/**\n\t * Generate a presigned URL for uploading a file to S3.\n\t */\n\tasync generateUploadUrl(\n\t\tparams: Omit<\n\t\t\tParameters<CossistantRestClient[\"generateUploadUrl\"]>[0],\n\t\t\t\"websiteId\"\n\t\t>\n\t) {\n\t\treturn this.restClient.generateUploadUrl(params);\n\t}\n\n\t/**\n\t * Upload a file to S3 using a presigned URL.\n\t */\n\tasync uploadFile(file: File, uploadUrl: string, contentType: string) {\n\t\treturn this.restClient.uploadFile(file, uploadUrl, contentType);\n\t}\n\n\t/**\n\t * Upload multiple files for a conversation message.\n\t */\n\tasync uploadFilesForMessage(files: File[], conversationId: string) {\n\t\treturn this.restClient.uploadFilesForMessage(files, conversationId);\n\t}\n\n\t// Cleanup method\n\tdestroy(): void {\n\t\t// No cleanup needed for REST client\n\t}\n}\n\nfunction normalizeBootstrapTimelineItem(\n\tconversationId: string,\n\titem: DefaultMessage | TimelineItem\n): TimelineItem {\n\tif (isDefaultMessage(item)) {\n\t\tconst createdAt =\n\t\t\ttypeof window !== \"undefined\" ? new Date().toISOString() : \"\";\n\n\t\treturn {\n\t\t\tid: generateMessageId(),\n\t\t\tconversationId,\n\t\t\torganizationId: \"\", // Not available at this point\n\t\t\ttype: ConversationTimelineType.MESSAGE,\n\t\t\ttext: item.content,\n\t\t\tparts: [{ type: \"text\" as const, text: item.content }],\n\t\t\tvisibility: TimelineItemVisibility.PUBLIC,\n\t\t\tuserId:\n\t\t\t\titem.senderType === SenderType.TEAM_MEMBER\n\t\t\t\t\t? (item.senderId ?? null)\n\t\t\t\t\t: null,\n\t\t\taiAgentId:\n\t\t\t\titem.senderType === SenderType.AI ? (item.senderId ?? null) : null,\n\t\t\tvisitorId:\n\t\t\t\titem.senderType === SenderType.VISITOR ? (item.senderId ?? null) : null,\n\t\t\tcreatedAt,\n\t\t\tdeletedAt: null,\n\t\t} satisfies TimelineItem;\n\t}\n\n\tconst createdAt = item.createdAt\n\t\t? item.createdAt\n\t\t: typeof window !== \"undefined\"\n\t\t\t? new Date().toISOString()\n\t\t\t: \"\";\n\n\treturn {\n\t\t...item,\n\t\tid: item.id ?? generateMessageId(),\n\t\tconversationId,\n\t\torganizationId: item.organizationId || \"\",\n\t\ttype: item.type ?? ConversationTimelineType.MESSAGE,\n\t\ttool: item.tool ?? null,\n\t\tcreatedAt,\n\t\tdeletedAt: item.deletedAt ?? null,\n\t\tuserId: item.userId ?? null,\n\t\taiAgentId: item.aiAgentId ?? null,\n\t\tvisitorId: item.visitorId ?? null,\n\t\tvisibility: item.visibility ?? TimelineItemVisibility.PUBLIC,\n\t} satisfies TimelineItem;\n}\n\nfunction isDefaultMessage(\n\titem: DefaultMessage | TimelineItem\n): item is DefaultMessage {\n\treturn (item as DefaultMessage).content !== undefined;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/rest-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./types/src/api/conversation.js";
|
|
1
|
+
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody, SubmitConversationRatingRequestBody, SubmitConversationRatingResponseBody } from "./types/src/api/conversation.js";
|
|
2
2
|
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse } from "./types/src/api/timeline-item.js";
|
|
3
3
|
import { IdentifyContactResponse } from "./types/src/api/contact.js";
|
|
4
4
|
import { GenerateUploadUrlRequest, GenerateUploadUrlResponse } from "./types/src/api/upload.js";
|
|
@@ -56,6 +56,9 @@ declare class CossistantRestClient {
|
|
|
56
56
|
visitorPreview?: string | null;
|
|
57
57
|
visitorId?: string;
|
|
58
58
|
}): Promise<SetConversationTypingResponseBody>;
|
|
59
|
+
submitConversationRating(params: {
|
|
60
|
+
conversationId: string;
|
|
61
|
+
} & SubmitConversationRatingRequestBody): Promise<SubmitConversationRatingResponseBody>;
|
|
59
62
|
sendMessage(params: SendTimelineItemRequest): Promise<SendTimelineItemResponse>;
|
|
60
63
|
getConversationTimelineItems(params: GetConversationTimelineItemsRequest & {
|
|
61
64
|
conversationId: string;
|
package/rest-client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-client.d.ts","names":[],"sources":["../src/rest-client.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"rest-client.d.ts","names":[],"sources":["../src/rest-client.ts"],"sourcesContent":[],"mappings":";;;;;;;cAgDa,oBAAA;;EAAA,QAAA,WAAA;EAQQ,QAAA,SAAA;EA6LQ,QAAA,SAAA;EAAR,QAAA,SAAA;EA6ET,QAAA,cAAA;EACA,WAAA,CAAA,MAAA,EA3QS,eAAA,CAAA,gBA2QT;EAAR,QAAA,wBAAA;EAyBS,QAAA,gBAAA;EAEA,QAAA,mBAAA;EAAR,QAAA,OAAA;EAqCO,UAAA,CAAA,CAAA,EA9IS,OA8IT,CA9IiB,eAAA,CAAA,qBA8IjB,CAAA;EACA,iBAAA,CAAA,SAAA,EAAA,MAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAR,iBAAA,CAAA,SAAA,EAAA,OAAA,CAAA,EAAA,IAAA;EAOc,mBAAA,CAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAAR,mBAAA,CAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EACE,qBAAA,CAAA,QAAA,EA1EA,eAAA,CAAA,eA0EA,CAAA,EAzER,OAyEQ,CAzEA,eAAA,CAAA,eAyEA,CAAA;EAAR;;;;EAwEc,QAAA,CAAA,MAAA,EAAA;IAAR,UAAA,CAAA,EAAA,MAAA;IACE,KAAA,CAAA,EAAA,MAAA;IAAR,IAAA,CAAA,EAAA,MAAA;IAiEM,KAAA,CAAA,EAAA,MAAA;IACE,QAAA,CAAA,EA3LC,MA2LD,CAAA,MAAA,EAAA,OAAA,CAAA;IAAR,qBAAA,CAAA,EAAA,MAAA;EAgCU,CAAA,CAAA,EAzNT,OAyNS,CAzND,uBAyNC,CAAA;EAAR;;;;EAsCD,qBAAA,CAAA,QAAA,EA1NO,MA0NP,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,EAzND,OAyNC,CAzNO,eAAA,CAAA,eAyNP,CAAA;EAmCQ,kBAAA,CAAA,MAAA,CAAA,EArPH,OAqPG,CArPK,6BAqPL,CAAA,CAAA,EApPT,OAoPS,CApPD,8BAoPC,CAAA;EAAR,mBAAA,CAAA,MAAA,EApM8B,OAoM9B,CApMsC,eAAA,CAAA,gBAoMtC,CAAA,CAAA,EApM0D,OAoM1D,CAAA,IAAA,CAAA;EA+CC,iBAAA,CAAA,MAAA,CAAA,EA3NI,OA2NJ,CA3NY,wBA2NZ,CAAA,CAAA,EA1NF,OA0NE,CA1NM,yBA0NN,CAAA;EACM,eAAA,CAAA,MAAA,EA1JF,sBA0JE,CAAA,EAzJR,OAyJQ,CAzJA,uBAyJA,CAAA;EAAR,oBAAA,CAAA,MAAA,EAAA;IAwCM,cAAA,EAAA,MAAA;EACE,CAAA,GAlKN,OAkKM,CAlKE,+BAkKF,CAAA,CAAA,EAjKR,OAiKQ,CAjKA,gCAiKA,CAAA;EAAR,uBAAA,CAAA,MAAA,EAAA;IAsBM,cAAA,EAAA,MAAA;EACE,CAAA,CAAA,EAnJP,OAmJO,CAnJC,+BAmJD,CAAA;EAAR,qBAAA,CAAA,MAAA,EAAA;IAwCW,cAAA,EAAA,MAAA;IAAL,QAAA,EAAA,OAAA;IAGE,cAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IAAR,SAAA,CAAA,EAAA,MAAA;EA2DI,CAAA,CAAA,EAtNH,OAsNG,CAtNK,iCAsNL,CAAA;EAGJ,wBAAA,CAAA,MAAA,EAAA;IA4BK,cAAA,EAAA,MAAA;EAGP,CAAA,GAzMI,mCAyMJ,CAAA,EAxME,OAwMF,CAxMU,oCAwMV,CAAA;EADE,WAAA,CAAA,MAAA,EA/JM,uBA+JN,CAAA,EA9JA,OA8JA,CA9JQ,wBA8JR,CAAA;EAAO,4BAAA,CAAA,MAAA,EAxID,mCAwIC,GAAA;;MAvIP,QAAQ;;;;;4BAwCF,KAAK;;MAGX,QAAQ;;;;;mBA2DJ,+CAGJ;;;;;;+BA4BK,iCAEL,QACF"}
|
package/rest-client.js
CHANGED
|
@@ -308,7 +308,14 @@ var CossistantRestClient = class {
|
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
310
|
async getConversationSeenData(params) {
|
|
311
|
-
|
|
311
|
+
const storedVisitorId = this.websiteId ? getVisitorId(this.websiteId) : void 0;
|
|
312
|
+
const visitorId = this.visitorId || storedVisitorId;
|
|
313
|
+
const headers = {};
|
|
314
|
+
if (visitorId) headers["X-Visitor-Id"] = visitorId;
|
|
315
|
+
return { seenData: (await this.request(`/conversations/${params.conversationId}/seen`, {
|
|
316
|
+
method: "GET",
|
|
317
|
+
headers
|
|
318
|
+
})).seenData.map((item) => ({
|
|
312
319
|
...item,
|
|
313
320
|
lastSeenAt: item.lastSeenAt,
|
|
314
321
|
createdAt: item.createdAt,
|
|
@@ -337,6 +344,25 @@ var CossistantRestClient = class {
|
|
|
337
344
|
sentAt: response.sentAt
|
|
338
345
|
};
|
|
339
346
|
}
|
|
347
|
+
async submitConversationRating(params) {
|
|
348
|
+
const storedVisitorId = this.websiteId ? getVisitorId(this.websiteId) : void 0;
|
|
349
|
+
const visitorId = params.visitorId || storedVisitorId;
|
|
350
|
+
if (!visitorId) throw new Error("Visitor ID is required to submit a rating");
|
|
351
|
+
const headers = {};
|
|
352
|
+
if (visitorId) headers["X-Visitor-Id"] = visitorId;
|
|
353
|
+
const body = { rating: params.rating };
|
|
354
|
+
if (params.visitorId) body.visitorId = params.visitorId;
|
|
355
|
+
const response = await this.request(`/conversations/${params.conversationId}/rating`, {
|
|
356
|
+
method: "POST",
|
|
357
|
+
body: JSON.stringify(body),
|
|
358
|
+
headers
|
|
359
|
+
});
|
|
360
|
+
return {
|
|
361
|
+
conversationId: response.conversationId,
|
|
362
|
+
rating: response.rating,
|
|
363
|
+
ratedAt: response.ratedAt
|
|
364
|
+
};
|
|
365
|
+
}
|
|
340
366
|
async sendMessage(params) {
|
|
341
367
|
const visitorId = this.websiteId ? getVisitorId(this.websiteId) : void 0;
|
|
342
368
|
const headers = {};
|
package/rest-client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-client.js","names":["headers: Record<string, string>","body: CreateConversationRequestBody","body: MarkConversationSeenRequestBody","body: SetConversationTypingRequestBody","body: GenerateUploadUrlRequest"],"sources":["../src/rest-client.ts"],"sourcesContent":["import type { IdentifyContactResponse } from \"@cossistant/types/api/contact\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tGetConversationSeenDataResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingRequestBody,\n\tSetConversationTypingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n} from \"@cossistant/types/api/timeline-item\";\nimport type {\n\tGenerateUploadUrlRequest,\n\tGenerateUploadUrlResponse,\n} from \"@cossistant/types/api/upload\";\nimport { logger } from \"./logger\";\nimport {\n\tCossistantAPIError,\n\ttype CossistantConfig,\n\ttype PublicWebsiteResponse,\n\ttype UpdateVisitorRequest,\n\ttype VisitorMetadata,\n\ttype VisitorResponse,\n} from \"./types\";\nimport {\n\tisAllowedMimeType,\n\tMAX_FILE_SIZE,\n\tvalidateFile,\n} from \"./upload-constants\";\nimport { generateConversationId } from \"./utils\";\nimport { collectVisitorData } from \"./visitor-data\";\nimport {\n\tgetExistingVisitorId,\n\tgetVisitorId,\n\tsetVisitorId,\n} from \"./visitor-tracker\";\n\nexport class CossistantRestClient {\n\tprivate config: CossistantConfig;\n\tprivate baseHeaders: Record<string, string>;\n\tprivate publicKey: string;\n\tprivate websiteId: string | null = null;\n\tprivate visitorId: string | null = null;\n\tprivate visitorBlocked = false;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\n\t\t// Get public key from config or environment variables\n\t\t// Next.js: NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t// React/other: COSSISTANT_API_KEY\n\t\tthis.publicKey =\n\t\t\tconfig.publicKey ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t\"\";\n\n\t\tif (!this.publicKey) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY (Next.js) or COSSISTANT_API_KEY (React) environment variable.\"\n\t\t\t);\n\t\t}\n\n\t\tthis.baseHeaders = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"X-Public-Key\": this.publicKey,\n\t\t};\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t}\n\t}\n\n\tprivate normalizeVisitorResponse(payload: VisitorResponse): VisitorResponse {\n\t\tconst contact = payload.contact ? payload.contact : null;\n\t\treturn {\n\t\t\t...payload,\n\t\t\t// Ensure latitude and longitude are numbers or null\n\t\t\tlatitude:\n\t\t\t\ttypeof payload.latitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.latitude)\n\t\t\t\t\t: payload.latitude,\n\t\t\tlongitude:\n\t\t\t\ttypeof payload.longitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.longitude)\n\t\t\t\t\t: payload.longitude,\n\t\t\tcreatedAt: payload.createdAt,\n\t\t\tupdatedAt: payload.updatedAt,\n\t\t\tlastSeenAt: payload.lastSeenAt ? payload.lastSeenAt : null,\n\t\t\tblockedAt: payload.blockedAt ? payload.blockedAt : null,\n\t\t\tcontact: payload.contact ? payload.contact : null,\n\t\t};\n\t}\n\n\tprivate resolveVisitorId(): string {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\tthis.visitorId = storedVisitorId;\n\t\t\t\treturn storedVisitorId;\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\"Visitor ID is required\");\n\t}\n\n\tprivate async syncVisitorSnapshot(visitorId: string): Promise<void> {\n\t\ttry {\n\t\t\tconst visitorData = await collectVisitorData();\n\t\t\tif (!visitorData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst payload = Object.entries(visitorData).reduce<\n\t\t\t\tPartial<UpdateVisitorRequest>\n\t\t\t>((acc, [key, value]) => {\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\t(acc as Record<string, unknown>)[key] = value;\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.request<VisitorResponse>(`/visitors/${visitorId}`, {\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlogger.warn(\"Failed to sync visitor data\", error);\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tpath: string,\n\t\toptions: RequestInit = {}\n\t): Promise<T> {\n\t\tif (this.visitorBlocked) {\n\t\t\tconst method = (options.method ?? \"GET\").toUpperCase();\n\t\t\tconst [rawPath] = path.split(\"?\");\n\t\t\tconst normalizedPath = rawPath?.endsWith(\"/\")\n\t\t\t\t? rawPath.slice(0, -1)\n\t\t\t\t: rawPath;\n\t\t\tconst isWebsitesRoot = normalizedPath === \"/websites\";\n\t\t\tconst isSafeMethod = method === \"GET\" || method === \"HEAD\";\n\n\t\t\tif (!(isWebsitesRoot && isSafeMethod)) {\n\t\t\t\tthrow new CossistantAPIError({\n\t\t\t\t\tcode: \"VISITOR_BLOCKED\",\n\t\t\t\t\tmessage: \"Visitor is blocked and cannot perform this action.\",\n\t\t\t\t\tdetails: { path, method },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst url = `${this.config.apiUrl}${path}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t...this.baseHeaders,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorData = await response.json().catch(() => ({}));\n\t\t\tconst statusCode = response.status;\n\t\t\tconst errorCode = errorData.code || `HTTP_${statusCode}`;\n\t\t\tconst serverMessage = errorData.message;\n\n\t\t\t// Determine if this is an authentication/authorization error\n\t\t\tconst isAuthError =\n\t\t\t\tstatusCode === 401 ||\n\t\t\t\tstatusCode === 403 ||\n\t\t\t\terrorCode === \"UNAUTHORIZED\" ||\n\t\t\t\terrorCode === \"FORBIDDEN\" ||\n\t\t\t\terrorCode === \"INVALID_API_KEY\" ||\n\t\t\t\terrorCode === \"API_KEY_EXPIRED\" ||\n\t\t\t\terrorCode === \"API_KEY_MISSING\" ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"AUTH\") ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"API_KEY\");\n\n\t\t\t// Use appropriate error message based on error type\n\t\t\tconst errorMessage = isAuthError\n\t\t\t\t? \"Your Cossistant public API key is invalid, expired, missing or not authorized to access this resource.\"\n\t\t\t\t: serverMessage || `Request failed with status ${statusCode}`;\n\n\t\t\t// Log with appropriate level based on error type\n\t\t\tif (isAuthError) {\n\t\t\t\tlogger.error(errorMessage, {\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlogger.error(\"API request failed\", {\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow new CossistantAPIError({\n\t\t\t\tcode: errorCode,\n\t\t\t\tmessage: errorMessage,\n\t\t\t\tdetails: errorData.details,\n\t\t\t});\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\t// Make the request with visitor ID if we have one stored\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// First, check if we already know the website ID and have a visitor ID for it\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = storedVisitorId;\n\t\t\t}\n\t\t} else {\n\t\t\t// We don't know the website ID yet, but check if we have any existing visitor\n\t\t\t// This prevents creating duplicate visitors on page refresh\n\t\t\tconst existingVisitor = getExistingVisitorId(this.publicKey);\n\t\t\tif (existingVisitor) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = existingVisitor.visitorId;\n\t\t\t\t// Pre-populate our local state\n\t\t\t\tthis.websiteId = existingVisitor.websiteId;\n\t\t\t\tthis.visitorId = existingVisitor.visitorId;\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.request<PublicWebsiteResponse>(\"/websites\", {\n\t\t\theaders,\n\t\t});\n\n\t\t// Store the website ID for future requests\n\t\tthis.websiteId = response.id;\n\n\t\t// Store the visitor ID if we got one\n\t\tthis.visitorBlocked = response.visitor?.isBlocked ?? false;\n\n\t\tif (response.visitor?.id) {\n\t\t\tif (this.visitorBlocked) {\n\t\t\t\tthis.visitorId = response.visitor.id;\n\t\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tthis.visitorId = response.visitor.id;\n\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\tthis.syncVisitorSnapshot(response.visitor.id);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t// Manually prime website and visitor context when the caller already has it\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.websiteId = websiteId;\n\t\tif (visitorId) {\n\t\t\tthis.visitorId = visitorId;\n\t\t\tsetVisitorId(websiteId, visitorId);\n\t\t}\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.visitorBlocked = isBlocked;\n\t}\n\n\tgetCurrentWebsiteId(): string | null {\n\t\treturn this.websiteId;\n\t}\n\n\tgetCurrentVisitorId(): string | null {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (!this.websiteId) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn getVisitorId(this.websiteId) ?? null;\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\t\tconst response = await this.request<VisitorResponse>(\n\t\t\t`/visitors/${visitorId}/metadata`,\n\t\t\t{\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify({ metadata }),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn this.normalizeVisitorResponse(response);\n\t}\n\n\t/**\n\t * Identify a visitor by creating or updating their contact information\n\t * This will link the visitor to a contact record that can be tracked across devices\n\t */\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\tconst response = await this.request<IdentifyContactResponse>(\n\t\t\t\"/contacts/identify\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tvisitorId,\n\t\t\t\t\t...params,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tcontact: {\n\t\t\t\t...response.contact,\n\t\t\t\t// Ensure metadata is properly typed\n\t\t\t\tmetadata:\n\t\t\t\t\ttypeof response.contact.metadata === \"string\"\n\t\t\t\t\t\t? JSON.parse(response.contact.metadata)\n\t\t\t\t\t\t: response.contact.metadata,\n\t\t\t\tcreatedAt: response.contact.createdAt,\n\t\t\t\tupdatedAt: response.contact.updatedAt,\n\t\t\t},\n\t\t\tvisitorId: response.visitorId,\n\t\t};\n\t}\n\n\t/**\n\t * Update metadata for the contact associated with the current visitor\n\t * Note: The visitor must be identified first via the identify() method\n\t */\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\t// This still uses the visitor metadata endpoint for backward compatibility\n\t\t// The endpoint will internally update the contact metadata\n\t\treturn this.updateVisitorMetadata(metadata as VisitorMetadata);\n\t}\n\n\tasync createConversation(\n\t\tparams: Partial<CreateConversationRequestBody> = {}\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst conversationId = params.conversationId || generateConversationId();\n\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\tconst body: CreateConversationRequestBody = {\n\t\t\tconversationId,\n\t\t\tvisitorId,\n\t\t\tdefaultTimelineItems: params.defaultTimelineItems || [],\n\t\t\tchannel: params.channel || \"widget\",\n\t\t};\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<CreateConversationResponseBody>(\n\t\t\t\"/conversations\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t};\n\t}\n\n\tasync updateConfiguration(config: Partial<CossistantConfig>): Promise<void> {\n\t\tif (config.publicKey) {\n\t\t\tthis.publicKey = config.publicKey;\n\t\t\tthis.baseHeaders[\"X-Public-Key\"] = config.publicKey;\n\t\t}\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t} else if (config.userId === null) {\n\t\t\tconst { \"X-User-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t} else if (config.organizationId === null) {\n\t\t\tconst { \"X-Organization-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tthis.config = { ...this.config, ...config };\n\t}\n\n\tasync listConversations(\n\t\tparams: Partial<ListConversationsRequest> = {}\n\t): Promise<ListConversationsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (visitorId) {\n\t\t\tqueryParams.set(\"visitorId\", visitorId);\n\t\t}\n\n\t\tif (params.page) {\n\t\t\tqueryParams.set(\"page\", params.page.toString());\n\t\t}\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.status) {\n\t\t\tqueryParams.set(\"status\", params.status);\n\t\t}\n\n\t\tif (params.orderBy) {\n\t\t\tqueryParams.set(\"orderBy\", params.orderBy);\n\t\t}\n\n\t\tif (params.order) {\n\t\t\tqueryParams.set(\"order\", params.order);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<ListConversationsResponse>(\n\t\t\t`/conversations?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversations: response.conversations.map((conv) => ({\n\t\t\t\t...conv,\n\t\t\t\tcreatedAt: conv.createdAt,\n\t\t\t\tupdatedAt: conv.updatedAt,\n\t\t\t\tdeletedAt: conv.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: conv.lastTimelineItem,\n\t\t\t})),\n\t\t\tpagination: response.pagination,\n\t\t};\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationResponse>(\n\t\t\t`/conversations/${params.conversationId}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to mark a conversation as seen\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: MarkConversationSeenRequestBody = {};\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tconst response = await this.request<MarkConversationSeenResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tlastSeenAt: response.lastSeenAt,\n\t\t};\n\t}\n\n\tasync getConversationSeenData(params: {\n\t\tconversationId: string;\n\t}): Promise<GetConversationSeenDataResponse> {\n\t\tconst response = await this.request<GetConversationSeenDataResponse>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tseenData: response.seenData.map((item) => ({\n\t\t\t\t...item,\n\t\t\t\tlastSeenAt: item.lastSeenAt,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tdeletedAt: item.deletedAt ? item.deletedAt : null,\n\t\t\t})),\n\t\t};\n\t}\n\n\tasync setConversationTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to report typing state\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: SetConversationTypingRequestBody = {\n\t\t\tisTyping: params.isTyping,\n\t\t};\n\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tif (params.visitorPreview && params.isTyping) {\n\t\t\tbody.visitorPreview = params.visitorPreview.slice(0, 2000);\n\t\t}\n\n\t\tconst response = await this.request<SetConversationTypingResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/typing`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tisTyping: response.isTyping,\n\t\t\tvisitorPreview: response.visitorPreview,\n\t\t\tsentAt: response.sentAt,\n\t\t};\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest\n\t): Promise<SendTimelineItemResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<SendTimelineItemResponse>(\"/messages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(params),\n\t\t\theaders,\n\t\t});\n\n\t\treturn {\n\t\t\titem: response.item,\n\t\t};\n\t}\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.cursor) {\n\t\t\tqueryParams.set(\"cursor\", params.cursor);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationTimelineItemsResponse>(\n\t\t\t`/conversations/${params.conversationId}/timeline?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\titems: response.items,\n\t\t\tnextCursor: response.nextCursor,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t};\n\t}\n\n\t/**\n\t * Generate a presigned URL for uploading a file to S3.\n\t * The URL can be used to PUT a file directly to S3.\n\t */\n\tasync generateUploadUrl(\n\t\tparams: Omit<GenerateUploadUrlRequest, \"websiteId\" | \"scope\"> & {\n\t\t\tconversationId: string;\n\t\t}\n\t): Promise<GenerateUploadUrlResponse> {\n\t\tif (!this.websiteId) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Website ID is required. Call getWebsite() first to initialize the client.\"\n\t\t\t);\n\t\t}\n\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\t// Validate file constraints on client side\n\t\tif (!isAllowedMimeType(params.contentType)) {\n\t\t\tthrow new Error(`File type \"${params.contentType}\" is not allowed`);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\t// Get organization ID from website response (stored during getWebsite)\n\t\t// For now, we'll make an additional call to get website info\n\t\tconst websiteResponse = await this.request<{ organizationId: string }>(\n\t\t\t\"/websites\",\n\t\t\t{ headers }\n\t\t);\n\n\t\tconst body: GenerateUploadUrlRequest = {\n\t\t\tcontentType: params.contentType,\n\t\t\twebsiteId: this.websiteId,\n\t\t\tscope: {\n\t\t\t\ttype: \"conversation\",\n\t\t\t\torganizationId: websiteResponse.organizationId,\n\t\t\t\twebsiteId: this.websiteId,\n\t\t\t\tconversationId: params.conversationId,\n\t\t\t},\n\t\t\tfileName: params.fileName,\n\t\t\tfileExtension: params.fileExtension,\n\t\t\tpath: params.path,\n\t\t\tuseCdn: false, // Files should not go to CDN\n\t\t\texpiresInSeconds: params.expiresInSeconds,\n\t\t};\n\n\t\tconst response = await this.request<GenerateUploadUrlResponse>(\n\t\t\t\"/uploads/sign-url\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Upload a file to S3 using a presigned URL.\n\t * @returns The public URL of the uploaded file\n\t */\n\tasync uploadFile(\n\t\tfile: File,\n\t\tuploadUrl: string,\n\t\tcontentType: string\n\t): Promise<void> {\n\t\t// Validate file before upload\n\t\tconst validationError = validateFile(file);\n\t\tif (validationError) {\n\t\t\tthrow new Error(validationError);\n\t\t}\n\n\t\tconst response = await fetch(uploadUrl, {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: file,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to upload file: ${response.status} ${response.statusText}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Upload multiple files for a conversation message.\n\t * Files are uploaded in parallel and the function returns timeline parts\n\t * that can be included in a message.\n\t */\n\tasync uploadFilesForMessage(\n\t\tfiles: File[],\n\t\tconversationId: string\n\t): Promise<\n\t\tArray<\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\turl: string;\n\t\t\t\t\tmediaType: string;\n\t\t\t\t\tfileName?: string;\n\t\t\t\t\tsize?: number;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\ttype: \"file\";\n\t\t\t\t\turl: string;\n\t\t\t\t\tmediaType: string;\n\t\t\t\t\tfileName?: string;\n\t\t\t\t\tsize?: number;\n\t\t\t }\n\t\t>\n\t> {\n\t\tif (files.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Validate all files first\n\t\tfor (const file of files) {\n\t\t\tconst error = validateFile(file);\n\t\t\tif (error) {\n\t\t\t\tthrow new Error(error);\n\t\t\t}\n\t\t}\n\n\t\t// Upload files in parallel\n\t\tconst uploadPromises = files.map(async (file) => {\n\t\t\t// Generate presigned URL\n\t\t\tconst uploadInfo = await this.generateUploadUrl({\n\t\t\t\tconversationId,\n\t\t\t\tcontentType: file.type,\n\t\t\t\tfileName: file.name,\n\t\t\t});\n\n\t\t\t// Upload file to S3\n\t\t\tawait this.uploadFile(file, uploadInfo.uploadUrl, file.type);\n\n\t\t\t// Return timeline part based on file type\n\t\t\tconst isImage = file.type.startsWith(\"image/\");\n\t\t\treturn {\n\t\t\t\ttype: isImage ? (\"image\" as const) : (\"file\" as const),\n\t\t\t\turl: uploadInfo.publicUrl,\n\t\t\t\tmediaType: file.type,\n\t\t\t\tfileName: file.name,\n\t\t\t\tsize: file.size,\n\t\t\t};\n\t\t});\n\n\t\treturn Promise.all(uploadPromises);\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rest-client.js","names":["headers: Record<string, string>","body: CreateConversationRequestBody","body: MarkConversationSeenRequestBody","body: SetConversationTypingRequestBody","body: SubmitConversationRatingRequestBody","body: GenerateUploadUrlRequest"],"sources":["../src/rest-client.ts"],"sourcesContent":["import type { IdentifyContactResponse } from \"@cossistant/types/api/contact\";\nimport type {\n\tCreateConversationRequestBody,\n\tCreateConversationResponseBody,\n\tGetConversationRequest,\n\tGetConversationResponse,\n\tGetConversationSeenDataResponse,\n\tListConversationsRequest,\n\tListConversationsResponse,\n\tMarkConversationSeenRequestBody,\n\tMarkConversationSeenResponseBody,\n\tSetConversationTypingRequestBody,\n\tSetConversationTypingResponseBody,\n\tSubmitConversationRatingRequestBody,\n\tSubmitConversationRatingResponseBody,\n} from \"@cossistant/types/api/conversation\";\nimport type {\n\tGetConversationTimelineItemsRequest,\n\tGetConversationTimelineItemsResponse,\n\tSendTimelineItemRequest,\n\tSendTimelineItemResponse,\n} from \"@cossistant/types/api/timeline-item\";\nimport type {\n\tGenerateUploadUrlRequest,\n\tGenerateUploadUrlResponse,\n} from \"@cossistant/types/api/upload\";\nimport { logger } from \"./logger\";\nimport {\n\tCossistantAPIError,\n\ttype CossistantConfig,\n\ttype PublicWebsiteResponse,\n\ttype UpdateVisitorRequest,\n\ttype VisitorMetadata,\n\ttype VisitorResponse,\n} from \"./types\";\nimport {\n\tisAllowedMimeType,\n\tMAX_FILE_SIZE,\n\tvalidateFile,\n} from \"./upload-constants\";\nimport { generateConversationId } from \"./utils\";\nimport { collectVisitorData } from \"./visitor-data\";\nimport {\n\tgetExistingVisitorId,\n\tgetVisitorId,\n\tsetVisitorId,\n} from \"./visitor-tracker\";\n\nexport class CossistantRestClient {\n\tprivate config: CossistantConfig;\n\tprivate baseHeaders: Record<string, string>;\n\tprivate publicKey: string;\n\tprivate websiteId: string | null = null;\n\tprivate visitorId: string | null = null;\n\tprivate visitorBlocked = false;\n\n\tconstructor(config: CossistantConfig) {\n\t\tthis.config = config;\n\n\t\t// Get public key from config or environment variables\n\t\t// Next.js: NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t// React/other: COSSISTANT_API_KEY\n\t\tthis.publicKey =\n\t\t\tconfig.publicKey ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t(typeof process !== \"undefined\"\n\t\t\t\t? process.env.COSSISTANT_API_KEY\n\t\t\t\t: undefined) ||\n\t\t\t\"\";\n\n\t\tif (!this.publicKey) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY (Next.js) or COSSISTANT_API_KEY (React) environment variable.\"\n\t\t\t);\n\t\t}\n\n\t\tthis.baseHeaders = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"X-Public-Key\": this.publicKey,\n\t\t};\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t}\n\t}\n\n\tprivate normalizeVisitorResponse(payload: VisitorResponse): VisitorResponse {\n\t\tconst contact = payload.contact ? payload.contact : null;\n\t\treturn {\n\t\t\t...payload,\n\t\t\t// Ensure latitude and longitude are numbers or null\n\t\t\tlatitude:\n\t\t\t\ttypeof payload.latitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.latitude)\n\t\t\t\t\t: payload.latitude,\n\t\t\tlongitude:\n\t\t\t\ttypeof payload.longitude === \"string\"\n\t\t\t\t\t? Number.parseFloat(payload.longitude)\n\t\t\t\t\t: payload.longitude,\n\t\t\tcreatedAt: payload.createdAt,\n\t\t\tupdatedAt: payload.updatedAt,\n\t\t\tlastSeenAt: payload.lastSeenAt ? payload.lastSeenAt : null,\n\t\t\tblockedAt: payload.blockedAt ? payload.blockedAt : null,\n\t\t\tcontact: payload.contact ? payload.contact : null,\n\t\t};\n\t}\n\n\tprivate resolveVisitorId(): string {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\tthis.visitorId = storedVisitorId;\n\t\t\t\treturn storedVisitorId;\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\"Visitor ID is required\");\n\t}\n\n\tprivate async syncVisitorSnapshot(visitorId: string): Promise<void> {\n\t\ttry {\n\t\t\tconst visitorData = await collectVisitorData();\n\t\t\tif (!visitorData) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst payload = Object.entries(visitorData).reduce<\n\t\t\t\tPartial<UpdateVisitorRequest>\n\t\t\t>((acc, [key, value]) => {\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\treturn acc;\n\t\t\t\t}\n\t\t\t\t(acc as Record<string, unknown>)[key] = value;\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.request<VisitorResponse>(`/visitors/${visitorId}`, {\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tlogger.warn(\"Failed to sync visitor data\", error);\n\t\t}\n\t}\n\n\tprivate async request<T>(\n\t\tpath: string,\n\t\toptions: RequestInit = {}\n\t): Promise<T> {\n\t\tif (this.visitorBlocked) {\n\t\t\tconst method = (options.method ?? \"GET\").toUpperCase();\n\t\t\tconst [rawPath] = path.split(\"?\");\n\t\t\tconst normalizedPath = rawPath?.endsWith(\"/\")\n\t\t\t\t? rawPath.slice(0, -1)\n\t\t\t\t: rawPath;\n\t\t\tconst isWebsitesRoot = normalizedPath === \"/websites\";\n\t\t\tconst isSafeMethod = method === \"GET\" || method === \"HEAD\";\n\n\t\t\tif (!(isWebsitesRoot && isSafeMethod)) {\n\t\t\t\tthrow new CossistantAPIError({\n\t\t\t\t\tcode: \"VISITOR_BLOCKED\",\n\t\t\t\t\tmessage: \"Visitor is blocked and cannot perform this action.\",\n\t\t\t\t\tdetails: { path, method },\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tconst url = `${this.config.apiUrl}${path}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\t...options,\n\t\t\theaders: {\n\t\t\t\t...this.baseHeaders,\n\t\t\t\t...options.headers,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst errorData = await response.json().catch(() => ({}));\n\t\t\tconst statusCode = response.status;\n\t\t\tconst errorCode = errorData.code || `HTTP_${statusCode}`;\n\t\t\tconst serverMessage = errorData.message;\n\n\t\t\t// Determine if this is an authentication/authorization error\n\t\t\tconst isAuthError =\n\t\t\t\tstatusCode === 401 ||\n\t\t\t\tstatusCode === 403 ||\n\t\t\t\terrorCode === \"UNAUTHORIZED\" ||\n\t\t\t\terrorCode === \"FORBIDDEN\" ||\n\t\t\t\terrorCode === \"INVALID_API_KEY\" ||\n\t\t\t\terrorCode === \"API_KEY_EXPIRED\" ||\n\t\t\t\terrorCode === \"API_KEY_MISSING\" ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"AUTH\") ||\n\t\t\t\terrorCode?.toUpperCase().includes(\"API_KEY\");\n\n\t\t\t// Use appropriate error message based on error type\n\t\t\tconst errorMessage = isAuthError\n\t\t\t\t? \"Your Cossistant public API key is invalid, expired, missing or not authorized to access this resource.\"\n\t\t\t\t: serverMessage || `Request failed with status ${statusCode}`;\n\n\t\t\t// Log with appropriate level based on error type\n\t\t\tif (isAuthError) {\n\t\t\t\tlogger.error(errorMessage, {\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tlogger.error(\"API request failed\", {\n\t\t\t\t\tmessage: errorMessage,\n\t\t\t\t\tdetails: errorData.details,\n\t\t\t\t\tpath,\n\t\t\t\t\tstatus: statusCode,\n\t\t\t\t\tcode: errorCode,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow new CossistantAPIError({\n\t\t\t\tcode: errorCode,\n\t\t\t\tmessage: errorMessage,\n\t\t\t\tdetails: errorData.details,\n\t\t\t});\n\t\t}\n\n\t\treturn response.json();\n\t}\n\n\tasync getWebsite(): Promise<PublicWebsiteResponse> {\n\t\t// Make the request with visitor ID if we have one stored\n\t\tconst headers: Record<string, string> = {};\n\n\t\t// First, check if we already know the website ID and have a visitor ID for it\n\t\tif (this.websiteId) {\n\t\t\tconst storedVisitorId = getVisitorId(this.websiteId);\n\t\t\tif (storedVisitorId) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = storedVisitorId;\n\t\t\t}\n\t\t} else {\n\t\t\t// We don't know the website ID yet, but check if we have any existing visitor\n\t\t\t// This prevents creating duplicate visitors on page refresh\n\t\t\tconst existingVisitor = getExistingVisitorId(this.publicKey);\n\t\t\tif (existingVisitor) {\n\t\t\t\theaders[\"X-Visitor-Id\"] = existingVisitor.visitorId;\n\t\t\t\t// Pre-populate our local state\n\t\t\t\tthis.websiteId = existingVisitor.websiteId;\n\t\t\t\tthis.visitorId = existingVisitor.visitorId;\n\t\t\t}\n\t\t}\n\n\t\tconst response = await this.request<PublicWebsiteResponse>(\"/websites\", {\n\t\t\theaders,\n\t\t});\n\n\t\t// Store the website ID for future requests\n\t\tthis.websiteId = response.id;\n\n\t\t// Store the visitor ID if we got one\n\t\tthis.visitorBlocked = response.visitor?.isBlocked ?? false;\n\n\t\tif (response.visitor?.id) {\n\t\t\tif (this.visitorBlocked) {\n\t\t\t\tthis.visitorId = response.visitor.id;\n\t\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\t\treturn response;\n\t\t\t}\n\n\t\t\tthis.visitorId = response.visitor.id;\n\t\t\tsetVisitorId(response.id, response.visitor.id);\n\t\t\tthis.syncVisitorSnapshot(response.visitor.id);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\t// Manually prime website and visitor context when the caller already has it\n\tsetWebsiteContext(websiteId: string, visitorId?: string): void {\n\t\tthis.websiteId = websiteId;\n\t\tif (visitorId) {\n\t\t\tthis.visitorId = visitorId;\n\t\t\tsetVisitorId(websiteId, visitorId);\n\t\t}\n\t}\n\n\tsetVisitorBlocked(isBlocked: boolean): void {\n\t\tthis.visitorBlocked = isBlocked;\n\t}\n\n\tgetCurrentWebsiteId(): string | null {\n\t\treturn this.websiteId;\n\t}\n\n\tgetCurrentVisitorId(): string | null {\n\t\tif (this.visitorId) {\n\t\t\treturn this.visitorId;\n\t\t}\n\n\t\tif (!this.websiteId) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn getVisitorId(this.websiteId) ?? null;\n\t}\n\n\tasync updateVisitorMetadata(\n\t\tmetadata: VisitorMetadata\n\t): Promise<VisitorResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\t\tconst response = await this.request<VisitorResponse>(\n\t\t\t`/visitors/${visitorId}/metadata`,\n\t\t\t{\n\t\t\t\tmethod: \"PATCH\",\n\t\t\t\tbody: JSON.stringify({ metadata }),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn this.normalizeVisitorResponse(response);\n\t}\n\n\t/**\n\t * Identify a visitor by creating or updating their contact information\n\t * This will link the visitor to a contact record that can be tracked across devices\n\t */\n\tasync identify(params: {\n\t\texternalId?: string;\n\t\temail?: string;\n\t\tname?: string;\n\t\timage?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t\tcontactOrganizationId?: string;\n\t}): Promise<IdentifyContactResponse> {\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\tconst response = await this.request<IdentifyContactResponse>(\n\t\t\t\"/contacts/identify\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tvisitorId,\n\t\t\t\t\t...params,\n\t\t\t\t}),\n\t\t\t\theaders: {\n\t\t\t\t\t\"X-Visitor-Id\": visitorId,\n\t\t\t\t},\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tcontact: {\n\t\t\t\t...response.contact,\n\t\t\t\t// Ensure metadata is properly typed\n\t\t\t\tmetadata:\n\t\t\t\t\ttypeof response.contact.metadata === \"string\"\n\t\t\t\t\t\t? JSON.parse(response.contact.metadata)\n\t\t\t\t\t\t: response.contact.metadata,\n\t\t\t\tcreatedAt: response.contact.createdAt,\n\t\t\t\tupdatedAt: response.contact.updatedAt,\n\t\t\t},\n\t\t\tvisitorId: response.visitorId,\n\t\t};\n\t}\n\n\t/**\n\t * Update metadata for the contact associated with the current visitor\n\t * Note: The visitor must be identified first via the identify() method\n\t */\n\tasync updateContactMetadata(\n\t\tmetadata: Record<string, unknown>\n\t): Promise<VisitorResponse> {\n\t\t// This still uses the visitor metadata endpoint for backward compatibility\n\t\t// The endpoint will internally update the contact metadata\n\t\treturn this.updateVisitorMetadata(metadata as VisitorMetadata);\n\t}\n\n\tasync createConversation(\n\t\tparams: Partial<CreateConversationRequestBody> = {}\n\t): Promise<CreateConversationResponseBody> {\n\t\tconst conversationId = params.conversationId || generateConversationId();\n\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\tconst body: CreateConversationRequestBody = {\n\t\t\tconversationId,\n\t\t\tvisitorId,\n\t\t\tdefaultTimelineItems: params.defaultTimelineItems || [],\n\t\t\tchannel: params.channel || \"widget\",\n\t\t};\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<CreateConversationResponseBody>(\n\t\t\t\"/conversations\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t\tinitialTimelineItems: response.initialTimelineItems,\n\t\t};\n\t}\n\n\tasync updateConfiguration(config: Partial<CossistantConfig>): Promise<void> {\n\t\tif (config.publicKey) {\n\t\t\tthis.publicKey = config.publicKey;\n\t\t\tthis.baseHeaders[\"X-Public-Key\"] = config.publicKey;\n\t\t}\n\n\t\tif (config.userId) {\n\t\t\tthis.baseHeaders[\"X-User-ID\"] = config.userId;\n\t\t} else if (config.userId === null) {\n\t\t\tconst { \"X-User-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tif (config.organizationId) {\n\t\t\tthis.baseHeaders[\"X-Organization-ID\"] = config.organizationId;\n\t\t} else if (config.organizationId === null) {\n\t\t\tconst { \"X-Organization-ID\": _, ...rest } = this.baseHeaders;\n\t\t\tthis.baseHeaders = rest;\n\t\t}\n\n\t\tthis.config = { ...this.config, ...config };\n\t}\n\n\tasync listConversations(\n\t\tparams: Partial<ListConversationsRequest> = {}\n\t): Promise<ListConversationsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID, or use the provided one\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required\");\n\t\t}\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (visitorId) {\n\t\t\tqueryParams.set(\"visitorId\", visitorId);\n\t\t}\n\n\t\tif (params.page) {\n\t\t\tqueryParams.set(\"page\", params.page.toString());\n\t\t}\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.status) {\n\t\t\tqueryParams.set(\"status\", params.status);\n\t\t}\n\n\t\tif (params.orderBy) {\n\t\t\tqueryParams.set(\"orderBy\", params.orderBy);\n\t\t}\n\n\t\tif (params.order) {\n\t\t\tqueryParams.set(\"order\", params.order);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<ListConversationsResponse>(\n\t\t\t`/conversations?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversations: response.conversations.map((conv) => ({\n\t\t\t\t...conv,\n\t\t\t\tcreatedAt: conv.createdAt,\n\t\t\t\tupdatedAt: conv.updatedAt,\n\t\t\t\tdeletedAt: conv.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: conv.lastTimelineItem,\n\t\t\t})),\n\t\t\tpagination: response.pagination,\n\t\t};\n\t}\n\n\tasync getConversation(\n\t\tparams: GetConversationRequest\n\t): Promise<GetConversationResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationResponse>(\n\t\t\t`/conversations/${params.conversationId}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\t// Convert date strings to Date objects\n\t\treturn {\n\t\t\tconversation: {\n\t\t\t\t...response.conversation,\n\t\t\t\tcreatedAt: response.conversation.createdAt,\n\t\t\t\tupdatedAt: response.conversation.updatedAt,\n\t\t\t\tdeletedAt: response.conversation.deletedAt ?? null,\n\t\t\t\tlastTimelineItem: response.conversation.lastTimelineItem,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync markConversationSeen(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & Partial<MarkConversationSeenRequestBody>\n\t): Promise<MarkConversationSeenResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to mark a conversation as seen\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: MarkConversationSeenRequestBody = {};\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tconst response = await this.request<MarkConversationSeenResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tlastSeenAt: response.lastSeenAt,\n\t\t};\n\t}\n\n\tasync getConversationSeenData(params: {\n\t\tconversationId: string;\n\t}): Promise<GetConversationSeenDataResponse> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = this.visitorId || storedVisitorId;\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationSeenDataResponse>(\n\t\t\t`/conversations/${params.conversationId}/seen`,\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tseenData: response.seenData.map((item) => ({\n\t\t\t\t...item,\n\t\t\t\tlastSeenAt: item.lastSeenAt,\n\t\t\t\tcreatedAt: item.createdAt,\n\t\t\t\tupdatedAt: item.updatedAt,\n\t\t\t\tdeletedAt: item.deletedAt ? item.deletedAt : null,\n\t\t\t})),\n\t\t};\n\t}\n\n\tasync setConversationTyping(params: {\n\t\tconversationId: string;\n\t\tisTyping: boolean;\n\t\tvisitorPreview?: string | null;\n\t\tvisitorId?: string;\n\t}): Promise<SetConversationTypingResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to report typing state\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: SetConversationTypingRequestBody = {\n\t\t\tisTyping: params.isTyping,\n\t\t};\n\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tif (params.visitorPreview && params.isTyping) {\n\t\t\tbody.visitorPreview = params.visitorPreview.slice(0, 2000);\n\t\t}\n\n\t\tconst response = await this.request<SetConversationTypingResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/typing`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\tisTyping: response.isTyping,\n\t\t\tvisitorPreview: response.visitorPreview,\n\t\t\tsentAt: response.sentAt,\n\t\t};\n\t}\n\n\tasync submitConversationRating(\n\t\tparams: {\n\t\t\tconversationId: string;\n\t\t} & SubmitConversationRatingRequestBody\n\t): Promise<SubmitConversationRatingResponseBody> {\n\t\tconst storedVisitorId = this.websiteId\n\t\t\t? getVisitorId(this.websiteId)\n\t\t\t: undefined;\n\t\tconst visitorId = params.visitorId || storedVisitorId;\n\n\t\tif (!visitorId) {\n\t\t\tthrow new Error(\"Visitor ID is required to submit a rating\");\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst body: SubmitConversationRatingRequestBody = {\n\t\t\trating: params.rating,\n\t\t};\n\n\t\tif (params.visitorId) {\n\t\t\tbody.visitorId = params.visitorId;\n\t\t}\n\n\t\tconst response = await this.request<SubmitConversationRatingResponseBody>(\n\t\t\t`/conversations/${params.conversationId}/rating`,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\tconversationId: response.conversationId,\n\t\t\trating: response.rating,\n\t\t\tratedAt: response.ratedAt,\n\t\t};\n\t}\n\n\tasync sendMessage(\n\t\tparams: SendTimelineItemRequest\n\t): Promise<SendTimelineItemResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<SendTimelineItemResponse>(\"/messages\", {\n\t\t\tmethod: \"POST\",\n\t\t\tbody: JSON.stringify(params),\n\t\t\theaders,\n\t\t});\n\n\t\treturn {\n\t\t\titem: response.item,\n\t\t};\n\t}\n\n\tasync getConversationTimelineItems(\n\t\tparams: GetConversationTimelineItemsRequest & { conversationId: string }\n\t): Promise<GetConversationTimelineItemsResponse> {\n\t\t// Get visitor ID from storage if we have the website ID\n\t\tconst visitorId = this.websiteId ? getVisitorId(this.websiteId) : undefined;\n\n\t\t// Create query parameters\n\t\tconst queryParams = new URLSearchParams();\n\n\t\tif (params.limit) {\n\t\t\tqueryParams.set(\"limit\", params.limit.toString());\n\t\t}\n\n\t\tif (params.cursor) {\n\t\t\tqueryParams.set(\"cursor\", params.cursor);\n\t\t}\n\n\t\t// Add visitor ID header if available\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\tconst response = await this.request<GetConversationTimelineItemsResponse>(\n\t\t\t`/conversations/${params.conversationId}/timeline?${queryParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn {\n\t\t\titems: response.items,\n\t\t\tnextCursor: response.nextCursor,\n\t\t\thasNextPage: response.hasNextPage,\n\t\t};\n\t}\n\n\t/**\n\t * Generate a presigned URL for uploading a file to S3.\n\t * The URL can be used to PUT a file directly to S3.\n\t */\n\tasync generateUploadUrl(\n\t\tparams: Omit<GenerateUploadUrlRequest, \"websiteId\" | \"scope\"> & {\n\t\t\tconversationId: string;\n\t\t}\n\t): Promise<GenerateUploadUrlResponse> {\n\t\tif (!this.websiteId) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Website ID is required. Call getWebsite() first to initialize the client.\"\n\t\t\t);\n\t\t}\n\n\t\tconst visitorId = this.resolveVisitorId();\n\n\t\t// Validate file constraints on client side\n\t\tif (!isAllowedMimeType(params.contentType)) {\n\t\t\tthrow new Error(`File type \"${params.contentType}\" is not allowed`);\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (visitorId) {\n\t\t\theaders[\"X-Visitor-Id\"] = visitorId;\n\t\t}\n\n\t\t// Get organization ID from website response (stored during getWebsite)\n\t\t// For now, we'll make an additional call to get website info\n\t\tconst websiteResponse = await this.request<{ organizationId: string }>(\n\t\t\t\"/websites\",\n\t\t\t{ headers }\n\t\t);\n\n\t\tconst body: GenerateUploadUrlRequest = {\n\t\t\tcontentType: params.contentType,\n\t\t\twebsiteId: this.websiteId,\n\t\t\tscope: {\n\t\t\t\ttype: \"conversation\",\n\t\t\t\torganizationId: websiteResponse.organizationId,\n\t\t\t\twebsiteId: this.websiteId,\n\t\t\t\tconversationId: params.conversationId,\n\t\t\t},\n\t\t\tfileName: params.fileName,\n\t\t\tfileExtension: params.fileExtension,\n\t\t\tpath: params.path,\n\t\t\tuseCdn: false, // Files should not go to CDN\n\t\t\texpiresInSeconds: params.expiresInSeconds,\n\t\t};\n\n\t\tconst response = await this.request<GenerateUploadUrlResponse>(\n\t\t\t\"/uploads/sign-url\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\theaders,\n\t\t\t}\n\t\t);\n\n\t\treturn response;\n\t}\n\n\t/**\n\t * Upload a file to S3 using a presigned URL.\n\t * @returns The public URL of the uploaded file\n\t */\n\tasync uploadFile(\n\t\tfile: File,\n\t\tuploadUrl: string,\n\t\tcontentType: string\n\t): Promise<void> {\n\t\t// Validate file before upload\n\t\tconst validationError = validateFile(file);\n\t\tif (validationError) {\n\t\t\tthrow new Error(validationError);\n\t\t}\n\n\t\tconst response = await fetch(uploadUrl, {\n\t\t\tmethod: \"PUT\",\n\t\t\tbody: file,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": contentType,\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to upload file: ${response.status} ${response.statusText}`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Upload multiple files for a conversation message.\n\t * Files are uploaded in parallel and the function returns timeline parts\n\t * that can be included in a message.\n\t */\n\tasync uploadFilesForMessage(\n\t\tfiles: File[],\n\t\tconversationId: string\n\t): Promise<\n\t\tArray<\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\turl: string;\n\t\t\t\t\tmediaType: string;\n\t\t\t\t\tfileName?: string;\n\t\t\t\t\tsize?: number;\n\t\t\t }\n\t\t\t| {\n\t\t\t\t\ttype: \"file\";\n\t\t\t\t\turl: string;\n\t\t\t\t\tmediaType: string;\n\t\t\t\t\tfileName?: string;\n\t\t\t\t\tsize?: number;\n\t\t\t }\n\t\t>\n\t> {\n\t\tif (files.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Validate all files first\n\t\tfor (const file of files) {\n\t\t\tconst error = validateFile(file);\n\t\t\tif (error) {\n\t\t\t\tthrow new Error(error);\n\t\t\t}\n\t\t}\n\n\t\t// Upload files in parallel\n\t\tconst uploadPromises = files.map(async (file) => {\n\t\t\t// Generate presigned URL\n\t\t\tconst uploadInfo = await this.generateUploadUrl({\n\t\t\t\tconversationId,\n\t\t\t\tcontentType: file.type,\n\t\t\t\tfileName: file.name,\n\t\t\t});\n\n\t\t\t// Upload file to S3\n\t\t\tawait this.uploadFile(file, uploadInfo.uploadUrl, file.type);\n\n\t\t\t// Return timeline part based on file type\n\t\t\tconst isImage = file.type.startsWith(\"image/\");\n\t\t\treturn {\n\t\t\t\ttype: isImage ? (\"image\" as const) : (\"file\" as const),\n\t\t\t\turl: uploadInfo.publicUrl,\n\t\t\t\tmediaType: file.type,\n\t\t\t\tfileName: file.name,\n\t\t\t\tsize: file.size,\n\t\t\t};\n\t\t});\n\n\t\treturn Promise.all(uploadPromises);\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations-store.d.ts","names":[],"sources":["../../src/store/conversations-store.ts"],"sourcesContent":[],"mappings":";;;;KAGY,sBAAA,GAAyB;KAGzB,oBAAA,GACX;AAJW,KAMA,kBAAA,GANsB;EAGtB,GAAA,EAAA,MAAA,EAAA;EAGA,IAAA,EAEL,MAFK,CAAA,MAAA,EAEU,oBAFQ,CAAA;EAER,UAAA,EACT,sBADS,GAAA,IAAA;CAAf;AACM,
|
|
1
|
+
{"version":3,"file":"conversations-store.d.ts","names":[],"sources":["../../src/store/conversations-store.ts"],"sourcesContent":[],"mappings":";;;;KAGY,sBAAA,GAAyB;KAGzB,oBAAA,GACX;AAJW,KAMA,kBAAA,GANsB;EAGtB,GAAA,EAAA,MAAA,EAAA;EAGA,IAAA,EAEL,MAFK,CAAA,MAAA,EAEU,oBAFQ,CAAA;EAER,UAAA,EACT,sBADS,GAAA,IAAA;CAAf;AACM,KA2MD,kBAAA,GAAqB,KA3MpB,CA2M0B,kBA3M1B,CAAA,GAAA;EAAsB,UAAA,CAAA,QAAA,EA4Mb,yBA5Ma,CAAA,EAAA,IAAA;EA2MvB,kBAAA,CAAA,YAAkB,EAEI,oBAFJ,CAAA,EAAA,IAAA;CAAS;AAAN,iBAKjB,wBAAA,CALiB,YAAA,CAAA,EAMlB,kBANkB,CAAA,EAO9B,kBAP8B;AACX,iBAoBN,gBAAA,CApBM,KAAA,EAqBd,KArBc,CAqBR,kBArBQ,CAAA,CAAA,EAsBnB,oBAtBmB,EAAA;AACY,iBA+BlB,mBAAA,CA/BkB,KAAA,EAgC1B,KAhC0B,CAgCpB,kBAhCoB,CAAA,EAAA,cAAA,EAAA,MAAA,CAAA,EAkC/B,oBAlC+B,GAAA,SAAA;AAAoB,iBAsCtC,yBAAA,CAtCsC,KAAA,EAuC9C,KAvC8C,CAuCxC,kBAvCwC,CAAA,CAAA,EAwCnD,sBAxCmD,GAAA,IAAA"}
|
|
@@ -13,7 +13,8 @@ function isSameDate(a, b) {
|
|
|
13
13
|
function isSameConversation(a, b) {
|
|
14
14
|
const deletedAtMatch = !(a.deletedAt || b.deletedAt) || a.deletedAt && b.deletedAt && isSameDate(a.deletedAt, b.deletedAt);
|
|
15
15
|
const visitorLastSeenAtMatch = !(a.visitorLastSeenAt || b.visitorLastSeenAt) || a.visitorLastSeenAt && b.visitorLastSeenAt && isSameDate(a.visitorLastSeenAt, b.visitorLastSeenAt);
|
|
16
|
-
|
|
16
|
+
const visitorRatingAtMatch = !(a.visitorRatingAt || b.visitorRatingAt) || a.visitorRatingAt && b.visitorRatingAt && isSameDate(a.visitorRatingAt, b.visitorRatingAt);
|
|
17
|
+
if (!(a.id === b.id && a.title === b.title && a.status === b.status && a.visitorId === b.visitorId && a.websiteId === b.websiteId && a.visitorRating === b.visitorRating && isSameDate(a.createdAt, b.createdAt) && isSameDate(a.updatedAt, b.updatedAt) && deletedAtMatch && visitorLastSeenAtMatch && visitorRatingAtMatch)) return false;
|
|
17
18
|
if (!(a.lastTimelineItem || b.lastTimelineItem)) return true;
|
|
18
19
|
if (!(a.lastTimelineItem && b.lastTimelineItem)) return false;
|
|
19
20
|
return a.lastTimelineItem.id === b.lastTimelineItem.id && a.lastTimelineItem.text === b.lastTimelineItem.text && isSameDate(a.lastTimelineItem.createdAt, b.lastTimelineItem.createdAt);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversations-store.js","names":["INITIAL_STATE: ConversationsState","next"],"sources":["../../src/store/conversations-store.ts"],"sourcesContent":["import type { ListConversationsResponse } from \"@cossistant/types/api/conversation\";\nimport { createStore, type Store } from \"./create-store\";\n\nexport type ConversationPagination = ListConversationsResponse[\"pagination\"];\n\n// Use the conversation type from the list response which includes visitorLastSeenAt\nexport type ConversationWithSeen =\n\tListConversationsResponse[\"conversations\"][number];\n\nexport type ConversationsState = {\n\tids: string[];\n\tbyId: Record<string, ConversationWithSeen>;\n\tpagination: ConversationPagination | null;\n};\n\nconst INITIAL_STATE: ConversationsState = {\n\tids: [],\n\tbyId: {},\n\tpagination: null,\n};\n\nfunction isSameDate(a: Date | string, b: Date | string): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tconst aTime = typeof a === \"string\" ? new Date(a).getTime() : a.getTime();\n\tconst bTime = typeof b === \"string\" ? new Date(b).getTime() : b.getTime();\n\n\treturn aTime === bTime;\n}\n\nfunction isSameConversation(\n\ta: ConversationWithSeen,\n\tb: ConversationWithSeen\n): boolean {\n\t// Check basic fields\n\tconst deletedAtMatch =\n\t\t!(a.deletedAt || b.deletedAt) ||\n\t\t(a.deletedAt && b.deletedAt && isSameDate(a.deletedAt, b.deletedAt));\n\n\t// Check visitorLastSeenAt\n\tconst visitorLastSeenAtMatch =\n\t\t!(a.visitorLastSeenAt || b.visitorLastSeenAt) ||\n\t\t(a.visitorLastSeenAt &&\n\t\t\tb.visitorLastSeenAt &&\n\t\t\tisSameDate(a.visitorLastSeenAt, b.visitorLastSeenAt));\n\n\tconst basicMatch =\n\t\ta.id === b.id &&\n\t\ta.title === b.title &&\n\t\ta.status === b.status &&\n\t\ta.visitorId === b.visitorId &&\n\t\ta.websiteId === b.websiteId &&\n\t\tisSameDate(a.createdAt, b.createdAt) &&\n\t\tisSameDate(a.updatedAt, b.updatedAt) &&\n\t\tdeletedAtMatch &&\n\t\tvisitorLastSeenAtMatch;\n\n\tif (!basicMatch) {\n\t\treturn false;\n\t}\n\n\t// Check lastTimelineItem - both undefined/null is a match\n\tif (!(a.lastTimelineItem || b.lastTimelineItem)) {\n\t\treturn true;\n\t}\n\n\t// One has timeline item, one doesn't - not a match\n\tif (!(a.lastTimelineItem && b.lastTimelineItem)) {\n\t\treturn false;\n\t}\n\n\t// Both have timeline items - compare them\n\treturn (\n\t\ta.lastTimelineItem.id === b.lastTimelineItem.id &&\n\t\ta.lastTimelineItem.text === b.lastTimelineItem.text &&\n\t\tisSameDate(a.lastTimelineItem.createdAt, b.lastTimelineItem.createdAt)\n\t);\n}\n\nfunction mergeMap(\n\texisting: Record<string, ConversationWithSeen>,\n\tincoming: ConversationWithSeen[]\n): [Record<string, ConversationWithSeen>, boolean] {\n\tlet changed = false;\n\tlet next = existing;\n\n\tfor (const conversation of incoming) {\n\t\tconst previous = next[conversation.id];\n\t\tif (!(previous && isSameConversation(previous, conversation))) {\n\t\t\tif (!changed) {\n\t\t\t\tnext = { ...next };\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tnext[conversation.id] = conversation;\n\t\t}\n\t}\n\n\treturn [next, changed];\n}\n\nfunction mergeOrder(\n\texisting: string[],\n\tincoming: string[],\n\tpage: number\n): [string[], boolean] {\n\tif (incoming.length === 0) {\n\t\treturn [existing, false];\n\t}\n\n\tif (page <= 1) {\n\t\tconst rest = existing.filter((id) => !incoming.includes(id));\n\t\tconst next = [...incoming, ...rest];\n\t\tconst changed =\n\t\t\tnext.length !== existing.length ||\n\t\t\tnext.some((value, index) => value !== existing[index]);\n\t\treturn changed ? [next, true] : [existing, false];\n\t}\n\n\tlet changed = false;\n\tconst seen = new Set(existing);\n\tconst next = [...existing];\n\n\tfor (const id of incoming) {\n\t\tif (seen.has(id)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(id);\n\t\tnext.push(id);\n\t\tchanged = true;\n\t}\n\n\treturn changed ? [next, true] : [existing, false];\n}\n\nfunction isSamePagination(\n\ta: ConversationPagination | null,\n\tb: ConversationPagination | null\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\tif (!(a && b)) {\n\t\treturn !(a || b);\n\t}\n\treturn (\n\t\ta.page === b.page &&\n\t\ta.limit === b.limit &&\n\t\ta.total === b.total &&\n\t\ta.totalPages === b.totalPages &&\n\t\ta.hasMore === b.hasMore\n\t);\n}\n\nfunction applyList(\n\tstate: ConversationsState,\n\tresponse: ListConversationsResponse\n): ConversationsState {\n\tconst [byId, mapChanged] = mergeMap(state.byId, response.conversations);\n\tconst [ids, idsChanged] = mergeOrder(\n\t\tstate.ids,\n\t\tresponse.conversations.map((conversation) => conversation.id),\n\t\tresponse.pagination.page\n\t);\n\tconst paginationChanged = !isSamePagination(\n\t\tstate.pagination,\n\t\tresponse.pagination\n\t);\n\n\tif (!(mapChanged || idsChanged || paginationChanged)) {\n\t\treturn state;\n\t}\n\n\treturn {\n\t\tbyId,\n\t\tids,\n\t\tpagination: paginationChanged ? response.pagination : state.pagination,\n\t};\n}\n\nfunction applyConversation(\n\tstate: ConversationsState,\n\tconversation: ConversationWithSeen\n): ConversationsState {\n\tconst previous = state.byId[conversation.id];\n\tconst sameConversation = previous\n\t\t? isSameConversation(previous, conversation)\n\t\t: false;\n\tconst byId = sameConversation\n\t\t? state.byId\n\t\t: { ...state.byId, [conversation.id]: conversation };\n\tconst hasId = state.ids.includes(conversation.id);\n\tconst ids = hasId ? state.ids : [...state.ids, conversation.id];\n\n\tif (byId === state.byId && ids === state.ids) {\n\t\treturn state;\n\t}\n\n\treturn {\n\t\tbyId,\n\t\tids,\n\t\tpagination: state.pagination,\n\t};\n}\n\nexport type ConversationsStore = Store<ConversationsState> & {\n\tingestList(response: ListConversationsResponse): void;\n\tingestConversation(conversation: ConversationWithSeen): void;\n};\n\nexport function createConversationsStore(\n\tinitialState: ConversationsState = INITIAL_STATE\n): ConversationsStore {\n\tconst store = createStore<ConversationsState>(initialState);\n\n\treturn {\n\t\t...store,\n\t\tingestList(response) {\n\t\t\tstore.setState((state) => applyList(state, response));\n\t\t},\n\t\tingestConversation(conversation) {\n\t\t\tstore.setState((state) => applyConversation(state, conversation));\n\t\t},\n\t};\n}\n\nexport function getConversations(\n\tstore: Store<ConversationsState>\n): ConversationWithSeen[] {\n\tconst state = store.getState();\n\treturn state.ids\n\t\t.map((id) => state.byId[id])\n\t\t.filter(\n\t\t\t(conversation): conversation is ConversationWithSeen =>\n\t\t\t\tconversation !== undefined\n\t\t);\n}\n\nexport function getConversationById(\n\tstore: Store<ConversationsState>,\n\tconversationId: string\n): ConversationWithSeen | undefined {\n\treturn store.getState().byId[conversationId];\n}\n\nexport function getConversationPagination(\n\tstore: Store<ConversationsState>\n): ConversationPagination | null {\n\treturn store.getState().pagination;\n}\n"],"mappings":";;;AAeA,MAAMA,gBAAoC;CACzC,KAAK,EAAE;CACP,MAAM,EAAE;CACR,YAAY;CACZ;AAED,SAAS,WAAW,GAAkB,GAA2B;AAChE,KAAI,MAAM,EACT,QAAO;AAMR,SAHc,OAAO,MAAM,WAAW,IAAI,KAAK,EAAE,CAAC,SAAS,GAAG,EAAE,SAAS,OAC3D,OAAO,MAAM,WAAW,IAAI,KAAK,EAAE,CAAC,SAAS,GAAG,EAAE,SAAS;;AAK1E,SAAS,mBACR,GACA,GACU;CAEV,MAAM,iBACL,EAAE,EAAE,aAAa,EAAE,cAClB,EAAE,aAAa,EAAE,aAAa,WAAW,EAAE,WAAW,EAAE,UAAU;CAGpE,MAAM,yBACL,EAAE,EAAE,qBAAqB,EAAE,sBAC1B,EAAE,qBACF,EAAE,qBACF,WAAW,EAAE,mBAAmB,EAAE,kBAAkB;AAatD,KAAI,EAVH,EAAE,OAAO,EAAE,MACX,EAAE,UAAU,EAAE,SACd,EAAE,WAAW,EAAE,UACf,EAAE,cAAc,EAAE,aAClB,EAAE,cAAc,EAAE,aAClB,WAAW,EAAE,WAAW,EAAE,UAAU,IACpC,WAAW,EAAE,WAAW,EAAE,UAAU,IACpC,kBACA,wBAGA,QAAO;AAIR,KAAI,EAAE,EAAE,oBAAoB,EAAE,kBAC7B,QAAO;AAIR,KAAI,EAAE,EAAE,oBAAoB,EAAE,kBAC7B,QAAO;AAIR,QACC,EAAE,iBAAiB,OAAO,EAAE,iBAAiB,MAC7C,EAAE,iBAAiB,SAAS,EAAE,iBAAiB,QAC/C,WAAW,EAAE,iBAAiB,WAAW,EAAE,iBAAiB,UAAU;;AAIxE,SAAS,SACR,UACA,UACkD;CAClD,IAAI,UAAU;CACd,IAAI,OAAO;AAEX,MAAK,MAAM,gBAAgB,UAAU;EACpC,MAAM,WAAW,KAAK,aAAa;AACnC,MAAI,EAAE,YAAY,mBAAmB,UAAU,aAAa,GAAG;AAC9D,OAAI,CAAC,SAAS;AACb,WAAO,EAAE,GAAG,MAAM;AAClB,cAAU;;AAEX,QAAK,aAAa,MAAM;;;AAI1B,QAAO,CAAC,MAAM,QAAQ;;AAGvB,SAAS,WACR,UACA,UACA,MACsB;AACtB,KAAI,SAAS,WAAW,EACvB,QAAO,CAAC,UAAU,MAAM;AAGzB,KAAI,QAAQ,GAAG;EACd,MAAM,OAAO,SAAS,QAAQ,OAAO,CAAC,SAAS,SAAS,GAAG,CAAC;EAC5D,MAAMC,SAAO,CAAC,GAAG,UAAU,GAAG,KAAK;AAInC,SAFCA,OAAK,WAAW,SAAS,UACzBA,OAAK,MAAM,OAAO,UAAU,UAAU,SAAS,OAAO,GACtC,CAACA,QAAM,KAAK,GAAG,CAAC,UAAU,MAAM;;CAGlD,IAAI,UAAU;CACd,MAAM,OAAO,IAAI,IAAI,SAAS;CAC9B,MAAM,OAAO,CAAC,GAAG,SAAS;AAE1B,MAAK,MAAM,MAAM,UAAU;AAC1B,MAAI,KAAK,IAAI,GAAG,CACf;AAED,OAAK,IAAI,GAAG;AACZ,OAAK,KAAK,GAAG;AACb,YAAU;;AAGX,QAAO,UAAU,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,MAAM;;AAGlD,SAAS,iBACR,GACA,GACU;AACV,KAAI,MAAM,EACT,QAAO;AAER,KAAI,EAAE,KAAK,GACV,QAAO,EAAE,KAAK;AAEf,QACC,EAAE,SAAS,EAAE,QACb,EAAE,UAAU,EAAE,SACd,EAAE,UAAU,EAAE,SACd,EAAE,eAAe,EAAE,cACnB,EAAE,YAAY,EAAE;;AAIlB,SAAS,UACR,OACA,UACqB;CACrB,MAAM,CAAC,MAAM,cAAc,SAAS,MAAM,MAAM,SAAS,cAAc;CACvE,MAAM,CAAC,KAAK,cAAc,WACzB,MAAM,KACN,SAAS,cAAc,KAAK,iBAAiB,aAAa,GAAG,EAC7D,SAAS,WAAW,KACpB;CACD,MAAM,oBAAoB,CAAC,iBAC1B,MAAM,YACN,SAAS,WACT;AAED,KAAI,EAAE,cAAc,cAAc,mBACjC,QAAO;AAGR,QAAO;EACN;EACA;EACA,YAAY,oBAAoB,SAAS,aAAa,MAAM;EAC5D;;AAGF,SAAS,kBACR,OACA,cACqB;CACrB,MAAM,WAAW,MAAM,KAAK,aAAa;CAIzC,MAAM,QAHmB,WACtB,mBAAmB,UAAU,aAAa,GAC1C,SAEA,MAAM,OACN;EAAE,GAAG,MAAM;GAAO,aAAa,KAAK;EAAc;CAErD,MAAM,MADQ,MAAM,IAAI,SAAS,aAAa,GAAG,GAC7B,MAAM,MAAM,CAAC,GAAG,MAAM,KAAK,aAAa,GAAG;AAE/D,KAAI,SAAS,MAAM,QAAQ,QAAQ,MAAM,IACxC,QAAO;AAGR,QAAO;EACN;EACA;EACA,YAAY,MAAM;EAClB;;AAQF,SAAgB,yBACf,eAAmC,eACd;CACrB,MAAM,QAAQ,YAAgC,aAAa;AAE3D,QAAO;EACN,GAAG;EACH,WAAW,UAAU;AACpB,SAAM,UAAU,UAAU,UAAU,OAAO,SAAS,CAAC;;EAEtD,mBAAmB,cAAc;AAChC,SAAM,UAAU,UAAU,kBAAkB,OAAO,aAAa,CAAC;;EAElE;;AAGF,SAAgB,iBACf,OACyB;CACzB,MAAM,QAAQ,MAAM,UAAU;AAC9B,QAAO,MAAM,IACX,KAAK,OAAO,MAAM,KAAK,IAAI,CAC3B,QACC,iBACA,iBAAiB,OAClB;;AAGH,SAAgB,oBACf,OACA,gBACmC;AACnC,QAAO,MAAM,UAAU,CAAC,KAAK;;AAG9B,SAAgB,0BACf,OACgC;AAChC,QAAO,MAAM,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"conversations-store.js","names":["INITIAL_STATE: ConversationsState","next"],"sources":["../../src/store/conversations-store.ts"],"sourcesContent":["import type { ListConversationsResponse } from \"@cossistant/types/api/conversation\";\nimport { createStore, type Store } from \"./create-store\";\n\nexport type ConversationPagination = ListConversationsResponse[\"pagination\"];\n\n// Use the conversation type from the list response which includes visitorLastSeenAt\nexport type ConversationWithSeen =\n\tListConversationsResponse[\"conversations\"][number];\n\nexport type ConversationsState = {\n\tids: string[];\n\tbyId: Record<string, ConversationWithSeen>;\n\tpagination: ConversationPagination | null;\n};\n\nconst INITIAL_STATE: ConversationsState = {\n\tids: [],\n\tbyId: {},\n\tpagination: null,\n};\n\nfunction isSameDate(a: Date | string, b: Date | string): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\n\tconst aTime = typeof a === \"string\" ? new Date(a).getTime() : a.getTime();\n\tconst bTime = typeof b === \"string\" ? new Date(b).getTime() : b.getTime();\n\n\treturn aTime === bTime;\n}\n\nfunction isSameConversation(\n\ta: ConversationWithSeen,\n\tb: ConversationWithSeen\n): boolean {\n\t// Check basic fields\n\tconst deletedAtMatch =\n\t\t!(a.deletedAt || b.deletedAt) ||\n\t\t(a.deletedAt && b.deletedAt && isSameDate(a.deletedAt, b.deletedAt));\n\n\t// Check visitorLastSeenAt\n\tconst visitorLastSeenAtMatch =\n\t\t!(a.visitorLastSeenAt || b.visitorLastSeenAt) ||\n\t\t(a.visitorLastSeenAt &&\n\t\t\tb.visitorLastSeenAt &&\n\t\t\tisSameDate(a.visitorLastSeenAt, b.visitorLastSeenAt));\n\n\t// Check visitorRatingAt\n\tconst visitorRatingAtMatch =\n\t\t!(a.visitorRatingAt || b.visitorRatingAt) ||\n\t\t(a.visitorRatingAt &&\n\t\t\tb.visitorRatingAt &&\n\t\t\tisSameDate(a.visitorRatingAt, b.visitorRatingAt));\n\n\tconst basicMatch =\n\t\ta.id === b.id &&\n\t\ta.title === b.title &&\n\t\ta.status === b.status &&\n\t\ta.visitorId === b.visitorId &&\n\t\ta.websiteId === b.websiteId &&\n\t\ta.visitorRating === b.visitorRating &&\n\t\tisSameDate(a.createdAt, b.createdAt) &&\n\t\tisSameDate(a.updatedAt, b.updatedAt) &&\n\t\tdeletedAtMatch &&\n\t\tvisitorLastSeenAtMatch &&\n\t\tvisitorRatingAtMatch;\n\n\tif (!basicMatch) {\n\t\treturn false;\n\t}\n\n\t// Check lastTimelineItem - both undefined/null is a match\n\tif (!(a.lastTimelineItem || b.lastTimelineItem)) {\n\t\treturn true;\n\t}\n\n\t// One has timeline item, one doesn't - not a match\n\tif (!(a.lastTimelineItem && b.lastTimelineItem)) {\n\t\treturn false;\n\t}\n\n\t// Both have timeline items - compare them\n\treturn (\n\t\ta.lastTimelineItem.id === b.lastTimelineItem.id &&\n\t\ta.lastTimelineItem.text === b.lastTimelineItem.text &&\n\t\tisSameDate(a.lastTimelineItem.createdAt, b.lastTimelineItem.createdAt)\n\t);\n}\n\nfunction mergeMap(\n\texisting: Record<string, ConversationWithSeen>,\n\tincoming: ConversationWithSeen[]\n): [Record<string, ConversationWithSeen>, boolean] {\n\tlet changed = false;\n\tlet next = existing;\n\n\tfor (const conversation of incoming) {\n\t\tconst previous = next[conversation.id];\n\t\tif (!(previous && isSameConversation(previous, conversation))) {\n\t\t\tif (!changed) {\n\t\t\t\tnext = { ...next };\n\t\t\t\tchanged = true;\n\t\t\t}\n\t\t\tnext[conversation.id] = conversation;\n\t\t}\n\t}\n\n\treturn [next, changed];\n}\n\nfunction mergeOrder(\n\texisting: string[],\n\tincoming: string[],\n\tpage: number\n): [string[], boolean] {\n\tif (incoming.length === 0) {\n\t\treturn [existing, false];\n\t}\n\n\tif (page <= 1) {\n\t\tconst rest = existing.filter((id) => !incoming.includes(id));\n\t\tconst next = [...incoming, ...rest];\n\t\tconst changed =\n\t\t\tnext.length !== existing.length ||\n\t\t\tnext.some((value, index) => value !== existing[index]);\n\t\treturn changed ? [next, true] : [existing, false];\n\t}\n\n\tlet changed = false;\n\tconst seen = new Set(existing);\n\tconst next = [...existing];\n\n\tfor (const id of incoming) {\n\t\tif (seen.has(id)) {\n\t\t\tcontinue;\n\t\t}\n\t\tseen.add(id);\n\t\tnext.push(id);\n\t\tchanged = true;\n\t}\n\n\treturn changed ? [next, true] : [existing, false];\n}\n\nfunction isSamePagination(\n\ta: ConversationPagination | null,\n\tb: ConversationPagination | null\n): boolean {\n\tif (a === b) {\n\t\treturn true;\n\t}\n\tif (!(a && b)) {\n\t\treturn !(a || b);\n\t}\n\treturn (\n\t\ta.page === b.page &&\n\t\ta.limit === b.limit &&\n\t\ta.total === b.total &&\n\t\ta.totalPages === b.totalPages &&\n\t\ta.hasMore === b.hasMore\n\t);\n}\n\nfunction applyList(\n\tstate: ConversationsState,\n\tresponse: ListConversationsResponse\n): ConversationsState {\n\tconst [byId, mapChanged] = mergeMap(state.byId, response.conversations);\n\tconst [ids, idsChanged] = mergeOrder(\n\t\tstate.ids,\n\t\tresponse.conversations.map((conversation) => conversation.id),\n\t\tresponse.pagination.page\n\t);\n\tconst paginationChanged = !isSamePagination(\n\t\tstate.pagination,\n\t\tresponse.pagination\n\t);\n\n\tif (!(mapChanged || idsChanged || paginationChanged)) {\n\t\treturn state;\n\t}\n\n\treturn {\n\t\tbyId,\n\t\tids,\n\t\tpagination: paginationChanged ? response.pagination : state.pagination,\n\t};\n}\n\nfunction applyConversation(\n\tstate: ConversationsState,\n\tconversation: ConversationWithSeen\n): ConversationsState {\n\tconst previous = state.byId[conversation.id];\n\tconst sameConversation = previous\n\t\t? isSameConversation(previous, conversation)\n\t\t: false;\n\tconst byId = sameConversation\n\t\t? state.byId\n\t\t: { ...state.byId, [conversation.id]: conversation };\n\tconst hasId = state.ids.includes(conversation.id);\n\tconst ids = hasId ? state.ids : [...state.ids, conversation.id];\n\n\tif (byId === state.byId && ids === state.ids) {\n\t\treturn state;\n\t}\n\n\treturn {\n\t\tbyId,\n\t\tids,\n\t\tpagination: state.pagination,\n\t};\n}\n\nexport type ConversationsStore = Store<ConversationsState> & {\n\tingestList(response: ListConversationsResponse): void;\n\tingestConversation(conversation: ConversationWithSeen): void;\n};\n\nexport function createConversationsStore(\n\tinitialState: ConversationsState = INITIAL_STATE\n): ConversationsStore {\n\tconst store = createStore<ConversationsState>(initialState);\n\n\treturn {\n\t\t...store,\n\t\tingestList(response) {\n\t\t\tstore.setState((state) => applyList(state, response));\n\t\t},\n\t\tingestConversation(conversation) {\n\t\t\tstore.setState((state) => applyConversation(state, conversation));\n\t\t},\n\t};\n}\n\nexport function getConversations(\n\tstore: Store<ConversationsState>\n): ConversationWithSeen[] {\n\tconst state = store.getState();\n\treturn state.ids\n\t\t.map((id) => state.byId[id])\n\t\t.filter(\n\t\t\t(conversation): conversation is ConversationWithSeen =>\n\t\t\t\tconversation !== undefined\n\t\t);\n}\n\nexport function getConversationById(\n\tstore: Store<ConversationsState>,\n\tconversationId: string\n): ConversationWithSeen | undefined {\n\treturn store.getState().byId[conversationId];\n}\n\nexport function getConversationPagination(\n\tstore: Store<ConversationsState>\n): ConversationPagination | null {\n\treturn store.getState().pagination;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seen-store.d.ts","names":[],"sources":["../../src/store/seen-store.ts"],"sourcesContent":[],"mappings":";;;;;KAIY,aAAA;KAEA,SAAA;EAFA,SAAA,EAGA,aAHa;EAEb,OAAA,EAAA,MAAS;EAMT,UAAA,EAAA,MAAA;AAEZ,CAAA;AAQK,KAVO,qBAAA,GAAwB,MAYxB,CAAA,MAAA,EAZuC,SAY1B,CAAA;AAiDb,KA3DA,SAAA,GA2DS;EAAS,aAAA,EA1Dd,MA0Dc,CAAA,MAAA,EA1DC,qBA0DD,CAAA;CAAN;KAnDnB,iBAAA,GAoDY;EACyB,cAAA,EAAA,MAAA;EAAgB,SAAA,EAnD9C,aAmD8C;
|
|
1
|
+
{"version":3,"file":"seen-store.d.ts","names":[],"sources":["../../src/store/seen-store.ts"],"sourcesContent":[],"mappings":";;;;;KAIY,aAAA;KAEA,SAAA;EAFA,SAAA,EAGA,aAHa;EAEb,OAAA,EAAA,MAAS;EAMT,UAAA,EAAA,MAAA;AAEZ,CAAA;AAQK,KAVO,qBAAA,GAAwB,MAYxB,CAAA,MAAA,EAZuC,SAY1B,CAAA;AAiDb,KA3DA,SAAA,GA2DS;EAAS,aAAA,EA1Dd,MA0Dc,CAAA,MAAA,EA1DC,qBA0DD,CAAA;CAAN;KAnDnB,iBAAA,GAoDY;EACyB,cAAA,EAAA,MAAA;EAAgB,SAAA,EAnD9C,aAmD8C;EAmD1C,OAAA,EAAA,MAAA;EA6HA,UAAA,EAAA,MAAA;AAQhB,CAAA;AAOgB,KAjMJ,SAAA,GAAY,KAiMR,CAjMc,SAiMY,CAAA,GAAA;kBAhMzB;2CACyB;;;iBAmD1B,eAAA,gBACD,YACZ;iBA2Ha,uBAAA,QACR,4CAEE;iBAKM,sBAAA,QACR,oBACE;iBAKM,0BAAA,QACR,kBACA"}
|
package/store/seen-store.js
CHANGED
|
@@ -19,6 +19,10 @@ function hasSameEntries(existing, next) {
|
|
|
19
19
|
return true;
|
|
20
20
|
}
|
|
21
21
|
function resolveActorIdentity(entry) {
|
|
22
|
+
if (entry.actorType && entry.actorId) return {
|
|
23
|
+
actorType: entry.actorType,
|
|
24
|
+
actorId: entry.actorId
|
|
25
|
+
};
|
|
22
26
|
if (entry.userId) return {
|
|
23
27
|
actorType: "user",
|
|
24
28
|
actorId: entry.userId
|
|
@@ -116,7 +120,7 @@ function applyConversationSeenEvent(store, event, options = {}) {
|
|
|
116
120
|
const { payload } = event;
|
|
117
121
|
const identity = resolveActorIdentity(payload);
|
|
118
122
|
if (!identity) return;
|
|
119
|
-
if (identity.actorType === "visitor" &&
|
|
123
|
+
if (identity.actorType === "visitor" && options.ignoreVisitorId && identity.actorId === options.ignoreVisitorId || identity.actorType === "user" && options.ignoreUserId && identity.actorId === options.ignoreUserId || identity.actorType === "ai_agent" && options.ignoreAiAgentId && identity.actorId === options.ignoreAiAgentId) return;
|
|
120
124
|
const lastSeenAt = payload.lastSeenAt;
|
|
121
125
|
upsertConversationSeen(store, {
|
|
122
126
|
conversationId: payload.conversationId,
|
package/store/seen-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"seen-store.js","names":["INITIAL_STATE: SeenState","nextConversation: ConversationSeenState","nextEntries: ConversationSeenState"],"sources":["../../src/store/seen-store.ts"],"sourcesContent":["import type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\nimport type { ConversationSeen } from \"@cossistant/types/schemas\";\nimport { createStore, type Store } from \"./create-store\";\n\nexport type SeenActorType = \"visitor\" | \"user\" | \"ai_agent\";\n\nexport type SeenEntry = {\n\tactorType: SeenActorType;\n\tactorId: string;\n\tlastSeenAt: string;\n};\n\nexport type ConversationSeenState = Record<string, SeenEntry>;\n\nexport type SeenState = {\n\tconversations: Record<string, ConversationSeenState>;\n};\n\nconst INITIAL_STATE: SeenState = {\n\tconversations: {},\n};\n\ntype UpsertSeenOptions = {\n\tconversationId: string;\n\tactorType: SeenActorType;\n\tactorId: string;\n\tlastSeenAt: string;\n};\n\nfunction makeKey(\n\tconversationId: string,\n\tactorType: SeenActorType,\n\tactorId: string\n): string {\n\treturn `${conversationId}:${actorType}:${actorId}`;\n}\n\nfunction hasSameEntries(\n\texisting: ConversationSeenState | undefined,\n\tnext: ConversationSeenState\n): boolean {\n\tif (!existing) {\n\t\treturn false;\n\t}\n\n\tconst existingKeys = Object.keys(existing);\n\tconst nextKeys = Object.keys(next);\n\n\tif (existingKeys.length !== nextKeys.length) {\n\t\treturn false;\n\t}\n\n\tfor (const key of nextKeys) {\n\t\tconst previous = existing[key];\n\t\tconst incoming = next[key];\n\n\t\tif (!(previous && incoming)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (\n\t\t\tprevious.actorType !== incoming.actorType ||\n\t\t\tprevious.actorId !== incoming.actorId ||\n\t\t\tnew Date(previous.lastSeenAt).getTime() !==\n\t\t\t\tnew Date(incoming.lastSeenAt).getTime()\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport type SeenStore = Store<SeenState> & {\n\tupsert(options: UpsertSeenOptions): void;\n\thydrate(conversationId: string, entries: ConversationSeen[]): void;\n\tclear(conversationId: string): void;\n};\n\ntype ActorIdentity = {\n\tactorType: SeenActorType;\n\tactorId: string;\n};\n\nfunction resolveActorIdentity(\n\tentry: Pick<\n\t\tConversationSeen | RealtimeEvent<\"conversationSeen\">[\"payload\"],\n\t\t\"userId\" | \"visitorId\" | \"aiAgentId\"\n\t>\n): ActorIdentity | null {\n\tif (entry.userId) {\n\t\treturn { actorType: \"user\", actorId: entry.userId } satisfies ActorIdentity;\n\t}\n\n\tif (entry.visitorId) {\n\t\treturn {\n\t\t\tactorType: \"visitor\",\n\t\t\tactorId: entry.visitorId,\n\t\t} satisfies ActorIdentity;\n\t}\n\n\tif (entry.aiAgentId) {\n\t\treturn {\n\t\t\tactorType: \"ai_agent\",\n\t\t\tactorId: entry.aiAgentId,\n\t\t} satisfies ActorIdentity;\n\t}\n\n\treturn null;\n}\n\nexport function createSeenStore(\n\tinitialState: SeenState = INITIAL_STATE\n): SeenStore {\n\tconst store = createStore<SeenState>({\n\t\tconversations: { ...initialState.conversations },\n\t});\n\n\treturn {\n\t\t...store,\n\t\tupsert({ conversationId, actorType, actorId, lastSeenAt }) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tconst existingConversation = state.conversations[conversationId] ?? {};\n\t\t\t\tconst key = makeKey(conversationId, actorType, actorId);\n\t\t\t\tconst previous = existingConversation[key];\n\n\t\t\t\tif (\n\t\t\t\t\tprevious &&\n\t\t\t\t\tnew Date(previous.lastSeenAt).getTime() >=\n\t\t\t\t\t\tnew Date(lastSeenAt).getTime()\n\t\t\t\t) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tconst nextConversation: ConversationSeenState = {\n\t\t\t\t\t...existingConversation,\n\t\t\t\t\t[key]: {\n\t\t\t\t\t\tactorType,\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tlastSeenAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\treturn {\n\t\t\t\t\tconversations: {\n\t\t\t\t\t\t...state.conversations,\n\t\t\t\t\t\t[conversationId]: nextConversation,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SeenState;\n\t\t\t});\n\t\t},\n\t\thydrate(conversationId, entries) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\tif (!(conversationId in state.conversations)) {\n\t\t\t\t\t\treturn state;\n\t\t\t\t\t}\n\t\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\t\tdelete nextConversations[conversationId];\n\t\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t\t}\n\n\t\t\t\tconst existing = state.conversations[conversationId] ?? {};\n\t\t\t\tconst nextEntries: ConversationSeenState = {\n\t\t\t\t\t...existing,\n\t\t\t\t};\n\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst identity = resolveActorIdentity(entry);\n\n\t\t\t\t\tif (!identity) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst key = makeKey(\n\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\tidentity.actorType,\n\t\t\t\t\t\tidentity.actorId\n\t\t\t\t\t);\n\t\t\t\t\tconst previous = existing[key];\n\t\t\t\t\tconst incomingTimestamp = new Date(entry.lastSeenAt).getTime();\n\t\t\t\t\tconst previousTimestamp = previous\n\t\t\t\t\t\t? new Date(previous.lastSeenAt).getTime()\n\t\t\t\t\t\t: null;\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tprevious &&\n\t\t\t\t\t\tpreviousTimestamp !== null &&\n\t\t\t\t\t\t!Number.isNaN(previousTimestamp) &&\n\t\t\t\t\t\t!Number.isNaN(incomingTimestamp) &&\n\t\t\t\t\t\tpreviousTimestamp > incomingTimestamp\n\t\t\t\t\t) {\n\t\t\t\t\t\tnextEntries[key] = previous;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnextEntries[key] = {\n\t\t\t\t\t\tactorType: identity.actorType,\n\t\t\t\t\t\tactorId: identity.actorId,\n\t\t\t\t\t\tlastSeenAt: entry.lastSeenAt,\n\t\t\t\t\t} satisfies SeenEntry;\n\t\t\t\t}\n\n\t\t\t\tif (hasSameEntries(existing, nextEntries)) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(nextEntries).length === 0) {\n\t\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\t\tdelete nextConversations[conversationId];\n\t\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tconversations: {\n\t\t\t\t\t\t...state.conversations,\n\t\t\t\t\t\t[conversationId]: nextEntries,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SeenState;\n\t\t\t});\n\t\t},\n\t\tclear(conversationId) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tif (!(conversationId in state.conversations)) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\tdelete nextConversations[conversationId];\n\n\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t});\n\t\t},\n\t} satisfies SeenStore;\n}\n\nexport function hydrateConversationSeen(\n\tstore: SeenStore,\n\tconversationId: string,\n\tentries: ConversationSeen[]\n): void {\n\tstore.hydrate(conversationId, entries);\n}\n\nexport function upsertConversationSeen(\n\tstore: SeenStore,\n\toptions: UpsertSeenOptions\n): void {\n\tstore.upsert(options);\n}\n\nexport function applyConversationSeenEvent(\n\tstore: SeenStore,\n\tevent: RealtimeEvent<\"conversationSeen\">,\n\toptions: {\n\t\tignoreVisitorId?: string | null;\n\t\tignoreUserId?: string | null;\n\t\tignoreAiAgentId?: string | null;\n\t} = {}\n): void {\n\tconst { payload } = event;\n\tconst identity = resolveActorIdentity(payload);\n\n\tif (!identity) {\n\t\treturn;\n\t}\n\n\tif (\n\t\t(identity.actorType === \"visitor\" &&\n\t\t\tpayload.visitorId &&\n\t\t\toptions.ignoreVisitorId &&\n\t\t\tpayload.visitorId === options.ignoreVisitorId) ||\n\t\t(identity.actorType === \"user\" &&\n\t\t\tpayload.userId &&\n\t\t\toptions.ignoreUserId &&\n\t\t\tpayload.userId === options.ignoreUserId) ||\n\t\t(identity.actorType === \"ai_agent\" &&\n\t\t\tpayload.aiAgentId &&\n\t\t\toptions.ignoreAiAgentId &&\n\t\t\tpayload.aiAgentId === options.ignoreAiAgentId)\n\t) {\n\t\treturn;\n\t}\n\n\tconst lastSeenAt = payload.lastSeenAt;\n\n\tupsertConversationSeen(store, {\n\t\tconversationId: payload.conversationId,\n\t\tactorType: identity.actorType,\n\t\tactorId: identity.actorId,\n\t\tlastSeenAt,\n\t});\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"seen-store.js","names":["INITIAL_STATE: SeenState","nextConversation: ConversationSeenState","nextEntries: ConversationSeenState"],"sources":["../../src/store/seen-store.ts"],"sourcesContent":["import type { RealtimeEvent } from \"@cossistant/types/realtime-events\";\nimport type { ConversationSeen } from \"@cossistant/types/schemas\";\nimport { createStore, type Store } from \"./create-store\";\n\nexport type SeenActorType = \"visitor\" | \"user\" | \"ai_agent\";\n\nexport type SeenEntry = {\n\tactorType: SeenActorType;\n\tactorId: string;\n\tlastSeenAt: string;\n};\n\nexport type ConversationSeenState = Record<string, SeenEntry>;\n\nexport type SeenState = {\n\tconversations: Record<string, ConversationSeenState>;\n};\n\nconst INITIAL_STATE: SeenState = {\n\tconversations: {},\n};\n\ntype UpsertSeenOptions = {\n\tconversationId: string;\n\tactorType: SeenActorType;\n\tactorId: string;\n\tlastSeenAt: string;\n};\n\nfunction makeKey(\n\tconversationId: string,\n\tactorType: SeenActorType,\n\tactorId: string\n): string {\n\treturn `${conversationId}:${actorType}:${actorId}`;\n}\n\nfunction hasSameEntries(\n\texisting: ConversationSeenState | undefined,\n\tnext: ConversationSeenState\n): boolean {\n\tif (!existing) {\n\t\treturn false;\n\t}\n\n\tconst existingKeys = Object.keys(existing);\n\tconst nextKeys = Object.keys(next);\n\n\tif (existingKeys.length !== nextKeys.length) {\n\t\treturn false;\n\t}\n\n\tfor (const key of nextKeys) {\n\t\tconst previous = existing[key];\n\t\tconst incoming = next[key];\n\n\t\tif (!(previous && incoming)) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (\n\t\t\tprevious.actorType !== incoming.actorType ||\n\t\t\tprevious.actorId !== incoming.actorId ||\n\t\t\tnew Date(previous.lastSeenAt).getTime() !==\n\t\t\t\tnew Date(incoming.lastSeenAt).getTime()\n\t\t) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport type SeenStore = Store<SeenState> & {\n\tupsert(options: UpsertSeenOptions): void;\n\thydrate(conversationId: string, entries: ConversationSeen[]): void;\n\tclear(conversationId: string): void;\n};\n\ntype ActorIdentity = {\n\tactorType: SeenActorType;\n\tactorId: string;\n};\n\n/**\n * Input type for resolving actor identity from either:\n * - ConversationSeen (has userId/visitorId/aiAgentId)\n * - RealtimeEvent<\"conversationSeen\"> payload (has actorType/actorId plus userId/visitorId/aiAgentId)\n */\ntype SeenEntryInput = {\n\tuserId?: string | null;\n\tvisitorId?: string | null;\n\taiAgentId?: string | null;\n\tactorType?: SeenActorType | string;\n\tactorId?: string;\n};\n\nfunction resolveActorIdentity(entry: SeenEntryInput): ActorIdentity | null {\n\tif (entry.actorType && entry.actorId) {\n\t\treturn {\n\t\t\tactorType: entry.actorType as SeenActorType,\n\t\t\tactorId: entry.actorId,\n\t\t} satisfies ActorIdentity;\n\t}\n\n\tif (entry.userId) {\n\t\treturn { actorType: \"user\", actorId: entry.userId } satisfies ActorIdentity;\n\t}\n\n\tif (entry.visitorId) {\n\t\treturn {\n\t\t\tactorType: \"visitor\",\n\t\t\tactorId: entry.visitorId,\n\t\t} satisfies ActorIdentity;\n\t}\n\n\tif (entry.aiAgentId) {\n\t\treturn {\n\t\t\tactorType: \"ai_agent\",\n\t\t\tactorId: entry.aiAgentId,\n\t\t} satisfies ActorIdentity;\n\t}\n\n\treturn null;\n}\n\nexport function createSeenStore(\n\tinitialState: SeenState = INITIAL_STATE\n): SeenStore {\n\tconst store = createStore<SeenState>({\n\t\tconversations: { ...initialState.conversations },\n\t});\n\n\treturn {\n\t\t...store,\n\t\tupsert({ conversationId, actorType, actorId, lastSeenAt }) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tconst existingConversation = state.conversations[conversationId] ?? {};\n\t\t\t\tconst key = makeKey(conversationId, actorType, actorId);\n\t\t\t\tconst previous = existingConversation[key];\n\n\t\t\t\tif (\n\t\t\t\t\tprevious &&\n\t\t\t\t\tnew Date(previous.lastSeenAt).getTime() >=\n\t\t\t\t\t\tnew Date(lastSeenAt).getTime()\n\t\t\t\t) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tconst nextConversation: ConversationSeenState = {\n\t\t\t\t\t...existingConversation,\n\t\t\t\t\t[key]: {\n\t\t\t\t\t\tactorType,\n\t\t\t\t\t\tactorId,\n\t\t\t\t\t\tlastSeenAt,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\treturn {\n\t\t\t\t\tconversations: {\n\t\t\t\t\t\t...state.conversations,\n\t\t\t\t\t\t[conversationId]: nextConversation,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SeenState;\n\t\t\t});\n\t\t},\n\t\thydrate(conversationId, entries) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tif (entries.length === 0) {\n\t\t\t\t\tif (!(conversationId in state.conversations)) {\n\t\t\t\t\t\treturn state;\n\t\t\t\t\t}\n\t\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\t\tdelete nextConversations[conversationId];\n\t\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t\t}\n\n\t\t\t\tconst existing = state.conversations[conversationId] ?? {};\n\t\t\t\tconst nextEntries: ConversationSeenState = {\n\t\t\t\t\t...existing,\n\t\t\t\t};\n\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst identity = resolveActorIdentity(entry);\n\n\t\t\t\t\tif (!identity) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst key = makeKey(\n\t\t\t\t\t\tconversationId,\n\t\t\t\t\t\tidentity.actorType,\n\t\t\t\t\t\tidentity.actorId\n\t\t\t\t\t);\n\t\t\t\t\tconst previous = existing[key];\n\t\t\t\t\tconst incomingTimestamp = new Date(entry.lastSeenAt).getTime();\n\t\t\t\t\tconst previousTimestamp = previous\n\t\t\t\t\t\t? new Date(previous.lastSeenAt).getTime()\n\t\t\t\t\t\t: null;\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tprevious &&\n\t\t\t\t\t\tpreviousTimestamp !== null &&\n\t\t\t\t\t\t!Number.isNaN(previousTimestamp) &&\n\t\t\t\t\t\t!Number.isNaN(incomingTimestamp) &&\n\t\t\t\t\t\tpreviousTimestamp > incomingTimestamp\n\t\t\t\t\t) {\n\t\t\t\t\t\tnextEntries[key] = previous;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnextEntries[key] = {\n\t\t\t\t\t\tactorType: identity.actorType,\n\t\t\t\t\t\tactorId: identity.actorId,\n\t\t\t\t\t\tlastSeenAt: entry.lastSeenAt,\n\t\t\t\t\t} satisfies SeenEntry;\n\t\t\t\t}\n\n\t\t\t\tif (hasSameEntries(existing, nextEntries)) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(nextEntries).length === 0) {\n\t\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\t\tdelete nextConversations[conversationId];\n\t\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tconversations: {\n\t\t\t\t\t\t...state.conversations,\n\t\t\t\t\t\t[conversationId]: nextEntries,\n\t\t\t\t\t},\n\t\t\t\t} satisfies SeenState;\n\t\t\t});\n\t\t},\n\t\tclear(conversationId) {\n\t\t\tstore.setState((state) => {\n\t\t\t\tif (!(conversationId in state.conversations)) {\n\t\t\t\t\treturn state;\n\t\t\t\t}\n\n\t\t\t\tconst nextConversations = { ...state.conversations };\n\t\t\t\tdelete nextConversations[conversationId];\n\n\t\t\t\treturn { conversations: nextConversations } satisfies SeenState;\n\t\t\t});\n\t\t},\n\t} satisfies SeenStore;\n}\n\nexport function hydrateConversationSeen(\n\tstore: SeenStore,\n\tconversationId: string,\n\tentries: ConversationSeen[]\n): void {\n\tstore.hydrate(conversationId, entries);\n}\n\nexport function upsertConversationSeen(\n\tstore: SeenStore,\n\toptions: UpsertSeenOptions\n): void {\n\tstore.upsert(options);\n}\n\nexport function applyConversationSeenEvent(\n\tstore: SeenStore,\n\tevent: RealtimeEvent<\"conversationSeen\">,\n\toptions: {\n\t\tignoreVisitorId?: string | null;\n\t\tignoreUserId?: string | null;\n\t\tignoreAiAgentId?: string | null;\n\t} = {}\n): void {\n\tconst { payload } = event;\n\tconst identity = resolveActorIdentity(payload);\n\n\tif (!identity) {\n\t\treturn;\n\t}\n\n\tif (\n\t\t(identity.actorType === \"visitor\" &&\n\t\t\toptions.ignoreVisitorId &&\n\t\t\tidentity.actorId === options.ignoreVisitorId) ||\n\t\t(identity.actorType === \"user\" &&\n\t\t\toptions.ignoreUserId &&\n\t\t\tidentity.actorId === options.ignoreUserId) ||\n\t\t(identity.actorType === \"ai_agent\" &&\n\t\t\toptions.ignoreAiAgentId &&\n\t\t\tidentity.actorId === options.ignoreAiAgentId)\n\t) {\n\t\treturn;\n\t}\n\n\tconst lastSeenAt = payload.lastSeenAt;\n\n\tupsertConversationSeen(store, {\n\t\tconversationId: payload.conversationId,\n\t\tactorType: identity.actorType,\n\t\tactorId: identity.actorId,\n\t\tlastSeenAt,\n\t});\n}\n"],"mappings":"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"}
|
|
@@ -115,7 +115,6 @@ declare const createConversationRequestSchema: z.ZodObject<{
|
|
|
115
115
|
}, z.core.$strip>, z.ZodObject<{
|
|
116
116
|
type: z.ZodLiteral<"event">;
|
|
117
117
|
eventType: z.ZodEnum<{
|
|
118
|
-
resolved: "resolved";
|
|
119
118
|
assigned: "assigned";
|
|
120
119
|
unassigned: "unassigned";
|
|
121
120
|
participant_requested: "participant_requested";
|
|
@@ -125,6 +124,7 @@ declare const createConversationRequestSchema: z.ZodObject<{
|
|
|
125
124
|
priority_changed: "priority_changed";
|
|
126
125
|
tag_added: "tag_added";
|
|
127
126
|
tag_removed: "tag_removed";
|
|
127
|
+
resolved: "resolved";
|
|
128
128
|
reopened: "reopened";
|
|
129
129
|
visitor_blocked: "visitor_blocked";
|
|
130
130
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -264,7 +264,6 @@ declare const createConversationResponseSchema: z.ZodObject<{
|
|
|
264
264
|
}, z.core.$strip>, z.ZodObject<{
|
|
265
265
|
type: z.ZodLiteral<"event">;
|
|
266
266
|
eventType: z.ZodEnum<{
|
|
267
|
-
resolved: "resolved";
|
|
268
267
|
assigned: "assigned";
|
|
269
268
|
unassigned: "unassigned";
|
|
270
269
|
participant_requested: "participant_requested";
|
|
@@ -274,6 +273,7 @@ declare const createConversationResponseSchema: z.ZodObject<{
|
|
|
274
273
|
priority_changed: "priority_changed";
|
|
275
274
|
tag_added: "tag_added";
|
|
276
275
|
tag_removed: "tag_removed";
|
|
276
|
+
resolved: "resolved";
|
|
277
277
|
reopened: "reopened";
|
|
278
278
|
visitor_blocked: "visitor_blocked";
|
|
279
279
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -306,10 +306,12 @@ declare const createConversationResponseSchema: z.ZodObject<{
|
|
|
306
306
|
visitorId: z.ZodString;
|
|
307
307
|
websiteId: z.ZodString;
|
|
308
308
|
status: z.ZodDefault<z.ZodEnum<{
|
|
309
|
-
open: "open";
|
|
310
309
|
resolved: "resolved";
|
|
310
|
+
open: "open";
|
|
311
311
|
spam: "spam";
|
|
312
312
|
}>>;
|
|
313
|
+
visitorRating: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
314
|
+
visitorRatingAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
313
315
|
deletedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
314
316
|
visitorLastSeenAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
315
317
|
lastTimelineItem: z.ZodOptional<z.ZodObject<{
|
|
@@ -423,7 +425,6 @@ declare const createConversationResponseSchema: z.ZodObject<{
|
|
|
423
425
|
}, z.core.$strip>, z.ZodObject<{
|
|
424
426
|
type: z.ZodLiteral<"event">;
|
|
425
427
|
eventType: z.ZodEnum<{
|
|
426
|
-
resolved: "resolved";
|
|
427
428
|
assigned: "assigned";
|
|
428
429
|
unassigned: "unassigned";
|
|
429
430
|
participant_requested: "participant_requested";
|
|
@@ -433,6 +434,7 @@ declare const createConversationResponseSchema: z.ZodObject<{
|
|
|
433
434
|
priority_changed: "priority_changed";
|
|
434
435
|
tag_added: "tag_added";
|
|
435
436
|
tag_removed: "tag_removed";
|
|
437
|
+
resolved: "resolved";
|
|
436
438
|
reopened: "reopened";
|
|
437
439
|
visitor_blocked: "visitor_blocked";
|
|
438
440
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -487,10 +489,12 @@ declare const listConversationsResponseSchema: z.ZodObject<{
|
|
|
487
489
|
visitorId: z.ZodString;
|
|
488
490
|
websiteId: z.ZodString;
|
|
489
491
|
status: z.ZodDefault<z.ZodEnum<{
|
|
490
|
-
open: "open";
|
|
491
492
|
resolved: "resolved";
|
|
493
|
+
open: "open";
|
|
492
494
|
spam: "spam";
|
|
493
495
|
}>>;
|
|
496
|
+
visitorRating: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
497
|
+
visitorRatingAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
494
498
|
deletedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
495
499
|
visitorLastSeenAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
496
500
|
lastTimelineItem: z.ZodOptional<z.ZodObject<{
|
|
@@ -604,7 +608,6 @@ declare const listConversationsResponseSchema: z.ZodObject<{
|
|
|
604
608
|
}, z.core.$strip>, z.ZodObject<{
|
|
605
609
|
type: z.ZodLiteral<"event">;
|
|
606
610
|
eventType: z.ZodEnum<{
|
|
607
|
-
resolved: "resolved";
|
|
608
611
|
assigned: "assigned";
|
|
609
612
|
unassigned: "unassigned";
|
|
610
613
|
participant_requested: "participant_requested";
|
|
@@ -614,6 +617,7 @@ declare const listConversationsResponseSchema: z.ZodObject<{
|
|
|
614
617
|
priority_changed: "priority_changed";
|
|
615
618
|
tag_added: "tag_added";
|
|
616
619
|
tag_removed: "tag_removed";
|
|
620
|
+
resolved: "resolved";
|
|
617
621
|
reopened: "reopened";
|
|
618
622
|
visitor_blocked: "visitor_blocked";
|
|
619
623
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -661,10 +665,12 @@ declare const getConversationResponseSchema: z.ZodObject<{
|
|
|
661
665
|
visitorId: z.ZodString;
|
|
662
666
|
websiteId: z.ZodString;
|
|
663
667
|
status: z.ZodDefault<z.ZodEnum<{
|
|
664
|
-
open: "open";
|
|
665
668
|
resolved: "resolved";
|
|
669
|
+
open: "open";
|
|
666
670
|
spam: "spam";
|
|
667
671
|
}>>;
|
|
672
|
+
visitorRating: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
673
|
+
visitorRatingAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
668
674
|
deletedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
669
675
|
visitorLastSeenAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
670
676
|
lastTimelineItem: z.ZodOptional<z.ZodObject<{
|
|
@@ -778,7 +784,6 @@ declare const getConversationResponseSchema: z.ZodObject<{
|
|
|
778
784
|
}, z.core.$strip>, z.ZodObject<{
|
|
779
785
|
type: z.ZodLiteral<"event">;
|
|
780
786
|
eventType: z.ZodEnum<{
|
|
781
|
-
resolved: "resolved";
|
|
782
787
|
assigned: "assigned";
|
|
783
788
|
unassigned: "unassigned";
|
|
784
789
|
participant_requested: "participant_requested";
|
|
@@ -788,6 +793,7 @@ declare const getConversationResponseSchema: z.ZodObject<{
|
|
|
788
793
|
priority_changed: "priority_changed";
|
|
789
794
|
tag_added: "tag_added";
|
|
790
795
|
tag_removed: "tag_removed";
|
|
796
|
+
resolved: "resolved";
|
|
791
797
|
reopened: "reopened";
|
|
792
798
|
visitor_blocked: "visitor_blocked";
|
|
793
799
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -831,6 +837,17 @@ declare const setConversationTypingResponseSchema: z.ZodObject<{
|
|
|
831
837
|
sentAt: z.ZodString;
|
|
832
838
|
}, z.core.$strip>;
|
|
833
839
|
type SetConversationTypingResponseBody = z.infer<typeof setConversationTypingResponseSchema>;
|
|
840
|
+
declare const submitConversationRatingRequestSchema: z.ZodObject<{
|
|
841
|
+
rating: z.ZodNumber;
|
|
842
|
+
visitorId: z.ZodOptional<z.ZodString>;
|
|
843
|
+
}, z.core.$strip>;
|
|
844
|
+
type SubmitConversationRatingRequestBody = z.infer<typeof submitConversationRatingRequestSchema>;
|
|
845
|
+
declare const submitConversationRatingResponseSchema: z.ZodObject<{
|
|
846
|
+
conversationId: z.ZodString;
|
|
847
|
+
rating: z.ZodNumber;
|
|
848
|
+
ratedAt: z.ZodString;
|
|
849
|
+
}, z.core.$strip>;
|
|
850
|
+
type SubmitConversationRatingResponseBody = z.infer<typeof submitConversationRatingResponseSchema>;
|
|
834
851
|
declare const getConversationSeenDataResponseSchema: z.ZodObject<{
|
|
835
852
|
seenData: z.ZodArray<z.ZodObject<{
|
|
836
853
|
id: z.ZodString;
|
|
@@ -846,5 +863,5 @@ declare const getConversationSeenDataResponseSchema: z.ZodObject<{
|
|
|
846
863
|
}, z.core.$strip>;
|
|
847
864
|
type GetConversationSeenDataResponse = z.infer<typeof getConversationSeenDataResponseSchema>;
|
|
848
865
|
//#endregion
|
|
849
|
-
export { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody };
|
|
866
|
+
export { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody, SubmitConversationRatingRequestBody, SubmitConversationRatingResponseBody };
|
|
850
867
|
//# sourceMappingURL=conversation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","names":[],"sources":["../../../../../types/src/api/conversation.ts"],"sourcesContent":[],"mappings":";;;cAIa,iCAA+B,CAAA,CAAA;;EAA/B,cAAA,eAAA,YAoBV,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAES,6BAAA,GAAgC,CAAA,CAAE,aACtC;cAGK,kCAAgC,CAAA,CAAA;;;;;;;;;;;;;;;;;MA1BD,IAAA,cAAA,CAAA,MAAA,CAAA;MAAA,IAAA,aAAA;MAsBhC,KAAA,eAAA,UAA6B,CAAA;QAI5B,SAAA,EAAA,WAAA
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","names":[],"sources":["../../../../../types/src/api/conversation.ts"],"sourcesContent":[],"mappings":";;;cAIa,iCAA+B,CAAA,CAAA;;EAA/B,cAAA,eAAA,YAoBV,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAES,6BAAA,GAAgC,CAAA,CAAE,aACtC;cAGK,kCAAgC,CAAA,CAAA;;;;;;;;;;;;;;;;;MA1BD,IAAA,cAAA,CAAA,MAAA,CAAA;MAAA,IAAA,aAAA;MAsBhC,KAAA,eAAA,UAA6B,CAAA;QAI5B,SAAA,EAAA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KASD,8BAAA,GAAiC,CAAA,CAAE,aACvC;cAGK,gCAA8B,CAAA,CAAA;;;;;;;;;;;;;;;;;KA6B/B,wBAAA,GAA2B,CAAA,CAAE,aACjC;cAGK,iCAA+B,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA9CC,IAAA,cAAA,CAAA,MAAA,CAAA;QAAA,IAAA,aAAA;QASjC,KAAA,eAAA,UAA8B,CAAA;UAI7B,SAAA,EAAA,WA2BV;;;;;;;;;;;;;;cA3BwC,OAAA,EAAA,SAAA;YAAA,CAAA,CAAA,CAAA;YA6B/B,eAAwB,eAC5B,YAAA,CAAA;YAGK,WAAA,eAaV,YAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAES,yBAAA,GAA4B,CAAA,CAAE,aAClC;cAGK,8BAA4B,CAAA,CAAA;;;KAU7B,sBAAA,GAAyB,CAAA,CAAE,aAC/B;cAGK,+BAA6B,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAjCE,gBAAA,eAAA,YAAA,CAAA;UAAA,UAAA,eAAA,YAAA,CAAA;YAehC,UAAyB,eAC7B,UAAA,CAAA;cAGK,MAAA,EAQV,QAAA;;;YARsC,eAAA,eAAA,YAAA,CAAA;YAAA,WAAA,eAAA,YAAA,CAAA;UAU7B,CAAA,eAAsB,CAAA,CAAA;QAIrB,CAAA,eAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAQD,uBAAA,GAA0B,CAAA,CAAE,aAChC;cAGK,mCAAiC,CAAA,CAAA;;;KAYlC,+BAAA,GAAkC,CAAA,CAAE,aACxC;cAGK,oCAAkC,CAAA,CAAA;;;;KAcnC,gCAAA,GAAmC,CAAA,CAAE,aACzC;cA0BK,qCAAmC,CAAA,CAAA;;;;;;KAoBpC,iCAAA,GAAoC,CAAA,CAAE,aAC1C;cAGK,uCAAqC,CAAA,CAAA;;;;KAetC,mCAAA,GAAsC,CAAA,CAAE,aAC5C;cAGK,wCAAsC,CAAA,CAAA;;;;;KAgBvC,oCAAA,GAAuC,CAAA,CAAE,aAC7C;cAGK,uCAAqC,CAAA,CAAA;;;;;;;;;;;;;KAuCtC,+BAAA,GAAkC,CAAA,CAAE,aACxC"}
|
|
@@ -113,7 +113,6 @@ declare const timelineItemSchema: z.ZodObject<{
|
|
|
113
113
|
}, z.core.$strip>, z.ZodObject<{
|
|
114
114
|
type: z.ZodLiteral<"event">;
|
|
115
115
|
eventType: z.ZodEnum<{
|
|
116
|
-
resolved: "resolved";
|
|
117
116
|
assigned: "assigned";
|
|
118
117
|
unassigned: "unassigned";
|
|
119
118
|
participant_requested: "participant_requested";
|
|
@@ -123,6 +122,7 @@ declare const timelineItemSchema: z.ZodObject<{
|
|
|
123
122
|
priority_changed: "priority_changed";
|
|
124
123
|
tag_added: "tag_added";
|
|
125
124
|
tag_removed: "tag_removed";
|
|
125
|
+
resolved: "resolved";
|
|
126
126
|
reopened: "reopened";
|
|
127
127
|
visitor_blocked: "visitor_blocked";
|
|
128
128
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -266,7 +266,6 @@ declare const getConversationTimelineItemsResponseSchema: z.ZodObject<{
|
|
|
266
266
|
}, z.core.$strip>, z.ZodObject<{
|
|
267
267
|
type: z.ZodLiteral<"event">;
|
|
268
268
|
eventType: z.ZodEnum<{
|
|
269
|
-
resolved: "resolved";
|
|
270
269
|
assigned: "assigned";
|
|
271
270
|
unassigned: "unassigned";
|
|
272
271
|
participant_requested: "participant_requested";
|
|
@@ -276,6 +275,7 @@ declare const getConversationTimelineItemsResponseSchema: z.ZodObject<{
|
|
|
276
275
|
priority_changed: "priority_changed";
|
|
277
276
|
tag_added: "tag_added";
|
|
278
277
|
tag_removed: "tag_removed";
|
|
278
|
+
resolved: "resolved";
|
|
279
279
|
reopened: "reopened";
|
|
280
280
|
visitor_blocked: "visitor_blocked";
|
|
281
281
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -409,7 +409,6 @@ declare const sendTimelineItemRequestSchema: z.ZodObject<{
|
|
|
409
409
|
}, z.core.$strip>, z.ZodObject<{
|
|
410
410
|
type: z.ZodLiteral<"event">;
|
|
411
411
|
eventType: z.ZodEnum<{
|
|
412
|
-
resolved: "resolved";
|
|
413
412
|
assigned: "assigned";
|
|
414
413
|
unassigned: "unassigned";
|
|
415
414
|
participant_requested: "participant_requested";
|
|
@@ -419,6 +418,7 @@ declare const sendTimelineItemRequestSchema: z.ZodObject<{
|
|
|
419
418
|
priority_changed: "priority_changed";
|
|
420
419
|
tag_added: "tag_added";
|
|
421
420
|
tag_removed: "tag_removed";
|
|
421
|
+
resolved: "resolved";
|
|
422
422
|
reopened: "reopened";
|
|
423
423
|
visitor_blocked: "visitor_blocked";
|
|
424
424
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -561,7 +561,6 @@ declare const sendTimelineItemResponseSchema: z.ZodObject<{
|
|
|
561
561
|
}, z.core.$strip>, z.ZodObject<{
|
|
562
562
|
type: z.ZodLiteral<"event">;
|
|
563
563
|
eventType: z.ZodEnum<{
|
|
564
|
-
resolved: "resolved";
|
|
565
564
|
assigned: "assigned";
|
|
566
565
|
unassigned: "unassigned";
|
|
567
566
|
participant_requested: "participant_requested";
|
|
@@ -571,6 +570,7 @@ declare const sendTimelineItemResponseSchema: z.ZodObject<{
|
|
|
571
570
|
priority_changed: "priority_changed";
|
|
572
571
|
tag_added: "tag_added";
|
|
573
572
|
tag_removed: "tag_removed";
|
|
573
|
+
resolved: "resolved";
|
|
574
574
|
reopened: "reopened";
|
|
575
575
|
visitor_blocked: "visitor_blocked";
|
|
576
576
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -115,10 +115,12 @@ declare const realtimeSchema: {
|
|
|
115
115
|
visitorId: z.ZodString;
|
|
116
116
|
websiteId: z.ZodString;
|
|
117
117
|
status: z.ZodDefault<z.ZodEnum<{
|
|
118
|
-
open: "open";
|
|
119
118
|
resolved: "resolved";
|
|
119
|
+
open: "open";
|
|
120
120
|
spam: "spam";
|
|
121
121
|
}>>;
|
|
122
|
+
visitorRating: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
123
|
+
visitorRatingAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
122
124
|
deletedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
123
125
|
visitorLastSeenAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
124
126
|
lastTimelineItem: z.ZodOptional<z.ZodObject<{
|
|
@@ -232,7 +234,6 @@ declare const realtimeSchema: {
|
|
|
232
234
|
}, z.core.$strip>, z.ZodObject<{
|
|
233
235
|
type: z.ZodLiteral<"event">;
|
|
234
236
|
eventType: z.ZodEnum<{
|
|
235
|
-
resolved: "resolved";
|
|
236
237
|
assigned: "assigned";
|
|
237
238
|
unassigned: "unassigned";
|
|
238
239
|
participant_requested: "participant_requested";
|
|
@@ -242,6 +243,7 @@ declare const realtimeSchema: {
|
|
|
242
243
|
priority_changed: "priority_changed";
|
|
243
244
|
tag_added: "tag_added";
|
|
244
245
|
tag_removed: "tag_removed";
|
|
246
|
+
resolved: "resolved";
|
|
245
247
|
reopened: "reopened";
|
|
246
248
|
visitor_blocked: "visitor_blocked";
|
|
247
249
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -270,8 +272,8 @@ declare const realtimeSchema: {
|
|
|
270
272
|
header: z.ZodObject<{
|
|
271
273
|
id: z.ZodString;
|
|
272
274
|
status: z.ZodEnum<{
|
|
273
|
-
open: "open";
|
|
274
275
|
resolved: "resolved";
|
|
276
|
+
open: "open";
|
|
275
277
|
spam: "spam";
|
|
276
278
|
}>;
|
|
277
279
|
priority: z.ZodEnum<{
|
|
@@ -300,6 +302,8 @@ declare const realtimeSchema: {
|
|
|
300
302
|
channel: z.ZodString;
|
|
301
303
|
title: z.ZodNullable<z.ZodString>;
|
|
302
304
|
resolutionTime: z.ZodNullable<z.ZodNumber>;
|
|
305
|
+
visitorRating: z.ZodNullable<z.ZodNumber>;
|
|
306
|
+
visitorRatingAt: z.ZodNullable<z.ZodString>;
|
|
303
307
|
startedAt: z.ZodNullable<z.ZodString>;
|
|
304
308
|
firstResponseAt: z.ZodNullable<z.ZodString>;
|
|
305
309
|
resolvedAt: z.ZodNullable<z.ZodString>;
|
|
@@ -427,7 +431,6 @@ declare const realtimeSchema: {
|
|
|
427
431
|
}, z.core.$strip>, z.ZodObject<{
|
|
428
432
|
type: z.ZodLiteral<"event">;
|
|
429
433
|
eventType: z.ZodEnum<{
|
|
430
|
-
resolved: "resolved";
|
|
431
434
|
assigned: "assigned";
|
|
432
435
|
unassigned: "unassigned";
|
|
433
436
|
participant_requested: "participant_requested";
|
|
@@ -437,6 +440,7 @@ declare const realtimeSchema: {
|
|
|
437
440
|
priority_changed: "priority_changed";
|
|
438
441
|
tag_added: "tag_added";
|
|
439
442
|
tag_removed: "tag_removed";
|
|
443
|
+
resolved: "resolved";
|
|
440
444
|
reopened: "reopened";
|
|
441
445
|
visitor_blocked: "visitor_blocked";
|
|
442
446
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -572,7 +576,6 @@ declare const realtimeSchema: {
|
|
|
572
576
|
}, z.core.$strip>, z.ZodObject<{
|
|
573
577
|
type: z.ZodLiteral<"event">;
|
|
574
578
|
eventType: z.ZodEnum<{
|
|
575
|
-
resolved: "resolved";
|
|
576
579
|
assigned: "assigned";
|
|
577
580
|
unassigned: "unassigned";
|
|
578
581
|
participant_requested: "participant_requested";
|
|
@@ -582,6 +585,7 @@ declare const realtimeSchema: {
|
|
|
582
585
|
priority_changed: "priority_changed";
|
|
583
586
|
tag_added: "tag_added";
|
|
584
587
|
tag_removed: "tag_removed";
|
|
588
|
+
resolved: "resolved";
|
|
585
589
|
reopened: "reopened";
|
|
586
590
|
visitor_blocked: "visitor_blocked";
|
|
587
591
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -680,7 +684,6 @@ declare const realtimeSchema: {
|
|
|
680
684
|
conversationId: z.ZodString;
|
|
681
685
|
organizationId: z.ZodString;
|
|
682
686
|
type: z.ZodEnum<{
|
|
683
|
-
resolved: "resolved";
|
|
684
687
|
assigned: "assigned";
|
|
685
688
|
unassigned: "unassigned";
|
|
686
689
|
participant_requested: "participant_requested";
|
|
@@ -690,6 +693,7 @@ declare const realtimeSchema: {
|
|
|
690
693
|
priority_changed: "priority_changed";
|
|
691
694
|
tag_added: "tag_added";
|
|
692
695
|
tag_removed: "tag_removed";
|
|
696
|
+
resolved: "resolved";
|
|
693
697
|
reopened: "reopened";
|
|
694
698
|
visitor_blocked: "visitor_blocked";
|
|
695
699
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAqBa
|
|
1
|
+
{"version":3,"file":"realtime-events.d.ts","names":[],"sources":["../../../../types/src/realtime-events.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAqBa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8VD,iBAAA,gBAAiC;KAEjC,+BAA+B,qBAAqB,CAAA,CAAE,cACzD,gBAAgB;KAGb,wBAAwB;QAC7B;WACG,qBAAqB"}
|
package/types/src/schemas.d.ts
CHANGED
|
@@ -10,10 +10,12 @@ declare const conversationSchema: z.ZodObject<{
|
|
|
10
10
|
visitorId: z.ZodString;
|
|
11
11
|
websiteId: z.ZodString;
|
|
12
12
|
status: z.ZodDefault<z.ZodEnum<{
|
|
13
|
-
open: "open";
|
|
14
13
|
resolved: "resolved";
|
|
14
|
+
open: "open";
|
|
15
15
|
spam: "spam";
|
|
16
16
|
}>>;
|
|
17
|
+
visitorRating: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
18
|
+
visitorRatingAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
17
19
|
deletedAt: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
18
20
|
visitorLastSeenAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
19
21
|
lastTimelineItem: z.ZodOptional<z.ZodObject<{
|
|
@@ -127,7 +129,6 @@ declare const conversationSchema: z.ZodObject<{
|
|
|
127
129
|
}, z.core.$strip>, z.ZodObject<{
|
|
128
130
|
type: z.ZodLiteral<"event">;
|
|
129
131
|
eventType: z.ZodEnum<{
|
|
130
|
-
resolved: "resolved";
|
|
131
132
|
assigned: "assigned";
|
|
132
133
|
unassigned: "unassigned";
|
|
133
134
|
participant_requested: "participant_requested";
|
|
@@ -137,6 +138,7 @@ declare const conversationSchema: z.ZodObject<{
|
|
|
137
138
|
priority_changed: "priority_changed";
|
|
138
139
|
tag_added: "tag_added";
|
|
139
140
|
tag_removed: "tag_removed";
|
|
141
|
+
resolved: "resolved";
|
|
140
142
|
reopened: "reopened";
|
|
141
143
|
visitor_blocked: "visitor_blocked";
|
|
142
144
|
visitor_unblocked: "visitor_unblocked";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.d.ts","names":[],"sources":["../../../../types/src/schemas.ts"],"sourcesContent":[],"mappings":";;;;cAkBa,oBAAkB,CAAA,CAAA
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","names":[],"sources":["../../../../types/src/schemas.ts"],"sourcesContent":[],"mappings":";;;;cAkBa,oBAAkB,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBnB,YAAA,GAAe,CAAA,CAAE,aAAa;cAE7B,wBAAsB,CAAA,CAAA;;;;;;;;EAvBJ,SAAA,aAAA;EAAA,SAAA,eAAA,YAAA,CAAA;AAqB/B,CAAA,eAAY,CAAA;AAEC,KAYD,gBAAA,GAAmB,CAAA,CAAE,KAF/B,CAAA,OAE4C,sBAF5C,CAAA"}
|