@cossistant/core 0.0.28 → 0.0.30
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/_virtual/rolldown_runtime.js +27 -12
- package/ai-sdk-utils.d.ts +141 -0
- package/ai-sdk-utils.d.ts.map +1 -0
- package/ai-sdk-utils.js +255 -0
- package/ai-sdk-utils.js.map +1 -0
- package/client.d.ts +17 -7
- package/client.d.ts.map +1 -1
- package/client.js +34 -3
- package/client.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js +3 -1
- package/package.json +1 -1
- package/privacy-filter.d.ts +112 -0
- package/privacy-filter.d.ts.map +1 -0
- package/privacy-filter.js +170 -0
- package/privacy-filter.js.map +1 -0
- package/rest-client.d.ts +4 -4
- package/rest-client.d.ts.map +1 -1
- package/rest-client.js +4 -4
- package/rest-client.js.map +1 -1
- package/store/conversations-store.d.ts +1 -1
- package/store/seen-store.d.ts +2 -2
- package/store/timeline-items-store.d.ts +5 -5
- package/store/timeline-items-store.d.ts.map +1 -1
- package/store/timeline-items-store.js +1 -1
- package/store/timeline-items-store.js.map +1 -1
- package/store/typing-store.d.ts +1 -1
- package/store/typing-store.d.ts.map +1 -1
- package/store/typing-store.js +12 -19
- package/store/typing-store.js.map +1 -1
- package/types/src/api/contact.d.ts.map +1 -0
- package/{conversation.d.ts → types/src/api/conversation.d.ts} +458 -78
- package/types/src/api/conversation.d.ts.map +1 -0
- package/types/src/api/timeline-item.d.ts +602 -0
- package/types/src/api/timeline-item.d.ts.map +1 -0
- package/types/src/api/timeline-item.js +67 -19
- package/types/src/api/timeline-item.js.map +1 -1
- package/types/src/api/upload.d.ts.map +1 -0
- package/types/src/enums.js +4 -1
- package/types/src/enums.js.map +1 -1
- package/types/src/realtime-events.d.ts +1000 -0
- package/types/src/realtime-events.d.ts.map +1 -0
- package/{schemas.d.ts → types/src/schemas.d.ts} +92 -16
- package/types/src/schemas.d.ts.map +1 -0
- package/contact.d.ts.map +0 -1
- package/conversation.d.ts.map +0 -1
- package/realtime-events.d.ts +0 -478
- package/realtime-events.d.ts.map +0 -1
- package/schemas.d.ts.map +0 -1
- package/timeline-item.d.ts +0 -298
- package/timeline-item.d.ts.map +0 -1
- package/upload.d.ts.map +0 -1
- /package/{contact.d.ts → types/src/api/contact.d.ts} +0 -0
- /package/{upload.d.ts → types/src/api/upload.d.ts} +0 -0
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\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};\n\n\t\t\t\tthis.conversationsStore.ingestConversation(nextConversation);\n\t\t\t}\n\t\t}\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,gBAAiB,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,WAAY,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;IACzB,MAAM,mBAAmB;KACxB,GAAG;KACH,WAAW,aAAa;KACxB,kBAAkB;KAClB;AAED,SAAK,mBAAmB,mBAAmB,iBAAiB;;;;;;;CAS/D,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} 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":"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"}
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AISDKFilePart, AISDKPart, AISDKReasoningPart, AISDKSourceDocumentPart, AISDKSourceUrlPart, AISDKStepStartPart, AISDKTextPart, AISDKToolPart, CossistantMessageMetadata, CossistantPartMetadata, CossistantUIMessage, FromUIMessageContext, extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages } from "./ai-sdk-utils.js";
|
|
1
2
|
import { CossistantAPIError } from "./types.js";
|
|
2
3
|
import { CossistantRestClient } from "./rest-client.js";
|
|
3
4
|
import { ConversationPagination, ConversationWithSeen, ConversationsState, ConversationsStore, createConversationsStore, getConversationById, getConversationPagination, getConversations } from "./store/conversations-store.js";
|
|
@@ -5,6 +6,7 @@ import { ConversationTimelineItemsState, TimelineItemsState, TimelineItemsStore,
|
|
|
5
6
|
import { WebsiteError, WebsiteState, WebsiteStatus, WebsiteStore, createWebsiteStore, getWebsiteState } from "./store/website-store.js";
|
|
6
7
|
import { CossistantClient } from "./client.js";
|
|
7
8
|
import { normalizeLocale } from "./locale-utils.js";
|
|
9
|
+
import { Audience, FilterOptions, PrivacyPresets, countVisibleParts, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, hasVisibleContent } from "./privacy-filter.js";
|
|
8
10
|
import { ConversationSeenState, SeenActorType, SeenEntry, SeenState, SeenStore, applyConversationSeenEvent, createSeenStore, hydrateConversationSeen, upsertConversationSeen } from "./store/seen-store.js";
|
|
9
11
|
import { DefaultRoutes, NavigationState, RouteRegistry, SUPPORT_PAGES, SupportConfig, SupportNavigation, SupportPage, SupportStore, SupportStoreActions, SupportStoreOptions, SupportStoreState, SupportStoreStorage, createSupportStore } from "./store/support-store.js";
|
|
10
12
|
import { ConversationTypingState, TypingActorType, TypingEntry, TypingState, TypingStore, TypingStoreDependencies, applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, createTypingStore, getConversationTyping, setTypingState } from "./store/typing-store.js";
|
|
@@ -15,4 +17,4 @@ import { VisitorData, collectVisitorData } from "./visitor-data.js";
|
|
|
15
17
|
import { generateVisitorName, getVisitorNameWithFallback } from "./visitor-name.js";
|
|
16
18
|
import { clearAllVisitorIds, clearVisitorId, getVisitorId, setVisitorId } from "./visitor-tracker.js";
|
|
17
19
|
import { CossistantConfig, CossistantError } from "@cossistant/types";
|
|
18
|
-
export { ALLOWED_FILE_TYPES_DESCRIPTION, ALLOWED_MIME_TYPES, type ConversationPagination, type ConversationSeenState, type ConversationTimelineItemsState, type ConversationTypingState, type ConversationWithSeen, type ConversationsState, type ConversationsStore, CossistantAPIError, CossistantClient, type CossistantConfig, type CossistantError, CossistantRestClient, type DefaultRoutes, FILE_INPUT_ACCEPT, MAX_FILES_PER_MESSAGE, MAX_FILE_SIZE, type NavigationState, type RouteRegistry, type SUPPORT_PAGES, type SeenActorType, type SeenEntry, type SeenState, type SeenStore, type SupportConfig, type SupportNavigation, type SupportPage, type SupportStore, type SupportStoreActions, type SupportStoreOptions, type SupportStoreState, type SupportStoreStorage, TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, type TimelineItemsState, type TimelineItemsStore, type TypingActorType, type TypingEntry, type TypingReporter, type TypingReporterConfig, type TypingState, type TypingStore, type TypingStoreDependencies, type VisitorData, type WebsiteError, type WebsiteState, type WebsiteStatus, type WebsiteStore, applyConversationSeenEvent, applyConversationTypingEvent, clearAllVisitorIds, clearTypingFromTimelineItem, clearTypingState, clearVisitorId, collectVisitorData, createConversationsStore, createSeenStore, createSupportStore, createTimelineItemsStore, createTypingReporter, createTypingStore, createWebsiteStore, CossistantClient as default, formatFileSize, generateConversationId, generateMessageId, generateVisitorName, getConversationById, getConversationPagination, getConversationTimelineItems, getConversationTyping, getConversations, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hydrateConversationSeen, isAllowedMimeType, isImageMimeType, normalizeLocale, setTypingState, setVisitorId, upsertConversationSeen, validateFile, validateFiles };
|
|
20
|
+
export { type AISDKFilePart, type AISDKPart, type AISDKReasoningPart, type AISDKSourceDocumentPart, type AISDKSourceUrlPart, type AISDKStepStartPart, type AISDKTextPart, type AISDKToolPart, ALLOWED_FILE_TYPES_DESCRIPTION, ALLOWED_MIME_TYPES, type Audience, type ConversationPagination, type ConversationSeenState, type ConversationTimelineItemsState, type ConversationTypingState, type ConversationWithSeen, type ConversationsState, type ConversationsStore, CossistantAPIError, CossistantClient, type CossistantConfig, type CossistantError, type CossistantMessageMetadata, type CossistantPartMetadata, CossistantRestClient, type CossistantUIMessage, type DefaultRoutes, FILE_INPUT_ACCEPT, type FilterOptions, type FromUIMessageContext, MAX_FILES_PER_MESSAGE, MAX_FILE_SIZE, type NavigationState, PrivacyPresets, type RouteRegistry, type SUPPORT_PAGES, type SeenActorType, type SeenEntry, type SeenState, type SeenStore, type SupportConfig, type SupportNavigation, type SupportPage, type SupportStore, type SupportStoreActions, type SupportStoreOptions, type SupportStoreState, type SupportStoreStorage, TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, type TimelineItemsState, type TimelineItemsStore, type TypingActorType, type TypingEntry, type TypingReporter, type TypingReporterConfig, type TypingState, type TypingStore, type TypingStoreDependencies, type VisitorData, type WebsiteError, type WebsiteState, type WebsiteStatus, type WebsiteStore, applyConversationSeenEvent, applyConversationTypingEvent, clearAllVisitorIds, clearTypingFromTimelineItem, clearTypingState, clearVisitorId, collectVisitorData, countVisibleParts, createConversationsStore, createSeenStore, createSupportStore, createTimelineItemsStore, createTypingReporter, createTypingStore, createWebsiteStore, CossistantClient as default, extractSources, extractToolCalls, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, formatFileSize, fromUIMessage, fromUIMessages, generateConversationId, generateMessageId, generateVisitorName, getConversationById, getConversationPagination, getConversationTimelineItems, getConversationTyping, getConversations, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hasProcessingParts, hasVisibleContent, hydrateConversationSeen, isAISDKCompatiblePart, isAllowedMimeType, isImageMimeType, normalizeLocale, setTypingState, setVisitorId, toUIMessage, toUIMessages, upsertConversationSeen, validateFile, validateFiles };
|
package/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages } from "./ai-sdk-utils.js";
|
|
1
2
|
import { CossistantAPIError } from "./types.js";
|
|
2
3
|
import { ALLOWED_FILE_TYPES_DESCRIPTION, ALLOWED_MIME_TYPES, FILE_INPUT_ACCEPT, MAX_FILES_PER_MESSAGE, MAX_FILE_SIZE, formatFileSize, isAllowedMimeType, isImageMimeType, validateFile, validateFiles } from "./upload-constants.js";
|
|
3
4
|
import { generateConversationId, generateMessageId } from "./utils.js";
|
|
@@ -9,10 +10,11 @@ import { createTimelineItemsStore, getConversationTimelineItems } from "./store/
|
|
|
9
10
|
import { createWebsiteStore, getWebsiteState } from "./store/website-store.js";
|
|
10
11
|
import { CossistantClient } from "./client.js";
|
|
11
12
|
import { normalizeLocale } from "./locale-utils.js";
|
|
13
|
+
import { PrivacyPresets, countVisibleParts, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, hasVisibleContent } from "./privacy-filter.js";
|
|
12
14
|
import { applyConversationSeenEvent, createSeenStore, hydrateConversationSeen, upsertConversationSeen } from "./store/seen-store.js";
|
|
13
15
|
import { createSupportStore } from "./store/support-store.js";
|
|
14
16
|
import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingState, createTypingStore, getConversationTyping, setTypingState } from "./store/typing-store.js";
|
|
15
17
|
import { TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, createTypingReporter } from "./typing-reporter.js";
|
|
16
18
|
import { generateVisitorName, getVisitorNameWithFallback } from "./visitor-name.js";
|
|
17
19
|
|
|
18
|
-
export { ALLOWED_FILE_TYPES_DESCRIPTION, ALLOWED_MIME_TYPES, CossistantAPIError, CossistantClient, CossistantRestClient, FILE_INPUT_ACCEPT, MAX_FILES_PER_MESSAGE, MAX_FILE_SIZE, TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, applyConversationSeenEvent, applyConversationTypingEvent, clearAllVisitorIds, clearTypingFromTimelineItem, clearTypingState, clearVisitorId, collectVisitorData, createConversationsStore, createSeenStore, createSupportStore, createTimelineItemsStore, createTypingReporter, createTypingStore, createWebsiteStore, CossistantClient as default, formatFileSize, generateConversationId, generateMessageId, generateVisitorName, getConversationById, getConversationPagination, getConversationTimelineItems, getConversationTyping, getConversations, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hydrateConversationSeen, isAllowedMimeType, isImageMimeType, normalizeLocale, setTypingState, setVisitorId, upsertConversationSeen, validateFile, validateFiles };
|
|
20
|
+
export { ALLOWED_FILE_TYPES_DESCRIPTION, ALLOWED_MIME_TYPES, CossistantAPIError, CossistantClient, CossistantRestClient, FILE_INPUT_ACCEPT, MAX_FILES_PER_MESSAGE, MAX_FILE_SIZE, PrivacyPresets, TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, applyConversationSeenEvent, applyConversationTypingEvent, clearAllVisitorIds, clearTypingFromTimelineItem, clearTypingState, clearVisitorId, collectVisitorData, countVisibleParts, createConversationsStore, createSeenStore, createSupportStore, createTimelineItemsStore, createTypingReporter, createTypingStore, createWebsiteStore, CossistantClient as default, extractSources, extractToolCalls, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, formatFileSize, fromUIMessage, fromUIMessages, generateConversationId, generateMessageId, generateVisitorName, getConversationById, getConversationPagination, getConversationTimelineItems, getConversationTyping, getConversations, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hasProcessingParts, hasVisibleContent, hydrateConversationSeen, isAISDKCompatiblePart, isAllowedMimeType, isImageMimeType, normalizeLocale, setTypingState, setVisitorId, toUIMessage, toUIMessages, upsertConversationSeen, validateFile, validateFiles };
|
package/package.json
CHANGED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { CossistantUIMessage } from "./ai-sdk-utils.js";
|
|
2
|
+
import { TimelineItem } from "@cossistant/types";
|
|
3
|
+
|
|
4
|
+
//#region src/privacy-filter.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Audience types for filtering
|
|
8
|
+
*/
|
|
9
|
+
type Audience = "dashboard" | "widget";
|
|
10
|
+
/**
|
|
11
|
+
* Privacy filter options
|
|
12
|
+
*/
|
|
13
|
+
type FilterOptions = {
|
|
14
|
+
/**
|
|
15
|
+
* Whether to include reasoning parts (AI chain-of-thought)
|
|
16
|
+
* Default: true for dashboard, false for widget
|
|
17
|
+
*/
|
|
18
|
+
includeReasoning?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether to include tool parts
|
|
21
|
+
* Default: true for dashboard, based on visibility for widget
|
|
22
|
+
*/
|
|
23
|
+
includeTools?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Whether to include source attributions
|
|
26
|
+
* Default: true
|
|
27
|
+
*/
|
|
28
|
+
includeSources?: boolean;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Filter a CossistantUIMessage for a specific audience
|
|
32
|
+
*
|
|
33
|
+
* @param message - The message to filter
|
|
34
|
+
* @param audience - The target audience ('dashboard' or 'widget')
|
|
35
|
+
* @param options - Optional filter options
|
|
36
|
+
* @returns The filtered message, or null if the entire message should be hidden
|
|
37
|
+
*/
|
|
38
|
+
declare function filterMessageForAudience(message: CossistantUIMessage, audience: Audience, options?: FilterOptions): CossistantUIMessage | null;
|
|
39
|
+
/**
|
|
40
|
+
* Filter multiple messages for an audience
|
|
41
|
+
*
|
|
42
|
+
* @param messages - The messages to filter
|
|
43
|
+
* @param audience - The target audience
|
|
44
|
+
* @param options - Optional filter options
|
|
45
|
+
* @returns Filtered messages (excluding any that become null)
|
|
46
|
+
*/
|
|
47
|
+
declare function filterMessagesForAudience(messages: CossistantUIMessage[], audience: Audience, options?: FilterOptions): CossistantUIMessage[];
|
|
48
|
+
/**
|
|
49
|
+
* Filter a TimelineItem for a specific audience
|
|
50
|
+
*
|
|
51
|
+
* @param item - The timeline item to filter
|
|
52
|
+
* @param audience - The target audience
|
|
53
|
+
* @param options - Optional filter options
|
|
54
|
+
* @returns The filtered item, or null if the entire item should be hidden
|
|
55
|
+
*/
|
|
56
|
+
declare function filterTimelineItemForAudience(item: TimelineItem, audience: Audience, options?: FilterOptions): TimelineItem | null;
|
|
57
|
+
/**
|
|
58
|
+
* Filter multiple timeline items for an audience
|
|
59
|
+
*
|
|
60
|
+
* @param items - The timeline items to filter
|
|
61
|
+
* @param audience - The target audience
|
|
62
|
+
* @param options - Optional filter options
|
|
63
|
+
* @returns Filtered items (excluding any that become null)
|
|
64
|
+
*/
|
|
65
|
+
declare function filterTimelineItemsForAudience(items: TimelineItem[], audience: Audience, options?: FilterOptions): TimelineItem[];
|
|
66
|
+
/**
|
|
67
|
+
* Privacy presets for common use cases
|
|
68
|
+
*/
|
|
69
|
+
declare const PrivacyPresets: {
|
|
70
|
+
/**
|
|
71
|
+
* TRANSPARENT: Show everything including AI reasoning
|
|
72
|
+
* Use for: Internal debugging, transparency-focused products
|
|
73
|
+
*/
|
|
74
|
+
readonly TRANSPARENT: {
|
|
75
|
+
includeReasoning: true;
|
|
76
|
+
includeTools: true;
|
|
77
|
+
includeSources: true;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* STANDARD: Default widget experience
|
|
81
|
+
* Use for: Most customer-facing widgets
|
|
82
|
+
*/
|
|
83
|
+
readonly STANDARD: {
|
|
84
|
+
includeReasoning: false;
|
|
85
|
+
includeTools: true;
|
|
86
|
+
includeSources: true;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* MINIMAL: Only show text responses
|
|
90
|
+
* Use for: Simple chatbots, text-only experiences
|
|
91
|
+
*/
|
|
92
|
+
readonly MINIMAL: {
|
|
93
|
+
includeReasoning: false;
|
|
94
|
+
includeTools: false;
|
|
95
|
+
includeSources: false;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Check if a message has any visible content for an audience
|
|
100
|
+
*/
|
|
101
|
+
declare function hasVisibleContent(message: CossistantUIMessage, audience: Audience, options?: FilterOptions): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Count visible parts for an audience
|
|
104
|
+
*/
|
|
105
|
+
declare function countVisibleParts(message: CossistantUIMessage, audience: Audience, options?: FilterOptions): number;
|
|
106
|
+
/**
|
|
107
|
+
* Extract only text content from a message (for previews, notifications, etc.)
|
|
108
|
+
*/
|
|
109
|
+
declare function extractVisibleText(message: CossistantUIMessage, audience: Audience): string | null;
|
|
110
|
+
//#endregion
|
|
111
|
+
export { Audience, FilterOptions, PrivacyPresets, countVisibleParts, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, hasVisibleContent };
|
|
112
|
+
//# sourceMappingURL=privacy-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privacy-filter.d.ts","names":[],"sources":["../src/privacy-filter.ts"],"sourcesContent":[],"mappings":";;;;;;AAiHA;;AAEW,KA3FC,QAAA,GA2FD,WAAA,GAAA,QAAA;;;;AAoBK,KA1GJ,aAAA,GA0GI;EACT;;;;EAGQ,gBAAA,CAAA,EAAA,OAAA;EAgCC;;;;EAIb,YAAA,CAAA,EAAA,OAAA;EAAY;AA6Hf;AAuCA;;EAEW,cAAA,CAAA,EAAA,OAAA;CACA;;AAQX;;;;;AAYA;;iBA7RgB,wBAAA,UACN,+BACC,oBACA,gBACR;;;;;;;;;iBAgCa,yBAAA,WACL,iCACA,oBACA,gBACR;;;;;;;;;iBAkBa,6BAAA,OACT,wBACI,oBACA,gBACR;;;;;;;;;iBAgCa,8BAAA,QACR,0BACG,oBACA,gBACR;;;;cA6HU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCG,iBAAA,UACN,+BACC,oBACA;;;;iBAQK,iBAAA,UACN,+BACC,oBACA;;;;iBASK,kBAAA,UACN,+BACC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
//#region src/privacy-filter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Default filter options for each audience
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_OPTIONS = {
|
|
6
|
+
dashboard: {
|
|
7
|
+
includeReasoning: true,
|
|
8
|
+
includeTools: true,
|
|
9
|
+
includeSources: true
|
|
10
|
+
},
|
|
11
|
+
widget: {
|
|
12
|
+
includeReasoning: false,
|
|
13
|
+
includeTools: true,
|
|
14
|
+
includeSources: true
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Filter a CossistantUIMessage for a specific audience
|
|
19
|
+
*
|
|
20
|
+
* @param message - The message to filter
|
|
21
|
+
* @param audience - The target audience ('dashboard' or 'widget')
|
|
22
|
+
* @param options - Optional filter options
|
|
23
|
+
* @returns The filtered message, or null if the entire message should be hidden
|
|
24
|
+
*/
|
|
25
|
+
function filterMessageForAudience(message, audience, options) {
|
|
26
|
+
const opts = {
|
|
27
|
+
...DEFAULT_OPTIONS[audience],
|
|
28
|
+
...options
|
|
29
|
+
};
|
|
30
|
+
if (audience === "widget" && message.metadata.visibility === "private") return null;
|
|
31
|
+
const filteredParts = message.parts.filter((part) => shouldIncludePart(part, audience, opts));
|
|
32
|
+
if (filteredParts.length === 0) return null;
|
|
33
|
+
return {
|
|
34
|
+
...message,
|
|
35
|
+
parts: filteredParts
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Filter multiple messages for an audience
|
|
40
|
+
*
|
|
41
|
+
* @param messages - The messages to filter
|
|
42
|
+
* @param audience - The target audience
|
|
43
|
+
* @param options - Optional filter options
|
|
44
|
+
* @returns Filtered messages (excluding any that become null)
|
|
45
|
+
*/
|
|
46
|
+
function filterMessagesForAudience(messages, audience, options) {
|
|
47
|
+
return messages.map((msg) => filterMessageForAudience(msg, audience, options)).filter((msg) => msg !== null);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Filter a TimelineItem for a specific audience
|
|
51
|
+
*
|
|
52
|
+
* @param item - The timeline item to filter
|
|
53
|
+
* @param audience - The target audience
|
|
54
|
+
* @param options - Optional filter options
|
|
55
|
+
* @returns The filtered item, or null if the entire item should be hidden
|
|
56
|
+
*/
|
|
57
|
+
function filterTimelineItemForAudience(item, audience, options) {
|
|
58
|
+
const opts = {
|
|
59
|
+
...DEFAULT_OPTIONS[audience],
|
|
60
|
+
...options
|
|
61
|
+
};
|
|
62
|
+
if (audience === "widget" && item.visibility === "private") return null;
|
|
63
|
+
const filteredParts = item.parts.filter((part) => shouldIncludeTimelineItemPart(part, audience, opts));
|
|
64
|
+
if (filteredParts.length === 0) return null;
|
|
65
|
+
return {
|
|
66
|
+
...item,
|
|
67
|
+
parts: filteredParts
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Filter multiple timeline items for an audience
|
|
72
|
+
*
|
|
73
|
+
* @param items - The timeline items to filter
|
|
74
|
+
* @param audience - The target audience
|
|
75
|
+
* @param options - Optional filter options
|
|
76
|
+
* @returns Filtered items (excluding any that become null)
|
|
77
|
+
*/
|
|
78
|
+
function filterTimelineItemsForAudience(items, audience, options) {
|
|
79
|
+
return items.map((item) => filterTimelineItemForAudience(item, audience, options)).filter((item) => item !== null);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Determine if an AI SDK part should be included based on audience and options
|
|
83
|
+
*/
|
|
84
|
+
function shouldIncludePart(part, audience, opts) {
|
|
85
|
+
const visibility = getPartVisibility(part);
|
|
86
|
+
if (audience === "widget" && visibility === "private") return false;
|
|
87
|
+
if (part.type === "reasoning") return opts.includeReasoning;
|
|
88
|
+
if (typeof part.type === "string" && part.type.startsWith("tool-")) {
|
|
89
|
+
if (!opts.includeTools) return false;
|
|
90
|
+
if (audience === "widget" && visibility !== "public") return false;
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
if (part.type === "source-url" || part.type === "source-document") return opts.includeSources;
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Determine if a TimelineItem part should be included based on audience and options
|
|
98
|
+
*/
|
|
99
|
+
function shouldIncludeTimelineItemPart(part, audience, opts) {
|
|
100
|
+
const visibility = getTimelineItemPartVisibility(part);
|
|
101
|
+
if (audience === "widget" && visibility === "private") return false;
|
|
102
|
+
if (part.type === "reasoning") return opts.includeReasoning;
|
|
103
|
+
if (typeof part.type === "string" && part.type.startsWith("tool-")) {
|
|
104
|
+
if (!opts.includeTools) return false;
|
|
105
|
+
if (audience === "widget" && visibility !== "public") return false;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (part.type === "source-url" || part.type === "source-document") return opts.includeSources;
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Extract visibility from an AI SDK part's providerMetadata
|
|
113
|
+
*/
|
|
114
|
+
function getPartVisibility(part) {
|
|
115
|
+
if ("providerMetadata" in part && part.providerMetadata) return part.providerMetadata.cossistant?.visibility ?? "public";
|
|
116
|
+
return "public";
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Extract visibility from a TimelineItem part's providerMetadata
|
|
120
|
+
*/
|
|
121
|
+
function getTimelineItemPartVisibility(part) {
|
|
122
|
+
if ("providerMetadata" in part) return part.providerMetadata?.cossistant?.visibility ?? "public";
|
|
123
|
+
return "public";
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Privacy presets for common use cases
|
|
127
|
+
*/
|
|
128
|
+
const PrivacyPresets = {
|
|
129
|
+
TRANSPARENT: {
|
|
130
|
+
includeReasoning: true,
|
|
131
|
+
includeTools: true,
|
|
132
|
+
includeSources: true
|
|
133
|
+
},
|
|
134
|
+
STANDARD: {
|
|
135
|
+
includeReasoning: false,
|
|
136
|
+
includeTools: true,
|
|
137
|
+
includeSources: true
|
|
138
|
+
},
|
|
139
|
+
MINIMAL: {
|
|
140
|
+
includeReasoning: false,
|
|
141
|
+
includeTools: false,
|
|
142
|
+
includeSources: false
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Check if a message has any visible content for an audience
|
|
147
|
+
*/
|
|
148
|
+
function hasVisibleContent(message, audience, options) {
|
|
149
|
+
return filterMessageForAudience(message, audience, options) !== null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Count visible parts for an audience
|
|
153
|
+
*/
|
|
154
|
+
function countVisibleParts(message, audience, options) {
|
|
155
|
+
return filterMessageForAudience(message, audience, options)?.parts.length ?? 0;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Extract only text content from a message (for previews, notifications, etc.)
|
|
159
|
+
*/
|
|
160
|
+
function extractVisibleText(message, audience) {
|
|
161
|
+
const filtered = filterMessageForAudience(message, audience);
|
|
162
|
+
if (!filtered) return null;
|
|
163
|
+
const textParts = filtered.parts.filter((part) => part.type === "text");
|
|
164
|
+
if (textParts.length === 0) return null;
|
|
165
|
+
return textParts.map((p) => p.text).join("\n");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
//#endregion
|
|
169
|
+
export { PrivacyPresets, countVisibleParts, extractVisibleText, filterMessageForAudience, filterMessagesForAudience, filterTimelineItemForAudience, filterTimelineItemsForAudience, hasVisibleContent };
|
|
170
|
+
//# sourceMappingURL=privacy-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"privacy-filter.js","names":["DEFAULT_OPTIONS: Record<Audience, Required<FilterOptions>>"],"sources":["../src/privacy-filter.ts"],"sourcesContent":["/**\n * Privacy Filter Utilities\n *\n * This module provides utilities for filtering timeline items and parts\n * based on audience (dashboard vs widget). The dashboard sees everything,\n * while the widget only sees public content.\n *\n * Filtering happens at the API layer, not baked into types.\n */\n\nimport type { TimelineItem, TimelineItemParts } from \"@cossistant/types\";\nimport type {\n\tAISDKPart,\n\tCossistantPartMetadata,\n\tCossistantUIMessage,\n} from \"./ai-sdk-utils\";\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Audience types for filtering\n */\nexport type Audience = \"dashboard\" | \"widget\";\n\n/**\n * Privacy filter options\n */\nexport type FilterOptions = {\n\t/**\n\t * Whether to include reasoning parts (AI chain-of-thought)\n\t * Default: true for dashboard, false for widget\n\t */\n\tincludeReasoning?: boolean;\n\n\t/**\n\t * Whether to include tool parts\n\t * Default: true for dashboard, based on visibility for widget\n\t */\n\tincludeTools?: boolean;\n\n\t/**\n\t * Whether to include source attributions\n\t * Default: true\n\t */\n\tincludeSources?: boolean;\n};\n\n/**\n * Default filter options for each audience\n */\nconst DEFAULT_OPTIONS: Record<Audience, Required<FilterOptions>> = {\n\tdashboard: {\n\t\tincludeReasoning: true,\n\t\tincludeTools: true,\n\t\tincludeSources: true,\n\t},\n\twidget: {\n\t\tincludeReasoning: false,\n\t\tincludeTools: true, // but filtered by visibility\n\t\tincludeSources: true,\n\t},\n};\n\n// ============================================================================\n// COSSISTANT UI MESSAGE FILTERING\n// ============================================================================\n\n/**\n * Filter a CossistantUIMessage for a specific audience\n *\n * @param message - The message to filter\n * @param audience - The target audience ('dashboard' or 'widget')\n * @param options - Optional filter options\n * @returns The filtered message, or null if the entire message should be hidden\n */\nexport function filterMessageForAudience(\n\tmessage: CossistantUIMessage,\n\taudience: Audience,\n\toptions?: FilterOptions\n): CossistantUIMessage | null {\n\tconst opts = { ...DEFAULT_OPTIONS[audience], ...options };\n\n\t// Widget can't see private messages\n\tif (audience === \"widget\" && message.metadata.visibility === \"private\") {\n\t\treturn null;\n\t}\n\n\t// Filter parts based on audience\n\tconst filteredParts = message.parts.filter((part) =>\n\t\tshouldIncludePart(part, audience, opts)\n\t);\n\n\t// If no parts remain, return null (empty message)\n\tif (filteredParts.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\t...message,\n\t\tparts: filteredParts,\n\t};\n}\n\n/**\n * Filter multiple messages for an audience\n *\n * @param messages - The messages to filter\n * @param audience - The target audience\n * @param options - Optional filter options\n * @returns Filtered messages (excluding any that become null)\n */\nexport function filterMessagesForAudience(\n\tmessages: CossistantUIMessage[],\n\taudience: Audience,\n\toptions?: FilterOptions\n): CossistantUIMessage[] {\n\treturn messages\n\t\t.map((msg) => filterMessageForAudience(msg, audience, options))\n\t\t.filter((msg): msg is CossistantUIMessage => msg !== null);\n}\n\n// ============================================================================\n// TIMELINE ITEM FILTERING (Direct, without conversion)\n// ============================================================================\n\n/**\n * Filter a TimelineItem for a specific audience\n *\n * @param item - The timeline item to filter\n * @param audience - The target audience\n * @param options - Optional filter options\n * @returns The filtered item, or null if the entire item should be hidden\n */\nexport function filterTimelineItemForAudience(\n\titem: TimelineItem,\n\taudience: Audience,\n\toptions?: FilterOptions\n): TimelineItem | null {\n\tconst opts = { ...DEFAULT_OPTIONS[audience], ...options };\n\n\t// Widget can't see private items\n\tif (audience === \"widget\" && item.visibility === \"private\") {\n\t\treturn null;\n\t}\n\n\t// Filter parts based on audience\n\tconst filteredParts = item.parts.filter((part) =>\n\t\tshouldIncludeTimelineItemPart(part, audience, opts)\n\t);\n\n\t// If no parts remain, return null (empty item)\n\tif (filteredParts.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\t...item,\n\t\tparts: filteredParts as TimelineItemParts,\n\t};\n}\n\n/**\n * Filter multiple timeline items for an audience\n *\n * @param items - The timeline items to filter\n * @param audience - The target audience\n * @param options - Optional filter options\n * @returns Filtered items (excluding any that become null)\n */\nexport function filterTimelineItemsForAudience(\n\titems: TimelineItem[],\n\taudience: Audience,\n\toptions?: FilterOptions\n): TimelineItem[] {\n\treturn items\n\t\t.map((item) => filterTimelineItemForAudience(item, audience, options))\n\t\t.filter((item): item is TimelineItem => item !== null);\n}\n\n// ============================================================================\n// PART-LEVEL FILTERING\n// ============================================================================\n\n/**\n * Determine if an AI SDK part should be included based on audience and options\n */\nfunction shouldIncludePart(\n\tpart: AISDKPart,\n\taudience: Audience,\n\topts: Required<FilterOptions>\n): boolean {\n\t// Check part visibility from providerMetadata\n\tconst visibility = getPartVisibility(part);\n\tif (audience === \"widget\" && visibility === \"private\") {\n\t\treturn false;\n\t}\n\n\t// Handle reasoning parts\n\tif (part.type === \"reasoning\") {\n\t\treturn opts.includeReasoning;\n\t}\n\n\t// Handle tool parts\n\tif (typeof part.type === \"string\" && part.type.startsWith(\"tool-\")) {\n\t\tif (!opts.includeTools) {\n\t\t\treturn false;\n\t\t}\n\t\t// For widget, check if the tool part is marked as public\n\t\tif (audience === \"widget\" && visibility !== \"public\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Handle source parts\n\tif (part.type === \"source-url\" || part.type === \"source-document\") {\n\t\treturn opts.includeSources;\n\t}\n\n\t// Include all other parts by default\n\treturn true;\n}\n\n/**\n * Determine if a TimelineItem part should be included based on audience and options\n */\nfunction shouldIncludeTimelineItemPart(\n\tpart: TimelineItemParts[number],\n\taudience: Audience,\n\topts: Required<FilterOptions>\n): boolean {\n\t// Check part visibility from providerMetadata\n\tconst visibility = getTimelineItemPartVisibility(part);\n\tif (audience === \"widget\" && visibility === \"private\") {\n\t\treturn false;\n\t}\n\n\t// Handle reasoning parts\n\tif (part.type === \"reasoning\") {\n\t\treturn opts.includeReasoning;\n\t}\n\n\t// Handle tool parts\n\tif (typeof part.type === \"string\" && part.type.startsWith(\"tool-\")) {\n\t\tif (!opts.includeTools) {\n\t\t\treturn false;\n\t\t}\n\t\t// For widget, check if the tool part is marked as public\n\t\tif (audience === \"widget\" && visibility !== \"public\") {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// Handle source parts\n\tif (part.type === \"source-url\" || part.type === \"source-document\") {\n\t\treturn opts.includeSources;\n\t}\n\n\t// Include all other parts by default\n\treturn true;\n}\n\n/**\n * Extract visibility from an AI SDK part's providerMetadata\n */\nfunction getPartVisibility(part: AISDKPart): \"public\" | \"private\" {\n\tif (\"providerMetadata\" in part && part.providerMetadata) {\n\t\tconst metadata = part.providerMetadata as {\n\t\t\tcossistant?: CossistantPartMetadata;\n\t\t};\n\t\treturn metadata.cossistant?.visibility ?? \"public\";\n\t}\n\treturn \"public\";\n}\n\n/**\n * Extract visibility from a TimelineItem part's providerMetadata\n */\nfunction getTimelineItemPartVisibility(\n\tpart: TimelineItemParts[number]\n): \"public\" | \"private\" {\n\tif (\"providerMetadata\" in part) {\n\t\tconst typedPart = part as {\n\t\t\tproviderMetadata?: { cossistant?: CossistantPartMetadata };\n\t\t};\n\t\treturn typedPart.providerMetadata?.cossistant?.visibility ?? \"public\";\n\t}\n\treturn \"public\";\n}\n\n// ============================================================================\n// PRIVACY PRESETS\n// ============================================================================\n\n/**\n * Privacy presets for common use cases\n */\nexport const PrivacyPresets = {\n\t/**\n\t * TRANSPARENT: Show everything including AI reasoning\n\t * Use for: Internal debugging, transparency-focused products\n\t */\n\tTRANSPARENT: {\n\t\tincludeReasoning: true,\n\t\tincludeTools: true,\n\t\tincludeSources: true,\n\t} satisfies FilterOptions,\n\n\t/**\n\t * STANDARD: Default widget experience\n\t * Use for: Most customer-facing widgets\n\t */\n\tSTANDARD: {\n\t\tincludeReasoning: false,\n\t\tincludeTools: true,\n\t\tincludeSources: true,\n\t} satisfies FilterOptions,\n\n\t/**\n\t * MINIMAL: Only show text responses\n\t * Use for: Simple chatbots, text-only experiences\n\t */\n\tMINIMAL: {\n\t\tincludeReasoning: false,\n\t\tincludeTools: false,\n\t\tincludeSources: false,\n\t} satisfies FilterOptions,\n} as const;\n\n// ============================================================================\n// UTILITY FUNCTIONS\n// ============================================================================\n\n/**\n * Check if a message has any visible content for an audience\n */\nexport function hasVisibleContent(\n\tmessage: CossistantUIMessage,\n\taudience: Audience,\n\toptions?: FilterOptions\n): boolean {\n\treturn filterMessageForAudience(message, audience, options) !== null;\n}\n\n/**\n * Count visible parts for an audience\n */\nexport function countVisibleParts(\n\tmessage: CossistantUIMessage,\n\taudience: Audience,\n\toptions?: FilterOptions\n): number {\n\tconst filtered = filterMessageForAudience(message, audience, options);\n\treturn filtered?.parts.length ?? 0;\n}\n\n/**\n * Extract only text content from a message (for previews, notifications, etc.)\n */\nexport function extractVisibleText(\n\tmessage: CossistantUIMessage,\n\taudience: Audience\n): string | null {\n\tconst filtered = filterMessageForAudience(message, audience);\n\tif (!filtered) {\n\t\treturn null;\n\t}\n\n\tconst textParts = filtered.parts.filter(\n\t\t(part): part is { type: \"text\"; text: string } => part.type === \"text\"\n\t);\n\n\tif (textParts.length === 0) {\n\t\treturn null;\n\t}\n\treturn textParts.map((p) => p.text).join(\"\\n\");\n}\n"],"mappings":"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"}
|
package/rest-client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./conversation.js";
|
|
2
|
-
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse } from "./timeline-item.js";
|
|
3
|
-
import { IdentifyContactResponse } from "./contact.js";
|
|
4
|
-
import { GenerateUploadUrlRequest, GenerateUploadUrlResponse } from "./upload.js";
|
|
1
|
+
import { CreateConversationRequestBody, CreateConversationResponseBody, GetConversationRequest, GetConversationResponse, GetConversationSeenDataResponse, ListConversationsRequest, ListConversationsResponse, MarkConversationSeenRequestBody, MarkConversationSeenResponseBody, SetConversationTypingResponseBody } from "./types/src/api/conversation.js";
|
|
2
|
+
import { GetConversationTimelineItemsRequest, GetConversationTimelineItemsResponse, SendTimelineItemRequest, SendTimelineItemResponse } from "./types/src/api/timeline-item.js";
|
|
3
|
+
import { IdentifyContactResponse } from "./types/src/api/contact.js";
|
|
4
|
+
import { GenerateUploadUrlRequest, GenerateUploadUrlResponse } from "./types/src/api/upload.js";
|
|
5
5
|
import { types_d_exports } from "./types.js";
|
|
6
6
|
|
|
7
7
|
//#region src/rest-client.d.ts
|
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":";;;;;;;cA8Ca,oBAAA;;EAAA,QAAA,WAAA;EAQQ,QAAA,SAAA;
|
|
1
|
+
{"version":3,"file":"rest-client.d.ts","names":[],"sources":["../src/rest-client.ts"],"sourcesContent":[],"mappings":";;;;;;;cA8Ca,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;EAwBQ,kBAAA,CAAA,MAAA,CAAA,EA1OH,OA0OG,CA1OK,6BA0OL,CAAA,CAAA,EAzOT,OAyOS,CAzOD,8BAyOC,CAAA;EAAR,mBAAA,CAAA,MAAA,EAzL8B,OAyL9B,CAzLsC,eAAA,CAAA,gBAyLtC,CAAA,CAAA,EAzL0D,OAyL1D,CAAA,IAAA,CAAA;EA6CK,iBAAA,CAAA,MAAA,CAAA,EA9MA,OA8MA,CA9MQ,wBA8MR,CAAA,CAAA,EA7MN,OA6MM,CA7ME,yBA6MF,CAAA;EACE,eAAA,CAAA,MAAA,EA7IF,sBA6IE,CAAA,EA5IR,OA4IQ,CA5IA,uBA4IA,CAAA;EAAR,oBAAA,CAAA,MAAA,EAAA;IAsBM,cAAA,EAAA,MAAA;EACE,CAAA,GAnIN,OAmIM,CAnIE,+BAmIF,CAAA,CAAA,EAlIR,OAkIQ,CAlIA,gCAkIA,CAAA;EAAR,uBAAA,CAAA,MAAA,EAAA;IAwCW,cAAA,EAAA,MAAA;EAAL,CAAA,CAAA,EArIL,OAqIK,CArIG,+BAqIH,CAAA;EAGE,qBAAA,CAAA,MAAA,EAAA;IAAR,cAAA,EAAA,MAAA;IA2DI,QAAA,EAAA,OAAA;IAGJ,cAAA,CAAA,EAAA,MAAA,GAAA,IAAA;IA4BK,SAAA,CAAA,EAAA,MAAA;EAGP,CAAA,CAAA,EA7MG,OA6MH,CA7MW,iCA6MX,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
|
@@ -15,8 +15,8 @@ var CossistantRestClient = class {
|
|
|
15
15
|
visitorBlocked = false;
|
|
16
16
|
constructor(config) {
|
|
17
17
|
this.config = config;
|
|
18
|
-
this.publicKey = config.publicKey || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY : void 0) || (typeof process !== "undefined" ? process.env.COSSISTANT_API_KEY : void 0) ||
|
|
19
|
-
if (!this.publicKey) throw new Error("Public key is required. Please provide it in the config or set NEXT_PUBLIC_COSSISTANT_API_KEY or COSSISTANT_API_KEY environment variable.");
|
|
18
|
+
this.publicKey = config.publicKey || (typeof process !== "undefined" ? process.env.NEXT_PUBLIC_COSSISTANT_API_KEY : void 0) || (typeof process !== "undefined" ? process.env.COSSISTANT_API_KEY : void 0) || "";
|
|
19
|
+
if (!this.publicKey) throw new Error("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.");
|
|
20
20
|
this.baseHeaders = {
|
|
21
21
|
"Content-Type": "application/json",
|
|
22
22
|
"X-Public-Key": this.publicKey
|
|
@@ -238,12 +238,12 @@ var CossistantRestClient = class {
|
|
|
238
238
|
}
|
|
239
239
|
if (config.userId) this.baseHeaders["X-User-ID"] = config.userId;
|
|
240
240
|
else if (config.userId === null) {
|
|
241
|
-
const { "X-User-ID": _
|
|
241
|
+
const { "X-User-ID": _, ...rest } = this.baseHeaders;
|
|
242
242
|
this.baseHeaders = rest;
|
|
243
243
|
}
|
|
244
244
|
if (config.organizationId) this.baseHeaders["X-Organization-ID"] = config.organizationId;
|
|
245
245
|
else if (config.organizationId === null) {
|
|
246
|
-
const { "X-Organization-ID": _
|
|
246
|
+
const { "X-Organization-ID": _, ...rest } = this.baseHeaders;
|
|
247
247
|
this.baseHeaders = rest;
|
|
248
248
|
}
|
|
249
249
|
this.config = {
|