@cossistant/core 0.0.32 → 0.1.0
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 +33 -3
- package/ai-sdk-utils.d.ts.map +1 -1
- package/ai-sdk-utils.js +85 -21
- package/ai-sdk-utils.js.map +1 -1
- package/client.d.ts +1 -0
- package/client.d.ts.map +1 -1
- package/client.js +5 -0
- package/client.js.map +1 -1
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/package.json +1 -1
- package/privacy-filter.d.ts.map +1 -1
- package/privacy-filter.js +7 -2
- package/privacy-filter.js.map +1 -1
- package/store/timeline-items-store.d.ts.map +1 -1
- package/types/src/api/conversation.d.ts +383 -8
- package/types/src/api/conversation.d.ts.map +1 -1
- package/types/src/api/timeline-item.d.ts +304 -4
- package/types/src/api/timeline-item.d.ts.map +1 -1
- package/types/src/api/timeline-item.js +14 -1
- package/types/src/api/timeline-item.js.map +1 -1
- package/types/src/realtime-events.d.ts +233 -8
- package/types/src/realtime-events.d.ts.map +1 -1
- package/types/src/schemas.d.ts +77 -2
- package/types/src/schemas.d.ts.map +1 -1
- package/types/src/tool-timeline-policy.js +16 -0
- package/types/src/tool-timeline-policy.js.map +1 -0
- package/utils.d.ts.map +1 -1
package/ai-sdk-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TimelineItem, TimelineItemParts } from "@cossistant/types";
|
|
1
|
+
import { TimelineItem, TimelineItemParts, ToolTimelineLogType } from "@cossistant/types";
|
|
2
2
|
|
|
3
3
|
//#region src/ai-sdk-utils.d.ts
|
|
4
4
|
|
|
@@ -24,6 +24,7 @@ type AISDKToolPart = {
|
|
|
24
24
|
output?: unknown;
|
|
25
25
|
state: "partial" | "result" | "error";
|
|
26
26
|
errorText?: string;
|
|
27
|
+
callProviderMetadata?: Record<string, unknown>;
|
|
27
28
|
providerMetadata?: Record<string, unknown>;
|
|
28
29
|
};
|
|
29
30
|
type AISDKSourceUrlPart = {
|
|
@@ -66,15 +67,44 @@ type CossistantMessageMetadata = {
|
|
|
66
67
|
tool?: string | null;
|
|
67
68
|
};
|
|
68
69
|
/**
|
|
69
|
-
* Cossistant-specific metadata stored in part.providerMetadata.cossistant
|
|
70
|
+
* Cossistant-specific metadata stored in part.callProviderMetadata/providerMetadata.cossistant
|
|
70
71
|
*/
|
|
72
|
+
type CossistantToolTimelineMetadata = {
|
|
73
|
+
logType: ToolTimelineLogType;
|
|
74
|
+
triggerMessageId: string;
|
|
75
|
+
workflowRunId: string;
|
|
76
|
+
triggerVisibility?: "public" | "private";
|
|
77
|
+
};
|
|
71
78
|
type CossistantPartMetadata = {
|
|
72
79
|
visibility?: "public" | "private";
|
|
73
80
|
progressMessage?: string;
|
|
74
81
|
knowledgeId?: string;
|
|
82
|
+
toolTimeline?: CossistantToolTimelineMetadata;
|
|
83
|
+
};
|
|
84
|
+
type AISDKPartMetadataCarrier = {
|
|
85
|
+
providerMetadata?: Record<string, unknown>;
|
|
86
|
+
callProviderMetadata?: Record<string, unknown>;
|
|
75
87
|
};
|
|
76
88
|
type AISDKPart = AISDKTextPart | AISDKReasoningPart | AISDKToolPart | AISDKSourceUrlPart | AISDKSourceDocumentPart | AISDKStepStartPart | AISDKFilePart;
|
|
77
89
|
type CossistantPart = TimelineItemParts[number];
|
|
90
|
+
/**
|
|
91
|
+
* Read cossistant part metadata from AI SDK v6-compatible part metadata.
|
|
92
|
+
* Prefers callProviderMetadata but accepts providerMetadata for backward compatibility.
|
|
93
|
+
*/
|
|
94
|
+
declare function getCossistantPartMetadata(part: AISDKPartMetadataCarrier): CossistantPartMetadata | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* Write cossistant part metadata into both callProviderMetadata and providerMetadata.
|
|
97
|
+
* This keeps AI SDK v6 semantics while remaining backward compatible.
|
|
98
|
+
*/
|
|
99
|
+
declare function setCossistantPartMetadata(part: AISDKPartMetadataCarrier, metadata: CossistantPartMetadata): AISDKPartMetadataCarrier;
|
|
100
|
+
/**
|
|
101
|
+
* Read tool timeline metadata from cossistant part metadata.
|
|
102
|
+
*/
|
|
103
|
+
declare function getCossistantToolTimelineMetadata(part: AISDKPartMetadataCarrier): CossistantToolTimelineMetadata | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Write tool timeline metadata into cossistant part metadata.
|
|
106
|
+
*/
|
|
107
|
+
declare function setCossistantToolTimelineMetadata(part: AISDKPartMetadataCarrier, toolTimeline: CossistantToolTimelineMetadata): AISDKPartMetadataCarrier;
|
|
78
108
|
/**
|
|
79
109
|
* Cossistant-compatible UIMessage type
|
|
80
110
|
* This is structurally compatible with AI SDK v6 UIMessage
|
|
@@ -137,5 +167,5 @@ declare function extractToolCalls(parts: AISDKPart[]): AISDKToolPart[];
|
|
|
137
167
|
*/
|
|
138
168
|
declare function hasProcessingParts(parts: AISDKPart[]): boolean;
|
|
139
169
|
//#endregion
|
|
140
|
-
export { AISDKFilePart, AISDKPart, AISDKReasoningPart, AISDKSourceDocumentPart, AISDKSourceUrlPart, AISDKStepStartPart, AISDKTextPart, AISDKToolPart, CossistantMessageMetadata, CossistantPartMetadata, CossistantUIMessage, FromUIMessageContext, extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages };
|
|
170
|
+
export { AISDKFilePart, AISDKPart, AISDKReasoningPart, AISDKSourceDocumentPart, AISDKSourceUrlPart, AISDKStepStartPart, AISDKTextPart, AISDKToolPart, CossistantMessageMetadata, CossistantPartMetadata, CossistantToolTimelineMetadata, CossistantUIMessage, FromUIMessageContext, extractSources, extractToolCalls, fromUIMessage, fromUIMessages, getCossistantPartMetadata, getCossistantToolTimelineMetadata, hasProcessingParts, isAISDKCompatiblePart, setCossistantPartMetadata, setCossistantToolTimelineMetadata, toUIMessage, toUIMessages };
|
|
141
171
|
//# sourceMappingURL=ai-sdk-utils.d.ts.map
|
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":"
|
|
1
|
+
{"version":3,"file":"ai-sdk-utils.d.ts","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":[],"mappings":";;;;AAwEA;AAcA;AAgBA;AAOY,KAnFA,aAAA,GAmFA;EAOP,IAAA,EAAA,MAAA;EASO,IAAA,EAAA,MAAS;EAClB,KAAA,CAAA,EAAA,WAAA,GAAA,MAAA;CACA;AACA,KAhGS,kBAAA,GAgGT;EACA,IAAA,EAAA,WAAA;EACA,IAAA,EAAA,MAAA;EACA,KAAA,CAAA,EAAA,WAAA,GAAA,MAAA;EACA,gBAAA,CAAA,EAhGiB,MAgGjB,CAAA,MAAA,EAAA,OAAA,CAAA;CAAa;AAEX,KA/FO,aAAA,GA+FO;EAuBH,IAAA,EAAA,QAAA,MAAA,EAAA;EAsBA,UAAA,EAAA,MAAA;EACT,QAAA,EAAA,MAAA;EACI,KAAA,EA1IH,MA0IG,CAAA,MAAA,EAAA,OAAA,CAAA;EACR,MAAA,CAAA,EAAA,OAAA;EAAwB,KAAA,EAAA,SAAA,GAAA,QAAA,GAAA,OAAA;EAoBX,SAAA,CAAA,EAAA,MAAA;EASA,oBAAA,CAAA,EApKQ,MAoKR,CAAA,MAAiC,EAAA,OAAA,CAAA;EAC1C,gBAAA,CAAA,EApKa,MAoKb,CAAA,MAAA,EAAA,OAAA,CAAA;CACQ;AACZ,KAnKS,kBAAA,GAmKT;EAAwB,IAAA,EAAA,YAAA;EAiGf,QAAA,EAAA,MAAA;EAaI,GAAA,EAAA,MAAA;EAsBA,KAAA,CAAA,EAAA,MAAA;EA4HJ,gBAAA,CAAA,EA9ZQ,MA8ZY,CAAA,MAAA,EAAA,OAAA,CAAA;AAgBhC,CAAA;AACU,KA5aE,uBAAA,GA4aF;EACA,IAAA,EAAA,iBAAA;EACP,QAAA,EAAA,MAAA;EAAY,SAAA,EAAA,MAAA;EA0BC,KAAA,EAAA,MAAA;EACL,QAAA,CAAA,EAAA,MAAA;EACD,gBAAA,CAAA,EApcU,MAocV,CAAA,MAAA,EAAA,OAAA,CAAA;CACP;AAAY,KAlcH,kBAAA,GAkcG;EA0HC,IAAA,EAAA,YAAA;AAUhB,CAAA;AACQ,KAnkBI,aAAA,GAmkBJ;EACJ,IAAA,EAAA,MAAA;EAAqB,GAAA,EAAA,MAAA;EAAuB,SAAA,EAAA,MAAA;EAUhC,QAAA,CAAA,EAAA,MAAA;AAUhB,CAAA;;;;KA1kBY,yBAAA;;;;;;;;;;;;;;;KAgBA,8BAAA;WACF;;;;;KAME,sBAAA;;;;iBAII;;KAGX,wBAAA;qBACe;yBACI;;KAOZ,SAAA,GACT,gBACA,qBACA,gBACA,qBACA,0BACA,qBACA;KAEE,cAAA,GAAiB;;;;;iBAuBN,yBAAA,OACT,2BACJ;;;;;iBAoBa,yBAAA,OACT,oCACI,yBACR;;;;iBAoBa,iCAAA,OACT,2BACJ;;;;iBAOa,iCAAA,OACT,wCACQ,iCACZ;;;;;;KAiGS,mBAAA;;;YAGD;SACH;;;;;;;;iBASQ,WAAA,OAAkB,eAAe;;;;iBAsBjC,YAAA,QAAoB,iBAAiB;;;;KA4HzC,oBAAA;;;;;;;;;;;;;;;iBAgBI,aAAA,UACN,8BACA,uBACP;;;;iBA0Ba,cAAA,WACL,gCACD,uBACP;;;;iBA0Ha,qBAAA,OAA4B;;;;iBAU5B,cAAA,QACR,eACJ,qBAAqB;;;;iBAUT,gBAAA,QAAwB,cAAc;;;;iBAUtC,kBAAA,QAA0B"}
|
package/ai-sdk-utils.js
CHANGED
|
@@ -1,4 +1,57 @@
|
|
|
1
1
|
//#region src/ai-sdk-utils.ts
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function getMetadataCarrier(part) {
|
|
6
|
+
return {
|
|
7
|
+
callProviderMetadata: part.callProviderMetadata ?? part.providerMetadata,
|
|
8
|
+
providerMetadata: part.providerMetadata ?? part.callProviderMetadata
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Read cossistant part metadata from AI SDK v6-compatible part metadata.
|
|
13
|
+
* Prefers callProviderMetadata but accepts providerMetadata for backward compatibility.
|
|
14
|
+
*/
|
|
15
|
+
function getCossistantPartMetadata(part) {
|
|
16
|
+
const { callProviderMetadata, providerMetadata } = getMetadataCarrier(part);
|
|
17
|
+
const metadata = callProviderMetadata ?? providerMetadata;
|
|
18
|
+
if (!isRecord(metadata)) return;
|
|
19
|
+
const cossistant = metadata.cossistant;
|
|
20
|
+
if (!isRecord(cossistant)) return;
|
|
21
|
+
return cossistant;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Write cossistant part metadata into both callProviderMetadata and providerMetadata.
|
|
25
|
+
* This keeps AI SDK v6 semantics while remaining backward compatible.
|
|
26
|
+
*/
|
|
27
|
+
function setCossistantPartMetadata(part, metadata) {
|
|
28
|
+
const { callProviderMetadata, providerMetadata } = getMetadataCarrier(part);
|
|
29
|
+
return {
|
|
30
|
+
callProviderMetadata: {
|
|
31
|
+
...isRecord(callProviderMetadata) ? callProviderMetadata : {},
|
|
32
|
+
cossistant: metadata
|
|
33
|
+
},
|
|
34
|
+
providerMetadata: {
|
|
35
|
+
...isRecord(providerMetadata) ? providerMetadata : {},
|
|
36
|
+
cossistant: metadata
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Read tool timeline metadata from cossistant part metadata.
|
|
42
|
+
*/
|
|
43
|
+
function getCossistantToolTimelineMetadata(part) {
|
|
44
|
+
return getCossistantPartMetadata(part)?.toolTimeline;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Write tool timeline metadata into cossistant part metadata.
|
|
48
|
+
*/
|
|
49
|
+
function setCossistantToolTimelineMetadata(part, toolTimeline) {
|
|
50
|
+
return setCossistantPartMetadata(part, {
|
|
51
|
+
...getCossistantPartMetadata(part) ?? {},
|
|
52
|
+
toolTimeline
|
|
53
|
+
});
|
|
54
|
+
}
|
|
2
55
|
function isTextPart(part) {
|
|
3
56
|
return part.type === "text" && "text" in part;
|
|
4
57
|
}
|
|
@@ -115,16 +168,20 @@ function toAISDKPart(part) {
|
|
|
115
168
|
filename: typedPart.filename ?? typedPart.fileName
|
|
116
169
|
};
|
|
117
170
|
}
|
|
118
|
-
if (isToolPart(part))
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
171
|
+
if (isToolPart(part)) {
|
|
172
|
+
const metadataCarrier = getMetadataCarrier(part);
|
|
173
|
+
return {
|
|
174
|
+
type: part.type,
|
|
175
|
+
toolCallId: part.toolCallId,
|
|
176
|
+
toolName: part.toolName,
|
|
177
|
+
input: part.input,
|
|
178
|
+
output: part.output,
|
|
179
|
+
state: part.state,
|
|
180
|
+
errorText: part.errorText,
|
|
181
|
+
callProviderMetadata: metadataCarrier.callProviderMetadata,
|
|
182
|
+
providerMetadata: metadataCarrier.providerMetadata
|
|
183
|
+
};
|
|
184
|
+
}
|
|
128
185
|
if (isEventPart(part) || isMetadataPart(part)) return null;
|
|
129
186
|
return null;
|
|
130
187
|
}
|
|
@@ -208,16 +265,23 @@ function fromAISDKPart(part) {
|
|
|
208
265
|
filename: typedPart.filename
|
|
209
266
|
};
|
|
210
267
|
default:
|
|
211
|
-
if (typedPart.type.startsWith("tool-"))
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
268
|
+
if (typedPart.type.startsWith("tool-")) {
|
|
269
|
+
const metadataCarrier = getMetadataCarrier({
|
|
270
|
+
callProviderMetadata: typedPart.callProviderMetadata,
|
|
271
|
+
providerMetadata: typedPart.providerMetadata
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
type: typedPart.type,
|
|
275
|
+
toolCallId: String(typedPart.toolCallId ?? ""),
|
|
276
|
+
toolName: String(typedPart.toolName ?? ""),
|
|
277
|
+
input: typedPart.input ?? {},
|
|
278
|
+
output: typedPart.output,
|
|
279
|
+
state: typedPart.state ?? "partial",
|
|
280
|
+
errorText: typedPart.errorText,
|
|
281
|
+
callProviderMetadata: metadataCarrier.callProviderMetadata,
|
|
282
|
+
providerMetadata: metadataCarrier.providerMetadata
|
|
283
|
+
};
|
|
284
|
+
}
|
|
221
285
|
return null;
|
|
222
286
|
}
|
|
223
287
|
}
|
|
@@ -251,5 +315,5 @@ function hasProcessingParts(parts) {
|
|
|
251
315
|
}
|
|
252
316
|
|
|
253
317
|
//#endregion
|
|
254
|
-
export { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages };
|
|
318
|
+
export { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, getCossistantPartMetadata, getCossistantToolTimelineMetadata, hasProcessingParts, isAISDKCompatiblePart, setCossistantPartMetadata, setCossistantToolTimelineMetadata, toUIMessage, toUIMessages };
|
|
255
319
|
//# sourceMappingURL=ai-sdk-utils.js.map
|
package/ai-sdk-utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-sdk-utils.js","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":["/**\n * AI SDK v6 Conversion Utilities\n *\n * This module provides utilities for converting between Cossistant's\n * TimelineItem format and Vercel AI SDK v6's UIMessage format.\n *\n * Key concepts:\n * - Cossistant uses TimelineItem with userId/aiAgentId/visitorId\n * - AI SDK uses UIMessage with role: 'user' | 'assistant' | 'system'\n * - Both use a parts array for content\n * - Extensions go in metadata (message level) and providerMetadata (part level)\n */\n\nimport type { TimelineItem, TimelineItemParts } from \"@cossistant/types\";\n\n// ============================================================================\n// AI SDK TYPES (re-export for convenience)\n// ============================================================================\n\n/**\n * AI SDK UIMessage part types - these are the standard AI SDK v6 parts\n */\nexport type AISDKTextPart = {\n\ttype: \"text\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n};\n\nexport type AISDKReasoningPart = {\n\ttype: \"reasoning\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKToolPart = {\n\ttype: `tool-${string}`;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\toutput?: unknown;\n\tstate: \"partial\" | \"result\" | \"error\";\n\terrorText?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceUrlPart = {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n\ttitle?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceDocumentPart = {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n\tfilename?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKStepStartPart = {\n\ttype: \"step-start\";\n};\n\nexport type AISDKFilePart = {\n\ttype: \"file\";\n\turl: string;\n\tmediaType: string;\n\tfilename?: string;\n};\n\n// ============================================================================\n// COSSISTANT METADATA TYPES\n// ============================================================================\n\n/**\n * Cossistant-specific metadata stored in UIMessage.metadata\n */\nexport type CossistantMessageMetadata = {\n\tconversationId: string;\n\torganizationId: string;\n\tvisibility: \"public\" | \"private\";\n\tuserId: string | null;\n\taiAgentId: string | null;\n\tvisitorId: string | null;\n\treplyToId?: string | null;\n\tcreatedAt: string;\n\tdeletedAt?: string | null;\n\ttool?: string | null;\n};\n\n/**\n * Cossistant-specific metadata stored in part.providerMetadata.cossistant\n */\nexport type CossistantPartMetadata = {\n\tvisibility?: \"public\" | \"private\";\n\tprogressMessage?: string;\n\tknowledgeId?: string;\n};\n\n// ============================================================================\n// TYPE HELPERS\n// ============================================================================\n\nexport type AISDKPart =\n\t| AISDKTextPart\n\t| AISDKReasoningPart\n\t| AISDKToolPart\n\t| AISDKSourceUrlPart\n\t| AISDKSourceDocumentPart\n\t| AISDKStepStartPart\n\t| AISDKFilePart;\n\ntype CossistantPart = TimelineItemParts[number];\n\n// Type guards for Cossistant parts\nfunction isTextPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"text\"; text: string } {\n\treturn part.type === \"text\" && \"text\" in part;\n}\n\nfunction isReasoningPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"reasoning\"; text: string } {\n\treturn part.type === \"reasoning\" && \"text\" in part;\n}\n\nfunction isSourceUrlPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n} {\n\treturn part.type === \"source-url\" && \"sourceId\" in part && \"url\" in part;\n}\n\nfunction isSourceDocumentPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n} {\n\treturn (\n\t\tpart.type === \"source-document\" &&\n\t\t\"sourceId\" in part &&\n\t\t\"mediaType\" in part &&\n\t\t\"title\" in part\n\t);\n}\n\nfunction isStepStartPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"step-start\" } {\n\treturn part.type === \"step-start\";\n}\n\nfunction isFilePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"file\"; url: string; mediaType: string } {\n\treturn part.type === \"file\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isImagePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"image\"; url: string; mediaType: string } {\n\treturn part.type === \"image\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isToolPart(part: CossistantPart): part is CossistantPart & {\n\ttype: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\tstate: \"partial\" | \"result\" | \"error\";\n} {\n\treturn (\n\t\ttypeof part.type === \"string\" &&\n\t\tpart.type.startsWith(\"tool-\") &&\n\t\t\"toolCallId\" in part &&\n\t\t\"toolName\" in part\n\t);\n}\n\nfunction isEventPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"event\" } {\n\treturn part.type === \"event\";\n}\n\nfunction isMetadataPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"metadata\" } {\n\treturn part.type === \"metadata\";\n}\n\n// ============================================================================\n// CONVERSION: TIMELINE ITEM -> UI MESSAGE\n// ============================================================================\n\n/**\n * Cossistant-compatible UIMessage type\n * This is structurally compatible with AI SDK v6 UIMessage\n * but uses our own part types for flexibility\n */\nexport type CossistantUIMessage = {\n\tid: string;\n\trole: \"user\" | \"assistant\" | \"system\";\n\tmetadata: CossistantMessageMetadata;\n\tparts: AISDKPart[];\n};\n\n/**\n * Convert a Cossistant TimelineItem to AI SDK UIMessage format\n *\n * @param item - The Cossistant TimelineItem to convert\n * @returns AI SDK compatible UIMessage with Cossistant metadata\n */\nexport function toUIMessage(item: TimelineItem): CossistantUIMessage {\n\treturn {\n\t\tid: item.id ?? \"\",\n\t\trole: getAISDKRole(item),\n\t\tmetadata: {\n\t\t\tconversationId: item.conversationId,\n\t\t\torganizationId: item.organizationId,\n\t\t\tvisibility: item.visibility,\n\t\t\tuserId: item.userId,\n\t\t\taiAgentId: item.aiAgentId,\n\t\t\tvisitorId: item.visitorId,\n\t\t\tcreatedAt: item.createdAt,\n\t\t\tdeletedAt: item.deletedAt ?? null,\n\t\t\ttool: item.tool ?? null,\n\t\t},\n\t\tparts: item.parts.map(toAISDKPart).filter(Boolean) as AISDKPart[],\n\t};\n}\n\n/**\n * Convert multiple TimelineItems to UIMessages\n */\nexport function toUIMessages(items: TimelineItem[]): CossistantUIMessage[] {\n\treturn items.map(toUIMessage);\n}\n\n/**\n * Determine AI SDK role from TimelineItem sender fields\n */\nfunction getAISDKRole(item: TimelineItem): \"user\" | \"assistant\" | \"system\" {\n\t// AI agent messages become assistant\n\tif (item.aiAgentId) {\n\t\treturn \"assistant\";\n\t}\n\n\t// Both visitor and human user messages become user\n\t// (AI SDK doesn't distinguish between these)\n\treturn \"user\";\n}\n\n/**\n * Convert a Cossistant part to AI SDK part format\n */\nfunction toAISDKPart(part: CossistantPart): AISDKPart | null {\n\tif (isTextPart(part)) {\n\t\treturn {\n\t\t\ttype: \"text\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t};\n\t}\n\n\tif (isReasoningPart(part)) {\n\t\treturn {\n\t\t\ttype: \"reasoning\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceUrlPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-url\",\n\t\t\tsourceId: part.sourceId,\n\t\t\turl: part.url,\n\t\t\ttitle: (part as { title?: string }).title,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceDocumentPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-document\",\n\t\t\tsourceId: part.sourceId,\n\t\t\tmediaType: part.mediaType,\n\t\t\ttitle: part.title,\n\t\t\tfilename: (part as { filename?: string }).filename,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isStepStartPart(part)) {\n\t\treturn {\n\t\t\ttype: \"step-start\",\n\t\t};\n\t}\n\n\tif (isFilePart(part)) {\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isImagePart(part)) {\n\t\t// Convert image to file part (AI SDK uses file for all media)\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isToolPart(part)) {\n\t\treturn {\n\t\t\ttype: part.type as `tool-${string}`,\n\t\t\ttoolCallId: part.toolCallId,\n\t\t\ttoolName: part.toolName,\n\t\t\tinput: part.input,\n\t\t\toutput: (part as { output?: unknown }).output,\n\t\t\tstate: part.state,\n\t\t\terrorText: (part as { errorText?: string }).errorText,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\t// Event and metadata parts are Cossistant-specific, skip for AI SDK\n\tif (isEventPart(part) || isMetadataPart(part)) {\n\t\treturn null;\n\t}\n\n\treturn null;\n}\n\n// ============================================================================\n// CONVERSION: UI MESSAGE -> TIMELINE ITEM\n// ============================================================================\n\n/**\n * Context required to create a TimelineItem from UIMessage\n */\nexport type FromUIMessageContext = {\n\tconversationId: string;\n\torganizationId: string;\n\taiAgentId?: string | null;\n\tuserId?: string | null;\n\tvisitorId?: string | null;\n\tvisibility?: \"public\" | \"private\";\n};\n\n/**\n * Convert an AI SDK UIMessage to Cossistant TimelineItem format\n *\n * @param message - The AI SDK UIMessage to convert\n * @param context - Context for creating the TimelineItem\n * @returns Cossistant TimelineItem\n */\nexport function fromUIMessage(\n\tmessage: CossistantUIMessage,\n\tcontext: FromUIMessageContext\n): TimelineItem {\n\t// Extract metadata if available\n\tconst metadata = message.metadata;\n\n\treturn {\n\t\tid: message.id,\n\t\tconversationId: metadata?.conversationId ?? context.conversationId,\n\t\torganizationId: metadata?.organizationId ?? context.organizationId,\n\t\tvisibility: metadata?.visibility ?? context.visibility ?? \"public\",\n\t\ttype: \"message\",\n\t\ttext: extractTextFromParts(message.parts),\n\t\tparts: message.parts\n\t\t\t.map(fromAISDKPart)\n\t\t\t.filter(Boolean) as TimelineItemParts,\n\t\tuserId: metadata?.userId ?? context.userId ?? null,\n\t\taiAgentId: metadata?.aiAgentId ?? context.aiAgentId ?? null,\n\t\tvisitorId: metadata?.visitorId ?? context.visitorId ?? null,\n\t\tcreatedAt: metadata?.createdAt ?? new Date().toISOString(),\n\t\tdeletedAt: metadata?.deletedAt ?? null,\n\t\ttool: metadata?.tool ?? null,\n\t};\n}\n\n/**\n * Convert multiple UIMessages to TimelineItems\n */\nexport function fromUIMessages(\n\tmessages: CossistantUIMessage[],\n\tcontext: FromUIMessageContext\n): TimelineItem[] {\n\treturn messages.map((msg) => fromUIMessage(msg, context));\n}\n\n/**\n * Extract plain text content from message parts\n */\nfunction extractTextFromParts(parts: unknown[]): string | null {\n\tconst textParts = parts.filter(\n\t\t(part): part is AISDKTextPart =>\n\t\t\ttypeof part === \"object\" &&\n\t\t\tpart !== null &&\n\t\t\t\"type\" in part &&\n\t\t\tpart.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\n/**\n * Convert an AI SDK part to Cossistant part format\n */\nfunction fromAISDKPart(part: unknown): CossistantPart | null {\n\tif (typeof part !== \"object\" || part === null || !(\"type\" in part)) {\n\t\treturn null;\n\t}\n\n\tconst typedPart = part as { type: string; [key: string]: unknown };\n\n\tswitch (typedPart.type) {\n\t\tcase \"text\":\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t};\n\n\t\tcase \"reasoning\":\n\t\t\treturn {\n\t\t\t\ttype: \"reasoning\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-url\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-url\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\ttitle: typedPart.title as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-document\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-document\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\ttitle: String(typedPart.title ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"step-start\":\n\t\t\treturn {\n\t\t\t\ttype: \"step-start\",\n\t\t\t};\n\n\t\tcase \"file\":\n\t\t\treturn {\n\t\t\t\ttype: \"file\",\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t};\n\n\t\tdefault:\n\t\t\t// Handle tool-* pattern\n\t\t\tif (typedPart.type.startsWith(\"tool-\")) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: typedPart.type,\n\t\t\t\t\ttoolCallId: String(typedPart.toolCallId ?? \"\"),\n\t\t\t\t\ttoolName: String(typedPart.toolName ?? \"\"),\n\t\t\t\t\tinput: (typedPart.input as Record<string, unknown>) ?? {},\n\t\t\t\t\toutput: typedPart.output,\n\t\t\t\t\tstate:\n\t\t\t\t\t\t(typedPart.state as \"partial\" | \"result\" | \"error\") ?? \"partial\",\n\t\t\t\t\terrorText: typedPart.errorText as string | undefined,\n\t\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t| undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn null;\n\t}\n}\n\n// ============================================================================\n// HELPER UTILITIES\n// ============================================================================\n\n/**\n * Check if a part is an AI SDK compatible part type\n */\nexport function isAISDKCompatiblePart(part: CossistantPart): boolean {\n\tif (part.type === \"event\" || part.type === \"metadata\") {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Extract all sources from a message's parts\n */\nexport function extractSources(\n\tparts: AISDKPart[]\n): (AISDKSourceUrlPart | AISDKSourceDocumentPart)[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKSourceUrlPart | AISDKSourceDocumentPart =>\n\t\t\tpart.type === \"source-url\" || part.type === \"source-document\"\n\t);\n}\n\n/**\n * Extract all tool calls from a message's parts\n */\nexport function extractToolCalls(parts: AISDKPart[]): AISDKToolPart[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKToolPart =>\n\t\t\ttypeof part.type === \"string\" && part.type.startsWith(\"tool-\")\n\t);\n}\n\n/**\n * Check if any parts are still processing\n */\nexport function hasProcessingParts(parts: AISDKPart[]): boolean {\n\treturn parts.some((part) => {\n\t\tif (\n\t\t\t\"state\" in part &&\n\t\t\t(part.state === \"streaming\" || part.state === \"partial\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t});\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-sdk-utils.js","names":[],"sources":["../src/ai-sdk-utils.ts"],"sourcesContent":["/**\n * AI SDK v6 Conversion Utilities\n *\n * This module provides utilities for converting between Cossistant's\n * TimelineItem format and Vercel AI SDK v6's UIMessage format.\n *\n * Key concepts:\n * - Cossistant uses TimelineItem with userId/aiAgentId/visitorId\n * - AI SDK uses UIMessage with role: 'user' | 'assistant' | 'system'\n * - Both use a parts array for content\n * - Extensions go in metadata (message level) and providerMetadata/callProviderMetadata (part level)\n */\n\nimport type {\n\tTimelineItem,\n\tTimelineItemParts,\n\tToolTimelineLogType,\n} from \"@cossistant/types\";\n\n// ============================================================================\n// AI SDK TYPES (re-export for convenience)\n// ============================================================================\n\n/**\n * AI SDK UIMessage part types - these are the standard AI SDK v6 parts\n */\nexport type AISDKTextPart = {\n\ttype: \"text\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n};\n\nexport type AISDKReasoningPart = {\n\ttype: \"reasoning\";\n\ttext: string;\n\tstate?: \"streaming\" | \"done\";\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKToolPart = {\n\ttype: `tool-${string}`;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\toutput?: unknown;\n\tstate: \"partial\" | \"result\" | \"error\";\n\terrorText?: string;\n\tcallProviderMetadata?: Record<string, unknown>;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceUrlPart = {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n\ttitle?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKSourceDocumentPart = {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n\tfilename?: string;\n\tproviderMetadata?: Record<string, unknown>;\n};\n\nexport type AISDKStepStartPart = {\n\ttype: \"step-start\";\n};\n\nexport type AISDKFilePart = {\n\ttype: \"file\";\n\turl: string;\n\tmediaType: string;\n\tfilename?: string;\n};\n\n// ============================================================================\n// COSSISTANT METADATA TYPES\n// ============================================================================\n\n/**\n * Cossistant-specific metadata stored in UIMessage.metadata\n */\nexport type CossistantMessageMetadata = {\n\tconversationId: string;\n\torganizationId: string;\n\tvisibility: \"public\" | \"private\";\n\tuserId: string | null;\n\taiAgentId: string | null;\n\tvisitorId: string | null;\n\treplyToId?: string | null;\n\tcreatedAt: string;\n\tdeletedAt?: string | null;\n\ttool?: string | null;\n};\n\n/**\n * Cossistant-specific metadata stored in part.callProviderMetadata/providerMetadata.cossistant\n */\nexport type CossistantToolTimelineMetadata = {\n\tlogType: ToolTimelineLogType;\n\ttriggerMessageId: string;\n\tworkflowRunId: string;\n\ttriggerVisibility?: \"public\" | \"private\";\n};\n\nexport type CossistantPartMetadata = {\n\tvisibility?: \"public\" | \"private\";\n\tprogressMessage?: string;\n\tknowledgeId?: string;\n\ttoolTimeline?: CossistantToolTimelineMetadata;\n};\n\ntype AISDKPartMetadataCarrier = {\n\tproviderMetadata?: Record<string, unknown>;\n\tcallProviderMetadata?: Record<string, unknown>;\n};\n\n// ============================================================================\n// TYPE HELPERS\n// ============================================================================\n\nexport type AISDKPart =\n\t| AISDKTextPart\n\t| AISDKReasoningPart\n\t| AISDKToolPart\n\t| AISDKSourceUrlPart\n\t| AISDKSourceDocumentPart\n\t| AISDKStepStartPart\n\t| AISDKFilePart;\n\ntype CossistantPart = TimelineItemParts[number];\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction getMetadataCarrier(\n\tpart: AISDKPartMetadataCarrier\n): AISDKPartMetadataCarrier {\n\tconst callProviderMetadata =\n\t\tpart.callProviderMetadata ?? part.providerMetadata;\n\tconst providerMetadata = part.providerMetadata ?? part.callProviderMetadata;\n\n\treturn {\n\t\tcallProviderMetadata,\n\t\tproviderMetadata,\n\t};\n}\n\n/**\n * Read cossistant part metadata from AI SDK v6-compatible part metadata.\n * Prefers callProviderMetadata but accepts providerMetadata for backward compatibility.\n */\nexport function getCossistantPartMetadata(\n\tpart: AISDKPartMetadataCarrier\n): CossistantPartMetadata | undefined {\n\tconst { callProviderMetadata, providerMetadata } = getMetadataCarrier(part);\n\tconst metadata = callProviderMetadata ?? providerMetadata;\n\n\tif (!isRecord(metadata)) {\n\t\treturn;\n\t}\n\n\tconst cossistant = metadata.cossistant;\n\tif (!isRecord(cossistant)) {\n\t\treturn;\n\t}\n\n\treturn cossistant as CossistantPartMetadata;\n}\n\n/**\n * Write cossistant part metadata into both callProviderMetadata and providerMetadata.\n * This keeps AI SDK v6 semantics while remaining backward compatible.\n */\nexport function setCossistantPartMetadata(\n\tpart: AISDKPartMetadataCarrier,\n\tmetadata: CossistantPartMetadata\n): AISDKPartMetadataCarrier {\n\tconst { callProviderMetadata, providerMetadata } = getMetadataCarrier(part);\n\tconst nextCallProviderMetadata = {\n\t\t...(isRecord(callProviderMetadata) ? callProviderMetadata : {}),\n\t\tcossistant: metadata,\n\t};\n\tconst nextProviderMetadata = {\n\t\t...(isRecord(providerMetadata) ? providerMetadata : {}),\n\t\tcossistant: metadata,\n\t};\n\n\treturn {\n\t\tcallProviderMetadata: nextCallProviderMetadata,\n\t\tproviderMetadata: nextProviderMetadata,\n\t};\n}\n\n/**\n * Read tool timeline metadata from cossistant part metadata.\n */\nexport function getCossistantToolTimelineMetadata(\n\tpart: AISDKPartMetadataCarrier\n): CossistantToolTimelineMetadata | undefined {\n\treturn getCossistantPartMetadata(part)?.toolTimeline;\n}\n\n/**\n * Write tool timeline metadata into cossistant part metadata.\n */\nexport function setCossistantToolTimelineMetadata(\n\tpart: AISDKPartMetadataCarrier,\n\ttoolTimeline: CossistantToolTimelineMetadata\n): AISDKPartMetadataCarrier {\n\tconst existing = getCossistantPartMetadata(part) ?? {};\n\treturn setCossistantPartMetadata(part, {\n\t\t...existing,\n\t\ttoolTimeline,\n\t});\n}\n\n// Type guards for Cossistant parts\nfunction isTextPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"text\"; text: string } {\n\treturn part.type === \"text\" && \"text\" in part;\n}\n\nfunction isReasoningPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"reasoning\"; text: string } {\n\treturn part.type === \"reasoning\" && \"text\" in part;\n}\n\nfunction isSourceUrlPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-url\";\n\tsourceId: string;\n\turl: string;\n} {\n\treturn part.type === \"source-url\" && \"sourceId\" in part && \"url\" in part;\n}\n\nfunction isSourceDocumentPart(part: CossistantPart): part is CossistantPart & {\n\ttype: \"source-document\";\n\tsourceId: string;\n\tmediaType: string;\n\ttitle: string;\n} {\n\treturn (\n\t\tpart.type === \"source-document\" &&\n\t\t\"sourceId\" in part &&\n\t\t\"mediaType\" in part &&\n\t\t\"title\" in part\n\t);\n}\n\nfunction isStepStartPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"step-start\" } {\n\treturn part.type === \"step-start\";\n}\n\nfunction isFilePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"file\"; url: string; mediaType: string } {\n\treturn part.type === \"file\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isImagePart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"image\"; url: string; mediaType: string } {\n\treturn part.type === \"image\" && \"url\" in part && \"mediaType\" in part;\n}\n\nfunction isToolPart(part: CossistantPart): part is CossistantPart & {\n\ttype: string;\n\ttoolCallId: string;\n\ttoolName: string;\n\tinput: Record<string, unknown>;\n\tstate: \"partial\" | \"result\" | \"error\";\n} {\n\treturn (\n\t\ttypeof part.type === \"string\" &&\n\t\tpart.type.startsWith(\"tool-\") &&\n\t\t\"toolCallId\" in part &&\n\t\t\"toolName\" in part\n\t);\n}\n\nfunction isEventPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"event\" } {\n\treturn part.type === \"event\";\n}\n\nfunction isMetadataPart(\n\tpart: CossistantPart\n): part is CossistantPart & { type: \"metadata\" } {\n\treturn part.type === \"metadata\";\n}\n\n// ============================================================================\n// CONVERSION: TIMELINE ITEM -> UI MESSAGE\n// ============================================================================\n\n/**\n * Cossistant-compatible UIMessage type\n * This is structurally compatible with AI SDK v6 UIMessage\n * but uses our own part types for flexibility\n */\nexport type CossistantUIMessage = {\n\tid: string;\n\trole: \"user\" | \"assistant\" | \"system\";\n\tmetadata: CossistantMessageMetadata;\n\tparts: AISDKPart[];\n};\n\n/**\n * Convert a Cossistant TimelineItem to AI SDK UIMessage format\n *\n * @param item - The Cossistant TimelineItem to convert\n * @returns AI SDK compatible UIMessage with Cossistant metadata\n */\nexport function toUIMessage(item: TimelineItem): CossistantUIMessage {\n\treturn {\n\t\tid: item.id ?? \"\",\n\t\trole: getAISDKRole(item),\n\t\tmetadata: {\n\t\t\tconversationId: item.conversationId,\n\t\t\torganizationId: item.organizationId,\n\t\t\tvisibility: item.visibility,\n\t\t\tuserId: item.userId,\n\t\t\taiAgentId: item.aiAgentId,\n\t\t\tvisitorId: item.visitorId,\n\t\t\tcreatedAt: item.createdAt,\n\t\t\tdeletedAt: item.deletedAt ?? null,\n\t\t\ttool: item.tool ?? null,\n\t\t},\n\t\tparts: item.parts.map(toAISDKPart).filter(Boolean) as AISDKPart[],\n\t};\n}\n\n/**\n * Convert multiple TimelineItems to UIMessages\n */\nexport function toUIMessages(items: TimelineItem[]): CossistantUIMessage[] {\n\treturn items.map(toUIMessage);\n}\n\n/**\n * Determine AI SDK role from TimelineItem sender fields\n */\nfunction getAISDKRole(item: TimelineItem): \"user\" | \"assistant\" | \"system\" {\n\t// AI agent messages become assistant\n\tif (item.aiAgentId) {\n\t\treturn \"assistant\";\n\t}\n\n\t// Both visitor and human user messages become user\n\t// (AI SDK doesn't distinguish between these)\n\treturn \"user\";\n}\n\n/**\n * Convert a Cossistant part to AI SDK part format\n */\nfunction toAISDKPart(part: CossistantPart): AISDKPart | null {\n\tif (isTextPart(part)) {\n\t\treturn {\n\t\t\ttype: \"text\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t};\n\t}\n\n\tif (isReasoningPart(part)) {\n\t\treturn {\n\t\t\ttype: \"reasoning\",\n\t\t\ttext: part.text,\n\t\t\tstate: (part as { state?: \"streaming\" | \"done\" }).state,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceUrlPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-url\",\n\t\t\tsourceId: part.sourceId,\n\t\t\turl: part.url,\n\t\t\ttitle: (part as { title?: string }).title,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isSourceDocumentPart(part)) {\n\t\treturn {\n\t\t\ttype: \"source-document\",\n\t\t\tsourceId: part.sourceId,\n\t\t\tmediaType: part.mediaType,\n\t\t\ttitle: part.title,\n\t\t\tfilename: (part as { filename?: string }).filename,\n\t\t\tproviderMetadata: (part as { providerMetadata?: Record<string, unknown> })\n\t\t\t\t.providerMetadata,\n\t\t};\n\t}\n\n\tif (isStepStartPart(part)) {\n\t\treturn {\n\t\t\ttype: \"step-start\",\n\t\t};\n\t}\n\n\tif (isFilePart(part)) {\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isImagePart(part)) {\n\t\t// Convert image to file part (AI SDK uses file for all media)\n\t\t// Support both 'filename' (new) and 'fileName' (legacy) for backward compatibility\n\t\tconst typedPart = part as { filename?: string; fileName?: string };\n\t\treturn {\n\t\t\ttype: \"file\",\n\t\t\turl: part.url,\n\t\t\tmediaType: part.mediaType,\n\t\t\tfilename: typedPart.filename ?? typedPart.fileName,\n\t\t};\n\t}\n\n\tif (isToolPart(part)) {\n\t\tconst typedPart = part as AISDKPartMetadataCarrier;\n\t\tconst metadataCarrier = getMetadataCarrier(typedPart);\n\n\t\treturn {\n\t\t\ttype: part.type as `tool-${string}`,\n\t\t\ttoolCallId: part.toolCallId,\n\t\t\ttoolName: part.toolName,\n\t\t\tinput: part.input,\n\t\t\toutput: (part as { output?: unknown }).output,\n\t\t\tstate: part.state,\n\t\t\terrorText: (part as { errorText?: string }).errorText,\n\t\t\tcallProviderMetadata: metadataCarrier.callProviderMetadata,\n\t\t\tproviderMetadata: metadataCarrier.providerMetadata,\n\t\t};\n\t}\n\n\t// Event and metadata parts are Cossistant-specific, skip for AI SDK\n\tif (isEventPart(part) || isMetadataPart(part)) {\n\t\treturn null;\n\t}\n\n\treturn null;\n}\n\n// ============================================================================\n// CONVERSION: UI MESSAGE -> TIMELINE ITEM\n// ============================================================================\n\n/**\n * Context required to create a TimelineItem from UIMessage\n */\nexport type FromUIMessageContext = {\n\tconversationId: string;\n\torganizationId: string;\n\taiAgentId?: string | null;\n\tuserId?: string | null;\n\tvisitorId?: string | null;\n\tvisibility?: \"public\" | \"private\";\n};\n\n/**\n * Convert an AI SDK UIMessage to Cossistant TimelineItem format\n *\n * @param message - The AI SDK UIMessage to convert\n * @param context - Context for creating the TimelineItem\n * @returns Cossistant TimelineItem\n */\nexport function fromUIMessage(\n\tmessage: CossistantUIMessage,\n\tcontext: FromUIMessageContext\n): TimelineItem {\n\t// Extract metadata if available\n\tconst metadata = message.metadata;\n\n\treturn {\n\t\tid: message.id,\n\t\tconversationId: metadata?.conversationId ?? context.conversationId,\n\t\torganizationId: metadata?.organizationId ?? context.organizationId,\n\t\tvisibility: metadata?.visibility ?? context.visibility ?? \"public\",\n\t\ttype: \"message\",\n\t\ttext: extractTextFromParts(message.parts),\n\t\tparts: message.parts\n\t\t\t.map(fromAISDKPart)\n\t\t\t.filter(Boolean) as TimelineItemParts,\n\t\tuserId: metadata?.userId ?? context.userId ?? null,\n\t\taiAgentId: metadata?.aiAgentId ?? context.aiAgentId ?? null,\n\t\tvisitorId: metadata?.visitorId ?? context.visitorId ?? null,\n\t\tcreatedAt: metadata?.createdAt ?? new Date().toISOString(),\n\t\tdeletedAt: metadata?.deletedAt ?? null,\n\t\ttool: metadata?.tool ?? null,\n\t};\n}\n\n/**\n * Convert multiple UIMessages to TimelineItems\n */\nexport function fromUIMessages(\n\tmessages: CossistantUIMessage[],\n\tcontext: FromUIMessageContext\n): TimelineItem[] {\n\treturn messages.map((msg) => fromUIMessage(msg, context));\n}\n\n/**\n * Extract plain text content from message parts\n */\nfunction extractTextFromParts(parts: unknown[]): string | null {\n\tconst textParts = parts.filter(\n\t\t(part): part is AISDKTextPart =>\n\t\t\ttypeof part === \"object\" &&\n\t\t\tpart !== null &&\n\t\t\t\"type\" in part &&\n\t\t\tpart.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\n/**\n * Convert an AI SDK part to Cossistant part format\n */\nfunction fromAISDKPart(part: unknown): CossistantPart | null {\n\tif (typeof part !== \"object\" || part === null || !(\"type\" in part)) {\n\t\treturn null;\n\t}\n\n\tconst typedPart = part as { type: string; [key: string]: unknown };\n\n\tswitch (typedPart.type) {\n\t\tcase \"text\":\n\t\t\treturn {\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t};\n\n\t\tcase \"reasoning\":\n\t\t\treturn {\n\t\t\t\ttype: \"reasoning\",\n\t\t\t\ttext: String(typedPart.text ?? \"\"),\n\t\t\t\tstate: typedPart.state as \"streaming\" | \"done\" | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-url\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-url\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\ttitle: typedPart.title as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"source-document\":\n\t\t\treturn {\n\t\t\t\ttype: \"source-document\",\n\t\t\t\tsourceId: String(typedPart.sourceId ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\ttitle: String(typedPart.title ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t| undefined,\n\t\t\t};\n\n\t\tcase \"step-start\":\n\t\t\treturn {\n\t\t\t\ttype: \"step-start\",\n\t\t\t};\n\n\t\tcase \"file\":\n\t\t\treturn {\n\t\t\t\ttype: \"file\",\n\t\t\t\turl: String(typedPart.url ?? \"\"),\n\t\t\t\tmediaType: String(typedPart.mediaType ?? \"\"),\n\t\t\t\tfilename: typedPart.filename as string | undefined,\n\t\t\t};\n\n\t\tdefault:\n\t\t\t// Handle tool-* pattern\n\t\t\tif (typedPart.type.startsWith(\"tool-\")) {\n\t\t\t\tconst metadataCarrier = getMetadataCarrier({\n\t\t\t\t\tcallProviderMetadata: typedPart.callProviderMetadata as\n\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t| undefined,\n\t\t\t\t\tproviderMetadata: typedPart.providerMetadata as\n\t\t\t\t\t\t| Record<string, unknown>\n\t\t\t\t\t\t| undefined,\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\ttype: typedPart.type,\n\t\t\t\t\ttoolCallId: String(typedPart.toolCallId ?? \"\"),\n\t\t\t\t\ttoolName: String(typedPart.toolName ?? \"\"),\n\t\t\t\t\tinput: (typedPart.input as Record<string, unknown>) ?? {},\n\t\t\t\t\toutput: typedPart.output,\n\t\t\t\t\tstate:\n\t\t\t\t\t\t(typedPart.state as \"partial\" | \"result\" | \"error\") ?? \"partial\",\n\t\t\t\t\terrorText: typedPart.errorText as string | undefined,\n\t\t\t\t\tcallProviderMetadata: metadataCarrier.callProviderMetadata,\n\t\t\t\t\tproviderMetadata: metadataCarrier.providerMetadata,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn null;\n\t}\n}\n\n// ============================================================================\n// HELPER UTILITIES\n// ============================================================================\n\n/**\n * Check if a part is an AI SDK compatible part type\n */\nexport function isAISDKCompatiblePart(part: CossistantPart): boolean {\n\tif (part.type === \"event\" || part.type === \"metadata\") {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Extract all sources from a message's parts\n */\nexport function extractSources(\n\tparts: AISDKPart[]\n): (AISDKSourceUrlPart | AISDKSourceDocumentPart)[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKSourceUrlPart | AISDKSourceDocumentPart =>\n\t\t\tpart.type === \"source-url\" || part.type === \"source-document\"\n\t);\n}\n\n/**\n * Extract all tool calls from a message's parts\n */\nexport function extractToolCalls(parts: AISDKPart[]): AISDKToolPart[] {\n\treturn parts.filter(\n\t\t(part): part is AISDKToolPart =>\n\t\t\ttypeof part.type === \"string\" && part.type.startsWith(\"tool-\")\n\t);\n}\n\n/**\n * Check if any parts are still processing\n */\nexport function hasProcessingParts(parts: AISDKPart[]): boolean {\n\treturn parts.some((part) => {\n\t\tif (\n\t\t\t\"state\" in part &&\n\t\t\t(part.state === \"streaming\" || part.state === \"partial\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t});\n}\n"],"mappings":"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"}
|
package/client.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ declare class CossistantClient {
|
|
|
33
33
|
constructor(config: types_d_exports.CossistantConfig);
|
|
34
34
|
updateConfiguration(config: Partial<types_d_exports.CossistantConfig>): void;
|
|
35
35
|
getConfiguration(): types_d_exports.CossistantConfig;
|
|
36
|
+
isConversationPending(conversationId: string | null | undefined): boolean;
|
|
36
37
|
fetchWebsite(params?: {
|
|
37
38
|
force?: boolean;
|
|
38
39
|
}): Promise<types_d_exports.PublicWebsiteResponse>;
|
package/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;KA6DK,0BAAA;;EAAA,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAKK,SAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EACoB,KAAA,CAAA,EAAA,MAAA;EAAiB,MAAA,CAAA,EADrC,YACqC,CAAA,QAAA,CAAA;EAAvB,oBAAA,CAAA,EAAA,KAAA,CAAM,cAAN,GAAuB,cAAvB,CAAA;CAAK;AAAA,KAGxB,0BAAA,GAA0B;EAMlB,cAAA,EAAA,MAAgB;EAKC,YAAA,EATf,YASe;EACA,oBAAA,EATP,cASO,EAAA;CACN;AAEH,cATR,gBAAA,CASQ;EASgB,QAAA,UAAA;EAAR,QAAA,MAAA;EAMR,QAAA,oBAAA;
|
|
1
|
+
{"version":3,"file":"client.d.ts","names":[],"sources":["../src/client.ts"],"sourcesContent":[],"mappings":"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"}
|
package/client.js
CHANGED
|
@@ -31,6 +31,10 @@ var CossistantClient = class {
|
|
|
31
31
|
getConfiguration() {
|
|
32
32
|
return { ...this.config };
|
|
33
33
|
}
|
|
34
|
+
isConversationPending(conversationId) {
|
|
35
|
+
if (!conversationId) return false;
|
|
36
|
+
return this.pendingConversations.has(conversationId);
|
|
37
|
+
}
|
|
34
38
|
async fetchWebsite(params = {}) {
|
|
35
39
|
const { force = false } = params;
|
|
36
40
|
const current = this.websiteStore.getState();
|
|
@@ -179,6 +183,7 @@ var CossistantClient = class {
|
|
|
179
183
|
if (pending && createIfPending !== false) try {
|
|
180
184
|
const response = await this.restClient.createConversation({
|
|
181
185
|
conversationId: rest.conversationId,
|
|
186
|
+
visitorId: pending.conversation.visitorId || void 0,
|
|
182
187
|
defaultTimelineItems: [...pending.initialTimelineItems, optimisticTimelineItem]
|
|
183
188
|
});
|
|
184
189
|
this.conversationsStore.ingestConversation(response.conversation);
|
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\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\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\t...(updates.status !== undefined && { status: updates.status }),\n\t\t\t...(updates.deletedAt !== undefined && {\n\t\t\t\tdeletedAt: updates.deletedAt,\n\t\t\t}),\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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"}
|
|
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\tisConversationPending(conversationId: string | null | undefined): boolean {\n\t\tif (!conversationId) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn this.pendingConversations.has(conversationId);\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\tvisitorId: pending.conversation.visitorId || undefined,\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\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\t...(updates.status !== undefined && { status: updates.status }),\n\t\t\t...(updates.deletedAt !== undefined && {\n\t\t\t\tdeletedAt: updates.deletedAt,\n\t\t\t}),\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,4 +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
|
+
import { AISDKFilePart, AISDKPart, AISDKReasoningPart, AISDKSourceDocumentPart, AISDKSourceUrlPart, AISDKStepStartPart, AISDKTextPart, AISDKToolPart, CossistantMessageMetadata, CossistantPartMetadata, CossistantToolTimelineMetadata, CossistantUIMessage, FromUIMessageContext, extractSources, extractToolCalls, fromUIMessage, fromUIMessages, getCossistantPartMetadata, getCossistantToolTimelineMetadata, hasProcessingParts, isAISDKCompatiblePart, setCossistantPartMetadata, setCossistantToolTimelineMetadata, toUIMessage, toUIMessages } from "./ai-sdk-utils.js";
|
|
2
2
|
import { CossistantAPIError } from "./types.js";
|
|
3
3
|
import { CossistantRestClient } from "./rest-client.js";
|
|
4
4
|
import { ConversationPagination, ConversationWithSeen, ConversationsState, ConversationsStore, createConversationsStore, getConversationById, getConversationPagination, getConversations } from "./store/conversations-store.js";
|
|
@@ -17,4 +17,4 @@ import { VisitorData, collectVisitorData } from "./visitor-data.js";
|
|
|
17
17
|
import { generateVisitorName, getVisitorNameWithFallback } from "./visitor-name.js";
|
|
18
18
|
import { clearAllVisitorIds, clearVisitorId, getVisitorId, setVisitorId } from "./visitor-tracker.js";
|
|
19
19
|
import { CossistantConfig, CossistantError } from "@cossistant/types";
|
|
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 };
|
|
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 CossistantToolTimelineMetadata, 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, getCossistantPartMetadata, getCossistantToolTimelineMetadata, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hasProcessingParts, hasVisibleContent, hydrateConversationSeen, isAISDKCompatiblePart, isAllowedMimeType, isImageMimeType, normalizeLocale, setCossistantPartMetadata, setCossistantToolTimelineMetadata, setTypingState, setVisitorId, toUIMessage, toUIMessages, upsertConversationSeen, validateFile, validateFiles };
|
package/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, hasProcessingParts, isAISDKCompatiblePart, toUIMessage, toUIMessages } from "./ai-sdk-utils.js";
|
|
1
|
+
import { extractSources, extractToolCalls, fromUIMessage, fromUIMessages, getCossistantPartMetadata, getCossistantToolTimelineMetadata, hasProcessingParts, isAISDKCompatiblePart, setCossistantPartMetadata, setCossistantToolTimelineMetadata, toUIMessage, toUIMessages } from "./ai-sdk-utils.js";
|
|
2
2
|
import { CossistantAPIError } from "./types.js";
|
|
3
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";
|
|
4
4
|
import { generateConversationId, generateMessageId } from "./utils.js";
|
|
@@ -17,4 +17,4 @@ import { applyConversationTypingEvent, clearTypingFromTimelineItem, clearTypingS
|
|
|
17
17
|
import { TYPING_KEEP_ALIVE_MS, TYPING_PREVIEW_MAX_LENGTH, TYPING_SEND_INTERVAL_MS, TYPING_STOP_DELAY_MS, createTypingReporter } from "./typing-reporter.js";
|
|
18
18
|
import { generateVisitorName, getVisitorNameWithFallback } from "./visitor-name.js";
|
|
19
19
|
|
|
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 };
|
|
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, getCossistantPartMetadata, getCossistantToolTimelineMetadata, getVisitorId, getVisitorNameWithFallback, getWebsiteState, hasProcessingParts, hasVisibleContent, hydrateConversationSeen, isAISDKCompatiblePart, isAllowedMimeType, isImageMimeType, normalizeLocale, setCossistantPartMetadata, setCossistantToolTimelineMetadata, setTypingState, setVisitorId, toUIMessage, toUIMessages, upsertConversationSeen, validateFile, validateFiles };
|
package/package.json
CHANGED
package/privacy-filter.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;AAyIf;AAuCA;;EAEW,cAAA,CAAA,EAAA,OAAA;CACA;;AAQX;;;;;AAYA;;iBAzSgB,wBAAA,UACN,+BACC,oBACA,gBACR;;;;;;;;;iBAgCa,yBAAA,WACL,iCACA,oBACA,gBACR;;;;;;;;;iBAkBa,6BAAA,OACT,wBACI,oBACA,gBACR;;;;;;;;;iBAgCa,8BAAA,QACR,0BACG,oBACA,gBACR;;;;cAyIU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCG,iBAAA,UACN,+BACC,oBACA;;;;iBAQK,iBAAA,UACN,+BACC,oBACA;;;;iBASK,kBAAA,UACN,+BACC"}
|
package/privacy-filter.js
CHANGED
|
@@ -112,14 +112,19 @@ function shouldIncludeTimelineItemPart(part, audience, opts) {
|
|
|
112
112
|
* Extract visibility from an AI SDK part's providerMetadata
|
|
113
113
|
*/
|
|
114
114
|
function getPartVisibility(part) {
|
|
115
|
-
|
|
115
|
+
const metadataCarrier = part;
|
|
116
|
+
const metadata = metadataCarrier.callProviderMetadata ?? metadataCarrier.providerMetadata;
|
|
117
|
+
if (metadata) return metadata.cossistant?.visibility ?? "public";
|
|
116
118
|
return "public";
|
|
117
119
|
}
|
|
118
120
|
/**
|
|
119
121
|
* Extract visibility from a TimelineItem part's providerMetadata
|
|
120
122
|
*/
|
|
121
123
|
function getTimelineItemPartVisibility(part) {
|
|
122
|
-
if ("providerMetadata" in part
|
|
124
|
+
if ("providerMetadata" in part || "callProviderMetadata" in part) {
|
|
125
|
+
const typedPart = part;
|
|
126
|
+
return typedPart.callProviderMetadata?.cossistant?.visibility ?? typedPart.providerMetadata?.cossistant?.visibility ?? "public";
|
|
127
|
+
}
|
|
123
128
|
return "public";
|
|
124
129
|
}
|
|
125
130
|
/**
|